Various improvements for BinEditor.

- Saving to file only takes modified data into account.
- Search functionality does not exhaust memory anymore.
- Searches can be canceled. This required updating the IFindSupport
  interface and all classes implementing it. No functional changes
  were done in those.

Reviewed-by: mae
This commit is contained in:
ck
2009-09-09 17:11:00 +02:00
parent 85dcd851da
commit 6f5cea2aaa
14 changed files with 209 additions and 106 deletions

View File

@@ -33,6 +33,9 @@
#include <texteditor/texteditorconstants.h> #include <texteditor/texteditorconstants.h>
#include <QtCore/QByteArrayMatcher> #include <QtCore/QByteArrayMatcher>
#include <QtCore/QFile>
#include <QtCore/QTemporaryFile>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QtGui/QClipboard> #include <QtGui/QClipboard>
#include <QtGui/QFontMetrics> #include <QtGui/QFontMetrics>
@@ -136,6 +139,8 @@ void BinEditor::addLazyData(quint64 block, const QByteArray &data)
Q_ASSERT(data.size() == m_blockSize); Q_ASSERT(data.size() == m_blockSize);
const quint64 addr = block * m_blockSize; const quint64 addr = block * m_blockSize;
if (addr >= m_baseAddr && addr <= m_baseAddr + m_size - 1) { if (addr >= m_baseAddr && addr <= m_baseAddr + m_size - 1) {
if (m_lazyData.size() * m_blockSize >= 64 * 1024 * 1024)
m_lazyData.clear();
const int translatedBlock = (addr - m_baseAddr) / m_blockSize; const int translatedBlock = (addr - m_baseAddr) / m_blockSize;
m_lazyData.insert(translatedBlock, data); m_lazyData.insert(translatedBlock, data);
m_lazyRequests.remove(translatedBlock); m_lazyRequests.remove(translatedBlock);
@@ -149,7 +154,10 @@ bool BinEditor::requestDataAt(int pos, bool synchronous) const
return true; return true;
int block = pos / m_blockSize; int block = pos / m_blockSize;
QMap<int, QByteArray>::const_iterator it = m_lazyData.find(block); QMap<int, QByteArray>::const_iterator it = m_modifiedData.find(block);
if (it != m_modifiedData.constEnd())
return true;
it = m_lazyData.find(block);
if (it == m_lazyData.end()) { if (it == m_lazyData.end()) {
if (!m_lazyRequests.contains(block)) { if (!m_lazyRequests.contains(block)) {
m_lazyRequests.insert(block); m_lazyRequests.insert(block);
@@ -168,10 +176,8 @@ char BinEditor::dataAt(int pos) const
{ {
if (!m_inLazyMode) if (!m_inLazyMode)
return m_data.at(pos); return m_data.at(pos);
int block = pos / m_blockSize; int block = pos / m_blockSize;
return m_lazyData.value(block, m_emptyBlock).at(pos - (block*m_blockSize)); return blockData(block).at(pos - (block*m_blockSize));
} }
void BinEditor::changeDataAt(int pos, char c) void BinEditor::changeDataAt(int pos, char c)
@@ -181,8 +187,17 @@ void BinEditor::changeDataAt(int pos, char c)
return; return;
} }
int block = pos / m_blockSize; int block = pos / m_blockSize;
if (m_lazyData.contains(block)) QMap<int, QByteArray>::iterator it = m_modifiedData.find(block);
m_lazyData[block][pos - (block*m_blockSize)] = c; if (it != m_modifiedData.end()) {
it.value()[pos - (block*m_blockSize)] = c;
} else {
it = m_lazyData.find(block);
if (it != m_lazyData.end()) {
QByteArray data = it.value();
data[pos - (block*m_blockSize)] = c;
m_modifiedData.insert(block, data);
}
}
} }
QByteArray BinEditor::dataMid(int from, int length) const QByteArray BinEditor::dataMid(int from, int length) const
@@ -195,7 +210,7 @@ QByteArray BinEditor::dataMid(int from, int length) const
QByteArray data; QByteArray data;
do { do {
data += m_lazyData.value(block++, m_emptyBlock); data += blockData(block++);
} while (block * m_blockSize < end); } while (block * m_blockSize < end);
return data.mid(from - ((from / m_blockSize) * m_blockSize), length); return data.mid(from - ((from / m_blockSize) * m_blockSize), length);
@@ -209,7 +224,9 @@ QByteArray BinEditor::blockData(int block) const
data.resize(m_blockSize); data.resize(m_blockSize);
return data; return data;
} }
return m_lazyData.value(block, m_emptyBlock); QMap<int, QByteArray>::const_iterator it = m_modifiedData.find(block);
return it != m_modifiedData.constEnd()
? it.value() : m_lazyData.value(block, m_emptyBlock);
} }
@@ -302,6 +319,7 @@ void BinEditor::setData(const QByteArray &data)
m_inLazyMode = false; m_inLazyMode = false;
m_baseAddr = 0; m_baseAddr = 0;
m_lazyData.clear(); m_lazyData.clear();
m_modifiedData.clear();
m_lazyRequests.clear(); m_lazyRequests.clear();
m_data = data; m_data = data;
m_size = data.size(); m_size = data.size();
@@ -323,17 +341,45 @@ QByteArray BinEditor::data() const
return m_data; return m_data;
} }
bool BinEditor::applyModifications(QByteArray &data) const bool BinEditor::save(const QString &oldFileName, const QString &newFileName)
{ {
if (!m_inLazyMode) { if (m_inLazyMode) {
data = m_data; if (oldFileName != newFileName) {
return true; QString tmpName;
} {
if (data.size() != m_size) QTemporaryFile tmp;
return false; if (!tmp.open())
for (QMap<int,QByteArray>::const_iterator it = m_lazyData.begin(); it != m_lazyData.end(); ++it) { return false;
::memcpy(data.data() + m_baseAddr + it.key() * m_blockSize, it->constData(), m_blockSize); tmpName = tmp.fileName();
}
if (!QFile::copy(oldFileName, tmpName))
return false;
if (QFile::exists(newFileName) && !QFile::remove(newFileName))
return false;
if (!QFile::rename(tmpName, newFileName))
return false;
}
QFile output(newFileName);
if (!output.open(QIODevice::ReadWrite)) // QtBug: WriteOnly truncates.
return false;
const qint64 size = output.size();
for (QMap<int, QByteArray>::const_iterator it = m_modifiedData.constBegin();
it != m_modifiedData.constEnd(); ++it) {
if (!output.seek(it.key() * m_blockSize))
return false;
if (output.write(it.value()) < m_blockSize)
return false;
}
if (size % m_blockSize != 0 && !output.resize(size))
return false;
} else {
QFile output(newFileName);
if (!output.open(QIODevice::WriteOnly | QIODevice::Truncate))
return false;
if (output.write(m_data) < m_size)
return false;
} }
setModified(false);
return true; return true;
} }
@@ -345,6 +391,7 @@ void BinEditor::setLazyData(quint64 startAddr, int range, int blockSize)
m_emptyBlock = QByteArray(blockSize, '\0'); m_emptyBlock = QByteArray(blockSize, '\0');
m_data.clear(); m_data.clear();
m_lazyData.clear(); m_lazyData.clear();
m_modifiedData.clear();
m_lazyRequests.clear(); m_lazyRequests.clear();
// In lazy mode, users can edit data in the range // In lazy mode, users can edit data in the range
@@ -485,8 +532,9 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti
QByteArrayMatcher matcher(pattern); QByteArrayMatcher matcher(pattern);
int block = from / m_blockSize; int block = from / m_blockSize;
const int end =
while (from < m_size) { qMin<qint64>(static_cast<qint64>(from) + SearchStride, m_size);
while (from < end) {
if (!requestDataAt(block * m_blockSize, true)) if (!requestDataAt(block * m_blockSize, true))
return -1; return -1;
QByteArray data = blockData(block); QByteArray data = blockData(block);
@@ -502,7 +550,7 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti
++block; ++block;
from = block * m_blockSize - trailing; from = block * m_blockSize - trailing;
} }
return -1; return end == m_size ? -1 : -2;
} }
int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSensitive) const int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSensitive) const
@@ -519,8 +567,8 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen
char *b = buffer.data(); char *b = buffer.data();
int block = from / m_blockSize; int block = from / m_blockSize;
const int lowerBound = qMax(0, from - SearchStride);
while (from > 0) { while (from > lowerBound) {
if (!requestDataAt(block * m_blockSize, true)) if (!requestDataAt(block * m_blockSize, true))
return -1; return -1;
QByteArray data = blockData(block); QByteArray data = blockData(block);
@@ -536,7 +584,7 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen
--block; --block;
from = block * m_blockSize + (m_blockSize-1) + trailing; from = block * m_blockSize + (m_blockSize-1) + trailing;
} }
return -1; return lowerBound == 0 ? -1 : -2;
} }
@@ -564,7 +612,8 @@ int BinEditor::find(const QByteArray &pattern_arg, int from,
: dataIndexOf(hexPattern, from); : dataIndexOf(hexPattern, from);
} }
int pos = (found >= 0 && (foundHex < 0 || found < foundHex)) ? found : foundHex; int pos = foundHex == -1 || (found >= 0 && (foundHex == -2 || found < foundHex))
? found : foundHex;
if (pos >= m_size) if (pos >= m_size)
pos = -1; pos = -1;

