diff --git a/basetypes.h b/basetypes.h
index eb8dd1b..4697439 100644
--- a/basetypes.h
+++ b/basetypes.h
@@ -1,13 +1,13 @@
 /* basetypes.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                                            
+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.             
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 */
 
@@ -108,12 +108,52 @@ typedef uint16_t  CHAR16;
 // Search modes
 #define SEARCH_MODE_HEADER  1
 #define SEARCH_MODE_BODY    2
-#define SEARCH_MODE_ALL     3         
+#define SEARCH_MODE_ALL     3
+
+// Actions
+enum ActionTypes {
+    NoAction = 50,
+    Create,
+    Insert,
+    Replace,
+    Remove,
+    Rebuild
+};
+
+// Types
+enum ItemTypes {
+    Root = 60,
+    Capsule,
+    Image,
+    Region,
+    Padding,
+    Volume,
+    File,
+    Section
+};
+// Subtypes
+enum ImageSubtypes{
+    IntelImage = 70,
+    BiosImage
+};
+
+enum CapsuleSubtypes {
+    AptioCapsule = 80,
+    UefiCapsule
+};
+
+enum RegionSubtypes {
+    DescriptorRegion = 90,
+    GbeRegion,
+    MeRegion,
+    BiosRegion,
+    PdrRegion
+};
 
 // EFI GUID
 typedef struct{
     UINT8 Data[16];
-} EFI_GUID; 
+} EFI_GUID;
 
 #define ALIGN4(Value) (((Value)+3) & ~3)
 #define ALIGN8(Value) (((Value)+7) & ~7)
diff --git a/descriptor.cpp b/descriptor.cpp
index 7a94d0b..262ee4e 100644
--- a/descriptor.cpp
+++ b/descriptor.cpp
@@ -18,15 +18,15 @@ QString regionTypeToQString(const UINT8 type)
 {
     switch (type)
     {
-    case TreeItem::DescriptorRegion:
+    case DescriptorRegion:
         return QObject::tr("Descriptor");
-    case TreeItem::GbeRegion:
+    case GbeRegion:
         return QObject::tr("GbE");
-    case TreeItem::MeRegion:
+    case MeRegion:
         return QObject::tr("ME");
-    case TreeItem::BiosRegion:
+    case BiosRegion:
         return QObject::tr("BIOS");
-    case TreeItem::PdrRegion:
+    case PdrRegion:
         return QObject::tr("PDR");
     default:
         return QObject::tr("Unknown");
@@ -58,4 +58,4 @@ UINT32 calculateRegionSize(const UINT16 base, const UINT16 limit)
     if (limit)
         return (limit + 1 - base) * 0x1000;
     return 0;
-}
\ No newline at end of file
+}
diff --git a/ffsengine.cpp b/ffsengine.cpp
index 9587ea7..8e11c43 100644
--- a/ffsengine.cpp
+++ b/ffsengine.cpp
@@ -27,19 +27,17 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 FfsEngine::FfsEngine(QObject *parent)
     : QObject(parent)
 {
-    rootItem = new TreeItem(TreeItem::Root);
-    treeModel = new TreeModel(rootItem);
+    model = new TreeModel();
 }
 
 FfsEngine::~FfsEngine(void)
 {
-    delete treeModel;
-    delete rootItem;
+    delete model;
 }
 
-TreeModel* FfsEngine::model() const
+TreeModel* FfsEngine::treeModel() const
 {
-    return treeModel;
+    return model;
 }
 
 void FfsEngine::msg(const QString & message, const QModelIndex index)
@@ -54,25 +52,7 @@ QQueue<MessageListItem> FfsEngine::messages() const
 
 void FfsEngine::clearMessages()
 {
-	messageItems.clear();
-}
-
-QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const
-{
-    if(!index.isValid())
-        return QModelIndex();
-
-    TreeItem *item;
-    QModelIndex parent = index;
-
-    for(item = static_cast<TreeItem*>(parent.internalPointer()); 
-        item != NULL && item != rootItem && item->type() != type;
-        item = static_cast<TreeItem*>(parent.internalPointer()))
-        parent = parent.parent();
-    if (item != NULL && item != rootItem)
-        return parent;
-
-    return QModelIndex();
+    messageItems.clear();
 }
 
 bool FfsEngine::hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2)
@@ -116,7 +96,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
             .arg(capsuleHeader->Flags, 8, 16, QChar('0'))
             .arg(capsuleHeader->CapsuleImageSize, 8, 16, QChar('0'));
         // Add tree item
-        index = treeModel->addItem(TreeItem::Capsule, TreeItem::UefiCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
+        index = model->addItem(Capsule, UefiCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
     }
 
     // Check buffer for being extended Aptio capsule header
@@ -133,7 +113,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
             .arg(aptioCapsuleHeader->CapsuleHeader.CapsuleImageSize - aptioCapsuleHeader->RomImageOffset, 8, 16, QChar('0'));
         //!TODO: more info about Aptio capsule
         // Add tree item
-        index = treeModel->addItem(TreeItem::Capsule, TreeItem::AptioCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
+        index = model->addItem(Capsule, AptioCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
     }
 
     // Skip capsule header to have flash chip image
@@ -147,7 +127,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
     if (descriptorHeader->Signature == FLASH_DESCRIPTOR_SIGNATURE) {
         // Parse as Intel image
         QModelIndex imageIndex;
-		result = parseIntelImage(flashImage, imageIndex, index); 
+        result = parseIntelImage(flashImage, imageIndex, index);
         if (result != ERR_INVALID_FLASH_DESCRIPTOR)
             return result;
     }
@@ -158,7 +138,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
         .arg(flashImage.size(), 8, 16, QChar('0'));
 
     // Add tree item
-    index = treeModel->addItem(TreeItem::Image, TreeItem::BiosImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), index);
+    index = model->addItem(Image, BiosImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), index);
     return parseBios(flashImage, index);
 }
 
@@ -187,7 +167,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
     // GbE region
     QByteArray gbe;
     UINT32 gbeBegin = 0;
-    UINT32 gbeEnd   = 0; 
+    UINT32 gbeEnd   = 0;
     if (regionSection->GbeLimit) {
         gbeBegin = calculateRegionOffset(regionSection->GbeBase);
         gbeEnd   = calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit);
@@ -197,7 +177,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
     // ME region
     QByteArray me;
     UINT32 meBegin = 0;
