feat: 引入文档撤销堆栈可视化;插件不再具有独立的撤销堆栈;

This commit is contained in:
寂静的羽夏 2025-07-05 21:04:30 +08:00
parent fb4f439e50
commit a3b465534c
53 changed files with 1884 additions and 1198 deletions

View File

@ -51,8 +51,8 @@ add_library(
document/commands/bookmark/bookmarkremovecommand.h document/commands/bookmark/bookmarkremovecommand.h
document/commands/bookmark/bookmarkreplacecommand.cpp document/commands/bookmark/bookmarkreplacecommand.cpp
document/commands/bookmark/bookmarkreplacecommand.h document/commands/bookmark/bookmarkreplacecommand.h
document/commands/baseaddrcommand.cpp document/commands/undocommandbase.h
document/commands/baseaddrcommand.h document/commands/undocommandbase.cpp
document/qhexcursor.cpp document/qhexcursor.cpp
document/qhexcursor.h document/qhexcursor.h
document/qhexdocument.cpp document/qhexdocument.cpp

View File

@ -23,8 +23,22 @@
BookMarkAddCommand::BookMarkAddCommand(QHexDocument *doc, qsizetype pos, BookMarkAddCommand::BookMarkAddCommand(QHexDocument *doc, qsizetype pos,
QString comment, QUndoCommand *parent) QString comment, QUndoCommand *parent)
: BookMarkCommand(doc, pos, comment, parent) {} : BookMarkCommand(tr("[AddBookMark] pos: %1").arg(pos), doc, pos, comment,
parent) {}
void BookMarkAddCommand::redo() { m_doc->addBookMark(m_pos, m_comment); } void BookMarkAddCommand::redo() { m_doc->addBookMark(m_pos, m_comment); }
int BookMarkAddCommand::id() const { return UndoID_BookMarkAdd; }
bool BookMarkAddCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const BookMarkAddCommand *>(other);
if (ucmd) {
if (this->m_pos == ucmd->m_pos) {
this->m_comment = m_comment;
return true;
}
}
return false;
}
void BookMarkAddCommand::undo() { m_doc->removeBookMark(m_pos); } void BookMarkAddCommand::undo() { m_doc->removeBookMark(m_pos); }

View File

@ -24,13 +24,22 @@
#include "bookmarkcommand.h" #include "bookmarkcommand.h"
class BookMarkAddCommand : public BookMarkCommand { #include <QCoreApplication>
public:
BookMarkAddCommand(QHexDocument *doc, qsizetype pos, QString comment,
QUndoCommand *parent = nullptr);
void undo() override; class BookMarkAddCommand : public BookMarkCommand {
void redo() override; Q_DECLARE_TR_FUNCTIONS(BookMarkAddCommand)
public:
explicit BookMarkAddCommand(QHexDocument *doc, qsizetype pos,
QString comment,
QUndoCommand *parent = nullptr);
// QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
}; };
#endif // BOOKMARKADDCOMMAND_H #endif // BOOKMARKADDCOMMAND_H

View File

@ -24,8 +24,16 @@
BookMarkClearCommand::BookMarkClearCommand( BookMarkClearCommand::BookMarkClearCommand(
QHexDocument *doc, const QMap<qsizetype, QString> &bookmarks, QHexDocument *doc, const QMap<qsizetype, QString> &bookmarks,
QUndoCommand *parent) QUndoCommand *parent)
: QUndoCommand(parent), m_doc(doc), m_bookmarks(bookmarks) {} : UndoCommandBase(tr("[ClearBookMark]"), parent), m_doc(doc),
m_bookmarks(bookmarks) {}
void BookMarkClearCommand::redo() { m_doc->clearBookMark(); } void BookMarkClearCommand::redo() { m_doc->clearBookMark(); }
int BookMarkClearCommand::id() const { return UndoID_BookMarkClear; }
bool BookMarkClearCommand::mergeWith(const QUndoCommand *other) {
Q_UNUSED(other);
return true;
}
void BookMarkClearCommand::undo() { m_doc->applyBookMarks(m_bookmarks); } void BookMarkClearCommand::undo() { m_doc->applyBookMarks(m_bookmarks); }

View File

@ -22,19 +22,26 @@
#ifndef BOOKMARKCLEARCOMMAND_H #ifndef BOOKMARKCLEARCOMMAND_H
#define BOOKMARKCLEARCOMMAND_H #define BOOKMARKCLEARCOMMAND_H
#include "../undocommandbase.h"
#include "document/qhexdocument.h" #include "document/qhexdocument.h"
#include <QCoreApplication>
#include <QMap> #include <QMap>
#include <QObject>
#include <QUndoCommand>
class BookMarkClearCommand : public QUndoCommand { class BookMarkClearCommand : public UndoCommandBase {
Q_DECLARE_TR_FUNCTIONS(BookMarkClearCommand)
public: public:
BookMarkClearCommand(QHexDocument *doc, explicit BookMarkClearCommand(QHexDocument *doc,
const QMap<qsizetype, QString> &bookmarks, const QMap<qsizetype, QString> &bookmarks,
QUndoCommand *parent = nullptr); QUndoCommand *parent = nullptr);
void undo() override; // QUndoCommand interface
void redo() override; public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
protected: protected:
QHexDocument *m_doc; QHexDocument *m_doc;

View File

@ -21,6 +21,8 @@
#include "bookmarkcommand.h" #include "bookmarkcommand.h"
BookMarkCommand::BookMarkCommand(QHexDocument *doc, qsizetype pos, BookMarkCommand::BookMarkCommand(const QString &text, QHexDocument *doc,
QString comment, QUndoCommand *parent) qsizetype pos, QString comment,
: QUndoCommand(parent), m_doc(doc), m_comment(comment), m_pos(pos) {} QUndoCommand *parent)
: UndoCommandBase(text, parent), m_doc(doc), m_comment(comment),
m_pos(pos) {}

View File

@ -22,14 +22,14 @@
#ifndef BOOKMARKCOMMAND_H #ifndef BOOKMARKCOMMAND_H
#define BOOKMARKCOMMAND_H #define BOOKMARKCOMMAND_H
#include "../undocommandbase.h"
#include "document/qhexdocument.h" #include "document/qhexdocument.h"
#include <QObject>
#include <QUndoCommand>
class BookMarkCommand : public QUndoCommand { class BookMarkCommand : public UndoCommandBase {
public: public:
BookMarkCommand(QHexDocument *doc, qsizetype pos, QString comment, explicit BookMarkCommand(const QString &text, QHexDocument *doc,
QUndoCommand *parent = nullptr); qsizetype pos, QString comment,
QUndoCommand *parent = nullptr);
protected: protected:
QHexDocument *m_doc; QHexDocument *m_doc;

View File

@ -24,8 +24,21 @@
BookMarkRemoveCommand::BookMarkRemoveCommand(QHexDocument *doc, qsizetype pos, BookMarkRemoveCommand::BookMarkRemoveCommand(QHexDocument *doc, qsizetype pos,
QString comment, QString comment,
QUndoCommand *parent) QUndoCommand *parent)
: BookMarkCommand(doc, pos, comment, parent) {} : BookMarkCommand(tr("[RemoveBookMark] pos: %1").arg(pos), doc, pos,
comment, parent) {}
void BookMarkRemoveCommand::redo() { m_doc->removeBookMark(m_pos); } void BookMarkRemoveCommand::redo() { m_doc->removeBookMark(m_pos); }
int BookMarkRemoveCommand::id() const { return UndoID_BookMarkRemove; }
bool BookMarkRemoveCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const BookMarkRemoveCommand *>(other);
if (ucmd) {
if (this->m_pos == ucmd->m_pos) {
return true;
}
}
return false;
}
void BookMarkRemoveCommand::undo() { m_doc->addBookMark(m_pos, m_comment); } void BookMarkRemoveCommand::undo() { m_doc->addBookMark(m_pos, m_comment); }

View File

@ -24,13 +24,23 @@
#include "bookmarkcommand.h" #include "bookmarkcommand.h"
class BookMarkRemoveCommand : public BookMarkCommand { #include <QCoreApplication>
public:
BookMarkRemoveCommand(QHexDocument *doc, qsizetype pos, QString comment,
QUndoCommand *parent = nullptr);
void undo() override; class BookMarkRemoveCommand : public BookMarkCommand {
void redo() override; Q_DECLARE_TR_FUNCTIONS(BookMarkRemoveCommand)
public:
explicit BookMarkRemoveCommand(QHexDocument *doc, qsizetype pos,
QString comment,
QUndoCommand *parent = nullptr);
// QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
}; };
#endif // BOOKMARKREMOVECOMMAND_H #endif // BOOKMARKREMOVECOMMAND_H

View File

@ -25,8 +25,23 @@ BookMarkReplaceCommand::BookMarkReplaceCommand(QHexDocument *doc, qsizetype pos,
QString comment, QString comment,
QString oldcomment, QString oldcomment,
QUndoCommand *parent) QUndoCommand *parent)
: BookMarkCommand(doc, pos, comment, parent), m_oldcomment(oldcomment) {} : BookMarkCommand(tr("[ReplaceBookMark] pos: %1").arg(pos), doc, pos,
comment, parent),
m_oldcomment(oldcomment) {}
void BookMarkReplaceCommand::redo() { m_doc->modBookMark(m_pos, m_comment); } void BookMarkReplaceCommand::redo() { m_doc->modBookMark(m_pos, m_comment); }
int BookMarkReplaceCommand::id() const { return UndoID_BookMarkReplace; }
bool BookMarkReplaceCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const BookMarkReplaceCommand *>(other);
if (ucmd) {
if (this->m_pos == ucmd->m_pos) {
this->m_comment = m_comment;
return true;
}
}
return false;
}
void BookMarkReplaceCommand::undo() { m_doc->modBookMark(m_pos, m_oldcomment); } void BookMarkReplaceCommand::undo() { m_doc->modBookMark(m_pos, m_oldcomment); }

View File

@ -24,13 +24,22 @@
#include "bookmarkcommand.h" #include "bookmarkcommand.h"
class BookMarkReplaceCommand : public BookMarkCommand { #include <QCoreApplication>
public:
BookMarkReplaceCommand(QHexDocument *doc, qsizetype pos, QString comment,
QString oldcomment, QUndoCommand *parent = nullptr);
void undo() override; class BookMarkReplaceCommand : public BookMarkCommand {
void redo() override; Q_DECLARE_TR_FUNCTIONS(BookMarkReplaceCommand)
public:
explicit BookMarkReplaceCommand(QHexDocument *doc, qsizetype pos,
QString comment, QString oldcomment,
QUndoCommand *parent = nullptr);
// QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
protected: protected:
QString m_oldcomment; QString m_oldcomment;

View File

@ -24,7 +24,7 @@
AppendCommand::AppendCommand(QHexDocument *doc, QHexCursor *cursor, AppendCommand::AppendCommand(QHexDocument *doc, QHexCursor *cursor,
const QByteArray &data, int nibbleindex, const QByteArray &data, int nibbleindex,
QUndoCommand *parent) QUndoCommand *parent)
: HexCommand(doc, cursor, nibbleindex, parent) { : HexCommand(tr("[HexAppend]"), doc, cursor, nibbleindex, parent) {
m_offset = -1; m_offset = -1;
m_data = data; m_data = data;
m_length = data.length(); m_length = data.length();
@ -36,7 +36,6 @@ void AppendCommand::undo() {
m_doc->insertBookMarkAdjustRevert(offset, m_length); m_doc->insertBookMarkAdjustRevert(offset, m_length);
m_doc->metadata()->insertAdjustRevert(offset, m_length); m_doc->metadata()->insertAdjustRevert(offset, m_length);
m_cursor->setPos(offset, m_nibbleindex); m_cursor->setPos(offset, m_nibbleindex);
HexCommand::undo();
} }
void AppendCommand::redo() { void AppendCommand::redo() {
@ -49,5 +48,15 @@ void AppendCommand::redo() {
} else { } else {
m_cursor->setPos(offset + m_length, m_nibbleindex); m_cursor->setPos(offset + m_length, m_nibbleindex);
} }
HexCommand::redo(); }
int AppendCommand::id() const { return UndoID_HexAppend; }
bool AppendCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const AppendCommand *>(other);
if (ucmd) {
this->m_data.append(ucmd->m_data);
return true;
}
return false;
} }

View File

@ -24,12 +24,22 @@
#include "hexcommand.h" #include "hexcommand.h"
#include <QCoreApplication>
class AppendCommand : public HexCommand { class AppendCommand : public HexCommand {
Q_DECLARE_TR_FUNCTIONS(AppendCommand)
public: public:
AppendCommand(QHexDocument *doc, QHexCursor *cursor, const QByteArray &data, explicit AppendCommand(QHexDocument *doc, QHexCursor *cursor,
int nibbleindex, QUndoCommand *parent = nullptr); const QByteArray &data, int nibbleindex,
void undo() override; QUndoCommand *parent = nullptr);
void redo() override;
// QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
}; };
#endif // APPENDCOMMAND_H #endif // APPENDCOMMAND_H

View File

@ -21,14 +21,8 @@
#include "hexcommand.h" #include "hexcommand.h"
HexCommand::HexCommand(QHexDocument *doc, QHexCursor *cursor, int nibbleindex, HexCommand::HexCommand(const QString &text, QHexDocument *doc,
QHexCursor *cursor, int nibbleindex,
QUndoCommand *parent) QUndoCommand *parent)
: QUndoCommand(parent), m_doc(doc), m_cursor(cursor), m_offset(0), : UndoCommandBase(text, parent), m_doc(doc), m_cursor(cursor), m_offset(0),
m_length(0), m_nibbleindex(nibbleindex) {} m_length(0), m_nibbleindex(nibbleindex) {}
void HexCommand::undo() {
Q_ASSERT(m_doc->m_bytesModFlag > 0);
m_doc->m_bytesModFlag--;
}
void HexCommand::redo() { m_doc->m_bytesModFlag++; }

View File

@ -25,15 +25,13 @@
#include "document/qhexcursor.h" #include "document/qhexcursor.h"
#include "document/qhexdocument.h" #include "document/qhexdocument.h"
#include <QUndoCommand> #include "document/commands/undocommandbase.h"
class HexCommand : public QUndoCommand { class HexCommand : public UndoCommandBase {
public: public:
HexCommand(QHexDocument *doc, QHexCursor *cursor, int nibbleindex, explicit HexCommand(const QString &text, QHexDocument *doc,
QUndoCommand *parent = nullptr); QHexCursor *cursor, int nibbleindex,
QUndoCommand *parent = nullptr);
void undo() override;
void redo() override;
protected: protected:
QHexDocument *m_doc; QHexDocument *m_doc;

View File

@ -21,10 +21,13 @@
#include "insertcommand.h" #include "insertcommand.h"
#include "document/commands/hex/replacecommand.h"
InsertCommand::InsertCommand(QHexDocument *doc, QHexCursor *cursor, InsertCommand::InsertCommand(QHexDocument *doc, QHexCursor *cursor,
qsizetype offset, const QByteArray &data, qsizetype offset, const QByteArray &data,
int nibbleindex, QUndoCommand *parent) int nibbleindex, QUndoCommand *parent)
: HexCommand(doc, cursor, nibbleindex, parent) { : HexCommand(tr("[HexInsert] pos: %1").arg(offset), doc, cursor,
nibbleindex, parent) {
m_offset = offset; m_offset = offset;
m_data = data; m_data = data;
m_length = data.length(); m_length = data.length();
@ -35,7 +38,6 @@ void InsertCommand::undo() {
m_doc->insertBookMarkAdjustRevert(m_offset, m_length); m_doc->insertBookMarkAdjustRevert(m_offset, m_length);
m_doc->metadata()->insertAdjustRevert(m_offset, m_length); m_doc->metadata()->insertAdjustRevert(m_offset, m_length);
m_cursor->setPos(m_offset, m_nibbleindex); m_cursor->setPos(m_offset, m_nibbleindex);
HexCommand::undo();
} }
void InsertCommand::redo() { void InsertCommand::redo() {
m_doc->_insert(m_offset, m_data); m_doc->_insert(m_offset, m_data);
@ -46,5 +48,28 @@ void InsertCommand::redo() {
} else { } else {
m_cursor->setPos(m_offset + m_length, m_nibbleindex); m_cursor->setPos(m_offset + m_length, m_nibbleindex);
} }
HexCommand::redo(); }
int InsertCommand::id() const { return UndoID_HexReplaceInsert; }
bool InsertCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = dynamic_cast<const InsertCommand *>(other);
if (ucmd) {
if (this->m_offset + this->m_length == ucmd->m_offset) {
this->m_length += ucmd->m_length;
this->m_data.append(ucmd->m_data);
return true;
}
} else {
auto ucmd = dynamic_cast<const ReplaceCommand *>(other);
if (ucmd) {
if (this->m_offset + this->m_length - 1 == ucmd->m_offset &&
ucmd->m_length == 1 && this->m_nibbleindex == 1 &&
ucmd->m_nibbleindex == 0) {
this->m_data.back() = ucmd->m_data.at(0);
return true;
}
}
}
return false;
} }

View File

@ -24,13 +24,23 @@
#include "hexcommand.h" #include "hexcommand.h"
#include <QCoreApplication>
class InsertCommand : public HexCommand { class InsertCommand : public HexCommand {
Q_DECLARE_TR_FUNCTIONS(InsertCommand)
public: public:
InsertCommand(QHexDocument *doc, QHexCursor *cursor, qsizetype offset, explicit InsertCommand(QHexDocument *doc, QHexCursor *cursor,
const QByteArray &data, int nibbleindex, qsizetype offset, const QByteArray &data,
QUndoCommand *parent = nullptr); int nibbleindex, QUndoCommand *parent = nullptr);
void undo() override;
void redo() override; // QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
}; };
#endif // INSERTCOMMAND_H #endif // INSERTCOMMAND_H

View File

@ -24,7 +24,8 @@
RemoveCommand::RemoveCommand(QHexDocument *doc, qsizetype offset, RemoveCommand::RemoveCommand(QHexDocument *doc, qsizetype offset,
qsizetype length, QHexCursor *cursor, qsizetype length, QHexCursor *cursor,
int nibbleindex, QUndoCommand *parent) int nibbleindex, QUndoCommand *parent)
: HexCommand(doc, cursor, nibbleindex, parent) { : HexCommand(tr("[HexRemove] pos: %1").arg(offset), doc, cursor,
nibbleindex, parent) {
m_offset = offset; m_offset = offset;
m_length = length; m_length = length;
m_data = doc->read(m_offset, m_length); m_data = doc->read(m_offset, m_length);
@ -43,7 +44,6 @@ void RemoveCommand::undo() {
m_cursor->setPos(m_offset, 0); m_cursor->setPos(m_offset, 0);
} }
} }
HexCommand::undo();
} }
void RemoveCommand::redo() { void RemoveCommand::redo() {
@ -51,5 +51,28 @@ void RemoveCommand::redo() {
m_doc->_remove(m_offset, m_length); m_doc->_remove(m_offset, m_length);
_rmbms = m_doc->removeBookMarkAdjust(m_offset, m_length); _rmbms = m_doc->removeBookMarkAdjust(m_offset, m_length);
_rmMetas = m_doc->metadata()->removeAdjust(m_offset, m_length); _rmMetas = m_doc->metadata()->removeAdjust(m_offset, m_length);
HexCommand::redo(); }
int RemoveCommand::id() const { return UndoID_HexRemove; }
bool RemoveCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const RemoveCommand *>(other);
if (ucmd) {
if (this->m_offset == ucmd->m_offset) {
this->m_data.append(ucmd->m_data);
auto bms = ucmd->_rmbms;
for (auto &&b : bms.asKeyValueRange()) {
this->_rmbms.insert(b.first + this->m_length, b.second);
}
auto metas = ucmd->_rmMetas;
for (auto &m : metas) {
m.begin += this->m_length;
m.end += this->m_length;
}
this->_rmMetas.append(ucmd->_rmMetas);
this->m_length += ucmd->m_length;
return true;
}
}
return false;
} }