View File

@@ -31,8 +31,10 @@
#define BINEDITOR_H #define BINEDITOR_H
#include <QtCore/QBasicTimer> #include <QtCore/QBasicTimer>
#include <QtCore/QMap>
#include <QtCore/QSet> #include <QtCore/QSet>
#include <QtCore/QStack> #include <QtCore/QStack>
#include <QtCore/QString>
#include <QtGui/QAbstractScrollArea> #include <QtGui/QAbstractScrollArea>
#include <QtGui/QTextDocument> #include <QtGui/QTextDocument>
@@ -67,7 +69,7 @@ public:
Q_INVOKABLE void setLazyData(quint64 startAddr, int range, int blockSize = 4096); Q_INVOKABLE void setLazyData(quint64 startAddr, int range, int blockSize = 4096);
inline int lazyDataBlockSize() const { return m_blockSize; } inline int lazyDataBlockSize() const { return m_blockSize; }
Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data); Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data);
bool applyModifications(QByteArray &data) const; bool save(const QString &oldFileName, const QString &newFileName);
void zoomIn(int range = 1); void zoomIn(int range = 1);
void zoomOut(int range = 1); void zoomOut(int range = 1);
@@ -109,6 +111,7 @@ public:
QString addressString(quint64 address); QString addressString(quint64 address);
static const int SearchStride = 1024 * 1024;
public Q_SLOTS: public Q_SLOTS:
void setFontSettings(const TextEditor::FontSettings &fs); void setFontSettings(const TextEditor::FontSettings &fs);
@@ -143,6 +146,7 @@ private:
QByteArray m_data; QByteArray m_data;
QMap <int, QByteArray> m_lazyData; QMap <int, QByteArray> m_lazyData;
int m_blockSize; int m_blockSize;
QMap <int, QByteArray> m_modifiedData;
mutable QSet<int> m_lazyRequests; mutable QSet<int> m_lazyRequests;
QByteArray m_emptyBlock; QByteArray m_emptyBlock;
QByteArray m_lowerBlock; QByteArray m_lowerBlock;

