}
}
-void QHexView::setMode(Mode m)
+void QHexView::set_mode(Mode m)
{
mode_ = m;
// so we don't update the viewport here
}
-void QHexView::setData(const DecodeBinaryClass* data)
+void QHexView::set_data(const DecodeBinaryClass* data)
{
data_ = data;
viewport()->update();
}
+unsigned int QHexView::get_bytes_per_line() const
+{
+ return BYTES_PER_LINE;
+}
+
void QHexView::clear()
{
verticalScrollBar()->setValue(0);
return std::make_pair(start, end);
}
+size_t QHexView::create_hex_line(size_t start, size_t end, QString* dest,
+ bool with_offset, bool with_ascii)
+{
+ dest->clear();
+
+ // Determine start address for the row
+ uint64_t row = start / BYTES_PER_LINE;
+ uint64_t offset = row * BYTES_PER_LINE;
+ end = std::min(end, offset + BYTES_PER_LINE);
+
+ if (with_offset)
+ dest->append(QString("%1 ").arg(row * BYTES_PER_LINE, 10, 16, QChar('0')).toUpper());
+
+ initialize_byte_iterator(offset);
+ for (size_t i = offset; i < offset + BYTES_PER_LINE; i++) {
+ uint8_t value = 0;
+
+ if (i < end)
+ value = get_next_byte();
+
+ if ((i < start) || (i >= end))
+ dest->append(" ");
+ else
+ dest->append(QString("%1 ").arg(value, 2, 16, QChar('0')).toUpper());
+ }
+
+ if (with_ascii) {
+ initialize_byte_iterator(offset);
+ for (size_t i = offset; i < end; i++) {
+ uint8_t value = get_next_byte();
+
+ if (i < start)
+ dest->append(' ');
+ else
+ dest->append((char)value);
+ }
+ }
+
+ return end;
+}
+
void QHexView::initialize_byte_iterator(size_t offset)
{
current_chunk_id_ = 0;
public:
QHexView(QWidget *parent = 0);
- void setMode(Mode m);
- void setData(const DecodeBinaryClass* data);
+ void set_mode(Mode m);
+ void set_data(const DecodeBinaryClass* data);
+ unsigned int get_bytes_per_line() const;
void clear();
void showFromOffset(size_t offset);
pair<size_t, size_t> get_selection() const;
+ size_t create_hex_line(size_t start, size_t end, QString* dest,
+ bool with_offset=false, bool with_ascii=false);
+
protected:
void initialize_byte_iterator(size_t offset);
uint8_t get_next_byte(bool* is_next_chunk = nullptr);
const char* SaveTypeNames[SaveTypeCount] = {
"Binary",
- "Hex Dump"
+ "Hex Dump, plain",
+ "Hex Dump, with offset",
+ "Hex Dump, complete"
};
const DecodeBinaryClass* bin_class =
signal_->get_binary_data_class(current_segment_, decoder_, bin_class_id_);
- hex_view_->setData(bin_class);
+ hex_view_->set_data(bin_class);
if (!save_button_->isEnabled())
save_button_->setEnabled(true);
}
}
-void View::save_data_as_hex_dump() const
+void View::save_data_as_hex_dump(bool with_offset, bool with_ascii) const
{
+ assert(decoder_);
+ assert(signal_);
+
+ if (!signal_)
+ return;
+
+ GlobalSettings settings;
+ const QString dir = settings.value("MainWindow/SaveDirectory").toString();
+
+ const QString file_name = QFileDialog::getSaveFileName(
+ parent_, tr("Save Binary Data"), dir, tr("Hex Dumps (*.txt);;All Files (*)"));
+
+ if (file_name.isEmpty())
+ return;
+
+ QFile file(file_name);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ pair<size_t, size_t> selection = hex_view_->get_selection();
+
+ vector<uint8_t> data;
+ signal_->get_merged_binary_data_chunks_by_offset(current_segment_, decoder_,
+ bin_class_id_, selection.first, selection.second, &data);
+
+ QTextStream out_stream(&file);
+
+ uint64_t offset = selection.first;
+ unsigned int n = hex_view_->get_bytes_per_line();
+ QString s;
+ while (offset < selection.second) {
+ size_t end = std::min(selection.second, offset + n);
+ offset = hex_view_->create_hex_line(offset, end, &s, with_offset, with_ascii);
+ out_stream << s << endl;
+ }
+
+ out_stream << endl;
+
+ if (out_stream.status() != QTextStream::Ok) {
+ QMessageBox msg(parent_);
+ msg.setText(tr("Error") + "\n\n" + tr("File %1 could not be written to.").arg(file_name));
+ msg.setStandardButtons(QMessageBox::Ok);
+ msg.setIcon(QMessageBox::Warning);
+ msg.exec();
+ return;
+ }
+ }
}
void View::on_selected_decoder_changed(int index)
if (action)
save_type = action->data().toInt();
- if (save_type == SaveTypeBinary)
- save_data();
- if (save_type == SaveTypeHexDump)
- save_data_as_hex_dump();
+ switch (save_type)
+ {
+ case SaveTypeBinary: save_data(); break;
+ case SaveTypeHexDumpPlain: save_data_as_hex_dump(false, false); break;
+ case SaveTypeHexDumpWithOffset: save_data_as_hex_dump(true, false); break;
+ case SaveTypeHexDumpComplete: save_data_as_hex_dump(true, true); break;
+ }
}
void View::perform_delayed_view_update()