-    UINT32 meEnd   = 0; 
+    UINT32 meEnd   = 0;
     if (regionSection->MeLimit) {
         meBegin = calculateRegionOffset(regionSection->MeBase);
         meEnd   = calculateRegionSize(regionSection->MeBase, regionSection->MeLimit);
@@ -207,7 +187,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
     // PDR region
     QByteArray pdr;
     UINT32 pdrBegin = 0;
-    UINT32 pdrEnd   = 0; 
+    UINT32 pdrEnd   = 0;
     if (regionSection->PdrLimit) {
         pdrBegin = calculateRegionOffset(regionSection->PdrBase);
         pdrEnd   = calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit);
@@ -217,7 +197,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
     // BIOS region
     QByteArray bios;
     UINT32 biosBegin = 0;
-    UINT32 biosEnd   = 0; 
+    UINT32 biosEnd   = 0;
     if (regionSection->BiosLimit) {
         biosBegin = calculateRegionOffset(regionSection->BiosBase);
         biosEnd   = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit);
@@ -288,7 +268,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
         .arg(descriptorMap->NumberOfIccTableEntries);
 
     // Add Intel image tree item
-    index = treeModel->addItem(TreeItem::Image, TreeItem::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
+    index = model->addItem(Image, IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
 
     // Descriptor
     // Get descriptor info
@@ -298,11 +278,11 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
 
     // Check regions presence once again
     QVector<UINT32> offsets;
-    if (regionSection->GbeLimit) { 
+    if (regionSection->GbeLimit) {
         offsets.append(gbeBegin);
         info += tr("\nGbE region offset: %1").arg(gbeBegin, 8, 16, QChar('0'));
     }
-    if (regionSection->MeLimit) {  
+    if (regionSection->MeLimit) {
         offsets.append(meBegin);
         info += tr("\nME region offset: %1").arg(meBegin, 8, 16, QChar('0'));
     }
@@ -310,13 +290,13 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
         offsets.append(biosBegin);
         info += tr("\nBIOS region offset: %1").arg(biosBegin, 8, 16, QChar('0'));
     }
-    if (regionSection->PdrLimit) { 
+    if (regionSection->PdrLimit) {
         offsets.append(pdrBegin);
         info += tr("\nPDR region offset: %1").arg(pdrBegin, 8, 16, QChar('0'));
     }
 
     // Add descriptor tree item
-    treeModel->addItem(TreeItem::Region, TreeItem::DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index);
+    model->addItem(Region, DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index);
 
     // Sort regions in ascending order
     qSort(offsets);
@@ -326,22 +306,22 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
     for (int i = 0; i < offsets.count(); i++) {
         // Parse GbE region
         if (offsets.at(i) == gbeBegin) {
-			QModelIndex gbeIndex;
+            QModelIndex gbeIndex;
             result = parseGbeRegion(gbe, gbeIndex, index);
         }
         // Parse ME region
         else if (offsets.at(i) == meBegin) {
-			QModelIndex meIndex;
+            QModelIndex meIndex;
             result = parseMeRegion(me, meIndex, index);
         }
         // Parse BIOS region
         else if (offsets.at(i) == biosBegin) {
-			QModelIndex biosIndex;
+            QModelIndex biosIndex;
             result = parseBiosRegion(bios, biosIndex, index);
         }
         // Parse PDR region
         else if (offsets.at(i) == pdrBegin) {
-			QModelIndex pdrIndex;
+            QModelIndex pdrIndex;
             result = parsePdrRegion(pdr, pdrIndex, index);
         }
         if (result)
@@ -372,7 +352,7 @@ UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, con
         .arg(version->minor);
 
     // Add tree item
-    index = treeModel->addItem(TreeItem::Region, TreeItem::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
+    index = model->addItem( Region,  GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
 
     return ERR_SUCCESS;
 }
@@ -403,7 +383,7 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const
     }
 
     // Add tree item
-    index = treeModel->addItem(TreeItem::Region, TreeItem::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
+    index = model->addItem( Region,  MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
 
     return ERR_SUCCESS;
 }
@@ -419,7 +399,7 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, con
         arg(pdr.size(), 8, 16, QChar('0'));
 
     // Add tree item
-    index = treeModel->addItem(TreeItem::Region, TreeItem::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
+    index = model->addItem( Region,  PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
 
     return ERR_SUCCESS;
 }
@@ -435,14 +415,14 @@ UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, c
         arg(bios.size(), 8, 16, QChar('0'));
 
     // Add tree item
-    index = treeModel->addItem(TreeItem::Region, TreeItem::BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent);
+    index = model->addItem( Region,  BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent);
 
     return parseBios(bios, index);
 }
 
 UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
 {
-	// Search for first volume
+    // Search for first volume
     UINT32 prevVolumeOffset;
     UINT8 result;
     result = findNextVolume(bios, 0, prevVolumeOffset);
@@ -460,7 +440,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
         info = tr("Size: %1")
             .arg(padding.size(), 8, 16, QChar('0'));
         // Add tree item
-        treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
+        model->addItem( Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
     }
 
     // Search for and parse all volumes
@@ -468,7 +448,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
     UINT32 prevVolumeSize = 0;
     UINT32 volumeSize = 0;
 
-    while(true) 
+    while(true)
     {
         // Padding between volumes
         if (volumeOffset > prevVolumeOffset + prevVolumeSize) {
@@ -479,8 +459,8 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
             info = tr("Size: %1")
                 .arg(padding.size(), 8, 16, QChar('0'));
             // Add tree item
-            treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
-        } 
+            model->addItem( Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
+        }
 
         // Get volume size
         result = getVolumeSize(bios, volumeOffset, volumeSize);
@@ -518,8 +498,8 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
 
             // Check alignment setup
             if (!alignmentCap &&
-                (  alignment2   || alignment4   || alignment8   || alignment16 
-                || alignment32  || alignment64  || alignment128 || alignment256 
+                (  alignment2   || alignment4   || alignment8   || alignment16
+                || alignment32  || alignment64  || alignment128 || alignment256
                 || alignment512 || alignment1k  || alignment2k  || alignment4k
                 || alignment8k  || alignment16k || alignment32k || alignment64k))
                 msg("parseBios: Incompatible revision 1 volume alignment setup", parent);
@@ -579,7 +559,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
 
         // Parse volume
         QModelIndex index;
-		UINT8 result = parseVolume(bios.mid(volumeOffset, volumeSize), index, parent);
+        UINT8 result = parseVolume(bios.mid(volumeOffset, volumeSize), index, parent);
         if (result)
             msg(tr("parseBios: Volume parsing failed (%1)").arg(result), parent);
 
@@ -598,7 +578,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
                 info = tr("Size: %2")
                     .arg(padding.size(), 8, 16, QChar('0'));
                 // Add tree item
-                treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
+                model->addItem( Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
             }
             break;
         }
@@ -628,7 +608,7 @@ UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UIN
     if (QByteArray((const char*) &volumeHeader->Signature, sizeof(volumeHeader->Signature)) != EFI_FV_SIGNATURE)
         return ERR_INVALID_VOLUME;
 
-    // Use BlockMap to determine volume size 
+    // Use BlockMap to determine volume size
     EFI_FV_BLOCK_MAP_ENTRY* entry = (EFI_FV_BLOCK_MAP_ENTRY*) (bios.constData() + volumeOffset + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
     volumeSize = 0;
     while(entry->NumBlocks != 0 && entry->Length != 0) {
@@ -657,7 +637,7 @@ UINT8  FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
     // FFS GUID v2
     else if (QByteArray((const char*) &volumeHeader->FileSystemGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_FILE_SYSTEM2_GUID) {
         // Code can be added here
-    } 
+    }
     // Other GUID
     else {
         msg(tr("parseBios: Unknown file system (%1)").arg(guidToQString(volumeHeader->FileSystemGuid)), parent);
@@ -690,7 +670,7 @@ UINT8  FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
     if (result)
         return result;
 
-    // Check reported size 
+    // Check reported size
     if (volumeSize != volumeHeader->FvLength) {
         msg(tr("%1: volume size stored in header %2 differs from calculated size %3")
             .arg(guidToQString(volumeHeader->FileSystemGuid))
@@ -709,7 +689,7 @@ 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  = treeModel->addItem(TreeItem::Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+    index  = model->addItem( Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
 
     // Do not parse volumes with unknown FS
     if (!parseCurrentVolume)
@@ -754,7 +734,7 @@ UINT8  FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
         files.enqueue(header.left(sizeof(EFI_GUID)));
 
         // Parse file
-		QModelIndex fileIndex;
+        QModelIndex fileIndex;
         result = parseFile(file, fileIndex, empty == '\xFF' ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index);
         if (result)
             msg(tr("parseVolume: Parse FFS file failed (%1)").arg(result), index);
@@ -842,7 +822,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U
     {
         //Check file tail;
         tail = body.right(sizeof(UINT16));
-		UINT16 tailValue = *(UINT16*) tail.constData();
+        UINT16 tailValue = *(UINT16*) tail.constData();
         if (fileHeader->IntegrityCheck.TailReference != (UINT16)~tailValue)
             msg(tr("parseFile: %1, bitwise not of tail value %2 differs from %3 stored in file header")
             .arg(guidToQString(fileHeader->Name))
@@ -919,8 +899,8 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U
         .arg(fileHeader->State, 2, 16, QChar('0'));
 
     // Add tree item
-    index = treeModel->addItem(TreeItem::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, tail, parent, mode);
-	
+    index = model->addItem( File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, tail, parent, mode);
+
     if (!parseCurrentFile)
         return ERR_SUCCESS;
 
@@ -956,14 +936,14 @@ UINT8 FfsEngine::parseSections(const QByteArray & body, const QModelIndex & pare
     UINT32 bodySize = body.size();
     UINT8  result;
 
-	while (true) {
+    while (true) {
         // Get section size
         result = getSectionSize(body, sectionOffset, sectionSize);
         if (result)
             return result;
 
         // Parse section
-		QModelIndex sectionIndex;
+        QModelIndex sectionIndex;
         result = parseSection(body.mid(sectionOffset, sectionSize), sectionIndex, parent);
         if (result)
             return result;
@@ -985,7 +965,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
     EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*) (section.constData());
     UINT32 sectionSize = uint24ToUint32(sectionHeader->Size);
     QString name = sectionTypeToQString(sectionHeader->Type) + tr(" section");
-    QString info; 
+    QString info;
     QByteArray header;
     QByteArray body;
     UINT32 headerSize;
@@ -1017,7 +997,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
                 .arg(compressedSectionHeader->UncompressedLength, 8, 16, QChar('0'));
 
             // Add tree item
-            index  = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
+            index  = model->addItem( Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
 
             // Parse decompressed data
             if (parseCurrentSection) {
@@ -1035,7 +1015,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
             guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) (header.constData());
             header = section.left(guidDefinedSectionHeader->DataOffset);
             guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) (header.constData());
-            body   = section.mid(guidDefinedSectionHeader->DataOffset, sectionSize - guidDefinedSectionHeader->DataOffset); 
+            body   = section.mid(guidDefinedSectionHeader->DataOffset, sectionSize - guidDefinedSectionHeader->DataOffset);
             QByteArray decompressed = body;
             UINT8 algorithm = COMPRESSION_ALGORITHM_NONE;
             // Check if section requires processing
@@ -1063,7 +1043,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
                 .arg(compressionTypeToQString(algorithm));
 
             // Add tree item
-            index  = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
+            index  = model->addItem( Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
 
             // Parse decompressed data
             if (parseCurrentSection) {
@@ -1084,7 +1064,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
                 .arg(body.size(), 8, 16, QChar('0'));
 
             // Add tree item
-            index  = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+            index  = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
 
             // Parse section body
             result = parseSections(body, index);
@@ -1113,7 +1093,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
             .arg(body.size(), 8, 16, QChar('0'));
 
         // Add tree item
-        index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+        index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
         break;
     case EFI_SECTION_USER_INTERFACE:
         {
@@ -1126,11 +1106,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
                 .arg(body.size(), 8, 16, QChar('0'));
 
             // Add tree item
-            index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+            index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
 
             // Rename parent file
             QString text = QString::fromUtf16((const ushort*)body.constData());
-            treeModel->setItemText(text, findParentOfType(TreeItem::File, parent));
+            model->setTextString(model->findParentOfType(parent,  File), text);
         }
         break;
     case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
@@ -1143,7 +1123,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
             .arg(body.size(), 8, 16, QChar('0'));
 
         // Add tree item
-        index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+        index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
 
         // Parse section body as BIOS space
         result = parseBios(body, index);
@@ -1162,7 +1142,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
             .arg(body.size(), 8, 16, QChar('0'));
 
         // Add tree item
-        index  = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+        index  = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
 
         // Parse section body as BIOS space
         result = parseBios(body, index);
@@ -1180,7 +1160,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
             .arg(body.size(), 8, 16, QChar('0'));
 
         // Add tree item
-        index  = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
+        index  = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
         msg(tr("parseSection: Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')), index);
     }
     return ERR_SUCCESS;
@@ -1189,167 +1169,166 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
 // Operations on tree items
 UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByteArray & header, const QByteArray & body, const UINT8 mode, const UINT8 action, const UINT8 algorithm)
 {
-	QByteArray created;
-	UINT8 result;
+    QByteArray created;
+    UINT8 result;
 
-	if (!index.isValid() || !index.parent().isValid())
+    if (!index.isValid() || !index.parent().isValid())
         return ERR_INVALID_PARAMETER;
 
-	QModelIndex parent;
-	if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
-		parent = index.parent();
-	else
-		parent = index;
-	TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
+    QModelIndex parent;
+    if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
+        parent = index.parent();
+    else
+        parent = index;
 
-	// Create item
-	if (type == TreeItem::File) {
-		if (parentItem->type() != TreeItem::Volume)
-			return ERR_INVALID_FILE;
-		
-		EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header().constData();
-		UINT8 revision = volumeHeader->Revision;
-		bool erasePolarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY;
+    // Create item
+    if (type ==  File) {
+        if (model->type(parent) !=  Volume)
+            return ERR_INVALID_FILE;
 
-		if (header.size() != sizeof(EFI_FFS_FILE_HEADER))
-			return ERR_INVALID_FILE;
-		
-		QByteArray newHeader = header;
-		EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) newHeader.data();
-				
-		// Correct file size
-		UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0;
-		uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + body.size() + tailSize, fileHeader->Size);
+        EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) model->header(parent).constData();
+        UINT8 revision = volumeHeader->Revision;
+        bool erasePolarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY;
 
-		// Recalculate header checksum
-		fileHeader->IntegrityCheck.Checksum.Header = 0;
-		fileHeader->IntegrityCheck.Checksum.File = 0;
-		fileHeader->IntegrityCheck.Checksum.Header = calculateChecksum8((UINT8*) fileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
-		
-		// Recalculate data checksum, if needed
+        if (header.size() != sizeof(EFI_FFS_FILE_HEADER))
+            return ERR_INVALID_FILE;
+
+        QByteArray newHeader = header;
+        EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) newHeader.data();
+
+        // Correct file size
+        UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0;
+        uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + body.size() + tailSize, fileHeader->Size);
+
+        // Recalculate header checksum
+        fileHeader->IntegrityCheck.Checksum.Header = 0;
+        fileHeader->IntegrityCheck.Checksum.File = 0;
+        fileHeader->IntegrityCheck.Checksum.Header = calculateChecksum8((UINT8*) fileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
+
+        // Recalculate data checksum, if needed
         if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM)
-			fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*) body.constData(), body.size());
+            fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*) body.constData(), body.size());
         else if (revision == 1)
-			fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
-		else 
-			fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
-		
-		// Append body
-		created.append(body);
+            fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+        else
+            fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
 
-		// Append tail, if needed
-		if (tailSize)
-			created.append(~fileHeader->IntegrityCheck.TailReference);
+        // Append body
+        created.append(body);
 
-		// Set file state
-		UINT8 state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
-		if (erasePolarity)
-			state = ~state;
-		fileHeader->State = state;
+        // Append tail, if needed
+        if (tailSize)
+            created.append(~fileHeader->IntegrityCheck.TailReference);
 
-		// Prepend header
-		created.prepend(newHeader);
+        // Set file state
+        UINT8 state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
+        if (erasePolarity)
+            state = ~state;
+        fileHeader->State = state;
 
-		// Parse file
-		QModelIndex fileIndex;
+        // Prepend header
+        created.prepend(newHeader);
+
+        // Parse file
+        QModelIndex fileIndex;
         result = parseFile(created, fileIndex, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode);
         if (result)
             return result;
 
-		// Set action
-		treeModel->setItemAction(action, fileIndex);
+        // Set action
+        model->setAction(fileIndex, action);
     }
-	else if (type == TreeItem::Section) {
-		if (parentItem->type() != TreeItem::File && parentItem->type() != TreeItem::Section)
-			return ERR_INVALID_SECTION;
-		
-		if (header.size() < sizeof(EFI_COMMON_SECTION_HEADER))
-			return ERR_INVALID_SECTION;
+    else if (type ==  Section) {
+        if (model->type(parent) !=  File && model->type(parent) !=  Section)
+            return ERR_INVALID_SECTION;
 
-		QByteArray newHeader = header;
-		EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) newHeader.data();
-		
-		switch (commonHeader->Type) 
-		{
-		case EFI_SECTION_COMPRESSION: {
-				EFI_COMPRESSION_SECTION* sectionHeader = (EFI_COMPRESSION_SECTION*) newHeader.data();
-				// Correct uncompressed size
-				sectionHeader->UncompressedLength = body.size();
-				// Set compression type
-				if (algorithm == COMPRESSION_ALGORITHM_NONE)
-					sectionHeader->CompressionType = EFI_NOT_COMPRESSED;
-				else if (algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO)
-					sectionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
-				else if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_IMLZMA)
-					sectionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
-				else
-					return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
-				// Compress body
-				QByteArray compressed;
-				result = compress(body, algorithm, compressed);
-				if (result)
-					return result;
+        if (header.size() < sizeof(EFI_COMMON_SECTION_HEADER))
+            return ERR_INVALID_SECTION;
 
-				// Correct section size
-				uint32ToUint24(header.size() + compressed.size(), commonHeader->Size);
+        QByteArray newHeader = header;
+        EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) newHeader.data();
 
-				// Append header and body
-				created.append(newHeader).append(compressed);
+        switch (commonHeader->Type)
+        {
+        case EFI_SECTION_COMPRESSION: {
+                EFI_COMPRESSION_SECTION* sectionHeader = (EFI_COMPRESSION_SECTION*) newHeader.data();
+                // Correct uncompressed size
+                sectionHeader->UncompressedLength = body.size();
+                // Set compression type
+                if (algorithm == COMPRESSION_ALGORITHM_NONE)
+                    sectionHeader->CompressionType = EFI_NOT_COMPRESSED;
+                else if (algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO)
+                    sectionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
+                else if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_IMLZMA)
+                    sectionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
+                else
+                    return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
+                // Compress body
+                QByteArray compressed;
+                result = compress(body, algorithm, compressed);
+                if (result)
+                    return result;
 
-				// Parse section
-				QModelIndex sectionIndex;
-				result = parseSection(created, sectionIndex, index, mode);
-				if (result)
-					return result;
+                // Correct section size
+                uint32ToUint24(header.size() + compressed.size(), commonHeader->Size);
 
-				// Set create action
-				treeModel->setItemAction(action, sectionIndex);
-			}
-			break;
-		case EFI_SECTION_GUID_DEFINED:{
-				// Compress body
-				QByteArray compressed;
-				result = compress(body, algorithm, compressed);
-				if (result)
-					return result;
+                // Append header and body
+                created.append(newHeader).append(compressed);
 
-				// Correct section size
-				uint32ToUint24(header.size() + compressed.size(), commonHeader->Size);
+                // Parse section
+                QModelIndex sectionIndex;
+                result = parseSection(created, sectionIndex, index, mode);
+                if (result)
+                    return result;
 
-				// Append header and body
-				created.append(newHeader).append(compressed);
+                // Set create action
+                model->setAction(sectionIndex, action);
+            }
+            break;
+        case EFI_SECTION_GUID_DEFINED:{
+                // Compress body
+                QByteArray compressed;
+                result = compress(body, algorithm, compressed);
+                if (result)
+                    return result;
 
-				// Parse section
-				QModelIndex sectionIndex;
-				result = parseSection(created, sectionIndex, index, mode);
-				if (result)
-					return result;
+                // Correct section size
+                uint32ToUint24(header.size() + compressed.size(), commonHeader->Size);
 
-				// Set create action
-				treeModel->setItemAction(action, sectionIndex);			  
-			}
-			break;
-		default:
-			// Correct section size
-			uint32ToUint24(header.size() + body.size(), commonHeader->Size);
+                // Append header and body
+                created.append(newHeader).append(compressed);
 
-			// Append header and body
-			created.append(newHeader).append(body);
+                // Parse section
+                QModelIndex sectionIndex;
+                result = parseSection(created, sectionIndex, index, mode);
+                if (result)
+                    return result;
 
-			// Parse section
+                // Set create action
+                model->setAction(sectionIndex, action);
+            }
+            break;
+        default:
+            // Correct section size
+            uint32ToUint24(header.size() + body.size(), commonHeader->Size);
+
+            // Append header and body
+            created.append(newHeader).append(body);
+
+            // Parse section
             QModelIndex sectionIndex;
-			result = parseSection(created, sectionIndex, index, mode);
+            result = parseSection(created, sectionIndex, index, mode);
             if (result)
                 return result;
 
-			// Set create action
-			treeModel->setItemAction(action, sectionIndex);
-		}
-	}
-	else
-		return ERR_NOT_IMPLEMENTED;
+            // Set create action
+            model->setAction(sectionIndex, action);
+        }
+    }
+    else
+        return ERR_NOT_IMPLEMENTED;
 
-	return ERR_SUCCESS;
+    return ERR_SUCCESS;
 }
 
 UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode)
@@ -1357,29 +1336,28 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
     if (!index.isValid() || !index.parent().isValid())
         return ERR_INVALID_PARAMETER;
 
-	QModelIndex parent;
-	if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
-		parent = index.parent();
-	else
-		parent = index;
-	TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
+    QModelIndex parent;
+    if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
+        parent = index.parent();
+    else
+        parent = index;
 
-	// Determine type of item to insert
-	UINT8 type;
-	UINT32 headerSize;
-	if (parentItem->type() == TreeItem::Volume) {
-		type = TreeItem::File;
-		headerSize = sizeof(EFI_FFS_FILE_HEADER);
-	}
-	else if (parentItem->type() == TreeItem::File) {
-		type = TreeItem::Section;
-		EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
-		headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
-	}
-	else
-		return ERR_NOT_IMPLEMENTED;
+    // Determine type of item to insert
+    UINT8 type;
+    UINT32 headerSize;
+    if (model->type(parent) ==  Volume) {
+        type =  File;
+        headerSize = sizeof(EFI_FFS_FILE_HEADER);
+    }
+    else if (model->type(parent) ==  File) {
+        type =  Section;
+        EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
+        headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
+    }
+    else
+        return ERR_NOT_IMPLEMENTED;
 
-	return create(index, type, object.left(headerSize), object.right(object.size() - headerSize), mode, TreeItem::Insert);
+    return create(index, type, object.left(headerSize), object.right(object.size() - headerSize), mode,  Insert);
 }
 
 UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode)
@@ -1387,44 +1365,42 @@ UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, c
     if (!index.isValid())
         return ERR_INVALID_PARAMETER;
 
-	TreeItem * parentItem = static_cast<TreeItem*>(index.internalPointer());
-
-	// Determine type of item to replace
-	UINT32 headerSize;
-	UINT8 result;
-	if (parentItem->type() == TreeItem::File) {
-		if (mode == REPLACE_MODE_AS_IS) {
-			headerSize = sizeof(EFI_FFS_FILE_HEADER);
-			result = create(index, TreeItem::File, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, TreeItem::Replace);
-		}
-		else if (mode == REPLACE_MODE_BODY)
-			result = create(index, TreeItem::File, parentItem->header(), object, CREATE_MODE_AFTER, TreeItem::Replace);
-		else
-			return ERR_NOT_IMPLEMENTED;
-	}
-	else if (parentItem->type() == TreeItem::Section) {
-		if (mode == REPLACE_MODE_AS_IS) {
-			EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
-			headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
-			result = create(index, TreeItem::Section, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, TreeItem::Replace);
-		}
-        else if (mode == REPLACE_MODE_BODY) {
-            result = create(index, TreeItem::Section, parentItem->header(), object, CREATE_MODE_AFTER, TreeItem::Replace, parentItem->compression());
+    // Determine type of item to replace
+    UINT32 headerSize;
+    UINT8 result;
+    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);
         }
-		else
-			return ERR_NOT_IMPLEMENTED;
-	}
-	else
-		return ERR_NOT_IMPLEMENTED;
+        else if (mode == REPLACE_MODE_BODY)
+            result = create(index,  File, model->header(index), object, CREATE_MODE_AFTER,  Replace);
+        else
+            return ERR_NOT_IMPLEMENTED;
+    }
+    else if (model->type(index) ==  Section) {
+        if (mode == REPLACE_MODE_AS_IS) {
+            EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
+            headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
+            result = create(index,  Section, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER,  Replace);
+        }
+        else if (mode == REPLACE_MODE_BODY) {
+            result = create(index,  Section, model->header(index), object, CREATE_MODE_AFTER,  Replace, model->compression(index));
+        }
+        else
+            return ERR_NOT_IMPLEMENTED;
+    }
+    else
+        return ERR_NOT_IMPLEMENTED;
 
-	// Check create result
-	if (result)
-		return result;
+    // Check create result
+    if (result)
+        return result;
 
-	// Set remove action to replaced item
-	treeModel->setItemAction(TreeItem::Remove, index);
-	
-	return ERR_SUCCESS;
+    // Set remove action to replaced item
+    model->setAction(index,  Remove);
+
+    return ERR_SUCCESS;
 }
 
 
@@ -1433,49 +1409,47 @@ UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, cons
     if (!index.isValid())
         return ERR_INVALID_PARAMETER;
 
-    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
-
     if (mode == EXTRACT_MODE_AS_IS) {
         // Extract as is, with header, body and tail
         extracted.clear();
-        extracted.append(item->header());
-        extracted.append(item->body());
-        extracted.append(item->tail());
+        extracted.append(model->header(index));
+        extracted.append(model->body(index));
+        extracted.append(model->tail(index));
     }
     else if (mode == EXTRACT_MODE_BODY) {
         // Extract without header and tail
         extracted.clear();
-		// Special case of compressed bodies
-		if (item->type() == TreeItem::Section) {
-			QByteArray decompressed;
-			UINT8 result;
-			if (item->subtype() == EFI_SECTION_COMPRESSION) {
-				EFI_COMPRESSION_SECTION* compressedHeader = (EFI_COMPRESSION_SECTION*) item->header().constData();
-				result = decompress(item->body(), compressedHeader->CompressionType, decompressed);
-				if (result) 
-					return result;
-				extracted.append(decompressed);
-				return ERR_SUCCESS;
-			}
-			else if (item->subtype() == EFI_SECTION_GUID_DEFINED) {
-				QByteArray decompressed;
-				// Check if section requires processing
-				EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) item->header().constData();
-				if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {
-					// Try to decompress section body using both known compression algorithms
-					result = decompress(item->body(), EFI_STANDARD_COMPRESSION, decompressed);
-					if (result) {
-						result = decompress(item->body(), EFI_CUSTOMIZED_COMPRESSION, decompressed);
-						if (result)
-							return result;
-					}
-					extracted.append(decompressed);
-					return ERR_SUCCESS;
-				}
-			}
-		}
+        // Special case of compressed bodies
+        if (model->type(index) ==  Section) {
+            QByteArray decompressed;
+            UINT8 result;
+            if (model->subtype(index) == EFI_SECTION_COMPRESSION) {
+                EFI_COMPRESSION_SECTION* compressedHeader = (EFI_COMPRESSION_SECTION*) model->header(index).constData();
+                result = decompress(model->body(index), compressedHeader->CompressionType, decompressed);
+                if (result)
+                    return result;
+                extracted.append(decompressed);
+                return ERR_SUCCESS;
+            }
+            else if (model->subtype(index) == EFI_SECTION_GUID_DEFINED) {
+                QByteArray decompressed;
+                // Check if section requires processing
+                EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) model->header(index).constData();
+                if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {
+                    // Try to decompress section body using both known compression algorithms
+                    result = decompress(model->body(index), EFI_STANDARD_COMPRESSION, decompressed);
+                    if (result) {
+                        result = decompress(model->body(index), EFI_CUSTOMIZED_COMPRESSION, decompressed);
+                        if (result)
+                            return result;
+                    }
+                    extracted.append(decompressed);
+                    return ERR_SUCCESS;
+                }
+            }
+        }
 
-		extracted.append(item->body());
+        extracted.append(model->body(index));
     }
     else
         return ERR_UNKNOWN_EXTRACT_MODE;
@@ -1489,7 +1463,7 @@ UINT8 FfsEngine::remove(const QModelIndex & index)
         return ERR_INVALID_PARAMETER;
 
     // Set action for the item
-    treeModel->setItemAction(TreeItem::Remove, index);
+    model->setAction(index,  Remove);
 
     return ERR_SUCCESS;
 }
@@ -1500,7 +1474,7 @@ UINT8 FfsEngine::rebuild(const QModelIndex & index)
         return ERR_INVALID_PARAMETER;
 
     // Set action for the item
-    treeModel->setItemAction(TreeItem::Rebuild, index);
+    model->setAction(index,  Rebuild);
 
     return ERR_SUCCESS;
 }
@@ -1577,7 +1551,7 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
 
         // Decompress section data
         if (ERR_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
-            // Intel modified LZMA workaround 
+            // Intel modified LZMA workaround
             EFI_COMMON_SECTION_HEADER* shittySectionHeader;
             UINT32 shittySectionSize;
             // Shitty compressed section with a section header between COMPRESSED_SECTION_HEADER and LZMA_HEADER
@@ -1628,13 +1602,13 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
     UINT32 compressedSize = 0;
 
     switch (algorithm) {
-    case COMPRESSION_ALGORITHM_NONE: 
+    case COMPRESSION_ALGORITHM_NONE:
         {
             compressedData = data;
             return ERR_SUCCESS;
         }
         break;
-    case COMPRESSION_ALGORITHM_EFI11: 
+    case COMPRESSION_ALGORITHM_EFI11:
         {
             if (EfiCompress((UINT8*) data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
                 return ERR_STANDARD_COMPRESSION_FAILED;
@@ -1646,7 +1620,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
             return ERR_SUCCESS;
         }
         break;
-    case COMPRESSION_ALGORITHM_TIANO: 
+    case COMPRESSION_ALGORITHM_TIANO:
         {
             if (TianoCompress((UINT8*) data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
                 return ERR_STANDARD_COMPRESSION_FAILED;
@@ -1658,7 +1632,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
             return ERR_SUCCESS;
         }
         break;
-    case COMPRESSION_ALGORITHM_LZMA: 
+    case COMPRESSION_ALGORITHM_LZMA:
         {
             if (LzmaCompress((const UINT8*) data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
                 return ERR_CUSTOMIZED_COMPRESSION_FAILED;
@@ -1670,7 +1644,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
             return ERR_SUCCESS;
         }
         break;
-    case COMPRESSION_ALGORITHM_IMLZMA: 
+    case COMPRESSION_ALGORITHM_IMLZMA:
         {
             QByteArray header = data.left(sizeof(EFI_COMMON_SECTION_HEADER));
             EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*) header.constData();
@@ -1697,7 +1671,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
 UINT8 FfsEngine::reconstructImage(QByteArray & reconstructed)
 {
     QQueue<QByteArray> queue;
-    UINT8 result = reconstruct(treeModel->index(0,0), queue);
+    UINT8 result = reconstruct(model->index(0,0), queue);
     if (result)
         return result;
     reconstructed.clear();
@@ -1740,35 +1714,31 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
     if (!index.isValid())
         return ERR_SUCCESS;
 
-    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
-    if (item == rootItem)
-        return ERR_SUCCESS;
-
     QByteArray reconstructed;
     UINT8 result;
 
     // No action is needed, just return header + body + tail
-    if (item->action() == TreeItem::NoAction) {
-        reconstructed = item->header().append(item->body()).append(item->tail());
+    if (model->action(index) ==  NoAction) {
+        reconstructed = model->header(index).append(model->body(index)).append(model->tail(index));
         queue.enqueue(reconstructed);
         return ERR_SUCCESS;
     }
     // Remove item
-    else if (item->action() == TreeItem::Remove) {
+    else if (model->action(index) ==  Remove) {
         // Volume can be removed by replacing all it's contents with empty bytes
-        if (item->type() == TreeItem::Volume) {
-            EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) item->header().constData();
+        if (model->type(index) ==  Volume) {
+            EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) model->header(index).constData();
             char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
-            reconstructed.fill(empty, item->header().size() + item->body().size() + item->tail().size());
+            reconstructed.fill(empty, model->header(index).size() + model->body(index).size() + model->tail(index).size());
             queue.enqueue(reconstructed);
             return ERR_SUCCESS;
         }
         // File can be removed
-        if (item->type() == TreeItem::File)
+        if (model->type(index) ==  File)
             // Add nothing to queue
                 return ERR_SUCCESS;
         // Section can be removed
-        else if (item->type() == TreeItem::Section)
+        else if (model->type(index) ==  Section)
             // Add nothing to queue
             return ERR_SUCCESS;
         // Other item types can't be removed
@@ -1776,12 +1746,15 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
             return ERR_NOT_IMPLEMENTED;
     }
     // Reconstruct item and it's children recursive
-    else if (item->action() == TreeItem::Create || item->action() == TreeItem::Insert || item->action() == TreeItem::Replace || item->action() == TreeItem::Rebuild) {
+    else if (model->action(index) ==  Create
+          || model->action(index) ==  Insert
+          || model->action(index) ==  Replace
+          || model->action(index) ==  Rebuild) {
         QQueue<QByteArray> childrenQueue;
 
-        switch (item->type()) {
-        case TreeItem::Image:
-            if (item->subtype() == TreeItem::IntelImage) {
+        switch (model->type(index)) {
+        case  Image:
+            if (model->subtype(index) ==  IntelImage) {
                 // Reconstruct Intel image
                 // First child will always be descriptor for this type of image
                 result = reconstruct(index.child(0, index.column()), childrenQueue);
@@ -1808,34 +1781,34 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                 UINT32 offset = descriptor.size();
                 // Reconstruct other regions
                 char empty = '\xFF'; //!TODO: determine empty char using one of reserved descriptor fields
-                for (int i = 1; i < item->childCount(); i++) {
+                for (int i = 1; i < model->rowCount(index); i++) {
                     result = reconstruct(index.child(i, index.column()), childrenQueue);
                     if (result)
                         return result;
-                    switch(item->child(i)->subtype()) 
+                    switch(model->subtype(model->index(i, 0, index)))
                     {
-                    case TreeItem::GbeRegion:
+                    case  GbeRegion:
                         gbe = childrenQueue.dequeue();
                         if (gbeBegin > offset)
                             reconstructed.append(QByteArray(gbeBegin - offset, empty));
                         reconstructed.append(gbe);
                         offset = gbeEnd;
                         break;
-                    case TreeItem::MeRegion:
+                    case  MeRegion:
                         me = childrenQueue.dequeue();
                         if (meBegin > offset)
                             reconstructed.append(QByteArray(meBegin - offset, empty));
                         reconstructed.append(me);
                         offset = meEnd;
                         break;
-                    case TreeItem::BiosRegion:
+                    case  BiosRegion:
                         bios = childrenQueue.dequeue();
                         if (biosBegin > offset)
                             reconstructed.append(QByteArray(biosBegin - offset, empty));
                         reconstructed.append(bios);
                         offset = biosEnd;
                         break;
-                    case TreeItem::PdrRegion:
+                    case  PdrRegion:
                         pdr = childrenQueue.dequeue();
                         if (pdrBegin > offset)
                             reconstructed.append(QByteArray(pdrBegin - offset, empty));
@@ -1847,37 +1820,37 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                         return ERR_INVALID_REGION;
                     }
                 }
-                if ((UINT32)item->body().size() > offset) 
-                    reconstructed.append(QByteArray((UINT32)item->body().size() - offset, empty));
+                if ((UINT32)model->body(index).size() > offset)
+                    reconstructed.append(QByteArray((UINT32)model->body(index).size() - offset, empty));
 
                 // Check size of reconstructed image, it must be same
-                if (reconstructed.size() > item->body().size()) {
+                if (reconstructed.size() > model->body(index).size()) {
                     msg(tr("reconstruct: reconstructed body %1 is bigger then original %2")
                         .arg(reconstructed.size(), 8, 16, QChar('0'))
-                        .arg(item->body().size(), 8, 16, QChar('0')), index);
+                        .arg(model->body(index).size(), 8, 16, QChar('0')), index);
                     return ERR_INVALID_PARAMETER;
                 }
-                else if (reconstructed.size() < item->body().size()) {
+                else if (reconstructed.size() < model->body(index).size()) {
                     msg(tr("reconstruct: reconstructed body %1 is smaller then original %2")
                         .arg(reconstructed.size(), 8, 16, QChar('0'))
-                        .arg(item->body().size(), 8, 16, QChar('0')), index);
+                        .arg(model->body(index).size(), 8, 16, QChar('0')), index);
                     return ERR_INVALID_PARAMETER;
                 }
 
                 // Enqueue reconstructed item
-                queue.enqueue(item->header().append(reconstructed));
+                queue.enqueue(model->header(index).append(reconstructed));
                 return ERR_SUCCESS;
             }
             // BIOS Image must be treated like region
-        case TreeItem::Capsule:
-            if (item->subtype() == TreeItem::AptioCapsule)
+        case  Capsule:
+            if (model->subtype(index) ==  AptioCapsule)
                 msg(tr("reconstruct: Aptio capsule checksum and signature can now become invalid"), index);
-        case TreeItem::Region:
+        case  Region:
             {
                 // Reconstruct item body
-                if (item->childCount()) {
+                if (model->rowCount(index)) {
                     // Reconstruct item children
-                    for (int i = 0; i < item->childCount(); i++) {
+                    for (int i = 0; i < model->rowCount(index); i++) {
                         result = reconstruct(index.child(i, index.column()), childrenQueue);
                         if (result)
                             return result;
@@ -1889,46 +1862,46 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                 }
                 // Use stored item body
                 else
-                    reconstructed = item->body();
+                    reconstructed = model->body(index);
 
                 // Check size of reconstructed image, it must be same
-                if (item->type() != TreeItem::Root) {
-                    if (reconstructed.size() > item->body().size()) {
+                if (model->type(index) !=  Root) {
+                    if (reconstructed.size() > model->body(index).size()) {
                         msg(tr("reconstructed: reconstructed body %1 is bigger then original %2")
                             .arg(reconstructed.size(), 8, 16, QChar('0'))
-                            .arg(item->body().size(), 8, 16, QChar('0')), index);
+                            .arg(model->body(index).size(), 8, 16, QChar('0')), index);
                         return ERR_INVALID_PARAMETER;
-                    } 
-                    else if (reconstructed.size() < item->body().size()) {
+                    }
+                    else if (reconstructed.size() < model->body(index).size()) {
                         msg(tr("reconstructed: reconstructed body %1 is smaller then original %2")
                             .arg(reconstructed.size(), 8, 16, QChar('0'))
-                            .arg(item->body().size(), 8, 16, QChar('0')), index);
+                            .arg(model->body(index).size(), 8, 16, QChar('0')), index);
                         return ERR_INVALID_PARAMETER;
                     }
                 }
 
                 // Enqueue reconstructed item
-                queue.enqueue(item->header().append(reconstructed));
+                queue.enqueue(model->header(index).append(reconstructed));
             }
             break;
 
-        case TreeItem::Volume: 
+        case  Volume:
             {
                 //!TODO: add check for weak aligned volumes
-                QByteArray header = item->header();
+                QByteArray header = model->header(index);
                 EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.data();
 
                 // Recalculate volume header checksum
                 volumeHeader->Checksum = 0;
-                volumeHeader->Checksum = calculateChecksum16((UINT16*) volumeHeader, volumeHeader->HeaderLength);    
+                volumeHeader->Checksum = calculateChecksum16((UINT16*) volumeHeader, volumeHeader->HeaderLength);
 
                 // Reconstruct volume body
-                if (item->childCount()) {
+                if (model->rowCount(index)) {
                     UINT8 polarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE;
                     char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
-                    
+
                     // Reconstruct files in volume
-                    for (int i = 0; i < item->childCount(); i++) {
+                    for (int i = 0; i < model->rowCount(index); i++) {
                         // Reconstruct files
                         result = reconstruct(index.child(i, index.column()), childrenQueue, volumeHeader->Revision, polarity);
                         if (result)
@@ -1976,7 +1949,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
 
                         // Get file from queue
                         QByteArray file = childrenQueue.dequeue();
-                        EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) file.data(); 
+                        EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) file.data();
 
                         // Check alignment
                         UINT8 alignmentPower;
@@ -2030,8 +2003,8 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                                 // No more space left in volume
                                 else if (vtfOffset < offset) {
                                     // Check if volume can be grown
-                                    UINT8 parentType = item->parent()->type();
-                                    if(parentType != TreeItem::File && parentType != TreeItem::Section) {
+                                    UINT8 parentType = model->type(index.parent());
+                                    if(parentType !=  File && parentType !=  Section) {
                                         msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)), index);
                                         return ERR_INVALID_VOLUME;
                                     }
@@ -2059,7 +2032,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                                     break;
                                 }
                             }
-                            
+
                             // Append last file and fill the rest with empty char
                             else {
                                 reconstructed.append(file);
@@ -2070,8 +2043,8 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                                 }
                                 else {
                                     // Check if volume can be grown
-                                    UINT8 parentType = item->parent()->type();
-                                    if(parentType != TreeItem::File && parentType != TreeItem::Section) {
+                                    UINT8 parentType = model->type(index.parent());
+                                    if(parentType !=  File && parentType !=  Section) {
                                         msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)), index);
                                         return ERR_INVALID_VOLUME;
                                     }
@@ -2090,7 +2063,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
 
                         // Append current file to new volume body
                         reconstructed.append(file);
-                        
+
                         // Change current file offset
                         offset += file.size();
                     }
@@ -2103,18 +2076,18 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                     }
                 }
                 // Use current volume body
-                else 
-                    reconstructed = item->body();
+                else
+                    reconstructed = model->body(index);
 
                 // Enqueue reconstructed item
-                queue.enqueue(header.append(reconstructed));    
+                queue.enqueue(header.append(reconstructed));
             }
             break;
 
-        case TreeItem::File: 
+        case  File:
             {
-                QByteArray header = item->header();
-                EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data(); 
+                QByteArray header = model->header(index);
+                EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
 
                 // Check erase polarity
                 if (erasePolarity == ERASE_POLARITY_UNKNOWN) {
@@ -2167,10 +2140,10 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                         .arg(guidToQString(fileHeader->Name)), index);
                     return ERR_SUCCESS;
                 }
-                
+
                 // Reconstruct file body
-                if (item->childCount()) {
-                    for (int i = 0; i < item->childCount(); i++) {
+                if (model->rowCount(index)) {
+                    for (int i = 0; i < model->rowCount(index); i++) {
                         // Reconstruct sections
                         result = reconstruct(index.child(i, index.column()), childrenQueue, revision, empty);
                         if (result)
@@ -2199,7 +2172,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                     }
 
                     // Correct file size
-                    UINT8 tailSize = item->hasEmptyTail() ? 0 : sizeof(UINT16);
+                    UINT8 tailSize = model->hasEmptyTail(index) ? 0 : sizeof(UINT16);
 
                     uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size);
 
@@ -2211,7 +2184,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                 }
                 // Use current file body
                 else
-                    reconstructed = item->body();
+                    reconstructed = model->body(index);
 
                 // Recalculate data checksum, if needed
                 if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
@@ -2219,11 +2192,11 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                 }
                 else if (revision == 1)
                     fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
-                else 
+                else
                     fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
 
                 // Append tail, if needed
-                if (!item->hasEmptyTail())
+                if (!model->hasEmptyTail(index))
                     reconstructed.append(~fileHeader->IntegrityCheck.TailReference);
 
                 // Set file state
@@ -2231,21 +2204,21 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                 if (erasePolarity == ERASE_POLARITY_TRUE)
                     state = ~state;
                 fileHeader->State = state;
-                
+
                 // Enqueue reconstructed item
-                queue.enqueue(header.append(reconstructed));  
+                queue.enqueue(header.append(reconstructed));
             }
             break;
 
-        case TreeItem::Section:
+        case  Section:
             {
-                QByteArray header = item->header();
+                QByteArray header = model->header(index);
                 EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) header.data();
 
                 // Section with children
-                if (item->childCount()) {
+                if (model->rowCount(index)) {
                     // Reconstruct section body
-                    for (int i = 0; i < item->childCount(); i++) {
+                    for (int i = 0; i < model->rowCount(index); i++) {
                         // Reconstruct subsections
                         result = reconstruct(index.child(i, index.column()), childrenQueue);
                         if (result)
@@ -2269,39 +2242,39 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
 
                         // Append current subsection to new section body
                         reconstructed.append(section);
-                        
+
                         // Change current file offset
                         offset += section.size();
                     }
 
                     // Only this 2 sections can have compressed body
-                    if (item->subtype() == EFI_SECTION_COMPRESSION) {
+                    if (model->subtype(index) == EFI_SECTION_COMPRESSION) {
                         EFI_COMPRESSION_SECTION* compessionHeader = (EFI_COMPRESSION_SECTION*) header.data();
                         // Set new uncompressed size
                         compessionHeader->UncompressedLength = reconstructed.size();
                         // Compress new section body
                         QByteArray compressed;
-                        result = compress(reconstructed, item->compression(), compressed);
+                        result = compress(reconstructed, model->compression(index), compressed);
                         if (result)
                             return result;
-						// Correct compression type
-                        if (item->compression() == COMPRESSION_ALGORITHM_NONE)
+                        // Correct compression type
+                        if (model->compression(index) == COMPRESSION_ALGORITHM_NONE)
                             compessionHeader->CompressionType = EFI_NOT_COMPRESSED;
-                        else if (item->compression() == COMPRESSION_ALGORITHM_LZMA || item->compression() == COMPRESSION_ALGORITHM_IMLZMA)
+                        else if (model->compression(index) == COMPRESSION_ALGORITHM_LZMA || model->compression(index) == COMPRESSION_ALGORITHM_IMLZMA)
                             compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
-                        else if (item->compression() == COMPRESSION_ALGORITHM_EFI11 || item->compression() == COMPRESSION_ALGORITHM_TIANO)
+                        else if (model->compression(index) == COMPRESSION_ALGORITHM_EFI11 || model->compression(index) == COMPRESSION_ALGORITHM_TIANO)
                             compessionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
-						else 
-							return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
+                        else
+                            return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
 
                         // Replace new section body
                         reconstructed = compressed;
                     }
-                    else if (item->subtype() == EFI_SECTION_GUID_DEFINED) {
+                    else if (model->subtype(index) == EFI_SECTION_GUID_DEFINED) {
                         EFI_GUID_DEFINED_SECTION* guidDefinedHeader = (EFI_GUID_DEFINED_SECTION*) header.data();
                         // Compress new section body
                         QByteArray compressed;
-                        result = compress(reconstructed, item->compression(), compressed);
+                        result = compress(reconstructed, model->compression(index), compressed);
                         if (result)
                             return result;
                         // Check for auth status valid attribute
@@ -2312,9 +2285,9 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                         // Replace new section body
                         reconstructed = compressed;
                     }
-                    else if (item->compression() != COMPRESSION_ALGORITHM_NONE) {
+                    else if (model->compression(index) != COMPRESSION_ALGORITHM_NONE) {
                         msg(tr("reconstruct: incorreclty required compression for section of type %1")
-                            .arg(item->subtype()));
+                            .arg(model->subtype(index)));
                         return ERR_INVALID_SECTION;
                     }
 
@@ -2322,8 +2295,8 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
                     uint32ToUint24(header.size() + reconstructed.size(), commonHeader->Size);
                 }
                 // Leaf section
-                else 
-                    reconstructed = item->body();
+                else
+                    reconstructed = model->body(index);
 
                 // Enqueue reconstructed item
                 queue.enqueue(header.append(reconstructed));
@@ -2331,13 +2304,13 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
             break;
 
         default:
-            msg(tr("reconstruct: Unknown item type (%1)").arg(item->type()));
+            msg(tr("reconstruct: Unknown item type (%1)").arg(model->type(index)));
             return ERR_UNKNOWN_ITEM_TYPE;
         }
-        
+
         return ERR_SUCCESS;
     }
-    
+
     return ERR_NOT_IMPLEMENTED;
 }
 
@@ -2382,92 +2355,84 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
 // Search routines
 UINT8 FfsEngine::findHexPattern(const QByteArray & pattern, const UINT8 mode)
 {
-	return findHexPatternIn(treeModel->index(0,0), pattern, mode);
+    return findHexPatternIn(model->index(0,0), pattern, mode);
 }
 
 UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode)
 {
-	if (pattern.isEmpty())
-		return ERR_INVALID_PARAMETER;
-	
-	if (!index.isValid())
+    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 = (model->rowCount(index) > 0);
+    for (int i = 0; i < model->rowCount(index); i++) {
+        findHexPatternIn(index.child(i, index.column()), pattern, mode);
+    }
 
-	bool hasChildren = (item->childCount() > 0);
-	for (int i = 0; i < item->childCount(); i++) {
-		findHexPatternIn(index.child(i, index.column()), pattern, mode);
-	}
-	
-	QByteArray data;
-	if (hasChildren) {
-		if(mode != SEARCH_MODE_BODY) 
-			data = item->header();
-	}
-	else {
-		if (mode == SEARCH_MODE_HEADER)
-			data.append(item->header()).append(item->tail());
-		else if (mode == SEARCH_MODE_BODY)
-			data.append(item->body());
-		else
-			data.append(item->header()).append(item->body()).append(item->tail());
-	}
+    QByteArray data;
+    if (hasChildren) {
+        if(mode != SEARCH_MODE_BODY)
+            data = model->header(index);
+    }
+    else {
+        if (mode == SEARCH_MODE_HEADER)
+            data.append(model->header(index)).append(model->tail(index));
+        else if (mode == SEARCH_MODE_BODY)
+            data.append(model->body(index));
+        else
+            data.append(model->header(index)).append(model->body(index)).append(model->tail(index));
+    }
 
-	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);
-	}
+    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(model->nameString(index))
+            .arg(offset, 8, 16, QChar('0')),
+            index);
+    }
 
-	return ERR_SUCCESS;
+    return ERR_SUCCESS;
 }
 
 UINT8 FfsEngine::findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
 {
-	return findTextPatternIn(treeModel->index(0,0), pattern, unicode, caseSensitive);
+    return findTextPatternIn(model->index(0,0), pattern, unicode, caseSensitive);
 }
 
 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())
+    if (pattern.isEmpty())
+        return ERR_INVALID_PARAMETER;
+
+    if (!index.isValid())
         return ERR_SUCCESS;
 
-    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
-    if (item == rootItem)
+    bool hasChildren = (model->rowCount(index) > 0);
+    for (int i = 0; i < model->rowCount(index); i++) {
+        findTextPatternIn(index.child(i, index.column()), pattern, unicode, caseSensitive);
+    }
+
+    if (hasChildren)
         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*) model->body(index).data(), model->body(index).length()/2);
+    else
+        data = QString::fromLatin1((const char*) model->body(index).data(), model->body(index).length());
 
-	QString data;
-	if (unicode)
-		data = QString::fromUtf16((const ushort*) item->body().data(), item->body().length()/2);
-	else
-        data = QString::fromLatin1((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(model->nameString(index))
+            .arg(unicode ? offset*2 : offset, 8, 16, QChar('0')),
+            index);
+    }
 
-	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;
+    return ERR_SUCCESS;
 }
diff --git a/ffsengine.h b/ffsengine.h
index 8390975..b59c939 100644
--- a/ffsengine.h
+++ b/ffsengine.h
@@ -19,7 +19,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <QQueue>
 
 #include "basetypes.h"
-#include "treeitem.h"
 #include "treemodel.h"
 #include "messagelistitem.h"
 
@@ -33,15 +32,15 @@ public:
     // Default constructor and destructor
     FfsEngine(QObject *parent = 0);
     ~FfsEngine(void);
-    
+
     // Returns model for Qt view classes
-    TreeModel* model() const;
+    TreeModel* treeModel() const;
 
     // Returns message items queue
     QQueue<MessageListItem> messages() const;
 
-	// Clears message items queue
-	void clearMessages();
+    // Clears message items queue
+    void clearMessages();
 
     // Firmware image parsing
     UINT8 parseInputFile(const QByteArray & buffer);
@@ -63,7 +62,7 @@ public:
     // Compression routines
     UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL);
     UINT8 compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData);
-    
+
     // Construction routines
     UINT8 reconstructImage(QByteArray & reconstructed);
     UINT8 constructPadFile(const UINT32 size, const UINT8 revision, const UINT8 erasePolarity, QByteArray & pad);
@@ -71,32 +70,30 @@ public:
     UINT8 growVolume(QByteArray & header, const UINT32 size, UINT32 & newSize);
 
     // Operations on tree items
-	UINT8 extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode);
-	
-	UINT8 create(const QModelIndex & index, const UINT8 type, const QByteArray & header, const QByteArray & body, const UINT8 mode, const UINT8 action, const UINT8 algorithm = COMPRESSION_ALGORITHM_NONE);
-	UINT8 insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
-	UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
-	    
-	UINT8 remove(const QModelIndex & index);
-    
-	UINT8 rebuild(const QModelIndex & index);
-    
-	// Search routines
-	UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
-	UINT8 findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode);
-	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);
+    UINT8 extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode);
+
+    UINT8 create(const QModelIndex & index, const UINT8 type, const QByteArray & header, const QByteArray & body, const UINT8 mode, const UINT8 action, const UINT8 algorithm = COMPRESSION_ALGORITHM_NONE);
+    UINT8 insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
+    UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
+
+    UINT8 remove(const QModelIndex & index);
+
+    UINT8 rebuild(const QModelIndex & index);
+
+    // Search routines
+    UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
+    UINT8 findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode);
+    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:
-    TreeItem  *rootItem;
-    TreeModel *treeModel;
-    
-	// Message helper
+    TreeModel *model;
+
+    // Message helper
     QQueue<MessageListItem> messageItems;
     void msg(const QString & message, const QModelIndex index = QModelIndex());
