Skip to content

Commit f57884c

Browse files
committed
Merge branch 'globalSearchRegexCheck' into 'master'
[OpenCS] Validate regex patterns and fix Replace in global search view Closes #7152 See merge request OpenMW/openmw!5127
2 parents 7541206 + 0ca93eb commit f57884c

File tree

5 files changed

+68
-35
lines changed

5 files changed

+68
-35
lines changed

apps/opencs/view/tools/reporttable.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ namespace CSVTools
8686
/// \return rows in the original model
8787
std::vector<int> getReplaceIndices(bool selection) const;
8888

89+
/// \return underlying report model
90+
CSMTools::ReportModel* getReportModel() const { return mModel; }
91+
8992
/// \param index row in the original model
9093
void flagAsReplaced(int index);
9194

apps/opencs/view/tools/searchbox.cpp

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,38 @@
88

99
#include "../../model/tools/search.hpp"
1010

11-
void CSVTools::SearchBox::updateSearchButton()
11+
void CSVTools::SearchBox::updateSearchButtons()
1212
{
13+
mReplace.setEnabled(false);
1314
if (!mSearchEnabled)
14-
mSearch.setEnabled(false);
15-
else
1615
{
17-
switch (mMode.currentIndex())
18-
{
19-
case 0:
20-
case 1:
21-
case 2:
22-
case 3:
23-
24-
mSearch.setEnabled(!mText.text().isEmpty());
25-
break;
16+
mSearch.setEnabled(false);
17+
return;
18+
}
2619

27-
case 4:
20+
const CSMTools::Search::Type type = static_cast<CSMTools::Search::Type>(mMode.currentIndex());
21+
if (type == CSMTools::Search::Type_RecordState)
22+
{
23+
mSearch.setEnabled(true);
24+
return;
25+
}
2826

29-
mSearch.setEnabled(true);
30-
break;
27+
bool canSearch = false;
28+
QString style;
29+
if (!mText.text().isEmpty())
30+
{
31+
canSearch = true;
32+
if (type == CSMTools::Search::Type_TextRegEx || type == CSMTools::Search::Type_IdRegEx)
33+
{
34+
canSearch = QRegularExpression(mText.text()).isValid();
35+
if (!canSearch)
36+
style = "QLineEdit { color: red; }";
3137
}
3238
}
39+
40+
mText.setStyleSheet(style);
41+
mSearch.setEnabled(canSearch);
42+
mReplace.setEnabled(mAllowReplace && mSearchResultCount > 0);
3343
}
3444

3545
CSVTools::SearchBox::SearchBox(QWidget* parent)
@@ -76,6 +86,7 @@ CSVTools::SearchBox::SearchBox(QWidget* parent)
7686
mLayout->addWidget(&mReplaceInput, 1, 1);
7787

7888
mLayout->addWidget(&mReplace, 1, 3);
89+
mReplace.setEnabled(false);
7990

8091
// layout adjustments
8192
mLayout->setColumnMinimumWidth(2, 50);
@@ -88,13 +99,29 @@ CSVTools::SearchBox::SearchBox(QWidget* parent)
8899
// update
89100
modeSelected(0);
90101

91-
updateSearchButton();
102+
updateSearchButtons();
103+
}
104+
105+
void CSVTools::SearchBox::setEditLock(bool locked)
106+
{
107+
mAllowReplace = !locked;
108+
updateSearchButtons();
92109
}
93110

94111
void CSVTools::SearchBox::setSearchMode(bool enabled)
95112
{
96113
mSearchEnabled = enabled;
97-
updateSearchButton();
114+
updateSearchButtons();
115+
}
116+
117+
void CSVTools::SearchBox::setSearchResultCount(int resultCount)
118+
{
119+
int priorResultCount = mSearchResultCount;
120+
mSearchResultCount = resultCount;
121+
122+
// Update search buttons only if we're changing between zero and non-zero
123+
if ((priorResultCount == 0) != (mSearchResultCount == 0))
124+
updateSearchButtons();
98125
}
99126

100127
CSMTools::Search CSVTools::SearchBox::getSearch() const
@@ -146,11 +173,6 @@ std::string CSVTools::SearchBox::getReplaceText() const
146173
}
147174
}
148175

149-
void CSVTools::SearchBox::setEditLock(bool locked)
150-
{
151-
mReplace.setEnabled(!locked);
152-
}
153-
154176
void CSVTools::SearchBox::focus()
155177
{
156178
mInput.currentWidget()->setFocus();
@@ -177,12 +199,12 @@ void CSVTools::SearchBox::modeSelected(int index)
177199

178200
mInput.currentWidget()->setFocus();
179201

180-
updateSearchButton();
202+
updateSearchButtons();
181203
}
182204

