blob: 39053d25b60052a0ca3ff27c45d7e574ac0f8fe9 [file] [log] [blame] [raw]
/* PE Header Editor
Copyright 2007-2014 PC GO Ld.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "options.h"
#include "ui_options.h"
#include "pe-struct.h"
#include <assert.h>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QSettings>
#include <QtGui/QCloseEvent>
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
is_modified = false;
pe = NULL;
set_current_file(0);
ui->ValueReference_characteristics->resizeColumnToContents(0);
ui->ValueReference_dll_characteristics->resizeColumnToContents(0);
ui->ValueReference_machine->resizeColumnToContents(0);
ui->ValueReference_magic->resizeColumnToContents(0);
ui->ValueReference_subsystem->resizeColumnToContents(0);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::load(const QString &filename) {
QFile file(filename, this);
if(!file.open(QFile::ReadOnly)) {
QString msg = tr("Load file %1 failed").arg(filename);
QMessageBox::warning(this, 0, msg);
ui->statusBar->showMessage(msg, 10);
return;
}
file.seek(0x3c);
QDataStream s(&file);
if(s.readRawData((char *)&pe_offset, sizeof pe_offset) < 1) {
QString msg = tr("Cannot locate the PE header");
QMessageBox::warning(this, 0, msg);
goto failed;
}
if(!pe_offset) {
QString msg = tr("Unexcepted PE offset, %1 may not a valid PE file").arg(filename);
QMessageBox::warning(this, 0, msg);
goto failed;
}
file.seek(pe_offset);
if(!pe) pe = new PortableExecutable;
if(s.readRawData((char *)pe, sizeof(PortableExecutable)) < 1) {
QString msg = tr("Cannot read PE header");
QMessageBox::warning(this, 0, msg);
goto failed;
}
//qDebug("pe->pe_signature = 0x%x", pe->pe_signature);
if(pe->pe_signature != 0x4550) {
QString msg = tr("The PE signature not found, %1 may not a valid PE file\n").arg(filename);
QMessageBox::warning(this, 0, msg);
goto failed;
}
update_table();
ui->TreeWidget->resizeColumnToContents(0);
ui->TreeWidget->resizeColumnToContents(2);
ui->TreeWidget->setEnabled(true);
ui->action_SaveAs->setEnabled(true);
ui->ReferenceBrowser->setEnabled(true);
set_current_file(filename);
return;
failed:
if(pe) {
delete pe;
pe = NULL;
}
file.close();
}
void MainWindow::open_file() {
if(!maybe_save()) return;
QString filename = QFileDialog::getOpenFileName(this, NULL, NULL, NULL, NULL, QFileDialog::DontUseNativeDialog);
if(!filename.isEmpty()) load(filename);
}
bool MainWindow::save_file(const QString &filename) {
if(!QFile::exists(current_file)) {
QString msg = tr("Cannot save because the file %1 is removed").arg(current_file);
QMessageBox::warning(this, 0, msg);
ui->statusBar->showMessage(msg, 10);
return false;
}
QFile old_file(current_file, this);
if(!old_file.copy(filename)) {
QString msg = tr("Cannot create file %1 for copying").arg(filename);
QMessageBox::warning(this, 0, msg);
ui->statusBar->showMessage(msg, 10);
return false;
}
set_current_file(filename);
old_file.close();
return is_modified ? save_file() : true;
}
bool MainWindow::save_file() {
if(!QFile::exists(current_file)) {
QString msg = tr("Cannot save because the file %1 is removed").arg(current_file);
QMessageBox::warning(this, 0, msg);
ui->statusBar->showMessage(msg, 10);
return true; // Returns true because we can't save this file any more
}
if(config->value("SavingConfirm", true).toBool()) {
if(QMessageBox::information(this, "PE Header Editor", tr("Are you sure you want to overwrite this file?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
return false;
}
}
QFile file(current_file, this);
// XXX: If we use QFile::WriteOnly, the file will be truncated, that is a bug of Qt?
if(!file.open(QFile::ReadWrite)) {
QString msg = tr("Cannot open file %1 for writing").arg(current_file);
QMessageBox::warning(this, 0, msg);
ui->statusBar->showMessage(msg, 10);
return false;
}
file.seek(pe_offset);
QDataStream s(&file);
if(s.writeRawData((const char *)pe, sizeof(PortableExecutable)) < 1) {
QString msg = tr("Write failed");
QMessageBox::warning(this, 0, msg);
ui->statusBar->showMessage(msg, 10);
return false;
}
file.close();
ui->statusBar->showMessage(tr("File %1 saved").arg(current_file));
set_modified(false);
return true;
}
bool MainWindow::save_file_as() {
QString filename = QFileDialog::getSaveFileName(this, tr("Save As"), current_file, NULL, NULL, QFileDialog::DontUseNativeDialog);
if(filename.isEmpty()) return false;
return save_file(filename);
}
void MainWindow::modified() {
set_modified(true);
}
void MainWindow::set_modified(bool mod) {
setWindowModified(mod);
is_modified = mod;
ui->action_Save->setEnabled(mod);
}
bool MainWindow::maybe_save() {
if(is_modified) {
QMessageBox::StandardButton r = QMessageBox::warning(this, 0,
tr("The table has been modified.\nDo you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
if(r == QMessageBox::Save) return save_file();
if(r == QMessageBox::Cancel) return false;
}
return true;
}
QString MainWindow::stripped_name(const QString &filename) {
return QFileInfo(filename).fileName();
}
void MainWindow::set_current_file(const QString &filename) {
//static int seq_number = 1;
//is_untitled = filename.isEmpty();
//if(is_untitled) {
if(filename.isEmpty()) {
setWindowTitle(tr("PE Header Editor"));
} else {
current_file = QFileInfo(filename).canonicalFilePath();
setWindowTitle(QString("%1[*] - %2").arg(stripped_name(current_file)).arg(tr("PE Header Editor")));
}
is_modified = false;
setWindowModified(false);
}
/*
void MainWindow::init_value_reference() {
QTreeWidget
}*/
void MainWindow::set_pe_header_item(const QString &name, uint8_t value, const QString &comment) {
QString v;
v.sprintf(config->value("Hexadecimal", true).toBool() ? "0x%hhx" : "%hhu", value);
set_pe_header_item(name, v, comment, "uint8");
}
void MainWindow::set_pe_header_item(const QString &name, uint16_t value, const QString &comment) {
QString v;
v.sprintf(config->value("Hexadecimal", true).toBool() ? "0x%hhx" : "%hhu", value);
set_pe_header_item(name, v, comment, "uint16");
}
void MainWindow::set_pe_header_item(const QString &name, uint32_t value, const QString &comment) {
QString v;
v.sprintf(config->value("Hexadecimal", true).toBool() ? "0x%hhx" : "%hhu", value);
set_pe_header_item(name, v, comment, "uint32");
}
void MainWindow::set_pe_header_item(const QString &name, const QString &value, const QString &comment, const QString &type) {
//qDebug("function: add_pe_header_item(%s, %s, %s, %s)", name.toLocal8Bit().data(), value.toLocal8Bit().data(), comment.toLocal8Bit().data(), type.toLocal8Bit().data());
qDebug() << value;
QTreeWidgetItem *item;
QList<QTreeWidgetItem *> r = ui->TreeWidget->findItems(name, Qt::MatchFixedString | Qt::MatchCaseSensitive, 0);
int exists = r.length();
if(exists) {
assert(exists == 1);
item = r[0];
} else {
item = new QTreeWidgetItem;
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
item->setText(0, name);
item->setText(1, type);
item->setText(2, value);
item->setText(3, comment);
if(!exists) ui->TreeWidget->addTopLevelItem(item);
}
QString MainWindow::get_comment_from_value_reference(const QTreeWidget *value_reference, const QString &value, bool bit_field) {
int value_count = value_reference->topLevelItemCount();
//if(!value_count) return QString();
while(value_count--) {
QTreeWidgetItem *value_item = value_reference->topLevelItem(value_count);
if(bit_field) {
uint32_t v1 = value.toUInt(NULL, 16);
uint32_t v2 = value_item->text(0).toUInt(NULL, 16);
if((v1 & v2) == v2) return value_item->text(1);
} else if(value_item->text(0) == value) return value_item->text(1);
}
return QString();
}
QString MainWindow::get_comment_and_update(const QString &name, uint32_t value, bool update_struct, bool update_reference) {
if(name == "machine") {
if(update_struct) pe->machine = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Machine</h4>\nWhat machine the file was compiled for."));
ui->stackedWidget->setCurrentWidget(ui->page_machine);
return QString();
}
QString v;
v.sprintf("0x%x", value);
return get_comment_from_value_reference(ui->ValueReference_machine, v);
} else if(name == "sections_count") {
if(update_struct) pe->sections_count = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Sections Count</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "time_stamp") {
if(update_struct) pe->time_stamp = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Time Stamp</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "symbol_table_pointer") {
if(update_struct) pe->symbol_table_pointer = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Symbol Table Pointer</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "symbols_count") {
if(update_struct) pe->symbols_count = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Symbols Count</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "optional_header_size") {
if(update_struct) pe->optional_header_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Optional Header Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "characteristics") {
if(update_struct) pe->characteristics = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Characteristics</h4>\nA field of bit flags."));
ui->stackedWidget->setCurrentWidget(ui->page_characteristics);
return QString();
}
QString v;
v.sprintf("0x%x", value);
return get_comment_from_value_reference(ui->ValueReference_characteristics, v, true);
} else if(name == "magic") {
if(update_struct) pe->magic = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Magic</h4>\nFor signature"));
ui->stackedWidget->setCurrentWidget(ui->page_magic);
}
QString v;
v.sprintf("0x%x", value);
return get_comment_from_value_reference(ui->ValueReference_magic, v);
} else if(name == "major_linker_version") {
if(update_struct) pe->major_linker_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Major Linker Version</h4>\nThe version of the linker used to create the PE."));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "minor_linker_version") {
if(update_struct) pe->minor_linker_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Minor Linker Version</h4>\nThe version of the linker used to create the PE."));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "code_size") {
if(update_struct) pe->code_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Code Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "initialized_data_size") {
if(update_struct) pe->initialized_data_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Initialized Data Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "uninitialized_data_size") {
if(update_struct) pe->uninitialized_data_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Uninitialized Data Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "entry_point_address") {
if(update_struct) pe->entry_point_address = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Entry Point Address</h4>\nThe RVA of the entry point to the executable."));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "code_base") {
if(update_struct) pe->code_base = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Code Base</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "data_base") {
if(update_struct) pe->data_base = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Data Base</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "image_base") {
if(update_struct) pe->image_base = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Image Base</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "section_alignment") {
if(update_struct) pe->section_alignment = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Section Alignment</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "file_alignment") {
if(update_struct) pe->file_alignment = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>File Alignment</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "major_os_version") {
if(update_struct) pe->major_os_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Major OS Version</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "minor_os_version") {
if(update_struct) pe->minor_os_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Minor OS Version</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "major_image_version") {
if(update_struct) pe->major_image_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Major Image Version</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "minor_image_version") {
if(update_struct) pe->minor_image_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Minor Image Version</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "major_subsystem_version") {
if(update_struct) pe->major_subsystem_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Major Subsystem Version</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "minor_subsystem_version") {
if(update_struct) pe->minor_subsystem_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Minor Subsystem Version</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "may_be_a_version") {
if(update_struct) pe->may_be_a_version = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("Reserved, may be a version"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "image_size") {
if(update_struct) pe->image_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Image Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "headers_size") {
if(update_struct) pe->headers_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Headers Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "check_sum") {
if(update_struct) pe->check_sum = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Checksum</h4>\nChecksum of the file, only used to verify validity of modules being loaded into kernel space. The formula used to calculate PE file checksums is proprietary, although Microsoft provides API calls that can calculate the checksum for you."));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "subsystem") {
if(update_struct) pe->subsystem = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Subsystem</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_subsystem);
return QString();
}
QString v;
v.sprintf("%u", value);
return get_comment_from_value_reference(ui->ValueReference_subsystem, v);
} else if(name == "dll_characteristics") {
if(update_struct) pe->dll_characteristics = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>DLL Characteristics</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_characteristics);
return QString();
}
QString v;
v.sprintf("0x%x", value);
return get_comment_from_value_reference(ui->ValueReference_dll_characteristics, v, true);
} else if(name == "stack_reserve_size") {
if(update_struct) pe->stack_reserve_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Stack Reserve Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "stack_commit_size") {
if(update_struct) pe->stack_commit_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Stack Commit Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "heap_reserve_size") {
if(update_struct) pe->heap_reserve_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Heap Reserve Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "heap_commit_size") {
if(update_struct) pe->heap_commit_size = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Heap Commit Size</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
} else if(name == "loader_flags") {
if(update_struct) pe->loader_flags = value;
if(update_reference) {
ui->ReferenceBrowser->setText(tr("<h4>Loader Flags</h4>"));
ui->stackedWidget->setCurrentWidget(ui->page_empty);
}
return QString();
}
return QString();
}
/*
void MainWindow::update_references(const QString &name) {
int items_count = ui->stackedWidget->count();
for(int i=1; i<items_count; i++) {
}
}*/
void MainWindow::update_item_value(QTreeWidgetItem *item) {
//update_references(item->text(0));
QString v = item->text(2);
int base = v.startsWith("0x") ? 16 : 10;
item->setText(3, get_comment_and_update(item->text(0), v.toUInt(NULL, base), true, false));
}
void MainWindow::update_references(QTreeWidgetItem *item) {
// Didn't need value when we updating the reference
get_comment_and_update(item->text(0), 0, false, true);
}
#define DEFINE_PE_HEADER_ITEM(NAME) set_pe_header_item(#NAME, pe->NAME, get_comment_and_update(#NAME, pe->NAME, false, false))
void MainWindow::update_table() {
DEFINE_PE_HEADER_ITEM(machine);
DEFINE_PE_HEADER_ITEM(sections_count);
DEFINE_PE_HEADER_ITEM(time_stamp);
DEFINE_PE_HEADER_ITEM(symbol_table_pointer);
DEFINE_PE_HEADER_ITEM(symbols_count);
DEFINE_PE_HEADER_ITEM(optional_header_size);
DEFINE_PE_HEADER_ITEM(characteristics);
DEFINE_PE_HEADER_ITEM(magic);
DEFINE_PE_HEADER_ITEM(major_linker_version);
DEFINE_PE_HEADER_ITEM(minor_linker_version);
DEFINE_PE_HEADER_ITEM(code_size);
DEFINE_PE_HEADER_ITEM(initialized_data_size);
DEFINE_PE_HEADER_ITEM(uninitialized_data_size);
DEFINE_PE_HEADER_ITEM(entry_point_address);
DEFINE_PE_HEADER_ITEM(code_base);
DEFINE_PE_HEADER_ITEM(data_base);
DEFINE_PE_HEADER_ITEM(image_base);
DEFINE_PE_HEADER_ITEM(section_alignment);
DEFINE_PE_HEADER_ITEM(file_alignment);
DEFINE_PE_HEADER_ITEM(major_os_version);
DEFINE_PE_HEADER_ITEM(minor_os_version);
DEFINE_PE_HEADER_ITEM(major_image_version);
DEFINE_PE_HEADER_ITEM(minor_image_version);
DEFINE_PE_HEADER_ITEM(major_subsystem_version);
DEFINE_PE_HEADER_ITEM(minor_subsystem_version);
DEFINE_PE_HEADER_ITEM(may_be_a_version);
DEFINE_PE_HEADER_ITEM(image_size);
DEFINE_PE_HEADER_ITEM(headers_size);
DEFINE_PE_HEADER_ITEM(check_sum);
DEFINE_PE_HEADER_ITEM(subsystem);
DEFINE_PE_HEADER_ITEM(dll_characteristics);
DEFINE_PE_HEADER_ITEM(stack_reserve_size);
DEFINE_PE_HEADER_ITEM(stack_commit_size);
DEFINE_PE_HEADER_ITEM(heap_reserve_size);
DEFINE_PE_HEADER_ITEM(heap_commit_size);
DEFINE_PE_HEADER_ITEM(loader_flags);
}
void MainWindow::edit_item(QTreeWidgetItem *item, int column) {
qDebug("slot: edit_item(%p, %d)", item, column);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
ui->TreeWidget->editItem(item, 2);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
void MainWindow::about() {
QMessageBox::about(this, tr("About"), tr("<h3>PE Header Editor %1</h3>Copyright 2007-2014 PC GO Ld.<br><br>").arg(VERSION) +
tr("This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.<br>"
"This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details."));
}
void MainWindow::load_ui_layout() {
QSize windowsize = config->value("MainWindowSize").toSize();
if(windowsize.width() > 0 && windowsize.height() > 0) resize(windowsize);
ui->DockWidget_Reference->setVisible(config->value("ShowInformationWidget", true).toBool());
ui->DockWidget_ValueReference->setVisible(config->value("ShowValueReferenceWidget", true).toBool());
}
void MainWindow::save_ui_layout() {
qDebug("slot: save_ui_layout()");
config->setValue("ShowInformationWidget", ui->DockWidget_Reference->isVisible());
config->setValue("ShowValueReferenceWidget", ui->DockWidget_ValueReference->isVisible());
if(!isMaximized()) config->setValue("MainWindowSize", size());
}
void MainWindow::closeEvent(QCloseEvent *event) {
if(maybe_save()) {
save_ui_layout();
event->accept();
} else {
event->ignore();
}
}
void MainWindow::options() {
Options d(this);
bool m = is_modified;
d.ui->checkBox_confirm->setChecked(config->value("SavingConfirm", true).toBool());
bool hex1 = config->value("Hexadecimal", true).toBool();
d.ui->checkBox_hex->setChecked(hex1);
d.ui->checkBox_toolbar_label->setChecked(config->value("ShowToolBarTextLabel", true).toBool());
d.ui->checkBox_info_widget->setChecked(config->value("ShowInformationWidget", true).toBool());
d.ui->checkBox_ref_widget->setChecked(config->value("ShowValueReferenceWidget", true).toBool());
if(d.exec()) {
config->setValue("SavingConfirm", d.ui->checkBox_confirm->isChecked());
bool hex2 = d.ui->checkBox_hex->isChecked();
config->setValue("Hexadecimal", hex2);
config->setValue("ShowToolBarTextLabel", d.ui->checkBox_toolbar_label->isChecked());
config->setValue("ShowInformationWidget", d.ui->checkBox_info_widget->isChecked());
config->setValue("ShowValueReferenceWidget", d.ui->checkBox_ref_widget->isChecked());
load_ui_layout();
if(hex1 != hex2) {
update_table();
set_modified(m);
}
}
}