BinEditor: Split out BinEditorDocument class definition

Still preparing data holder re-organization.

Change-Id: I29473fed8320b3812288b72d0d5fc943aa67a2cf
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2024-07-11 15:25:10 +02:00
parent 5cd6f6086a
commit 0469dd5602

View File

@@ -75,6 +75,50 @@ using namespace Core;
namespace BinEditor::Internal { namespace BinEditor::Internal {
class BinEditorWidget;
class BinEditorDocument : public IDocument
{
Q_OBJECT
public:
BinEditorDocument(BinEditorWidget *parent);
QByteArray contents() const final;
bool setContents(const QByteArray &contents) final;
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const final
{
return type == TypeRemoved ? BehaviorSilent : IDocument::reloadBehavior(state, type);
}
OpenResult open(QString *errorString, const FilePath &filePath,
const FilePath &realFilePath) final
{
QTC_CHECK(filePath == realFilePath); // The bineditor can do no autosaving
return openImpl(errorString, filePath);
}
OpenResult openImpl(QString *errorString, const FilePath &filePath, quint64 offset = 0);
void provideData(quint64 address);
void provideNewRange(quint64 offset)
{
if (filePath().exists())
openImpl(nullptr, filePath(), offset);
}
bool isModified() const final;
bool isSaveAsAllowed() const final { return true; }
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) final;
bool saveImpl(QString *errorString, const Utils::FilePath &filePath, bool autoSave) final;
private:
BinEditorWidget *m_widget;
};
class BinEditorWidget final : public QAbstractScrollArea, public EditorService class BinEditorWidget final : public QAbstractScrollArea, public EditorService
{ {
Q_OBJECT Q_OBJECT
@@ -2065,148 +2109,120 @@ private:
}; };
class BinEditorDocument : public IDocument // BinEditorDocument
BinEditorDocument::BinEditorDocument(BinEditorWidget *parent)
: IDocument(parent)
{ {
Q_OBJECT setId(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID);
public: setMimeType(Utils::Constants::OCTET_STREAM_MIMETYPE);
BinEditorDocument(BinEditorWidget *parent) : m_widget = parent;
IDocument(parent) EditorService *es = m_widget->editorService();
{ es->setFetchDataHandler([this](quint64 address) { provideData(address); });
setId(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID); es->setNewRangeRequestHandler([this](quint64 offset) { provideNewRange(offset); });
setMimeType(Utils::Constants::OCTET_STREAM_MIMETYPE); es->setDataChangedHandler([this](quint64, const QByteArray &) { contentsChanged(); });
m_widget = parent; }
EditorService *es = m_widget->editorService();
es->setFetchDataHandler([this](quint64 address) { provideData(address); }); QByteArray BinEditorDocument::contents() const
es->setNewRangeRequestHandler([this](quint64 offset) { provideNewRange(offset); }); {
es->setDataChangedHandler([this](quint64, const QByteArray &) { contentsChanged(); }); return m_widget->contents();
}
bool BinEditorDocument::setContents(const QByteArray &contents)
{
m_widget->clear();
if (!contents.isEmpty()) {
m_widget->setSizes(0, contents.length(), contents.length());
m_widget->addData(0, contents);
}
return true;
}
IDocument::OpenResult BinEditorDocument::openImpl(QString *errorString, const FilePath &filePath, quint64 offset)
{
const qint64 size = filePath.fileSize();
if (size < 0) {
QString msg = Tr::tr("Cannot open %1: %2").arg(filePath.toUserOutput(), Tr::tr("File Error"));
// FIXME: Was: file.errorString(), but we don't have a file anymore.
if (errorString)
*errorString = msg;
else
QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg);
return OpenResult::ReadError;
} }
QByteArray contents() const override if (size == 0) {
{ QString msg = Tr::tr("The Binary Editor cannot open empty files.");
return m_widget->contents(); if (errorString)
*errorString = msg;
else
QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg);
return OpenResult::CannotHandle;
} }
bool setContents(const QByteArray &contents) override if (size / 16 >= qint64(1) << 31) {
{ // The limit is 2^31 lines (due to QText* interfaces) * 16 bytes per line.
m_widget->clear(); QString msg = Tr::tr("The file is too big for the Binary Editor (max. 32GB).");
if (!contents.isEmpty()) { if (errorString)
m_widget->setSizes(0, contents.length(), contents.length()); *errorString = msg;
m_widget->addData(0, contents); else
} QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg);
return true; return OpenResult::CannotHandle;
} }
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override if (offset >= quint64(size))
{ return OpenResult::CannotHandle;
return type == TypeRemoved ? BehaviorSilent : IDocument::reloadBehavior(state, type);
}
OpenResult open(QString *errorString, const FilePath &filePath, setFilePath(filePath);
const FilePath &realFilePath) override m_widget->setSizes(offset, size);
{ return OpenResult::Success;
QTC_CHECK(filePath == realFilePath); // The bineditor can do no autosaving }
return openImpl(errorString, filePath);
}
OpenResult openImpl(QString *errorString, const FilePath &filePath, quint64 offset = 0) void BinEditorDocument::provideData(quint64 address)
{ {
const qint64 size = filePath.fileSize(); const FilePath fn = filePath();
if (size < 0) { if (fn.isEmpty())
QString msg = Tr::tr("Cannot open %1: %2").arg(filePath.toUserOutput(), Tr::tr("File Error")); return;
// FIXME: Was: file.errorString(), but we don't have a file anymore. const int blockSize = m_widget->dataBlockSize();
if (errorString) QByteArray data = fn.fileContents(blockSize, address).value_or(QByteArray());
*errorString = msg; const int dataSize = data.size();
else if (dataSize != blockSize)
QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg); data += QByteArray(blockSize - dataSize, 0);
return OpenResult::ReadError; m_widget->addData(address, data);
}
if (size == 0) {
QString msg = Tr::tr("The Binary Editor cannot open empty files.");
if (errorString)
*errorString = msg;
else
QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg);
return OpenResult::CannotHandle;
}
if (size / 16 >= qint64(1) << 31) {
// The limit is 2^31 lines (due to QText* interfaces) * 16 bytes per line.
QString msg = Tr::tr("The file is too big for the Binary Editor (max. 32GB).");
if (errorString)
*errorString = msg;
else
QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), msg);
return OpenResult::CannotHandle;
}
if (offset >= quint64(size))
return OpenResult::CannotHandle;
setFilePath(filePath);
m_widget->setSizes(offset, size);
return OpenResult::Success;
}
void provideData(quint64 address)
{
const FilePath fn = filePath();
if (fn.isEmpty())
return;
const int blockSize = m_widget->dataBlockSize();
QByteArray data = fn.fileContents(blockSize, address).value_or(QByteArray());
const int dataSize = data.size();
if (dataSize != blockSize)
data += QByteArray(blockSize - dataSize, 0);
m_widget->addData(address, data);
// QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"), // QMessageBox::critical(ICore::dialogParent(), Tr::tr("File Error"),
// Tr::tr("Cannot open %1: %2").arg( // Tr::tr("Cannot open %1: %2").arg(
// fn.toUserOutput(), file.errorString())); // fn.toUserOutput(), file.errorString()));
}
bool BinEditorDocument::isModified() const
{
return isTemporary()/*e.g. memory view*/ ? false
: m_widget->isModified();
}
bool BinEditorDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type)
{
Q_UNUSED(type)
if (flag == FlagIgnore)
return true;
emit aboutToReload();
int cPos = m_widget->cursorPosition();
m_widget->clear();
const bool success = (openImpl(errorString, filePath()) == OpenResult::Success);
m_widget->setCursorPosition(cPos);
emit reloadFinished(success);
return success;
}
bool BinEditorDocument::saveImpl(QString *errorString, const Utils::FilePath &filePath, bool autoSave)
{
QTC_ASSERT(!autoSave, return true); // bineditor does not support autosave - it would be a bit expensive
if (m_widget->save(errorString, this->filePath(), filePath)) {
setFilePath(filePath);
return true;
} }
return false;
void provideNewRange(quint64 offset) }
{
if (filePath().exists())
openImpl(nullptr, filePath(), offset);
}
public:
bool isModified() const override
{
return isTemporary()/*e.g. memory view*/ ? false
: m_widget->isModified();
}
bool isSaveAsAllowed() const override { return true; }
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override
{
Q_UNUSED(type)
if (flag == FlagIgnore)
return true;
emit aboutToReload();
int cPos = m_widget->cursorPosition();
m_widget->clear();
const bool success = (openImpl(errorString, filePath()) == OpenResult::Success);
m_widget->setCursorPosition(cPos);
emit reloadFinished(success);
return success;
}
protected:
bool saveImpl(QString *errorString, const Utils::FilePath &filePath, bool autoSave) override
{
QTC_ASSERT(!autoSave, return true); // bineditor does not support autosave - it would be a bit expensive
if (m_widget->save(errorString, this->filePath(), filePath)) {
setFilePath(filePath);
return true;
}
return false;
}
private:
BinEditorWidget *m_widget;
};
class BinEditorImpl: public IEditor class BinEditorImpl: public IEditor
{ {