-    
+
     // Internal operations
-    QModelIndex findParentOfType(UINT8 type, const QModelIndex & index) const;
     bool hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
 };
 
diff --git a/treeitem.cpp b/treeitem.cpp
index 8f2dc81..b0e3855 100644
--- a/treeitem.cpp
+++ b/treeitem.cpp
@@ -1,13 +1,13 @@
 /* treeitem.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                                            
+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.             
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 */
 
@@ -16,56 +16,56 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "ffs.h"
 #include "descriptor.h"
 
-QString itemTypeToQString(const UINT8 type) 
+QString itemTypeToQString(const UINT8 type)
 {
     switch (type) {
-    case TreeItem::Root:
+    case Root:
         return QObject::tr("Root");
-    case TreeItem::Image:
+    case Image:
         return QObject::tr("Image");
-    case TreeItem::Capsule:
+    case Capsule:
         return QObject::tr("Capsule");
-    case TreeItem::Region:
+    case Region:
         return QObject::tr("Region");
-    case TreeItem::Volume:
+    case Volume:
         return QObject::tr("Volume");
-    case TreeItem::Padding:
+    case Padding:
         return QObject::tr("Padding");
-    case TreeItem::File:
+    case File:
         return QObject::tr("File");
-    case TreeItem::Section:
+    case Section:
         return QObject::tr("Section");
     default:
         return QObject::tr("Unknown");
     }
 }
 
-QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) 
+QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
 {
     switch (type) {
-    case TreeItem::Root:
-    case TreeItem::Image:
-        if (subtype == TreeItem::IntelImage)
+    case Root:
+    case Image:
+        if (subtype == IntelImage)
             return QObject::tr("Intel");
-        else if (subtype == TreeItem::BiosImage)
+        else if (subtype == BiosImage)
             return QObject::tr("BIOS");
         else
             return QObject::tr("Unknown");
-    case TreeItem::Padding:
-    case TreeItem::Volume:
+    case Padding:
+    case Volume:
         return "";
-    case TreeItem::Capsule:
-        if (subtype == TreeItem::AptioCapsule)
+    case Capsule:
+        if (subtype == AptioCapsule)
             return QObject::tr("Aptio extended");
-        else if (subtype == TreeItem::UefiCapsule)
+        else if (subtype == UefiCapsule)
             return QObject::tr("UEFI 2.0");
         else
             return QObject::tr("Unknown");
-    case TreeItem::Region:
+    case Region:
         return regionTypeToQString(subtype);
-    case TreeItem::File:
+    case File:
         return fileTypeToQString(subtype);
-    case TreeItem::Section:
+    case Section:
         return sectionTypeToQString(subtype);
     default:
         return QObject::tr("Unknown");
@@ -91,8 +91,8 @@ QString compressionTypeToQString(UINT8 algorithm)
 }
 
 TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
-                   const QString & name, const QString & text, const QString & info, 
-                   const QByteArray & header, const QByteArray & body, const QByteArray & tail, 
+                   const QString & name, const QString & text, const QString & info,
+                   const QByteArray & header, const QByteArray & body, const QByteArray & tail,
                    TreeItem *parent)
 {
     itemAction = NoAction;
@@ -106,7 +106,7 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compressio
     itemBody = body;
     itemTail = tail;
     parentItem = parent;
-    
+
     // Set default names
     setDefaultNames();
 }
