fix: 重构查找对话框;搜索字节支持'?'通配符(WIP);

This commit is contained in:
寂静的羽夏 2025-02-23 23:36:02 +08:00
parent 3b4d1a1d4b
commit 82c8466335
20 changed files with 1176 additions and 706 deletions

View File

@ -414,8 +414,8 @@ void QHexDocument::applyBookMarks(const QMap<qsizetype, QString> &books) {
emit documentChanged();
}
void QHexDocument::findAllBytes(qsizetype begin, qsizetype end, QByteArray b,
QList<qsizetype> &results,
void QHexDocument::findAllBytes(qsizetype begin, qsizetype end,
const QByteArray &b, QList<qsizetype> &results,
const std::function<bool()> &pred) {
results.clear();
if (!b.length())
@ -424,7 +424,7 @@ void QHexDocument::findAllBytes(qsizetype begin, qsizetype end, QByteArray b,
qsizetype e = end > begin ? end : -1;
auto offset = b.size();
while (pred()) {
p = m_buffer->indexOf(b, p);
p = findNext(p, b);
if (p < 0 || (e > 0 && p > e)) {
break;
}
@ -434,10 +434,51 @@ void QHexDocument::findAllBytes(qsizetype begin, qsizetype end, QByteArray b,
break;
}
results.append(p);
p += offset + 1;
p += offset;
}
}
qsizetype QHexDocument::findAllBytesExt(qsizetype begin, qsizetype end,
const QString &pattern,
QList<qsizetype> &results,
const std::function<bool()> &pred) {
results.clear();
auto patterns = parseConvertPattern(pattern);
if (patterns.isEmpty()) {
return 0;
}
qsizetype p = begin > 0 ? begin : 0;
qsizetype e = end > begin ? end : -1;
qsizetype offset = 0;
for (auto &p : patterns) {
if (std::holds_alternative<QByteArray>(p)) {
offset += std::get<QByteArray>(p).length();
} else if (std::holds_alternative<size_t>(p)) {
offset += std::get<size_t>(p);
} else if (std::holds_alternative<HexWildItem>(p)) {
offset += 1;
}
}
while (pred()) {
p = findNextExt(p, pattern);
if (p < 0 || (e > 0 && p > e)) {
break;
}
if (results.size() ==
std::numeric_limits<QList<qsizetype>::size_type>::max()) {
break;
}
results.append(p);
p += offset;
}
return offset;
}
bool QHexDocument::insert(qsizetype offset, uchar b) {
if (m_keepsize || m_readonly || m_islocked ||
(offset < m_buffer->length() && m_metadata->hasMetadata()))
@ -499,6 +540,259 @@ bool QHexDocument::_remove(qsizetype offset, qsizetype len) {
return true;
}
qsizetype QHexDocument::findNextExt(qsizetype begin,
const QList<FindStep> &patterns) {
auto op = [this](qsizetype &pos, const FindStep &step) -> bool {
if (pos < 0 || pos >= length()) {
return false;
}
if (std::holds_alternative<QByteArray>(step)) {
auto v = std::get<QByteArray>(step);
auto len = v.length();
auto r = findNext(pos, v);
if (r >= 0) {
pos = r + len;
return true;
} else {
pos += len;
}
} else if (std::holds_alternative<HexWildItem>(step)) {
auto v = std::get<HexWildItem>(step);
auto wc = uchar(at(pos));
pos += 1;
if (v.higher == '?') {
if ((wc & 0xf) == v.lower) {
return true;
}
} else {
if ((wc >> 4) == v.higher) {
return true;
}
}
} else if (std::holds_alternative<size_t>(step)) {
auto v = std::get<size_t>(step);
pos += v;
if (v + pos < length()) {
return true;
}
}
return false;
};
while (begin < length()) {
auto pos = begin;
auto p = patterns.cbegin();
auto r = op(pos, *p);
if (!r) {
continue;
}
++p;
bool ok = true;
for (; p != patterns.cend(); ++p) {
auto r = op(pos, *p);
if (!r) {
ok = false;
begin = pos;
break;
}
}
if (ok) {
return begin;
}
}
return -1;
}
qsizetype QHexDocument::findPreviousExt(qsizetype begin,
const QList<FindStep> &patterns) {
auto op = [this](qsizetype pos, const FindStep &step,
qsizetype &len) -> bool {
len = 0;
if (pos < 0 || pos >= length()) {
return false;
}
if (std::holds_alternative<QByteArray>(step)) {
auto v = std::get<QByteArray>(step);
len = v.length();
if (findPrevious(pos, v) >= 0) {
return true;
}
} else if (std::holds_alternative<HexWildItem>(step)) {
auto v = std::get<HexWildItem>(step);
auto wc = uchar(at(pos));
len = 1;
if (v.higher == '?') {
if ((wc & 0xf) == v.lower) {
return true;
}
} else {
if ((wc >> 4) == v.higher) {
return true;
}
}
} else if (std::holds_alternative<size_t>(step)) {
auto v = std::get<size_t>(step);
len = v;
if (pos - v >= 0) {
return true;
}
}
return false;
};
while (begin >= 0) {
auto pos = begin;
qsizetype len;
auto p = patterns.crbegin();
auto r = op(pos, *p, len);
if (r) {
pos -= len;
} else {
begin = pos - len;
continue;
}
++p;
bool ok = true;
for (; p != patterns.crend(); ++p) {
auto r = op(pos, *p, len);
if (r) {
pos -= len;
} else {
ok = false;
begin = pos;
break;
}
}
if (ok) {
return begin;
}
}
return -1;
}
QList<QHexDocument::FindStep>
QHexDocument::parseConvertPattern(const QString &pattern) {
// process hex pattern
QList<HexWildItem> words;
std::optional<uchar> higher;
for (auto pchar = pattern.cbegin(); pchar != pattern.cend(); ++pchar) {
if (pchar->isSpace()) {
if (higher) {
return {};
} else {
continue;
}
}
auto c = pchar->unicode();
if (c >= '0' && c <= '9') {
if (higher) {
HexWildItem item;
item.higher = higher.value();
item.lower = uchar(c) - '0';
words.append(item);
higher.reset();
} else {
higher = uchar(c) - '0';
}
} else if (c >= 'A' && c <= 'F') {
if (higher) {
HexWildItem item;
item.higher = higher.value();
item.lower = uchar(c) - 'A' + 10;
words.append(item);
higher.reset();
} else {
higher = uchar(c) - 'A' + 10;
}
} else if (c >= 'a' && c <= 'f') {
if (higher) {
HexWildItem item;
item.higher = higher.value();
item.lower = uchar(c) - 'a' + 10;
words.append(item);
higher.reset();
} else {
higher = uchar(c) - 'a' + 10;
}
} else if (c == '?') {
if (higher) {
HexWildItem item;
item.higher = higher.value();
item.lower = '?';
words.append(item);
higher.reset();
} else {
higher = '?';
}
}
}
if (higher) {
return {};
}
if (!words.isEmpty()) {
QList<FindStep> steps;
// parsing...
QByteArray buffer;
size_t len = 0;
for (auto pw = words.cbegin(); pw != words.cend(); ++pw) {
auto higher = pw->higher;
auto lower = pw->lower;
if (higher == '?' || lower == '?') {
if (higher == '?' && lower == '?') {
if (!buffer.isEmpty()) {
steps.append(buffer);
buffer.clear();
}
len++;
} else {
if (len != 0) {
steps.append(len);
len = 0;
}
if (!buffer.isEmpty()) {
steps.append(buffer);
buffer.clear();
}
HexWildItem item;
item.higher = higher;
item.lower = lower;
steps.append(item);
}
} else {
if (len != 0) {
steps.append(len);
len = 0;
}
buffer.append(char(pw->higher << 4 | pw->lower));
}
}
// clean up
if (len != 0) {
steps.append(len);
}
if (!buffer.isEmpty()) {
steps.append(buffer);
}
return steps;
}
return {};
}
/*======================*/
// modified by wingsummer
@ -728,20 +1022,39 @@ bool QHexDocument::saveTo(QIODevice *device, bool cleanUndo) {
return true;
}
qsizetype QHexDocument::searchForward(qsizetype begin, const QByteArray &ba) {
qsizetype QHexDocument::findNext(qsizetype begin, const QByteArray &ba) {
if (begin < 0) {
return -1;
}
return m_buffer->indexOf(ba, begin);
}
qsizetype QHexDocument::searchBackward(qsizetype begin, const QByteArray &ba) {
qsizetype QHexDocument::findPrevious(qsizetype begin, const QByteArray &ba) {
if (begin < 0) {
return -1;
}
return m_buffer->lastIndexOf(ba, begin);
}
qsizetype QHexDocument::findNextExt(qsizetype begin, const QString &pattern) {
auto patterns = parseConvertPattern(pattern);
if (patterns.isEmpty()) {
return -1;
}
return findNextExt(begin, patterns);
}
qsizetype QHexDocument::findPreviousExt(qsizetype begin,
const QString &pattern) {
auto patterns = parseConvertPattern(pattern);
if (patterns.isEmpty()) {
return -1;
}
return findPreviousExt(begin, patterns);
}
QHexDocument *QHexDocument::fromLargeFile(const QString &filename,
bool readonly) {

View File

@ -103,7 +103,13 @@ public:
bool existBookMark(qsizetype pos);
void findAllBytes(
qsizetype begin, qsizetype end, QByteArray b, QList<qsizetype> &results,
qsizetype begin, qsizetype end, const QByteArray &b,
QList<qsizetype> &results,
const std::function<bool()> &pred = [] { return true; });
qsizetype findAllBytesExt(
qsizetype begin, qsizetype end, const QString &pattern,
QList<qsizetype> &results,
const std::function<bool()> &pred = [] { return true; });
bool isDocSaved();
@ -179,8 +185,11 @@ public slots:
/*================================*/
// added by wingsummer
qsizetype searchForward(qsizetype begin, const QByteArray &ba);
qsizetype searchBackward(qsizetype begin, const QByteArray &ba);
qsizetype findNext(qsizetype begin, const QByteArray &ba);
qsizetype findPrevious(qsizetype begin, const QByteArray &ba);
qsizetype findNextExt(qsizetype begin, const QString &pattern);
qsizetype findPreviousExt(qsizetype begin, const QString &pattern);
bool insert(qsizetype offset, uchar b);
bool insert(qsizetype offset, const QByteArray &data);
@ -194,6 +203,20 @@ public slots:
bool _replace(qsizetype offset, const QByteArray &data);
bool _remove(qsizetype offset, qsizetype len);
private:
// AB
struct HexWildItem {
uchar higher; // A
uchar lower; // B
};
// std::variant< find-content, hex with wildcard, all-wildcards >
using FindStep = std::variant<QByteArray, HexWildItem, size_t>;
QList<FindStep> parseConvertPattern(const QString &pattern);
qsizetype findNextExt(qsizetype begin, const QList<FindStep> &patterns);
qsizetype findPreviousExt(qsizetype begin, const QList<FindStep> &patterns);
/*================================*/
/*================================*/

View File

@ -336,21 +336,21 @@ void QHexView::setCopyLimit(qsizetype newCopylimit) {
qreal QHexView::scaleRate() const { return m_scaleRate; }
qsizetype QHexView::searchForward(qsizetype begin, const QByteArray &ba) {
qsizetype QHexView::findNext(qsizetype begin, const QByteArray &ba) {
if (begin < 0) {
begin = m_cursor->position().offset();
}
return m_document->searchForward(begin, ba);
return m_document->findNext(begin, ba);
}
qsizetype QHexView::searchBackward(qsizetype begin, const QByteArray &ba) {
qsizetype QHexView::findPrevious(qsizetype begin, const QByteArray &ba) {
qsizetype startPos;
if (begin < 0) {
startPos = m_cursor->position().offset() - 1;
} else {
startPos = begin;
}
return m_document->searchBackward(startPos, ba);
return m_document->findPrevious(startPos, ba);
}
bool QHexView::RemoveSelection(int nibbleindex) {

View File

@ -122,8 +122,8 @@ public:
void setScaleRate(qreal rate);
qreal scaleRate() const;
qsizetype searchForward(qsizetype begin, const QByteArray &ba);
qsizetype searchBackward(qsizetype begin, const QByteArray &ba);
qsizetype findNext(qsizetype begin, const QByteArray &ba);
qsizetype findPrevious(qsizetype begin, const QByteArray &ba);
bool RemoveSelection(int nibbleindex = 1);
bool removeSelection();

View File

@ -282,7 +282,8 @@ set(CLASS_SRC
src/class/diffutil.cpp
src/class/clickcallback.h
src/class/crashhandler.h
src/class/crashhandler.cpp)
src/class/crashhandler.cpp
src/class/hexstringvalidator.h src/class/hexstringvalidator.cpp)
set(INTERNAL_PLG_SRC
src/class/wingangelapi.h src/class/wingangelapi.cpp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "hexstringvalidator.h"
#include <QRegularExpression>
HexStringValidator::HexStringValidator(QObject *parent) : QValidator(parent) {}
QValidator::State HexStringValidator::validate(QString &input, int &pos) const {
const QChar space = QLatin1Char(' ');
QString data = input;
data.remove(space);
if (data.isEmpty())
return Intermediate;
// limit maximum size and forbid trailing spaces
if (input.endsWith(space))
return Invalid;
// check if all input is valid
static const QRegularExpression re(QStringLiteral("^[[:xdigit:]?]*$"));
auto m = re.match(data);
if (!m.hasMatch())
return Invalid;
// insert a space after every two hex nibbles
static const QRegularExpression insertSpace(
QStringLiteral("(?:[[:xdigit:]?]{2} )*[[:xdigit:]?]{3}"));
m = insertSpace.match(input);
if (m.hasMatch()) {
input.insert(input.size() - 1, space);
pos = input.size();
}
input = input.toUpper();
return Acceptable;
}

View File

@ -0,0 +1,32 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** This program is free software: you can redistribute it and/or modify it under
** the terms of the GNU Affero General Public License as published by the Free
** Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
** details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef HEXSTRINGVALIDATOR_H
#define HEXSTRINGVALIDATOR_H
#include <QString>
#include <QValidator>
class HexStringValidator : public QValidator {
Q_OBJECT
public:
explicit HexStringValidator(QObject *parent = nullptr);
QValidator::State validate(QString &input, int &pos) const override;
};
#endif // HEXSTRINGVALIDATOR_H

View File

@ -775,15 +775,15 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
registerAPI<qsizetype(qsizetype, const CScriptArray &)>(
engine,
std::bind(&WingAngelAPI::_HexReader_searchForward, this,
std::bind(&WingAngelAPI::_HexReader_findNext, this,
std::placeholders::_1, std::placeholders::_2),
QSIZETYPE_WRAP("searchForward(" QSIZETYPE " begin, byte[] &in ba)"));
QSIZETYPE_WRAP("findNext(" QSIZETYPE " begin, byte[] &in ba)"));
registerAPI<qsizetype(qsizetype, const CScriptArray &)>(
engine,
std::bind(&WingAngelAPI::_HexReader_searchBackward, this,
std::bind(&WingAngelAPI::_HexReader_findPrevious, this,
std::placeholders::_1, std::placeholders::_2),
QSIZETYPE_WRAP("searchBackward(" QSIZETYPE " begin, byte[] &in ba)"));
QSIZETYPE_WRAP("findPrevious(" QSIZETYPE " begin, byte[] &in ba)"));
registerAPI<CScriptArray *(qsizetype, qsizetype, const CScriptArray &)>(
engine,
@ -2374,8 +2374,8 @@ CScriptArray *WingAngelAPI::_HexReader_readBytes(qsizetype offset,
});
}
qsizetype WingAngelAPI::_HexReader_searchForward(qsizetype begin,
const CScriptArray &ba) {
qsizetype WingAngelAPI::_HexReader_findNext(qsizetype begin,
const CScriptArray &ba) {
// If called from the script, there will always be an active
// context, which can be used to obtain a pointer to the engine.
asIScriptContext *ctx = asGetActiveContext();
@ -2386,14 +2386,14 @@ qsizetype WingAngelAPI::_HexReader_searchForward(qsizetype begin,
auto byteID = engine->GetTypeIdByDecl("byte");
Q_ASSERT(byteID);
auto bab = cArray2ByteArray(ba, byteID, &ok);
return emit reader.searchForward(begin, bab);
return emit reader.findNext(begin, bab);
} else {
return qsizetype(-1);
}
}
qsizetype WingAngelAPI::_HexReader_searchBackward(qsizetype begin,
const CScriptArray &ba) {
qsizetype WingAngelAPI::_HexReader_findPrevious(qsizetype begin,
const CScriptArray &ba) {
// If called from the script, there will always be an active
// context, which can be used to obtain a pointer to the engine.
asIScriptContext *ctx = asGetActiveContext();
@ -2404,7 +2404,7 @@ qsizetype WingAngelAPI::_HexReader_searchBackward(qsizetype begin,
auto byteID = engine->GetTypeIdByDecl("byte");
auto bab = cArray2ByteArray(ba, byteID, &ok);
if (ok) {
return emit reader.searchBackward(begin, bab);
return emit reader.findPrevious(begin, bab);
} else {
return qsizetype(-1);
}

View File

@ -223,9 +223,9 @@ private:
CScriptArray *_HexReader_readBytes(qsizetype offset, qsizetype len);
qsizetype _HexReader_searchForward(qsizetype begin, const CScriptArray &ba);
qsizetype _HexReader_findNext(qsizetype begin, const CScriptArray &ba);
qsizetype _HexReader_searchBackward(qsizetype begin,
qsizetype _HexReader_findPrevious(qsizetype begin,
const CScriptArray &ba);
CScriptArray *_HexReader_findAllBytes(qsizetype begin, qsizetype end,

View File

@ -204,17 +204,20 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
} break;
}
QByteArray data;
QString data;
data = result.str;
qsizetype contextLen = 0;
if (result.isStringFind) {
data = Utilities::encodingString(result.str, result.encoding);
auto raw = Utilities::encodingString(data, result.encoding);
contextLen = raw.length();
m_findResults->setEncoding(result.encoding);
d->findAllBytes(begin, end, raw, results);
} else {
data = result.buffer;
contextLen = d->findAllBytesExt(begin, end, result.str, results);
}
d->findAllBytes(begin, end, data, results);
m_findResults->beginUpdate();
m_findResults->clear();
@ -226,7 +229,7 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
r.col = r.offset % lineWidth;
m_findResults->results().append(r);
m_findResults->findData().append(
readContextFinding(ritem, data.size(), FIND_CONTEXT_SIZE,
readContextFinding(ritem, contextLen, FIND_CONTEXT_SIZE,
FIND_MAX_DISPLAY_FIND_CHARS));
}

View File

@ -25,60 +25,71 @@
#include <QShortcut>
#include <QVBoxLayout>
#include "control/toast.h"
FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
: FramelessDialogBase(parent) {
_hexvalidator = new HexStringValidator(this);
auto widget = new QWidget(this);
auto layout = new QVBoxLayout(widget);
m_string = new QRadioButton(this);
m_string->setText(tr("findstring"));
layout->addWidget(m_string);
layout->addSpacing(3);
m_encodings = new QComboBox(this);
m_encodings->addItems(Utilities::getEncodings());
m_encodings->setCurrentIndex(0);
m_encodings->setEnabled(false);
connect(m_string, &QRadioButton::toggled, m_encodings,
&QComboBox::setEnabled);
layout->addWidget(m_encodings);
layout->addWidget(new QLabel(tr("Mode:"), this));
m_findMode = new QComboBox(this);
m_findMode->addItem(QStringLiteral("HEX"));
m_findMode->addItems(Utilities::getEncodings());
m_findMode->setCurrentIndex(1);
layout->addWidget(m_findMode);
layout->addSpacing(3);
layout->addWidget(new QLabel(tr("Content:"), this));
m_lineeditor = new QLineEdit(this);
m_lineeditor->setEnabled(false);
connect(m_string, &QRadioButton::toggled, m_lineeditor,
&QLineEdit::setEnabled);
layout->addWidget(m_lineeditor);
layout->addSpacing(3);
m_hex = new QRadioButton(this);
m_hex->setText(tr("findhex"));
layout->addWidget(m_hex);
layout->addSpacing(3);
layout->addWidget(new QLabel(tr("EncBytes:"), this));
m_preview = new QTextEdit(this);
m_preview->setFocusPolicy(Qt::NoFocus);
m_preview->setReadOnly(true);
m_preview->setUndoRedoEnabled(false);
m_preview->setWordWrapMode(QTextOption::WordWrap);
m_preview->setAcceptRichText(false);
m_preview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
layout->addWidget(m_preview);
m_hexeditor = new QHexView(this);
m_hexeditor->setAsciiVisible(false);
m_hexeditor->setAddressVisible(false);
m_hexeditor->setEnabled(true);
connect(m_hex, &QRadioButton::toggled, m_hexeditor, &QHexView::setEnabled);
layout->addWidget(m_hexeditor);
layout->addSpacing(10);
connect(m_lineeditor, &QLineEdit::textChanged, this,
[this](const QString &text) {
if (m_findMode->currentIndex()) {
auto encoding = m_findMode->currentText();
auto dbytes = Utilities::encodingString(text, encoding);
m_preview->setText(dbytes.toHex(' '));
} else {
m_preview->setText(text);
}
});
connect(m_findMode, &QComboBox::currentIndexChanged, this,
[this](int index) {
auto oldva = m_lineeditor->validator();
auto newva = index > 0 ? nullptr : _hexvalidator;
m_lineeditor->setValidator(newva);
if (oldva != newva) {
m_lineeditor->clear();
} else {
// force update
emit m_lineeditor->textChanged(m_lineeditor->text());
}
});
if (info.isStringFind) {
m_string->setChecked(true);
m_lineeditor->setEnabled(true);
m_hexeditor->setEnabled(false);
if (!info.encoding.isEmpty()) {
m_encodings->setCurrentText(info.encoding);
m_findMode->setCurrentText(info.encoding);
}
} else {
m_hex->setChecked(true);
m_lineeditor->setEnabled(false);
m_hexeditor->setEnabled(true);
m_findMode->setCurrentIndex(0);
}
m_lineeditor->setText(info.str);
m_hexeditor->document()->_insert(0, info.buffer);
auto regionw = new QWidget(this);
auto regionLayout = new QHBoxLayout(regionw);
@ -106,8 +117,6 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
m_regionStop->setPrefix(QStringLiteral("0x"));
regionLayout->addWidget(m_regionStop, 1);
layout->addWidget(regionw);
auto group = new QButtonGroup(this);
group->setExclusive(true);
@ -134,8 +143,8 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
if (b) {
_result.dir = SearchDirection::Region;
}
m_regionStart->setEnabled(b);
m_regionStop->setEnabled(b);
regionw->setVisible(b);
regionw->setEnabled(b);
});
group->addButton(b, id++);
buttonLayout->addWidget(b);
@ -177,7 +186,7 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
group->button(info.isBigFile ? 1 : 0)->setChecked(true);
layout->addWidget(btnBox);
layout->addSpacing(20);
auto dbbox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
connect(dbbox, &QDialogButtonBox::accepted, this, &FindDialog::on_accept);
@ -185,25 +194,42 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
auto key = QKeySequence(Qt::Key_Return);
auto s = new QShortcut(key, this);
connect(s, &QShortcut::activated, this, &FindDialog::on_accept);
layout->addWidget(regionw);
regionw->hide();
layout->addSpacing(20);
layout->addWidget(dbbox);
buildUpContent(widget);
this->setWindowTitle(tr("find"));
m_lineeditor->setFocus();
}
FindDialog::Result FindDialog::getResult() const { return _result; }
void FindDialog::on_accept() {
_result.start = 0;
_result.stop = 0;
_result.isStringFind = m_findMode->currentIndex() > 0;
_result.str = m_lineeditor->text();
if (!_result.isStringFind) {
// check the last byte nibbles
if (std::next(_result.str.rbegin())->isSpace()) {
Toast::toast(this, NAMEICONRES("find"), tr("InvalidHexSeq"));
return;
}
}
if (m_regionStart->isEnabled()) {
_result.start = m_regionStart->value();
_result.stop = m_regionStop->value();
} else {
_result.start = 0;
_result.stop = 0;
}
_result.encoding = m_encodings->currentText();
_result.isStringFind = m_string->isChecked();
_result.buffer = m_hexeditor->document()->read(0);
_result.str = m_lineeditor->text();
_result.encoding = m_findMode->currentText();
done(1);
}

View File

@ -18,14 +18,16 @@
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include "QHexView/qhexview.h"
#include "control/qtlonglongspinbox.h"
#include "framelessdialogbase.h"
#include "class/hexstringvalidator.h"
#include <QComboBox>
#include <QLineEdit>
#include <QObject>
#include <QRadioButton>
#include <QTextEdit>
enum class SearchDirection { None, Region, Foreword, Backword, Selection };
@ -39,7 +41,6 @@ public:
// for searching info
bool isStringFind;
QByteArray buffer;
QString encoding;
QString str;
};
@ -66,11 +67,11 @@ private:
void on_reject();
private:
QHexView *m_hexeditor;
QLineEdit *m_lineeditor;
QRadioButton *m_string;
QRadioButton *m_hex;
QComboBox *m_encodings;
QComboBox *m_findMode;
QTextEdit *m_preview;
HexStringValidator *_hexvalidator;
QtLongLongSpinBox *m_regionStart;
QtLongLongSpinBox *m_regionStop;

View File

@ -661,9 +661,6 @@ MainWindow::buildUpFindResultDock(ads::CDockManager *dock,
m_findresult->setModel(_findEmptyResult);
m_findEncoding.value(_findEmptyResult->encoding())->setChecked(true);
header->setSectionResizeMode(3, QHeaderView::Stretch);
header->setSectionResizeMode(4, QHeaderView::Stretch);
connect(m_findresult, &QTableView::doubleClicked, this,
[=](const QModelIndex &index) {
auto editor =
@ -2301,7 +2298,6 @@ void MainWindow::on_findfile() {
auto r = fd.getResult();
info.isStringFind = r.isStringFind;
info.encoding = r.encoding;
info.buffer = r.buffer;
info.str = r.str;
ExecAsync<EditorView::FindError>(
@ -2775,8 +2771,7 @@ void MainWindow::on_exportfindresult() {
auto d = findresitem->lastFindData();
fobj.insert(QStringLiteral("find"),
QString::fromLatin1(d.toHex(' ').toUpper()));
fobj.insert(QStringLiteral("find"), d);
QJsonArray arr;
for (int i = 0; i < c; i++) {
auto data = findresitem->resultAt(i);

View File

@ -133,7 +133,7 @@ QList<FindResultModel::FindInfo> &FindResultModel::findData() {
return m_findData;
}
QByteArray &FindResultModel::lastFindData() { return m_lastFindData; }
QString &FindResultModel::lastFindData() { return m_lastFindData; }
void FindResultModel::beginUpdate() { this->beginResetModel(); }

View File

@ -38,7 +38,7 @@ public:
QList<WingHex::FindResult> &results();
QList<FindInfo> &findData();
QByteArray &lastFindData();
QString &lastFindData();
void beginUpdate();
void endUpdate();
@ -63,7 +63,7 @@ public:
private:
QList<WingHex::FindResult> m_results;
QList<FindInfo> m_findData;
QByteArray m_lastFindData;
QString m_lastFindData;
QString m_encoding;
};

View File

@ -142,9 +142,9 @@ signals:
const QString &encoding = QString());
Q_REQUIRED_RESULT QByteArray readBytes(qsizetype offset, qsizetype count);
Q_REQUIRED_RESULT qsizetype searchForward(qsizetype begin,
Q_REQUIRED_RESULT qsizetype findNext(qsizetype begin,
const QByteArray &ba);
Q_REQUIRED_RESULT qsizetype searchBackward(qsizetype begin,
Q_REQUIRED_RESULT qsizetype findPrevious(qsizetype begin,
const QByteArray &ba);
Q_REQUIRED_RESULT QList<qsizetype>
findAllBytes(qsizetype begin, qsizetype end, const QByteArray &b);

View File

@ -1875,9 +1875,9 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
_rwlock.lockForRead();
auto hexeditor = e->hexEditor();
auto doc = hexeditor->document();
auto pos = doc->searchForward(offset, QByteArray(1, 0));
auto pos = doc->findNext(offset, QByteArray(1, 0));
if (pos < 0) {
pos = doc->searchForward(offset, QByteArray(1, '\n'));
pos = doc->findNext(offset, QByteArray(1, '\n'));
if (pos < 0) {
return QString();
}
@ -1900,19 +1900,19 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
}
return results;
});
connect(preader, &WingPlugin::Reader::searchForward, _win,
connect(preader, &WingPlugin::Reader::findNext, _win,
[=](qsizetype begin, const QByteArray &ba) -> qsizetype {
auto e = pluginCurrentEditor(plg);
if (e) {
return e->hexEditor()->document()->searchForward(begin, ba);
return e->hexEditor()->document()->findNext(begin, ba);
}
return qsizetype(-1);
});
connect(preader, &WingPlugin::Reader::searchBackward, _win,
connect(preader, &WingPlugin::Reader::findPrevious, _win,
[=](qsizetype begin, const QByteArray &ba) -> qsizetype {
auto e = pluginCurrentEditor(plg);
if (e) {
return e->hexEditor()->document()->searchBackward(begin,
return e->hexEditor()->document()->findPrevious(begin,
ba);
}
return qsizetype(-1);

View File

@ -149,6 +149,7 @@ public:
}
}
#endif
encodings.sort();
}
return encodings;