183205
void CSVTools::SearchBox::textChanged(const QString& text)
184206
{
185-
updateSearchButton();
207+
updateSearchButtons();
186208
}
187209

188210
void CSVTools::SearchBox::startSearch(bool checked)

apps/opencs/view/tools/searchbox.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,30 @@ namespace CSVTools
3030
QGridLayout* mLayout;
3131
QComboBox mMode;
3232
bool mSearchEnabled;
33+
bool mAllowReplace{ false };
3334
QStackedWidget mReplaceInput;
3435
QLineEdit mReplaceText;
3536
QLabel mReplacePlaceholder;
3637
QPushButton mReplace;
3738

3839
private:
39-
void updateSearchButton();
40+
int mSearchResultCount = 0;
41+
42+
void updateSearchButtons();
4043

4144
public:
4245
SearchBox(QWidget* parent = nullptr);
4346

47+
void setEditLock(bool locked);
48+
4449
void setSearchMode(bool enabled);
4550

51+
void setSearchResultCount(int resultCount);
52+
4653
CSMTools::Search getSearch() const;
4754

4855
std::string getReplaceText() const;
4956

50-
void setEditLock(bool locked);
51-
5257
void focus();
5358

5459
private slots:

apps/opencs/view/tools/searchsubview.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@
2222

2323
void CSVTools::SearchSubView::replace(bool selection)
2424
{
25-
if (mLocked)
25+
if (!mAllowReplace)
2626
return;
2727

2828
std::vector<int> indices = mTable->getReplaceIndices(selection);
29+
if (indices.empty())
30+
return;
2931

3032
std::string replace = mSearchBox.getReplaceText();
3133

32-
const CSMTools::ReportModel& model = dynamic_cast<const CSMTools::ReportModel&>(*mTable->model());
34+
const CSMTools::ReportModel* model = mTable->getReportModel();
3335

3436
bool autoDelete = CSMPrefs::get()["Search & Replace"]["auto-delete"].isTrue();
3537

@@ -40,7 +42,7 @@ void CSVTools::SearchSubView::replace(bool selection)
4042
// in a single string.
4143
for (std::vector<int>::const_reverse_iterator iter(indices.rbegin()); iter != indices.rend(); ++iter)
4244
{
43-
const CSMWorld::UniversalId& id = model.getUniversalId(*iter);
45+
const CSMWorld::UniversalId& id = model->getUniversalId(*iter);
4446

4547
CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::getParentType(id.getType());
4648

@@ -52,7 +54,7 @@ void CSVTools::SearchSubView::replace(bool selection)
5254
currentTable = table;
5355
}
5456

55-
std::string hint = model.getHint(*iter);
57+
std::string hint = model->getHint(*iter);
5658

5759
if (search.verify(mDocument, table, id, hint))
5860
{
@@ -74,7 +76,6 @@ void CSVTools::SearchSubView::showEvent(QShowEvent* event)
7476
CSVTools::SearchSubView::SearchSubView(const CSMWorld::UniversalId& id, CSMDoc::Document& document)
7577
: CSVDoc::SubView(id)
7678
, mDocument(document)
77-
, mLocked(false)
7879
{
7980
QVBoxLayout* layout = new QVBoxLayout;
8081

@@ -112,7 +113,7 @@ CSVTools::SearchSubView::SearchSubView(const CSMWorld::UniversalId& id, CSMDoc::
112113

113114
void CSVTools::SearchSubView::setEditLock(bool locked)
114115
{
115-
mLocked = locked;
116+
mAllowReplace = !locked;
116117
mSearchBox.setEditLock(locked);
117118
}
118119

@@ -149,7 +150,9 @@ void CSVTools::SearchSubView::replaceAllRequest()
149150

150151
void CSVTools::SearchSubView::tableSizeUpdate()
151152
{
152-
mBottom->tableSizeChanged(mDocument.getReport(getUniversalId())->rowCount(), 0, 0);
153+
int resultCount = mDocument.getReport(getUniversalId())->rowCount();
154+
mBottom->tableSizeChanged(resultCount, 0, 0);
155+
mSearchBox.setSearchResultCount(resultCount);
153156
}
154157

155158
void CSVTools::SearchSubView::operationDone(int type, bool failed)

apps/opencs/view/tools/searchsubview.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace CSVTools
3131
SearchBox mSearchBox;
3232
CSMDoc::Document& mDocument;
3333
CSMTools::Search mSearch;
34-
bool mLocked;
34+
bool mAllowReplace{ false };
3535
CSVWorld::TableBottomBox* mBottom;
3636

3737
private:

0 commit comments

Comments
 (0)