View File

@ -24,13 +24,21 @@
#include "hexcommand.h" #include "hexcommand.h"
#include <QCoreApplication>
class RemoveCommand : public HexCommand { class RemoveCommand : public HexCommand {
Q_DECLARE_TR_FUNCTIONS(RemoveCommand)
public: public:
RemoveCommand(QHexDocument *doc, qsizetype offset, qsizetype length, explicit RemoveCommand(QHexDocument *doc, qsizetype offset,
QHexCursor *cursor, int nibbleindex, qsizetype length, QHexCursor *cursor,
QUndoCommand *parent = nullptr); int nibbleindex, QUndoCommand *parent = nullptr);
void undo() override; // QUndoCommand interface
void redo() override; public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
private: private:
QVector<QHexMetadataItem> _rmMetas; QVector<QHexMetadataItem> _rmMetas;

View File

@ -25,7 +25,8 @@
ReplaceCommand::ReplaceCommand(QHexDocument *doc, qsizetype offset, ReplaceCommand::ReplaceCommand(QHexDocument *doc, qsizetype offset,
const QByteArray &data, QHexCursor *cursor, const QByteArray &data, QHexCursor *cursor,
int nibbleindex, QUndoCommand *parent) int nibbleindex, QUndoCommand *parent)
: HexCommand(doc, cursor, nibbleindex, parent) { : HexCommand(tr("[HexReplace] pos: %1").arg(offset), doc, cursor,
nibbleindex, parent) {
m_offset = offset; m_offset = offset;
m_data = data; m_data = data;
m_length = data.length(); m_length = data.length();
@ -35,7 +36,6 @@ ReplaceCommand::ReplaceCommand(QHexDocument *doc, qsizetype offset,
void ReplaceCommand::undo() { void ReplaceCommand::undo() {
m_doc->_replace(m_offset, m_olddata); m_doc->_replace(m_offset, m_olddata);
m_cursor->setPos(m_offset, m_nibbleindex); m_cursor->setPos(m_offset, m_nibbleindex);
HexCommand::undo();
} }
void ReplaceCommand::redo() { void ReplaceCommand::redo() {
@ -45,5 +45,48 @@ void ReplaceCommand::redo() {
} else { } else {
m_cursor->setPos(m_offset + m_length, !m_nibbleindex); m_cursor->setPos(m_offset + m_length, !m_nibbleindex);
} }
HexCommand::redo(); }
int ReplaceCommand::id() const { return UndoID_HexReplaceInsert; }
bool ReplaceCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = dynamic_cast<const ReplaceCommand *>(other);
if (ucmd) {
if (this->m_offset == ucmd->m_offset) {
if (this->m_length <= ucmd->m_length) {
this->m_olddata = ucmd->m_olddata;
this->m_data = ucmd->m_data;
this->m_length = ucmd->m_length;
} else {
this->m_data.replace(0, ucmd->m_length, ucmd->m_data);
}
return true;
}
if (this->m_offset + this->m_length == ucmd->m_offset) {
this->m_length += ucmd->m_offset;
this->m_data.append(ucmd->m_data);
this->m_olddata.append(ucmd->m_olddata);
this->m_nibbleindex = ucmd->m_nibbleindex;
return true;
}
if (this->m_offset <= ucmd->m_offset &&
this->m_offset + m_length >= ucmd->m_offset + ucmd->m_length) {
auto dis = ucmd->m_offset - this->m_offset;
this->m_data.replace(dis, ucmd->m_length, ucmd->m_data);
return true;
}
if (this->m_offset >= ucmd->m_offset &&
this->m_offset + m_length <= ucmd->m_offset + ucmd->m_length) {
this->m_offset = ucmd->m_offset;
this->m_data = ucmd->m_data;
this->m_length = ucmd->m_length;
this->m_olddata = ucmd->m_olddata;
this->m_nibbleindex = ucmd->m_nibbleindex;
setText(tr("[HexReplace] pos: %1").arg(this->m_offset));
return true;
}
}
return false;
} }

View File

@ -24,13 +24,23 @@
#include "hexcommand.h" #include "hexcommand.h"
#include <QCoreApplication>
class ReplaceCommand : public HexCommand { class ReplaceCommand : public HexCommand {
Q_DECLARE_TR_FUNCTIONS(ReplaceCommand)
friend class InsertCommand;
public: public:
ReplaceCommand(QHexDocument *doc, qsizetype offset, const QByteArray &data, explicit ReplaceCommand(QHexDocument *doc, qsizetype offset,
QHexCursor *cursor, int nibbleindex, const QByteArray &data, QHexCursor *cursor,
QUndoCommand *parent = nullptr); int nibbleindex, QUndoCommand *parent = nullptr);
void undo() override; // QUndoCommand interface
void redo() override; public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
private: private:
QByteArray m_olddata; QByteArray m_olddata;

View File

@ -24,7 +24,7 @@
MetaAddCommand::MetaAddCommand(QHexMetadata *hexmeta, MetaAddCommand::MetaAddCommand(QHexMetadata *hexmeta,
const QHexMetadataItem &meta, const QHexMetadataItem &meta,
QUndoCommand *parent) QUndoCommand *parent)
: MetaCommand(hexmeta, meta, parent) { : MetaCommand(tr("[MetaAdd]"), hexmeta, meta, parent) {
_brokenMetas = m_hexmeta->mayBrokenMetaData(meta.begin, meta.end); _brokenMetas = m_hexmeta->mayBrokenMetaData(meta.begin, meta.end);
} }
@ -33,6 +33,20 @@ void MetaAddCommand::redo() {
m_meta.background, m_meta.comment); m_meta.background, m_meta.comment);
} }
int MetaAddCommand::id() const { return UndoID_MetaAdd; }
bool MetaAddCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const MetaAddCommand *>(other);
if (ucmd) {
if (this->m_meta.foreground == ucmd->m_meta.foreground &&
this->m_meta.background == ucmd->m_meta.background &&
this->m_meta.comment == ucmd->m_meta.comment) {
return this->m_meta.mergeRegionWithoutMetaCheck(ucmd->m_meta);
}
}
return false;
}
void MetaAddCommand::undo() { void MetaAddCommand::undo() {
m_hexmeta->removeMetadata(m_meta.begin, m_meta.end); m_hexmeta->removeMetadata(m_meta.begin, m_meta.end);
for (auto &meta : _brokenMetas) { for (auto &meta : _brokenMetas) {

View File

@ -23,14 +23,22 @@
#define METAADDCOMMAND_H #define METAADDCOMMAND_H
#include "metacommand.h" #include "metacommand.h"
#include <QCoreApplication>
#include <QObject> #include <QObject>
class MetaAddCommand : public MetaCommand { class MetaAddCommand : public MetaCommand {
Q_DECLARE_TR_FUNCTIONS(MetaAddCommand)
public: public:
MetaAddCommand(QHexMetadata *hexmeta, const QHexMetadataItem &meta, explicit MetaAddCommand(QHexMetadata *hexmeta, const QHexMetadataItem &meta,
QUndoCommand *parent = nullptr); QUndoCommand *parent = nullptr);
void undo() override;
void redo() override; // QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
private: private:
QVector<QHexMetadataItem> _brokenMetas; QVector<QHexMetadataItem> _brokenMetas;

View File

@ -24,8 +24,16 @@
MetaClearCommand::MetaClearCommand(QHexMetadata *hexmeta, MetaClearCommand::MetaClearCommand(QHexMetadata *hexmeta,
const QVector<QHexMetadataItem> &metas, const QVector<QHexMetadataItem> &metas,
QUndoCommand *parent) QUndoCommand *parent)
: QUndoCommand(parent), m_hexmeta(hexmeta), m_metas(metas) {} : UndoCommandBase(tr("[MetaClear]"), parent), m_hexmeta(hexmeta),
m_metas(metas) {}
void MetaClearCommand::redo() { m_hexmeta->clear(); } void MetaClearCommand::redo() { m_hexmeta->clear(); }
int MetaClearCommand::id() const { return UndoID_MetaClear; }
bool MetaClearCommand::mergeWith(const QUndoCommand *other) {
Q_UNUSED(other);
return true;
}
void MetaClearCommand::undo() { m_hexmeta->applyMetas(m_metas); } void MetaClearCommand::undo() { m_hexmeta->applyMetas(m_metas); }

View File

@ -23,21 +23,27 @@
#define METACLEARCOMMAND_H #define METACLEARCOMMAND_H
#include "../../qhexmetadata.h" #include "../../qhexmetadata.h"
#include <QList> #include "../undocommandbase.h"
#include <QObject>
#include <QUndoCommand> #include <QCoreApplication>
#include <QUndoStack> #include <QVector>
// this class is newed by wingsummer // this class is newed by wingsummer
class MetaClearCommand : public QUndoCommand { class MetaClearCommand : public UndoCommandBase {
Q_DECLARE_TR_FUNCTIONS(MetaClearCommand)
public: public:
MetaClearCommand(QHexMetadata *hexmeta, explicit MetaClearCommand(QHexMetadata *hexmeta,
const QVector<QHexMetadataItem> &metas, const QVector<QHexMetadataItem> &metas,
QUndoCommand *parent = nullptr); QUndoCommand *parent = nullptr);
void undo() override; // QUndoCommand interface
void redo() override; public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
protected: protected:
QHexMetadata *m_hexmeta; QHexMetadata *m_hexmeta;

View File

@ -21,6 +21,6 @@
#include "metacommand.h" #include "metacommand.h"
MetaCommand::MetaCommand(QHexMetadata *hexmeta, const QHexMetadataItem &meta, MetaCommand::MetaCommand(const QString &text, QHexMetadata *hexmeta,
QUndoCommand *parent) const QHexMetadataItem &meta, QUndoCommand *parent)
: QUndoCommand(parent), m_hexmeta(hexmeta), m_meta(meta) {} : UndoCommandBase(text, parent), m_hexmeta(hexmeta), m_meta(meta) {}

View File

@ -22,17 +22,16 @@
#ifndef METACOMMAND_H #ifndef METACOMMAND_H
#define METACOMMAND_H #define METACOMMAND_H
#include <QObject>
#include <QUndoCommand>
#include "../../qhexmetadata.h" #include "../../qhexmetadata.h"
#include "../undocommandbase.h"
// this class is newed by wingsummer // this class is newed by wingsummer
class MetaCommand : public QUndoCommand { class MetaCommand : public UndoCommandBase {
public: public:
MetaCommand(QHexMetadata *hexmeta, const QHexMetadataItem &meta, explicit MetaCommand(const QString &text, QHexMetadata *hexmeta,
QUndoCommand *parent = nullptr); const QHexMetadataItem &meta,
QUndoCommand *parent = nullptr);
protected: protected:
QHexMetadata *m_hexmeta; QHexMetadata *m_hexmeta;

View File

@ -24,10 +24,20 @@
MetaRemoveCommand::MetaRemoveCommand(QHexMetadata *hexmeta, MetaRemoveCommand::MetaRemoveCommand(QHexMetadata *hexmeta,
const QHexMetadataItem &meta, const QHexMetadataItem &meta,
QUndoCommand *parent) QUndoCommand *parent)
: MetaCommand(hexmeta, meta, parent) {} : MetaCommand(tr("[MetaRemove]"), hexmeta, meta, parent) {}
void MetaRemoveCommand::redo() { m_hexmeta->removeMetadata(m_meta); } void MetaRemoveCommand::redo() { m_hexmeta->removeMetadata(m_meta); }
int MetaRemoveCommand::id() const { return UndoID_MetaRemove; }
bool MetaRemoveCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const MetaRemoveCommand *>(other);
if (ucmd) {
return this->m_meta == ucmd->m_meta;
}
return false;
}
void MetaRemoveCommand::undo() { void MetaRemoveCommand::undo() {
m_hexmeta->metadata(m_meta.begin, m_meta.end, m_meta.foreground, m_hexmeta->metadata(m_meta.begin, m_meta.end, m_meta.foreground,
m_meta.background, m_meta.comment); m_meta.background, m_meta.comment);

View File

@ -23,18 +23,26 @@
#define METAREMOVECOMMAND_H #define METAREMOVECOMMAND_H
#include "metacommand.h" #include "metacommand.h"
#include <QCoreApplication>
#include <QList> #include <QList>
#include <QObject> #include <QObject>
// this class is newed by wingsummer // this class is newed by wingsummer
class MetaRemoveCommand : public MetaCommand { class MetaRemoveCommand : public MetaCommand {
Q_DECLARE_TR_FUNCTIONS(MetaRemoveCommand)
public: public:
MetaRemoveCommand(QHexMetadata *hexmeta, const QHexMetadataItem &meta, explicit MetaRemoveCommand(QHexMetadata *hexmeta,
QUndoCommand *parent = nullptr); const QHexMetadataItem &meta,
QUndoCommand *parent = nullptr);
void undo() override; // QUndoCommand interface
void redo() override; public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
}; };
#endif // METAREMOVECOMMAND_H #endif // METAREMOVECOMMAND_H

View File

@ -23,16 +23,28 @@
MetaRemovePosCommand::MetaRemovePosCommand(QHexMetadata *hexmeta, qsizetype pos, MetaRemovePosCommand::MetaRemovePosCommand(QHexMetadata *hexmeta, qsizetype pos,
QUndoCommand *parent) QUndoCommand *parent)
: QUndoCommand(parent), m_hexmeta(hexmeta), m_pos(pos) { : MetaCommand(tr("[MetaRemovePos]"), hexmeta, {}, parent), m_pos(pos) {
auto po = m_hexmeta->get(pos); auto po = m_hexmeta->get(pos);
if (po.has_value()) { if (po.has_value()) {
oldmeta = po.value(); m_meta = po.value();
} }
} }
void MetaRemovePosCommand::redo() { m_hexmeta->removeMetadata(m_pos); } void MetaRemovePosCommand::redo() { m_hexmeta->removeMetadata(m_pos); }
void MetaRemovePosCommand::undo() { int MetaRemovePosCommand::id() const { return UndoID_MetaRemovePos; }
m_hexmeta->metadata(oldmeta.begin, oldmeta.end, oldmeta.foreground,
oldmeta.background, oldmeta.comment); bool MetaRemovePosCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const MetaRemovePosCommand *>(other);
if (ucmd) {
if (this->m_pos == ucmd->m_pos) {
return true;
}
}
return false;
}
void MetaRemovePosCommand::undo() {
m_hexmeta->metadata(m_meta.begin, m_meta.end, m_meta.foreground,
m_meta.background, m_meta.comment);
} }

View File

@ -22,24 +22,26 @@
#ifndef METAREMOVEPOSCOMMAND_H #ifndef METAREMOVEPOSCOMMAND_H
#define METAREMOVEPOSCOMMAND_H #define METAREMOVEPOSCOMMAND_H
#include "../../qhexmetadata.h" #include "metacommand.h"
#include <QList>
#include <QObject>
#include <QUndoCommand>
#include <QUndoStack>
class MetaRemovePosCommand : public QUndoCommand { #include <QCoreApplication>
class MetaRemovePosCommand : public MetaCommand {
Q_DECLARE_TR_FUNCTIONS(MetaRemovePosCommand)
public: public:
MetaRemovePosCommand(QHexMetadata *hexmeta, qsizetype pos, explicit MetaRemovePosCommand(QHexMetadata *hexmeta, qsizetype pos,
QUndoCommand *parent = nullptr); QUndoCommand *parent = nullptr);
void undo() override; // QUndoCommand interface
void redo() override; public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
protected: protected:
QHexMetadata *m_hexmeta;
qsizetype m_pos; qsizetype m_pos;
QHexMetadataItem oldmeta;
}; };
#endif // METAREMOVEPOSCOMMAND_H #endif // METAREMOVEPOSCOMMAND_H

View File

@ -25,8 +25,21 @@ MetaReplaceCommand::MetaReplaceCommand(QHexMetadata *hexmeta,
const QHexMetadataItem &meta, const QHexMetadataItem &meta,
const QHexMetadataItem &oldmeta, const QHexMetadataItem &oldmeta,
QUndoCommand *parent) QUndoCommand *parent)
: MetaCommand(hexmeta, meta, parent), m_old(oldmeta) {} : MetaCommand(tr("[MetaReplace]"), hexmeta, meta, parent), m_old(oldmeta) {}
void MetaReplaceCommand::undo() { m_hexmeta->modifyMetadata(m_old, m_meta); } void MetaReplaceCommand::undo() { m_hexmeta->modifyMetadata(m_old, m_meta); }
void MetaReplaceCommand::redo() { m_hexmeta->modifyMetadata(m_meta, m_old); } void MetaReplaceCommand::redo() { m_hexmeta->modifyMetadata(m_meta, m_old); }
int MetaReplaceCommand::id() const { return UndoID_MetaReplace; }
bool MetaReplaceCommand::mergeWith(const QUndoCommand *other) {
auto ucmd = static_cast<const MetaReplaceCommand *>(other);
if (ucmd) {
if (this->m_old == ucmd->m_old) {
this->m_meta = ucmd->m_meta;
return true;
}
}
return false;
}

View File

@ -23,15 +23,24 @@
#define METAREPLACECOMMAND_H #define METAREPLACECOMMAND_H
#include "metacommand.h" #include "metacommand.h"
#include <QCoreApplication>
#include <QObject> #include <QObject>
class MetaReplaceCommand : public MetaCommand { class MetaReplaceCommand : public MetaCommand {
Q_DECLARE_TR_FUNCTIONS(MetaReplaceCommand)
public: public:
MetaReplaceCommand(QHexMetadata *hexmeta, const QHexMetadataItem &meta, explicit MetaReplaceCommand(QHexMetadata *hexmeta,
const QHexMetadataItem &oldmeta, const QHexMetadataItem &meta,
QUndoCommand *parent = nullptr); const QHexMetadataItem &oldmeta,
void undo() override; QUndoCommand *parent = nullptr);
void redo() override;
// QUndoCommand interface
public:
virtual void undo() override;
virtual void redo() override;
virtual int id() const override;
virtual bool mergeWith(const QUndoCommand *other) override;
private: private:
QHexMetadataItem m_old; QHexMetadataItem m_old;

View File

@ -19,12 +19,7 @@
** ============================================================================= ** =============================================================================
*/ */
#include "baseaddrcommand.h" #include "undocommandbase.h"
BaseAddrCommand::BaseAddrCommand(QHexDocument *doc, quint64 oldaddr, UndoCommandBase::UndoCommandBase(const QString &text, QUndoCommand *parent)
quint64 newaddr, QUndoCommand *parent) : QUndoCommand(text, parent) {}
: QUndoCommand(parent), m_doc(doc), m_old(oldaddr), m_new(newaddr) {}
void BaseAddrCommand::redo() { m_doc->setBaseAddress(m_new); }
void BaseAddrCommand::undo() { m_doc->setBaseAddress(m_old); }

View File

@ -19,23 +19,31 @@
** ============================================================================= ** =============================================================================
*/ */
#ifndef BASEADDRCOMMAND_H #ifndef UNDOCOMMANDBASE_H
#define BASEADDRCOMMAND_H #define UNDOCOMMANDBASE_H
#include "document/qhexdocument.h"
#include <QUndoCommand> #include <QUndoCommand>
class BaseAddrCommand : public QUndoCommand { class UndoCommandBase : public QUndoCommand {
public: public:
BaseAddrCommand(QHexDocument *doc, quint64 oldaddr, quint64 newaddr, enum UndoCommandID {
QUndoCommand *parent = nullptr); UndoID_BookMarkAdd,
UndoID_BookMarkClear,
UndoID_BookMarkRemove,
UndoID_BookMarkReplace,
UndoID_HexAppend,
UndoID_HexReplaceInsert,
UndoID_HexRemove,
UndoID_MetaAdd,
UndoID_MetaClear,
UndoID_MetaRemove,
UndoID_MetaRemovePos,
UndoID_MetaReplace
};
void redo() override; public:
void undo() override; explicit UndoCommandBase(const QString &text,
QUndoCommand *parent = nullptr);
private:
QHexDocument *m_doc;
quint64 m_old, m_new;
}; };
#endif // BASEADDRCOMMAND_H #endif // UNDOCOMMANDBASE_H

View File

@ -21,7 +21,6 @@
#include "qhexdocument.h" #include "qhexdocument.h"
#include "buffer/qfilebuffer.h" #include "buffer/qfilebuffer.h"
#include "commands/baseaddrcommand.h"
#include "commands/bookmark/bookmarkaddcommand.h" #include "commands/bookmark/bookmarkaddcommand.h"
#include "commands/bookmark/bookmarkclearcommand.h" #include "commands/bookmark/bookmarkclearcommand.h"
#include "commands/bookmark/bookmarkremovecommand.h" #include "commands/bookmark/bookmarkremovecommand.h"
@ -221,8 +220,6 @@ void QHexDocument::removeBookMarkAdjustRevert(
bool QHexDocument::isDocSaved() { return m_undostack->isClean(); } bool QHexDocument::isDocSaved() { return m_undostack->isClean(); }
bool QHexDocument::isUndoByteModified() { return m_bytesModFlag > 0; }
void QHexDocument::setDocSaved(bool b) { void QHexDocument::setDocSaved(bool b) {
if (b) { if (b) {
m_undostack->setClean(); m_undostack->setClean();
@ -677,20 +674,16 @@ char QHexDocument::at(qsizetype offset) const {
return char(m_buffer->at(offset)); return char(m_buffer->at(offset));
} }
void QHexDocument::SetBaseAddress(quint64 baseaddress) { bool QHexDocument::setBaseAddress(quint64 baseaddress) {
m_undostack->push(new BaseAddrCommand(this, m_baseaddress, baseaddress)); if (m_baseaddress == baseaddress) {
} return false;
}
void QHexDocument::setBaseAddress(quint64 baseaddress) {
if (m_baseaddress == baseaddress)
return;
m_baseaddress = baseaddress; m_baseaddress = baseaddress;
Q_EMIT documentChanged(); Q_EMIT documentChanged();
return true;
} }
void QHexDocument::sync() { Q_EMIT documentChanged(); }
void QHexDocument::undo() { void QHexDocument::undo() {
m_undostack->undo(); m_undostack->undo();
Q_EMIT documentChanged(); Q_EMIT documentChanged();
@ -904,3 +897,5 @@ QHexDocument *QHexDocument::fromLargeFile(const QString &filename,
} }
QHexBuffer *QHexDocument::buffer() const { return m_buffer; } QHexBuffer *QHexDocument::buffer() const { return m_buffer; }
QUndoStack *QHexDocument::undoStack() const { return m_undostack; }

View File

@ -32,8 +32,6 @@
class QHexDocument : public QObject { class QHexDocument : public QObject {
Q_OBJECT Q_OBJECT
friend class HexCommand;
private: private:
explicit QHexDocument(QHexBuffer *buffer, explicit QHexDocument(QHexBuffer *buffer,
bool readonly = false); // modified by wingsummer bool readonly = false); // modified by wingsummer
@ -113,7 +111,6 @@ public:
const std::function<bool()> &pred = [] { return true; }); const std::function<bool()> &pred = [] { return true; });
bool isDocSaved(); bool isDocSaved();
bool isUndoByteModified();
void setDocSaved(bool b = true); void setDocSaved(bool b = true);
void setMetafgVisible(bool b); void setMetafgVisible(bool b);
@ -137,9 +134,7 @@ public:
QByteArray read(qsizetype offset, qsizetype len = -1) const; QByteArray read(qsizetype offset, qsizetype len = -1) const;
char at(qsizetype offset) const; char at(qsizetype offset) const;
void SetBaseAddress(quintptr baseaddress); bool setBaseAddress(quintptr baseaddress);
void setBaseAddress(quintptr baseaddress);
void sync();
public slots: public slots:
void undo(); void undo();
@ -247,6 +242,8 @@ public:
QHexBuffer *buffer() const; QHexBuffer *buffer() const;
QUndoStack *undoStack() const;
signals: signals:
/*================================*/ /*================================*/
@ -277,7 +274,6 @@ private:
QHexMetadata *m_metadata; QHexMetadata *m_metadata;
QUndoStack *m_undostack; QUndoStack *m_undostack;
size_t m_bytesModFlag = 0;
quintptr m_baseaddress; quintptr m_baseaddress;
quint8 m_areaindent; quint8 m_areaindent;

View File

@ -32,37 +32,7 @@
#include <QUndoStack> #include <QUndoStack>
#include <QVector> #include <QVector>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
using qhash_result_t = uint;
// copying from QT6 source code for supporting QT5's qHashMulti
namespace QtPrivate {
template <typename T>
inline constexpr bool QNothrowHashableHelper_v =
noexcept(qHash(std::declval<const T &>()));
template <typename T, typename Enable = void>
struct QNothrowHashable : std::false_type {};
template <typename T>
struct QNothrowHashable<T, std::enable_if_t<QNothrowHashableHelper_v<T>>>
: std::true_type {};
template <typename T>
constexpr inline bool QNothrowHashable_v = QNothrowHashable<T>::value;
} // namespace QtPrivate
template <typename... T>
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;
}
#else
using qhash_result_t = size_t; using qhash_result_t = size_t;
#endif
struct QHexMetadataItem : QHexRegionObject<qsizetype, QHexMetadataItem> { struct QHexMetadataItem : QHexRegionObject<qsizetype, QHexMetadataItem> {
QColor foreground, background; QColor foreground, background;
@ -96,24 +66,7 @@ public:
if (sel.foreground == this->foreground && if (sel.foreground == this->foreground &&
sel.background == this->background && sel.background == this->background &&
sel.comment == this->comment) { sel.comment == this->comment) {
if (canMerge(sel)) { if (mergeRegionWithoutMetaCheck(sel, locker)) {
if (locker) {
locker->lock();
}
if (!this->contains(sel)) {
if (this->begin < sel.end) {
this->begin = qMin(this->begin, next(sel.begin));
this->end = qMax(next(this->end), sel.end);
} else {
this->begin = qMin(next(this->begin), sel.begin);
this->end = qMax(this->end, next(sel.end));
}
}
if (locker) {
locker->unlock();
}
return std::nullopt; return std::nullopt;
} }
return false; return false;
@ -130,6 +83,18 @@ public:
} }
} }
} }
bool mergeRegionWithoutMetaCheck(const QHexMetadataItem &sel,
QMutex *locker = nullptr) {
Q_ASSERT(sel.foreground == this->foreground &&
sel.background == this->background &&
sel.comment == this->comment);
auto ret = Super::mergeRegion(sel, locker);
if (std::holds_alternative<bool>(ret)) {
return std::get<bool>(ret);
}
return false;
}
}; };
inline qhash_result_t qHash(const QHexMetadataItem &c, inline qhash_result_t qHash(const QHexMetadataItem &c,

View File

@ -101,7 +101,7 @@ void QHexView::setHeaderVisible(bool b) {
quintptr QHexView::addressBase() { return m_document->baseAddress(); } quintptr QHexView::addressBase() { return m_document->baseAddress(); }
void QHexView::setAddressBase(quintptr base) { void QHexView::setAddressBase(quintptr base) {
m_document->SetBaseAddress(base); m_document->setBaseAddress(base);
} }
bool QHexView::isSaved() { return m_document->isDocSaved(); } bool QHexView::isSaved() { return m_document->isDocSaved(); }
@ -109,7 +109,7 @@ bool QHexView::isSaved() { return m_document->isDocSaved(); }
QFont QHexView::getHexeditorFont() { QFont QHexView::getHexeditorFont() {
QFont f = QFontDatabase::systemFont(QFontDatabase::FixedFont); QFont f = QFontDatabase::systemFont(QFontDatabase::FixedFont);
if (f.styleHint() != QFont::TypeWriter) { if (f.styleHint() != QFont::TypeWriter) {
f.setFamily("Monospace"); // Force Monospaced font f.setFamily(QStringLiteral("Monospace")); // Force Monospaced font
f.setStyleHint(QFont::TypeWriter); f.setStyleHint(QFont::TypeWriter);
} }
return f; return f;

@ -1 +1 @@
Subproject commit cdaf256c8a44e724cc295e5b23cc291ac2414c02 Subproject commit 3fa9d2ba9d7dd78f719c43b482a5e7f49f135f1c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,20 @@
/*==============================================================================
** 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 "crashhandler.h" #include "crashhandler.h"
#include "angelscript.h" #include "angelscript.h"
#include "class/pluginsystem.h" #include "class/pluginsystem.h"

View File

@ -1,3 +1,20 @@
/*==============================================================================
** 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 "dockcomponentsfactory.h" #include "dockcomponentsfactory.h"
#include "DockWidget.h" #include "DockWidget.h"

View File

@ -1241,11 +1241,11 @@ bool PluginSystem::switchDocument(const QObject *sender, int handle) {
} }
if (handle < 0) { if (handle < 0) {
m_plgCurrentfid[plg] = -1; m_plgviewMap[plg].currentFID = -1;
} else { } else {
auto ctx = pluginContextById(plg, handle); auto ctx = pluginContextById(plg, handle);
if (ctx) { if (ctx) {
m_plgCurrentfid[plg] = handle; m_plgviewMap[plg].currentFID = handle;
} }
} }
return true; return true;
@ -1421,14 +1421,26 @@ bool PluginSystem::beginMarco(const QObject *sender, const QString &txt) {
return false; return false;
} }
auto fid = m_plgCurrentfid[plg]; auto fid = m_plgviewMap[plg].currentFID;
if (fid < 0) { if (fid < 0) {
return false; return false;
} }
auto r = pluginContextById(plg, fid); auto r = pluginContextById(plg, fid);
if (r) { if (r) {
r->cmd = new QUndoCommand(txt); auto &u = m_viewBindings[r->view];
auto rtxt = txt.trimmed();
if (rtxt.isEmpty()) {
rtxt = _pinfos.value(plg).id;
}
if (u.undoStackPlg.isEmpty()) {
u.undoStackPlg.append(qMakePair(new QUndoCommand(rtxt), plg));
} else {
u.undoStackPlg.append(qMakePair(
new QUndoCommand(rtxt, u.undoStackPlg.last().first), plg));
}
} }
return true; return true;
} }
@ -1443,26 +1455,108 @@ bool PluginSystem::endMarco(const QObject *sender) {
return false; return false;
} }
auto fid = m_plgCurrentfid[plg]; auto fid = m_plgviewMap[plg].currentFID;
if (fid < 0) { if (fid < 0) {
return false; return false;
} }
auto r = pluginContextById(plg, fid); auto r = pluginContextById(plg, fid);
if (r) { if (r) {
if (r->cmd) { auto &u = m_viewBindings[r->view];
auto e = pluginCurrentEditor(plg); auto &undo = u.undoStackPlg;
if (e) {
if (undo.isEmpty()) {
return false;
} else {
auto &l = undo.last();
if (l.second != plg) {
return false;
}
auto r = std::find_if(
undo.rbegin(), undo.rend(),
[plg](const QPair<QUndoCommand *, IWingPlugin *> &ctx) {
return ctx.second == plg;
});
if (r == undo.rend()) {
return false;
}
if (r != undo.rbegin()) {
Logger::warning(tr("UnexpectedUndoCmdPushDetected"));
undo.erase(r.base(), undo.end());
}
auto cmdl = undo.takeLast();
if (undo.isEmpty()) {
auto e = pluginCurrentEditor(plg);
if (e == nullptr) {
return false;
}
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
doc->pushMakeUndo(r->cmd); doc->pushMakeUndo(cmdl.first);
r->cmd = nullptr;
return true; return true;
} }
return true;
} }
} }
return false; return false;
} }
bool PluginSystem::isMacroEmpty(const QObject *sender) {
auto plg = checkPluginAndReport(sender, __func__);
if (plg == nullptr) {
return true;
}
if (passByFailedGuard(sender, __func__, {})) {
return true;
}
auto fid = m_plgviewMap[plg].currentFID;
if (fid < 0) {
return true;
}
auto r = pluginContextById(plg, fid);
if (r) {
auto &u = m_viewBindings[r->view];
auto &undo = u.undoStackPlg;
return undo.isEmpty();
}
return true;
}
bool PluginSystem::resetMarco(const QObject *sender) {
auto plg = checkPluginAndReport(sender, __func__);
if (plg == nullptr) {
return false;
}
if (passByFailedGuard(sender, __func__, {})) {
return false;
}
auto fid = m_plgviewMap[plg].currentFID;
if (fid < 0) {
return false;
}
auto r = pluginContextById(plg, fid);
if (r) {
auto &u = m_viewBindings[r->view];
auto &undo = u.undoStackPlg;
if (!undo.isEmpty()) {
delete undo.first().first;
undo.clear();
}
return true;
}
return false;
}
bool PluginSystem::writeInt8(const QObject *sender, qsizetype offset, bool PluginSystem::writeInt8(const QObject *sender, qsizetype offset,
qint8 value) { qint8 value) {
auto plg = checkPluginAndReport(sender, __func__); auto plg = checkPluginAndReport(sender, __func__);
@ -1620,7 +1714,7 @@ bool PluginSystem::writeString(const QObject *sender, qsizetype offset,
auto doc = editor->document(); auto doc = editor->document();
auto unicode = Utilities::encodingString(value, encoding); auto unicode = Utilities::encodingString(value, encoding);
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeReplace(uc, editor->cursor(), offset, unicode); auto cmd = doc->MakeReplace(uc, editor->cursor(), offset, unicode);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -1647,7 +1741,7 @@ bool PluginSystem::writeBytes(const QObject *sender, qsizetype offset,
if (e) { if (e) {
auto editor = e->hexEditor(); auto editor = e->hexEditor();
auto doc = editor->document(); auto doc = editor->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeReplace(uc, editor->cursor(), offset, data); auto cmd = doc->MakeReplace(uc, editor->cursor(), offset, data);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -1816,7 +1910,7 @@ bool PluginSystem::insertString(const QObject *sender, qsizetype offset,
auto doc = editor->document(); auto doc = editor->document();
auto unicode = Utilities::encodingString(value, encoding); auto unicode = Utilities::encodingString(value, encoding);
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, unicode); auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, unicode);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -1843,7 +1937,7 @@ bool PluginSystem::insertBytes(const QObject *sender, qsizetype offset,
if (e) { if (e) {
auto editor = e->hexEditor(); auto editor = e->hexEditor();
auto doc = editor->document(); auto doc = editor->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, data); auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, data);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -1998,7 +2092,7 @@ bool PluginSystem::appendString(const QObject *sender, const QString &value,
auto offset = doc->length(); auto offset = doc->length();
auto unicode = Utilities::encodingString(value, encoding); auto unicode = Utilities::encodingString(value, encoding);
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, unicode); auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, unicode);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -2024,7 +2118,7 @@ bool PluginSystem::appendBytes(const QObject *sender, const QByteArray &data) {
if (e) { if (e) {
auto editor = e->hexEditor(); auto editor = e->hexEditor();
auto doc = editor->document(); auto doc = editor->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeAppend(uc, editor->cursor(), data); auto cmd = doc->MakeAppend(uc, editor->cursor(), data);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -2052,7 +2146,7 @@ bool PluginSystem::removeBytes(const QObject *sender, qsizetype offset,
auto editor = e->hexEditor(); auto editor = e->hexEditor();
auto doc = editor->document(); auto doc = editor->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeRemove(uc, editor->cursor(), offset, len); auto cmd = doc->MakeRemove(uc, editor->cursor(), offset, len);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
_rwlock.lockForWrite(); _rwlock.lockForWrite();
@ -2195,7 +2289,7 @@ bool PluginSystem::metadata(const QObject *sender, qsizetype begin,
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->metadata()->MakeMetadata(uc, begin, begin + length - 1, auto cmd = doc->metadata()->MakeMetadata(uc, begin, begin + length - 1,
fgcolor, bgcolor, comment); fgcolor, bgcolor, comment);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
@ -2223,7 +2317,7 @@ bool PluginSystem::removeMetadata(const QObject *sender, qsizetype offset) {
auto e = pluginCurrentEditor(plg); auto e = pluginCurrentEditor(plg);
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->metadata()->MakeRemoveMetadata(uc, offset); auto cmd = doc->metadata()->MakeRemoveMetadata(uc, offset);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
doc->pushMakeUndo(cmd); doc->pushMakeUndo(cmd);
@ -2250,7 +2344,7 @@ bool PluginSystem::clearMetadata(const QObject *sender) {
auto e = pluginCurrentEditor(plg); auto e = pluginCurrentEditor(plg);
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->metadata()->MakeClear(uc); auto cmd = doc->metadata()->MakeClear(uc);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
doc->pushMakeUndo(cmd); doc->pushMakeUndo(cmd);
@ -2372,7 +2466,7 @@ bool PluginSystem::addBookMark(const QObject *sender, qsizetype pos,
auto e = pluginCurrentEditor(plg); auto e = pluginCurrentEditor(plg);
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeAddBookMark(uc, pos, comment); auto cmd = doc->MakeAddBookMark(uc, pos, comment);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
doc->pushMakeUndo(cmd); doc->pushMakeUndo(cmd);
@ -2400,7 +2494,7 @@ bool PluginSystem::modBookMark(const QObject *sender, qsizetype pos,
auto e = pluginCurrentEditor(plg); auto e = pluginCurrentEditor(plg);
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeModBookMark(uc, pos, comment); auto cmd = doc->MakeModBookMark(uc, pos, comment);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
doc->pushMakeUndo(cmd); doc->pushMakeUndo(cmd);
@ -2427,7 +2521,7 @@ bool PluginSystem::removeBookMark(const QObject *sender, qsizetype pos) {
auto e = pluginCurrentEditor(plg); auto e = pluginCurrentEditor(plg);
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeRemoveBookMark(uc, pos); auto cmd = doc->MakeRemoveBookMark(uc, pos);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
doc->pushMakeUndo(cmd); doc->pushMakeUndo(cmd);
@ -2454,7 +2548,7 @@ bool PluginSystem::clearBookMark(const QObject *sender) {
auto e = pluginCurrentEditor(plg); auto e = pluginCurrentEditor(plg);
if (e) { if (e) {
auto doc = e->hexEditor()->document(); auto doc = e->hexEditor()->document();
auto uc = pluginCurrentUndoCmd(plg); auto uc = currentUndoCmd(e);
auto cmd = doc->MakeClearBookMark(uc); auto cmd = doc->MakeClearBookMark(uc);
if (uc == nullptr && cmd) { if (uc == nullptr && cmd) {
doc->pushMakeUndo(cmd); doc->pushMakeUndo(cmd);
@ -2478,11 +2572,12 @@ bool PluginSystem::closeAllFiles(const QObject *sender) {
return false; return false;
} }
auto &maps = m_plgviewMap[plg]; auto &map = m_plgviewMap[plg];
auto &maps = map.contexts;
for (auto &item : maps) { for (auto &item : maps) {
closeEditor(plg, getUIDHandle(item->fid), true); closeEditor(plg, getUIDHandle(item->fid), true);
} }
m_plgCurrentfid[plg] = -1; map.currentFID = -1;
maps.clear(); maps.clear();
return true; return true;
} }
@ -2690,7 +2785,7 @@ ErrFile PluginSystem::closeCurrent(const QObject *sender, bool force) {
return _win->closeEditor(view, force); return _win->closeEditor(view, force);
} }
ErrFile PluginSystem::openCurrent(const QObject *sender) { int PluginSystem::openCurrent(const QObject *sender) {
if (!checkThreadAff()) { if (!checkThreadAff()) {
return ErrFile::NotAllowedInNoneGUIThread; return ErrFile::NotAllowedInNoneGUIThread;
} }
@ -2710,16 +2805,14 @@ ErrFile PluginSystem::openCurrent(const QObject *sender) {
return ErrFile::AlreadyOpened; return ErrFile::AlreadyOpened;
} }
auto id = assginHandleForPluginView(plg, view); auto id = assginHandleForOpenPluginView(plg, view);
auto handle = getUIDHandle(id);
m_plgCurrentfid[plg] = handle;
PluginSystem::instance().dispatchEvent( PluginSystem::instance().dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileOpened, IWingPlugin::RegisteredEvent::PluginFileOpened,
{quintptr(plg), view->fileName(), handle, {quintptr(plg), view->fileName(), id,
QVariant::fromValue(_win->getEditorViewFileType(view))}); QVariant::fromValue(_win->getEditorViewFileType(view))});
return ErrFile(handle); return id;
} }
return ErrFile::Error; return ErrFile::Error;
} }
@ -2778,8 +2871,8 @@ ErrFile PluginSystem::exportFile(const QObject *sender, int handle,
return ErrFile::NotExist; return ErrFile::NotExist;
} }
ErrFile PluginSystem::openWorkSpace(const QObject *sender, int PluginSystem::openWorkSpace(const QObject *sender,
const QString &filename) { const QString &filename) {
if (!checkThreadAff()) { if (!checkThreadAff()) {
return ErrFile::NotAllowedInNoneGUIThread; return ErrFile::NotAllowedInNoneGUIThread;
} }
@ -2803,16 +2896,14 @@ ErrFile PluginSystem::openWorkSpace(const QObject *sender,
checkPluginHasAlreadyOpened(plg, view)) { checkPluginHasAlreadyOpened(plg, view)) {
return ErrFile::AlreadyOpened; return ErrFile::AlreadyOpened;
} }
auto id = assginHandleForPluginView(plg, view); auto id = assginHandleForOpenPluginView(plg, view);
auto handle = getUIDHandle(id);
m_plgCurrentfid[plg] = handle;
PluginSystem::instance().dispatchEvent( PluginSystem::instance().dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileOpened, IWingPlugin::RegisteredEvent::PluginFileOpened,
{quintptr(plg), filename, handle, {quintptr(plg), filename, id,
QVariant::fromValue(_win->getEditorViewFileType(view))}); QVariant::fromValue(_win->getEditorViewFileType(view))});
return ErrFile(handle); return id;
} else { } else {
return ret; return ret;
} }
@ -2884,8 +2975,8 @@ ErrFile PluginSystem::closeHandle(const QObject *sender, int handle) {
return WingHex::ErrFile::NotExist; return WingHex::ErrFile::NotExist;
} }
ErrFile PluginSystem::openExtFile(const QObject *sender, const QString &ext, int PluginSystem::openExtFile(const QObject *sender, const QString &ext,
const QString &file) { const QString &file) {
if (!checkThreadAff()) { if (!checkThreadAff()) {
return ErrFile::NotAllowedInNoneGUIThread; return ErrFile::NotAllowedInNoneGUIThread;
} }
@ -2909,22 +3000,20 @@ ErrFile PluginSystem::openExtFile(const QObject *sender, const QString &ext,
checkPluginHasAlreadyOpened(plg, view)) { checkPluginHasAlreadyOpened(plg, view)) {
return ErrFile::AlreadyOpened; return ErrFile::AlreadyOpened;
} }
auto id = assginHandleForPluginView(plg, view); auto id = assginHandleForOpenPluginView(plg, view);
auto handle = getUIDHandle(id);
m_plgCurrentfid[plg] = handle;
PluginSystem::instance().dispatchEvent( PluginSystem::instance().dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileOpened, IWingPlugin::RegisteredEvent::PluginFileOpened,
{quintptr(plg), file, handle, {quintptr(plg), file, id,
QVariant::fromValue(_win->getEditorViewFileType(view))}); QVariant::fromValue(_win->getEditorViewFileType(view))});
return ErrFile(handle); return id;
} else { } else {
return ret; return ret;
} }
} }
ErrFile PluginSystem::openFile(const QObject *sender, const QString &filename) { int PluginSystem::openFile(const QObject *sender, const QString &filename) {
if (!checkThreadAff()) { if (!checkThreadAff()) {
return ErrFile::NotAllowedInNoneGUIThread; return ErrFile::NotAllowedInNoneGUIThread;
} }
@ -2948,21 +3037,19 @@ ErrFile PluginSystem::openFile(const QObject *sender, const QString &filename) {
checkPluginHasAlreadyOpened(plg, view)) { checkPluginHasAlreadyOpened(plg, view)) {
return ErrFile::AlreadyOpened; return ErrFile::AlreadyOpened;
} }
auto id = assginHandleForPluginView(plg, view); auto id = assginHandleForOpenPluginView(plg, view);
auto handle = getUIDHandle(id);
m_plgCurrentfid[plg] = handle;
PluginSystem::instance().dispatchEvent( PluginSystem::instance().dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileOpened, IWingPlugin::RegisteredEvent::PluginFileOpened,
{quintptr(plg), filename, handle, {quintptr(plg), filename, id,
QVariant::fromValue(_win->getEditorViewFileType(view))}); QVariant::fromValue(_win->getEditorViewFileType(view))});
return ErrFile(handle); return id;
} else { } else {
return ret; return ret;
} }
} }
ErrFile PluginSystem::newFile(const QObject *sender) { int PluginSystem::newFile(const QObject *sender) {
if (!checkThreadAff()) { if (!checkThreadAff()) {
return ErrFile::NotAllowedInNoneGUIThread; return ErrFile::NotAllowedInNoneGUIThread;
} }
@ -2981,18 +3068,17 @@ ErrFile PluginSystem::newFile(const QObject *sender) {
} }
auto view = _win->newfileGUI(); auto view = _win->newfileGUI();
if (view) { if (view) {
auto id = assginHandleForPluginView(plg, view); auto id = assginHandleForOpenPluginView(plg, view);
auto handle = getUIDHandle(id); m_plgviewMap[plg].currentFID = id;
m_plgCurrentfid[plg] = handle;
PluginSystem::instance().dispatchEvent( PluginSystem::instance().dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileOpened, IWingPlugin::RegisteredEvent::PluginFileOpened,
{quintptr(plg), {quintptr(plg),
{}, {},
handle, id,
QVariant::fromValue(_win->getEditorViewFileType(view))}); QVariant::fromValue(_win->getEditorViewFileType(view))});
return ErrFile(handle); return id;
} else { } else {
return ErrFile::Error; return ErrFile::Error;
} }
@ -3196,11 +3282,8 @@ EditorView *PluginSystem::getCurrentPluginView(IWingPlugin *plg) {
if (plg == nullptr) { if (plg == nullptr) {
return nullptr; return nullptr;
} }
if (!m_plgCurrentfid.contains(plg)) {
m_plgCurrentfid.insert(plg, -1);
}
auto fid = m_plgCurrentfid[plg]; auto fid = m_plgviewMap[plg].currentFID;
auto ctx = pluginContextById(plg, fid); auto ctx = pluginContextById(plg, fid);
if (ctx) { if (ctx) {
return ctx->view; return ctx->view;
@ -3236,8 +3319,8 @@ void PluginSystem::retranslateMetadata(IWingPluginBase *plg, PluginInfo &meta) {
meta.license = plg->retranslate(meta.license); meta.license = plg->retranslate(meta.license);
} }
PluginSystem::SharedUniqueId int PluginSystem::assginHandleForOpenPluginView(IWingPlugin *plg,
PluginSystem::assginHandleForPluginView(IWingPlugin *plg, EditorView *view) { EditorView *view) {
if (plg == nullptr || view == nullptr) { if (plg == nullptr || view == nullptr) {
return {}; return {};
} }
@ -3249,9 +3332,13 @@ PluginSystem::assginHandleForPluginView(IWingPlugin *plg, EditorView *view) {
context->linkedplg = plg; context->linkedplg = plg;
context->view = view; context->view = view;
m_plgviewMap[plg].append(context); auto handle = getUIDHandle(id);
m_viewBindings[view].append(plg);
return id; m_plgviewMap[plg].currentFID = handle;
m_plgviewMap[plg].contexts.append(context);
m_viewBindings[view].linkedplg.append(plg);
return handle;
} }
PluginInfo PluginSystem::parsePluginMetadata(const QJsonObject &meta) { PluginInfo PluginSystem::parsePluginMetadata(const QJsonObject &meta) {
@ -3329,12 +3416,12 @@ bool PluginSystem::checkPluginCanOpenedFile(IWingPlugin *plg) {
if (plg == nullptr) { if (plg == nullptr) {
return false; return false;
} }
return m_plgviewMap[plg].size() <= UCHAR_MAX; return m_plgviewMap[plg].contexts.size() <= UCHAR_MAX;
} }
bool PluginSystem::checkPluginHasAlreadyOpened(IWingPlugin *plg, bool PluginSystem::checkPluginHasAlreadyOpened(IWingPlugin *plg,
EditorView *view) { EditorView *view) {
auto &maps = m_plgviewMap[plg]; auto &maps = m_plgviewMap[plg].contexts;
auto ret = auto ret =
std::find_if(maps.begin(), maps.end(), std::find_if(maps.begin(), maps.end(),
[view](const QSharedPointer<PluginFileContext> &content) { [view](const QSharedPointer<PluginFileContext> &content) {
@ -3348,35 +3435,15 @@ void PluginSystem::cleanUpEditorViewHandle(EditorView *view) {
auto v = m_viewBindings[view]; auto v = m_viewBindings[view];
// clean up // clean up
for (auto &plg : v) { for (auto &plg : v.linkedplg) {
auto &handles = m_plgviewMap[plg]; auto &handles = m_plgviewMap[plg];
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) auto id = handles.currentFID;
handles.erase(std::remove_if( handles.contexts.removeIf(
handles.begin(), handles.end(), [view, this, id,
[view, this](const QSharedPointer<PluginFileContext> &v) { plg](const QSharedPointer<PluginFileContext> &v) {
if (v->view == view) { if (v->view == view) {
if (equalCompareHandle(v->fid, if (equalCompareHandle(v->fid, id)) {
m_plgCurrentfid[v->linkedplg])) { m_plgviewMap[plg].currentFID = -1;
m_plgCurrentfid[v->linkedplg] = -1;
}
dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileClosed,
{quintptr(v->linkedplg), v->view->fileName(),
getUIDHandle(v->fid),
QVariant::fromValue(
_win->getEditorViewFileType(view))});
return true;
}
return false;
}));
#else
handles.removeIf(
[view, this](const QSharedPointer<PluginFileContext> &v) {
if (v->view == view) {
if (equalCompareHandle(v->fid,
m_plgCurrentfid[v->linkedplg])) {
m_plgCurrentfid[v->linkedplg] = -1;
} }
dispatchEvent( dispatchEvent(
IWingPlugin::RegisteredEvent::PluginFileClosed, IWingPlugin::RegisteredEvent::PluginFileClosed,
@ -3388,7 +3455,6 @@ void PluginSystem::cleanUpEditorViewHandle(EditorView *view) {
} }
return false; return false;
}); });
#endif
} }
m_viewBindings.remove(view); m_viewBindings.remove(view);
} }
@ -3396,7 +3462,8 @@ void PluginSystem::cleanUpEditorViewHandle(EditorView *view) {
bool PluginSystem::closeEditor(IWingPlugin *plg, int handle, bool force) { bool PluginSystem::closeEditor(IWingPlugin *plg, int handle, bool force) {
if (handle >= 0) { if (handle >= 0) {
auto &handles = m_plgviewMap[plg]; auto &vm = m_plgviewMap[plg];
auto &handles = vm.contexts;
auto r = std::find_if( auto r = std::find_if(
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
handles.cbegin(), handles.cend(), handles.cbegin(), handles.cend(),
@ -3411,15 +3478,16 @@ bool PluginSystem::closeEditor(IWingPlugin *plg, int handle, bool force) {
} }
auto sharedc = *r; auto sharedc = *r;
auto &bind = m_viewBindings[sharedc->view]; auto &vb = m_viewBindings[sharedc->view];
auto &bind = vb.linkedplg;
bind.removeOne(plg); bind.removeOne(plg);
if (bind.isEmpty()) { if (bind.isEmpty()) {
_win->closeEditor(sharedc->view, force); _win->closeEditor(sharedc->view, force);
m_viewBindings.remove(sharedc->view); m_viewBindings.remove(sharedc->view);
} }
if (m_plgCurrentfid[plg] == handle) { if (vm.currentFID == handle) {
m_plgCurrentfid[plg] = -1; vm.currentFID = -1;
} }
handles.erase(r); handles.erase(r);
@ -3434,7 +3502,8 @@ bool PluginSystem::closeHandle(IWingPlugin *plg, int handle) {
if (handle < 0) { if (handle < 0) {
return false; return false;
} }
auto &handles = m_plgviewMap[plg]; auto &vm = m_plgviewMap[plg];
auto &handles = vm.contexts;
auto r = std::find_if( auto r = std::find_if(
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
handles.cbegin(), handles.cend(), handles.cbegin(), handles.cend(),
@ -3449,14 +3518,14 @@ bool PluginSystem::closeHandle(IWingPlugin *plg, int handle) {
} }
auto sharedc = *r; auto sharedc = *r;
auto &bind = m_viewBindings[sharedc->view]; auto &bind = m_viewBindings[sharedc->view].linkedplg;
bind.removeOne(plg); bind.removeOne(plg);
if (bind.isEmpty()) { if (bind.isEmpty()) {
m_viewBindings.remove(sharedc->view); m_viewBindings.remove(sharedc->view);
} }
if (m_plgCurrentfid[plg] == handle) { if (vm.currentFID == handle) {
m_plgCurrentfid[plg] = -1; vm.currentFID = -1;
} }
handles.erase(r); handles.erase(r);
return true; return true;
@ -3949,7 +4018,6 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta,
// prepare for file contenxt // prepare for file contenxt
m_plgviewMap.insert(p, {}); m_plgviewMap.insert(p, {});
m_plgCurrentfid.insert(p, -1);
} catch (const QString &error) { } catch (const QString &error) {
Logger::critical(error); Logger::critical(error);
if (p_tr) { if (p_tr) {
@ -4323,7 +4391,7 @@ void PluginSystem::destory() {
EditorView *PluginSystem::pluginCurrentEditor(IWingPlugin *plg) const { EditorView *PluginSystem::pluginCurrentEditor(IWingPlugin *plg) const {
if (plg) { if (plg) {
auto fid = m_plgCurrentfid[plg]; auto fid = m_plgviewMap[plg].currentFID;
if (fid < 0) { if (fid < 0) {
return _win->currentEditor(); return _win->currentEditor();
} }
@ -4336,12 +4404,23 @@ EditorView *PluginSystem::pluginCurrentEditor(IWingPlugin *plg) const {
return nullptr; return nullptr;
} }
QUndoCommand *PluginSystem::currentUndoCmd(EditorView *view) {
if (m_viewBindings.contains(view)) {
auto &vb = m_viewBindings[view];
auto &undo = vb.undoStackPlg;
if (!undo.isEmpty()) {
return undo.last().first;
}
}
return nullptr;
}
QSharedPointer<PluginSystem::PluginFileContext> QSharedPointer<PluginSystem::PluginFileContext>
PluginSystem::pluginContextById(IWingPlugin *plg, int fid) const { PluginSystem::pluginContextById(IWingPlugin *plg, int fid) const {
if (fid < 0) { if (fid < 0) {
return nullptr; return nullptr;
} }
auto &handles = m_plgviewMap[plg]; auto &handles = m_plgviewMap[plg].contexts;
auto r = std::find_if(handles.begin(), handles.end(), auto r = std::find_if(handles.begin(), handles.end(),
[fid](const QSharedPointer<PluginFileContext> &d) { [fid](const QSharedPointer<PluginFileContext> &d) {
return equalCompareHandle(d->fid, fid); return equalCompareHandle(d->fid, fid);
@ -4351,18 +4430,3 @@ PluginSystem::pluginContextById(IWingPlugin *plg, int fid) const {
} }
return *r; return *r;
} }
QUndoCommand *PluginSystem::pluginCurrentUndoCmd(IWingPlugin *plg) const {
if (plg) {
auto fid = m_plgCurrentfid[plg];
if (fid < 0) {
return nullptr;
}
auto ctx = pluginContextById(plg, fid);
if (ctx) {
return ctx->cmd;
}
}
return nullptr;
}

View File

@ -118,12 +118,22 @@ private:
SharedUniqueId fid; SharedUniqueId fid;
EditorView *view = nullptr; EditorView *view = nullptr;
IWingPlugin *linkedplg = nullptr; IWingPlugin *linkedplg = nullptr;
QUndoCommand *cmd = nullptr; };
~PluginFileContext() { struct PluginFile {
if (cmd) { QVector<QSharedPointer<PluginFileContext>> contexts;
delete cmd; int currentFID = -1;
};
struct ViewBind {
QList<IWingPlugin *> linkedplg;
QList<QPair<QUndoCommand *, IWingPlugin *>> undoStackPlg;
~ViewBind() {
if (!undoStackPlg.isEmpty()) {
delete undoStackPlg.first().first;
} }
undoStackPlg.clear();
} }
}; };
@ -194,8 +204,7 @@ private:
EditorView *handle2EditorView(IWingPlugin *plg, int handle); EditorView *handle2EditorView(IWingPlugin *plg, int handle);
SharedUniqueId assginHandleForPluginView(IWingPlugin *plg, int assginHandleForOpenPluginView(IWingPlugin *plg, EditorView *view);
EditorView *view);
static bool equalCompareHandle(const SharedUniqueId &id, int handle); static bool equalCompareHandle(const SharedUniqueId &id, int handle);
@ -226,7 +235,7 @@ private:
QSharedPointer<PluginFileContext> pluginContextById(IWingPlugin *plg, QSharedPointer<PluginFileContext> pluginContextById(IWingPlugin *plg,
int fid) const; int fid) const;
QUndoCommand *pluginCurrentUndoCmd(IWingPlugin *plg) const; QUndoCommand *currentUndoCmd(EditorView *view);
private: private:
void loadPlugin(IWingPlugin *p, PluginInfo &meta, void loadPlugin(IWingPlugin *p, PluginInfo &meta,
@ -274,7 +283,7 @@ private:
auto e = getCurrentPluginView(plg); auto e = getCurrentPluginView(plg);
if (e) { if (e) {
return EditorView::insertBasicTypeContent<T>( return EditorView::insertBasicTypeContent<T>(
e, offset, value, pluginCurrentUndoCmd(plg), _rwlock); e, offset, value, currentUndoCmd(e), _rwlock);
} }
return false; return false;
} }
@ -286,7 +295,7 @@ private:
auto e = getCurrentPluginView(plg); auto e = getCurrentPluginView(plg);
if (e) { if (e) {
return EditorView::writeBasicTypeContent<T>( return EditorView::writeBasicTypeContent<T>(
e, offset, value, pluginCurrentUndoCmd(plg), _rwlock); e, offset, value, currentUndoCmd(e), _rwlock);
} }
return false; return false;
} }
@ -297,7 +306,7 @@ private:
auto e = getCurrentPluginView(plg); auto e = getCurrentPluginView(plg);
if (e) { if (e) {
return EditorView::appendBasicTypeContent<T>( return EditorView::appendBasicTypeContent<T>(
e, value, pluginCurrentUndoCmd(plg), _rwlock); e, value, currentUndoCmd(e), _rwlock);
} }
return false; return false;
} }
@ -518,6 +527,10 @@ public slots:
WING_API bool endMarco(const QObject *sender); WING_API bool endMarco(const QObject *sender);
WING_API bool isMacroEmpty(const QObject *sender);
WING_API bool resetMarco(const QObject *sender);
WING_API bool writeInt8(const QObject *sender, qsizetype offset, WING_API bool writeInt8(const QObject *sender, qsizetype offset,
qint8 value); qint8 value);
@ -648,16 +661,14 @@ public slots:
WING_API bool setMetaCommentVisible(const QObject *sender, bool b); WING_API bool setMetaCommentVisible(const QObject *sender, bool b);
// mainwindow // mainwindow
WING_API WingHex::ErrFile newFile(const QObject *sender); WING_API int newFile(const QObject *sender);
WING_API WingHex::ErrFile openFile(const QObject *sender, WING_API int openFile(const QObject *sender, const QString &filename);
const QString &filename);
WING_API WingHex::ErrFile WING_API int openExtFile(const QObject *sender, const QString &ext,
openExtFile(const QObject *sender, const QString &ext, const QString &file); const QString &file);
WING_API WingHex::ErrFile openWorkSpace(const QObject *sender, WING_API int openWorkSpace(const QObject *sender, const QString &filename);
const QString &filename);
WING_API WingHex::ErrFile closeHandle(const QObject *sender, int handle); WING_API WingHex::ErrFile closeHandle(const QObject *sender, int handle);
@ -672,7 +683,7 @@ public slots:
WING_API WingHex::ErrFile saveAsFile(const QObject *sender, int handle, WING_API WingHex::ErrFile saveAsFile(const QObject *sender, int handle,
const QString &savename); const QString &savename);
WING_API WingHex::ErrFile openCurrent(const QObject *sender); WING_API int openCurrent(const QObject *sender);
WING_API WingHex::ErrFile closeCurrent(const QObject *sender, bool force); WING_API WingHex::ErrFile closeCurrent(const QObject *sender, bool force);
@ -729,10 +740,8 @@ private:
QMap<IWingPlugin::RegisteredEvent, QList<IWingPlugin *>> _evplgs; QMap<IWingPlugin::RegisteredEvent, QList<IWingPlugin *>> _evplgs;
QHash<IWingPlugin *, QVector<QSharedPointer<PluginFileContext>>> QHash<IWingPlugin *, PluginFile> m_plgviewMap;
m_plgviewMap; QHash<EditorView *, ViewBind> m_viewBindings;
QHash<IWingPlugin *, int> m_plgCurrentfid; // fid
QHash<EditorView *, QList<IWingPlugin *>> m_viewBindings;
UniqueIdGenerator m_idGen; UniqueIdGenerator m_idGen;

View File

@ -722,6 +722,12 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
registerAPI(engine, registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, endMarco, (void), bool), asMETHODPR(WingHex::IWingPlugin, endMarco, (void), bool),
"bool endMarco()"); "bool endMarco()");
registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, isMacroEmpty, (void), bool),
"bool isMacroEmpty()");
registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, resetMarco, (void), bool),
"bool resetMarco()");
registerAPI( registerAPI(
engine, engine,
@ -948,20 +954,18 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
asMETHODPR(WingHex::IWingPlugin, setMetaCommentVisible, (bool), bool), asMETHODPR(WingHex::IWingPlugin, setMetaCommentVisible, (bool), bool),
"bool setMetaCommentVisible(bool b)"); "bool setMetaCommentVisible(bool b)");
registerAPI(engine, registerAPI(engine, asMETHODPR(WingHex::IWingPlugin, newFile, (), int),
asMETHODPR(WingHex::IWingPlugin, newFile, (), WingHex::ErrFile), "int newFile()");
"ErrFile newFile()");
registerAPI(engine, registerAPI(
asMETHODPR(WingHex::IWingPlugin, openFile, (const QString &), engine,
WingHex::ErrFile), asMETHODPR(WingHex::IWingPlugin, openFile, (const QString &), int),
"ErrFile openFile(string &in filename)"); "int openFile(string &in filename)");
registerAPI(engine, registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, openExtFile, asMETHODPR(WingHex::IWingPlugin, openExtFile,
(const QString &, const QString &), (const QString &, const QString &), int),
WingHex::ErrFile), "int openExtFile(string &in ext, string &in file)");
"ErrFile openExtFile(string &in ext, string &in file)");
registerAPI(engine, registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, closeFile, (int, bool), asMETHODPR(WingHex::IWingPlugin, closeFile, (int, bool),
@ -988,10 +992,8 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
(int, const QString &), WingHex::ErrFile), (int, const QString &), WingHex::ErrFile),
"ErrFile saveAsFile(int handle, string &in savename)"); "ErrFile saveAsFile(int handle, string &in savename)");
registerAPI( registerAPI(engine, asMETHODPR(WingHex::IWingPlugin, openCurrent, (), int),
engine, "int openCurrent()");
asMETHODPR(WingHex::IWingPlugin, openCurrent, (), WingHex::ErrFile),
"ErrFile openCurrent()");
registerAPI(engine, registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, closeCurrent, (bool), asMETHODPR(WingHex::IWingPlugin, closeCurrent, (bool),
@ -1027,10 +1029,10 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) {
asMETHODPR(WingHex::IWingPlugin, clearBookMark, (), bool), asMETHODPR(WingHex::IWingPlugin, clearBookMark, (), bool),
"bool clearBookMark()"); "bool clearBookMark()");
registerAPI(engine, registerAPI(
asMETHODPR(WingHex::IWingPlugin, openWorkSpace, engine,
(const QString &), WingHex::ErrFile), asMETHODPR(WingHex::IWingPlugin, openWorkSpace, (const QString &), int),
"ErrFile openWorkSpace(string &in filename)"); "int openWorkSpace(string &in filename)");
registerAPI(engine, registerAPI(engine,
asMETHODPR(WingHex::IWingPlugin, closeAllFiles, (), bool), asMETHODPR(WingHex::IWingPlugin, closeAllFiles, (), bool),

View File

@ -559,7 +559,7 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path,
} }
} }
if (doc->isUndoByteModified() || m_fileName != fileName || isNewFile()) { if (!doc->isDocSaved() || m_fileName != fileName || isNewFile()) {
if (m_docType == DocumentType::Extension) { if (m_docType == DocumentType::Extension) {
if (_dev->isOpen()) { if (_dev->isOpen()) {
_dev->close(); _dev->close();

View File

@ -238,7 +238,7 @@ private slots:
WING_API bool existsServiceHost(QObject *caller, const QString &puid); WING_API bool existsServiceHost(QObject *caller, const QString &puid);
WING_API bool invokeServiceImpl(const QObject *sender, const QString &puid, WING_API bool invokeServiceImpl(const QObject *sender, const QString &puid,
const MetaCallInfo &infos); const WingHex::MetaCallInfo &infos);
private slots: private slots:
WING_API QString currentDocFilename(QObject *caller); WING_API QString currentDocFilename(QObject *caller);
@ -544,6 +544,7 @@ private:
GotoWidget *m_goto = nullptr; GotoWidget *m_goto = nullptr;
QWidget *m_hexContainer = nullptr; QWidget *m_hexContainer = nullptr;
bool _hasRegistered = false; bool _hasRegistered = false;
quintptr _oldbase = 0;
QHexView *m_hex = nullptr; QHexView *m_hex = nullptr;
QMenu *m_menu = nullptr; QMenu *m_menu = nullptr;

View File

@ -198,7 +198,6 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
m_toolBtneditors.value(ToolButtonIndex::EDITOR_VIEWS)->setEnabled(false); m_toolBtneditors.value(ToolButtonIndex::EDITOR_VIEWS)->setEnabled(false);
// ok, preparing for starting... // ok, preparing for starting...
this->setWindowTitle(tr("WingHexExplorer"));
this->setWindowIcon(Utilities::isRoot() this->setWindowIcon(Utilities::isRoot()
? ICONRES(QStringLiteral("iconroot")) ? ICONRES(QStringLiteral("iconroot"))
: ICONRES(QStringLiteral("icon"))); : ICONRES(QStringLiteral("icon")));
@ -467,6 +466,7 @@ void MainWindow::buildUpDockSystem(QWidget *container) {
m_metadatas->setModel(_metadataEmpty); m_metadatas->setModel(_metadataEmpty);
m_aDelBookMark->setEnabled(false); m_aDelBookMark->setEnabled(false);
m_aDelMetaData->setEnabled(false); m_aDelMetaData->setEnabled(false);
_undoView->setStack(nullptr);
} }
updateEditModeEnabled(); updateEditModeEnabled();
}); });
@ -570,6 +570,8 @@ void MainWindow::buildUpDockSystem(QWidget *container) {
qApp->processEvents(); qApp->processEvents();
buildUpDecodingStrShowDock(m_dock, ads::CenterDockWidgetArea, rightArea); buildUpDecodingStrShowDock(m_dock, ads::CenterDockWidgetArea, rightArea);
qApp->processEvents(); qApp->processEvents();
buildUpUndoStackDock(m_dock, ads::CenterDockWidgetArea, rightArea);
qApp->processEvents();
ads::CDockAreaWidget *bottomRightArea; ads::CDockAreaWidget *bottomRightArea;
if (SettingManager::instance().scriptEnabled()) { if (SettingManager::instance().scriptEnabled()) {
@ -1113,6 +1115,16 @@ MainWindow::buildUpScriptBgOutputDock(ads::CDockManager *dock,
return dock->addDockWidget(area, dw, areaw); return dock->addDockWidget(area, dw, areaw);
} }
ads::CDockAreaWidget *
MainWindow::buildUpUndoStackDock(ads::CDockManager *dock,
ads::DockWidgetArea area,
ads::CDockAreaWidget *areaw) {
_undoView = new QUndoView(this);
auto dw = buildDockWidget(dock, QStringLiteral("UndoStack"),
tr("UndoStack"), _undoView);
return dock->addDockWidget(area, dw, areaw);
}
RibbonTabContent *MainWindow::buildFilePage(RibbonTabContent *tab) { RibbonTabContent *MainWindow::buildFilePage(RibbonTabContent *tab) {
auto shortcuts = QKeySequences::instance(); auto shortcuts = QKeySequences::instance();
{ {
@ -3218,7 +3230,7 @@ void MainWindow::connectEditorView(EditorView *editor) {
auto total = hexeditor->selectionCount(); auto total = hexeditor->selectionCount();
if (m.exec()) { if (m.exec()) {
auto meta = doc->metadata(); auto meta = doc->metadata();
meta->beginMarco(QStringLiteral("OnMetaData")); meta->beginMarco(tr("[MetaAdd]"));
for (int i = 0; i < total; ++i) { for (int i = 0; i < total; ++i) {
auto begin = cur->selectionStart(i).offset(); auto begin = cur->selectionStart(i).offset();
auto end = cur->selectionEnd(i).offset(); auto end = cur->selectionEnd(i).offset();
@ -3345,6 +3357,15 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) {
connect(hexeditor, &QHexView::documentSaved, this, [this](bool b) { connect(hexeditor, &QHexView::documentSaved, this, [this](bool b) {
m_iSaved->setIcon(b ? _infoSaved : _infoUnsaved); m_iSaved->setIcon(b ? _infoSaved : _infoUnsaved);
m_sSaved->setIcon(b ? _infoSaved : _infoUnsaved); m_sSaved->setIcon(b ? _infoSaved : _infoUnsaved);
if (b) {
auto cur = currentEditor();
auto fn = cur->fileName();
if (cur) {
m_sSaved->setToolTip(fn);
setWindowFilePath(QFileInfo(fn).fileName());
updateWindowTitle();
}
}
}); });
connect(hexeditor, &QHexView::documentKeepSize, this, [this](bool b) { connect(hexeditor, &QHexView::documentKeepSize, this, [this](bool b) {
m_iCanOver->setIcon(b ? _infoCannotOver : _infoCanOver); m_iCanOver->setIcon(b ? _infoCannotOver : _infoCanOver);
@ -3409,6 +3430,8 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) {
m_metadatas->selectionModel()->hasSelection()); m_metadatas->selectionModel()->hasSelection());
}); });
_undoView->setStack(doc->undoStack());
m_curEditor = cur; m_curEditor = cur;
hexeditor->getStatus(); hexeditor->getStatus();
@ -3417,6 +3440,17 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) {
{cur->fileName(), (old ? old->fileName() : QString())}); {cur->fileName(), (old ? old->fileName() : QString())});
} }
void MainWindow::updateWindowTitle() {
static auto title = tr("WingHexExplorer");
auto fp = windowFilePath();
if (fp.isEmpty()) {
this->setWindowTitle(title);
} else {
QFileInfo info(fp);
this->setWindowTitle(title + QStringLiteral(" - ") + info.fileName());
}
}
void MainWindow::loadFindResult(EditorView *view) { void MainWindow::loadFindResult(EditorView *view) {
auto result = view->findResultModel(); auto result = view->findResultModel();
m_findresult->setModel(result); m_findresult->setModel(result);
@ -3672,11 +3706,15 @@ void MainWindow::updateEditModeEnabled() {
doc->canRedo()); doc->canRedo());
m_toolBtneditors[ToolButtonIndex::UNDO_ACTION]->setEnabled( m_toolBtneditors[ToolButtonIndex::UNDO_ACTION]->setEnabled(
doc->canUndo()); doc->canUndo());
setWindowFilePath(editor->fileName());
} else { } else {
m_lblloc->setText(QStringLiteral("(0,0)")); m_lblloc->setText(QStringLiteral("(0,0)"));
m_lblsellen->setText(QStringLiteral("0 - 0x0")); m_lblsellen->setText(QStringLiteral("0 - 0x0"));
_numsitem->clear(); _numsitem->clear();
setWindowFilePath({});
} }
updateWindowTitle();
} }
void MainWindow::setCurrentHexEditorScale(qreal rate) { void MainWindow::setCurrentHexEditorScale(qreal rate) {

View File

@ -34,6 +34,7 @@
#include <QTextBrowser> #include <QTextBrowser>
#include <QToolButton> #include <QToolButton>
#include <QTreeView> #include <QTreeView>
#include <QUndoView>
#include <QtConcurrent/QtConcurrentRun> #include <QtConcurrent/QtConcurrentRun>
#include <QtEndian> #include <QtEndian>
@ -44,7 +45,6 @@
#include "Qt-Advanced-Docking-System/src/DockWidget.h" #include "Qt-Advanced-Docking-System/src/DockWidget.h"
#include "WingPlugin/iwingplugin.h" #include "WingPlugin/iwingplugin.h"
#include "class/recentfilemanager.h" #include "class/recentfilemanager.h"
#include "class/scriptmanager.h"
#include "control/editorview.h" #include "control/editorview.h"
#include "control/qtableviewext.h" #include "control/qtableviewext.h"
#include "control/scriptingconsole.h" #include "control/scriptingconsole.h"
@ -122,6 +122,10 @@ private:
buildUpScriptBgOutputDock(ads::CDockManager *dock, ads::DockWidgetArea area, buildUpScriptBgOutputDock(ads::CDockManager *dock, ads::DockWidgetArea area,
ads::CDockAreaWidget *areaw = nullptr); ads::CDockAreaWidget *areaw = nullptr);
ads::CDockAreaWidget *
buildUpUndoStackDock(ads::CDockManager *dock, ads::DockWidgetArea area,
ads::CDockAreaWidget *areaw = nullptr);
RibbonTabContent *buildFilePage(RibbonTabContent *tab); RibbonTabContent *buildFilePage(RibbonTabContent *tab);
RibbonTabContent *buildEditPage(RibbonTabContent *tab); RibbonTabContent *buildEditPage(RibbonTabContent *tab);
RibbonTabContent *buildViewPage(RibbonTabContent *tab); RibbonTabContent *buildViewPage(RibbonTabContent *tab);
@ -243,6 +247,7 @@ private:
void connectEditorView(EditorView *editor); void connectEditorView(EditorView *editor);
void swapEditor(EditorView *old, EditorView *cur); void swapEditor(EditorView *old, EditorView *cur);
void updateWindowTitle();
void loadFindResult(EditorView *view); void loadFindResult(EditorView *view);
@ -496,6 +501,8 @@ private:
QTableViewExt *m_metadatas = nullptr; QTableViewExt *m_metadatas = nullptr;
MetaDataModel *_metadataEmpty = nullptr; MetaDataModel *_metadataEmpty = nullptr;
QUndoView *_undoView = nullptr;
QMap<ToolButtonIndex, QToolButton *> m_toolBtneditors; QMap<ToolButtonIndex, QToolButton *> m_toolBtneditors;
QAction *m_aDelBookMark = nullptr; QAction *m_aDelBookMark = nullptr;

View File

@ -86,7 +86,7 @@ ScriptingDialog::ScriptingDialog(QWidget *parent)
m_Tbtneditors.value(ToolButtonIndex::EDITOR_VIEWS)->setEnabled(false); m_Tbtneditors.value(ToolButtonIndex::EDITOR_VIEWS)->setEnabled(false);
// ok, preparing for starting... // ok, preparing for starting...
this->setWindowTitle(tr("ScriptEditor")); updateWindowTitle();
this->setWindowIcon(ICONRES(QStringLiteral("script"))); this->setWindowIcon(ICONRES(QStringLiteral("script")));
this->setMinimumSize(800, 600); this->setMinimumSize(800, 600);
@ -833,6 +833,16 @@ void ScriptingDialog::updateEditModeEnabled() {
item->setEnabled(b); item->setEnabled(b);
} }
if (b) {
auto fn = editor->fileName();
setWindowFilePath(fn);
m_status->setToolTip(fn);
} else {
setWindowFilePath({});
m_status->setToolTip({});
m_status->clearMessage();
}
updateWindowTitle();
updateRunDebugMode(); updateRunDebugMode();
} }
@ -895,6 +905,17 @@ void ScriptingDialog::swapEditor(ScriptEditor *old, ScriptEditor *cur) {
} }
} }
void ScriptingDialog::updateWindowTitle() {
auto title = tr("ScriptEditor");
auto fp = windowFilePath();
if (fp.isEmpty()) {
this->setWindowTitle(title);
} else {
QFileInfo info(fp);
this->setWindowTitle(title + QStringLiteral(" - ") + info.fileName());
}
}
void ScriptingDialog::updateRunDebugMode(bool disable) { void ScriptingDialog::updateRunDebugMode(bool disable) {
auto &runner = ScriptMachine::instance(); auto &runner = ScriptMachine::instance();
auto enable = !disable; auto enable = !disable;
@ -1239,6 +1260,8 @@ void ScriptingDialog::on_save() {
auto res = editor->save(); auto res = editor->save();
if (res) { if (res) {
setWindowFilePath(editor->fileName());
updateWindowTitle();
Toast::toast(this, NAMEICONRES(QStringLiteral("save")), Toast::toast(this, NAMEICONRES(QStringLiteral("save")),
tr("SaveSuccessfully")); tr("SaveSuccessfully"));
} else { } else {
@ -1267,6 +1290,8 @@ void ScriptingDialog::on_saveas() {
auto res = editor->save(filename); auto res = editor->save(filename);
if (res) { if (res) {
setWindowFilePath(editor->fileName());
updateWindowTitle();
Toast::toast(this, NAMEICONRES(QStringLiteral("saveas")), Toast::toast(this, NAMEICONRES(QStringLiteral("saveas")),
tr("SaveSuccessfully")); tr("SaveSuccessfully"));
} else { } else {

View File

@ -202,6 +202,7 @@ private:
void updateEditModeEnabled(); void updateEditModeEnabled();
ScriptEditor *currentEditor() const; ScriptEditor *currentEditor() const;
void swapEditor(ScriptEditor *old, ScriptEditor *cur); void swapEditor(ScriptEditor *old, ScriptEditor *cur);
void updateWindowTitle();
void updateRunDebugMode(bool disable = false); void updateRunDebugMode(bool disable = false);