Version 0.11.0

- UI reworked once again
- Hex pattern and text string search implemented
- Code slightly refactored
This commit is contained in:
Nikolaj Schlej 2013-12-04 21:27:12 +01:00
parent 7d8b5fbc20
commit bb6f58f509
26 changed files with 4697 additions and 4327 deletions

View File

@ -139,11 +139,11 @@ INT32
EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE); EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE);
LzmaResult = LzmaDecode( LzmaResult = LzmaDecode(
Destination, (Byte*) Destination,
&DecodedBufSize, &DecodedBufSize,
(Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
&EncodedDataSize, &EncodedDataSize,
Source, (CONST Byte*) Source,
LZMA_PROPS_SIZE, LZMA_PROPS_SIZE,
LZMA_FINISH_END, LZMA_FINISH_END,
&Status, &Status,

View File

@ -111,6 +111,11 @@ typedef uint16_t CHAR16;
#define ERASE_POLARITY_TRUE 1 #define ERASE_POLARITY_TRUE 1
#define ERASE_POLARITY_UNKNOWN 0xFF #define ERASE_POLARITY_UNKNOWN 0xFF
// Search modes
#define SEARCH_MODE_HEX 0
#define SEARCH_MODE_ASCII 1
#define SEARCH_MODE_UNICODE 2
// EFI GUID // EFI GUID
typedef struct{ typedef struct{
UINT8 Data[16]; UINT8 Data[16];

View File

@ -51,11 +51,16 @@ void FfsEngine::msg(const QString & message, const QModelIndex index)
messageItems.enqueue(MessageListItem(message, NULL, 0, index)); messageItems.enqueue(MessageListItem(message, NULL, 0, index));
} }
QQueue<MessageListItem> FfsEngine::message() QQueue<MessageListItem> FfsEngine::messages()
{ {
return messageItems; return messageItems;
} }
void FfsEngine::clearMessages()
{
messageItems.clear();
}
QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const
{ {
if(!index.isValid()) if(!index.isValid())
@ -1341,46 +1346,20 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
scratch = new UINT8[scratchSize]; scratch = new UINT8[scratchSize];
// Decompress section data // Decompress section data
//!TODO: better check needed // Try Tiano decompression first
// Try EFI1.1 decompression first
if (ERR_SUCCESS != EfiDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
// Not EFI 1.1, try Tiano
if (ERR_SUCCESS != TianoDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) { if (ERR_SUCCESS != TianoDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
// Not Tiano, try EFI 1.1
if (ERR_SUCCESS != EfiDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
if (algorithm) if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_UNKNOWN; *algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
return ERR_STANDARD_DECOMPRESSION_FAILED; return ERR_STANDARD_DECOMPRESSION_FAILED;
} }
else if (algorithm) else if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_TIANO;
}
else {
// Possible EFI 1.1
// Try decompressing it as Tiano
UINT8* tianoDecompressed = new UINT8[decompressedSize];
UINT8* tianoScratch = new UINT8[scratchSize];
if (ERR_SUCCESS != TianoDecompress(data, dataSize, tianoDecompressed, decompressedSize, tianoScratch, scratchSize)) {
// Not Tiano, definitely EFI 1.1
if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_EFI11; *algorithm = COMPRESSION_ALGORITHM_EFI11;
} }
else { else if (algorithm)
// Both algorithms work
if(memcmp(decompressed, tianoDecompressed, decompressedSize)) {
// If decompressed data are different - it's Tiano for sure
delete[] decompressed;
delete[] scratch;
decompressed = tianoDecompressed;
scratch = tianoScratch;
if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_TIANO; *algorithm = COMPRESSION_ALGORITHM_TIANO;
}
else {
// Data are same - it's EFI 1.1
if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_EFI11;
}
}
}
decompressedData = QByteArray((const char*) decompressed, decompressedSize); decompressedData = QByteArray((const char*) decompressed, decompressedSize);
// Free allocated memory // Free allocated memory
@ -1572,7 +1551,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
QByteArray reconstructed; QByteArray reconstructed;
UINT8 result; UINT8 result;
// No action is needed, just return header + body // No action is needed, just return header + body + tail
if (item->action() == TreeItem::NoAction) { if (item->action() == TreeItem::NoAction) {
reconstructed = item->header().append(item->body()).append(item->tail()); reconstructed = item->header().append(item->body()).append(item->tail());
queue.enqueue(reconstructed); queue.enqueue(reconstructed);
@ -2188,85 +2167,93 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
return ERR_SUCCESS; return ERR_SUCCESS;
} }
// Will be refactored later // Search routines
/*QByteArray FfsEngine::decompressFile(const QModelIndex& index) const UINT8 FfsEngine::findHexPattern(const QByteArray & pattern, const bool bodyOnly)
{ {
if (!index.isValid()) return findHexPatternIn(treeModel->index(0,0), pattern, bodyOnly);
return QByteArray();
// Check index item to be FFS file
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if(item->type() != TreeItem::File)
return QByteArray();
QByteArray file;
UINT32 offset = 0;
// Construct new item body
for (int i = 0; i < item->childCount(); i++) {
// If section is not compressed, add it to new body as is
TreeItem* sectionItem = item->child(i);
if (sectionItem->subtype() != EFI_SECTION_COMPRESSION) {
QByteArray section = sectionItem->header().append(sectionItem->body());
UINT32 align = ALIGN4(offset) - offset;
file.append(QByteArray(align, '\x00')).append(section);
offset += align + section.size();
} }
else {
// Construct new section body by adding all child sections to this new section UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const bool bodyOnly)
QByteArray section;
UINT32 subOffset = 0;
for (int j = 0; j < sectionItem->childCount(); j++)
{ {
TreeItem* subSectionItem = sectionItem->child(j); if (pattern.isEmpty())
QByteArray subSection = subSectionItem->header().append(subSectionItem->body()); return ERR_INVALID_PARAMETER;
UINT32 align = ALIGN4(subOffset) - subOffset;
section.append(QByteArray(align, '\x00')).append(subSection);
subOffset += align + subSection.size();
}
// Add newly constructed section to file body
EFI_COMPRESSION_SECTION sectionHeader; if (!index.isValid())
sectionHeader.Type = EFI_SECTION_COMPRESSION; return ERR_SUCCESS;
sectionHeader.CompressionType = EFI_NOT_COMPRESSED;
sectionHeader.UncompressedLength = section.size(); TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
uint32ToUint24(section.size() + sizeof(EFI_COMPRESSION_SECTION), sectionHeader.Size); if (item == rootItem)
UINT32 align = ALIGN4(offset) - offset; return ERR_SUCCESS;
file.append(QByteArray(align, '\x00'))
.append(QByteArray((const char*) &sectionHeader, sizeof(EFI_COMPRESSION_SECTION))) bool hasChildren = (item->childCount() > 0);
.append(section); for (int i = 0; i < item->childCount(); i++) {
offset += align + section.size(); findHexPatternIn(index.child(i, index.column()), pattern, bodyOnly);
} }
QByteArray data;
if (hasChildren) {
if(!bodyOnly)
data = item->header();
}
else {
if (bodyOnly)
data = item->body();
else
data = item->header().append(item->body()).append(item->tail());
}
int offset = -1;
while ((offset = data.indexOf(pattern, offset + 1)) >= 0) {
msg(tr("Hex pattern \"%1\" found in %2 at offset %3")
.arg(QString(pattern.toHex()))
.arg(item->data(0).toString())
.arg(offset, 8, 16, QChar('0')),
index);
}
return ERR_SUCCESS;
} }
QByteArray header = item->header(); UINT8 FfsEngine::findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
// Correct file data checksum, if needed
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
UINT32 bufferSize = file.size() - sizeof(EFI_FFS_FILE_HEADER);
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*)(file.data() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
}
// Add file tail, if needed
if(fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
file.append(!fileHeader->IntegrityCheck.TailReference);
return header.append(file);
}*/
/*bool FfsEngine::isCompressedFile(const QModelIndex& index) const
{ {
if (!index.isValid()) return findTextPatternIn(treeModel->index(0,0), pattern, unicode, caseSensitive);
return false;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if(item->type() != TreeItem::File)
return false;
for (int i = 0; i < item->childCount(); i++) {
if (item->child(i)->subtype() == EFI_SECTION_COMPRESSION)
return true;
} }
return false; UINT8 FfsEngine::findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
}*/ {
if (pattern.isEmpty())
return ERR_INVALID_PARAMETER;
if (!index.isValid())
return ERR_SUCCESS;
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
if (item == rootItem)
return ERR_SUCCESS;
bool hasChildren = (item->childCount() > 0);
for (int i = 0; i < item->childCount(); i++) {
findTextPatternIn(index.child(i, index.column()), pattern, unicode, caseSensitive);
}
if (hasChildren)
return ERR_SUCCESS;
QString data;
if (unicode)
data = QString::fromUtf16((const ushort*) item->body().data(), item->body().length()/2);
else
data = QString::fromAscii((const char*) item->body().data(), item->body().length());
int offset = -1;
while ((offset = data.indexOf(pattern, offset + 1, caseSensitive)) >= 0) {
msg(tr("%1 text pattern \"%2\" found in %3 at offset %4")
.arg(unicode ? "Unicode" : "ASCII")
.arg(pattern)
.arg(item->data(0).toString())
.arg(unicode ? offset*2 : offset, 8, 16, QChar('0')),
index);
}
return ERR_SUCCESS;
}

View File

@ -38,7 +38,10 @@ public:
TreeModel* model() const; TreeModel* model() const;
// Returns message items queue // Returns message items queue
QQueue<MessageListItem> message(); QQueue<MessageListItem> messages();
// Clears message items queue
void clearMessages();
// Firmware image parsing // Firmware image parsing
UINT8 parseInputFile(const QByteArray & buffer); UINT8 parseInputFile(const QByteArray & buffer);
@ -74,6 +77,11 @@ public:
UINT8 rebuild(const QModelIndex & index); UINT8 rebuild(const QModelIndex & index);
UINT8 changeCompression(const QModelIndex & index, const UINT8 algorithm); UINT8 changeCompression(const QModelIndex & index, const UINT8 algorithm);
// Search routines
UINT8 findHexPattern(const QByteArray & pattern, const bool bodyOnly);
UINT8 findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const bool bodyOnly);
UINT8 findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
UINT8 findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
private: private:
TreeItem *rootItem; TreeItem *rootItem;
TreeModel *treeModel; TreeModel *treeModel;

View File

@ -20,6 +20,10 @@ int main(int argc, char *argv[])
QApplication a(argc, argv); QApplication a(argc, argv);
UEFITool w; UEFITool w;
QCoreApplication::setOrganizationName("CodeRush");
QCoreApplication::setOrganizationDomain("coderush.me");
QCoreApplication::setApplicationName("UEFITool");
if (a.arguments().length() > 1) if (a.arguments().length() > 1)
w.openImageFile(a.arguments().at(1)); w.openImageFile(a.arguments().at(1));
w.show(); w.show();

48
searchdialog.cpp Normal file
View File

@ -0,0 +1,48 @@
/* searchdialog.cpp
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "searchdialog.h"
SearchDialog::SearchDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SearchDialog)
{
// Create UI
ui->setupUi(this);
// Connect
//connect(ui->dataTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setEditMask()));
//connect(ui->translateFromHexCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setEditMask()));
}
SearchDialog::~SearchDialog()
{
delete ui;
}
/*void SearchDialog::setEditMask()
{
int index = ui->dataTypeComboBox->currentIndex();
QString mask;
if (index == 0) // Hex pattern, max 48 bytes long
mask = "";
else if (index == 1) {
if (ui->translateFromHexCheckBox->isChecked())
mask = "<HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH;_";
else
mask = "<HHHHHHHH-HHHH-HHHH-HHHHHHHHHHHHHHHH;_";
}
else
mask = "";
ui->searchEdit->setInputMask(mask);
}*/

34
searchdialog.h Normal file
View File

@ -0,0 +1,34 @@
/* searchdialog.h
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#ifndef SEARCHDIALOG_H
#define SEARCHDIALOG_H
#include <QDialog>
#include "ui_searchdialog.h"
class SearchDialog : public QDialog
{
Q_OBJECT
public:
SearchDialog(QWidget *parent = 0);
~SearchDialog();
Ui::SearchDialog* ui;
private slots:
//void setEditMask();
};
#endif

199
searchdialog.ui Normal file
View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SearchDialog</class>
<widget class="QDialog" name="SearchDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>290</width>
<height>172</height>
</rect>
</property>
<property name="windowTitle">
<string>Search</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="searchForLabel">
<property name="text">
<string>Search for:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="dataTypeLabel">
<property name="text">
<string>Data type:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="searchEdit"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="dataTypeComboBox">
<item>
<property name="text">
<string>Hex pattern</string>
</property>
</item>
<item>
<property name="text">
<string>Text string</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="hexPage">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="hexGroupBox">
<property name="title">
<string>Hex pattern search scope</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="allRadioButton">
<property name="text">
<string>Header, data and footer</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dataOnlyRadioButton">
<property name="text">
<string>Data only</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="textPage">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="textGroupBox">
<property name="title">
<string>Text string options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="unicodeCheckBox">
<property name="text">
<string>Unicode</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="caseSensitiveCheckBox">
<property name="text">
<string>Case sensitive</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>searchEdit</tabstop>
<tabstop>dataTypeComboBox</tabstop>
<tabstop>allRadioButton</tabstop>
<tabstop>dataOnlyRadioButton</tabstop>
<tabstop>unicodeCheckBox</tabstop>
<tabstop>caseSensitiveCheckBox</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SearchDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>173</x>
<y>162</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>216</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SearchDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>173</x>
<y>162</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>216</y>
</hint>
</hints>
</connection>
<connection>
<sender>dataTypeComboBox</sender>
<signal>activated(int)</signal>
<receiver>stackedWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>151</x>
<y>42</y>
</hint>
<hint type="destinationlabel">
<x>88</x>
<y>68</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -18,11 +18,15 @@ UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::UEFITool) ui(new Ui::UEFITool)
{ {
// Create UI
ui->setupUi(this); ui->setupUi(this);
searchDialog = new SearchDialog(this);
ffsEngine = NULL; ffsEngine = NULL;
//Connect // Connect signals to slots
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile())); connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs())); connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody())); connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(extractUncompressed())); connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(extractUncompressed()));
@ -32,96 +36,31 @@ UEFITool::UEFITool(QWidget *parent) :
connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replace())); connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replace()));
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove())); connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild())); connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild()));
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
connect(ui->actionChangeToNone, SIGNAL(triggered()), this, SLOT(changeToNone())); connect(ui->actionChangeToNone, SIGNAL(triggered()), this, SLOT(changeToNone()));
connect(ui->actionChangeToEfi11, SIGNAL(triggered()), this, SLOT(changeToEfi11())); connect(ui->actionChangeToEfi11, SIGNAL(triggered()), this, SLOT(changeToEfi11()));
connect(ui->actionChangeToTiano, SIGNAL(triggered()), this, SLOT(changeToTiano())); connect(ui->actionChangeToTiano, SIGNAL(triggered()), this, SLOT(changeToTiano()));
connect(ui->actionChangeToLzma, SIGNAL(triggered()), this, SLOT(changeToLzma())); connect(ui->actionChangeToLzma, SIGNAL(triggered()), this, SLOT(changeToLzma()));
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about())); connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt())); connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(exit())); connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(exit()));
connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(writeSettings()));
// Enable Drag-and-Drop actions // Enable Drag-and-Drop actions
this->setAcceptDrops(true); this->setAcceptDrops(true);
// Create menus
createMenus();
// Initialize non-persistent data // Initialize non-persistent data
init(); init();
}
void UEFITool::createMenus() // Read stored settings
{ readSettings();
// Capsule
capsuleMenu.clear();
capsuleMenu.addAction(ui->actionExtract);
capsuleMenu.addAction(ui->actionExtractBody);
capsuleMenu.addSeparator();
capsuleMenu.addAction(ui->actionRebuild);
// Image
imageMenu.clear();
imageMenu.addAction(ui->actionExtract);
imageMenu.addSeparator();
imageMenu.addAction(ui->actionRebuild);
// Region
regionMenu.clear();
regionMenu.addAction(ui->actionExtract);
regionMenu.addSeparator();
regionMenu.addAction(ui->actionRebuild);
// Padding
paddingMenu.clear();
paddingMenu.addAction(ui->actionExtract);
// Volume
volumeMenu.clear();
volumeMenu.addAction(ui->actionExtract);
volumeMenu.addAction(ui->actionExtractBody);
volumeMenu.addSeparator();
volumeMenu.addAction(ui->actionRebuild);
volumeMenu.addSeparator();
volumeMenu.addAction(ui->actionInsertInto);
volumeMenu.addSeparator();
volumeMenu.addAction(ui->actionRemove);
// File
fileMenu.clear();
fileMenu.addAction(ui->actionExtract);
fileMenu.addAction(ui->actionExtractBody);
//fileMenu.addAction(ui->actionExtractUncompressed);
fileMenu.addSeparator();
fileMenu.addAction(ui->actionRebuild);
fileMenu.addSeparator();
fileMenu.addAction(ui->actionInsertInto);
fileMenu.addAction(ui->actionInsertBefore);
fileMenu.addAction(ui->actionInsertAfter);
fileMenu.addSeparator();
fileMenu.addAction(ui->actionRemove);
// Section
sectionMenu.clear();
sectionMenu.addAction(ui->actionExtract);
sectionMenu.addAction(ui->actionExtractBody);
//sectionMenu.addAction(ui->actionExtractUncompressed);
sectionMenu.addSeparator();
sectionMenu.addAction(ui->actionRebuild);
sectionMenu.addSeparator();
sectionMenu.addAction(ui->actionInsertInto);
sectionMenu.addAction(ui->actionInsertBefore);
sectionMenu.addAction(ui->actionInsertAfter);
sectionMenu.addSeparator();
sectionMenu.addAction(ui->actionRemove);
sectionMenu.addSeparator();
sectionMenu.addMenu(ui->menuChangeCompressionTo);
} }
UEFITool::~UEFITool() UEFITool::~UEFITool()
{ {
delete ui; delete ui;
delete ffsEngine; delete ffsEngine;
delete searchDialog;
} }
void UEFITool::init() void UEFITool::init()
@ -130,18 +69,14 @@ void UEFITool::init()
ui->messageListWidget->clear(); ui->messageListWidget->clear();
ui->infoEdit->clear(); ui->infoEdit->clear();
// Disable actions and menus // Disable menus
ui->actionExtract->setDisabled(true); ui->menuCapsuleActions->setDisabled(true);
ui->actionExtractBody->setDisabled(true); ui->menuImageActions->setDisabled(true);
ui->actionExtractUncompressed->setDisabled(true); ui->menuRegionActions->setDisabled(true);
ui->actionReplace->setDisabled(true); ui->menuPaddingActions->setDisabled(true);
ui->actionRemove->setDisabled(true); ui->menuVolumeActions->setDisabled(true);
ui->actionRebuild->setDisabled(true); ui->menuFileActions->setDisabled(true);
ui->actionInsertInto->setDisabled(true); ui->menuSectionActions->setDisabled(true);
ui->actionInsertBefore->setDisabled(true);
ui->actionInsertAfter->setDisabled(true);
ui->actionSaveImageFile->setDisabled(true);
ui->menuChangeCompressionTo->setDisabled(true);
// Make new ffsEngine // Make new ffsEngine
if (ffsEngine) if (ffsEngine)
@ -155,8 +90,6 @@ void UEFITool::init()
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &))); this, SLOT(populateUi(const QModelIndex &)));
connect(ui->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); connect(ui->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
resizeTreeViewColums();
} }
void UEFITool::populateUi(const QModelIndex &current) void UEFITool::populateUi(const QModelIndex &current)
@ -169,7 +102,19 @@ void UEFITool::populateUi(const QModelIndex &current)
UINT8 subtype = item->subtype(); UINT8 subtype = item->subtype();
UINT8 algorithm = item->compression(); UINT8 algorithm = item->compression();
// Set info text
ui->infoEdit->setPlainText(item->info()); ui->infoEdit->setPlainText(item->info());
// Enable menus
ui->menuCapsuleActions->setEnabled(type == TreeItem::Capsule);
ui->menuImageActions->setEnabled(type == TreeItem::Image);
ui->menuRegionActions->setEnabled(type == TreeItem::Region);
ui->menuPaddingActions->setEnabled(type == TreeItem::Padding);
ui->menuVolumeActions->setEnabled(type == TreeItem::Volume);
ui->menuFileActions->setEnabled(type == TreeItem::File);
ui->menuSectionActions->setEnabled(type == TreeItem::Section);
// Enable actions
ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail()); ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail()); ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
ui->actionExtractBody->setDisabled(item->hasEmptyHeader()); ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
@ -182,6 +127,29 @@ void UEFITool::populateUi(const QModelIndex &current)
(algorithm == COMPRESSION_ALGORITHM_NONE || COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO || algorithm == COMPRESSION_ALGORITHM_LZMA)); (algorithm == COMPRESSION_ALGORITHM_NONE || COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO || algorithm == COMPRESSION_ALGORITHM_LZMA));
} }
void UEFITool::search()
{
if (searchDialog->exec() != QDialog::Accepted)
return;
int index = searchDialog->ui->dataTypeComboBox->currentIndex();
if (index == 0) { // Hex pattern
QByteArray pattern = QByteArray::fromHex(searchDialog->ui->searchEdit->text().toAscii());
if (pattern.isEmpty())
return;
ffsEngine->findHexPattern(pattern, searchDialog->ui->dataOnlyRadioButton->isChecked());
showMessages();
}
else if (index == 1) { // Text string
QString pattern = searchDialog->ui->searchEdit->text();
if (pattern.isEmpty())
return;
ffsEngine->findTextPattern(pattern, searchDialog->ui->unicodeCheckBox->isChecked(),
(Qt::CaseSensitivity) searchDialog->ui->caseSensitiveCheckBox->isChecked());
showMessages();
}
}
void UEFITool::rebuild() void UEFITool::rebuild()
{ {
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
@ -360,7 +328,7 @@ void UEFITool::saveImageFile()
QByteArray reconstructed; QByteArray reconstructed;
UINT8 result = ffsEngine->reconstructImage(reconstructed); UINT8 result = ffsEngine->reconstructImage(reconstructed);
showMessage(); showMessages();
if (result) { if (result) {
ui->statusBar->showMessage(tr("Reconstruction failed (%1)").arg(result)); ui->statusBar->showMessage(tr("Reconstruction failed (%1)").arg(result));
return; return;
@ -372,7 +340,7 @@ void UEFITool::saveImageFile()
ui->statusBar->showMessage(tr("Reconstructed image written")); ui->statusBar->showMessage(tr("Reconstructed image written"));
} }
void UEFITool::resizeTreeViewColums() void UEFITool::resizeTreeViewColumns()
{ {
int count = ffsEngine->model()->columnCount(); int count = ffsEngine->model()->columnCount();
for(int i = 0; i < count; i++) for(int i = 0; i < count; i++)
@ -406,13 +374,21 @@ void UEFITool::openImageFile(QString path)
init(); init();
UINT8 result = ffsEngine->parseInputFile(buffer); UINT8 result = ffsEngine->parseInputFile(buffer);
showMessage(); showMessages();
if (result) if (result)
ui->statusBar->showMessage(tr("Opened file can't be parsed (%1)").arg(result)); ui->statusBar->showMessage(tr("Opened file can't be parsed (%1)").arg(result));
else else
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName())); ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
resizeTreeViewColums(); // Enable search
ui->actionSearch->setEnabled(true);
}
void UEFITool::clearMessages()
{
ffsEngine->clearMessages();
messageItems.clear();
ui->messageListWidget->clear();
} }
void UEFITool::extract(const UINT8 mode) void UEFITool::extract(const UINT8 mode)
@ -500,13 +476,13 @@ void UEFITool::dropEvent(QDropEvent* event)
openImageFile(path); openImageFile(path);
} }
void UEFITool::showMessage() void UEFITool::showMessages()
{ {
ui->messageListWidget->clear(); ui->messageListWidget->clear();
if (!ffsEngine) if (!ffsEngine)
return; return;
messageItems = ffsEngine->message(); messageItems = ffsEngine->messages();
for (int i = 0; i < messageItems.count(); i++) { for (int i = 0; i < messageItems.count(); i++) {
ui->messageListWidget->addItem(new MessageListItem(messageItems.at(i))); ui->messageListWidget->addItem(new MessageListItem(messageItems.at(i)));
} }
@ -523,8 +499,13 @@ void UEFITool::scrollTreeView(QListWidgetItem* item)
} }
} }
void UEFITool::contextMenuEvent (QContextMenuEvent* event) void UEFITool::contextMenuEvent(QContextMenuEvent* event)
{ {
if (ui->messageListWidget->underMouse()) {
ui->menuMessages->exec(event->globalPos());
return;
}
if(!ui->structureTreeView->underMouse()) if(!ui->structureTreeView->underMouse())
return; return;
@ -537,25 +518,61 @@ void UEFITool::contextMenuEvent (QContextMenuEvent* event)
switch(item->type()) switch(item->type())
{ {
case TreeItem::Capsule: case TreeItem::Capsule:
capsuleMenu.exec(event->globalPos()); ui->menuCapsuleActions->exec(event->globalPos());
break; break;
case TreeItem::Image: case TreeItem::Image:
imageMenu.exec(event->globalPos()); ui->menuImageActions->exec(event->globalPos());
break; break;
case TreeItem::Region: case TreeItem::Region:
regionMenu.exec(event->globalPos()); ui->menuRegionActions->exec(event->globalPos());
break; break;
case TreeItem::Padding: case TreeItem::Padding:
paddingMenu.exec(event->globalPos()); ui->menuPaddingActions->exec(event->globalPos());
break; break;
case TreeItem::Volume: case TreeItem::Volume:
volumeMenu.exec(event->globalPos()); ui->menuVolumeActions->exec(event->globalPos());
break; break;
case TreeItem::File: case TreeItem::File:
fileMenu.exec(event->globalPos()); ui->menuFileActions->exec(event->globalPos());
break; break;
case TreeItem::Section: case TreeItem::Section:
sectionMenu.exec(event->globalPos()); ui->menuSectionActions->exec(event->globalPos());
break; break;
} }
} }
void UEFITool::readSettings()
{
QSettings settings("UEFITool.ini", QSettings::IniFormat, this);
resize(settings.value("mainWindow/size", QSize(800, 600)).toSize());
move(settings.value("mainWindow/position", QPoint(0, 0)).toPoint());
QList<int> horList, vertList;
horList.append(settings.value("mainWindow/treeWidth", 600).toInt());
horList.append(settings.value("mainWindow/infoWidth", 180).toInt());
vertList.append(settings.value("mainWindow/treeHeight", 400).toInt());
vertList.append(settings.value("mainWindow/messageHeight", 180).toInt());
ui->infoSplitter->setSizes(horList);
ui->messagesSplitter->setSizes(vertList);
resizeTreeViewColumns();
ui->structureTreeView->setColumnWidth(0, settings.value("tree/columnWidth0", ui->structureTreeView->columnWidth(0)).toInt());
ui->structureTreeView->setColumnWidth(1, settings.value("tree/columnWidth1", ui->structureTreeView->columnWidth(1)).toInt());
ui->structureTreeView->setColumnWidth(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
ui->structureTreeView->setColumnWidth(3, settings.value("tree/columnWidth3", ui->structureTreeView->columnWidth(3)).toInt());
//ui->structureTreeView->setColumnWidth(4, settings.value("tree/columnWidth4", 10).toInt());
}
void UEFITool::writeSettings()
{
QSettings settings("UEFITool.ini", QSettings::IniFormat, this);
settings.setValue("mainWindow/size", size());
settings.setValue("mainWindow/position", pos());
settings.setValue("mainWindow/treeWidth", ui->structureGroupBox->width());
settings.setValue("mainWindow/infoWidth", ui->infoGroupBox->width());
settings.setValue("mainWindow/treeHeight", ui->structureGroupBox->height());
settings.setValue("mainWindow/messageHeight", ui->messageGroupBox->height());
settings.setValue("tree/columnWidth0", ui->structureTreeView->columnWidth(0));
settings.setValue("tree/columnWidth1", ui->structureTreeView->columnWidth(1));
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
//settings.setValue("tree/columnWidth4", ui->structureTreeView->columnWidth(4));
}

View File

@ -21,18 +21,24 @@
#include <QFile> #include <QFile>
#include <QFileDialog> #include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
#include <QListWidget>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QMimeData> #include <QMimeData>
#include <QPlainTextEdit>
#include <QSettings>
#include <QSplitter>
#include <QString> #include <QString>
#include <QTreeView>
#include <QUrl> #include <QUrl>
#include "basetypes.h" #include "basetypes.h"
#include "ffs.h" #include "ffs.h"
#include "ffsengine.h" #include "ffsengine.h"
#include "searchdialog.h"
namespace Ui { namespace Ui {
class UEFITool; class UEFITool;
} }
class UEFITool : public QMainWindow class UEFITool : public QMainWindow
@ -48,11 +54,12 @@ public:
private slots: private slots:
void init(); void init();
void populateUi(const QModelIndex &current); void populateUi(const QModelIndex &current);
void resizeTreeViewColumns();
void scrollTreeView(QListWidgetItem* item);
void openImageFile(); void openImageFile();
void saveImageFile(); void saveImageFile();
void search();
void resizeTreeViewColums();
void scrollTreeView(QListWidgetItem* item);
void extract(const UINT8 mode); void extract(const UINT8 mode);
void extractAsIs(); void extractAsIs();
@ -75,30 +82,26 @@ private slots:
void changeToTiano(); void changeToTiano();
void changeToLzma(); void changeToLzma();
void clearMessages();
void about(); void about();
void aboutQt(); void aboutQt();
void exit(); void exit();
void writeSettings();
private: private:
Ui::UEFITool * ui; Ui::UEFITool* ui;
FfsEngine* ffsEngine; FfsEngine* ffsEngine;
SearchDialog* searchDialog;
QQueue<MessageListItem> messageItems; QQueue<MessageListItem> messageItems;
void showMessage(); void showMessages();
QMenu capsuleMenu;
QMenu imageMenu;
QMenu regionMenu;
QMenu paddingMenu;
QMenu volumeMenu;
QMenu fileMenu;
QMenu sectionMenu;
void createMenus();
void dragEnterEvent(QDragEnterEvent* event); void dragEnterEvent(QDragEnterEvent* event);
void dropEvent(QDropEvent* event); void dropEvent(QDropEvent* event);
void contextMenuEvent (QContextMenuEvent* event); void contextMenuEvent(QContextMenuEvent* event);
void readSettings();
}; };
#endif #endif

View File

@ -6,6 +6,7 @@ TEMPLATE = app
SOURCES += main.cpp \ SOURCES += main.cpp \
uefitool.cpp \ uefitool.cpp \
searchdialog.cpp \
descriptor.cpp \ descriptor.cpp \
ffs.cpp \ ffs.cpp \
ffsengine.cpp \ ffsengine.cpp \
@ -20,7 +21,9 @@ SOURCES += main.cpp \
Tiano/EfiTianoDecompress.c \ Tiano/EfiTianoDecompress.c \
Tiano/EfiCompress.c \ Tiano/EfiCompress.c \
Tiano/TianoCompress.c Tiano/TianoCompress.c
HEADERS += uefitool.h \ HEADERS += uefitool.h \
searchdialog.h \
basetypes.h \ basetypes.h \
descriptor.h \ descriptor.h \
gbe.h \ gbe.h \
@ -34,6 +37,10 @@ HEADERS += uefitool.h \
LZMA/LzmaDecompress.h \ LZMA/LzmaDecompress.h \
Tiano/EfiTianoDecompress.h \ Tiano/EfiTianoDecompress.h \
Tiano/EfiTianoCompress.h Tiano/EfiTianoCompress.h
FORMS += uefitool.ui
FORMS += uefitool.ui \
searchdialog.ui
RC_FILE = uefitool.rc RC_FILE = uefitool.rc
ICON = uefitool.icns ICON = uefitool.icns

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>834</width>
<height>600</height> <height>499</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -20,7 +20,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>UEFITool 0.10.0</string> <string>UEFITool 0.11.0</string>
</property> </property>
<widget class="QWidget" name="centralWidget"> <widget class="QWidget" name="centralWidget">
<property name="sizePolicy"> <property name="sizePolicy">
@ -29,24 +29,32 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing"> <property name="spacing">
<number>5</number> <number>0</number>
</property> </property>
<property name="margin"> <property name="margin">
<number>8</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QSplitter" name="messagesSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QSplitter" name="infoSplitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QGroupBox" name="structureGroupBox">
<property name="title"> <property name="title">
<string>Structure</string> <string>Structure</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing"> <property name="spacing">
<number>5</number> <number>0</number>
</property> </property>
<property name="margin"> <property name="margin">
<number>8</number> <number>5</number>
</property> </property>
<item> <item>
<widget class="QTreeView" name="structureTreeView"> <widget class="QTreeView" name="structureTreeView">
@ -75,103 +83,16 @@
</item> </item>
</layout> </layout>
</widget> </widget>
</item> <widget class="QGroupBox" name="infoGroupBox">
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title"> <property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionOpenImageFile"/>
<addaction name="actionSaveImageFile"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuAction">
<property name="title">
<string>A&amp;ction</string>
</property>
<widget class="QMenu" name="menuChangeCompressionTo">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Change &amp;compression to</string>
</property>
<addaction name="actionChangeToNone"/>
<addaction name="actionChangeToTiano"/>
<addaction name="actionChangeToEfi11"/>
<addaction name="actionChangeToLzma"/>
</widget>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
<addaction name="separator"/>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="actionExtractUncompressed"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertAfter"/>
<addaction name="actionInsertBefore"/>
<addaction name="separator"/>
<addaction name="actionReplace"/>
<addaction name="separator"/>
<addaction name="menuChangeCompressionTo"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>H&amp;elp</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionAboutQt"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuAction"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QDockWidget" name="infoDockWidget">
<property name="minimumSize">
<size>
<width>89</width>
<height>111</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>524287</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Information</string> <string>Information</string>
</property> </property>
<attribute name="dockWidgetArea"> <layout class="QHBoxLayout" name="horizontalLayout_5">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing"> <property name="spacing">
<number>5</number> <number>0</number>
</property> </property>
<property name="margin"> <property name="margin">
<number>8</number> <number>5</number>
</property> </property>
<item> <item>
<widget class="QPlainTextEdit" name="infoEdit"> <widget class="QPlainTextEdit" name="infoEdit">
@ -192,38 +113,16 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="messageDockWidget"> <widget class="QGroupBox" name="messageGroupBox">
<property name="minimumSize"> <property name="title">
<size>
<width>91</width>
<height>113</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>524287</width>
<height>113</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::BottomDockWidgetArea|Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Messages</string> <string>Messages</string>
</property> </property>
<attribute name="dockWidgetArea"> <layout class="QHBoxLayout" name="horizontalLayout_6">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing"> <property name="spacing">
<number>5</number> <number>0</number>
</property> </property>
<property name="margin"> <property name="margin">
<number>8</number> <number>5</number>
</property> </property>
<item> <item>
<widget class="QListWidget" name="messageListWidget"/> <widget class="QListWidget" name="messageListWidget"/>
@ -231,6 +130,146 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>834</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionOpenImageFile"/>
<addaction name="actionSaveImageFile"/>
<addaction name="separator"/>
<addaction name="actionSearch"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>H&amp;elp</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionAboutQt"/>
</widget>
<widget class="QMenu" name="menuAction">
<property name="title">
<string>&amp;Action</string>
</property>
<widget class="QMenu" name="menuCapsuleActions">
<property name="title">
<string>&amp;Capsule</string>
</property>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
</widget>
<widget class="QMenu" name="menuImageActions">
<property name="title">
<string>&amp;Image</string>
</property>
<addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
</widget>
<widget class="QMenu" name="menuRegionActions">
<property name="title">
<string>&amp;Region</string>
</property>
<addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
</widget>
<widget class="QMenu" name="menuPaddingActions">
<property name="title">
<string>&amp;Padding</string>
</property>
<addaction name="actionExtract"/>
</widget>
<widget class="QMenu" name="menuVolumeActions">
<property name="title">
<string>&amp;Volume</string>
</property>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
</widget>
<widget class="QMenu" name="menuFileActions">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
<addaction name="actionInsertAfter"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
</widget>
<widget class="QMenu" name="menuSectionActions">
<property name="title">
<string>&amp;Section</string>
</property>
<widget class="QMenu" name="menuChangeCompressionTo">
<property name="title">
<string>Change compression to</string>
</property>
<addaction name="actionChangeToNone"/>
<addaction name="actionChangeToTiano"/>
<addaction name="actionChangeToEfi11"/>
<addaction name="actionChangeToLzma"/>
</widget>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
<addaction name="actionInsertAfter"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
<addaction name="separator"/>
<addaction name="menuChangeCompressionTo"/>
</widget>
<widget class="QMenu" name="menuMessages">
<property name="title">
<string>&amp;Messages</string>
</property>
<addaction name="actionMessagesClear"/>
</widget>
<addaction name="menuCapsuleActions"/>
<addaction name="menuImageActions"/>
<addaction name="menuRegionActions"/>
<addaction name="menuPaddingActions"/>
<addaction name="menuVolumeActions"/>
<addaction name="menuFileActions"/>
<addaction name="menuSectionActions"/>
<addaction name="separator"/>
<addaction name="menuMessages"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuAction"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionInsertAfter"> <action name="actionInsertAfter">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
@ -441,6 +480,25 @@
<string>Ctrl+U</string> <string>Ctrl+U</string>
</property> </property>
</action> </action>
<action name="actionSearch">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Sear&amp;ch...</string>
</property>
<property name="shortcut">
<string>Ctrl+F</string>
</property>
</action>
<action name="actionMessagesClear">
<property name="text">
<string>&amp;Clear</string>
</property>
<property name="shortcut">
<string>Ctrl+Backspace</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources/> <resources/>