Implemented restore functionality in snapshot diff window
This commit is contained in:
@@ -80,6 +80,17 @@ namespace Bloom::Widgets
|
|||||||
this->dataBPrimaryLabel->setText("Current");
|
this->dataBPrimaryLabel->setText("Current");
|
||||||
this->dataASecondaryLabel->setText(snapshotA.createdDate.toString("dd/MM/yyyy hh:mm"));
|
this->dataASecondaryLabel->setText(snapshotA.createdDate.toString("dd/MM/yyyy hh:mm"));
|
||||||
this->dataBSecondaryLabel->setVisible(false);
|
this->dataBSecondaryLabel->setVisible(false);
|
||||||
|
|
||||||
|
this->restoreBytesAction = new ContextMenuAction("Restore Selection", std::nullopt, this);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
this->restoreBytesAction,
|
||||||
|
&ContextMenuAction::invoked,
|
||||||
|
this,
|
||||||
|
[this] (const std::unordered_map<Targets::TargetMemoryAddress, ByteItem*>& selectedByteItemsByAddress) {
|
||||||
|
this->restoreSelectedBytes(selectedByteItemsByAddress, true);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnapshotDiff::refreshB(
|
void SnapshotDiff::refreshB(
|
||||||
@@ -154,8 +165,6 @@ namespace Bloom::Widgets
|
|||||||
this->syncHexViewerHoverButton = toolBar->findChild<SvgToolButton*>("sync-hover-btn");
|
this->syncHexViewerHoverButton = toolBar->findChild<SvgToolButton*>("sync-hover-btn");
|
||||||
this->syncHexViewerSelectionButton = toolBar->findChild<SvgToolButton*>("sync-selection-btn");
|
this->syncHexViewerSelectionButton = toolBar->findChild<SvgToolButton*>("sync-selection-btn");
|
||||||
|
|
||||||
this->restoreBytesAction = new ContextMenuAction("Restore Selection", std::nullopt, this);
|
|
||||||
|
|
||||||
this->dataAContainer = this->container->findChild<QWidget*>("data-a-container");
|
this->dataAContainer = this->container->findChild<QWidget*>("data-a-container");
|
||||||
this->dataBContainer = this->container->findChild<QWidget*>("data-b-container");
|
this->dataBContainer = this->container->findChild<QWidget*>("data-b-container");
|
||||||
|
|
||||||
@@ -203,6 +212,9 @@ namespace Bloom::Widgets
|
|||||||
this->bottomBar = this->container->findChild<QWidget*>("bottom-bar");
|
this->bottomBar = this->container->findChild<QWidget*>("bottom-bar");
|
||||||
this->bottomBarLayout = this->bottomBar->findChild<QHBoxLayout*>();
|
this->bottomBarLayout = this->bottomBar->findChild<QHBoxLayout*>();
|
||||||
|
|
||||||
|
this->taskProgressIndicator = new TaskProgressIndicator(this);
|
||||||
|
this->bottomBarLayout->insertWidget(0, this->taskProgressIndicator);
|
||||||
|
|
||||||
this->setSyncHexViewerSettingsEnabled(this->settings.syncHexViewerSettings);
|
this->setSyncHexViewerSettingsEnabled(this->settings.syncHexViewerSettings);
|
||||||
this->setSyncHexViewerScrollEnabled(this->settings.syncHexViewerScroll);
|
this->setSyncHexViewerScrollEnabled(this->settings.syncHexViewerScroll);
|
||||||
this->setSyncHexViewerHoverEnabled(this->settings.syncHexViewerHover);
|
this->setSyncHexViewerHoverEnabled(this->settings.syncHexViewerHover);
|
||||||
@@ -256,7 +268,10 @@ namespace Bloom::Widgets
|
|||||||
void SnapshotDiff::onHexViewerAReady() {
|
void SnapshotDiff::onHexViewerAReady() {
|
||||||
this->hexViewerWidgetB->setOther(this->hexViewerWidgetA);
|
this->hexViewerWidgetB->setOther(this->hexViewerWidgetA);
|
||||||
|
|
||||||
// this->hexViewerWidgetA->addExternalContextMenuAction(this->restoreBytesAction);
|
if (this->restoreBytesAction != nullptr) {
|
||||||
|
this->hexViewerWidgetA->addExternalContextMenuAction(this->restoreBytesAction);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->memoryDescriptor.type == Targets::TargetMemoryType::RAM) {
|
if (this->memoryDescriptor.type == Targets::TargetMemoryType::RAM) {
|
||||||
this->hexViewerWidgetA->setStackPointer(this->stackPointerA);
|
this->hexViewerWidgetA->setStackPointer(this->stackPointerA);
|
||||||
}
|
}
|
||||||
@@ -289,4 +304,114 @@ namespace Bloom::Widgets
|
|||||||
this->settings.syncHexViewerSelection = enabled;
|
this->settings.syncHexViewerSelection = enabled;
|
||||||
this->syncHexViewerSelectionButton->setChecked(this->settings.syncHexViewerSelection);
|
this->syncHexViewerSelectionButton->setChecked(this->settings.syncHexViewerSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SnapshotDiff::restoreSelectedBytes(
|
||||||
|
const std::unordered_map<Targets::TargetMemoryAddress, ByteItem*>& selectedByteItemsByAddress,
|
||||||
|
bool confirmationPromptEnabled
|
||||||
|
) {
|
||||||
|
auto sortedByteItemsByAddress = std::map<Targets::TargetMemoryAddress, ByteItem*>();
|
||||||
|
|
||||||
|
for (const auto& pair : selectedByteItemsByAddress) {
|
||||||
|
if (pair.second->excluded) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortedByteItemsByAddress.insert(pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sortedByteItemsByAddress.empty()) {
|
||||||
|
// The user has only selected bytes that are within an excluded region - nothing to do here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmationPromptEnabled) {
|
||||||
|
auto* confirmationDialog = new ConfirmationDialog(
|
||||||
|
"Restore selected bytes",
|
||||||
|
"This operation will write " + QString::number(sortedByteItemsByAddress.size())
|
||||||
|
+ " byte(s) to the target's "
|
||||||
|
+ QString(this->memoryDescriptor.type == Targets::TargetMemoryType::EEPROM ? "EEPROM" : "RAM")
|
||||||
|
+ ".<br/><br/>Are you sure you want to proceed?",
|
||||||
|
"Proceed",
|
||||||
|
std::nullopt,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
confirmationDialog,
|
||||||
|
&ConfirmationDialog::confirmed,
|
||||||
|
this,
|
||||||
|
[this, selectedByteItemsByAddress] {
|
||||||
|
this->restoreSelectedBytes(selectedByteItemsByAddress, false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
confirmationDialog->show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto writeBlocks = std::vector<WriteTargetMemory::Block>();
|
||||||
|
|
||||||
|
Targets::TargetMemoryAddress blockStartAddress = sortedByteItemsByAddress.begin()->first;
|
||||||
|
Targets::TargetMemoryAddress blockEndAddress = blockStartAddress;
|
||||||
|
|
||||||
|
for (const auto& [address, byteItem] : sortedByteItemsByAddress) {
|
||||||
|
if (address > (blockEndAddress + 1)) {
|
||||||
|
// Commit the block
|
||||||
|
const auto dataBeginOffset = blockStartAddress - this->memoryDescriptor.addressRange.startAddress;
|
||||||
|
const auto dataEndOffset = blockEndAddress - this->memoryDescriptor.addressRange.startAddress + 1;
|
||||||
|
|
||||||
|
writeBlocks.emplace_back(
|
||||||
|
blockStartAddress,
|
||||||
|
Targets::TargetMemoryBuffer(
|
||||||
|
this->hexViewerDataA->begin() + dataBeginOffset,
|
||||||
|
this->hexViewerDataA->begin() + dataEndOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
blockStartAddress = address;
|
||||||
|
blockEndAddress = address;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockEndAddress = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto dataBeginOffset = blockStartAddress - this->memoryDescriptor.addressRange.startAddress;
|
||||||
|
const auto dataEndOffset = blockEndAddress - this->memoryDescriptor.addressRange.startAddress + 1;
|
||||||
|
|
||||||
|
writeBlocks.emplace_back(
|
||||||
|
blockStartAddress,
|
||||||
|
Targets::TargetMemoryBuffer(
|
||||||
|
this->hexViewerDataA->begin() + dataBeginOffset,
|
||||||
|
this->hexViewerDataA->begin() + dataEndOffset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto after = [this, writeBlocks] {
|
||||||
|
auto& hexViewerDataB = this->hexViewerDataB.value();
|
||||||
|
|
||||||
|
for (const auto& writeBlock : writeBlocks) {
|
||||||
|
std::copy(
|
||||||
|
writeBlock.data.begin(),
|
||||||
|
writeBlock.data.end(),
|
||||||
|
hexViewerDataB.begin()
|
||||||
|
+ (writeBlock.startAddress - this->memoryDescriptor.addressRange.startAddress)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->hexViewerWidgetB->updateValues();
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto writeMemoryTask = QSharedPointer<WriteTargetMemory>(
|
||||||
|
new WriteTargetMemory(this->memoryDescriptor, std::move(writeBlocks)),
|
||||||
|
&QObject::deleteLater
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(writeMemoryTask.get(), &WriteTargetMemory::targetMemoryWritten, this, after);
|
||||||
|
|
||||||
|
this->taskProgressIndicator->addTask(writeMemoryTask);
|
||||||
|
InsightWorker::queueTask(writeMemoryTask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ namespace Bloom::Widgets
|
|||||||
QWidget* bottomBar = nullptr;
|
QWidget* bottomBar = nullptr;
|
||||||
QHBoxLayout* bottomBarLayout = nullptr;
|
QHBoxLayout* bottomBarLayout = nullptr;
|
||||||
|
|
||||||
|
TaskProgressIndicator* taskProgressIndicator = nullptr;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void onHexViewerAReady();
|
void onHexViewerAReady();
|
||||||
@@ -107,5 +109,10 @@ namespace Bloom::Widgets
|
|||||||
void setSyncHexViewerScrollEnabled(bool enabled);
|
void setSyncHexViewerScrollEnabled(bool enabled);
|
||||||
void setSyncHexViewerHoverEnabled(bool enabled);
|
void setSyncHexViewerHoverEnabled(bool enabled);
|
||||||
void setSyncHexViewerSelectionEnabled(bool enabled);
|
void setSyncHexViewerSelectionEnabled(bool enabled);
|
||||||
|
|
||||||
|
void restoreSelectedBytes(
|
||||||
|
const std::unordered_map<Targets::TargetMemoryAddress, ByteItem*>& selectedByteItemsByAddress,
|
||||||
|
bool confirmationPromptEnabled
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user