diff --git a/src/plugins/bineditor/bineditor.cpp b/src/plugins/bineditor/bineditor.cpp index 573feb78bb4..06e0d61da72 100644 --- a/src/plugins/bineditor/bineditor.cpp +++ b/src/plugins/bineditor/bineditor.cpp @@ -89,7 +89,6 @@ BinEditor::BinEditor(QWidget *parent) : QAbstractScrollArea(parent) { m_ieditor = 0; - m_inLazyMode = false; m_baseAddr = 0; m_blockSize = 4096; m_size = 0; @@ -161,39 +160,35 @@ void BinEditor::init() } -void BinEditor::addLazyData(quint64 block, const QByteArray &data) +void BinEditor::addData(quint64 block, const QByteArray &data) { - Q_ASSERT(m_inLazyMode); Q_ASSERT(data.size() == m_blockSize); const quint64 addr = block * m_blockSize; if (addr >= m_baseAddr && addr <= m_baseAddr + m_size - 1) { - if (m_lazyData.size() * m_blockSize >= 64 * 1024 * 1024) - m_lazyData.clear(); + if (m_data.size() * m_blockSize >= 64 * 1024 * 1024) + m_data.clear(); const int translatedBlock = (addr - m_baseAddr) / m_blockSize; - m_lazyData.insert(translatedBlock, data); - m_lazyRequests.remove(translatedBlock); + m_data.insert(translatedBlock, data); + m_requests.remove(translatedBlock); viewport()->update(); } } bool BinEditor::requestDataAt(int pos, bool synchronous) const { - if (!m_inLazyMode) - return true; - int block = pos / m_blockSize; - QMap::const_iterator it = m_modifiedData.find(block); + BlockMap::const_iterator it = m_modifiedData.find(block); if (it != m_modifiedData.constEnd()) return true; - it = m_lazyData.find(block); - if (it != m_lazyData.end()) + it = m_data.find(block); + if (it != m_data.end()) return true; - if (!m_lazyRequests.contains(block)) { - m_lazyRequests.insert(block); + if (!m_requests.contains(block)) { + m_requests.insert(block); emit const_cast(this)-> - lazyDataRequested(editorInterface(), m_baseAddr / m_blockSize + block, + dataRequested(editor(), m_baseAddr / m_blockSize + block, synchronous); - if (!m_lazyRequests.contains(block)) + if (!m_requests.contains(block)) return true; // synchronous data source } return false; @@ -201,34 +196,26 @@ bool BinEditor::requestDataAt(int pos, bool synchronous) const bool BinEditor::requestOldDataAt(int pos) const { - if (!m_inLazyMode) - return false; int block = pos / m_blockSize; - QMap::const_iterator it = m_oldLazyData.find(block); - return it != m_oldLazyData.end(); + BlockMap::const_iterator it = m_oldData.find(block); + return it != m_oldData.end(); } char BinEditor::dataAt(int pos, bool old) const { - if (!m_inLazyMode) - return m_data.at(pos); int block = pos / m_blockSize; return blockData(block, old).at(pos - (block*m_blockSize)); } void BinEditor::changeDataAt(int pos, char c) { - if (!m_inLazyMode) { - m_data[pos] = c; - return; - } int block = pos / m_blockSize; - QMap::iterator it = m_modifiedData.find(block); + BlockMap::iterator it = m_modifiedData.find(block); if (it != m_modifiedData.end()) { it.value()[pos - (block*m_blockSize)] = c; } else { - it = m_lazyData.find(block); - if (it != m_lazyData.end()) { + it = m_data.find(block); + if (it != m_data.end()) { QByteArray data = it.value(); data[pos - (block*m_blockSize)] = c; m_modifiedData.insert(block, data); @@ -238,9 +225,6 @@ void BinEditor::changeDataAt(int pos, char c) QByteArray BinEditor::dataMid(int from, int length, bool old) const { - if (!m_inLazyMode) - return m_data.mid(from, length); - int end = from + length; int block = from / m_blockSize; @@ -256,19 +240,13 @@ QByteArray BinEditor::dataMid(int from, int length, bool old) const QByteArray BinEditor::blockData(int block, bool old) const { if (old) { - QMap::const_iterator it = m_modifiedData.find(block); + BlockMap::const_iterator it = m_modifiedData.find(block); return it != m_modifiedData.constEnd() - ? it.value() : m_oldLazyData.value(block, m_emptyBlock); + ? it.value() : m_oldData.value(block, m_emptyBlock); } - if (!m_inLazyMode) { - QByteArray data = m_data.mid(block * m_blockSize, m_blockSize); - if (data.size() < m_blockSize) - data.resize(m_blockSize); - return data; - } - QMap::const_iterator it = m_modifiedData.find(block); + BlockMap::const_iterator it = m_modifiedData.find(block); return it != m_modifiedData.constEnd() - ? it.value() : m_lazyData.value(block, m_emptyBlock); + ? it.value() : m_data.value(block, m_emptyBlock); } void BinEditor::setFontSettings(const TextEditor::FontSettings &fs) @@ -358,100 +336,63 @@ bool BinEditor::isReadOnly() const return m_readOnly; } -void BinEditor::setData(const QByteArray &data) -{ - m_inLazyMode = false; - m_baseAddr = 0; - m_lazyData.clear(); - m_oldLazyData.clear(); - m_modifiedData.clear(); - m_lazyRequests.clear(); - m_data = data; - m_size = data.size(); - m_addressBytes = 4; - - m_unmodifiedState = 0; - m_undoStack.clear(); - m_redoStack.clear(); - - init(); - m_cursorPosition = 0; - verticalScrollBar()->setValue(0); - - emit cursorPositionChanged(m_cursorPosition); - viewport()->update(); -} - -QByteArray BinEditor::data() const -{ - return m_data; -} - bool BinEditor::save(const QString &oldFileName, const QString &newFileName) { - if (m_inLazyMode) { - if (oldFileName != newFileName) { - QString tmpName; - { - QTemporaryFile tmp; - if (!tmp.open()) - return false; - tmpName = tmp.fileName(); - } - if (!QFile::copy(oldFileName, tmpName)) - return false; - if (QFile::exists(newFileName) && !QFile::remove(newFileName)) - return false; - if (!QFile::rename(tmpName, newFileName)) + if (oldFileName != newFileName) { + QString tmpName; + { + QTemporaryFile tmp; + if (!tmp.open()) return false; + tmpName = tmp.fileName(); } - QFile output(newFileName); - if (!output.open(QIODevice::ReadWrite)) // QtBug: WriteOnly truncates. + if (!QFile::copy(oldFileName, tmpName)) return false; - const qint64 size = output.size(); - for (QMap::const_iterator it = m_modifiedData.constBegin(); - it != m_modifiedData.constEnd(); ++it) { - if (!output.seek(it.key() * m_blockSize)) - return false; - if (output.write(it.value()) < m_blockSize) - return false; - } - - // We may have padded the displayed data, so we have to make sure - // changes to that area are not actually written back to disk. - if (!output.resize(size)) + if (QFile::exists(newFileName) && !QFile::remove(newFileName)) return false; - } else { - QFile output(newFileName); - if (!output.open(QIODevice::WriteOnly | QIODevice::Truncate)) - return false; - if (output.write(m_data) < m_size) + if (!QFile::rename(tmpName, newFileName)) return false; } + QFile output(newFileName); + if (!output.open(QIODevice::ReadWrite)) // QtBug: WriteOnly truncates. + return false; + const qint64 size = output.size(); + for (BlockMap::const_iterator it = m_modifiedData.constBegin(); + it != m_modifiedData.constEnd(); ++it) { + if (!output.seek(it.key() * m_blockSize)) + return false; + if (output.write(it.value()) < m_blockSize) + return false; + } + + // We may have padded the displayed data, so we have to make sure + // changes to that area are not actually written back to disk. + if (!output.resize(size)) + return false; + setModified(false); return true; } -void BinEditor::setLazyData(quint64 startAddr, int range, int blockSize) +void BinEditor::setSizes(quint64 startAddr, int range, bool fixedSize, int blockSize) { - m_inLazyMode = true; m_blockSize = blockSize; + m_fixedSize = fixedSize; Q_ASSERT((blockSize/16) * 16 == blockSize); m_emptyBlock = QByteArray(blockSize, '\0'); - m_data.clear(); m_modifiedData.clear(); - m_lazyRequests.clear(); + m_requests.clear(); - // In lazy mode, users can edit data in the range + // Users can edit data in the range // [startAddr - range/2, startAddr + range/2]. - m_baseAddr = static_cast(range/2) > startAddr - ? 0 : startAddr - range/2; + m_baseAddr = quint64(range/2) > startAddr ? 0 : startAddr - range/2; m_baseAddr = (m_baseAddr / blockSize) * blockSize; + const quint64 maxRange = Q_UINT64_C(0xffffffffffffffff) - m_baseAddr + 1; - m_size = m_baseAddr != 0 && static_cast(range) >= maxRange - ? maxRange : range; + m_size = m_baseAddr != 0 && quint64(range) >= maxRange + ? maxRange : range; m_addressBytes = (m_baseAddr + m_size < quint64(1) << 32 - && m_baseAddr + m_size >= m_baseAddr) ? 4 : 8; + && m_baseAddr + m_size >= m_baseAddr) ? 4 : 8; m_unmodifiedState = 0; m_undoStack.clear(); @@ -471,15 +412,12 @@ void BinEditor::resizeEvent(QResizeEvent *) void BinEditor::scrollContentsBy(int dx, int dy) { viewport()->scroll(isRightToLeft() ? -dx : dx, dy * m_lineHeight); - if (m_inLazyMode) { - const QScrollBar * const scrollBar = verticalScrollBar(); - const int scrollPos = scrollBar->value(); - if (dy <= 0 && scrollPos == scrollBar->maximum()) - emit newRangeRequested(editorInterface(), - baseAddress() + dataSize()); - else if (dy >= 0 && scrollPos == scrollBar->minimum()) - emit newRangeRequested(editorInterface(), baseAddress()); - } + const QScrollBar * const scrollBar = verticalScrollBar(); + const int scrollPos = scrollBar->value(); + if (dy <= 0 && scrollPos == scrollBar->maximum()) + emit newRangeRequested(editor(), baseAddress() + m_size); + else if (dy >= 0 && scrollPos == scrollBar->minimum()) + emit newRangeRequested(editor(), baseAddress()); } void BinEditor::changeEvent(QEvent *e) @@ -576,10 +514,6 @@ void BinEditor::updateLines(int fromPosition, int toPosition) int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensitive) const { - if (!m_inLazyMode && caseSensitive) { - return m_data.indexOf(pattern, from); - } - int trailing = pattern.size(); if (trailing > m_blockSize) return -1; @@ -613,9 +547,6 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSensitive) const { - if (!m_inLazyMode && caseSensitive) - return m_data.lastIndexOf(pattern, from); - int trailing = pattern.size(); if (trailing > m_blockSize) return -1; @@ -1058,10 +989,28 @@ void BinEditor::selectAll() void BinEditor::clear() { - setData(QByteArray()); + m_baseAddr = 0; + m_data.clear(); + m_oldData.clear(); + m_modifiedData.clear(); + m_requests.clear(); + m_size = 0; + m_addressBytes = 4; + + m_unmodifiedState = 0; + m_undoStack.clear(); + m_redoStack.clear(); + + init(); + m_cursorPosition = 0; + verticalScrollBar()->setValue(0); + + emit cursorPositionChanged(m_cursorPosition); + viewport()->update(); } -bool BinEditor::event(QEvent *e) { +bool BinEditor::event(QEvent *e) +{ if (e->type() == QEvent::KeyPress) { switch (static_cast(e)->key()) { case Qt::Key_Tab: @@ -1071,16 +1020,14 @@ bool BinEditor::event(QEvent *e) { ensureCursorVisible(); e->accept(); return true; - case Qt::Key_Down: - if (m_inLazyMode) { - const QScrollBar * const scrollBar = verticalScrollBar(); - if (scrollBar->value() >= scrollBar->maximum() - 1) { - emit newRangeRequested(editorInterface(), - baseAddress() + dataSize()); - return true; - } + case Qt::Key_Down: { + const QScrollBar * const scrollBar = verticalScrollBar(); + if (scrollBar->value() >= scrollBar->maximum() - 1) { + emit newRangeRequested(editor(), baseAddress() + m_size); + return true; } break; + } default:; } } else if (e->type() == QEvent::ToolTip) { @@ -1220,20 +1167,14 @@ void BinEditor::keyPressEvent(QKeyEvent *e) case Qt::Key_Home: if (e->modifiers() & Qt::ControlModifier) { - if (m_inLazyMode) - emit startOfFileRequested(editorInterface()); - else - setCursorPosition(0); + emit startOfFileRequested(editor()); } else { setCursorPosition(m_cursorPosition/16 * 16, moveMode); } break; case Qt::Key_End: if (e->modifiers() & Qt::ControlModifier) { - if (m_inLazyMode) - emit endOfFileRequested(editorInterface()); - else - setCursorPosition(m_size - 1); + emit endOfFileRequested(editor()); } else { setCursorPosition(m_cursorPosition/16 * 16 + 15, moveMode); } @@ -1474,10 +1415,10 @@ void BinEditor::setupJumpToMenuAction(QMenu *menu, QAction *actionHere, void BinEditor::jumpToAddress(quint64 address) { - if (address >= m_baseAddr && address < m_baseAddr + m_data.size()) + if (address >= m_baseAddr && address < m_baseAddr + m_size) setCursorPosition(address - m_baseAddr); - else if (m_inLazyMode) - emit newRangeRequested(editorInterface(), address); + else + emit newRangeRequested(editor(), address); } void BinEditor::setNewWindowRequestAllowed() @@ -1487,9 +1428,9 @@ void BinEditor::setNewWindowRequestAllowed() void BinEditor::updateContents() { - m_oldLazyData = m_lazyData; - m_lazyData.clear(); - setLazyData(baseAddress() + cursorPosition(), dataSize(), m_blockSize); + m_oldData = m_data; + m_data.clear(); + setSizes(baseAddress() + cursorPosition(), m_size, m_blockSize); } QPoint BinEditor::offsetToPos(int offset) @@ -1504,7 +1445,7 @@ void BinEditor::asIntegers(int offset, int count, quint64 &beValue, { beValue = leValue = 0; const QByteArray &data = dataMid(offset, count, old); - for (int pos = 0; pos < count; ++pos) { + for (int pos = 0; pos < data.size(); ++pos) { const quint64 val = static_cast(data.at(pos)) & 0xff; beValue += val << (pos * 8); leValue += val << ((count - pos - 1) * 8); diff --git a/src/plugins/bineditor/bineditor.h b/src/plugins/bineditor/bineditor.h index ccfba172fc2..0ddffc7d37f 100644 --- a/src/plugins/bineditor/bineditor.h +++ b/src/plugins/bineditor/bineditor.h @@ -66,16 +66,11 @@ public: BinEditor(QWidget *parent = 0); ~BinEditor(); - void setData(const QByteArray &data); - QByteArray data() const; - - inline int dataSize() const { return m_size; } quint64 baseAddress() const { return m_baseAddr; } - inline bool inLazyMode() const { return m_inLazyMode; } - Q_INVOKABLE void setLazyData(quint64 startAddr, int range, int blockSize = 4096); - inline int lazyDataBlockSize() const { return m_blockSize; } - Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data); + Q_INVOKABLE void setSizes(quint64 startAddr, int range, bool fixedSize, int blockSize = 4096); + int dataBlockSize() const { return m_blockSize; } + Q_INVOKABLE void addData(quint64 block, const QByteArray &data); Q_INVOKABLE void setNewWindowRequestAllowed(); Q_INVOKABLE void updateContents(); bool save(const QString &oldFileName, const QString &newFileName); @@ -107,8 +102,8 @@ public: void undo(); void redo(); - Core::IEditor *editorInterface() const { return m_ieditor; } - void setEditorInterface(Core::IEditor *ieditor) { m_ieditor = ieditor; } + Core::IEditor *editor() const { return m_ieditor; } + void setEditor(Core::IEditor *ieditor) { m_ieditor = ieditor; } bool hasSelection() const { return m_cursorPosition != m_anchorPosition; } int selectionStart() const { return qMin(m_anchorPosition, m_cursorPosition); } @@ -136,7 +131,7 @@ Q_SIGNALS: void copyAvailable(bool); void cursorPositionChanged(int position); - void lazyDataRequested(Core::IEditor *editor, quint64 block, bool synchronous); + void dataRequested(Core::IEditor *editor, quint64 block, bool synchronous); void newWindowRequested(quint64 address); void newRangeRequested(Core::IEditor *, quint64 address); void startOfFileRequested(Core::IEditor *); @@ -158,13 +153,12 @@ protected: void contextMenuEvent(QContextMenuEvent *event); private: - bool m_inLazyMode; - QByteArray m_data; - QMap m_lazyData; - QMap m_oldLazyData; + typedef QMap BlockMap; + BlockMap m_data; + BlockMap m_oldData; int m_blockSize; - QMap m_modifiedData; - mutable QSet m_lazyRequests; + BlockMap m_modifiedData; + mutable QSet m_requests; QByteArray m_emptyBlock; QByteArray m_lowerBlock; int m_size; @@ -198,6 +192,7 @@ private: int m_numVisibleLines; quint64 m_baseAddr; + bool m_fixedSize; bool m_cursorVisible; int m_cursorPosition; diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp index 7719d5ca9b6..72fbb0d415e 100644 --- a/src/plugins/bineditor/bineditorplugin.cpp +++ b/src/plugins/bineditor/bineditorplugin.cpp @@ -183,7 +183,7 @@ public: m_mimeType(QLatin1String(BINEditor::Constants::C_BINEDITOR_MIMETYPE)) { m_editor = parent; - connect(m_editor, SIGNAL(lazyDataRequested(Core::IEditor *, quint64, bool)), + connect(m_editor, SIGNAL(dataRequested(Core::IEditor *, quint64, bool)), this, SLOT(provideData(Core::IEditor *, quint64))); connect(m_editor, SIGNAL(newRangeRequested(Core::IEditor*,quint64)), this, SLOT(provideNewRange(Core::IEditor*,quint64))); @@ -201,8 +201,7 @@ public: = fileName.isEmpty() ? m_fileName : fileName; if (m_editor->save(m_fileName, fileNameToUse)) { m_fileName = fileNameToUse; - m_editor->editorInterface()-> - setDisplayName(QFileInfo(fileNameToUse).fileName()); + m_editor->editor()->setDisplayName(QFileInfo(fileNameToUse).fileName()); emit changed(); return true; } else { @@ -212,7 +211,7 @@ public: void rename(const QString &newName) { m_fileName = newName; - m_editor->editorInterface()->setDisplayName(QFileInfo(fileName()).fileName()); + m_editor->editor()->setDisplayName(QFileInfo(fileName()).fileName()); emit changed(); } @@ -221,13 +220,8 @@ public: if (offset < static_cast(file.size()) && file.open(QIODevice::ReadOnly)) { m_fileName = fileName; - qint64 maxRange = 64 * 1024 * 1024; - if (file.size() <= maxRange) - m_editor->setData(file.readAll()); - else - m_editor->setLazyData(offset, maxRange); - m_editor->editorInterface()-> - setDisplayName(QFileInfo(fileName).fileName()); + m_editor->setSizes(offset, file.size(), true); + m_editor->editor()->setDisplayName(QFileInfo(fileName).fileName()); file.close(); return true; } @@ -238,13 +232,13 @@ private slots: void provideData(Core::IEditor *, quint64 block) { QFile file(m_fileName); if (file.open(QIODevice::ReadOnly)) { - int blockSize = m_editor->lazyDataBlockSize(); + int blockSize = m_editor->dataBlockSize(); file.seek(block * blockSize); QByteArray data = file.read(blockSize); const int dataSize = data.size(); if (dataSize != blockSize) data += QByteArray(blockSize - dataSize, 0); - m_editor->addLazyData(block, data); + m_editor->addData(block, data); file.close(); } } @@ -359,7 +353,7 @@ public: Core::Context context() const { return m_context; } bool createNew(const QString & /* contents */ = QString()) { - m_editor->setData(QByteArray()); + m_editor->clear(); m_file->setFilename(QString()); return true; } @@ -432,7 +426,7 @@ Core::IEditor *BinEditorFactory::createEditor(QWidget *parent) { BinEditor *editor = new BinEditor(parent); m_owner->initializeEditor(editor); - return editor->editorInterface(); + return editor->editor(); } QStringList BinEditorFactory::mimeTypes() const @@ -475,7 +469,7 @@ void BinEditorPlugin::initializeEditor(BinEditor *editor) { BinEditorInterface *editorInterface = new BinEditorInterface(editor); QObject::connect(editor, SIGNAL(modificationChanged(bool)), editorInterface, SIGNAL(changed())); - editor->setEditorInterface(editorInterface); + editor->setEditor(editorInterface); m_context.add(Constants::C_BINEDITOR); if (!m_undoAction) { diff --git a/src/plugins/debugger/memoryagent.cpp b/src/plugins/debugger/memoryagent.cpp index 198bbe3a6cc..f1dc0717baf 100644 --- a/src/plugins/debugger/memoryagent.cpp +++ b/src/plugins/debugger/memoryagent.cpp @@ -93,7 +93,7 @@ void MemoryAgent::createBinEditor(quint64 addr) editor->setProperty(Debugger::Constants::OPENED_BY_DEBUGGER, true); editor->setProperty(Debugger::Constants::OPENED_WITH_MEMORY, true); connect(editor->widget(), - SIGNAL(lazyDataRequested(Core::IEditor *, quint64,bool)), + SIGNAL(dataRequested(Core::IEditor *, quint64,bool)), SLOT(fetchLazyData(Core::IEditor *, quint64,bool))); connect(editor->widget(), SIGNAL(newWindowRequested(quint64)), @@ -109,8 +109,11 @@ void MemoryAgent::createBinEditor(quint64 addr) SLOT(handleEndOfFileRequested(Core::IEditor*))); m_editors << editor; QMetaObject::invokeMethod(editor->widget(), "setNewWindowRequestAllowed"); - QMetaObject::invokeMethod(editor->widget(), "setLazyData", - Q_ARG(quint64, addr), Q_ARG(int, DataRange), Q_ARG(int, BinBlockSize)); + QMetaObject::invokeMethod(editor->widget(), "setSizes", + Q_ARG(quint64, addr), + Q_ARG(int, DataRange), + Q_ARG(bool, false), + Q_ARG(int, BinBlockSize)); } else { showMessageBox(QMessageBox::Warning, tr("No memory viewer available"), @@ -131,15 +134,17 @@ void MemoryAgent::addLazyData(QObject *editorToken, quint64 addr, { IEditor *editor = qobject_cast(editorToken); if (editor && editor->widget()) { - QMetaObject::invokeMethod(editor->widget(), "addLazyData", + QMetaObject::invokeMethod(editor->widget(), "addData", Q_ARG(quint64, addr / BinBlockSize), Q_ARG(QByteArray, ba)); } } void MemoryAgent::provideNewRange(IEditor *editor, quint64 address) { - QMetaObject::invokeMethod(editor->widget(), "setLazyData", - Q_ARG(quint64, address), Q_ARG(int, DataRange), + QMetaObject::invokeMethod(editor->widget(), "setSizes", + Q_ARG(quint64, address), + Q_ARG(int, DataRange), + Q_ARG(bool, false), Q_ARG(int, BinBlockSize)); }