@@ -172,15 +172,15 @@ QVariant TreeItem::data(int column) const
     case 0: //Name
         return itemName;
     case 1: //Action
-		if (itemAction == TreeItem::Create)
+        if (itemAction == Create)
             return QObject::tr("Create");
-		if (itemAction == TreeItem::Insert)
+        if (itemAction == Insert)
             return QObject::tr("Insert");
-        if (itemAction == TreeItem::Replace)
+        if (itemAction == Replace)
             return QObject::tr("Replace");
-        if (itemAction == TreeItem::Remove)
+        if (itemAction == Remove)
             return QObject::tr("Remove");
-        if (itemAction == TreeItem::Rebuild)
+        if (itemAction == Rebuild)
             return QObject::tr("Rebuild");
         return QVariant();
     case 2: //Type
@@ -286,13 +286,14 @@ void TreeItem::setAction(const UINT8 action)
 {
     itemAction = action;
 
-	// On insert action, set insert action for children
-	if (action == TreeItem::Insert)
-		for(int i = 0; i < childCount(); i++)
-			child(i)->setAction(TreeItem::Insert);
-	
-	// Set rebuild action for parent, if it has no action now
-	if (parentItem && parentItem->type() != TreeItem::Root && parentItem->action() == TreeItem::NoAction)
-			parentItem->setAction(TreeItem::Rebuild);
+    // On insert action, set insert action for children
+    if (action == Insert)
+        for(int i = 0; i < childCount(); i++)
+            child(i)->setAction(Insert);
+
+    // Set rebuild action for parent, if it has no action now
+    if (parentItem && parentItem->type() != Root
+     && parentItem->action() == NoAction)
+            parentItem->setAction(Rebuild);
 }
 
