mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-10 14:21:31 +00:00
Move find/replace logic out of shader viewer so it can be reused
This commit is contained in:
9 files changed
+736
-514
No files matched your search
@@ -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<SDObject *> &StructuredDataItemModel::objects() const
|
||||
{
|
||||
return m_Objects;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -25,10 +25,16 @@
|
||||
#include "FindReplace.h"
|
||||
#include <QKeyEvent>
|
||||
#include <QLineEdit>
|
||||
#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<ScintillaEdit *> &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<ScintillaEdit *>(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<int, int> 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<ScintillaEdit *> scintillas = m_Scintillas;
|
||||
|
||||
if(ctx == FindReplace::File)
|
||||
scintillas = {cur};
|
||||
|
||||
QList<QPair<int, int>> 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<int, int> 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<int, int> 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<ScintillaEdit *> 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<int, int> 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();
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
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<ScintillaEdit *> &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<ScintillaEdit *> &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<QPair<ScintillaEdit *, int>> 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<int, int> 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();
|
||||
};
|
||||
@@ -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();
|
||||
|
||||
@@ -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<ScintillaEdit *> m_Scintillas;
|
||||
|
||||
FindReplace *m_FindReplace;
|
||||
ScintillaEdit *m_FindResults = NULL;
|
||||
|
||||
void setupTabs();
|
||||
|
||||
ScintillaEdit *curEditor();
|
||||
ScintillaEdit *makeEditor(rdcstr filename);
|
||||
|
||||
void updateEditorCloseButton();
|
||||
|
||||
void addRecentFile(rdcstr filename);
|
||||
|
||||
@@ -251,7 +251,34 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="sep">
|
||||
<widget class="Line" name="sep1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="findReplace">
|
||||
<property name="toolTip">
|
||||
<string>Find & Replace</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Find</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/find.png</normaloff>:/find.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="sep2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
|
||||
@@ -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<int, int> 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<ScintillaEdit *> scintillas = m_Scintillas;
|
||||
|
||||
if(context == FindReplace::File)
|
||||
scintillas = {cur};
|
||||
|
||||
QList<QPair<int, int>> 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<int, int> 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<int, int> 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<ScintillaEdit *> 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<int, int> 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();
|
||||
|
||||
@@ -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<ScintillaEdit *> 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<int, int> prevResult;
|
||||
} m_FindState;
|
||||
FindReplace *m_FindReplace = NULL;
|
||||
|
||||
SaveCallback m_SaveCallback;
|
||||
RevertCallback m_RevertCallback;
|
||||
@@ -354,8 +331,6 @@ private:
|
||||
|
||||
std::map<ShaderDirectAccess, rdcstr> m_LogicalBindNames;
|
||||
|
||||
QList<QPair<ScintillaEdit *, int>> 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<ScintillaEdit *, QList<sptr_t>> 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
|
||||
|
||||
Reference in new issue
Block a user