View File

@@ -61,7 +61,11 @@ class BinEditorFind : public Find::IFindSupport
{ {
Q_OBJECT Q_OBJECT
public: public:
BinEditorFind(BinEditor *editor) { m_editor = editor; m_incrementalStartPos = -1; } BinEditorFind(BinEditor *editor)
{
m_editor = editor;
m_incrementalStartPos = m_contPos = -1;
}
~BinEditorFind() {} ~BinEditorFind() {}
bool supportsReplace() const { return false; } bool supportsReplace() const { return false; }
@@ -70,7 +74,11 @@ public:
return IFindSupport::FindBackward | IFindSupport::FindCaseSensitively; return IFindSupport::FindBackward | IFindSupport::FindCaseSensitively;
} }
void resetIncrementalSearch() { m_incrementalStartPos = -1; } void resetIncrementalSearch()
{
m_incrementalStartPos = m_contPos = -1;
}
void clearResults() { m_editor->highlightSearchResults(QByteArray()); } void clearResults() { m_editor->highlightSearchResults(QByteArray()); }
QString currentFindString() const { return QString(); } QString currentFindString() const { return QString(); }
QString completedFindString() const { return QString(); } QString completedFindString() const { return QString(); }
@@ -82,41 +90,68 @@ public:
return pos; return pos;
} }
int found = m_editor->find(pattern, pos, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); return m_editor->find(pattern, pos, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
if (found < 0)
found = m_editor->find(pattern,
(findFlags & Find::IFindSupport::FindBackward)?m_editor->dataSize()-1:0,
Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
return found;
} }
bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) { Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) {
QByteArray pattern = txt.toLatin1(); QByteArray pattern = txt.toLatin1();
if (pattern != m_lastPattern)
resetIncrementalSearch(); // Because we don't search for nibbles.
m_lastPattern = pattern;
if (m_incrementalStartPos < 0) if (m_incrementalStartPos < 0)
m_incrementalStartPos = m_editor->selectionStart(); m_incrementalStartPos = m_editor->selectionStart();
int pos = m_incrementalStartPos; if (m_contPos == -1)
m_contPos = m_incrementalStartPos;
findFlags &= ~Find::IFindSupport::FindBackward; findFlags &= ~Find::IFindSupport::FindBackward;
int found = find(pattern, pos, findFlags); int found = find(pattern, m_contPos, findFlags);
if (found >= 0) Result result;
if (found >= 0) {
result = Found;
m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
else m_contPos = -1;
m_editor->highlightSearchResults(QByteArray(), 0); } else {
return found >= 0; if (found == -2) {
result = NotYetFound;
m_contPos +=
findFlags & Find::IFindSupport::FindBackward
? -BinEditor::SearchStride : BinEditor::SearchStride;
} else {
result = NotFound;
m_contPos = -1;
m_editor->highlightSearchResults(QByteArray(), 0);
}
}
return result;
} }
bool findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) { Result findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) {
QByteArray pattern = txt.toLatin1(); QByteArray pattern = txt.toLatin1();
bool wasReset = (m_incrementalStartPos < 0); bool wasReset = (m_incrementalStartPos < 0);
int pos = m_editor->cursorPosition(); if (m_contPos == -1) {
if (findFlags & Find::IFindSupport::FindBackward) m_contPos = m_editor->cursorPosition();
pos = m_editor->selectionStart()-1; if (findFlags & Find::IFindSupport::FindBackward)
int found = find(pattern, pos, findFlags); m_contPos = m_editor->selectionStart()-1;
if (found) }
int found = find(pattern, m_contPos, findFlags);
Result result;
if (found >= 0) {
result = Found;
m_incrementalStartPos = found; m_incrementalStartPos = found;
if (wasReset && found >= 0) m_contPos = -1;
m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); if (wasReset)
return found >= 0; m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags));
} else if (found == -2) {
result = NotYetFound;
m_contPos += findFlags & Find::IFindSupport::FindBackward
? -BinEditor::SearchStride : BinEditor::SearchStride;
} else {
result = NotFound;
m_contPos = -1;
}
return result;
} }
bool replaceStep(const QString &, const QString &, bool replaceStep(const QString &, const QString &,
Find::IFindSupport::FindFlags) { return false;} Find::IFindSupport::FindFlags) { return false;}
int replaceAll(const QString &, const QString &, int replaceAll(const QString &, const QString &,
@@ -125,6 +160,8 @@ public:
private: private:
BinEditor *m_editor; BinEditor *m_editor;
int m_incrementalStartPos; int m_incrementalStartPos;
int m_contPos; // Only valid if last result was NotYetFound.
QByteArray m_lastPattern;
}; };
@@ -144,42 +181,26 @@ public:
virtual QString mimeType() const { return m_mimeType; } virtual QString mimeType() const { return m_mimeType; }
bool save(const QString &fileName = QString()) { bool save(const QString &fileName = QString()) {
QFile file(fileName); if (m_editor->save(m_fileName, fileName)) {
QByteArray data;
if (m_editor->inLazyMode()) {
QFile read(m_fileName);
if (!read.open(QIODevice::ReadOnly))
return false;
data = read.readAll();
read.close();
if (!m_editor->applyModifications(data))
return false;
} else {
data = m_editor->data();
}
if (file.open(QIODevice::WriteOnly)) {
file.write(data);
file.close();
m_editor->setModified(false);
m_editor->editorInterface()->
setDisplayName(QFileInfo(fileName).fileName());
m_fileName = fileName; m_fileName = fileName;
m_editor->editorInterface()->
setDisplayName(QFileInfo(fileName).fileName());
emit changed(); emit changed();
return true; return true;
} else {
return false;
} }
return false;
} }
bool open(const QString &fileName) { bool open(const QString &fileName) {
QFile file(fileName); QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
m_fileName = fileName; m_fileName = fileName;
if (file.isSequential() && file.size() <= INT_MAX) { if (file.isSequential() && file.size() <= 64 * 1024 * 1024) {
m_editor->setData(file.readAll()); m_editor->setData(file.readAll());
} else { } else {
m_editor->setLazyData(0, qMin(file.size(), m_editor->setLazyData(0, qMin(file.size(),
static_cast<qint64>(INT_MAX))); static_cast<qint64>(INT_MAX-16)));
m_editor->editorInterface()-> m_editor->editorInterface()->
setDisplayName(QFileInfo(fileName).fileName()); setDisplayName(QFileInfo(fileName).fileName());
} }

View File

@@ -40,6 +40,7 @@ class CORE_EXPORT IEditor : public IContext
{ {
Q_OBJECT Q_OBJECT
public: public:
IEditor(QObject *parent = 0) : IContext(parent) {} IEditor(QObject *parent = 0) : IContext(parent) {}
virtual ~IEditor() {} virtual ~IEditor() {}

View File

@@ -95,7 +95,7 @@ void MemoryViewAgent::init(quint64 addr)
this, SLOT(fetchLazyData(quint64,bool))); this, SLOT(fetchLazyData(quint64,bool)));
editorManager->activateEditor(m_editor); editorManager->activateEditor(m_editor);
QMetaObject::invokeMethod(m_editor->widget(), "setLazyData", QMetaObject::invokeMethod(m_editor->widget(), "setLazyData",
Q_ARG(quint64, addr), Q_ARG(int, INT_MAX), Q_ARG(int, BinBlockSize)); Q_ARG(quint64, addr), Q_ARG(int, 1024 * 1024), Q_ARG(int, BinBlockSize));
} }
void MemoryViewAgent::fetchLazyData(quint64 block, bool sync) void MemoryViewAgent::fetchLazyData(quint64 block, bool sync)

