feat: 十六进制编辑增加多选支持;修复程序单例问题;增加布局管理器;完善插件系统;
This commit is contained in:
parent
e47b96b563
commit
735298d850
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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>
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
File diff suppressed because it is too large
Load Diff
6
main.cpp
6
main.cpp
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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(); },
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -187,7 +187,7 @@ private slots:
|
|||
|
||||
void on_viewtxt();
|
||||
void on_fullScreen();
|
||||
void on_restoreLayout();
|
||||
void on_saveLayout();
|
||||
void on_exportlog();
|
||||
void on_clslog();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -2965,6 +2965,8 @@ Toast
|
|||
qproperty-fontPointSize: 18;
|
||||
}
|
||||
|
||||
QStatusBar::item { border: 0px solid black; }
|
||||
|
||||
/* style sheet for ScriptEditor */
|
||||
QEditor
|
||||
{
|
||||
|
|
|
@ -2969,6 +2969,8 @@ Toast
|
|||
qproperty-fontPointSize: 18;
|
||||
}
|
||||
|
||||
QStatusBar::item { border: 0px solid black; }
|
||||
|
||||
/* style sheet for ScriptEditor */
|
||||
QEditor
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue