feat: 十六进制编辑增加多选支持;修复程序单例问题;增加布局管理器;完善插件系统;

This commit is contained in:
寂静的羽夏 2024-12-14 19:12:38 +08:00
parent e47b96b563
commit 735298d850
38 changed files with 1865 additions and 778 deletions

View File

@ -1,15 +1,7 @@
#include "qhexcursor.h"
#include <QWidget>
void QHexCursor::setSelection(qsizetype offset, qsizetype length) {
auto lld = lldiv(offset, m_position.lineWidth);
m_position.line = lld.quot;
m_position.column = int(lld.rem);
moveTo(m_position);
lld = lldiv(offset + length - 1, m_position.lineWidth);
m_selection.line = lld.quot;
m_selection.column = int(lld.rem);
}
#include <QtConcurrent/QtConcurrentMap>
QHexCursor::QHexCursor(QObject *parent)
: QObject(parent), m_insertionmode(QHexCursor::OverwriteMode) {
@ -20,104 +12,168 @@ QHexCursor::QHexCursor(QObject *parent)
m_selection.line = m_selection.column = 0;
m_position.nibbleindex = m_selection.nibbleindex = 1;
setLineWidth(DEFAULT_HEX_LINE_LENGTH);
}
const QHexPosition &QHexCursor::selectionStart() const {
if (m_position.line < m_selection.line)
return m_position;
if (m_position.line == m_selection.line) {
if (m_position.column < m_selection.column)
return m_position;
}
return m_selection;
const QHexPosition &QHexCursor::selectionStart(qsizetype index) const {
return m_sels.at(index).start;
}
const QHexPosition &QHexCursor::selectionEnd() const {
if (m_position.line > m_selection.line)
return m_position;
if (m_position.line == m_selection.line) {
if (m_position.column > m_selection.column)
return m_position;
}
return m_selection;
const QHexPosition &QHexCursor::selectionEnd(qsizetype index) const {
return m_sels.at(index).end;
}
const QHexPosition &QHexCursor::position() const { return m_position; }
qsizetype QHexCursor::selectionCount() const { return m_sels.size(); }
const QHexSelection &QHexCursor::selection(qsizetype index) const {
return m_sels.at(index);
}
QHexCursor::InsertionMode QHexCursor::insertionMode() const {
return m_insertionmode;
}
qsizetype QHexCursor::selectionLength() const {
return this->selectionEnd() - this->selectionStart() + 1;
qsizetype QHexCursor::selectionLength(qsizetype index) const {
return m_sels.at(index).length();
}
qsizetype QHexCursor::currentLine() const { return m_position.line; }
int QHexCursor::currentColumn() const { return m_position.column; }
int QHexCursor::currentNibble() const { return m_position.nibbleindex; }
qsizetype QHexCursor::selectionLine() const { return m_selection.line; }
qsizetype QHexCursor::selectionColumn() const { return m_selection.column; }
int QHexCursor::selectionNibble() const { return m_selection.nibbleindex; }
qsizetype QHexCursor::currentSelectionLength() const {
if (hasPreviewSelection() && m_preMode != SelectionRemove) {
return qAbs(m_position - m_selection);
}
qsizetype len = 0;
auto res = QtConcurrent::blockingMappedReduced(
m_sels, &QHexSelection::length,
QOverload<
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
const qsizetype &
#else
QVector<qsizetype>::parameter_type
#endif
>::of(&QVector<qsizetype>::append));
for (auto &item : res) {
len += item;
}
return len;
}
qsizetype QHexCursor::currentLine() const { return m_selection.line; }
int QHexCursor::currentColumn() const { return m_selection.column; }
int QHexCursor::currentNibble() const { return m_selection.nibbleindex; }
bool QHexCursor::isLineSelected(qsizetype line) const {
if (!this->hasSelection())
return false;
auto first = std::min(m_position.line, m_selection.line);
auto last = std::max(m_position.line, m_selection.line);
if (isLineSelected(previewSelection(), line)) {
return true;
}
if ((line < first) || (line > last))
return false;
for (auto &sel : m_sels) {
if (isLineSelected(sel, line)) {
return true;
}
}
return true;
return false;
}
bool QHexCursor::hasSelection() const { return m_position != m_selection; }
bool QHexCursor::hasSelection() const {
return hasPreviewSelection() || hasInternalSelection();
}
void QHexCursor::clearSelection() {
bool QHexCursor::hasInternalSelection() const { return !m_sels.isEmpty(); }
void QHexCursor::clearPreviewSelection() {
m_selection = m_position;
emit positionChanged();
m_preMode = SelectionNormal;
}
void QHexCursor::moveTo(const QHexPosition &pos) {
this->moveTo(pos.line, pos.column, pos.nibbleindex);
void QHexCursor::clearSelection() { m_sels.clear(); }
void QHexCursor::moveTo(const QHexPosition &pos, bool clearSelection) {
this->moveTo(pos.line, pos.column, pos.nibbleindex, clearSelection);
}
void QHexCursor::select(const QHexPosition &pos) {
this->select(pos.line, pos.column, pos.nibbleindex);
void QHexCursor::select(const QHexPosition &pos,
QHexCursor::SelectionModes mode) {
this->select(pos.line, pos.column, pos.nibbleindex, mode);
}
void QHexCursor::moveTo(qsizetype line, int column, int nibbleindex) {
m_selection.line = line;
m_selection.column = column;
m_selection.nibbleindex = nibbleindex;
this->select(line, column, nibbleindex);
}
void QHexCursor::select(qsizetype line, int column, int nibbleindex) {
void QHexCursor::moveTo(qsizetype line, int column, int nibbleindex,
bool clearSelection) {
m_position.line = line;
m_position.column = qMax(0, column); // fix the bug by wingsummer
m_position.nibbleindex = nibbleindex;
m_selection = m_position;
if (clearSelection) {
m_sels.clear();
}
emit positionChanged();
}
void QHexCursor::moveTo(qsizetype offset) {
auto line = offset / m_lineWidth;
this->moveTo(line, int(offset - (line * m_lineWidth)));
void QHexCursor::select(qsizetype line, int column, int nibbleindex,
SelectionModes modes) {
if (modes.testFlag(SelectionPreview)) {
m_selection.line = line;
m_selection.column = qMax(0, column); // fix the bug by wingsummer
m_selection.nibbleindex = nibbleindex;
modes.setFlag(SelectionPreview, false);
m_preMode = SelectionMode(int(modes));
} else {
QHexSelection sel;
sel.start = m_position;
sel.end.line = line;
sel.end.column = column;
sel.end.nibbleindex = nibbleindex;
sel.normalize();
switch (modes) {
case SelectionAdd:
mergeAdd(sel);
break;
case SelectionNormal:
m_sels.clear();
m_sels.append(sel);
break;
case SelectionRemove:
mergeRemove(sel);
break;
}
}
emit positionChanged();
emit selectionChanged();
}
void QHexCursor::setPos(qsizetype offset, int nibbleindex) {
void QHexCursor::moveTo(qsizetype offset, bool clearSelection) {
auto line = offset / m_lineWidth;
this->moveTo(line, int(offset - (line * m_lineWidth)), nibbleindex);
this->moveTo(line, int(offset - (line * m_lineWidth)), clearSelection);
}
void QHexCursor::select(qsizetype length) {
this->select(
m_position.line,
std::min(m_lineWidth - 1, int(m_position.column + length - 1)));
void QHexCursor::setPos(qsizetype offset, int nibbleindex,
bool clearSelection) {
auto line = offset / m_lineWidth;
this->moveTo(line, int(offset - (line * m_lineWidth)), nibbleindex,
clearSelection);
}
void QHexCursor::select(qsizetype length, QHexCursor::SelectionModes mode) {
this->select(m_position.line,
std::min(m_lineWidth - 1, int(m_position.column + length - 1)),
1, mode);
}
void QHexCursor::selectOffset(qsizetype offset, qsizetype length) {
@ -137,6 +193,11 @@ void QHexCursor::setLineWidth(quint8 width) {
m_lineWidth = width;
m_position.lineWidth = width;
m_selection.lineWidth = width;
for (auto &sel : m_sels) {
sel.start.lineWidth = width;
sel.end.lineWidth = width;
}
}
void QHexCursor::switchInsertionMode() {
@ -147,3 +208,100 @@ void QHexCursor::switchInsertionMode() {
emit insertionModeChanged();
}
bool QHexCursor::hasPreviewSelection() const {
return m_selection != m_position;
}
void QHexCursor::mergeRemove(const QHexSelection &sel) {
Q_ASSERT(sel.isNormalized());
QList<QHexSelection> buffer;
QMutex locker;
QtConcurrent::blockingMap(m_sels,
[&buffer, &locker, &sel](QHexSelection &s) {
auto r = s.removeSelection(sel);
if (r.has_value()) {
QMutexLocker l(&locker);
buffer.append(r.value());
}
});
// clean up invalid selections
auto cleanup = [](const QHexSelection &s) { return s.start == s.end; };
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
m_sels.removeIf(cleanup);
#else
m_sels.erase(std::remove_if(m_sels.begin(), m_sels.end(), cleanup));
#endif
QtConcurrent::blockingMap(
buffer, [&locker, this](QHexSelection &s) { mergeAdd(s, &locker); });
}
void QHexCursor::mergeAdd(const QHexSelection &sel, QMutex *locker) {
bool merged = false;
Q_ASSERT(sel.isNormalized());
for (auto p = m_sels.begin(); p != m_sels.end(); ++p) {
merged = p->mergeSelection(sel, locker);
if (merged) {
break;
}
}
if (!merged) {
m_sels.append(sel);
}
}
bool QHexCursor::isLineSelected(const QHexSelection &sel,
qsizetype line) const {
auto first = std::min(sel.start.line, sel.end.line);
auto last = std::max(sel.start.line, sel.end.line);
if ((line >= first) && (line <= last))
return true;
return false;
}
QHexSelection QHexCursor::previewSelection() const {
QHexSelection sel;
sel.start = m_position;
sel.end = m_selection;
return sel;
}
void QHexCursor::setPreviewSelectionMode(SelectionMode mode) {
m_preMode = mode;
}
QHexCursor::SelectionMode QHexCursor::previewSelectionMode() const {
return m_preMode;
}
void QHexCursor::mergePreviewSelection() {
auto ss = QHexSelection{m_position, m_selection}.normalized();
switch (m_preMode) {
case SelectionNormal:
if (m_sels.isEmpty()) {
m_sels.append(ss);
}
break;
case SelectionAdd:
mergeAdd(ss);
break;
case SelectionRemove:
mergeRemove(ss);
break;
case SelectionSingle:
m_sels.clear();
m_sels.append(ss);
break;
case SelectionPreview:
// should not go here
break;
}
clearPreviewSelection();
}

View File

@ -1,23 +1,40 @@
#ifndef QHEXCURSOR_H
#define QHEXCURSOR_H
#include <QMutex>
#include <QObject>
#include <optional>
#define DEFAULT_HEX_LINE_LENGTH 0x10
#define DEFAULT_AREA_IDENTATION 0x01
struct QHexPosition {
qsizetype line;
int column;
quint8 lineWidth;
int nibbleindex;
qsizetype line = -1;
int column = -1;
quint8 lineWidth = 0;
int nibbleindex = -1;
QHexPosition() = default;
inline qsizetype offset() const {
return static_cast<qsizetype>(line * lineWidth) + column;
}
inline int operator-(const QHexPosition &rhs) const {
return int(this->offset() - rhs.offset());
inline qsizetype operator-(const QHexPosition &rhs) const {
return this->offset() - rhs.offset();
}
inline void operator++() {
this->column++;
if (this->column >= lineWidth) {
this->line++;
this->column = 0;
}
}
inline void operator--() {
this->column--;
if (this->column < 0) {
this->line--;
this->column = lineWidth - 1;
}
}
inline bool operator==(const QHexPosition &rhs) const {
return (line == rhs.line) && (column == rhs.column) &&
@ -27,6 +44,135 @@ struct QHexPosition {
return (line != rhs.line) || (column != rhs.column) ||
(nibbleindex != rhs.nibbleindex);
}
inline bool operator<(const QHexPosition &rhs) const {
return this->offset() < rhs.offset();
}
inline bool operator>(const QHexPosition &rhs) const {
return this->offset() > rhs.offset();
}
inline bool operator<=(const QHexPosition &rhs) const {
return this->offset() <= rhs.offset();
}
inline bool operator>=(const QHexPosition &rhs) const {
return this->offset() >= rhs.offset();
}
};
struct QHexSelection {
QHexPosition start;
QHexPosition end;
void normalize(QMutex *locker = nullptr) {
if (locker) {
locker->lock();
}
if (end < start) {
std::swap(start, end);
}
if (locker) {
locker->unlock();
}
}
qsizetype length() const { return qAbs(end - start) + 1; }
bool contains(const QHexSelection &sel) const {
Q_ASSERT(isNormalized());
return this->start <= sel.start && this->end >= sel.end;
}
bool isLineSelected(qsizetype line) const {
Q_ASSERT(isNormalized());
if (this->start.line == line || this->end.line == line) {
return true;
}
return this->start.line < line && line < this->end.line;
}
bool isNormalized() const { return end >= start; }
QHexSelection normalized() const {
QHexSelection sel = *this;
if (end < start) {
std::swap(sel.start, sel.end);
}
return sel;
}
bool isIntersected(const QHexSelection &sel) const {
Q_ASSERT(isNormalized());
return !(sel.end < this->start || sel.start > this->end);
}
void intersect(const QHexSelection &sel, QMutex *locker = nullptr) {
Q_ASSERT(isNormalized());
auto s = sel.normalized();
if (locker) {
locker->lock();
}
this->start = qMax(this->start, s.start);
this->end = qMin(this->end, s.end);
if (locker) {
locker->unlock();
}
}
Q_REQUIRED_RESULT std::optional<QHexSelection>
removeSelection(const QHexSelection &sel, QMutex *locker = nullptr) {
Q_ASSERT(isNormalized());
Q_ASSERT(sel.isNormalized());
if (locker) {
locker->lock();
}
if (sel.start <= this->start) {
if (sel.end >= this->start) {
if (sel.end < this->end) {
this->start = sel.end;
++this->start;
} else {
// makes it invalid, delete later
this->end = this->start;
}
}
} else if (sel.start > this->start && sel.start < this->end) {
this->end = sel.start;
--this->end;
if (sel.end < this->end) {
// break into two ranges
QHexSelection sel;
sel.start = sel.end;
sel.end = this->end;
if (locker) {
locker->unlock();
}
return sel;
}
}
if (locker) {
locker->unlock();
}
return {};
}
bool mergeSelection(const QHexSelection &sel, QMutex *locker = nullptr) {
Q_ASSERT(isNormalized());
if (isIntersected(sel)) {
if (locker) {
locker->lock();
}
this->start = qMin(this->start, sel.start);
this->end = qMax(this->end, sel.end);
if (locker) {
locker->unlock();
}
return true;
}
return false;
}
};
class QHexCursor : public QObject {
@ -35,50 +181,89 @@ class QHexCursor : public QObject {
public:
enum InsertionMode { OverwriteMode, InsertMode };
enum SelectionMode {
SelectionNormal = 0,
SelectionAdd = 1,
SelectionRemove = 2,
SelectionSingle = 4,
SelectionPreview = 16 // a flag
};
Q_DECLARE_FLAGS(SelectionModes, SelectionMode)
public:
explicit QHexCursor(QObject *parent = nullptr);
public:
const QHexPosition &selectionStart() const;
const QHexPosition &selectionEnd() const;
const QHexPosition &position() const;
void setSelection(qsizetype offset,
qsizetype length); // added by wingsummer
qsizetype selectionCount() const;
const QHexSelection &selection(qsizetype index) const;
const QHexPosition &selectionStart(qsizetype index) const;
const QHexPosition &selectionEnd(qsizetype index) const;
InsertionMode insertionMode() const;
qsizetype selectionLength() const;
qsizetype currentLine() const;
int currentColumn() const;
int currentNibble() const;
qsizetype selectionLine() const;
qsizetype selectionColumn() const;
int selectionNibble() const;
qsizetype selectionLength(qsizetype index) const;
qsizetype currentSelectionLength() const;
bool atEnd() const;
bool isLineSelected(qsizetype line) const;
bool hasSelection() const;
bool hasInternalSelection() const;
void clearPreviewSelection();
void clearSelection();
public:
void moveTo(const QHexPosition &pos);
void moveTo(qsizetype line, int column, int nibbleindex = 1);
void moveTo(qsizetype offset);
void setPos(qsizetype offset, int nibbleindex);
// 和 moveTo 其实一样,只是为了不冲突
void select(const QHexPosition &pos);
void select(qsizetype line, int column, int nibbleindex = 1);
void select(qsizetype length);
void moveTo(const QHexPosition &pos, bool clearSelection = false);
void moveTo(qsizetype line, int column, int nibbleindex = 1,
bool clearSelection = false);
void moveTo(qsizetype offset, bool clearSelection = false);
void setPos(qsizetype offset, int nibbleindex, bool clearSelection = false);
void select(const QHexPosition &pos,
QHexCursor::SelectionModes mode = SelectionNormal);
void select(qsizetype line, int column, int nibbleindex = 1,
QHexCursor::SelectionModes mode = SelectionNormal);
void select(qsizetype length,
QHexCursor::SelectionModes mode = SelectionNormal);
void selectOffset(qsizetype offset, qsizetype length);
void setInsertionMode(InsertionMode mode);
void setLineWidth(quint8 width);
void switchInsertionMode();
bool hasPreviewSelection() const;
QHexSelection previewSelection() const;
void setPreviewSelectionMode(SelectionMode mode);
SelectionMode previewSelectionMode() const;
void mergePreviewSelection();
private:
void mergeRemove(const QHexSelection &sel);
void mergeAdd(const QHexSelection &sel, QMutex *locker = nullptr);
bool isLineSelected(const QHexSelection &sel, qsizetype line) const;
signals:
void positionChanged();
void insertionModeChanged();
void selectionChanged();
private:
InsertionMode m_insertionmode;
quint8 m_lineWidth;
QHexPosition m_position, m_selection;
SelectionMode m_preMode;
QList<QHexSelection> m_sels;
};
#endif // QHEXCURSOR_H

View File

@ -476,6 +476,12 @@ void QHexDocument::redo() {
emit documentChanged();
}
void QHexDocument::beginMarco(const QString &text) {
m_undostack->beginMacro(text);
}
void QHexDocument::endMarco() { m_undostack->endMacro(); }
void QHexDocument::Insert(QHexCursor *cursor, qsizetype offset, uchar b,
int nibbleindex) {
if (m_keepsize || m_readonly || m_islocked)

View File

@ -104,6 +104,9 @@ public slots:
void undo();
void redo();
void beginMarco(const QString &text);
void endMarco();
void Insert(QHexCursor *cursor, qsizetype offset, uchar b, int nibbleindex);
void Insert(QHexCursor *cursor, qsizetype offset, const QByteArray &data,
int nibbleindex);

View File

@ -177,6 +177,10 @@ bool QHexMetadata::lineHasMetadata(qsizetype line) const {
qsizetype QHexMetadata::size() const { return m_metadata.size(); }
void QHexMetadata::beginMarco(const QString &text) { m_undo->beginMacro(text); }
void QHexMetadata::endMarco() { m_undo->endMacro(); }
void QHexMetadata::clear() {
m_linemeta.clear();
m_metadata.clear();

View File

@ -31,7 +31,8 @@ constexpr inline bool QNothrowHashable_v = QNothrowHashable<T>::value;
} // namespace QtPrivate
template <typename... T>
constexpr qhash_result_t qHashMulti(size_t seed, const T &...args) noexcept(
constexpr qhash_result_t
qHashMulti(qhash_result_t seed, const T &...args) noexcept(
std::conjunction_v<QtPrivate::QNothrowHashable<T>...>) {
QtPrivate::QHashCombine hash;
return ((seed = hash(seed, args)), ...), seed;
@ -85,6 +86,9 @@ public:
/*============================*/
// added by wingsummer
void beginMarco(const QString &text);
void endMarco();
void ModifyMetadata(QHexMetadataItem newmeta, QHexMetadataItem oldmeta);
void RemoveMetadatas(const QList<QHexMetadataItem> &items);
void RemoveMetadata(QHexMetadataItem item);

View File

@ -429,8 +429,31 @@ void QHexRenderer::applySelection(QTextCursor &textcursor, qsizetype line,
if (!m_cursor->isLineSelected(line))
return;
const QHexPosition &startsel = m_cursor->selectionStart();
const QHexPosition &endsel = m_cursor->selectionEnd();
auto total = m_cursor->selectionCount();
for (int i = 0; i < total; ++i) {
applySelection(m_cursor->selection(i), textcursor, line, factor, false,
false);
}
if (m_cursor->hasPreviewSelection()) {
applySelection(
m_cursor->previewSelection().normalized(), textcursor, line, factor,
m_cursor->previewSelectionMode() == QHexCursor::SelectionRemove,
m_cursor->previewSelectionMode() == QHexCursor::SelectionNormal &&
m_cursor->hasInternalSelection());
}
}
void QHexRenderer::applySelection(const QHexSelection &selection,
QTextCursor &textcursor, qsizetype line,
Factor factor, bool strikeOut,
bool hasSelection) const {
if (!selection.isLineSelected(line)) {
return;
}
const QHexPosition &startsel = selection.start;
const QHexPosition &endsel = selection.end;
if (startsel.line == endsel.line) {
textcursor.setPosition(startsel.column * factor);
@ -455,8 +478,13 @@ void QHexRenderer::applySelection(QTextCursor &textcursor, qsizetype line,
textcursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1);
QTextCharFormat charformat;
charformat.setBackground(m_selBackgroundColor);
charformat.setForeground(m_selectionColor);
charformat.setBackground(strikeOut || hasSelection
? m_selBackgroundColor.darker()
: m_selBackgroundColor);
charformat.setForeground(strikeOut ? m_selectionColor.darker()
: m_selectionColor);
charformat.setFontStrikeOut(strikeOut);
charformat.setFontItalic(strikeOut);
textcursor.mergeCharFormat(charformat);
}
@ -543,7 +571,7 @@ void QHexRenderer::drawHex(QPainter *painter, const QRect &linerect,
textcursor.insertText(this->hexString(line, &rawline));
if (line == this->documentLastLine())
textcursor.insertText(" ");
textcursor.insertText(QStringLiteral(" "));
QRect hexrect = linerect;
hexrect.setX(this->getHexColumnX() + this->borderSize());

View File

@ -120,8 +120,13 @@ private:
Factor factor) const;
void applyMetadata(QTextCursor &textcursor, qsizetype line,
Factor factor) const;
void applySelection(QTextCursor &textcursor, qsizetype line,
Factor factor) const;
void applySelection(const QHexSelection &selection, QTextCursor &textcursor,
qsizetype line, Factor factor, bool strikeOut,
bool hasSelection) const;
void applyBookMark(QTextCursor &textcursor, qsizetype line,
Factor factor); // added by wingsummer
void applyCursorAscii(QTextCursor &textcursor, qsizetype line) const;

View File

@ -44,7 +44,13 @@ qsizetype QHexView::currentRow() { return m_cursor->currentLine(); }
qsizetype QHexView::currentColumn() { return m_cursor->currentColumn(); }
qsizetype QHexView::currentOffset() { return m_cursor->position().offset(); }
qsizetype QHexView::selectlength() { return m_cursor->selectionLength(); }
qsizetype QHexView::currentSelectionLength() {
return m_cursor->currentSelectionLength();
}
qsizetype QHexView::selectionCount() { return m_cursor->selectionCount(); }
bool QHexView::hasSelection() { return m_cursor->hasSelection(); }
bool QHexView::asciiVisible() { return m_renderer->stringVisible(); }
@ -100,13 +106,15 @@ void QHexView::getStatus() {
}
void QHexView::establishSignal(QHexDocument *doc) {
connect(doc, &QHexDocument::documentChanged, this, [&]() {
connect(doc, &QHexDocument::documentChanged, this, [this]() {
this->adjustScrollBars();
this->viewport()->update();
});
connect(m_cursor, &QHexCursor::positionChanged, this,
&QHexView::moveToSelection);
connect(m_cursor, &QHexCursor::selectionChanged, this,
[this]() { this->viewport()->update(); });
connect(m_cursor, &QHexCursor::insertionModeChanged, this,
&QHexView::renderCurrentLine);
connect(doc, &QHexDocument::canUndoChanged, this,
@ -283,9 +291,6 @@ qsizetype QHexView::searchBackward(qsizetype begin, const QByteArray &ba) {
qsizetype startPos;
if (begin < 0) {
startPos = m_cursor->position().offset() - 1;
if (m_cursor->hasSelection()) {
startPos = m_cursor->selectionStart().offset() - 1;
}
} else {
startPos = begin;
}
@ -296,10 +301,17 @@ bool QHexView::RemoveSelection(int nibbleindex) {
if (!m_cursor->hasSelection())
return false;
auto res = m_document->Remove(m_cursor, m_cursor->selectionStart().offset(),
m_cursor->selectionLength(), nibbleindex);
if (res)
m_cursor->clearSelection();
auto total = m_cursor->selectionCount();
bool res = true;
m_document->beginMarco(QStringLiteral(""));
for (int i = 0; i < total; ++i) {
res &=
m_document->Remove(m_cursor, m_cursor->selectionStart(i).offset(),
m_cursor->selectionLength(i), nibbleindex);
}
m_document->endMarco();
m_cursor->clearSelection();
return res;
}
@ -307,10 +319,16 @@ bool QHexView::removeSelection() {
if (!m_cursor->hasSelection())
return false;
auto res = m_document->remove(m_cursor->selectionStart().offset(),
m_cursor->selectionLength());
if (res)
m_cursor->clearSelection();
// We essure selections are ordered by desending
// by selection-start, so it's safe to remove
auto total = m_cursor->selectionCount();
bool res = true;
for (int i = 0; i < total; ++i) {
res &= m_document->remove(m_cursor->selectionStart(i).offset(),
m_cursor->selectionLength(i));
}
m_cursor->clearSelection();
return res;
}
@ -318,12 +336,27 @@ bool QHexView::atEnd() const {
return m_cursor->position().offset() >= m_document->length();
}
QByteArray QHexView::selectedBytes() const {
if (!m_cursor->hasSelection())
return QByteArray();
QByteArray QHexView::selectedBytes(qsizetype index) const {
return m_document->read(m_cursor->selectionStart(index).offset(),
m_cursor->currentSelectionLength());
}
return m_document->read(m_cursor->selectionStart().offset(),
m_cursor->selectionLength());
QByteArray QHexView::previewSelectedBytes() const {
auto sel = m_cursor->previewSelection().normalized();
return m_document->read(sel.start.offset(), sel.length());
}
QByteArrayList QHexView::selectedBytes() const {
if (!m_cursor->hasSelection())
return {};
QByteArrayList res;
auto total = m_cursor->selectionCount();
for (int i = 0; i < total; ++i) {
res << m_document->read(m_cursor->selectionStart(i).offset(),
m_cursor->selectionLength(i));
}
return res;
}
void QHexView::paste(bool hex) {
@ -412,7 +445,7 @@ bool QHexView::copy(bool hex) {
QClipboard *c = qApp->clipboard();
auto len = m_cursor->selectionLength();
auto len = currentSelectionLength();
// 如果拷贝字节超过 ? MB 阻止
if (len > 1024 * 1024 * m_copylimit) {
@ -420,7 +453,7 @@ bool QHexView::copy(bool hex) {
return false;
}
QByteArray bytes = this->selectedBytes();
QByteArray bytes = this->selectedBytes().join();
if (hex)
bytes = bytes.toHex(' ').toUpper();
@ -521,8 +554,18 @@ void QHexView::mousePressEvent(QMouseEvent *e) {
m_renderer->selectArea(abspos);
if (m_renderer->editableArea(m_renderer->selectedArea()))
m_cursor->moveTo(position);
if (m_renderer->editableArea(m_renderer->selectedArea())) {
auto m = getSelectionMode();
bool clearSelection = false;
if (m == QHexCursor::SelectionNormal) {
clearSelection = m_cursor->selectionCount() <= 1 ||
e->modifiers().testFlag(Qt::ControlModifier);
} else if (m == QHexCursor::SelectionSingle) {
clearSelection = true;
}
m_cursor->moveTo(position, clearSelection);
}
e->accept();
}
@ -546,7 +589,9 @@ void QHexView::mouseMoveEvent(QMouseEvent *e) {
if (!m_renderer->hitTest(abspos, &position, this->firstVisibleLine()))
return;
cursor->select(position.line, position.column, 0);
cursor->select(position.line, position.column, 0,
QHexCursor::SelectionModes(
getSelectionMode() | QHexCursor::SelectionPreview));
e->accept();
}
@ -567,6 +612,13 @@ void QHexView::mouseReleaseEvent(QMouseEvent *e) {
return;
if (!m_blinktimer->isActive())
m_blinktimer->start();
if (m_cursor->hasPreviewSelection()) {
auto sel = m_cursor->previewSelection();
m_cursor->mergePreviewSelection();
m_cursor->moveTo(sel.end);
}
e->accept();
}
@ -706,7 +758,7 @@ void QHexView::moveNext(bool select) {
if (select)
cur->select(line, std::min(m_renderer->hexLineWidth() - 1, int(column)),
nibbleindex);
nibbleindex, QHexCursor::SelectionAdd);
else
cur->moveTo(line, std::min(m_renderer->hexLineWidth() - 1, int(column)),
nibbleindex);
@ -749,6 +801,34 @@ void QHexView::movePrevious(bool select) {
cur->moveTo(line, std::max(0, column), nibbleindex);
}
QHexCursor::SelectionMode QHexView::getSelectionMode() const {
auto mods = qApp->keyboardModifiers();
bool pressedShift = mods.testFlag(Qt::ShiftModifier);
bool pressedAlt = mods.testFlag(Qt::AltModifier);
bool pressedControl = mods.testFlag(Qt::ControlModifier);
if (pressedAlt && pressedShift) {
pressedShift = false;
pressedAlt = false;
pressedControl = true;
}
if (pressedControl) {
return QHexCursor::SelectionSingle;
}
if (pressedShift) {
return QHexCursor::SelectionAdd;
}
if (pressedAlt) {
return QHexCursor::SelectionRemove;
}
return QHexCursor::SelectionNormal;
}
void QHexView::renderCurrentLine() {
if (m_document)
this->renderLine(m_cursor->currentLine());
@ -896,7 +976,7 @@ bool QHexView::processMove(QHexCursor *cur, QKeyEvent *e) {
if (e->matches(QKeySequence::MoveToEndOfDocument))
cur->moveTo(m_renderer->documentLastLine(),
m_renderer->documentLastColumn());
int(m_renderer->documentLastColumn()));
else
cur->select(m_renderer->documentLastLine(),
m_renderer->documentLastColumn());
@ -911,7 +991,7 @@ bool QHexView::processMove(QHexCursor *cur, QKeyEvent *e) {
if (e->matches(QKeySequence::MoveToEndOfLine)) {
if (cur->currentLine() == m_renderer->documentLastLine())
cur->moveTo(cur->currentLine(),
m_renderer->documentLastColumn());
int(m_renderer->documentLastColumn()));
else
cur->moveTo(cur->currentLine(), m_renderer->hexLineWidth() - 1,
0);

View File

@ -51,7 +51,10 @@ public:
qsizetype currentRow();
qsizetype currentColumn();
qsizetype currentOffset();
qsizetype selectlength();
qsizetype currentSelectionLength();
qsizetype selectionCount();
bool hasSelection();
void setAsciiVisible(bool b);
bool asciiVisible();
@ -101,7 +104,9 @@ public:
bool removeSelection();
bool atEnd() const;
QByteArray selectedBytes() const;
QByteArray selectedBytes(qsizetype index) const;
QByteArray previewSelectedBytes() const;
QByteArrayList selectedBytes() const;
bool cut(bool hex);
bool copy(bool hex = false);
@ -168,6 +173,8 @@ private:
void moveNext(bool select = false);
void movePrevious(bool select = false);
QHexCursor::SelectionMode getSelectionMode() const;
private:
bool processMove(QHexCursor *cur, QKeyEvent *e);
bool processTextInput(QHexCursor *cur, QKeyEvent *e);

View File

@ -247,7 +247,9 @@ set(CLASS_SRC
src/class/clangformatmanager.h
src/class/clangformatmanager.cpp
src/class/aspreprocesser.h
src/class/aspreprocesser.cpp)
src/class/aspreprocesser.cpp
src/class/layoutmanager.h
src/class/layoutmanager.cpp)
if(WINGHEX_USE_FRAMELESS)
set(WIDGET_FRAME_SRC

View File

@ -1,36 +0,0 @@
# TestPlugin
## How to Build
Create a build directory and run
cmake -DCMAKE_PREFIX_PATH=<path_to_qtcreator> -DCMAKE_BUILD_TYPE=RelWithDebInfo <path_to_plugin_source>
cmake --build .
where `<path_to_qtcreator>` is the relative or absolute path to a Qt Creator build directory, or to a
combined binary and development package (Windows / Linux), or to the `Qt Creator.app/Contents/Resources/`
directory of a combined binary and development package (macOS), and `<path_to_plugin_source>` is the
relative or absolute path to this plugin directory.
## How to Run
Run a compatible Qt Creator with the additional command line argument
-pluginpath <path_to_plugin>
where `<path_to_plugin>` is the path to the resulting plugin library in the build directory
(`<plugin_build>/lib/qtcreator/plugins` on Windows and Linux,
`<plugin_build>/Qt Creator.app/Contents/PlugIns` on macOS).
You might want to add `-temporarycleansettings` (or `-tcs`) to ensure that the opened Qt Creator
instance cannot mess with your user-global Qt Creator settings.
When building and running the plugin from Qt Creator, you can use
-pluginpath "%{buildDir}/lib/qtcreator/plugins" -tcs
on Windows and Linux, or
-pluginpath "%{buildDir}/Qt Creator.app/Contents/PlugIns" -tcs
for the `Command line arguments` field in the run settings.

View File

@ -14,37 +14,75 @@
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="35"/>
<location filename="../testform.ui" line="36"/>
<source>Log</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="77"/>
<source>Level</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="87"/>
<location filename="../testform.ui" line="180"/>
<source>Text</source>
<translation> </translation>
</message>
<message>
<location filename="../testform.ui" line="110"/>
<location filename="../testform.ui" line="203"/>
<source>Send</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="117"/>
<location filename="../testform.ui" line="210"/>
<source>Clear</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="129"/>
<source>Toast</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="170"/>
<source>Icon</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="236"/>
<source>Reader</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="40"/>
<location filename="../testform.ui" line="241"/>
<source>Controller</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="45"/>
<location filename="../testform.ui" line="246"/>
<source>MessageBox</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="50"/>
<location filename="../testform.ui" line="251"/>
<source>InputBox</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="55"/>
<location filename="../testform.ui" line="256"/>
<source>FileDialog</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="60"/>
<location filename="../testform.ui" line="261"/>
<source>ColorDialog</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="65"/>
<location filename="../testform.ui" line="266"/>
<source>DataVisual</source>
<translation></translation>
</message>
@ -57,13 +95,25 @@
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="66"/>
<location filename="../testplugin.cpp" line="79"/>
<location filename="../testplugin.cpp" line="68"/>
<location filename="../testplugin.cpp" line="77"/>
<location filename="../testplugin.cpp" line="82"/>
<location filename="../testplugin.cpp" line="110"/>
<source>TestPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="86"/>
<source>Button - </source>
<translation> - </translation>
</message>
<message>
<location filename="../testplugin.cpp" line="90"/>
<source>Click</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="117"/>
<source>A Test Plugin for WingHexExplorer2.</source>
<translation>2</translation>
</message>

View File

@ -21,8 +21,57 @@
#include "testform.h"
#include "ui_testform.h"
TestForm::TestForm(QWidget *parent) : QWidget(parent), ui(new Ui::TestForm) {
#include <QMetaEnum>
TestForm::TestForm(WingHex::IWingPlugin *plg, QWidget *parent)
: QWidget(parent), ui(new Ui::TestForm), _plg(plg) {
ui->setupUi(this);
initLogCombo();
initStyleCombo();
}
TestForm::~TestForm() { delete ui; }
void TestForm::initLogCombo() {
auto e = QMetaEnum::fromType<Level>();
for (int i = LEVEL_BEGIN; i < LEVEL_END; ++i) {
ui->cbLogLevel->addItem(e.key(i));
}
}
void TestForm::initStyleCombo() {
auto style = this->style();
auto e = QMetaEnum::fromType<QStyle::StandardPixmap>();
for (int i = 0; i < QStyle::StandardPixmap::NStandardPixmap; ++i) {
auto icon = style->standardIcon(QStyle::StandardPixmap(i));
if (!icon.isNull()) {
ui->cbToastIcon->addItem(icon, e.key(i));
}
}
}
void TestForm::on_btnSendLog_clicked() {
auto txt = ui->leLogText->text();
switch (Level(ui->cbLogLevel->currentIndex())) {
case q1ERROR:
emit _plg->error(txt);
break;
case q2WARN:
emit _plg->warn(txt);
break;
case q3INFO:
emit _plg->info(txt);
break;
case q4DEBUG:
emit _plg->debug(txt);
break;
case q5TRACE:
emit _plg->trace(txt);
break;
default:
break;
}
}
void TestForm::on_btnSendToast_clicked() {}

View File

@ -21,6 +21,8 @@
#ifndef TESTFORM_H
#define TESTFORM_H
#include "iwingplugin.h"
#include <QWidget>
namespace Ui {
@ -31,11 +33,37 @@ class TestForm : public QWidget {
Q_OBJECT
public:
explicit TestForm(QWidget *parent = nullptr);
// copy from LogError
enum Level : int {
q1ERROR,
q2WARN,
q3INFO,
q4DEBUG,
q5TRACE,
LEVEL_BEGIN = q1ERROR,
LEVEL_LAST = q5TRACE,
LEVEL_END = LEVEL_LAST + 1
};
Q_ENUM(Level)
public:
explicit TestForm(WingHex::IWingPlugin *plg, QWidget *parent = nullptr);
~TestForm();
private slots:
void on_btnSendLog_clicked();
void on_btnSendToast_clicked();
private:
void initLogCombo();
void initStyleCombo();
private:
Ui::TestForm *ui;
WingHex::IWingPlugin *_plg;
};
#endif // TESTFORM_H

View File

@ -29,6 +29,207 @@
<attribute name="title">
<string>Basic</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Log</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>8</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="horizontalSpacing">
<number>8</number>
</property>
<property name="verticalSpacing">
<number>8</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Level</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cbLogLevel"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Text</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leLogText"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="btnSendLog">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnClearSend">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Toast</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>8</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout_3">
<property name="horizontalSpacing">
<number>8</number>
</property>
<property name="verticalSpacing">
<number>8</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Icon</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cbToastIcon"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Text</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leToastText"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="btnSendToast">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnClearText">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
@ -70,5 +271,38 @@
</layout>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>btnClearSend</sender>
<signal>clicked()</signal>
<receiver>leLogText</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>371</x>
<y>122</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>100</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnClearText</sender>
<signal>clicked()</signal>
<receiver>leToastText</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>461</x>
<y>249</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>229</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -36,13 +36,13 @@ int TestPlugin::sdkVersion() const { return WingHex::SDKVERSION; }
const QString TestPlugin::signature() const { return WingHex::WINGSUMMER; }
bool TestPlugin::init(const QSettings &set) {
auto v = set.value("Test", 0).toInt();
bool TestPlugin::init(const std::unique_ptr<QSettings> &set) {
auto v = set->value("Test", 0).toInt();
// 如果你之前启动过且正常推出,这个值一定是 5
qDebug() << v;
// 和日志与 UI 相关的接口此时可用,剩余的 API 初始化成功才可用
_tform = emit createDialog(new TestForm);
_tform = emit createDialog(new TestForm(this));
using TBInfo = WingHex::WingRibbonToolBoxInfo;
TBInfo::RibbonCatagories cats;
@ -60,17 +60,48 @@ bool TestPlugin::init(const QSettings &set) {
_tform->raise();
}
});
_rtbinfo = {WingHex::WingRibbonToolBoxInfo{
.catagory = cats.PLUGIN,
.toolboxs = {
TBInfo::Toolbox{.name = tr("TestPlugin"), .tools = {tb}}}}};
{
WingHex::WingRibbonToolBoxInfo rtinfo;
rtinfo.catagory = cats.PLUGIN;
TBInfo::Toolbox tbtb;
tbtb.name = tr("TestPlugin");
tbtb.tools = {tb};
rtinfo.toolboxs = {tbtb};
_rtbinfo.append(rtinfo);
}
{
WingHex::WingRibbonToolBoxInfo rtinfo;
rtinfo.catagory = QStringLiteral("TestPlugin");
rtinfo.displayName = tr("TestPlugin");
QIcon btnIcon(QStringLiteral(":/images/TestPlugin/images/btn.png"));
for (int i = 0; i < 3; ++i) {
TBInfo::Toolbox tbtb;
tbtb.name = tr("TestPlugin") + QStringLiteral("(%1)").arg(i);
for (int y = 0; y < 5; ++y) {
auto tb = new QToolButton;
tb->setIcon(btnIcon);
tb->setText(tr("Button - ") +
QStringLiteral("(%1, %2)").arg(i).arg(y));
connect(tb, &QToolButton::clicked, this, [this] {
auto tb = qobject_cast<QToolButton *>(sender());
emit msgbox.information(nullptr, tr("Click"), tb->text());
});
tbtb.tools.append(tb);
}
rtinfo.toolboxs.append(tbtb);
}
_rtbinfo.append(rtinfo);
}
return true;
}
void TestPlugin::unload(QSettings &set) {
void TestPlugin::unload(std::unique_ptr<QSettings> &set) {
// 设个数字,那就是 5 测试一下配置是否正常工作
set.setValue("Test", 5);
set->setValue("Test", 5);
_tform->close();
_tform->deleteLater();

View File

@ -45,8 +45,8 @@ public:
public:
virtual int sdkVersion() const override;
virtual const QString signature() const override;
virtual bool init(const QSettings &set) override;
virtual void unload(QSettings &set) override;
virtual bool init(const std::unique_ptr<QSettings> &set) override;
virtual void unload(std::unique_ptr<QSettings> &set) override;
virtual const QString pluginName() const override;
virtual const QString pluginAuthor() const override;
virtual uint pluginVersion() const override;

BIN
images/layoutexport.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,11 @@ int main(int argc, char *argv[]) {
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
QGuiApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QApplication::setApplicationName(APP_NAME);
QApplication::setOrganizationName(APP_ORG);
QApplication::setApplicationVersion(WINGHEX_VERSION);
try {
AppManager a(argc, argv);

View File

@ -257,6 +257,9 @@ Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChang
else:
pak_out = args.output
if len(args.cc) == 0:
exit(0)
ret = run_command_interactive([args.cc, f'/O{pak_out}', script_src])
exit(ret)

View File

@ -41,6 +41,7 @@
<file>images/info.png</file>
<file>images/jmp.png</file>
<file>images/layout.png</file>
<file>images/layoutexport.png</file>
<file>images/lock.png</file>
<file>images/log.png</file>
<file>images/mAddr.png</file>

View File

@ -27,11 +27,13 @@
#define QPTR_WRAP(decl) "uint " decl
#define QPTR "uint"
#define QSIZETYPE "int"
#define QUSIZETYPE "uint"
#elif Q_PROCESSOR_WORDSIZE == 8
#define QSIZETYPE_WRAP(decl) "int64 " decl
#define QPTR_WRAP(decl) "uint64 " decl
#define QPTR "uint64"
#define QSIZETYPE "int64"
#define QUSIZETYPE "uint64"
#else
#error "Processor with unexpected word size"
#endif

View File

@ -22,6 +22,7 @@
#include "angelscript.h"
#include "clangformatmanager.h"
#include "dbghelper.h"
#include "define.h"
#include "dialog/mainwindow.h"
#include "dialog/splashdialog.h"
#include "languagemanager.h"
@ -37,10 +38,6 @@ AppManager::AppManager(int &argc, char *argv[])
: SingleApplication(argc, argv, true) {
ASSERT_SINGLETON;
setApplicationName(APP_NAME);
setOrganizationName(APP_ORG);
setApplicationVersion(WINGHEX_VERSION);
auto args = arguments();
if (isSecondary()) {
QByteArray buffer;
@ -51,6 +48,7 @@ AppManager::AppManager(int &argc, char *argv[])
}
}
sendMessage(buffer);
throw CrashCode::AlreadyStart;
}
#ifndef ANGELSCRIPT_H
@ -64,7 +62,7 @@ AppManager::AppManager(int &argc, char *argv[])
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) {
WingMessageBox::critical(nullptr, qAppName(),
tr("GenericCallNotFullySupported"));
exit(-1);
throw CrashCode::GenericCallNotSupported;
}
Logger::instance();
@ -93,19 +91,28 @@ AppManager::AppManager(int &argc, char *argv[])
return;
}
_w->show();
_w->raise();
_w->activateWindow();
_w->raise();
});
connect(this, &SingleApplication::receivedMessage, this,
[this](quint32 instanceId, QByteArray message) {
Q_UNUSED(instanceId);
QDataStream out(&message, QIODevice::WriteOnly);
Q_ASSERT(_w);
if (!_w->isEnabled()) {
return;
}
QDataStream out(&message, QIODevice::ReadOnly);
while (!out.atEnd()) {
QString param;
out >> param;
openFile(param);
}
_w->show();
_w->activateWindow();
_w->raise();
});
if (splash)

View File

@ -0,0 +1,84 @@
/*==============================================================================
** 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 "layoutmanager.h"
#include "dbghelper.h"
#include "languagemanager.h"
#include "utilities.h"
LayoutManager &LayoutManager::instance() {
static LayoutManager ins;
return ins;
}
const QHash<QString, QByteArray> LayoutManager::layouts() const {
return _layouts;
}
QByteArray LayoutManager::layout(const QString &v) const {
return _layouts.value(v);
}
qsizetype LayoutManager::layoutCount() const { return _layouts.size(); }
LayoutManager::LayoutManager() {
ASSERT_SINGLETON;
QDir pdir(Utilities::getAppDataPath());
auto lname = QStringLiteral("layouts");
if (!pdir.exists(lname)) {
pdir.mkdir(lname);
return;
}
if (!pdir.cd(lname)) {
return;
}
// read translation names
auto trf = QStringLiteral("metatr.ini");
if (pdir.exists(trf)) {
process(pdir, std::make_unique<QSettings>(pdir.absoluteFilePath(trf),
QSettings::IniFormat));
} else {
process(pdir, nullptr);
}
}
void LayoutManager::process(const QDir &dir,
const std::unique_ptr<QSettings> &set) {
auto name = LanguageManager::instance().defaultLocale().name();
auto sep = QStringLiteral("/");
for (auto &l : dir.entryInfoList({"*.wing-layout"}, QDir::Files)) {
QString k;
if (set) {
k = set->value(name + sep + l.baseName()).toString();
}
if (k.isEmpty()) {
k = l.baseName();
}
QFile f(l.absoluteFilePath());
if (f.open(QFile::ReadOnly)) {
auto b = f.readAll();
if (!b.isEmpty()) {
_layouts.insert(k.trimmed(), b);
}
}
}
}

50
src/class/layoutmanager.h Normal file
View File

@ -0,0 +1,50 @@
/*==============================================================================
** 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 LAYOUTMANAGER_H
#define LAYOUTMANAGER_H
#include <QDir>
#include <QHash>
#include <QSettings>
#include <QString>
#include <memory>
class LayoutManager {
public:
static LayoutManager &instance();
public:
const QHash<QString, QByteArray> layouts() const;
QByteArray layout(const QString &v) const;
qsizetype layoutCount() const;
private:
LayoutManager();
void process(const QDir &dir, const std::unique_ptr<QSettings> &set);
private:
QHash<QString, QByteArray> _layouts;
Q_DISABLE_COPY_MOVE(LayoutManager)
};
#endif // LAYOUTMANAGER_H

View File

@ -55,12 +55,12 @@ int WingAngelAPI::sdkVersion() const { return WingHex::SDKVERSION; }
const QString WingAngelAPI::signature() const { return WingHex::WINGSUMMER; }
bool WingAngelAPI::init(const QSettings &set) {
bool WingAngelAPI::init(const std::unique_ptr<QSettings> &set) {
Q_UNUSED(set);
return true;
}
void WingAngelAPI::unload(QSettings &set) {
void WingAngelAPI::unload(std::unique_ptr<QSettings> &set) {
Q_UNUSED(set);
this->disconnect();
}
@ -383,6 +383,7 @@ void WingAngelAPI::installColorDialogAPI(asIScriptEngine *engine) {
void WingAngelAPI::installHexBaseType(asIScriptEngine *engine) {
registerAngelType<WingHex::ErrFile>(engine, "ErrFile");
registerAngelType<WingHex::SelectionMode>(engine, "SelectionMode");
int r = engine->RegisterTypedef("byte", "uint8");
Q_ASSERT(r >= 0);
@ -408,23 +409,6 @@ void WingAngelAPI::installHexBaseType(asIScriptEngine *engine) {
Q_ASSERT(r >= 0);
Q_UNUSED(r);
// BookMark
r = engine->RegisterObjectType("BookMark", sizeof(WingHex::BookMark),
asOBJ_VALUE | asOBJ_POD |
asGetTypeTraits<WingHex::BookMark>());
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty("BookMark", QSIZETYPE_WRAP("pos"),
asOFFSET(WingHex::BookMark, pos));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty("BookMark", "string comment",
asOFFSET(WingHex::BookMark, comment));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
// HexPosition
r = engine->RegisterObjectType("HexPosition", sizeof(WingHex::HexPosition),
asOBJ_VALUE | asOBJ_POD |
@ -474,42 +458,6 @@ void WingAngelAPI::installHexBaseType(asIScriptEngine *engine) {
asCALL_THISCALL);
Q_ASSERT(r >= 0);
Q_UNUSED(r);
// HexMetadataItem
r = engine->RegisterObjectType(
"HexMetadataItem", sizeof(WingHex::HexMetadataItem),
asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<WingHex::HexMetadataItem>());
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty(
"HexMetadataItem", QSIZETYPE_WRAP("begin"),
asOFFSET(WingHex::HexMetadataItem, begin));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty("HexMetadataItem", QSIZETYPE_WRAP("end"),
asOFFSET(WingHex::HexMetadataItem, end));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty(
"HexMetadataItem", "color foreground",
asOFFSET(WingHex::HexMetadataItem, foreground));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty(
"HexMetadataItem", "color background",
asOFFSET(WingHex::HexMetadataItem, background));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
r = engine->RegisterObjectProperty(
"HexMetadataItem", "string comment",
asOFFSET(WingHex::HexMetadataItem, comment));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
}
void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
@ -544,10 +492,6 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
engine, std::bind(&WingHex::WingPlugin::Reader::currentPos, reader),
"HexPosition currentPos()");
registerAPI<WingHex::HexPosition(void)>(
engine, std::bind(&WingHex::WingPlugin::Reader::selectionPos, reader),
"HexPosition selectionPos()");
registerAPI<bool(void)>(
engine, std::bind(&WingHex::WingPlugin::Reader::stringVisible, reader),
"bool stringVisible()");
@ -609,9 +553,34 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
engine, std::bind(&WingHex::WingPlugin::Reader::selectedLength, reader),
QSIZETYPE_WRAP("selectedLength()"));
registerAPI<CScriptArray *(void)>(
engine, std::bind(&WingAngelAPI::_HexReader_selectedBytes, this),
"array<byte>@ selectedBytes()");
registerAPI<CScriptArray *(qsizetype)>(
engine,
std::bind(&WingAngelAPI::_HexReader_selectedBytes, this,
std::placeholders::_1),
"array<byte>@ selectedBytes(" QSIZETYPE " index)");
registerAPI<CScriptArray *()>(
engine, std::bind(&WingAngelAPI::_HexReader_selectionBytes, this),
"array<array<byte>>@ selectionBytes()");
registerAPI<WingHex::HexPosition(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::selectionStart, reader,
std::placeholders::_1),
"HexPosition selectionStart(" QSIZETYPE " index)");
registerAPI<WingHex::HexPosition(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::selectionEnd, reader,
std::placeholders::_1),
"HexPosition selectionEnd(" QSIZETYPE " index)");
registerAPI<qsizetype(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::selectionLength, reader,
std::placeholders::_1),
QSIZETYPE_WRAP("selectionLength(" QSIZETYPE " index)"));
registerAPI<qsizetype()>(
engine, std::bind(&WingHex::WingPlugin::Reader::selectionCount, reader),
QSIZETYPE_WRAP("selectionCount()"));
registerAPI<quintptr(void)>(
engine, std::bind(&WingHex::WingPlugin::Reader::addressBase, reader),
@ -709,12 +678,6 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
std::placeholders::_1),
"bool lineHasMetadata(" QSIZETYPE " line)");
registerAPI<CScriptArray *(qsizetype)>(
engine,
std::bind(&WingAngelAPI::_HexReader_getMetadatas, this,
std::placeholders::_1),
"array<HexMetadataItem>@ getMetadatas(" QSIZETYPE " offset)");
registerAPI<bool(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::lineHasBookMark, reader,
@ -727,22 +690,12 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
std::placeholders::_1),
"array<" QSIZETYPE ">@ getsBookmarkPos(" QSIZETYPE " pos)");
registerAPI<WingHex::BookMark(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::bookMark, reader,
std::placeholders::_1),
"BookMark bookMark(" QSIZETYPE " pos)");
registerAPI<QString(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::bookMarkComment, reader,
std::placeholders::_1),
"string bookMarkComment(" QSIZETYPE " pos)");
registerAPI<CScriptArray *()>(
engine, std::bind(&WingAngelAPI::_HexReader_getBookMarks, this),
"array<BookMark>@ getBookMarks()");
registerAPI<bool(qsizetype)>(
engine,
std::bind(&WingHex::WingPlugin::Reader::existBookMark, reader,
@ -1005,27 +958,29 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
engine, std::bind(&WingHex::WingPlugin::Controller::removeAll, ctl),
"bool removeAll()");
registerAPI<bool(qsizetype, qsizetype, int)>(
registerAPI<bool(qsizetype, qsizetype, int, bool)>(
engine,
std::bind(QOverload<qsizetype, qsizetype, int>::of(
std::bind(QOverload<qsizetype, qsizetype, int, bool>::of(
&WingHex::WingPlugin::Controller::moveTo),
ctl, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
std::placeholders::_3, std::placeholders::_4),
"bool moveTo(" QSIZETYPE " line, " QSIZETYPE
" column, int nibbleindex = -1)");
" column, int nibbleindex = -1, bool clearSelection = true)");
registerAPI<bool(qsizetype)>(
registerAPI<bool(qsizetype, bool)>(
engine,
std::bind(
QOverload<qsizetype>::of(&WingHex::WingPlugin::Controller::moveTo),
ctl, std::placeholders::_1),
"bool moveTo(" QSIZETYPE " offset)");
std::bind(QOverload<qsizetype, bool>::of(
&WingHex::WingPlugin::Controller::moveTo),
ctl, std::placeholders::_1, std::placeholders::_2),
"bool moveTo(" QSIZETYPE " offset, bool clearSelection = true)");
registerAPI<bool(qsizetype, qsizetype)>(
registerAPI<bool(qsizetype, qsizetype, WingHex::SelectionMode)>(
engine,
std::bind(&WingHex::WingPlugin::Controller::select, ctl,
std::placeholders::_1, std::placeholders::_2),
"bool select(" QSIZETYPE " offset, " QSIZETYPE " len)");
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
"bool select(" QSIZETYPE " offset, " QSIZETYPE
" len, SelectionMode mode = SelectionMode::Add)");
registerAPI<bool(bool)>(
engine,
@ -1036,14 +991,14 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
registerAPI<bool(qsizetype, qsizetype, const QColor &, const QColor &,
const QString &)>(
engine,
std::bind(QOverload<qsizetype, qsizetype, const QColor &,
std::bind(QOverload<qsizetype, WingHex::qusizetype, const QColor &,
const QColor &, const QString &>::
of(&WingHex::WingPlugin::Controller::metadata),
ctl, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5),
"bool metadata(" QSIZETYPE " begin, " QSIZETYPE
" end, color &in fgcolor, color &in bgcolor, string &in comment)");
"bool metadata(" QSIZETYPE " begin, " QUSIZETYPE
" length, color &in fgcolor, color &in bgcolor, string &in comment)");
registerAPI<bool(qsizetype)>(
engine,
@ -1055,29 +1010,29 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
engine, std::bind(&WingHex::WingPlugin::Controller::clearMetadata, ctl),
"bool clearMetadata()");
registerAPI<bool(qsizetype, qsizetype, const QColor &)>(
registerAPI<bool(qsizetype, WingHex::qusizetype, const QColor &)>(
engine,
std::bind(&WingHex::WingPlugin::Controller::foreground, ctl,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
"bool foreground(" QSIZETYPE " begin, " QSIZETYPE
" end, color &in fgcolor)");
"bool foreground(" QSIZETYPE " begin, " QUSIZETYPE
" length, color &in fgcolor)");
registerAPI<bool(qsizetype, qsizetype, const QColor &)>(
registerAPI<bool(qsizetype, WingHex::qusizetype, const QColor &)>(
engine,
std::bind(&WingHex::WingPlugin::Controller::background, ctl,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
"bool background(" QSIZETYPE " begin, " QSIZETYPE
" end, color &in bgcolor)");
"bool background(" QSIZETYPE " begin, " QUSIZETYPE
" length, color &in bgcolor)");
registerAPI<bool(qsizetype, qsizetype, const QString &)>(
registerAPI<bool(qsizetype, WingHex::qusizetype, const QString &)>(
engine,
std::bind(&WingHex::WingPlugin::Controller::comment, ctl,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
"bool comment(" QSIZETYPE " begin, " QSIZETYPE
" end, string &in comment)");
"bool comment(" QSIZETYPE " begin, " QUSIZETYPE
" length, string &in comment)");
registerAPI<bool(bool)>(
engine,
@ -2119,9 +2074,41 @@ CScriptArray *WingAngelAPI::_FileDialog_getOpenFileNames(
"array<string>");
}
CScriptArray *WingAngelAPI::_HexReader_selectedBytes() {
return byteArrayWrapperFunction(
[this]() -> QByteArray { return emit reader.selectedBytes(); });
CScriptArray *WingAngelAPI::_HexReader_selectedBytes(qsizetype index) {
return byteArrayWrapperFunction([this, index]() -> QByteArray {
return emit reader.selectedBytes(index);
});
}
CScriptArray *WingAngelAPI::_HexReader_selectionBytes() {
// context, which can be used to obtain a pointer to the
// engine.
asIScriptContext *ctx = asGetActiveContext();
if (ctx) {
asIScriptEngine *engine = ctx->GetEngine();
auto ret = emit reader.selectionBytes();
// The script array needs to know its type to properly handle the
// elements. Note that the object type should be cached to avoid
// performance issues if the function is called frequently.
asITypeInfo *arrt = engine->GetTypeInfoByDecl("array<array<byte>>");
asITypeInfo *t = engine->GetTypeInfoByDecl("array<byte>");
Q_ASSERT(arrt && t);
auto array = CScriptArray::Create(arrt, ret.size());
for (qsizetype i = 0; i < ret.size(); ++i) {
auto buffer = ret.at(i);
auto conarr = CScriptArray::Create(t, ret.size());
for (qsizetype i = 0; i < ret.size(); ++i) {
auto v = ret.at(buffer.at(i));
conarr->SetValue(i, &v);
}
array->SetValue(i, conarr);
}
return array;
} else {
return nullptr;
}
}
CScriptArray *WingAngelAPI::_HexReader_readBytes(qsizetype offset,
@ -2220,14 +2207,6 @@ CScriptArray *WingAngelAPI::_HexReader_findAllBytes(qsizetype begin,
}
}
CScriptArray *WingAngelAPI::_HexReader_getMetadatas(qsizetype offset) {
return retarrayWrapperFunction(
[this, offset]() -> QList<WingHex::HexMetadataItem> {
return emit reader.getMetadatas(offset);
},
"array<HexMetadataItem>");
}
CScriptArray *WingAngelAPI::_HexReader_getsBookmarkPos(qsizetype line) {
return retarrayWrapperFunction(
[this, line]() -> QList<qsizetype> {
@ -2236,14 +2215,6 @@ CScriptArray *WingAngelAPI::_HexReader_getsBookmarkPos(qsizetype line) {
"array<" QSIZETYPE ">");
}
CScriptArray *WingAngelAPI::_HexReader_getBookMarks() {
return retarrayWrapperFunction(
[this]() -> QList<WingHex::BookMark> {
return emit reader.getBookMarks();
},
"array<BookMark>");
}
CScriptArray *WingAngelAPI::_HexReader_getSupportedEncodings() {
return retarrayWrapperFunction(
[this]() -> QStringList { return emit reader.getSupportedEncodings(); },

View File

@ -39,8 +39,8 @@ public:
public:
virtual int sdkVersion() const override;
virtual const QString signature() const override;
virtual bool init(const QSettings &set) override;
virtual void unload(QSettings &set) override;
virtual bool init(const std::unique_ptr<QSettings> &set) override;
virtual void unload(std::unique_ptr<QSettings> &set) override;
virtual const QString pluginName() const override;
virtual const QString pluginAuthor() const override;
virtual uint pluginVersion() const override;
@ -137,7 +137,9 @@ private:
QString *selectedFilter,
QFileDialog::Options options);
CScriptArray *_HexReader_selectedBytes();
CScriptArray *_HexReader_selectedBytes(qsizetype index);
CScriptArray *_HexReader_selectionBytes();
CScriptArray *_HexReader_readBytes(qsizetype offset, qsizetype len);
@ -157,12 +159,8 @@ private:
CScriptArray *_HexReader_findAllBytes(qsizetype begin, qsizetype end,
const CScriptArray &ba);
CScriptArray *_HexReader_getMetadatas(qsizetype offset);
CScriptArray *_HexReader_getsBookmarkPos(qsizetype line);
CScriptArray *_HexReader_getBookMarks();
CScriptArray *_HexReader_getSupportedEncodings();
bool _HexController_writeBytes(qsizetype offset, const CScriptArray &ba);

View File

@ -175,8 +175,8 @@ EditorView::FindError EditorView::find(const QByteArray &data,
} break;
case SearchDirection::Selection: {
auto cur = m_hex->cursor();
begin = cur->selectionStart().offset();
end = cur->selectionEnd().offset();
begin = cur->selectionStart(0).offset();
end = cur->selectionEnd(0).offset();
} break;
default: {
begin = -1;

View File

@ -1,6 +1,11 @@
#ifndef DEFINE_H
#define DEFINE_H
enum class CrashCode : int { LanguageFile = 1, PluginSetting };
enum class CrashCode : int {
AlreadyStart,
LanguageFile,
PluginSetting,
GenericCallNotSupported
};
#endif // DEFINE_H

View File

@ -26,6 +26,7 @@
#include "class/appmanager.h"
#include "class/langservice.h"
#include "class/languagemanager.h"
#include "class/layoutmanager.h"
#include "class/logger.h"
#include "class/qkeysequences.h"
#include "class/scriptconsolemachine.h"
@ -1133,8 +1134,28 @@ RibbonTabContent *MainWindow::buildViewPage(RibbonTabContent *tab) {
auto pannel = tab->addGroup(tr("Layout"));
addPannelAction(pannel, QStringLiteral("fullscreen"), tr("Fullscreen"),
&MainWindow::on_fullScreen);
auto &l = LayoutManager::instance().layouts();
auto menu = new QMenu(this);
menu->addAction(newAction(
tr("Default"), [this]() { m_dock->restoreState(_defaultLayout); }));
if (!l.isEmpty()) {
menu->addSeparator();
}
for (auto p = l.constKeyValueBegin(); p != l.constKeyValueEnd(); ++p) {
auto layout = p->second;
menu->addAction(newAction(
p->first, [this, layout]() { m_dock->restoreState(layout); }));
}
addPannelAction(pannel, QStringLiteral("layout"), tr("RestoreLayout"),
&MainWindow::on_restoreLayout);
EMPTY_FUNC, {}, menu);
addPannelAction(pannel, QStringLiteral("layoutexport"),
tr("SaveLayout"), &MainWindow::on_saveLayout);
}
{
@ -1648,7 +1669,7 @@ void MainWindow::on_savesel() {
m_lastusedpath = QFileInfo(filename).absoluteDir().absolutePath();
QFile qfile(filename);
if (qfile.open(QFile::WriteOnly)) {
auto buffer = hexeditor->selectedBytes();
auto buffer = hexeditor->selectedBytes().join();
qfile.write(buffer);
qfile.close();
Toast::toast(this, NAMEICONRES(QStringLiteral("savesel")),
@ -1743,7 +1764,7 @@ void MainWindow::on_findfile() {
}
auto hexeditor = editor->hexEditor();
FindDialog fd(editor->isBigFile(), 0, int(hexeditor->documentBytes()),
hexeditor->selectlength() > 1, this);
hexeditor->selectionCount() == 1, this);
if (fd.exec()) {
FindDialog::Result r;
auto res = fd.getResult(r);
@ -1801,12 +1822,12 @@ void MainWindow::on_checksum() {
auto cs = d.getResults();
auto hashes = Utilities::supportedHashAlgorithms();
if (editor->hexEditor()->selectlength() > 1) {
if (editor->hexEditor()->hasSelection()) {
auto data = editor->hexEditor()->selectedBytes();
for (auto &c : cs) {
auto h = hashes.at(c);
QCryptographicHash hash(h);
hash.addData(data);
hash.addData(data.join());
_hashModel->setCheckSumData(h, hash.result().toHex().toUpper());
}
} else {
@ -1892,11 +1913,17 @@ void MainWindow::on_fill() {
auto ch = char(in.toULongLong(&b, 0));
if (b) {
auto doc = hexeditor->document();
if (doc->isEmpty() || hexeditor->selectlength() == 0)
if (doc->isEmpty() || !hexeditor->hasSelection())
return;
auto pos = hexeditor->cursor()->selectionStart().offset();
hexeditor->Replace(
pos, QByteArray(int(hexeditor->selectlength()), char(ch)));
auto total = hexeditor->selectionCount();
doc->beginMarco(QStringLiteral("FillBytes"));
for (int i = 0; i < total; ++i) {
auto pos = hexeditor->cursor()->selectionStart(i).offset();
hexeditor->Replace(
pos, QByteArray(int(hexeditor->hasSelection()), char(ch)));
}
doc->endMarco();
} else {
Toast::toast(this, NAMEICONRES(QStringLiteral("fill")),
tr("FillInputError"));
@ -1910,11 +1937,18 @@ void MainWindow::on_fillzero() {
return;
}
auto doc = hexeditor->document();
if (doc->isEmpty() || hexeditor->selectlength() == 0)
if (doc->isEmpty() || !hexeditor->hasSelection())
return;
auto pos = hexeditor->cursor()->selectionStart().offset();
hexeditor->Replace(pos,
QByteArray(int(hexeditor->selectlength()), char(0)));
auto cur = hexeditor->cursor();
auto total = cur->selectionCount();
doc->beginMarco(QStringLiteral("FillZero"));
for (int i = 0; i < total; ++i) {
auto pos = cur->selectionStart(i).offset();
hexeditor->Replace(pos,
QByteArray(int(hexeditor->hasSelection()), char(0)));
}
doc->endMarco();
}
void MainWindow::on_bookmark() {
@ -1977,12 +2011,19 @@ void MainWindow::on_metadata() {
if (hexeditor->documentBytes() > 0) {
MetaDialog m(this);
auto cur = hexeditor->cursor();
if (cur->selectionLength() > 0) {
auto begin = cur->selectionStart().offset();
auto end = cur->selectionEnd().offset() + 1;
if (cur->hasSelection()) {
if (m.exec()) {
doc->metadata()->Metadata(begin, end, m.foreGroundColor(),
m.backGroundColor(), m.comment());
auto total = cur->selectionCount();
auto meta = doc->metadata();
meta->beginMarco(QStringLiteral("MetaData"));
for (int i = 0; i < total; ++i) {
auto begin = cur->selectionStart(i).offset();
auto end = cur->selectionEnd(i).offset() + 1;
meta->Metadata(begin, end, m.foreGroundColor(),
m.backGroundColor(), m.comment());
}
meta->endMarco();
cur->clearSelection();
}
} else {
Toast::toast(this, NAMEICONRES(QStringLiteral("metadata")),
@ -2001,7 +2042,7 @@ void MainWindow::on_metadataedit() {
if (hexeditor->documentBytes() > 0) {
MetaDialog m(this);
auto cur = hexeditor->cursor();
if (cur->selectionLength() > 0) {
if (cur->currentSelectionLength() > 0) {
auto mc = doc->metadata()->gets(cur->position().offset());
if (mc.length() > 0) {
@ -2190,7 +2231,7 @@ void MainWindow::on_locChanged() {
m_lblloc->setText(QStringLiteral("(%1,%2)")
.arg(hexeditor->currentRow())
.arg(hexeditor->currentColumn()));
auto sellen = hexeditor->selectlength();
auto sellen = hexeditor->currentSelectionLength();
m_lblsellen->setText(QStringLiteral("%1 - 0x%2")
.arg(sellen)
.arg(QString::number(sellen, 16).toUpper()));
@ -2268,27 +2309,55 @@ void MainWindow::on_locChanged() {
}
// 解码字符串
if (sellen > 1) {
auto cursor = hexeditor->cursor();
QByteArrayList buffer;
bool isPreview = false;
if (cursor->previewSelectionMode() != QHexCursor::SelectionRemove &&
cursor->hasPreviewSelection()) {
buffer.append(hexeditor->previewSelectedBytes());
isPreview = true;
}
if (buffer.isEmpty()) {
if (hexeditor->selectionCount() > 0) {
buffer = hexeditor->selectedBytes();
}
}
auto total = buffer.size();
m_txtDecode->clear();
for (int i = 0; i < total; i++) {
auto b = buffer.at(i);
if (!isPreview) {
m_txtDecode->insertHtml(
QStringLiteral("<font color=\"gold\">[ %1 / %2 ]</font><br />")
.arg(i + 1)
.arg(total));
}
// 如果不超过 10KB (默认)那么解码,防止太多卡死
if (sellen <= 1024 * _decstrlim) {
if (buffer.length() <= 1024 * _decstrlim) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
auto enc = QStringConverter::encodingForName(
hexeditor->renderer()->encoding().toUtf8());
Q_ASSERT(enc.has_value());
QStringDecoder dec(enc.value());
m_txtDecode->setText(dec.decode(hexeditor->selectedBytes()));
m_txtDecode->insertPlainText(dec.decode(b));
#else
auto enc = QTextCodec::codecForName(
hexeditor->renderer()->encoding().toUtf8());
auto dec = enc->makeDecoder();
m_txtDecode->setText(dec->toUnicode(hexeditor->selectedBytes()));
m_txtDecode->setText(dec->toUnicode(b));
#endif
m_txtDecode->insertPlainText(QStringLiteral("\n"));
} else {
m_txtDecode->setHtml(QStringLiteral("<font color=\"red\">%1</font>")
.arg(tr("TooManyBytesDecode")));
m_txtDecode->insertHtml(
QStringLiteral("<font color=\"red\">%1</font><br />")
.arg(tr("TooManyBytesDecode")));
}
} else {
m_txtDecode->clear();
}
}
@ -2308,7 +2377,23 @@ void MainWindow::on_fullScreen() {
}
}
void MainWindow::on_restoreLayout() { m_dock->restoreState(_defaultLayout); }
void MainWindow::on_saveLayout() {
auto filename = WingFileDialog::getSaveFileName(
this, tr("SaveLayout"), m_lastusedpath,
QStringLiteral("Layout (*.wing-layout)"));
if (!filename.isEmpty()) {
QFile f(filename);
if (f.open(QFile::WriteOnly)) {
f.write(m_dock->saveState());
f.close();
Toast::toast(this, NAMEICONRES(QStringLiteral("layoutexport")),
tr("SaveLayoutSuccess"));
} else {
Toast::toast(this, NAMEICONRES(QStringLiteral("layoutexport")),
tr("SaveLayoutError"));
}
}
}
void MainWindow::on_exportlog() {
auto nfile = saveLog();
@ -2469,7 +2554,7 @@ void MainWindow::connectEditorView(EditorView *editor) {
if (hexeditor->documentBytes() > 0) {
MetaDialog m(this);
auto cur = hexeditor->cursor();
if (cur->selectionLength() > 0) {
if (cur->hasSelection()) {
auto mc = doc->metadata()->gets(cur->position().offset());
if (mc.length() > 0) {
@ -2490,12 +2575,18 @@ void MainWindow::connectEditorView(EditorView *editor) {
mi->ModifyMetadata(meta, o);
}
} else {
auto begin = cur->selectionStart().offset();
auto end = cur->selectionEnd().offset() + 1;
auto total = hexeditor->selectionCount();
if (m.exec()) {
doc->metadata()->Metadata(
begin, end, m.foreGroundColor(),
m.backGroundColor(), m.comment());
auto meta = doc->metadata();
meta->beginMarco(QStringLiteral("OnMetaData"));
for (int i = 0; i < total; ++i) {
auto begin = cur->selectionStart(i).offset();
auto end = cur->selectionEnd(i).offset() + 1;
meta->Metadata(begin, end, m.foreGroundColor(),
m.backGroundColor(), m.comment());
}
meta->endMarco();
cur->clearSelection();
}
}
} else {

View File

@ -187,7 +187,7 @@ private slots:
void on_viewtxt();
void on_fullScreen();
void on_restoreLayout();
void on_saveLayout();
void on_exportlog();
void on_clslog();

View File

@ -23,6 +23,8 @@
#include "settingpage.h"
#include <memory>
#include <QCryptographicHash>
#include <QDockWidget>
#include <QList>
@ -45,6 +47,8 @@
namespace WingHex {
using qusizetype = QIntegerForSizeof<std::size_t>::Unsigned;
Q_DECL_UNUSED constexpr auto SDKVERSION = 14;
Q_DECL_UNUSED static QString PLUGINDIR() {
@ -73,17 +77,16 @@ enum ErrFile : int {
};
Q_ENUM_NS(ErrFile)
Q_NAMESPACE
enum class SelectionMode : int { Add, Remove, Single };
Q_ENUM_NS(SelectionMode)
struct FindResult {
qsizetype offset = -1;
qsizetype line = -1;
qsizetype col = -1;
};
struct BookMark {
qsizetype pos = -1;
QString comment;
};
class IWingPlugin;
struct HexPosition {
@ -108,31 +111,6 @@ struct HexPosition {
}
};
struct HexMetadataItem {
qsizetype begin;
qsizetype end;
QColor foreground, background;
QString comment;
// added by wingsummer
bool operator==(const HexMetadataItem &item) {
return begin == item.begin && end == item.end &&
foreground == item.foreground && background == item.background &&
comment == item.comment;
}
HexMetadataItem() = default;
HexMetadataItem(qsizetype begin, qsizetype end, QColor foreground,
QColor background, QString comment) {
this->begin = begin;
this->end = end;
this->foreground = foreground;
this->background = background;
this->comment = comment;
}
};
namespace WingPlugin {
class Reader : public QObject {
@ -148,12 +126,18 @@ signals:
qsizetype documentLines();
qsizetype documentBytes();
WingHex::HexPosition currentPos();
WingHex::HexPosition selectionPos();
qsizetype currentRow();
qsizetype currentColumn();
qsizetype currentOffset();
qsizetype selectedLength();
QByteArray selectedBytes();
QByteArray selectedBytes(qsizetype index);
QByteArrayList selectionBytes();
WingHex::HexPosition selectionStart(qsizetype index);
WingHex::HexPosition selectionEnd(qsizetype index);
qsizetype selectionLength(qsizetype index);
qsizetype selectionCount();
bool stringVisible();
bool addressVisible();
@ -191,14 +175,11 @@ signals:
// metadata
bool lineHasMetadata(qsizetype line);
QList<WingHex::HexMetadataItem> getMetadatas(qsizetype offset);
// bookmark
bool lineHasBookMark(qsizetype line);
QList<qsizetype> getsBookmarkPos(qsizetype line);
WingHex::BookMark bookMark(qsizetype pos);
QString bookMarkComment(qsizetype pos);
QList<WingHex::BookMark> getBookMarks();
bool existBookMark(qsizetype pos);
// extension
@ -258,17 +239,19 @@ signals:
bool removeAll(); // extension
// cursor
bool moveTo(qsizetype line, qsizetype column, int nibbleindex = 1);
bool moveTo(qsizetype offset);
bool select(qsizetype offset, qsizetype length);
bool moveTo(qsizetype line, qsizetype column, int nibbleindex = 1,
bool clearSelection = true);
bool moveTo(qsizetype offset, bool clearSelection = true);
bool select(qsizetype offset, qsizetype length,
SelectionMode mode = SelectionMode::Add);
bool setInsertionMode(bool isinsert);
// metadata
bool foreground(qsizetype begin, qsizetype end, const QColor &fgcolor);
bool background(qsizetype begin, qsizetype end, const QColor &bgcolor);
bool comment(qsizetype begin, qsizetype end, const QString &comment);
bool foreground(qsizetype begin, qusizetype length, const QColor &fgcolor);
bool background(qsizetype begin, qusizetype length, const QColor &bgcolor);
bool comment(qsizetype begin, qusizetype length, const QString &comment);
bool metadata(qsizetype begin, qsizetype end, const QColor &fgcolor,
bool metadata(qsizetype begin, qusizetype length, const QColor &fgcolor,
const QColor &bgcolor, const QString &comment);
bool removeMetadata(qsizetype offset);
@ -523,8 +506,8 @@ public:
virtual const QString signature() const = 0;
virtual ~IWingPlugin() = default;
virtual bool init(const QSettings &set) = 0;
virtual void unload(QSettings &set) = 0;
virtual bool init(const std::unique_ptr<QSettings> &set) = 0;
virtual void unload(std::unique_ptr<QSettings> &set) = 0;
virtual const QString pluginName() const = 0;
virtual const QString pluginAuthor() const = 0;
virtual uint pluginVersion() const = 0;

View File

@ -48,8 +48,9 @@ PluginSystem::~PluginSystem() {
}
for (auto &item : loadedplgs) {
QSettings set(udir.absoluteFilePath(item->metaObject()->className()),
QSettings::Format::IniFormat);
auto set = std::make_unique<QSettings>(
udir.absoluteFilePath(item->metaObject()->className()),
QSettings::Format::IniFormat);
item->unload(set);
delete item;
}
@ -289,7 +290,8 @@ QString PluginSystem::getPUID(IWingPlugin *p) {
}
}
bool PluginSystem::loadPlugin(IWingPlugin *p, const QDir &setdir) {
bool PluginSystem::loadPlugin(IWingPlugin *p,
const std::optional<QDir> &setdir) {
QTranslator *p_tr = nullptr;
try {
@ -317,20 +319,19 @@ bool PluginSystem::loadPlugin(IWingPlugin *p, const QDir &setdir) {
connectLoadingInterface(p);
QSettings *setp;
if (setdir == QDir()) {
setp = new QSettings;
} else {
setp = new QSettings(
setdir.absoluteFilePath(p->metaObject()->className()),
QSettings::Format::IniFormat);
}
{
std::unique_ptr<QSettings> setp(nullptr);
if (setdir.has_value()) {
setp = std::make_unique<QSettings>(
setdir->absoluteFilePath(p->metaObject()->className()),
QSettings::Format::IniFormat);
}
if (!p->init(*setp)) {
setp->deleteLater();
throw tr("ErrLoadInitPlugin");
if (!p->init(setp)) {
setp->deleteLater();
throw tr("ErrLoadInitPlugin");
}
}
setp->deleteLater();
loadedplgs.push_back(p);
loadedpuid << puid;
@ -603,26 +604,11 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
auto e = pluginCurrentEditor(plg);
if (e) {
auto qpos = e->hexEditor()->cursor()->position();
pos.line = qpos.line;
pos.column = qpos.column;
pos.lineWidth = qpos.lineWidth;
pos.nibbleindex = qpos.nibbleindex;
}
return pos;
});
connect(preader, &WingPlugin::Reader::selectionPos, _win,
[=]() -> HexPosition {
HexPosition pos;
memset(&pos, 0, sizeof(HexPosition));
auto e = pluginCurrentEditor(plg);
if (e) {
auto cur = e->hexEditor()->cursor();
pos.line = cur->selectionLine();
pos.column = cur->selectionColumn();
pos.nibbleindex = cur->selectionNibble();
pos.lineWidth = cur->position().lineWidth;
auto cursor = e->hexEditor()->cursor();
pos.line = cursor->currentLine();
pos.column = cursor->currentColumn();
pos.lineWidth = e->hexEditor()->document()->hexLineWidth();
pos.nibbleindex = cursor->currentNibble();
}
return pos;
});
@ -653,18 +639,77 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
[=]() -> qsizetype {
auto e = pluginCurrentEditor(plg);
if (e) {
return e->hexEditor()->cursor()->selectionLength();
return e->hexEditor()->cursor()->currentSelectionLength();
}
return 0;
});
connect(preader, &WingPlugin::Reader::selectedBytes, _win,
[=]() -> QByteArray {
[=](qsizetype index) -> QByteArray {
auto e = pluginCurrentEditor(plg);
if (e && index >= 0 &&
index < e->hexEditor()->cursor()->selectionCount()) {
return e->hexEditor()->selectedBytes(index);
}
return {};
});
connect(preader, &WingPlugin::Reader::selectionBytes, _win,
[=]() -> QByteArrayList {
auto e = pluginCurrentEditor(plg);
if (e) {
return e->hexEditor()->selectedBytes();
}
return {};
});
connect(preader, &WingPlugin::Reader::selectionStart, _win,
[=](qsizetype index) -> HexPosition {
HexPosition pos;
memset(&pos, 0, sizeof(HexPosition));
auto e = pluginCurrentEditor(plg);
auto cursor = e->hexEditor()->cursor();
if (e && index >= 0 && index < cursor->selectionCount()) {
auto qpos = cursor->selectionStart(index);
pos.line = qpos.line;
pos.column = qpos.column;
pos.lineWidth = qpos.lineWidth;
pos.nibbleindex = qpos.nibbleindex;
}
return pos;
});
connect(preader, &WingPlugin::Reader::selectionEnd, _win,
[=](qsizetype index) -> HexPosition {
HexPosition pos;
memset(&pos, 0, sizeof(HexPosition));
auto e = pluginCurrentEditor(plg);
auto cursor = e->hexEditor()->cursor();
if (e && index >= 0 && index < cursor->selectionCount()) {
auto qpos = cursor->selectionEnd(index);
pos.line = qpos.line;
pos.column = qpos.column;
pos.lineWidth = qpos.lineWidth;
pos.nibbleindex = qpos.nibbleindex;
}
return pos;
});
connect(preader, &WingPlugin::Reader::selectionLength, _win,
[=](qsizetype index) -> qsizetype {
auto e = pluginCurrentEditor(plg);
auto cursor = e->hexEditor()->cursor();
if (e && index >= 0 && index < cursor->selectionCount()) {
return cursor->selectionLength(index);
}
return 0;
});
connect(preader, &WingPlugin::Reader::selectionCount, _win,
[=]() -> qsizetype {
auto e = pluginCurrentEditor(plg);
auto cursor = e->hexEditor()->cursor();
if (e) {
return cursor->selectionCount();
}
return 0;
});
connect(preader, &WingPlugin::Reader::stringVisible, _win, [=]() -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
@ -830,22 +875,6 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
}
return qsizetype(-1);
});
connect(preader, &WingPlugin::Reader::getMetadatas, _win,
[=](qsizetype offset) -> QList<HexMetadataItem> {
auto e = pluginCurrentEditor(plg);
if (e) {
auto ometaline =
e->hexEditor()->document()->metadata()->gets(offset);
QList<HexMetadataItem> metaline;
for (auto &item : ometaline) {
metaline.push_back(HexMetadataItem(
item.begin, item.end, item.foreground,
item.background, item.comment));
}
return metaline;
}
return {};
});
connect(
preader, &WingPlugin::Reader::lineHasMetadata, _win,
[=](qsizetype line) -> bool {
@ -873,18 +902,6 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
}
return {};
});
connect(preader, &WingPlugin::Reader::bookMark, _win,
[=](qsizetype pos) -> BookMark {
auto e = pluginCurrentEditor(plg);
if (e) {
auto comment = e->hexEditor()->document()->bookMark(pos);
BookMark book;
book.pos = pos;
book.comment = comment;
return book;
}
return {};
});
connect(preader, &WingPlugin::Reader::bookMarkComment, _win,
[=](qsizetype pos) -> QString {
auto e = pluginCurrentEditor(plg);
@ -893,21 +910,6 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
}
return {};
});
connect(preader, &WingPlugin::Reader::getBookMarks, _win,
[=]() -> QList<BookMark> {
auto e = pluginCurrentEditor(plg);
if (e) {
auto &bs = e->hexEditor()->document()->bookMarks();
QList<BookMark> bookmarks;
for (auto p = bs.cbegin(); p != bs.cbegin(); ++p) {
BookMark i;
i.pos = p.key();
i.comment = p.value();
bookmarks.push_back(i);
}
}
return {};
});
connect(preader, &WingPlugin::Reader::existBookMark, _win,
[=](qsizetype pos) -> bool {
auto e = pluginCurrentEditor(plg);
@ -1253,35 +1255,53 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) {
return false;
});
connect(pctl,
QOverload<qsizetype, qsizetype, int>::of(
QOverload<qsizetype, qsizetype, int, bool>::of(
&WingPlugin::Controller::moveTo),
_win,
[=](qsizetype line, qsizetype column, int nibbleindex) -> bool {
[=](qsizetype line, qsizetype column, int nibbleindex,
bool clearSelection) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
e->hexEditor()->cursor()->moveTo(line, column, nibbleindex);
e->hexEditor()->cursor()->moveTo(line, column, nibbleindex,
clearSelection);
return true;
}
return false;
});
connect(pctl, QOverload<qsizetype>::of(&WingPlugin::Controller::moveTo),
_win, [=](qsizetype offset) -> bool {
connect(pctl,
QOverload<qsizetype, bool>::of(&WingPlugin::Controller::moveTo),
_win, [=](qsizetype offset, bool clearSelection) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
e->hexEditor()->cursor()->moveTo(offset);
e->hexEditor()->cursor()->moveTo(offset, clearSelection);
return true;
}
return false;
});
connect(pctl, &WingPlugin::Controller::select, _win,
[=](qsizetype offset, qsizetype length) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
e->hexEditor()->cursor()->setSelection(offset, length);
return true;
connect(
pctl, &WingPlugin::Controller::select, _win,
[=](qsizetype offset, qsizetype length, SelectionMode mode) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto cursor = e->hexEditor()->cursor();
cursor->moveTo(offset);
QHexCursor::SelectionMode smode;
switch (mode) {
case WingHex::SelectionMode::Add:
smode = QHexCursor::SelectionAdd;
break;
case WingHex::SelectionMode::Remove:
smode = QHexCursor::SelectionRemove;
break;
case WingHex::SelectionMode::Single:
smode = QHexCursor::SelectionNormal;
break;
}
return false;
});
cursor->select(length, smode);
return true;
}
return false;
});
connect(pctl, &WingPlugin::Controller::setInsertionMode, _win,
[=](bool isinsert) -> bool {
auto e = pluginCurrentEditor(plg);
@ -1294,30 +1314,30 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) {
return false;
});
connect(pctl,
QOverload<qsizetype, qsizetype, const QColor &, const QColor &,
QOverload<qsizetype, qusizetype, const QColor &, const QColor &,
const QString &>::of(&WingPlugin::Controller::metadata),
_win,
[=](qsizetype begin, qsizetype end, const QColor &fgcolor,
[=](qsizetype begin, qusizetype length, const QColor &fgcolor,
const QColor &bgcolor, const QString &comment) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->metadata(begin, end, fgcolor,
bgcolor, comment);
return doc->metadata()->metadata(begin, begin + length,
fgcolor, bgcolor, comment);
}
return false;
});
connect(pctl,
QOverload<qsizetype, qsizetype, const QColor &, const QColor &,
QOverload<qsizetype, qusizetype, const QColor &, const QColor &,
const QString &>::of(&WingPlugin::Controller::metadata),
_win,
[=](qsizetype begin, qsizetype end, const QColor &fgcolor,
[=](qsizetype begin, qusizetype length, const QColor &fgcolor,
const QColor &bgcolor, const QString &comment) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->metadata(begin, end, fgcolor,
bgcolor, comment);
return doc->metadata()->metadata(begin, begin + length,
fgcolor, bgcolor, comment);
}
return false;
});
@ -1340,34 +1360,39 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) {
}
return false;
});
connect(pctl, &WingPlugin::Controller::comment, _win,
[=](qsizetype begin, qusizetype length,
const QString &comment) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->comment(begin, begin + length,
comment);
}
return false;
});
connect(
pctl, &WingPlugin::Controller::comment, _win,
[=](qsizetype begin, qsizetype end, const QString &comment) -> bool {
pctl, &WingPlugin::Controller::foreground, _win,
[=](qsizetype begin, qusizetype length, const QColor &fgcolor) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->comment(begin, end, comment);
return doc->metadata()->foreground(begin, begin + length,
fgcolor);
}
return false;
});
connect(
pctl, &WingPlugin::Controller::background, _win,
[=](qsizetype begin, qusizetype length, const QColor &bgcolor) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->background(begin, begin + length,
bgcolor);
}
return false;
});
connect(pctl, &WingPlugin::Controller::foreground, _win,
[=](qsizetype begin, qsizetype end, const QColor &fgcolor) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->foreground(begin, end, fgcolor);
}
return false;
});
connect(pctl, &WingPlugin::Controller::background, _win,
[=](qsizetype begin, qsizetype end, const QColor &bgcolor) -> bool {
auto e = pluginCurrentEditor(plg);
if (e) {
auto doc = e->hexEditor()->document();
return doc->metadata()->background(begin, end, bgcolor);
}
return false;
});
connect(pctl, &WingPlugin::Controller::setMetaVisible, _win,
[=](bool b) -> bool {
auto e = pluginCurrentEditor(plg);
@ -1857,7 +1882,7 @@ void PluginSystem::LoadPlugin() {
_angelplg = new WingAngelAPI;
auto ret = loadPlugin(_angelplg, QDir());
auto ret = loadPlugin(_angelplg, std::nullopt);
Q_ASSERT(ret);
Q_UNUSED(ret);

View File

@ -126,7 +126,7 @@ private:
QString getPUID(IWingPlugin *p);
private:
bool loadPlugin(IWingPlugin *p, const QDir &setdir);
bool loadPlugin(IWingPlugin *p, const std::optional<QDir> &setdir);
void connectInterface(IWingPlugin *plg);
void connectLoadingInterface(IWingPlugin *plg);

View File

@ -2965,6 +2965,8 @@ Toast
qproperty-fontPointSize: 18;
}
QStatusBar::item { border: 0px solid black; }
/* style sheet for ScriptEditor */
QEditor
{

View File

@ -2969,6 +2969,8 @@ Toast
qproperty-fontPointSize: 18;
}
QStatusBar::item { border: 0px solid black; }
/* style sheet for ScriptEditor */
QEditor
{