1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2026-01-31 13:48:27 +00:00

Merge branch 'globalSearchRegexCheck' into 'master'

[OpenCS] Validate regex patterns and fix Replace in global search view

Closes #7152

See merge request OpenMW/openmw!5127
This commit is contained in:
Alexei Kotov 2026-01-26 22:59:03 +03:00
commit f57884c424
5 changed files with 69 additions and 36 deletions

View file

@ -86,6 +86,9 @@ namespace CSVTools
/// \return rows in the original model
std::vector<int> getReplaceIndices(bool selection) const;
/// \return underlying report model
CSMTools::ReportModel* getReportModel() const { return mModel; }
/// \param index row in the original model
void flagAsReplaced(int index);

View file

@ -8,28 +8,38 @@
#include "../../model/tools/search.hpp"
void CSVTools::SearchBox::updateSearchButton()
void CSVTools::SearchBox::updateSearchButtons()
{
mReplace.setEnabled(false);
if (!mSearchEnabled)
mSearch.setEnabled(false);
else
{
switch (mMode.currentIndex())
mSearch.setEnabled(false);
return;
}
const CSMTools::Search::Type type = static_cast<CSMTools::Search::Type>(mMode.currentIndex());
if (type == CSMTools::Search::Type_RecordState)
{
mSearch.setEnabled(true);
return;
}
bool canSearch = false;
QString style;
if (!mText.text().isEmpty())
{
canSearch = true;
if (type == CSMTools::Search::Type_TextRegEx || type == CSMTools::Search::Type_IdRegEx)
{
case 0:
case 1:
case 2:
case 3:
mSearch.setEnabled(!mText.text().isEmpty());
break;
case 4:
mSearch.setEnabled(true);
break;
canSearch = QRegularExpression(mText.text()).isValid();
if (!canSearch)
style = "QLineEdit { color: red; }";
}
}
mText.setStyleSheet(style);
mSearch.setEnabled(canSearch);
mReplace.setEnabled(mAllowReplace && mSearchResultCount > 0);
}
CSVTools::SearchBox::SearchBox(QWidget* parent)
@ -76,6 +86,7 @@ CSVTools::SearchBox::SearchBox(QWidget* parent)
mLayout->addWidget(&mReplaceInput, 1, 1);
mLayout->addWidget(&mReplace, 1, 3);
mReplace.setEnabled(false);
// layout adjustments
mLayout->setColumnMinimumWidth(2, 50);
@ -88,13 +99,29 @@ CSVTools::SearchBox::SearchBox(QWidget* parent)
// update
modeSelected(0);
updateSearchButton();
updateSearchButtons();
}
void CSVTools::SearchBox::setEditLock(bool locked)
{
mAllowReplace = !locked;
updateSearchButtons();
}
void CSVTools::SearchBox::setSearchMode(bool enabled)
{
mSearchEnabled = enabled;
updateSearchButton();
updateSearchButtons();
}
void CSVTools::SearchBox::setSearchResultCount(int resultCount)
{
int priorResultCount = mSearchResultCount;
mSearchResultCount = resultCount;
// Update search buttons only if we're changing between zero and non-zero
if ((priorResultCount == 0) != (mSearchResultCount == 0))
updateSearchButtons();
}
CSMTools::Search CSVTools::SearchBox::getSearch() const
@ -146,11 +173,6 @@ std::string CSVTools::SearchBox::getReplaceText() const
}
}
void CSVTools::SearchBox::setEditLock(bool locked)
{
mReplace.setEnabled(!locked);
}
void CSVTools::SearchBox::focus()
{
mInput.currentWidget()->setFocus();
@ -177,12 +199,12 @@ void CSVTools::SearchBox::modeSelected(int index)
mInput.currentWidget()->setFocus();
updateSearchButton();
updateSearchButtons();
}
void CSVTools::SearchBox::textChanged(const QString& text)
{
updateSearchButton();
updateSearchButtons();
}
void CSVTools::SearchBox::startSearch(bool checked)

View file

@ -30,25 +30,30 @@ namespace CSVTools
QGridLayout* mLayout;
QComboBox mMode;
bool mSearchEnabled;
bool mAllowReplace{ false };
QStackedWidget mReplaceInput;
QLineEdit mReplaceText;
QLabel mReplacePlaceholder;
QPushButton mReplace;
private:
void updateSearchButton();
int mSearchResultCount = 0;
void updateSearchButtons();
public:
SearchBox(QWidget* parent = nullptr);
void setEditLock(bool locked);
void setSearchMode(bool enabled);
void setSearchResultCount(int resultCount);
CSMTools::Search getSearch() const;
std::string getReplaceText() const;
void setEditLock(bool locked);
void focus();
private slots:

View file

@ -22,14 +22,16 @@
void CSVTools::SearchSubView::replace(bool selection)
{
if (mLocked)
if (!mAllowReplace)
return;
std::vector<int> indices = mTable->getReplaceIndices(selection);
if (indices.empty())
return;
std::string replace = mSearchBox.getReplaceText();
const CSMTools::ReportModel& model = dynamic_cast<const CSMTools::ReportModel&>(*mTable->model());
const CSMTools::ReportModel* model = mTable->getReportModel();
bool autoDelete = CSMPrefs::get()["Search & Replace"]["auto-delete"].isTrue();
@ -40,7 +42,7 @@ void CSVTools::SearchSubView::replace(bool selection)
// in a single string.
for (std::vector<int>::const_reverse_iterator iter(indices.rbegin()); iter != indices.rend(); ++iter)
{
const CSMWorld::UniversalId& id = model.getUniversalId(*iter);
const CSMWorld::UniversalId& id = model->getUniversalId(*iter);
CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::getParentType(id.getType());
@ -52,7 +54,7 @@ void CSVTools::SearchSubView::replace(bool selection)
currentTable = table;
}
std::string hint = model.getHint(*iter);
std::string hint = model->getHint(*iter);
if (search.verify(mDocument, table, id, hint))
{
@ -74,7 +76,6 @@ void CSVTools::SearchSubView::showEvent(QShowEvent* event)
CSVTools::SearchSubView::SearchSubView(const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: CSVDoc::SubView(id)
, mDocument(document)
, mLocked(false)
{
QVBoxLayout* layout = new QVBoxLayout;
@ -112,7 +113,7 @@ CSVTools::SearchSubView::SearchSubView(const CSMWorld::UniversalId& id, CSMDoc::
void CSVTools::SearchSubView::setEditLock(bool locked)
{
mLocked = locked;
mAllowReplace = !locked;
mSearchBox.setEditLock(locked);
}
@ -149,7 +150,9 @@ void CSVTools::SearchSubView::replaceAllRequest()
void CSVTools::SearchSubView::tableSizeUpdate()
{
mBottom->tableSizeChanged(mDocument.getReport(getUniversalId())->rowCount(), 0, 0);
int resultCount = mDocument.getReport(getUniversalId())->rowCount();
mBottom->tableSizeChanged(resultCount, 0, 0);
mSearchBox.setSearchResultCount(resultCount);
}
void CSVTools::SearchSubView::operationDone(int type, bool failed)

View file

@ -31,7 +31,7 @@ namespace CSVTools
SearchBox mSearchBox;
CSMDoc::Document& mDocument;
CSMTools::Search mSearch;
bool mLocked;
bool mAllowReplace{ false };
CSVWorld::TableBottomBox* mBottom;
private: