/
githubmirror
/
x64dbg
Обзор
Документация
Войти
/
githubmirror
/
x64dbg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
development
src/gui/Src/Gui/HexEditDialog.cpp
879 строк
27 KB
Duncan Ogilvie
Implement better UX for pattern finding
23 авг 2025, 02:15
23 авг 2025, 02:15
9685327
Код
Авторство
О чём код?
#include <QTextCodec> #include <QCryptographicHash> #include "Configuration.h" #include "HexEditDialog.h" #include "QHexEdit/QHexEdit.h" #include "ui_HexEditDialog.h" #include "Configuration.h" #include "Bridge.h" #include "CodepageSelectionDialog.h" #include "LineEditDialog.h" #include "StringUtil.h" #ifndef AF_INET6 #define AF_INET6 23 // Internetwork Version 6 #endif //AF_INET6 typedef PCTSTR(__stdcall* INETNTOPW)(INT Family, PVOID pAddr, wchar_t* pStringBuf, size_t StringBufSize); HexEditDialog::HexEditDialog(QWidget* parent) : QDialog(parent), ui(new Ui::HexEditDialog) { ui->setupUi(this); ui->editCode->setFont(ConfigFont("HexEdit")); setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) | Qt::WindowMaximizeButtonHint); setModal(true); //modal window //setup text fields ui->lineEditAscii->setEncoding(QTextCodec::codecForName("System")); ui->lineEditUnicode->setEncoding(QTextCodec::codecForName("UTF-16")); ui->chkKeepSize->setChecked(ConfigBool("HexDump", "KeepSize")); ui->chkKeepSize->hide(); ui->chkEntireBlock->hide(); ui->chkFromSelection->hide(); mDataInitialized = false; stringEditorLock = false; fallbackCodec = QTextCodec::codecForLocale(); //setup hex editor mHexEdit = new QHexEdit(this); mHexEdit->setEditFont(ConfigFont("HexEdit")); mHexEdit->setHorizontalSpacing(6); mHexEdit->setOverwriteMode(true); ui->scrollArea->setWidget(mHexEdit); mHexEdit->widget()->setFocus(); connect(mHexEdit, SIGNAL(dataChanged()), this, SLOT(dataChangedSlot())); connect(mHexEdit, SIGNAL(dataEdited()), this, SLOT(dataEditedSlot())); connect(ui->btnCodePage2, SIGNAL(clicked()), this, SLOT(on_btnCodepage_clicked())); connect(ui->chkCRLF, SIGNAL(clicked()), this, SLOT(on_stringEditor_textChanged())); connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(updateStyle())); updateStyle(); updateCodepage(); //The following initialization code is from Data Copy Dialog. mTypes[DataCByte] = FormatType { tr("C-Style BYTE (Hex)"), 16 }; mTypes[DataCWord] = FormatType { tr("C-Style WORD (Hex)"), 12 }; mTypes[DataCDword] = FormatType { tr("C-Style DWORD (Hex)"), 8 }; mTypes[DataCQword] = FormatType { tr("C-Style QWORD (Hex)"), 4 }; mTypes[DataCString] = FormatType { tr("C-Style String"), 1 }; mTypes[DataCUnicodeString] = FormatType { tr("C-Style Unicode String"), 1 }; mTypes[DataCShellcodeString] = FormatType { tr("C-Style Shellcode String"), 1 }; mTypes[DataASMByte] = FormatType { tr("ASM-Style BYTE (Hex)"), 16, "DB"}; mTypes[DataASMWord] = FormatType { tr("ASM-Style WORD (Hex)"), 12, "DW"}; mTypes[DataASMDWord] = FormatType { tr("ASM-Style DWORD (Hex)"), 8, "DD"}; mTypes[DataASMQWord] = FormatType { tr("ASM-Style QWORD (Hex)"), 4, "DQ"}; mTypes[DataASMString] = FormatType { tr("ASM-Style String"), 4 }; mTypes[DataPascalByte] = FormatType { tr("Pascal BYTE (Hex)"), 42 }; mTypes[DataPascalWord] = FormatType { tr("Pascal WORD (Hex)"), 21 }; mTypes[DataPascalDword] = FormatType { tr("Pascal DWORD (Hex)"), 10 }; mTypes[DataPascalQword] = FormatType { tr("Pascal QWORD (Hex)"), 5 }; mTypes[DataPython3Byte] = FormatType { tr("Python 3 BYTE (Hex)"), 1 }; mTypes[DataString] = FormatType { tr("String"), 1 }; mTypes[DataUnicodeString] = FormatType { tr("Unicode String"), 1 }; mTypes[DataUTF8String] = FormatType { tr("UTF8 String"), 1 }; mTypes[DataUCS4String] = FormatType { tr("UCS4 String"), 1 }; mTypes[DataHexStream] = FormatType { tr("Hex Stream"), 1 }; mTypes[DataGUID] = FormatType { tr("GUID"), 1 }; mTypes[DataIPv4] = FormatType { tr("IP Address (IPv4)"), 5 }; mTypes[DataIPv6] = FormatType { tr("IP Address (IPv6)"), 1 }; mTypes[DataBase64] = FormatType { tr("Base64"), 1 }; mTypes[DataMD5] = FormatType { "MD5", 1}; mTypes[DataSHA1] = FormatType { "SHA1", 1}; mTypes[DataSHA256] = FormatType { "SHA256 (SHA-2)", 1}; mTypes[DataSHA512] = FormatType { "SHA512 (SHA-2)", 1}; mTypes[DataSHA256_3] = FormatType { "SHA256 (SHA-3)", 1}; mTypes[DataSHA512_3] = FormatType { "SHA512 (SHA-3)", 1}; for(int i = 0; i < DataLast; i++) ui->listType->addItem(mTypes[i].name); duint lastDataType = ConfigUint("HexDump", "CopyDataType"); lastDataType = std::min(lastDataType, static_cast<duint>(ui->listType->count() - 1)); QModelIndex index = ui->listType->model()->index(lastDataType, 0); ui->listType->setCurrentIndex(index); Config()->loadWindowGeometry(this); } HexEditDialog::~HexEditDialog() { Config()->saveWindowGeometry(this); delete ui; } void HexEditDialog::showKeepSize(bool show) { ui->chkKeepSize->setVisible(show); } void HexEditDialog::setupFindMode(duint rangeStart, duint rangeEnd, duint selectionStart, bool startFromSelection) { mRangeStart = rangeStart; mRangeEnd = rangeEnd; mSelectionStart = selectionStart; // Only show the checkbox if selection is different from range start bool hasSelection = (selectionStart != rangeStart); ui->chkFromSelection->setVisible(hasSelection); ui->chkFromSelection->setChecked(hasSelection ? startFromSelection : false); // Generate range texts using ToPtrString mSearchRangeFromStart = tr("Search range: %1 - %2").arg(ToPtrString(rangeStart)).arg(ToPtrString(rangeEnd)); mSearchRangeFromSelection = tr("Search range: %1 - %2").arg(ToPtrString(selectionStart)).arg(ToPtrString(rangeEnd)); // Update the label updateSearchRangeLabel(); } void HexEditDialog::isDataCopiable(bool copyDataEnabled) { if(copyDataEnabled == false) ui->tabModeSelect->removeTab(2); //This can't be undone! } void HexEditDialog::updateCodepage() { duint lastCodepage; auto allCodecs = QTextCodec::availableCodecs(); if(!BridgeSettingGetUint("Misc", "LastCodepage", &lastCodepage) || lastCodepage >= duint(allCodecs.size())) lastCodec = fallbackCodec; else lastCodec = QTextCodec::codecForName(allCodecs.at(lastCodepage)); ui->lineEditCodepage->setEncoding(lastCodec); ui->lineEditCodepage->setData(mHexEdit->data()); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(mHexEdit->data())); ui->labelLastCodepage->setText(lastCodec->name().constData()); ui->labelLastCodepage2->setText(ui->labelLastCodepage->text()); } void HexEditDialog::updateCodepage(const QByteArray & name) { lastCodec = QTextCodec::codecForName(name); if(!lastCodec) lastCodec = fallbackCodec; ui->lineEditCodepage->setEncoding(lastCodec); ui->lineEditCodepage->setData(mHexEdit->data()); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(mHexEdit->data())); ui->labelLastCodepage->setText(QString(name)); ui->labelLastCodepage2->setText(ui->labelLastCodepage->text()); } bool HexEditDialog::startFromSelection() { return ui->chkFromSelection->isChecked(); } void HexEditDialog::updateStyle() { QString style = QString("QLineEdit { border-style: outset; border-width: 1px; border-color: %1; color: %1; background-color: %2 }").arg(ConfigColor("HexEditTextColor").name(), ConfigColor("HexEditBackgroundColor").name()); ui->lineEditAscii->setStyleSheet(style); ui->lineEditUnicode->setStyleSheet(style); ui->lineEditCodepage->setStyleSheet(style); mHexEdit->setTextColor(ConfigColor("HexEditTextColor")); mHexEdit->setWildcardColor(ConfigColor("HexEditWildcardColor")); mHexEdit->setBackgroundColor(ConfigColor("HexEditBackgroundColor")); mHexEdit->setSelectionColor(ConfigColor("HexEditSelectionColor")); } void HexEditDialog::on_chkKeepSize_toggled(bool checked) { if(!this->isVisible()) return; mHexEdit->setKeepSize(checked); ui->lineEditAscii->setKeepSize(checked); ui->lineEditUnicode->setKeepSize(checked); ui->lineEditCodepage->setKeepSize(checked); Config()->setBool("HexDump", "KeepSize", checked); } void HexEditDialog::dataChangedSlot() { // Allows initialization of the data by calling setData() on mHexEdit. if(!mDataInitialized) { QByteArray data = mHexEdit->data(); ui->lineEditAscii->setData(data); ui->lineEditUnicode->setData(data); ui->lineEditCodepage->setData(data); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(data)); checkDataRepresentable(0); printData((DataType)ui->listType->currentIndex().row()); mDataInitialized = true; } } void HexEditDialog::dataEditedSlot() { QByteArray data = mHexEdit->data(); ui->lineEditAscii->setData(data); ui->lineEditUnicode->setData(data); ui->lineEditCodepage->setData(data); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(data)); printData((DataType)ui->listType->currentIndex().row()); checkDataRepresentable(0); } void HexEditDialog::on_lineEditAscii_dataEdited() { QByteArray data = ui->lineEditAscii->data(); data = resizeData(data); ui->lineEditUnicode->setData(data); ui->lineEditCodepage->setData(data); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(data)); printData((DataType)ui->listType->currentIndex().row()); mHexEdit->setData(data); } void HexEditDialog::on_lineEditUnicode_dataEdited() { QByteArray data = ui->lineEditUnicode->data(); data = resizeData(data); ui->lineEditAscii->setData(data); ui->lineEditCodepage->setData(data); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(data)); printData((DataType)ui->listType->currentIndex().row()); mHexEdit->setData(data); } void HexEditDialog::on_stringEditor_textChanged() //stack overflow? { if(stringEditorLock || ui->tabModeSelect->currentIndex() != 1) return; stringEditorLock = true; QTextCodec::ConverterState converter(QTextCodec::IgnoreHeader); //Don't add BOM for UTF-16 QString text = ui->stringEditor->document()->toPlainText(); if(ui->chkCRLF->checkState() == Qt::Checked) { text = text.replace(QChar('\n'), "\r\n"); text = text.replace("\r\r\n", "\r\n"); } QByteArray data = lastCodec->fromUnicode(text.constData(), text.size(), &converter); data = resizeData(data); ui->lineEditAscii->setData(data); ui->lineEditUnicode->setData(data); ui->lineEditCodepage->setData(data); printData((DataType)ui->listType->currentIndex().row()); mHexEdit->setData(data); stringEditorLock = false; } void HexEditDialog::on_lineEditCodepage_dataEdited() { QByteArray data = ui->lineEditCodepage->data(); data = resizeData(data); ui->lineEditAscii->setData(data); ui->lineEditUnicode->setData(data); ui->stringEditor->document()->setPlainText(lastCodec->toUnicode(data)); mHexEdit->setData(data); } QByteArray HexEditDialog::resizeData(QByteArray & data) { // truncate or pad the data if(mHexEdit->keepSize()) { int dataSize = mHexEdit->data().size(); int data_size = data.size(); if(dataSize < data_size) data.resize(dataSize); else if(dataSize > data_size) data.append(QByteArray(dataSize - data_size, 0)); } return data; } void HexEditDialog::on_btnCodepage_clicked() { CodepageSelectionDialog codepageDialog(this); if(codepageDialog.exec() != QDialog::Accepted) return; stringEditorLock = true; updateCodepage(codepageDialog.getSelectedCodepage()); checkDataRepresentable(3); checkDataRepresentable(4); stringEditorLock = false; } bool HexEditDialog::checkDataRepresentable(int mode) { QTextCodec* codec; QLabel* label; if(mode == 1) { codec = QTextCodec::codecForName("System"); label = ui->labelWarningCodepageASCII; } else if(mode == 2) { codec = QTextCodec::codecForName("UTF-16"); label = ui->labelWarningCodepageUTF; } else if(mode == 3) { codec = lastCodec; label = ui->labelWarningCodepage; } else if(mode == 4) { codec = lastCodec; label = ui->labelWarningCodepageString; } else { bool isRepresentable; isRepresentable = checkDataRepresentable(1); isRepresentable = checkDataRepresentable(2) && isRepresentable; isRepresentable = checkDataRepresentable(3) && isRepresentable; isRepresentable = checkDataRepresentable(4) && isRepresentable; return isRepresentable; } if(codec == nullptr) { label->show(); return false; } QString test; QByteArray original = mHexEdit->data(); QTextCodec::ConverterState converter(QTextCodec::IgnoreHeader); test = codec->toUnicode(original); QByteArray test2; test2 = codec->fromUnicode(test.constData(), test.size(), &converter); if(test2.size() < original.size() || memcmp(test2.constData(), original.constData(), original.size()) != 0) { label->show(); return false; } else { label->hide(); return true; } } //The following code is from Data Copy Dialog. static QString printEscapedString(bool & bPrevWasHex, int ch, const char* hexFormat) { QString data = ""; switch(ch) //escaping { case '\t': data = "\\t"; bPrevWasHex = false; break; case '\f': data = "\\f"; bPrevWasHex = false; break; case '\v': data = "\\v"; bPrevWasHex = false; break; case '\n': data = "\\n"; bPrevWasHex = false; break; case '\r': data = "\\r"; bPrevWasHex = false; break; case '\\': data = "\\\\"; bPrevWasHex = false; break; case '\"': data = "\\\""; bPrevWasHex = false; break; case '\a': data = "\\a"; bPrevWasHex = false; break; case '\b': data = "\\b"; bPrevWasHex = false; break; default: if(ch >= ' ' && ch <= '~') { if(bPrevWasHex && isxdigit(ch)) data = QString().sprintf("\"\"%c", ch); else data = QString().sprintf("%c", ch); bPrevWasHex = false; } else { bPrevWasHex = true; data = QString().sprintf(hexFormat, ch); } break; } return data; } template<typename T> static QString formatLoop(const QByteArray & bytes, const HexEditDialog::FormatType & type, QString(*format)(T)) { QString data; int count = bytes.size() / sizeof(T); for(int i = 0; i < count; i++) { if(i) { data += ','; if(type.itemsPerLine > 0 && i % type.itemsPerLine == 0) { data += '\n'; data += type.linePrefix; data += ' '; } else { data += ' '; } } data += format(((const T*)bytes.constData())[i]); } return data; } static QString printHash(const QByteArray & bytes, QCryptographicHash::Algorithm algorithm) { QCryptographicHash temp(algorithm); temp.addData((const char*)bytes.constData(), bytes.size()); return temp.result().toHex().toUpper(); } void HexEditDialog::printData(DataType type) { ui->editCode->clear(); QString data; QByteArray mData = mHexEdit->data(); switch(type) { case DataCByte: { data = "{\n" + formatLoop<unsigned char>(mData, mTypes[mIndex], [](unsigned char n) { return QString().sprintf("0x%02X", n); }) + "\n};"; } break; case DataCWord: { data = "{\n" + formatLoop<unsigned short>(mData, mTypes[mIndex], [](unsigned short n) { return QString().sprintf("0x%04X", n); }) + "\n};"; } break; case DataCDword: { data = "{\n" + formatLoop<unsigned int>(mData, mTypes[mIndex], [](unsigned int n) { return QString().sprintf("0x%08X", n); }) + "\n};"; } break; case DataCQword: { data = "{\n" + formatLoop<unsigned long long>(mData, mTypes[mIndex], [](unsigned long long n) { return QString().sprintf("0x%016llX", n); }) + "\n};"; } break; case DataCString: { data += "\""; bool bPrevWasHex = false; for(int i = 0; i < mData.size(); i++) { byte_t ch = mData.at(i); data += printEscapedString(bPrevWasHex, ch, "\\x%02X"); } data += "\""; } break; case DataCUnicodeString: //extended ASCII + hex escaped only { data += "L\""; int numwchars = mData.size() / sizeof(unsigned short); bool bPrevWasHex = false; for(int i = 0; i < numwchars; i++) { unsigned short ch = ((unsigned short*)mData.constData())[i]; if((ch & 0xFF00) == 0) //extended ASCII { data += printEscapedString(bPrevWasHex, ch, "\\x%04X"); } else //full unicode character { bPrevWasHex = true; data += QString().sprintf("\\x%04X", ch); } } data += "\""; } break; case DataCShellcodeString: { data += "\""; for(int i = 0; i < mData.size(); i++) { byte_t ch = mData.at(i); data += QString().sprintf("\\x%02X", ch); } data += "\""; } break; case DataString: { data = QTextCodec::codecForName("System")->makeDecoder()->toUnicode((const char*)(mData.constData()), mData.size()); } break; case DataUnicodeString: { data = QString::fromUtf16((const ushort*)(mData.constData()), mData.size() / 2); } break; case DataUTF8String: { data = QString::fromUtf8((const char*)mData.constData(), mData.size()); } break; case DataUCS4String: { data = QString::fromUcs4((const uint*)(mData.constData()), mData.size() / 4); } break; case DataASMByte: { data = "array DB " + formatLoop<unsigned char>(mData, mTypes[mIndex], [](unsigned char n) { QString value = QString().sprintf("%02Xh", n); if(value.at(0).isLetter()) value.insert(0, '0'); return value; }); } break; case DataASMWord: { data = "array DW " + formatLoop<unsigned short>(mData, mTypes[mIndex], [](unsigned short n) { QString value = QString().sprintf("%04Xh", n); if(value.at(0).isLetter()) value.insert(0, '0'); return value; }); } break; case DataASMDWord: { data = "array DD " + formatLoop<unsigned int>(mData, mTypes[mIndex], [](unsigned int n) { QString value = QString().sprintf("%08Xh", n); if(value.at(0).isLetter()) value.insert(0, '0'); return value; }); } break; case DataASMQWord: { data = "array DQ " + formatLoop<unsigned long long>(mData, mTypes[mIndex], [](unsigned long long n) { QString value = QString().sprintf("%016llXh", n); if(value.at(0).isLetter()) value.insert(0, '0'); return value; }); } break; case DataASMString: { QString line; int index = 0; bool bPrevWasHex = false; while(index < mData.size()) { QChar chr = QChar(mData.at(index)); if(chr >= ' ' && chr <= '~') { if(line.length() == 0) line += "\""; if(bPrevWasHex) { line += ",\""; bPrevWasHex = false; } line += chr; } else { QString asmhex = QString().sprintf("%02Xh", (unsigned char)mData.at(index)); if(asmhex.at(0).isLetter()) asmhex.insert(0, "0"); if(line.length() == 0) line += asmhex; else if(!bPrevWasHex) line += "\"," + asmhex; else line += "," + asmhex; bPrevWasHex = true; } index++; } if(!bPrevWasHex) line += "\""; data = line; } break; case DataPascalByte: { data += QString().sprintf("Array [1..%u] of Byte = (\n", mData.size()); data += formatLoop<unsigned char>(mData, mTypes[mIndex], [](unsigned char n) { return QString().sprintf("$%02X", n); }); data += "\n);"; } break; case DataPascalWord: { data += QString().sprintf("Array [1..%u] of Word = (\n", mData.size() / 2); data += formatLoop<unsigned short>(mData, mTypes[mIndex], [](unsigned short n) { return QString().sprintf("$%04X", n); }); data += "\n);"; } break; case DataPascalDword: { data += QString().sprintf("Array [1..%u] of Dword = (\n", mData.size() / 4); data += formatLoop<unsigned int>(mData, mTypes[mIndex], [](unsigned int n) { return QString().sprintf("$%08X", n); }); data += "\n);"; } break; case DataPascalQword: { data += QString().sprintf("Array [1..%u] of Int64 = (\n", mData.size() / 8); data += formatLoop<unsigned long long>(mData, mTypes[mIndex], [](unsigned long long n) { return QString().sprintf("$%016llX", n); }); data += "\n);"; } break; case DataPython3Byte: { data += "b\""; for(int i = 0; i < mData.size(); i++) { byte_t ch = mData.at(i); data += QString().sprintf("\\x%02X", ch); } data += "\""; } break; case DataHexStream: { for(int i = 0; i < mData.size(); i++) { byte_t ch = mData.at(i); data += QString().sprintf("%02X", ch); } } break; case DataGUID: { data = formatLoop<GUID>(mData, mTypes[mIndex], [](GUID guid) { return QString().sprintf("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); }); } break; case DataIPv4: { int numIPs = mData.size() / 4; for(int i = 0; i < numIPs; i++) { if(i) { if((i % mTypes[mIndex].itemsPerLine) == 0) data += "\n"; else data += ", "; } data += QString("%1.%2.%3.%4").arg((unsigned char)(mData.constData()[i * 4])).arg((unsigned char)(mData.constData()[i * 4 + 1])) .arg((unsigned char)(mData.constData()[i * 4 + 2])).arg((unsigned char)(mData.constData()[i * 4 + 3])); } } break; case DataIPv6: { INETNTOPW InetNtopW; int numIPs = mData.size() / 16; HMODULE hWinsock = LoadLibraryW(L"ws2_32.dll"); InetNtopW = INETNTOPW(GetProcAddress(hWinsock, "InetNtopW")); if(InetNtopW) { for(int i = 0; i < numIPs; i++) { if(i) { if((i % mTypes[mIndex].itemsPerLine) == 0) data += "\n"; else data += ", "; } wchar_t buffer[56]; memset(buffer, 0, sizeof(buffer)); InetNtopW(AF_INET6, const_cast<char*>(mData.constData() + i * 16), buffer, 56); data += QString::fromWCharArray(buffer); } } else //fallback for Windows XP { for(int i = 0; i < numIPs; i++) { if(i) { if((i % mTypes[mIndex].itemsPerLine) == 0) data += "\n"; else data += ", "; } QString temp(QByteArray(reinterpret_cast<const char*>(mData.constData() + i * 16), 16).toHex()); temp.insert(28, ':'); temp.insert(24, ':'); temp.insert(20, ':'); temp.insert(16, ':'); temp.insert(12, ':'); temp.insert(8, ':'); temp.insert(4, ':'); data += temp; } } FreeLibrary(hWinsock); } break; case DataBase64: { data = QByteArray(reinterpret_cast<const char*>(mData.constData()), mData.size()).toBase64().constData(); } break; case DataMD5: data = printHash(mData, QCryptographicHash::Md5); break; case DataSHA1: data = printHash(mData, QCryptographicHash::Sha1); break; case DataSHA256: data = printHash(mData, QCryptographicHash::Sha256); break; case DataSHA512: data = printHash(mData, QCryptographicHash::Sha512); break; case DataSHA256_3: data = printHash(mData, QCryptographicHash::Sha3_256); break; case DataSHA512_3: data = printHash(mData, QCryptographicHash::Sha3_512); break; default: break; } ui->editCode->setPlainText(data); } void HexEditDialog::on_listType_currentRowChanged(int currentRow) { mIndex = currentRow; ui->spinBox->setValue(mTypes[mIndex].itemsPerLine); printData(DataType(mIndex)); Config()->setUint("HexDump", "CopyDataType", currentRow); } void HexEditDialog::on_buttonCopy_clicked() { Bridge::CopyToClipboard(ui->editCode->toPlainText()); } void HexEditDialog::on_spinBox_valueChanged(int value) { mTypes[mIndex].itemsPerLine = value; printData(DataType(mIndex)); } void HexEditDialog::on_chkFromSelection_toggled(bool /*checked*/) { updateSearchRangeLabel(); } void HexEditDialog::updateSearchRangeLabel() { // Only update if we have valid range data if(mRangeStart == 0 && mRangeEnd == 0) return; const QString & text = ui->chkFromSelection->isChecked() ? mSearchRangeFromSelection : mSearchRangeFromStart; if(ui->labelSearchRange) ui->labelSearchRange->setText(text); }