mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Version 0.17.0
- solved a big in extracting tailed file - added "Unknown" volume type - files can't be inserted to unknown volumes - sections can be inserted into encapsulation sections - regions (except Descriptor) can be replaced - Rebuild action removed from all types of items but Volume, File and Section, it did nothing for them - Descriptor region info now shows region access map and BIOS access table
This commit is contained in:
parent
a4a40ec329
commit
66dc4bb6e3
@ -152,7 +152,8 @@ enum CapsuleSubtypes {
|
||||
};
|
||||
|
||||
enum VolumeSubtypes {
|
||||
BootVolume = 90
|
||||
BootVolume = 90,
|
||||
UnknownVolume
|
||||
};
|
||||
|
||||
enum RegionSubtypes {
|
||||
|
101
ffsengine.cpp
101
ffsengine.cpp
@ -299,7 +299,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in
|
||||
|
||||
// Region access settings
|
||||
info += tr("\nRegion access settings:");
|
||||
info += tr("\nBIOS %1%2 ME %2%3 GbE %4%5")
|
||||
info += tr("\nBIOS:%1%2 ME:%2%3 GbE:%4%5")
|
||||
.arg(masterSection->BiosRead, 2, 16, QChar('0'))
|
||||
.arg(masterSection->BiosWrite, 2, 16, QChar('0'))
|
||||
.arg(masterSection->MeRead, 2, 16, QChar('0'))
|
||||
@ -328,7 +328,6 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in
|
||||
|
||||
// Add descriptor tree item
|
||||
model->addItem(Region, DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index);
|
||||
|
||||
// Sort regions in ascending order
|
||||
qSort(offsets);
|
||||
|
||||
@ -362,7 +361,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, const QModelIndex & parent)
|
||||
UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
|
||||
{
|
||||
if (gbe.isEmpty())
|
||||
return ERR_EMPTY_REGION;
|
||||
@ -383,12 +382,12 @@ UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, con
|
||||
.arg(version->minor);
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem( Region, GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
|
||||
index = model->addItem(Region, GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent, mode);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent)
|
||||
UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
|
||||
{
|
||||
if (me.isEmpty())
|
||||
return ERR_EMPTY_REGION;
|
||||
@ -413,12 +412,12 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const
|
||||
}
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem( Region, MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
|
||||
index = model->addItem(Region, MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent, mode);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent)
|
||||
UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
|
||||
{
|
||||
if (pdr.isEmpty())
|
||||
return ERR_EMPTY_REGION;
|
||||
@ -429,12 +428,12 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, con
|
||||
arg(pdr.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem( Region, PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
|
||||
index = model->addItem(Region, PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent, mode);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent)
|
||||
UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
|
||||
{
|
||||
if (bios.isEmpty())
|
||||
return ERR_EMPTY_REGION;
|
||||
@ -445,7 +444,7 @@ UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, c
|
||||
arg(bios.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem( Region, BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent);
|
||||
index = model->addItem(Region, BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent, mode);
|
||||
|
||||
return parseBios(bios, index);
|
||||
}
|
||||
@ -459,7 +458,6 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
|
||||
// First volume is not at the beginning of BIOS space
|
||||
QString name;
|
||||
QString info;
|
||||
@ -674,7 +672,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
|
||||
}
|
||||
// Other GUID
|
||||
else {
|
||||
msg(tr("parseBios: Unknown file system (%1)").arg(guidToQString(volumeHeader->FileSystemGuid)), parent);
|
||||
msg(tr("parseVolume: Unknown file system (%1)").arg(guidToQString(volumeHeader->FileSystemGuid)), parent);
|
||||
parseCurrentVolume = false;
|
||||
}
|
||||
|
||||
@ -684,7 +682,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
|
||||
|
||||
// Check header checksum by recalculating it
|
||||
if (calculateChecksum16((UINT16*) volumeHeader, volumeHeader->HeaderLength)) {
|
||||
msg(tr("parseBios: Volume header checksum is invalid"), parent);
|
||||
msg(tr("parseVolume: Volume header checksum is invalid"), parent);
|
||||
}
|
||||
|
||||
// Check for presence of extended header, only if header revision is greater then 1
|
||||
@ -706,7 +704,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
|
||||
|
||||
// Check reported size
|
||||
if (volumeSize != volumeHeader->FvLength) {
|
||||
msg(tr("%1: volume size stored in header %2 differs from calculated size %3")
|
||||
msg(tr("parseVolume: %1: volume size stored in header %2 differs from calculated size %3")
|
||||
.arg(guidToQString(volumeHeader->FileSystemGuid))
|
||||
.arg(volumeHeader->FvLength, 8, 16, QChar('0'))
|
||||
.arg(volumeSize, 8, 16, QChar('0')), parent);
|
||||
@ -723,11 +721,15 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
|
||||
// Add tree item
|
||||
QByteArray header = volume.left(headerSize);
|
||||
QByteArray body = volume.mid(headerSize, volumeSize - headerSize);
|
||||
index = model->addItem( Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
|
||||
// Do not parse volumes with unknown FS
|
||||
if (!parseCurrentVolume)
|
||||
if (!parseCurrentVolume) {
|
||||
index = model->addItem(Volume, UnknownVolume, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
else
|
||||
index = model->addItem(Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Search for and parse all files
|
||||
UINT32 fileOffset = headerSize;
|
||||
@ -1228,7 +1230,32 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
parent = index;
|
||||
|
||||
// Create item
|
||||
if (type == File) {
|
||||
if (type == Region) {
|
||||
UINT8 subtype = model->subtype(index);
|
||||
switch (subtype) {
|
||||
case BiosRegion:
|
||||
result = parseBiosRegion(body, fileIndex, index, mode);
|
||||
break;
|
||||
case MeRegion:
|
||||
result = parseMeRegion(body, fileIndex, index, mode);
|
||||
break;
|
||||
case GbeRegion:
|
||||
result = parseGbeRegion(body, fileIndex, index, mode);
|
||||
break;
|
||||
case PdrRegion:
|
||||
result = parsePdrRegion(body, fileIndex, index, mode);
|
||||
break;
|
||||
default:
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
// Set action
|
||||
model->setAction(fileIndex, action);
|
||||
}
|
||||
else if (type == File) {
|
||||
if (model->type(parent) != Volume)
|
||||
return ERR_INVALID_FILE;
|
||||
|
||||
@ -1263,8 +1290,11 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
created.append(body);
|
||||
|
||||
// Append tail, if needed
|
||||
if (tailSize)
|
||||
created.append(~fileHeader->IntegrityCheck.TailReference);
|
||||
if (tailSize) {
|
||||
UINT8 ht = ~fileHeader->IntegrityCheck.Checksum.Header;
|
||||
UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File;
|
||||
created.append(ht).append(ft);
|
||||
}
|
||||
|
||||
// Set file state
|
||||
UINT8 state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
|
||||
@ -1282,6 +1312,9 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
|
||||
// Set action
|
||||
model->setAction(fileIndex, action);
|
||||
|
||||
// Rebase all PEI-files that follow
|
||||
rebasePeiFiles(fileIndex);
|
||||
}
|
||||
else if (type == Section) {
|
||||
if (model->type(parent) != File && model->type(parent) != Section)
|
||||
@ -1380,15 +1413,12 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
// Find parent file for rebase
|
||||
fileIndex = model->findParentOfType(parent, File);
|
||||
}
|
||||
}
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
|
||||
if (!fileIndex.isValid())
|
||||
return ERR_INVALID_FILE;
|
||||
|
||||
// Rebase all PEI-files that follow
|
||||
rebasePeiFiles(fileIndex);
|
||||
}
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -1437,6 +1467,11 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
|
||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
|
||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
||||
}
|
||||
else if (model->type(parent) == Section) {
|
||||
type = Section;
|
||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
|
||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
||||
}
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
|
||||
@ -1451,7 +1486,13 @@ UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, c
|
||||
// Determine type of item to replace
|
||||
UINT32 headerSize;
|
||||
UINT8 result;
|
||||
if (model->type(index) == File) {
|
||||
if (model->type(index) == Region) {
|
||||
if (mode == REPLACE_MODE_AS_IS)
|
||||
result = create(index, Region, QByteArray(), object, CREATE_MODE_AFTER, Replace);
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (model->type(index) == File) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
headerSize = sizeof(EFI_FFS_FILE_HEADER);
|
||||
result = create(index, File, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, Replace);
|
||||
@ -1923,8 +1964,12 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst
|
||||
reconstructed = model->header(index).append(model->body(index)).append(model->tail(index));
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
else if (model->action(index) == Rebuild) {
|
||||
else if (model->action(index) == Remove) {
|
||||
reconstructed.clear();
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
else if (model->action(index) == Rebuild ||
|
||||
model->action(index) == Replace) {
|
||||
if (model->rowCount(index)) {
|
||||
reconstructed.clear();
|
||||
// Reconstruct children
|
||||
|
@ -46,10 +46,10 @@ public:
|
||||
// Firmware image parsing
|
||||
UINT8 parseImageFile(const QByteArray & buffer);
|
||||
UINT8 parseIntelImage(const QByteArray & intelImage, QModelIndex & index, const QModelIndex & parent = QModelIndex());
|
||||
UINT8 parseGbeRegion(const QByteArray & gbe, QModelIndex & index, const QModelIndex & parent);
|
||||
UINT8 parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent);
|
||||
UINT8 parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent);
|
||||
UINT8 parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent);
|
||||
UINT8 parseGbeRegion(const QByteArray & gbe, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
|
||||
UINT8 parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
|
||||
UINT8 parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
|
||||
UINT8 parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
|
||||
UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex());
|
||||
UINT8 parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||
UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||
|
@ -56,11 +56,13 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
||||
case Volume:
|
||||
if (subtype == BootVolume)
|
||||
return QObject::tr("Boot");
|
||||
else if (subtype == UnknownVolume)
|
||||
return QObject::tr("Unknown");
|
||||
else
|
||||
return "";
|
||||
case Capsule:
|
||||
if (subtype == AptioCapsule)
|
||||
return QObject::tr("Aptio extended");
|
||||
return QObject::tr("AMI Aptio");
|
||||
else if (subtype == UefiCapsule)
|
||||
return QObject::tr("UEFI 2.0");
|
||||
else
|
||||
|
30
uefitool.cpp
30
uefitool.cpp
@ -109,13 +109,15 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
||||
|
||||
// Enable actions
|
||||
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
|
||||
ui->actionRebuild->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
|
||||
ui->actionRebuild->setEnabled(type == Volume || type == File || type == Section);
|
||||
ui->actionExtractBody->setDisabled(model->hasEmptyHeader(current));
|
||||
ui->actionRemove->setEnabled(type == Volume || type == File || type == Section);
|
||||
ui->actionInsertInto->setEnabled(type == Volume || (type == File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD));
|
||||
ui->actionInsertInto->setEnabled((type == Volume && subtype != UnknownVolume) ||
|
||||
(type == File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD) ||
|
||||
(type == Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE)));
|
||||
ui->actionInsertBefore->setEnabled(type == File || type == Section);
|
||||
ui->actionInsertAfter->setEnabled(type == File || type == Section);
|
||||
ui->actionReplace->setEnabled(type == File || type == Section);
|
||||
ui->actionReplace->setEnabled((type == Region && subtype != DescriptorRegion) || type == File || type == Section);
|
||||
ui->actionReplaceBody->setEnabled(type == File || type == Section);
|
||||
}
|
||||
|
||||
@ -222,7 +224,7 @@ void UEFITool::insert(const UINT8 mode)
|
||||
|
||||
UINT8 result = ffsEngine->insert(index, buffer, mode);
|
||||
if (result)
|
||||
QMessageBox::critical(this, tr("Insertion failed"), tr("Error code: %d").arg(result), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Insertion failed"), tr("Error code: %1").arg(result), QMessageBox::Ok);
|
||||
else
|
||||
ui->actionSaveImageFile->setEnabled(true);
|
||||
}
|
||||
@ -260,7 +262,14 @@ void UEFITool::replace(const UINT8 mode)
|
||||
|
||||
TreeModel* model = ffsEngine->treeModel();
|
||||
QString path;
|
||||
if (model->type(index) == File) {
|
||||
if (model->type(index) == Region) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select region file to replace selected object"), ".", "Region files (*.rgn *.bin);;All files (*.*)");
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if (model->type(index) == File) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to replace selected object"),".","FFS files (*.ffs *.bin);;All files (*.*)");
|
||||
}
|
||||
@ -314,7 +323,7 @@ void UEFITool::replace(const UINT8 mode)
|
||||
|
||||
UINT8 result = ffsEngine->replace(index, buffer, mode);
|
||||
if (result)
|
||||
QMessageBox::critical(this, tr("Replacing failed"), tr("Error code: %d").arg(result), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Replacing failed"), tr("Error code: %1").arg(result), QMessageBox::Ok);
|
||||
else
|
||||
ui->actionSaveImageFile->setEnabled(true);
|
||||
}
|
||||
@ -399,7 +408,7 @@ void UEFITool::extract(const UINT8 mode)
|
||||
QByteArray extracted;
|
||||
UINT8 result = ffsEngine->extract(index, extracted, mode);
|
||||
if (result) {
|
||||
QMessageBox::critical(this, tr("Extraction failed"), tr("Error code: %d").arg(result), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Extraction failed"), tr("Error code: %1").arg(result), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -441,13 +450,14 @@ void UEFITool::saveImageFile()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi);;All files (*.*)");
|
||||
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
QByteArray reconstructed;
|
||||
UINT8 result = ffsEngine->reconstructImageFile(reconstructed);
|
||||
showMessages();
|
||||
if (result) {
|
||||
QMessageBox::critical(this, tr("Image reconstruction failed"), tr("Error code: %d").arg(result), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Image reconstruction failed"), tr("Error code: %1").arg(result), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -495,7 +505,7 @@ void UEFITool::openImageFile(QString path)
|
||||
UINT8 result = ffsEngine->parseImageFile(buffer);
|
||||
showMessages();
|
||||
if (result)
|
||||
QMessageBox::critical(this, tr("Image parsing failed"), tr("Error code: %d").arg(result), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Image parsing failed"), tr("Error code: %1").arg(result), QMessageBox::Ok);
|
||||
else
|
||||
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>UEFITool 0.16.6</string>
|
||||
<string>UEFITool 0.17.0</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<property name="sizePolicy">
|
||||
@ -226,16 +226,12 @@
|
||||
</property>
|
||||
<addaction name="actionExtract"/>
|
||||
<addaction name="actionExtractBody"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRebuild"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuImageActions">
|
||||
<property name="title">
|
||||
<string>&Image</string>
|
||||
</property>
|
||||
<addaction name="actionExtract"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRebuild"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuRegionActions">
|
||||
<property name="title">
|
||||
@ -243,7 +239,7 @@
|
||||
</property>
|
||||
<addaction name="actionExtract"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRebuild"/>
|
||||
<addaction name="actionReplace"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuPaddingActions">
|
||||
<property name="title">
|
||||
|
Loading…
Reference in New Issue
Block a user