diff --git a/treeitem.h b/treeitem.h
index 0abd597..5d25834 100644
--- a/treeitem.h
+++ b/treeitem.h
@@ -1,13 +1,13 @@
 /* treeitem.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                                            
+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.             
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 */
 
@@ -28,55 +28,10 @@ extern QString compressionTypeToQString(UINT8 algorithm);
 class TreeItem
 {
 public:
-    // Action types
-    enum ActionTypes {
-        NoAction = 50,
-		Create,
-        Insert,
-		Replace,
-        Remove,      
-        Rebuild
-    };
-    
-    // Item types
-    enum ItemTypes {
-        Root = 60,
-        Capsule,    
-        Image,      
-        Region,     
-        Padding,    
-        Volume,     
-        File,       
-        Section    
-    };
-
-    // Image subtypes 
-    enum ImageSubtypes{
-        IntelImage = 70,
-        BiosImage
-    };
-
-    // Capsule subtypes
-    enum CapsuleSubtypes {
-        AptioCapsule = 80,
-        UefiCapsule
-    };
-
-    // Region subtypes
-    enum RegionSubtypes {
-        DescriptorRegion = 90,
-        GbeRegion,
-        MeRegion,
-        BiosRegion,
-        PdrRegion
-    };
-    
-    // Constructor
-    TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, 
-        const QString &name = QString(), const QString &text = QString(), const QString &info = QString(), 
+    TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
+        const QString &name = QString(), const QString &text = QString(), const QString &info = QString(),
         const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
         TreeItem *parent = 0);
-    // Destructor
     ~TreeItem();
 
     // Operations with items
@@ -107,8 +62,8 @@ public:
     UINT8 compression() const;
 
     // Some values can be changed after item construction
-	void setAction(const UINT8 action); 
-	void setTypeName(const QString &text);
+    void setAction(const UINT8 action);
+    void setTypeName(const QString &text);
     void setSubtypeName(const QString &text);
     void setName(const QString &text);
     void setText(const QString &text);
@@ -117,7 +72,7 @@ private:
     // Set default names after construction
     // They can later be changed by set* methods
     void setDefaultNames();
-    
+
     QList<TreeItem*> childItems;
     UINT8 itemAction;
     UINT8 itemType;
@@ -126,8 +81,8 @@ private:
     QByteArray itemHeader;
     QByteArray itemBody;
     QByteArray itemTail;
-	QString itemName;
-	QString itemTypeName;
+    QString itemName;
+    QString itemTypeName;
     QString itemSubtypeName;
     QString itemText;
     QString itemInfo;
diff --git a/treemodel.cpp b/treemodel.cpp
index 0112a61..37686a4 100644
--- a/treemodel.cpp
+++ b/treemodel.cpp
@@ -1,27 +1,28 @@
 /* treemodel.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                                            
+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.             
+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 "treeitem.h"
 #include "treemodel.h"
 
-TreeModel::TreeModel(TreeItem *root, QObject *parent)
+TreeModel::TreeModel(QObject *parent)
     : QAbstractItemModel(parent)
 {
-    rootItem = root;
+    rootItem = new TreeItem(Root);
 }
 
 TreeModel::~TreeModel()
 {
+    delete rootItem;
 }
 
 int TreeModel::columnCount(const QModelIndex &parent) const
@@ -62,20 +63,20 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
                                int role) const
 {
     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
-		switch(section) 
-		{
-		case 0:
-			return tr("Name");
-		case 1:
-			return tr("Action");
-		case 2:
-			return tr("Type");
-		case 3:
-			return tr("Subtype");
-		case 4:
-			return tr("Text");
-		}
-	}
+        switch(section)
+        {
+        case 0:
+            return tr("Name");
+        case 1:
+            return tr("Action");
+        case 2:
+            return tr("Type");
+        case 3:
+            return tr("Subtype");
+        case 4:
+            return tr("Text");
+        }
+    }
 
     return QVariant();
 }
@@ -108,7 +109,7 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const
     TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
     if (childItem == rootItem)
         return QModelIndex();
-    
+
     TreeItem *parentItem = childItem->parent();
 
     if (parentItem == rootItem)
@@ -117,7 +118,6 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const
     return createIndex(parentItem->row(), 0, parentItem);
 }
 
-
 int TreeModel::rowCount(const QModelIndex &parent) const
 {
     TreeItem *parentItem;
@@ -132,63 +132,213 @@ int TreeModel::rowCount(const QModelIndex &parent) const
     return parentItem->childCount();
 }
 
-UINT8 TreeModel::setItemName(const QString &data, const QModelIndex &index)
+UINT8 TreeModel::type(const QModelIndex &index) const
 {
     if(!index.isValid())
-        return ERR_INVALID_PARAMETER;
-    
+        return 0;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->type();
+}
+
+UINT8 TreeModel::subtype(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return 0;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->subtype();
+}
+
+QByteArray TreeModel::header(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QByteArray();
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->header();
+}
+
+bool TreeModel::hasEmptyHeader(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return true;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->hasEmptyHeader();
+}
+
+QByteArray TreeModel::body(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QByteArray();
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->body();
+}
+
+bool TreeModel::hasEmptyBody(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return true;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->hasEmptyBody();
+}
+
+QByteArray TreeModel::tail(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QByteArray();
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->tail();
+}
+
+bool TreeModel::hasEmptyTail(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return true;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->hasEmptyTail();
+}
+
+QString TreeModel::info(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QString();
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->info();
+}
+
+UINT8 TreeModel::action(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return NoAction;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->action();
+}
+
+UINT8 TreeModel::compression(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return COMPRESSION_ALGORITHM_UNKNOWN;
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->compression();
+}
+
+void TreeModel::setNameString(const QModelIndex &index, const QString &data)
+{
+    if(!index.isValid())
+        return;
+
     TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
     item->setName(data);
     emit dataChanged(index, index);
-    return ERR_SUCCESS;
 }
 
-UINT8 TreeModel::setItemText(const QString &data, const QModelIndex &index)
+void TreeModel::setTypeString(const QModelIndex &index, const QString &data)
 {
     if(!index.isValid())
-        return ERR_INVALID_PARAMETER;
+        return;
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    item->setTypeName(data);
+    emit dataChanged(index, index);
+}
+
+void TreeModel::setSubtypeString(const QModelIndex &index, const QString &data)
+{
+    if(!index.isValid())
+        return;
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    item->setSubtypeName(data);
+    emit dataChanged(index, index);
+}
+
+void TreeModel::setTextString(const QModelIndex &index, const QString &data)
+{
+    if(!index.isValid())
+        return;
 
     TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
     item->setText(data);
     emit dataChanged(index, index);
-    return ERR_SUCCESS;
 }
 
-UINT8 TreeModel::setItemAction(const UINT8 action, const QModelIndex &index)
+QString TreeModel::nameString(const QModelIndex &index) const
 {
     if(!index.isValid())
-        return ERR_INVALID_PARAMETER;
+        return QString();
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->data(0).toString();
+}
+
+QString TreeModel::actionString(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QString();
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->data(1).toString();}
+
+QString TreeModel::typeString(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QString();
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->data(2).toString();
+}
+
+QString TreeModel::subtypeString(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QString();
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->data(3).toString();
+}
+
+QString TreeModel::textString(const QModelIndex &index) const
+{
+    if(!index.isValid())
+        return QString();
+
+    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+    return item->data(4).toString();
+}
+
+
+void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
+{
+    if(!index.isValid())
+        return;
 
     TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
     item->setAction(action);
     emit dataChanged(this->index(0,0), index);
-    return ERR_SUCCESS;
 }
 
-QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression, 
-                               const QString & name, const QString & text, const QString & info, 
+QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
+                               const QString & name, const QString & text, const QString & info,
                                const QByteArray & header, const QByteArray & body, const QByteArray & tail,
-                               const QModelIndex & index, const UINT8 mode)
+                               const QModelIndex & parent, const UINT8 mode)
 {
     TreeItem *item = 0;
     TreeItem *parentItem = 0;
     int parentColumn = 0;
 
-    if (!index.isValid())
+    if (!parent.isValid())
         parentItem = rootItem;
     else
     {
         if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER) {
-            item = static_cast<TreeItem*>(index.internalPointer());
+            item = static_cast<TreeItem*>(parent.internalPointer());
             parentItem = item->parent();
-            parentColumn = index.parent().column();
+            parentColumn = parent.parent().column();
         }
         else {
-            parentItem = static_cast<TreeItem*>(index.internalPointer());
-            parentColumn = index.column();
+            parentItem = static_cast<TreeItem*>(parent.internalPointer());
+            parentColumn = parent.column();
         }
     }
-    
+
     TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, tail, parentItem);
     if (mode == CREATE_MODE_APPEND) {
         emit layoutAboutToBeChanged();
@@ -206,10 +356,28 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
         emit layoutAboutToBeChanged();
         parentItem->insertChildAfter(item, newItem);
     }
-    else 
+    else
         return QModelIndex();
-    
+
     emit layoutChanged();
-    
+
     return createIndex(newItem->row(), parentColumn, newItem);
 }
+
+QModelIndex TreeModel::findParentOfType(const QModelIndex& index, UINT8 type) const
+{
+    if(!index.isValid())
+        return QModelIndex();
+
+    TreeItem *item;
+    QModelIndex parent = index;
+
+    for(item = static_cast<TreeItem*>(parent.internalPointer());
+        item != NULL && item != rootItem && item->type() != type;
+        item = static_cast<TreeItem*>(parent.internalPointer()))
+        parent = parent.parent();
+    if (item != NULL && item != rootItem)
+        return parent;
+
+    return QModelIndex();
+}
diff --git a/treemodel.h b/treemodel.h
index 410c40f..ae00036 100644
--- a/treemodel.h
+++ b/treemodel.h
@@ -1,13 +1,13 @@
 /* treemodel.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                                            
+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.             
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 */
 