View File

@@ -125,7 +125,7 @@ QString BaseTextFind::completedFindString() const
return cursor.selectedText(); return cursor.selectedText();
} }
bool BaseTextFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) IFindSupport::Result BaseTextFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags)
{ {
QTextCursor cursor = textCursor(); QTextCursor cursor = textCursor();
if (m_incrementalStartPos < 0) if (m_incrementalStartPos < 0)
@@ -137,15 +137,15 @@ bool BaseTextFind::findIncremental(const QString &txt, IFindSupport::FindFlags f
emit highlightAll(txt, findFlags); emit highlightAll(txt, findFlags);
else else
emit highlightAll(QString(), 0); emit highlightAll(QString(), 0);
return found; return found ? Found : NotFound;
} }
bool BaseTextFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags) IFindSupport::Result BaseTextFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags)
{ {
bool found = find(txt, findFlags, textCursor()); bool found = find(txt, findFlags, textCursor());
if (found) if (found)
m_incrementalStartPos = textCursor().selectionStart(); m_incrementalStartPos = textCursor().selectionStart();
return found; return found ? Found : NotFound;
} }
namespace { namespace {

View File

@@ -53,8 +53,8 @@ public:
QString currentFindString() const; QString currentFindString() const;
QString completedFindString() const; QString completedFindString() const;
bool findIncremental(const QString &txt, IFindSupport::FindFlags findFlags); Result findIncremental(const QString &txt, IFindSupport::FindFlags findFlags);
bool findStep(const QString &txt, IFindSupport::FindFlags findFlags); Result findStep(const QString &txt, IFindSupport::FindFlags findFlags);
bool replaceStep(const QString &before, const QString &after, bool replaceStep(const QString &before, const QString &after,
IFindSupport::FindFlags findFlags); IFindSupport::FindFlags findFlags);
int replaceAll(const QString &before, const QString &after, int replaceAll(const QString &before, const QString &after,

View File

@@ -106,15 +106,15 @@ void CurrentDocumentFind::highlightAll(const QString &txt, IFindSupport::FindFla
m_currentFind->highlightAll(txt, findFlags); m_currentFind->highlightAll(txt, findFlags);
} }
bool CurrentDocumentFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) IFindSupport::Result CurrentDocumentFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags)
{ {
QTC_ASSERT(m_currentFind, return false); QTC_ASSERT(m_currentFind, return IFindSupport::NotFound);
return m_currentFind->findIncremental(txt, findFlags); return m_currentFind->findIncremental(txt, findFlags);
} }
bool CurrentDocumentFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags) IFindSupport::Result CurrentDocumentFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags)
{ {
QTC_ASSERT(m_currentFind, return false); QTC_ASSERT(m_currentFind, return IFindSupport::NotFound);
return m_currentFind->findStep(txt, findFlags); return m_currentFind->findStep(txt, findFlags);
} }

