Option to find&replace in selection #1618

New check box in the Find and Replace dialog for Scintilla editors. The
new option uses the feature in QScintilla for finding text in the
selection only.

The implementation has been changed to use findFirst(InSelection) and
findNext so it works exactly as designed by QScintilla. Consequently the
finding process has to be cancel whenever any of the parameters have
changed.
This commit is contained in:
mgrojo
2018-11-24 00:22:55 +01:00
parent 058f2acd14
commit 87a8aeb1c0
3 changed files with 94 additions and 54 deletions

View File

@@ -6,7 +6,8 @@
FindReplaceDialog::FindReplaceDialog(QWidget* parent)
: QDialog(parent),
ui(new Ui::FindReplaceDialog)
ui(new Ui::FindReplaceDialog),
findInProgress(false)
{
// Create UI
ui->setupUi(this);
@@ -34,29 +35,67 @@ void FindReplaceDialog::setExtendedScintilla(ExtendedScintilla* scintilla)
connect(m_scintilla, SIGNAL(destroyed()), this, SLOT(hide()));
connect(ui->findText, SIGNAL(editingFinished()), this, SLOT(cancelFind()));
connect(ui->regexpCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind);
connect(ui->caseCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind);
connect(ui->wholeWordsCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind);
connect(ui->wrapCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind);
connect(ui->backwardsCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind);
connect(ui->selectionCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind);
connect(ui->selectionCheckBox, &QCheckBox::toggled, ui->wrapCheckBox, &QCheckBox::setDisabled);
}
bool FindReplaceDialog::findFirst(bool wrap, bool forward)
{
if (ui->selectionCheckBox->isChecked())
return m_scintilla->findFirstInSelection
(ui->findText->text(),
ui->regexpCheckBox->isChecked(),
ui->caseCheckBox->isChecked(),
ui->wholeWordsCheckBox->isChecked(),
forward);
else
return m_scintilla->findFirst
(ui->findText->text(),
ui->regexpCheckBox->isChecked(),
ui->caseCheckBox->isChecked(),
ui->wholeWordsCheckBox->isChecked(),
wrap,
forward);
}
bool FindReplaceDialog::findNext()
{
clearIndicators();
bool found = m_scintilla->findText
(ui->findText->text(),
ui->regexpCheckBox->isChecked(),
ui->caseCheckBox->isChecked(),
ui->wholeWordsCheckBox->isChecked(),
ui->wrapCheckBox->isChecked(),
!ui->backwardsCheckBox->isChecked());
if (!found)
if (findInProgress)
findInProgress = m_scintilla->findNext();
else
findInProgress = findFirst(ui->wrapCheckBox->isChecked(),
!ui->backwardsCheckBox->isChecked());
if (!findInProgress)
ui->messageLabel->setText(tr("The searched text was not found"));
return found;
return findInProgress;
}
void FindReplaceDialog::show()
{
ui->findText->setFocus();
// If there is multi-line selected text set automatically the selection
// check box. If it's only part of a line, use it as text to find.
if (m_scintilla->hasSelectedText())
if (m_scintilla->selectedText().contains("\n"))
ui->selectionCheckBox->setChecked(true);
else {
ui->findText->setText(m_scintilla->selectedText());
ui->selectionCheckBox->setChecked(false);
}
else
ui->selectionCheckBox->setChecked(false);
ui->findText->selectAll();
QDialog::show();
}
@@ -73,24 +112,27 @@ void FindReplaceDialog::indicateSelection()
int fromRow, fromIndex, toRow, toIndex;
m_scintilla->getSelection(&fromRow, &fromIndex, &toRow, &toIndex);
m_scintilla->fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, foundIndicatorNumber);
}
void FindReplaceDialog::findAll()
void FindReplaceDialog::searchAll(bool replace)
{
clearIndicators();
if (!ui->selectionCheckBox->isChecked())
m_scintilla->setCursorPosition(0, 0);
bool found = findFirst(/* wrap */ false, /* fordward */ true);
int occurrences = 0;
m_scintilla->setCursorPosition(0, 0);
while (m_scintilla->findText
(ui->findText->text(),
ui->regexpCheckBox->isChecked(),
ui->caseCheckBox->isChecked(),
ui->wholeWordsCheckBox->isChecked(),
false,
true)) {
while (found) {
if (replace)
m_scintilla->replace(ui->replaceWithText->text());
indicateSelection();
++occurrences;
found = m_scintilla->findNext();
}
m_scintilla->clearSelection();
if (!ui->selectionCheckBox->isChecked())
m_scintilla->clearSelection();
QString message;
switch (occurrences) {
@@ -98,55 +140,39 @@ void FindReplaceDialog::findAll()
message = tr("The searched text was not found.");
break;
case 1:
message = tr("The searched text was found one time.");
if (replace)
message = tr("The searched text was replaced one time.");
else
message = tr("The searched text was found one time.");
break;
default:
message = tr("The searched text was found %1 times.").arg(occurrences);
if (replace)
message = tr("The searched text was replaced %1 times.").arg(occurrences);
else
message = tr("The searched text was found %1 times.").arg(occurrences);
break;
}
ui->messageLabel->setText(message);
}
void FindReplaceDialog::findAll()
{
searchAll(/* replace */ false);
}
void FindReplaceDialog::replaceAll()
{
clearIndicators();
int occurrences = 0;
m_scintilla->setCursorPosition(0, 0);
while (m_scintilla->findText
(ui->findText->text(),
ui->regexpCheckBox->isChecked(),
ui->caseCheckBox->isChecked(),
ui->wholeWordsCheckBox->isChecked(),
false,
true)) {
m_scintilla->replace(ui->replaceWithText->text());
indicateSelection();
++occurrences;
}
m_scintilla->clearSelection();
QString message;
switch (occurrences) {
case 0:
message = tr("The searched text was not found.");
break;
case 1:
message = tr("The searched text was replaced one time.");
break;
default:
message = tr("The searched text was replaced %1 times.").arg(occurrences);
break;
}
ui->messageLabel->setText(message);
searchAll(/* replace */ true);
}
void FindReplaceDialog::cancelFind()
{
m_scintilla->findFirst(QString(), false, false, false, false);
clearIndicators();
findInProgress = false;
ui->messageLabel->setText("");
}
void FindReplaceDialog::help()
{

View File

@@ -33,11 +33,14 @@ private slots:
void buttonBox_clicked(QAbstractButton* button);
private:
bool findFirst(bool wrap, bool forward);
void searchAll(bool replace);
void indicateSelection();
void clearIndicators();
Ui::FindReplaceDialog* ui;
ExtendedScintilla* m_scintilla;
int foundIndicatorNumber;
bool findInProgress;
};
#endif

View File

@@ -101,6 +101,16 @@
</widget>
</item>
<item row="8" column="1">
<widget class="QCheckBox" name="selectionCheckBox">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When checked, the pattern to find is searched only in the current selection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;Selection only</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="regexpCheckBox">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When checked, the pattern to find is interpreted as a UNIX regular expression. See &lt;a href=&quot;https://en.wikibooks.org/wiki/Regular_Expressions&quot;&gt;Regular Expression in Wikibooks&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -210,6 +220,7 @@
<tabstop>wholeWordsCheckBox</tabstop>
<tabstop>wrapCheckBox</tabstop>
<tabstop>backwardsCheckBox</tabstop>
<tabstop>selectionCheckBox</tabstop>
<tabstop>regexpCheckBox</tabstop>
<tabstop>findNextButton</tabstop>
<tabstop>replaceButton</tabstop>