@@ -28,7 +28,7 @@ class TreeModel : public QAbstractItemModel
     Q_OBJECT
 
 public:
-    TreeModel(TreeItem *root, QObject *parent = 0);
+    TreeModel(QObject *parent = 0);
     ~TreeModel();
 
     QVariant data(const QModelIndex &index, int role) const;
@@ -40,15 +40,37 @@ public:
     QModelIndex parent(const QModelIndex &index) const;
     int rowCount(const QModelIndex &parent = QModelIndex()) const;
     int columnCount(const QModelIndex &parent = QModelIndex()) const;
-    
-    UINT8 setItemName(const QString &data, const QModelIndex &index);
-    UINT8 setItemText(const QString &data, const QModelIndex &index);
-    UINT8 setItemAction(const UINT8 action, const QModelIndex &index);
+
+    QString nameString(const QModelIndex &index) const;
+    QString actionString(const QModelIndex &index) const;
+    QString typeString(const QModelIndex &index) const;
+    QString subtypeString(const QModelIndex &index) const;
+    QString textString(const QModelIndex &index) const;
+
+    void setAction(const QModelIndex &index, const UINT8 action);
+    void setTypeString(const QModelIndex &index, const QString &text);
+    void setSubtypeString(const QModelIndex &index, const QString &text);
+    void setNameString(const QModelIndex &index, const QString &text);
+    void setTextString(const QModelIndex &index, const QString &text);
+
+    UINT8 type(const QModelIndex &index) const;
+    UINT8 subtype(const QModelIndex &index) const;
+    QByteArray header(const QModelIndex &index) const;
+    bool hasEmptyHeader(const QModelIndex &index) const;
+    QByteArray body(const QModelIndex &index) const;
+    bool hasEmptyBody(const QModelIndex &index) const;
+    QByteArray tail(const QModelIndex &index) const;
+    bool hasEmptyTail(const QModelIndex &index) const;
+    QString info(const QModelIndex &index) const;
+    UINT8 action(const QModelIndex &index) const;
+    UINT8 compression(const QModelIndex &index) const;
 
     QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
-        const QString & name = QString(), const QString & text = QString(), const QString & info = QString(), 
+        const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
         const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
-        const QModelIndex & index = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
+        const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
+
+    QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;
 
 private:
     TreeItem *rootItem;
diff --git a/uefitool.cpp b/uefitool.cpp
index f0141b8..bac7fb1 100644
--- a/uefitool.cpp
+++ b/uefitool.cpp
@@ -21,23 +21,23 @@ UEFITool::UEFITool(QWidget *parent) :
     // Create UI
     ui->setupUi(this);
     searchDialog = new SearchDialog(this);
-	ffsEngine = NULL;
-	
+    ffsEngine = NULL;
+
     // Connect signals to slots
     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->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
+    connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
     connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
     connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
     connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
     connect(ui->actionInsertBefore, SIGNAL(triggered()), this, SLOT(insertBefore()));
     connect(ui->actionInsertAfter, SIGNAL(triggered()), this, SLOT(insertAfter()));
     connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replaceAsIs()));
-	connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody()));
+    connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody()));
     connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
     connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild()));
     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->actionQuit, SIGNAL(triggered()), this, SLOT(exit()));
     connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(writeSettings()));
@@ -47,24 +47,24 @@ UEFITool::UEFITool(QWidget *parent) :
 
     // Initialize non-persistent data
     init();
-	
-	// Read stored settings
-	readSettings();
+
+    // Read stored settings
+    readSettings();
 }
 
 UEFITool::~UEFITool()
 {
     delete ui;
     delete ffsEngine;
-	delete searchDialog;
+    delete searchDialog;
 }
 
 void UEFITool::init()
 {
-	// Clear components
+    // Clear components
     ui->messageListWidget->clear();
     ui->infoEdit->clear();
-    
+
     // Disable menus
     ui->menuCapsuleActions->setDisabled(true);
     ui->menuImageActions->setDisabled(true);
@@ -78,8 +78,8 @@ void UEFITool::init()
     if (ffsEngine)
         delete ffsEngine;
     ffsEngine = new FfsEngine(this);
-    ui->structureTreeView->setModel(ffsEngine->model());
-    
+    ui->structureTreeView->setModel(ffsEngine->treeModel());
+
     // Connect
     connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
         this, SLOT(populateUi(const QModelIndex &)));
@@ -91,62 +91,62 @@ void UEFITool::populateUi(const QModelIndex &current)
     if (!current.isValid())
         return;
 
-    TreeItem* item = static_cast<TreeItem*>(current.internalPointer());
-    UINT8 type = item->type();
-    UINT8 subtype = item->subtype();
-    
+    TreeModel* model = ffsEngine->treeModel();
+    UINT8 type = model->type(current);
+    UINT8 subtype =  model->subtype(current);
+
     // Set info text
-    ui->infoEdit->setPlainText(item->info());
+    ui->infoEdit->setPlainText(model->info(current));
 
     // 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);
-    
+    ui->menuCapsuleActions->setEnabled(type == Capsule);
+    ui->menuImageActions->setEnabled(type == Image);
+    ui->menuRegionActions->setEnabled(type == Region);
+    ui->menuPaddingActions->setEnabled(type == Padding);
+    ui->menuVolumeActions->setEnabled(type == Volume);
+    ui->menuFileActions->setEnabled(type == File);
+    ui->menuSectionActions->setEnabled(type == Section);
+
     // Enable actions