View File

@@ -55,8 +55,8 @@ public:
bool isEnabled() const; bool isEnabled() const;
bool candidateIsEnabled() const; bool candidateIsEnabled() const;
void highlightAll(const QString &txt, IFindSupport::FindFlags findFlags); void highlightAll(const QString &txt, IFindSupport::FindFlags findFlags);
bool findIncremental(const QString &txt, IFindSupport::FindFlags findFlags); IFindSupport::Result findIncremental(const QString &txt, IFindSupport::FindFlags findFlags);
bool findStep(const QString &txt, IFindSupport::FindFlags findFlags); IFindSupport::Result findStep(const QString &txt, IFindSupport::FindFlags findFlags);
bool replaceStep(const QString &before, const QString &after, bool replaceStep(const QString &before, const QString &after,
IFindSupport::FindFlags findFlags); IFindSupport::FindFlags findFlags);
int replaceAll(const QString &before, const QString &after, int replaceAll(const QString &before, const QString &after,

View File

@@ -69,7 +69,8 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_replaceNextAction(0), m_replaceNextAction(0),
m_casesensitiveIcon(":/find/images/casesensitively.png"), m_casesensitiveIcon(":/find/images/casesensitively.png"),
m_regexpIcon(":/find/images/regexp.png"), m_regexpIcon(":/find/images/regexp.png"),
m_wholewordsIcon(":/find/images/wholewords.png") m_wholewordsIcon(":/find/images/wholewords.png"),
m_findIncrementalTimer(this), m_findStepTimer(this)
{ {
//setup ui //setup ui
m_ui.setupUi(this); m_ui.setupUi(this);
@@ -215,6 +216,12 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
connect(m_currentDocumentFind, SIGNAL(candidateChanged()), this, SLOT(adaptToCandidate())); connect(m_currentDocumentFind, SIGNAL(candidateChanged()), this, SLOT(adaptToCandidate()));
connect(m_currentDocumentFind, SIGNAL(changed()), this, SLOT(updateToolBar())); connect(m_currentDocumentFind, SIGNAL(changed()), this, SLOT(updateToolBar()));
updateToolBar(); updateToolBar();
m_findIncrementalTimer.setSingleShot(true);
m_findStepTimer.setSingleShot(true);
connect(&m_findIncrementalTimer, SIGNAL(timeout()),
this, SLOT(invokeFindIncremental()));
connect(&m_findStepTimer, SIGNAL(timeout()), this, SLOT(invokeFindStep()));
} }
FindToolBar::~FindToolBar() FindToolBar::~FindToolBar()
@@ -373,17 +380,27 @@ void FindToolBar::selectFindText()
void FindToolBar::invokeFindStep() void FindToolBar::invokeFindStep()
{ {
m_findStepTimer.stop();
m_findIncrementalTimer.stop();
if (m_currentDocumentFind->isEnabled()) { if (m_currentDocumentFind->isEnabled()) {
m_plugin->updateFindCompletion(getFindText()); m_plugin->updateFindCompletion(getFindText());
m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags()); IFindSupport::Result result =
m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags());
if (result == IFindSupport::NotYetFound)
m_findStepTimer.start(50);
} }
} }
void FindToolBar::invokeFindIncremental() void FindToolBar::invokeFindIncremental()
{ {
m_findIncrementalTimer.stop();
m_findStepTimer.stop();
if (m_currentDocumentFind->isEnabled()) { if (m_currentDocumentFind->isEnabled()) {
QString text = getFindText(); QString text = getFindText();
m_currentDocumentFind->findIncremental(text, effectiveFindFlags()); IFindSupport::Result result =
m_currentDocumentFind->findIncremental(text, effectiveFindFlags());
if (result == IFindSupport::NotYetFound)
m_findIncrementalTimer.start(50);
if (text.isEmpty()) if (text.isEmpty())
m_currentDocumentFind->clearResults(); m_currentDocumentFind->clearResults();
} }
@@ -421,6 +438,8 @@ void FindToolBar::invokeReplaceAll()
void FindToolBar::invokeResetIncrementalSearch() void FindToolBar::invokeResetIncrementalSearch()
{ {
m_findIncrementalTimer.stop();
m_findStepTimer.stop();
if (m_currentDocumentFind->isEnabled()) if (m_currentDocumentFind->isEnabled())
m_currentDocumentFind->resetIncrementalSearch(); m_currentDocumentFind->resetIncrementalSearch();
} }

View File

@@ -37,6 +37,8 @@
#include <coreplugin/findplaceholder.h> #include <coreplugin/findplaceholder.h>
#include <utils/styledbar.h> #include <utils/styledbar.h>
#include <QtCore/QTimer>
#include <QtGui/QStringListModel> #include <QtGui/QStringListModel>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QtGui/QLabel> #include <QtGui/QLabel>
@@ -124,6 +126,9 @@ private:
QPixmap m_casesensitiveIcon; QPixmap m_casesensitiveIcon;
QPixmap m_regexpIcon; QPixmap m_regexpIcon;
QPixmap m_wholewordsIcon; QPixmap m_wholewordsIcon;
QTimer m_findIncrementalTimer;
QTimer m_findStepTimer;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -50,6 +50,8 @@ public:
}; };
Q_DECLARE_FLAGS(FindFlags, FindFlag) Q_DECLARE_FLAGS(FindFlags, FindFlag)
enum Result { Found, NotFound, NotYetFound };
IFindSupport() : QObject(0) {} IFindSupport() : QObject(0) {}
virtual ~IFindSupport() {} virtual ~IFindSupport() {}
@@ -61,8 +63,8 @@ public:
virtual QString completedFindString() const = 0; virtual QString completedFindString() const = 0;
virtual void highlightAll(const QString &txt, FindFlags findFlags); virtual void highlightAll(const QString &txt, FindFlags findFlags);
virtual bool findIncremental(const QString &txt, FindFlags findFlags) = 0; virtual Result findIncremental(const QString &txt, FindFlags findFlags) = 0;
virtual bool findStep(const QString &txt, FindFlags findFlags) = 0; virtual Result findStep(const QString &txt, FindFlags findFlags) = 0;
virtual bool replaceStep(const QString &before, const QString &after, virtual bool replaceStep(const QString &before, const QString &after,
FindFlags findFlags) = 0; FindFlags findFlags) = 0;
virtual int replaceAll(const QString &before, const QString &after, virtual int replaceAll(const QString &before, const QString &after,

View File

@@ -72,17 +72,19 @@ QString HelpFindSupport::completedFindString() const
return QString(); return QString();
} }
bool HelpFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) Find::IFindSupport::Result HelpFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags)
{ {
QTC_ASSERT(m_centralWidget, return false); QTC_ASSERT(m_centralWidget, return NotFound);
findFlags &= ~Find::IFindSupport::FindBackward; findFlags &= ~Find::IFindSupport::FindBackward;
return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), true); return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), true)
? Found : NotFound;
} }
bool HelpFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) Find::IFindSupport::Result HelpFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags)
{ {
QTC_ASSERT(m_centralWidget, return false); QTC_ASSERT(m_centralWidget, return NotFound);
return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), false); return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), false)
? Found : NotFound;
} }
HelpViewerFindSupport::HelpViewerFindSupport(HelpViewer *viewer) HelpViewerFindSupport::HelpViewerFindSupport(HelpViewer *viewer)
@@ -106,17 +108,17 @@ QString HelpViewerFindSupport::currentFindString() const
#endif #endif
} }
bool HelpViewerFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) Find::IFindSupport::Result HelpViewerFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags)
{ {
QTC_ASSERT(m_viewer, return false); QTC_ASSERT(m_viewer, return NotFound);
findFlags &= ~Find::IFindSupport::FindBackward; findFlags &= ~Find::IFindSupport::FindBackward;
return find(txt, findFlags, true); return find(txt, findFlags, true) ? Found : NotFound;
} }
bool HelpViewerFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) Find::IFindSupport::Result HelpViewerFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags)
{ {
QTC_ASSERT(m_viewer, return false); QTC_ASSERT(m_viewer, return NotFound);
return find(txt, findFlags, false); return find(txt, findFlags, false) ? Found : NotFound;
} }
bool HelpViewerFindSupport::find(const QString &txt, Find::IFindSupport::FindFlags findFlags, bool incremental) bool HelpViewerFindSupport::find(const QString &txt, Find::IFindSupport::FindFlags findFlags, bool incremental)

View File

@@ -57,8 +57,8 @@ public:
QString currentFindString() const; QString currentFindString() const;
QString completedFindString() const; QString completedFindString() const;
bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags); Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags);
bool findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags); Result findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags);
bool replaceStep(const QString &, const QString &, bool replaceStep(const QString &, const QString &,
Find::IFindSupport::FindFlags ) { return false; } Find::IFindSupport::FindFlags ) { return false; }
int replaceAll(const QString &, const QString &, int replaceAll(const QString &, const QString &,
@@ -84,8 +84,8 @@ public:
QString currentFindString() const; QString currentFindString() const;
QString completedFindString() const { return QString(); } QString completedFindString() const { return QString(); }
bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags); Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags);
bool findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags); Result findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags);
bool replaceStep(const QString &, const QString &, bool replaceStep(const QString &, const QString &,
Find::IFindSupport::FindFlags ) { return false; } Find::IFindSupport::FindFlags ) { return false; }
int replaceAll(const QString &, const QString &, int replaceAll(const QString &, const QString &,