From b60f42d8b1a828e8d1045f0fb2bf130a53dcec71 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 17 Jun 2026 14:49:46 +0100 Subject: [PATCH] Move find/replace logic out of shader viewer so it can be reused --- qrenderdoc/Code/QRDUtils.cpp | 10 + qrenderdoc/Code/QRDUtils.h | 4 + qrenderdoc/Widgets/FindReplace.cpp | 562 +++++++++++++++++++++++++++- qrenderdoc/Widgets/FindReplace.h | 70 +++- qrenderdoc/Windows/PythonShell.cpp | 46 +++ qrenderdoc/Windows/PythonShell.h | 6 + qrenderdoc/Windows/PythonShell.ui | 29 +- qrenderdoc/Windows/ShaderViewer.cpp | 490 ++---------------------- qrenderdoc/Windows/ShaderViewer.h | 33 +- 9 files changed, 736 insertions(+), 514 deletions(-) diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index 7002faff0..23196c6f3 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -56,6 +56,7 @@ #include "Code/Resources.h" #include "Widgets/Extended/RDListWidget.h" #include "Widgets/Extended/RDTreeWidget.h" +#include "scintilla/include/qt/ScintillaEdit.h" // normally this is in the renderdoc core library, but it's needed for the 'unknown enum' path, // so we implement it here using QString. It's inefficient, but this is a very uncommon path - @@ -3679,6 +3680,15 @@ void UpdateVisibleColumns(rdcstr windowTitle, int columnCount, QHeaderView *head } } +void EnsureLineScrolled(ScintillaEdit *editor, int line) +{ + int firstLine = editor->firstVisibleLine(); + int linesVisible = editor->linesOnScreen(); + + if(editor->isVisible() && (line < firstLine || line > (firstLine + linesVisible - 1))) + editor->setFirstVisibleLine(qMax(0, line - linesVisible / 2)); +} + const rdcarray &StructuredDataItemModel::objects() const { return m_Objects; diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index 2ce7708b2..17c036a99 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -1062,6 +1062,10 @@ void *AccessWaylandPlatformInterface(const QByteArray &resource, QWindow *window void UpdateVisibleColumns(rdcstr windowTitle, int columnCount, QHeaderView *header, const QStringList &headers); +class ScintillaEdit; + +void EnsureLineScrolled(ScintillaEdit *editor, int line); + // A version of QToolButton that can also handle right clicks class QRClickToolButton : public QToolButton { diff --git a/qrenderdoc/Widgets/FindReplace.cpp b/qrenderdoc/Widgets/FindReplace.cpp index b41f848da..3302bbd88 100644 --- a/qrenderdoc/Widgets/FindReplace.cpp +++ b/qrenderdoc/Widgets/FindReplace.cpp @@ -25,10 +25,16 @@ #include "FindReplace.h" #include #include +#include "Code/QRDUtils.h" +#include "Code/ScintillaSyntax.h" #include "Widgets/Extended/RDLineEdit.h" +#include "scintilla/include/qt/ScintillaEdit.h" +#include "toolwindowmanager/ToolWindowManager.h" +#include "toolwindowmanager/ToolWindowManagerArea.h" #include "ui_FindReplace.h" -FindReplace::FindReplace(QWidget *parent) : QFrame(parent), ui(new Ui::FindReplace) +FindReplace::FindReplace(QList &scintillas, QWidget *parent) + : QFrame(parent), ui(new Ui::FindReplace), m_Scintillas(scintillas) { ui->setupUi(this); @@ -55,7 +61,7 @@ FindReplace::FindReplace(QWidget *parent) : QFrame(parent), ui(new Ui::FindRepla m_direction = SearchDirection::Down; addHistory(ui->findText); - emit performFind(); + performFind(); m_direction = dir; } @@ -99,6 +105,52 @@ bool FindReplace::regexp() return ui->regexp->isChecked(); } +void FindReplace::configureFindIndicator(ScintillaEdit *editor, sptr_t indic) +{ + editor->indicSetFore(indic, SCINTILLA_COLOUR(200, 200, 64)); + editor->indicSetStyle(indic, INDIC_FULLBOX); + editor->indicSetAlpha(indic, 50); + editor->indicSetOutlineAlpha(indic, 80); +} + +void FindReplace::raiseOrShow() +{ + if(m_DockManager) + { + if(isVisible()) + { + ToolWindowManager::raiseToolWindow(this); + } + else + { + m_DockManager->moveToolWindow( + this, ToolWindowManager::AreaReference(ToolWindowManager::NewFloatingArea)); + m_DockManager->setToolWindowProperties(this, ToolWindowManager::HideOnClose); + } + m_DockManager->areaOf(this)->parentWidget()->activateWindow(); + } + takeFocus(); +} + +void FindReplace::setFindAllResultsDisplay(ScintillaEdit *findResults) +{ + m_FindResultsDisplay = findResults; + + configureFindIndicator(m_FindResultsDisplay, INDICATOR_FINDRESULTHIGHLIGHT); + + QColor highlightColor = palette().color(QPalette::Highlight).toRgb(); + + m_FindResultsDisplay->indicSetFore( + INDICATOR_FINDALLCURRENTRESULT, + SCINTILLA_COLOUR(highlightColor.red(), highlightColor.green(), highlightColor.blue())); + m_FindResultsDisplay->indicSetStyle(INDICATOR_FINDALLCURRENTRESULT, INDIC_FULLBOX); + m_FindResultsDisplay->indicSetAlpha(INDICATOR_FINDALLCURRENTRESULT, 120); + m_FindResultsDisplay->indicSetOutlineAlpha(INDICATOR_FINDALLCURRENTRESULT, 180); + + QObject::connect(m_FindResultsDisplay, &ScintillaEdit::doubleClick, this, + &FindReplace::resultsDoubleClick); +} + void FindReplace::setFindText(QString text) { ui->findText->setCurrentText(text); @@ -124,6 +176,14 @@ void FindReplace::allowUserModeChange(bool allow) ui->modeChangeFrame->setVisible(allow); } +void FindReplace::allowFindAll(bool allow) +{ + ui->searchContextLabel->setVisible(allow); + ui->searchContext->setVisible(allow); + if(!allow) + ui->searchContext->setCurrentIndex(FindReplace::File); +} + void FindReplace::setReplaceMode(bool replacing) { ui->replaceLabel->setVisible(replacing); @@ -159,12 +219,23 @@ void FindReplace::keyPressEvent(QKeyEvent *event) else m_direction = SearchDirection::Down; - emit performFind(); + performFind(); m_direction = dir; } else { + if(event->key() == Qt::Key_Escape) + { + // if we are in a floating area, hide on escape + ToolWindowManagerArea *area = m_DockManager->areaOf(this); + + if(area && m_DockManager->isFloating(this)) + { + m_DockManager->hideToolWindow(this); + } + } + emit keyPress(event); } } @@ -191,34 +262,34 @@ void FindReplace::on_findPrev_clicked() { setDirection(FindReplace::Up); addHistory(ui->findText); - emit performFind(); + performFind(); } void FindReplace::on_find_clicked() { setDirection(FindReplace::Down); addHistory(ui->findText); - emit performFind(); + performFind(); } void FindReplace::on_findAll_clicked() { addHistory(ui->findText); - emit performFindAll(); + performFindAll(); } void FindReplace::on_replace_clicked() { addHistory(ui->findText); addHistory(ui->replaceText); - emit performReplace(); + performReplace(); } void FindReplace::on_replaceAll_clicked() { addHistory(ui->findText); addHistory(ui->replaceText); - emit performReplaceAll(); + performReplaceAll(); } void FindReplace::on_findMode_clicked() @@ -230,3 +301,478 @@ void FindReplace::on_replaceMode_clicked() { setReplaceMode(true); } + +ScintillaEdit *FindReplace::currentScintilla() +{ + ScintillaEdit *cur = qobject_cast(QApplication::focusWidget()); + + if(cur == NULL) + { + for(ScintillaEdit *s : m_Scintillas) + { + if(s->isVisible()) + { + cur = s; + break; + } + } + } + + return cur; +} + +ScintillaEdit *FindReplace::nextScintilla(ScintillaEdit *cur) +{ + for(int i = 0; i < m_Scintillas.count(); i++) + { + if(m_Scintillas[i] == cur) + { + if(i + 1 < m_Scintillas.count()) + return m_Scintillas[i + 1]; + + return m_Scintillas[0]; + } + } + + if(!m_Scintillas.isEmpty()) + return m_Scintillas[0]; + + return NULL; +} + +void FindReplace::clearFindState() +{ + m_FindState = FindState(); +} + +void FindReplace::performFind(bool down) +{ + ScintillaEdit *cur = currentScintilla(); + + if(!cur) + return; + + QString find = findText(); + + sptr_t flags = 0; + + if(matchCase()) + flags |= SCFIND_MATCHCASE; + if(matchWord()) + flags |= SCFIND_WHOLEWORD; + if(regexp()) + flags |= SCFIND_REGEXP | SCFIND_POSIX; + + FindReplace::SearchContext ctx = context(); + + QString findHash = QFormatStr("%1%2%3%4").arg(find).arg(flags).arg((int)ctx).arg(down); + + if(findHash != m_FindState.hash) + { + m_FindState.hash = findHash; + m_FindState.start = 0; + m_FindState.end = cur->length(); + m_FindState.offset = cur->currentPos(); + if(down && cur->selectionStart() == m_FindState.offset && + cur->selectionEnd() - m_FindState.offset == find.length()) + m_FindState.offset += find.length(); + } + + int start = m_FindState.start + m_FindState.offset; + int end = m_FindState.end; + + if(!down) + end = m_FindState.start; + + QPair result = cur->findText(flags, find.toUtf8().data(), start, end); + + m_FindState.prevResult = result; + + if(result.first == -1) + { + sptr_t maxOffset = down ? 0 : m_FindState.end; + + // if we're at offset 0 searching down, there are no results. Same for offset max and + // searching up + if(m_FindState.offset == maxOffset) + return; + + // otherwise, we can wrap the search around + + if(ctx == FindReplace::AllFiles) + { + cur = nextScintilla(cur); + ToolWindowManager::raiseToolWindow(cur); + cur->activateWindow(); + cur->QWidget::setFocus(); + } + + m_FindState.offset = maxOffset; + + start = m_FindState.start + m_FindState.offset; + end = m_FindState.end; + + if(!down) + end = m_FindState.start; + + result = cur->findText(flags, find.toUtf8().data(), start, end); + + m_FindState.prevResult = result; + + if(result.first == -1) + return; + } + + cur->setSelection(result.first, result.second); + + EnsureLineScrolled(cur, cur->lineFromPosition(result.first)); + + if(down) + m_FindState.offset = result.second - m_FindState.start; + else + m_FindState.offset = result.first - m_FindState.start; +} + +void FindReplace::handleEditorKeypress(ScintillaEdit *editor, QKeyEvent *ev) +{ + bool readOnly = editor->readOnly(); + + if((ev->modifiers() & Qt::ControlModifier) && (ev->key() == Qt::Key_F || ev->key() == Qt::Key_F3)) + { + // if there's a selection, fill the find prompt with that + if(!editor->getSelText().isEmpty()) + { + setFindText(QString::fromUtf8(editor->getSelText())); + } + else + { + // otherwise pick the word under the cursor, if there is one + sptr_t scintillaPos = editor->currentPos(); + + sptr_t start = editor->wordStartPosition(scintillaPos, true); + sptr_t end = editor->wordEndPosition(scintillaPos, true); + + QByteArray text = editor->textRange(start, end); + + if(!text.isEmpty()) + setFindText(QString::fromUtf8(text)); + } + } + + if(ev->key() == Qt::Key_F && (ev->modifiers() & Qt::ControlModifier)) + { + setReplaceMode(false); + raiseOrShow(); + } + + if(ev->key() == Qt::Key_F3) + { + setReplaceMode(false); + performFind((ev->modifiers() & Qt::ShiftModifier) == 0); + } + + if(!readOnly && ev->key() == Qt::Key_H && (ev->modifiers() & Qt::ControlModifier)) + { + setReplaceMode(true); + raiseOrShow(); + } +} + +void FindReplace::performFind() +{ + performFind(direction() == FindReplace::Down); +} + +void FindReplace::performFindAll() +{ + ScintillaEdit *cur = currentScintilla(); + + if(!cur) + return; + + clearFindState(); + m_FindAllResults.clear(); + + QString find = findText(); + + sptr_t flags = 0; + + m_FindAllResultString = tr("Find all \"%1\"").arg(find); + + if(matchCase()) + { + flags |= SCFIND_MATCHCASE; + m_FindAllResultString += tr(", Match case"); + } + + if(matchWord()) + { + flags |= SCFIND_WHOLEWORD; + m_FindAllResultString += tr(", Match whole word"); + } + + if(regexp()) + { + flags |= SCFIND_REGEXP | SCFIND_POSIX; + m_FindAllResultString += tr(", with Regular Expressions"); + } + + FindReplace::SearchContext ctx = context(); + + if(ctx == FindReplace::File) + m_FindAllResultString += tr(", in current file\n"); + else + m_FindAllResultString += tr(", in all files\n"); + + QList scintillas = m_Scintillas; + + if(ctx == FindReplace::File) + scintillas = {cur}; + + QList> resultList; + + QByteArray findUtf8 = find.toUtf8(); + + if(findUtf8.isEmpty()) + return; + + for(ScintillaEdit *s : scintillas) + { + sptr_t start = 0; + sptr_t end = s->length(); + + if(m_FindIndicator >= 0) + { + s->setIndicatorCurrent(m_FindIndicator); + s->indicatorClearRange(start, end); + } + + QPair result; + + do + { + result = s->findText(flags, findUtf8.data(), start, end); + + if(result.first >= 0) + { + int line = s->lineFromPosition(result.first); + sptr_t lineStart = s->positionFromLine(line); + sptr_t lineEnd = s->lineEndPosition(line); + + if(m_FindIndicator >= 0) + s->indicatorFillRange(result.first, result.second - result.first); + + QString lineText = QString::fromUtf8(s->textRange(lineStart, lineEnd)); + + m_FindAllResultString += QFormatStr(" %1(%2): ").arg(s->windowTitle()).arg(line + 1, 4); + int startPos = m_FindAllResultString.length(); + + m_FindAllResultString += lineText; + m_FindAllResultString += lit("\n"); + + resultList.push_back( + qMakePair(result.first - lineStart + startPos, result.second - lineStart + startPos)); + + m_FindAllResults.push_back({s, result.first}); + } + + start = result.second; + + } while(result.first >= 0); + } + + m_FindAllResultString += tr("Matching lines: %1").arg(resultList.count()); + + if(m_FindResultsDisplay) + { + m_FindResultsDisplay->setReadOnly(false); + m_FindResultsDisplay->setText(m_FindAllResultString.toUtf8().data()); + + m_FindResultsDisplay->setIndicatorCurrent(INDICATOR_FINDALLCURRENTRESULT); + m_FindResultsDisplay->indicatorClearRange(0, m_FindResultsDisplay->length()); + + m_FindResultsDisplay->setIndicatorCurrent(INDICATOR_FINDRESULTHIGHLIGHT); + + for(QPair r : resultList) + m_FindResultsDisplay->indicatorFillRange(r.first, r.second - r.first); + + m_FindResultsDisplay->setReadOnly(true); + + if(m_FindResultsDisplay->isVisible()) + { + if(m_DockManager) + ToolWindowManager::raiseToolWindow(m_FindResultsDisplay); + } + else + { + if(m_DockManager) + { + m_DockManager->moveToolWindow(m_FindResultsDisplay, ToolWindowManager::AreaReference( + ToolWindowManager::BottomOf, + m_DockManager->areaOf(cur), 0.2f)); + m_DockManager->setToolWindowProperties( + m_FindResultsDisplay, + ToolWindowManager::HideOnClose | ToolWindowManager::DisallowFloatWindow); + } + } + } +} + +void FindReplace::performReplace() +{ + ScintillaEdit *cur = currentScintilla(); + + if(!cur) + return; + + QString find = findText(); + + if(find.isEmpty()) + return; + + sptr_t flags = 0; + + if(matchCase()) + flags |= SCFIND_MATCHCASE; + if(matchWord()) + flags |= SCFIND_WHOLEWORD; + if(regexp()) + flags |= SCFIND_REGEXP | SCFIND_POSIX; + + FindReplace::SearchContext ctx = context(); + + bool down = direction() == FindReplace::Down; + QString findHash = QFormatStr("%1%2%3%4").arg(find).arg(flags).arg((int)ctx).arg(down); + + // if we didn't have a valid previous find, just do a find and bail + if(findHash != m_FindState.hash) + { + performFind(); + return; + } + + if(m_FindState.prevResult.first == -1) + return; + + cur->setTargetRange(m_FindState.prevResult.first, m_FindState.prevResult.second); + + FindState save = m_FindState; + + QString dest = replaceText(); + + // otherwise we have a valid previous find. Do the replace now + // note this will invalidate the find state (as most user operations would), so we save/restore + // the state + if(regexp()) + cur->replaceTargetRE(-1, dest.toUtf8().data()); + else + cur->replaceTarget(-1, dest.toUtf8().data()); + + m_FindState = save; + + // adjust the offset if we replaced text and it went up or down in size + m_FindState.offset += (dest.count() - find.count()); + + // move to the next result + performFind(); +} + +void FindReplace::performReplaceAll() +{ + ScintillaEdit *cur = currentScintilla(); + + if(!cur) + return; + + QString find = findText(); + QString replace = replaceText(); + + if(find.isEmpty()) + return; + + sptr_t flags = 0; + + if(matchCase()) + flags |= SCFIND_MATCHCASE; + if(matchWord()) + flags |= SCFIND_WHOLEWORD; + if(regexp()) + flags |= SCFIND_REGEXP | SCFIND_POSIX; + + FindReplace::SearchContext ctx = context(); + + // trash the find state for any incremental finds + clearFindState(); + + QList scintillas = m_Scintillas; + + if(ctx == FindReplace::File) + scintillas = {cur}; + + int numReplacements = 0; + + for(ScintillaEdit *s : scintillas) + { + sptr_t start = 0; + sptr_t end = s->length(); + + QPair result; + + QByteArray findUtf8 = find.toUtf8(); + QByteArray replaceUtf8 = replace.toUtf8(); + + do + { + result = s->findText(flags, findUtf8.data(), start, end); + + if(result.first >= 0) + { + s->setTargetRange(result.first, result.second); + + if(regexp()) + s->replaceTargetRE(-1, replaceUtf8.data()); + else + s->replaceTarget(-1, replaceUtf8.data()); + + numReplacements++; + } + + start = result.second + (replaceUtf8.count() - findUtf8.count()); + + } while(result.first >= 0); + } + + QString message; + + if(scintillas.count() > 1) + message = tr("%1 replacements made in %2 files.").arg(numReplacements).arg(scintillas.count()); + else + message = tr("%1 replacements made.").arg(numReplacements); + + RDDialog::information(this, tr("Replace all"), message); +} + +void FindReplace::resultsDoubleClick(int position, int line) +{ + if(line >= 1 && line - 1 < m_FindAllResults.count()) + { + m_FindResultsDisplay->setIndicatorCurrent(INDICATOR_FINDALLCURRENTRESULT); + m_FindResultsDisplay->indicatorClearRange(0, m_FindResultsDisplay->length()); + + sptr_t start = m_FindResultsDisplay->positionFromLine(line); + sptr_t length = m_FindResultsDisplay->lineLength(line); + + m_FindResultsDisplay->indicatorFillRange(start, length); + + m_FindResultsDisplay->setSelection(position, position); + + ScintillaEdit *s = m_FindAllResults[line - 1].first; + int resultPos = m_FindAllResults[line - 1].second; + ToolWindowManager::raiseToolWindow(s); + s->activateWindow(); + s->QWidget::setFocus(); + s->clearSelections(); + s->setSelection(resultPos, resultPos); + s->scrollCaret(); + } +} diff --git a/qrenderdoc/Widgets/FindReplace.h b/qrenderdoc/Widgets/FindReplace.h index 60c40b057..adbc4f823 100644 --- a/qrenderdoc/Widgets/FindReplace.h +++ b/qrenderdoc/Widgets/FindReplace.h @@ -25,6 +25,11 @@ #pragma once #include +class ScintillaEdit; +class ToolWindowManager; + +// from Scintilla +typedef intptr_t sptr_t; namespace Ui { @@ -38,7 +43,7 @@ class FindReplace : public QFrame Q_OBJECT public: - explicit FindReplace(QWidget *parent = 0); + explicit FindReplace(QList &scintillas, QWidget *parent = 0); ~FindReplace(); enum SearchContext @@ -61,22 +66,38 @@ public: bool matchWord(); bool regexp(); + void setDockManager(ToolWindowManager *manager) { m_DockManager = manager; } + + void setFindAllResultsDisplay(ScintillaEdit *findResults); + void setFindIndicator(sptr_t indic) { m_FindIndicator = indic; } + void configureFindIndicator(ScintillaEdit *editor) + { + configureFindIndicator(editor, m_FindIndicator); + } + + void raiseOrShow(); + void setFindText(QString text); QString findText(); void setReplaceText(QString text); QString replaceText(); + void performFind(bool down); + + QString findAllResultString() { return m_FindAllResultString; } + + void handleEditorKeypress(ScintillaEdit *editor, QKeyEvent *ev); + public slots: void allowUserModeChange(bool allow); + void allowFindAll(bool allow); void setReplaceMode(bool replacing); void setDirection(SearchDirection dir); void takeFocus(); + void clearFindState(); + void resultsDoubleClick(int position, int line); signals: - void performFind(); - void performFindAll(); - void performReplace(); - void performReplaceAll(); void keyPress(QKeyEvent *e); private slots: @@ -94,7 +115,46 @@ private: Ui::FindReplace *ui; + ToolWindowManager *m_DockManager = NULL; + + QList &m_Scintillas; + ScintillaEdit *m_FindResultsDisplay = NULL; + + sptr_t m_FindIndicator = -1; + + static const int INDICATOR_FINDRESULTHIGHLIGHT = 0; + static const int INDICATOR_FINDALLCURRENTRESULT = 1; + + QString m_FindAllResultString; + QList> m_FindAllResults; + SearchDirection m_direction; + struct FindState + { + // hash identifies when the search has changed + QString hash; + + // the range identified when the search first occurred (for incremental find/replace) + sptr_t start = 0; + sptr_t end = 0; + + // the current offset where to search from next time, relative to above range + sptr_t offset = 0; + + // the last result + QPair prevResult; + } m_FindState; + void addHistory(QComboBox *combo); + + ScintillaEdit *currentScintilla(); + ScintillaEdit *nextScintilla(ScintillaEdit *cur); + + void configureFindIndicator(ScintillaEdit *editor, sptr_t indic); + + void performFind(); + void performFindAll(); + void performReplace(); + void performReplaceAll(); }; diff --git a/qrenderdoc/Windows/PythonShell.cpp b/qrenderdoc/Windows/PythonShell.cpp index 9d15c1504..6703a4dc4 100644 --- a/qrenderdoc/Windows/PythonShell.cpp +++ b/qrenderdoc/Windows/PythonShell.cpp @@ -37,6 +37,7 @@ #include "Code/ScintillaSyntax.h" #include "Code/pyrenderdoc/PythonContext.h" #include "Widgets/Extended/RDToolTip.h" +#include "Widgets/FindReplace.h" #include "scintilla/include/SciLexer.h" #include "toolwindowmanager/ToolWindowManagerArea.h" #include "ui_PythonShell.h" @@ -171,6 +172,29 @@ PythonShell::PythonShell(ICaptureContext &ctx, QWidget *parent) QObject::connect(ui->lineInput, &RDLineEdit::leave, [this]() { hideFunccompleteTooltip(); }); + // we create this up front so its state stays persistent as much as possible. + m_FindReplace = new FindReplace(m_Scintillas, this); + m_FindReplace->allowFindAll(false); + m_FindReplace->setDockManager(ui->docking); + + { + m_FindResults = new ScintillaEdit(this); + + m_FindResults->styleSetFont(STYLE_DEFAULT, Formatter::FixedFont().family().toUtf8().data()); + m_FindResults->styleSetFont(100, Formatter::FixedFont().family().toUtf8().data()); + m_FindResults->styleSetBack( + 100, IsDarkTheme() ? SCINTILLA_COLOUR(175, 70, 70) : SCINTILLA_COLOUR(255, 150, 150)); + + ConfigureSyntax(m_FindResults, SCLEX_NULL); + m_FindResults->usePopUp(SC_POPUP_NEVER); + m_FindResults->setWrapMode(SC_WRAP_WORD); + m_FindResults->setReadOnly(true); + m_FindResults->setWindowTitle(lit("Find Results")); + } + + m_FindReplace->setFindIndicator(2); + m_FindReplace->setFindAllResultsDisplay(m_FindResults); + ui->lineInput->setFont(Formatter::FixedFont()); ui->interactiveOutput->setFont(Formatter::FixedFont()); ui->scriptOutput->setFont(Formatter::FixedFont()); @@ -248,6 +272,13 @@ PythonShell::PythonShell(ICaptureContext &ctx, QWidget *parent) setupTabs(); + ui->docking->addToolWindow(m_FindReplace, ToolWindowManager::NoArea); + ui->docking->setToolWindowProperties(m_FindReplace, ToolWindowManager::HideOnClose); + + ui->docking->addToolWindow(m_FindResults, ToolWindowManager::NoArea); + ui->docking->setToolWindowProperties( + m_FindResults, ToolWindowManager::HideOnClose | ToolWindowManager::DisallowFloatWindow); + ui->docking->addToolWindow( ui->replGroup, ToolWindowManager::AreaReference(ToolWindowManager::BottomOf, ui->docking->areaOf(m_Scintillas[0]), 0.3f)); @@ -598,6 +629,8 @@ ScintillaEdit *PythonShell::makeEditor(rdcstr filename) editor->indicSetFore(0, 0x0000ff); + m_FindReplace->configureFindIndicator(editor); + editor->styleSetFont(STYLE_DEFAULT, Formatter::FixedFont().family().toUtf8().data()); editor->styleSetFont(100, Formatter::FixedFont().family().toUtf8().data()); editor->styleSetBack( @@ -672,6 +705,8 @@ ScintillaEdit *PythonShell::makeEditor(rdcstr filename) if(type & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT | SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) { + m_FindReplace->clearFindState(); + markEditorModified(editor, true); updateEditorTitle(editor); @@ -711,6 +746,10 @@ ScintillaEdit *PythonShell::makeEditor(rdcstr filename) if(!editor->geometry().contains(editor->mapFromGlobal(QCursor::pos()))) return; + QWidget *widgetInCursor = QApplication::widgetAt(QCursor::pos()); + if(widgetInCursor && editor != widgetInCursor && editor != widgetInCursor->parentWidget()) + return; + sptr_t pos = editor->positionFromPointClose(x, y); if(pos == -1) @@ -774,6 +813,8 @@ ScintillaEdit *PythonShell::makeEditor(rdcstr filename) selectedHelp(typeName); } } + + m_FindReplace->handleEditorKeypress(editor, ev); }); if(m_Scintillas.empty()) @@ -1100,6 +1141,11 @@ void PythonShell::runScript(bool debugging) PythonContext::LaunchDebugger(this, m_Ctx.Config(), QString()); } +void PythonShell::on_findReplace_clicked() +{ + m_FindReplace->raiseOrShow(); +} + void PythonShell::on_execute_clicked() { QString command = ui->lineInput->text(); diff --git a/qrenderdoc/Windows/PythonShell.h b/qrenderdoc/Windows/PythonShell.h index 80cfe97bb..9f3a97a54 100644 --- a/qrenderdoc/Windows/PythonShell.h +++ b/qrenderdoc/Windows/PythonShell.h @@ -34,6 +34,7 @@ class QTextEdit; class RDToolTip; class QTimer; class QCompleter; +class FindReplace; class QStringListModel; class QFileSystemWatcher; class RDTreeWidgetItem; @@ -98,6 +99,7 @@ public: private slots: // automatic slots + void on_findReplace_clicked(); void on_execute_clicked(); void on_clear_clicked(); void on_newScript_clicked(); @@ -177,10 +179,14 @@ private: QList m_Scintillas; + FindReplace *m_FindReplace; + ScintillaEdit *m_FindResults = NULL; + void setupTabs(); ScintillaEdit *curEditor(); ScintillaEdit *makeEditor(rdcstr filename); + void updateEditorCloseButton(); void addRecentFile(rdcstr filename); diff --git a/qrenderdoc/Windows/PythonShell.ui b/qrenderdoc/Windows/PythonShell.ui index 66a336a76..118e9d509 100644 --- a/qrenderdoc/Windows/PythonShell.ui +++ b/qrenderdoc/Windows/PythonShell.ui @@ -251,7 +251,34 @@ - + + + Qt::Vertical + + + + + + + Find & Replace + + + Find + + + + :/find.png:/find.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + Qt::Vertical diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index 6f20f6add..fd7099089 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -235,37 +235,22 @@ ShaderViewer::ShaderViewer(ICaptureContext &ctx, QWidget *parent) ui->outputSig->setFont(Formatter::PreferredFont()); ui->callstack->setFont(Formatter::PreferredFont()); - // we create this up front so its state stays persistent as much as possible. - m_FindReplace = new FindReplace(this); - m_FindResults = MakeEditor(lit("findresults"), QString(), SCLEX_NULL); m_FindResults->setReadOnly(true); m_FindResults->setWindowTitle(lit("Find Results")); + // we create this up front so its state stays persistent as much as possible. + m_FindReplace = new FindReplace(m_Scintillas, this); + m_FindReplace->setFindIndicator(1); + m_FindReplace->setDockManager(ui->docking); + + m_FindReplace->setFindAllResultsDisplay(m_FindResults); + // remove margins m_FindResults->setMarginWidthN(0, 0); m_FindResults->setMarginWidthN(1, 0); m_FindResults->setMarginWidthN(2, 0); - QObject::connect(m_FindReplace, &FindReplace::performFind, this, &ShaderViewer::performFind); - QObject::connect(m_FindReplace, &FindReplace::performFindAll, this, &ShaderViewer::performFindAll); - QObject::connect(m_FindReplace, &FindReplace::performReplace, this, &ShaderViewer::performReplace); - QObject::connect(m_FindReplace, &FindReplace::performReplaceAll, this, - &ShaderViewer::performReplaceAll); - QObject::connect(m_FindReplace, &FindReplace::keyPress, [this](QKeyEvent *e) { - if(e->key() == Qt::Key_Escape) - { - // the find replace dialog is the only thing allowed to float. If it's in a floating area, - // hide it on escape - ToolWindowManagerArea *area = ui->docking->areaOf(m_FindReplace); - - if(area && ui->docking->isFloating(m_FindReplace)) - { - ui->docking->hideToolWindow(m_FindReplace); - } - } - }); - ui->docking->addToolWindow(m_FindReplace, ToolWindowManager::NoArea); ui->docking->setToolWindowProperties(m_FindReplace, ToolWindowManager::HideOnClose); @@ -273,17 +258,15 @@ ShaderViewer::ShaderViewer(ICaptureContext &ctx, QWidget *parent) ui->docking->setToolWindowProperties( m_FindResults, ToolWindowManager::HideOnClose | ToolWindowManager::DisallowFloatWindow); - QObject::connect(m_FindResults, &ScintillaEdit::doubleClick, this, - &ShaderViewer::resultsDoubleClick); - { m_DisassemblyView = MakeEditor(lit("scintillaDisassem"), QString(), m_Ctx.APIProps().pipelineType == GraphicsAPI::Vulkan ? SCLEX_GLSL : SCLEX_HLSL); m_DisassemblyView->setReadOnly(true); - QObject::connect(m_DisassemblyView, &ScintillaEdit::keyPressed, this, - &ShaderViewer::readonly_keyPressed); + QObject::connect(m_DisassemblyView, &ScintillaEdit::keyPressed, [this](QKeyEvent *ev) { + m_FindReplace->handleEditorKeypress(m_DisassemblyView, ev); + }); m_Scintillas.push_back(m_DisassemblyView); @@ -469,13 +452,12 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e ScintillaEdit *scintilla = AddFileScintilla(name, text, shaderEncoding); scintilla->setReadOnly(false); - QObject::connect(scintilla, &ScintillaEdit::keyPressed, this, &ShaderViewer::editable_keyPressed); QObject::connect(scintilla, &ScintillaEdit::modified, [this](int type, int, int, int, const QByteArray &, int, int, int) { if(type & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT | SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) - m_FindState = FindState(); + m_FindReplace->clearFindState(); MarkModification(); }); @@ -520,7 +502,8 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e m_Errors->setMarginWidthN(1, 0); m_Errors->setMarginWidthN(2, 0); - QObject::connect(m_Errors, &ScintillaEdit::keyPressed, this, &ShaderViewer::readonly_keyPressed); + QObject::connect(m_Errors, &ScintillaEdit::keyPressed, + [this](QKeyEvent *ev) { m_FindReplace->handleEditorKeypress(m_Errors, ev); }); ui->docking->addToolWindow( m_Errors, ToolWindowManager::AreaReference(ToolWindowManager::BottomOf, @@ -687,7 +670,7 @@ void ShaderViewer::debugShader(const ShaderReflection *shader, ResourceId pipeli if(m_ShaderDetails->debugInfo.entryLocation.lineStart > 0) { GUIInvoke::defer(scintilla, [scintilla, this]() { - ensureLineScrolled(scintilla, m_ShaderDetails->debugInfo.entryLocation.lineStart); + EnsureLineScrolled(scintilla, m_ShaderDetails->debugInfo.entryLocation.lineStart); }); } } @@ -1666,7 +1649,9 @@ ScintillaEdit *ShaderViewer::AddFileScintilla(const QString &name, const QString scintilla->setWindowTitle(name); ((QWidget *)scintilla)->setProperty("name", name); - QObject::connect(scintilla, &ScintillaEdit::keyPressed, this, &ShaderViewer::readonly_keyPressed); + QObject::connect(scintilla, &ScintillaEdit::keyPressed, [this, scintilla](QKeyEvent *ev) { + m_FindReplace->handleEditorKeypress(scintilla, ev); + }); ToolWindowManager::AreaReference ref(ToolWindowManager::EmptySpace); @@ -1700,20 +1685,8 @@ ScintillaEdit *ShaderViewer::MakeEditor(const QString &name, const QString &text ret->indicSetFore(INDICATOR_REGHIGHLIGHT, SCINTILLA_COLOUR(0, 100, 0)); ret->indicSetStyle(INDICATOR_REGHIGHLIGHT, INDIC_ROUNDBOX); - // set up find result highlight style - ret->indicSetFore(INDICATOR_FINDRESULT, SCINTILLA_COLOUR(200, 200, 64)); - ret->indicSetStyle(INDICATOR_FINDRESULT, INDIC_FULLBOX); - ret->indicSetAlpha(INDICATOR_FINDRESULT, 50); - ret->indicSetOutlineAlpha(INDICATOR_FINDRESULT, 80); - - QColor highlightColor = palette().color(QPalette::Highlight).toRgb(); - - ret->indicSetFore( - INDICATOR_FINDALLHIGHLIGHT, - SCINTILLA_COLOUR(highlightColor.red(), highlightColor.green(), highlightColor.blue())); - ret->indicSetStyle(INDICATOR_FINDALLHIGHLIGHT, INDIC_FULLBOX); - ret->indicSetAlpha(INDICATOR_FINDALLHIGHLIGHT, 120); - ret->indicSetOutlineAlpha(INDICATOR_FINDALLHIGHLIGHT, 180); + if(m_FindReplace) + m_FindReplace->configureFindIndicator(ret); // C# Highlight for bookmarks ret->markerSetBack(BOOKMARK_MARKER, SCINTILLA_COLOUR(51, 153, 255)); @@ -1750,32 +1723,6 @@ void ShaderViewer::SetTextAndUpdateMargin0(ScintillaEdit *sc, const QString &tex sc->setMarginWidthN(0, int(width)); } -void ShaderViewer::readonly_keyPressed(QKeyEvent *event) -{ - if(event->key() == Qt::Key_F && (event->modifiers() & Qt::ControlModifier)) - { - m_FindReplace->setReplaceMode(false); - SetFindTextFromCurrentWord(); - on_findReplace_clicked(); - } - - if(event->key() == Qt::Key_F3) - { - if(event->modifiers() & Qt::ControlModifier) - SetFindTextFromCurrentWord(); - find((event->modifiers() & Qt::ShiftModifier) == 0); - } -} - -void ShaderViewer::editable_keyPressed(QKeyEvent *event) -{ - if(event->key() == Qt::Key_H && (event->modifiers() & Qt::ControlModifier)) - { - m_FindReplace->setReplaceMode(true); - on_findReplace_clicked(); - } -} - void ShaderViewer::debug_contextMenu(const QPoint &pos) { m_ContextActive = true; @@ -4074,7 +4021,7 @@ void ShaderViewer::updateDebugState() int pos = m_DisassemblyView->positionFromLine(lineInfo.disassemblyLine - 1); m_DisassemblyView->setSelection(pos, pos); - ensureLineScrolled(m_DisassemblyView, lineInfo.disassemblyLine - 1); + EnsureLineScrolled(m_DisassemblyView, lineInfo.disassemblyLine - 1); } if(IsLastState() && (lineInfo.fileIndex < 0 || lineInfo.fileIndex >= m_FileScintillas.count())) @@ -4140,7 +4087,7 @@ void ShaderViewer::updateDebugState() int pos = m_CurInstructionScintilla->positionFromLine(lineInfo.lineStart - 1); m_CurInstructionScintilla->setSelection(pos, pos); - ensureLineScrolled(m_CurInstructionScintilla, lineInfo.lineStart - 1); + EnsureLineScrolled(m_CurInstructionScintilla, lineInfo.lineStart - 1); } } } @@ -5480,15 +5427,6 @@ const ShaderVariable *ShaderViewer::GetDebugVariable(const DebugVariableReferenc return NULL; } -void ShaderViewer::ensureLineScrolled(ScintillaEdit *s, int line) -{ - int firstLine = s->firstVisibleLine(); - int linesVisible = s->linesOnScreen(); - - if(s->isVisible() && (line < firstLine || line > (firstLine + linesVisible - 1))) - s->setFirstVisibleLine(qMax(0, line - linesVisible / 2)); -} - uint32_t ShaderViewer::CurrentStep() { return (uint32_t)m_CurrentStateIdx; @@ -6269,18 +6207,7 @@ ShaderEncoding ShaderViewer::currentEncoding() void ShaderViewer::on_findReplace_clicked() { - if(m_FindReplace->isVisible()) - { - ToolWindowManager::raiseToolWindow(m_FindReplace); - } - else - { - ui->docking->moveToolWindow( - m_FindReplace, ToolWindowManager::AreaReference(ToolWindowManager::NewFloatingArea)); - ui->docking->setToolWindowProperties(m_FindReplace, ToolWindowManager::HideOnClose); - } - ui->docking->areaOf(m_FindReplace)->parentWidget()->activateWindow(); - m_FindReplace->takeFocus(); + m_FindReplace->raiseOrShow(); } void ShaderViewer::PopulateCompileTools() @@ -6762,379 +6689,6 @@ ScintillaEdit *ShaderViewer::nextScintilla(ScintillaEdit *cur) return NULL; } -void ShaderViewer::find(bool down) -{ - ScintillaEdit *cur = currentScintilla(); - - if(!cur) - return; - - QString find = m_FindReplace->findText(); - - sptr_t flags = 0; - - if(m_FindReplace->matchCase()) - flags |= SCFIND_MATCHCASE; - if(m_FindReplace->matchWord()) - flags |= SCFIND_WHOLEWORD; - if(m_FindReplace->regexp()) - flags |= SCFIND_REGEXP | SCFIND_POSIX; - - FindReplace::SearchContext context = m_FindReplace->context(); - - QString findHash = QFormatStr("%1%2%3%4").arg(find).arg(flags).arg((int)context).arg(down); - - if(findHash != m_FindState.hash) - { - m_FindState.hash = findHash; - m_FindState.start = 0; - m_FindState.end = cur->length(); - m_FindState.offset = cur->currentPos(); - if(down && cur->selectionStart() == m_FindState.offset && - cur->selectionEnd() - m_FindState.offset == find.length()) - m_FindState.offset += find.length(); - } - - int start = m_FindState.start + m_FindState.offset; - int end = m_FindState.end; - - if(!down) - end = m_FindState.start; - - QPair result = cur->findText(flags, find.toUtf8().data(), start, end); - - m_FindState.prevResult = result; - - if(result.first == -1) - { - sptr_t maxOffset = down ? 0 : m_FindState.end; - - // if we're at offset 0 searching down, there are no results. Same for offset max and - // searching up - if(m_FindState.offset == maxOffset) - return; - - // otherwise, we can wrap the search around - - if(context == FindReplace::AllFiles) - { - cur = nextScintilla(cur); - ToolWindowManager::raiseToolWindow(cur); - cur->activateWindow(); - cur->QWidget::setFocus(); - } - - m_FindState.offset = maxOffset; - - start = m_FindState.start + m_FindState.offset; - end = m_FindState.end; - - if(!down) - end = m_FindState.start; - - result = cur->findText(flags, find.toUtf8().data(), start, end); - - m_FindState.prevResult = result; - - if(result.first == -1) - return; - } - - cur->setSelection(result.first, result.second); - - ensureLineScrolled(cur, cur->lineFromPosition(result.first)); - - if(down) - m_FindState.offset = result.second - m_FindState.start; - else - m_FindState.offset = result.first - m_FindState.start; -} - -void ShaderViewer::performFind() -{ - find(m_FindReplace->direction() == FindReplace::Down); -} - -void ShaderViewer::performFindAll() -{ - ScintillaEdit *cur = currentScintilla(); - - if(!cur) - return; - - QString find = m_FindReplace->findText(); - - sptr_t flags = 0; - - QString results = tr("Find all \"%1\"").arg(find); - - if(m_FindReplace->matchCase()) - { - flags |= SCFIND_MATCHCASE; - results += tr(", Match case"); - } - - if(m_FindReplace->matchWord()) - { - flags |= SCFIND_WHOLEWORD; - results += tr(", Match whole word"); - } - - if(m_FindReplace->regexp()) - { - flags |= SCFIND_REGEXP | SCFIND_POSIX; - results += tr(", with Regular Expressions"); - } - - FindReplace::SearchContext context = m_FindReplace->context(); - - if(context == FindReplace::File) - results += tr(", in current file\n"); - else - results += tr(", in all files\n"); - - // trash the find state for any incremental finds - m_FindState = FindState(); - - QList scintillas = m_Scintillas; - - if(context == FindReplace::File) - scintillas = {cur}; - - QList> resultList; - - m_FindAllResults.clear(); - - QByteArray findUtf8 = find.toUtf8(); - - if(findUtf8.isEmpty()) - return; - - for(ScintillaEdit *s : scintillas) - { - sptr_t start = 0; - sptr_t end = s->length(); - - s->setIndicatorCurrent(INDICATOR_FINDRESULT); - s->indicatorClearRange(start, end); - - QPair result; - - do - { - result = s->findText(flags, findUtf8.data(), start, end); - - if(result.first >= 0) - { - int line = s->lineFromPosition(result.first); - sptr_t lineStart = s->positionFromLine(line); - sptr_t lineEnd = s->lineEndPosition(line); - - s->indicatorFillRange(result.first, result.second - result.first); - - QString lineText = QString::fromUtf8(s->textRange(lineStart, lineEnd)); - - results += QFormatStr(" %1(%2): ").arg(s->windowTitle()).arg(line + 1, 4); - int startPos = results.length(); - - results += lineText; - results += lit("\n"); - - resultList.push_back( - qMakePair(result.first - lineStart + startPos, result.second - lineStart + startPos)); - - m_FindAllResults.push_back({s, result.first}); - } - - start = result.second; - - } while(result.first >= 0); - } - - results += tr("Matching lines: %1").arg(resultList.count()); - - m_FindResults->setReadOnly(false); - m_FindResults->setText(results.toUtf8().data()); - - m_FindResults->setIndicatorCurrent(INDICATOR_FINDALLHIGHLIGHT); - m_FindResults->indicatorClearRange(0, m_FindResults->length()); - - m_FindResults->setIndicatorCurrent(INDICATOR_FINDRESULT); - - for(QPair r : resultList) - m_FindResults->indicatorFillRange(r.first, r.second - r.first); - - m_FindResults->setReadOnly(true); - - if(m_FindResults->isVisible()) - { - ToolWindowManager::raiseToolWindow(m_FindResults); - } - else - { - ui->docking->moveToolWindow(m_FindResults, - ToolWindowManager::AreaReference(ToolWindowManager::BottomOf, - ui->docking->areaOf(cur), 0.2f)); - ui->docking->setToolWindowProperties( - m_FindResults, ToolWindowManager::HideOnClose | ToolWindowManager::DisallowFloatWindow); - } -} - -void ShaderViewer::resultsDoubleClick(int position, int line) -{ - if(line >= 1 && line - 1 < m_FindAllResults.count()) - { - m_FindResults->setIndicatorCurrent(INDICATOR_FINDALLHIGHLIGHT); - m_FindResults->indicatorClearRange(0, m_FindResults->length()); - - sptr_t start = m_FindResults->positionFromLine(line); - sptr_t length = m_FindResults->lineLength(line); - m_FindResults->indicatorFillRange(start, length); - - m_FindResults->setSelection(position, position); - - ScintillaEdit *s = m_FindAllResults[line - 1].first; - int resultPos = m_FindAllResults[line - 1].second; - ToolWindowManager::raiseToolWindow(s); - s->activateWindow(); - s->QWidget::setFocus(); - s->clearSelections(); - s->setSelection(resultPos, resultPos); - s->scrollCaret(); - } -} - -void ShaderViewer::performReplace() -{ - ScintillaEdit *cur = currentScintilla(); - - if(!cur) - return; - - QString find = m_FindReplace->findText(); - - if(find.isEmpty()) - return; - - sptr_t flags = 0; - - if(m_FindReplace->matchCase()) - flags |= SCFIND_MATCHCASE; - if(m_FindReplace->matchWord()) - flags |= SCFIND_WHOLEWORD; - if(m_FindReplace->regexp()) - flags |= SCFIND_REGEXP | SCFIND_POSIX; - - FindReplace::SearchContext context = m_FindReplace->context(); - - bool down = m_FindReplace->direction() == FindReplace::Down; - QString findHash = QFormatStr("%1%2%3%4").arg(find).arg(flags).arg((int)context).arg(down); - - // if we didn't have a valid previous find, just do a find and bail - if(findHash != m_FindState.hash) - { - performFind(); - return; - } - - if(m_FindState.prevResult.first == -1) - return; - - cur->setTargetRange(m_FindState.prevResult.first, m_FindState.prevResult.second); - - FindState save = m_FindState; - - QString replaceText = m_FindReplace->replaceText(); - - // otherwise we have a valid previous find. Do the replace now - // note this will invalidate the find state (as most user operations would), so we save/restore - // the state - if(m_FindReplace->regexp()) - cur->replaceTargetRE(-1, replaceText.toUtf8().data()); - else - cur->replaceTarget(-1, replaceText.toUtf8().data()); - - m_FindState = save; - - // adjust the offset if we replaced text and it went up or down in size - m_FindState.offset += (replaceText.count() - find.count()); - - // move to the next result - performFind(); -} - -void ShaderViewer::performReplaceAll() -{ - ScintillaEdit *cur = currentScintilla(); - - if(!cur) - return; - - QString find = m_FindReplace->findText(); - QString replace = m_FindReplace->replaceText(); - - if(find.isEmpty()) - return; - - sptr_t flags = 0; - - if(m_FindReplace->matchCase()) - flags |= SCFIND_MATCHCASE; - if(m_FindReplace->matchWord()) - flags |= SCFIND_WHOLEWORD; - if(m_FindReplace->regexp()) - flags |= SCFIND_REGEXP | SCFIND_POSIX; - - FindReplace::SearchContext context = m_FindReplace->context(); - - (void)context; - - // trash the find state for any incremental finds - m_FindState = FindState(); - - QList scintillas = m_Scintillas; - - if(context == FindReplace::File) - scintillas = {cur}; - - int numReplacements = 0; - - for(ScintillaEdit *s : scintillas) - { - sptr_t start = 0; - sptr_t end = s->length(); - - QPair result; - - QByteArray findUtf8 = find.toUtf8(); - QByteArray replaceUtf8 = replace.toUtf8(); - - do - { - result = s->findText(flags, findUtf8.data(), start, end); - - if(result.first >= 0) - { - s->setTargetRange(result.first, result.second); - - if(m_FindReplace->regexp()) - s->replaceTargetRE(-1, replaceUtf8.data()); - else - s->replaceTarget(-1, replaceUtf8.data()); - - numReplacements++; - } - - start = result.second + (replaceUtf8.count() - findUtf8.count()); - - } while(result.first >= 0); - } - - RDDialog::information( - this, tr("Replace all"), - tr("%1 replacements made in %2 files").arg(numReplacements).arg(scintillas.count())); -} - void ShaderViewer::ToggleBookmark() { ScintillaEdit *cur = currentScintilla(); diff --git a/qrenderdoc/Windows/ShaderViewer.h b/qrenderdoc/Windows/ShaderViewer.h index c171a2bd8..955d77be6 100644 --- a/qrenderdoc/Windows/ShaderViewer.h +++ b/qrenderdoc/Windows/ShaderViewer.h @@ -198,19 +198,12 @@ private slots: void on_watch_itemChanged(RDTreeWidgetItem *item, int column); // manual slots - void readonly_keyPressed(QKeyEvent *event); - void editable_keyPressed(QKeyEvent *event); void debug_contextMenu(const QPoint &pos); void variables_contextMenu(const QPoint &pos); void accessedResources_contextMenu(const QPoint &pos); void disassembly_buttonReleased(QMouseEvent *event); void disassemble_typeChanged(int index); void watch_keyPress(QKeyEvent *event); - void performFind(); - void performFindAll(); - void resultsDoubleClick(int position, int line); - void performReplace(); - void performReplaceAll(); void snippet_constants(); void snippet_samplers(); @@ -301,23 +294,7 @@ private: ScintillaEdit *m_CurInstructionScintilla = NULL; QList m_FileScintillas; - FindReplace *m_FindReplace; - - struct FindState - { - // hash identifies when the search has changed - QString hash; - - // the range identified when the search first occurred (for incremental find/replace) - sptr_t start = 0; - sptr_t end = 0; - - // the current offset where to search from next time, relative to above range - sptr_t offset = 0; - - // the last result - QPair prevResult; - } m_FindState; + FindReplace *m_FindReplace = NULL; SaveCallback m_SaveCallback; RevertCallback m_RevertCallback; @@ -354,8 +331,6 @@ private: std::map m_LogicalBindNames; - QList> m_FindAllResults; - static const int BOOKMARK_MAX_MENU_ENTRY_LENGTH = 40; // max length of bookmark names in menu static const int BOOKMARK_MAX_MENU_ENTRY_COUNT = 30; // max number of bookmarks listed in menu QMap> m_Bookmarks; @@ -370,9 +345,7 @@ private: static const int CURRENT_INDICATOR = 20; static const int FINISHED_INDICATOR = 21; - static const int INDICATOR_FINDRESULT = 0; static const int INDICATOR_REGHIGHLIGHT = 1; - static const int INDICATOR_FINDALLHIGHLIGHT = 2; QString targetName(const ShaderProcessingTool &disasm); @@ -424,10 +397,6 @@ private: const ShaderVariable *GetDebugVariable(const DebugVariableReference &r); - void ensureLineScrolled(ScintillaEdit *s, int i); - - void find(bool down); - void updateEditState(); enum StepMode