-    ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
-    ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
-    ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
-    ui->actionRemove->setEnabled(type == TreeItem::Volume || type == TreeItem::File || type == TreeItem::Section);
-    ui->actionInsertInto->setEnabled(type == TreeItem::Volume || (type == TreeItem::File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD));
-    ui->actionInsertBefore->setEnabled(type == TreeItem::File || type == TreeItem::Section);
-    ui->actionInsertAfter->setEnabled(type == TreeItem::File || type == TreeItem::Section);
-	ui->actionReplace->setEnabled(type == TreeItem::File || type == TreeItem::Section);
-	ui->actionReplaceBody->setEnabled(type == TreeItem::File || type == TreeItem::Section);
+    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->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->actionInsertBefore->setEnabled(type == File || type == Section);
+    ui->actionInsertAfter->setEnabled(type == File || type == Section);
+    ui->actionReplace->setEnabled(type == File || type == Section);
+    ui->actionReplaceBody->setEnabled(type == File || type == Section);
 }
 
 void UEFITool::search()
 {
-	if (searchDialog->exec() != QDialog::Accepted)
-		return;
+    if (searchDialog->exec() != QDialog::Accepted)
+        return;
 
-	int index = searchDialog->ui->dataTypeComboBox->currentIndex();
-	if (index == 0) { // Hex pattern
+    int index = searchDialog->ui->dataTypeComboBox->currentIndex();
+    if (index == 0) { // Hex pattern
         QByteArray pattern = QByteArray::fromHex(searchDialog->ui->searchEdit->text().toLatin1());
-		if (pattern.isEmpty())
-			return;
-		UINT8 mode;
-		if (searchDialog->ui->headerOnlyRadioButton->isChecked())
-			mode = SEARCH_MODE_HEADER;
-		else if (searchDialog->ui->bodyOnlyRadioButton->isChecked())
-			mode = SEARCH_MODE_BODY;
-		else
-			mode = SEARCH_MODE_ALL;
-		ffsEngine->findHexPattern(pattern, mode);
-		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();
-	}
+        if (pattern.isEmpty())
+            return;
+        UINT8 mode;
+        if (searchDialog->ui->headerOnlyRadioButton->isChecked())
+            mode = SEARCH_MODE_HEADER;
+        else if (searchDialog->ui->bodyOnlyRadioButton->isChecked())
+            mode = SEARCH_MODE_BODY;
+        else
+            mode = SEARCH_MODE_ALL;
+        ffsEngine->findHexPattern(pattern, mode);
+        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()
@@ -156,7 +156,7 @@ void UEFITool::rebuild()
         return;
 
     UINT8 result = ffsEngine->rebuild(index);
-    
+
     if (result == ERR_SUCCESS)
         ui->actionSaveImageFile->setEnabled(true);
 }
@@ -178,26 +178,26 @@ void UEFITool::insert(const UINT8 mode)
     QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
     if (!index.isValid())
         return;
-    
-    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
+
+    TreeModel* model = ffsEngine->treeModel();
     UINT8 type;
     UINT8 objectType;
 
     if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
-        type = item->parent()->type();
+        type = model->type(index.parent());
     else
-        type = item->type();
+        type = model->type(index);
 
     QString path;
     switch (type) {
-    case TreeItem::Volume:
+    case Volume:
         path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS files (*.ffs *.bin);;All files (*.*)");
-        objectType = TreeItem::File;
+        objectType = File;
     break;
-    case TreeItem::File:
-    case TreeItem::Section:
+    case File:
+    case Section:
         path = QFileDialog::getOpenFileName(this, tr("Select section file to insert"),".","Section files (*.sct *.bin);;All files (*.*)");
-        objectType = TreeItem::Section;
+        objectType = Section;
     break;
     default:
         return;
@@ -254,48 +254,48 @@ void UEFITool::replaceBody()
 
 void UEFITool::replace(const UINT8 mode)
 {
-	QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
+    QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
     if (!index.isValid())
         return;
 
-	TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
-	QString path;
-	if (item->type() == TreeItem::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 (*.*)");
-		}
-		else if (mode == REPLACE_MODE_BODY) {
-			if (item->subtype() == EFI_FV_FILETYPE_ALL || item->subtype() == EFI_FV_FILETYPE_RAW)
-				path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"),".","Raw files (*.raw *.bin);;All files (*.*)");
-			else if (item->subtype() == EFI_FV_FILETYPE_PAD) // Pad file body can't be replaced
-				return;
-			else
-				path = QFileDialog::getOpenFileName(this, tr("Select FFS file body to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
-		}
-		else
-			return;
-	}
-	else if (item->type() == TreeItem::Section) {
-		if (mode == REPLACE_MODE_AS_IS) {
-			path = QFileDialog::getOpenFileName(this, tr("Select section file to replace selected object"),".","Section files (*.sec *.bin);;All files (*.*)");
-		}
-		else if (mode == REPLACE_MODE_BODY) {
-			if (item->subtype() == EFI_SECTION_COMPRESSION || item->subtype() == EFI_SECTION_GUID_DEFINED || item->subtype() == EFI_SECTION_DISPOSABLE)
-				path = QFileDialog::getOpenFileName(this, tr("Select FFS file body file to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
-			else if (item->subtype() == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
-				path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"),".","Volume files (*.vol *.bin);;All files (*.*)");
-			else if (item->subtype() == EFI_SECTION_RAW)
-				path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"),".","Raw files (*.raw *.bin);;All files (*.*)");
-			else
-				path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"),".","Binary files (*.bin);;All files (*.*)");
-		}
-		else
-			return;
-	}
-	else
-		return;
+    TreeModel* model = ffsEngine->treeModel();
+    QString path;
+    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 (*.*)");
+        }
+        else if (mode == REPLACE_MODE_BODY) {
+            if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW)
+                path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"),".","Raw files (*.raw *.bin);;All files (*.*)");
+            else if (model->subtype(index) == EFI_FV_FILETYPE_PAD) // Pad file body can't be replaced
+                return;
+            else
+                path = QFileDialog::getOpenFileName(this, tr("Select FFS file body to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
+        }
+        else
+            return;
+    }
+    else if (model->type(index) == Section) {
+        if (mode == REPLACE_MODE_AS_IS) {
+            path = QFileDialog::getOpenFileName(this, tr("Select section file to replace selected object"),".","Section files (*.sec *.bin);;All files (*.*)");
+        }
+        else if (mode == REPLACE_MODE_BODY) {
+            if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)
+                path = QFileDialog::getOpenFileName(this, tr("Select FFS file body file to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
+            else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
+                path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"),".","Volume files (*.vol *.bin);;All files (*.*)");
+            else if (model->subtype(index) == EFI_SECTION_RAW)
+                path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"),".","Raw files (*.raw *.bin);;All files (*.*)");
+            else
+                path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"),".","Binary files (*.bin);;All files (*.*)");
+        }
+        else
+            return;
+    }
+    else
+        return;
 
-	QFileInfo fileInfo = QFileInfo(path);
+    QFileInfo fileInfo = QFileInfo(path);
     if (!fileInfo.exists()) {
         ui->statusBar->showMessage(tr("Please select existing file"));
         return;
@@ -334,68 +334,68 @@ void UEFITool::extract(const UINT8 mode)
     QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
     if (!index.isValid())
         return;
-    
-    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
-    UINT8 type = item->type();
+
+    TreeModel* model = ffsEngine->treeModel();
+    UINT8 type = model->type(index);
 
     QString path;
     if (mode == EXTRACT_MODE_AS_IS) {
         switch (type) {
-        case TreeItem::Capsule:
+        case Capsule:
             path = QFileDialog::getSaveFileName(this, tr("Save capsule to file"),".","Capsule files (*.cap *.bin);;All files (*.*)");
             break;
-        case TreeItem::Image:
+        case Image:
             path = QFileDialog::getSaveFileName(this, tr("Save image to file"),".","Image files (*.rom *.bin);;All files (*.*)");
             break;
-        case TreeItem::Region:
+        case Region:
             path = QFileDialog::getSaveFileName(this, tr("Save region to file"),".","Region files (*.rgn *.bin);;All files (*.*)");
             break;
-        case TreeItem::Padding:
+        case Padding:
             path = QFileDialog::getSaveFileName(this, tr("Save padding to file"),".","Padding files (*.pad *.bin);;All files (*.*)");
             break;
-        case TreeItem::Volume:
+        case Volume:
             path = QFileDialog::getSaveFileName(this, tr("Save volume to file"),".","Volume files (*.vol *.bin);;All files (*.*)");
             break;
-        case TreeItem::File:
+        case File:
             path = QFileDialog::getSaveFileName(this, tr("Save FFS file to file"),".","FFS files (*.ffs *.bin);;All files (*.*)");
             break;
-        case TreeItem::Section:
+        case Section:
             path = QFileDialog::getSaveFileName(this, tr("Save section file to file"),".","Section files (*.sct *.bin);;All files (*.*)");
         break;
         default:
-			path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
+            path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
         }
     }
-	else if (mode == EXTRACT_MODE_BODY) {
+    else if (mode == EXTRACT_MODE_BODY) {
         switch (type) {
-        case TreeItem::Capsule:
+        case Capsule:
             path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"),".","Image files (*.rom *.bin);;All files (*.*)");
             break;
-        case TreeItem::File: {
-				if (item->subtype() == EFI_FV_FILETYPE_ALL || item->subtype() == EFI_FV_FILETYPE_RAW)
-					path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to raw file"),".","Raw files (*.raw *.bin);;All files (*.*)");
-				else
-					path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to file"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
-			}
+        case File: {
+                if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW)
+                    path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to raw file"),".","Raw files (*.raw *.bin);;All files (*.*)");
+                else
+                    path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to file"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
+            }
             break;
-        case TreeItem::Section: {
-			if (item->subtype() == EFI_SECTION_COMPRESSION || item->subtype() == EFI_SECTION_GUID_DEFINED || item->subtype() == EFI_SECTION_DISPOSABLE)
-				path = QFileDialog::getSaveFileName(this, tr("Save encapsulated section body to FFS body file"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
-			else if (item->subtype() == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
-				path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"),".","Volume files (*.vol *.bin);;All files (*.*)");
-			else if (item->subtype() == EFI_SECTION_RAW)
-				path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"),".","Raw files (*.raw *.bin);;All files (*.*)");
-			else
-				path = QFileDialog::getSaveFileName(this, tr("Save section body to file"),".","Binary files (*.bin);;All files (*.*)");
-			}
+        case Section: {
+            if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)
+                path = QFileDialog::getSaveFileName(this, tr("Save encapsulated section body to FFS body file"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
+            else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
+                path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"),".","Volume files (*.vol *.bin);;All files (*.*)");
+            else if (model->subtype(index) == EFI_SECTION_RAW)
+                path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"),".","Raw files (*.raw *.bin);;All files (*.*)");
+            else
+                path = QFileDialog::getSaveFileName(this, tr("Save section body to file"),".","Binary files (*.bin);;All files (*.*)");
+            }
         break;
         default:
-			path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
+            path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
         }
     }
     else
         path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
-    
+
     QFile outputFile;
     outputFile.setFileName(path);
     if (!outputFile.open(QFile::WriteOnly)) {
@@ -405,7 +405,7 @@ void UEFITool::extract(const UINT8 mode)
 
     QByteArray extracted;
     UINT8 result = ffsEngine->extract(index, extracted, mode);
-    if (result) 
+    if (result)
         ui->statusBar->showMessage(tr("File can't be extracted (%1)").arg(result));
     else {
         outputFile.resize(0);
@@ -433,7 +433,7 @@ void UEFITool::aboutQt()
 
 void UEFITool::exit()
 {
-	QCoreApplication::exit(0);
+    QCoreApplication::exit(0);
 }
 
 void UEFITool::saveImageFile()
@@ -445,8 +445,8 @@ void UEFITool::saveImageFile()
     if (!outputFile.open(QFile::WriteOnly)) {
         ui->statusBar->showMessage(tr("Can't open file for writing"));
         return;
-    }    
-    
+    }
+
     QByteArray reconstructed;
     UINT8 result = ffsEngine->reconstructImage(reconstructed);
     showMessages();
@@ -501,15 +501,15 @@ void UEFITool::openImageFile(QString path)
     else
         ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
 
-	// Enable search
-	ui->actionSearch->setEnabled(true);
+    // Enable search
+    ui->actionSearch->setEnabled(true);
 }
 
 void UEFITool::clearMessages()
 {
-	ffsEngine->clearMessages();
-	messageItems.clear();
-	ui->messageListWidget->clear();
+    ffsEngine->clearMessages();
+    messageItems.clear();
+    ui->messageListWidget->clear();
 }
 
 void UEFITool::dragEnterEvent(QDragEnterEvent* event)
@@ -540,8 +540,8 @@ void UEFITool::scrollTreeView(QListWidgetItem* item)
 {
     MessageListItem* messageItem = (MessageListItem*) item;
     QModelIndex index = messageItem->index();
-	if (index.isValid()) {
-		ui->structureTreeView->scrollTo(index);
+    if (index.isValid()) {
+        ui->structureTreeView->scrollTo(index);
         ui->structureTreeView->selectionModel()->clearSelection();
         ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
     }
@@ -550,40 +550,40 @@ void UEFITool::scrollTreeView(QListWidgetItem* item)
 void UEFITool::contextMenuEvent(QContextMenuEvent* event)
 {
     if (ui->messageListWidget->underMouse()) {
-		ui->menuMessages->exec(event->globalPos());
-		return;
-	}
-	
-	if(!ui->structureTreeView->underMouse())
+        ui->menuMessages->exec(event->globalPos());
         return;
-    
-	QPoint pt = event->pos();
+    }
+
+    if(!ui->structureTreeView->underMouse())
+        return;
+
+    QPoint pt = event->pos();
     QModelIndex index = ui->structureTreeView->indexAt(ui->structureTreeView->viewport()->mapFrom(this, pt));
     if(!index.isValid())
         return;
 
-    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
-    switch(item->type())
+    TreeModel* model = ffsEngine->treeModel();
+    switch(model->type(index))
     {
-    case TreeItem::Capsule:
+    case Capsule:
         ui->menuCapsuleActions->exec(event->globalPos());
         break;
-    case TreeItem::Image:
+    case Image:
         ui->menuImageActions->exec(event->globalPos());
         break;
-    case TreeItem::Region:
+    case Region:
         ui->menuRegionActions->exec(event->globalPos());
         break;
-    case TreeItem::Padding:
+    case Padding:
         ui->menuPaddingActions->exec(event->globalPos());
         break;
-    case TreeItem::Volume:
+    case Volume:
         ui->menuVolumeActions->exec(event->globalPos());
         break;
-    case TreeItem::File:
+    case File:
         ui->menuFileActions->exec(event->globalPos());
         break;
-    case TreeItem::Section:
+    case Section:
         ui->menuSectionActions->exec(event->globalPos());
         break;
     }
@@ -591,35 +591,35 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
 
 void UEFITool::readSettings()
 {
-	QSettings settings("UEFITool.ini", QSettings::IniFormat, this);
-	resize(settings.value("mainWindow/size", QSize(800, 600)).toSize());
+    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);
-	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());
+    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);
+    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));
+    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));
 }
diff --git a/uefitool.ui b/uefitool.ui
index d74901d..466cf98 100644
--- a/uefitool.ui
+++ b/uefitool.ui
@@ -20,7 +20,7 @@
    <bool>true</bool>
   </property>
   <property name="windowTitle">
-   <string>UEFITool 0.13.0</string>
+   <string>UEFITool 0.14.0</string>
   </property>
   <widget class="QWidget" name="centralWidget">
    <property name="sizePolicy">