#include "xtreewidget.h" #include "qheaderview.h" #include "qmenu.h" #include "logmanager.h" XTreeWidget::XTreeWidget(QWidget *parent) : QTreeWidget(parent) { mFastFiles = QMap(); mZoneFiles = QMap(); //mDDSFiles = QMap(); //mIWIFiles = QMap(); mRootItemMap = QMap>(); setContextMenuPolicy(Qt::CustomContextMenu); setSelectionMode(QTreeWidget::SingleSelection); setColumnCount(3); header()->hide(); setMinimumWidth(350); setSortingEnabled(true); setIconSize(QSize(16, 16)); header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); // Set the last two columns to a fixed width //header()->setSectionResizeMode(1, QHeaderView::Fixed); //header()->setSectionResizeMode(2, QHeaderView::Fixed); // Adjust the fixed widths to suit your icon size (e.g., 32 pixels) //header()->resizeSection(0, 275); //header()->resizeSection(1, 32); //header()->resizeSection(2, 32); connect(this, &XTreeWidget::itemSelectionChanged, this, &XTreeWidget::ItemSelectionChanged); connect(this, &XTreeWidget::customContextMenuRequested, this, &XTreeWidget::PrepareContextMenu); } XTreeWidget::~XTreeWidget() { } void XTreeWidget::AddFastFile(FastFile* aFastFile) { XTreeWidgetItem *fastFileItem = new XTreeWidgetItem(this); fastFileItem->setText(0, aFastFile->GetStem()); fastFileItem->setIcon(0, Utils::CreateAssetIcon("FF")); if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("PC")); } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("360")); } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_PS3) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("PS3")); } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_WII) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("WII")); } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_WIIU) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("WU")); } if (aFastFile->GetCommonInfo().GetGame() == GAME_COD2) { fastFileItem->setIcon(2, Utils::CreateGameIcon(2)); } if (aFastFile->GetCommonInfo().GetGame() == GAME_COD4) { fastFileItem->setIcon(2, Utils::CreateGameIcon(4)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD5) { fastFileItem->setIcon(2, Utils::CreateGameIcon(5)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD6) { fastFileItem->setIcon(2, Utils::CreateGameIcon(6)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD7) { fastFileItem->setIcon(2, Utils::CreateGameIcon(7)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD8) { fastFileItem->setIcon(2, Utils::CreateGameIcon(8)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD9) { fastFileItem->setIcon(2, Utils::CreateGameIcon(9)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD10) { fastFileItem->setIcon(2, Utils::CreateGameIcon(10)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD11) { fastFileItem->setIcon(2, Utils::CreateGameIcon(11)); } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD12) { fastFileItem->setIcon(2, Utils::CreateGameIcon(12)); } AddZoneFile(aFastFile->GetZoneFile(), fastFileItem); mFastFiles[aFastFile->GetStem()] = aFastFile; resizeColumnToContents(1); setSortingEnabled(true); sortByColumn(0, Qt::AscendingOrder); } void XTreeWidget::AddAsset(XAsset* aAsset, const QString& aZoneFileName, XTreeWidgetItem* aRootItem) { const XAssetType assetType = aAsset->GetType(); QIcon assetIcon = Utils::CreateAssetIcon(assetType); QTreeWidgetItem *groupItem = nullptr; for (int i = 0; i < aRootItem->childCount(); i++) { QTreeWidgetItem *testItem = aRootItem->child(i); if (testItem && (testItem->text(0) == aAsset->GetName() || (testItem->text(0) + "s") == aAsset->GetName())) { groupItem = testItem; break; } } if (!groupItem) { QString newName = aAsset->GetName(); if (*(newName.end() - 1) != 's') { newName += 's'; } groupItem = new XTreeWidgetItem(aRootItem); groupItem->setText(0, newName); groupItem->setIcon(0, assetIcon); } XTreeWidgetItem *newItem = new XTreeWidgetItem(groupItem); newItem->SetAssetType(assetType); newItem->SetAssetPtr(aAsset); newItem->setText(0, aAsset->DisplayName()); newItem->setIcon(0, assetIcon); for (XAsset *subAsset : aAsset->SubAssets()) { AddAsset(subAsset, aZoneFileName, newItem); } update(); } void XTreeWidget::AddZoneFile(const ZoneFile* aZoneFile, XTreeWidgetItem *aParentItem) { XTreeWidgetItem *zoneItem; if (aParentItem != nullptr) { zoneItem = new XTreeWidgetItem(aParentItem); } else { zoneItem = new XTreeWidgetItem(this); } const QString zoneFileName = aZoneFile->GetBaseStem() + ".zone"; zoneItem->setText(0, zoneFileName); zoneItem->setIcon(0, Utils::CreateAssetIcon("ZF")); XAssetList assetList = aZoneFile->GetAssetList(); for (int i = 0; i < assetList.Size(); i++) { AddAsset(assetList.GetAsset(i), zoneFileName, zoneItem); } mZoneFiles[aZoneFile->GetBaseStem() + ".zone"] = aZoneFile; } void XTreeWidget::CloseFastFile(const QString aFFName) { const QString fileStem = aFFName; emit ItemClosed(fileStem); } void XTreeWidget::PrepareContextMenu(const QPoint &pos) { auto activeItem = itemAt(pos); if (!activeItem) { return; } if (activeItem->text(0).isEmpty()) { return; } QString activeText = activeItem->text(0); QMenu *contextMenu = new QMenu(this); if (activeText.contains(".dds")) { // const QString fileStem = activeText.replace(".dds", ""); // if (!mDDSFiles.contains(fileStem)) { // qDebug() << "Error: Could not find " << fileStem << " in DDS map!"; // return; // } // QAction *closeAction = new QAction("Close File"); // contextMenu->addAction(closeAction); // connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) { // Q_UNUSED(checked); // mDDSFiles.remove(fileStem); // invisibleRootItem()->removeChild(activeItem); // }); // QMenu *exportSubmenu = new QMenu("Export...", this); // contextMenu->addMenu(exportSubmenu); // const DDSFile* ddsFile = mDDSFiles[fileStem]; // QAction *exportIWIAction = new QAction("Export as IWI"); // exportSubmenu->addAction(exportIWIAction); // connect(exportIWIAction, &QAction::triggered, this, [ddsFile](bool checked) { // Q_UNUSED(checked); // ddsFile->SaveIWI(); // }); // QAction *exportPNGAction = new QAction("Export as PNG"); // exportSubmenu->addAction(exportPNGAction); // connect(exportPNGAction, &QAction::triggered, this, [ddsFile](bool checked) { // Q_UNUSED(checked); // ddsFile->SavePNG(); // }); // QAction *exportJPGAction = new QAction("Export as JPG"); // exportSubmenu->addAction(exportJPGAction); // connect(exportJPGAction, &QAction::triggered, this, [ddsFile](bool checked) { // Q_UNUSED(checked); // ddsFile->SaveJPG(); // }); } else if (activeText.contains(".iwi")) { // const QString fileStem = activeText.replace(".iwi", ""); // if (!mIWIFiles.contains(fileStem)) { // qDebug() << "Error: Could not find " << fileStem << " in IWI map!"; // return; // } // QAction *closeAction = new QAction("Close File"); // contextMenu->addAction(closeAction); // connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) { // Q_UNUSED(checked); // mIWIFiles.remove(fileStem); // invisibleRootItem()->removeChild(activeItem); // }); // QMenu *exportSubmenu = new QMenu("Export...", this); // contextMenu->addMenu(exportSubmenu); // const IWIFile* iwiFile = mIWIFiles[fileStem]; // QAction *exportDDSAction = new QAction("Export as DDS"); // exportSubmenu->addAction(exportDDSAction); // connect(exportDDSAction, &QAction::triggered, this, [iwiFile](bool checked) { // Q_UNUSED(checked); // iwiFile->SaveDDS(); // }); // QAction *exportPNGAction = new QAction("Export as PNG"); // exportSubmenu->addAction(exportPNGAction); // connect(exportPNGAction, &QAction::triggered, this, [iwiFile](bool checked) { // Q_UNUSED(checked); // iwiFile->SavePNG(); // }); // QAction *exportJPGAction = new QAction("Export as JPG"); // exportSubmenu->addAction(exportJPGAction); // connect(exportJPGAction, &QAction::triggered, this, [iwiFile](bool checked) { // Q_UNUSED(checked); // iwiFile->SaveJPG(); // }); } else if (activeText.contains(".ff")) { const QString fileStem = activeText; QMenu *closeMultipleAction = new QMenu("Close Multiple Tabs"); QAction *closeAllAction = new QAction("Close All"); closeMultipleAction->addAction(closeAllAction); connect(closeAllAction, &QAction::triggered, this, [this](bool checked) { Q_UNUSED(checked); mFastFiles.clear(); clear(); emit Cleared(); }); QAction *closeAllButAction = new QAction("Close All BUT This"); closeMultipleAction->addAction(closeAllButAction); connect(closeAllButAction, &QAction::triggered, this, [this, &activeItem](bool checked) { Q_UNUSED(checked); for (int i = 0; i < invisibleRootItem()->childCount(); i++) { auto childItem = invisibleRootItem()->child(i); if (childItem == activeItem) { continue; } const QString fileStem = childItem->text(0); if (!mFastFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; return; } mFastFiles.remove(fileStem); CloseFastFile(fileStem); invisibleRootItem()->removeChild(childItem); i--; } }); QAction *closeAboveAction = new QAction("Close All Above"); closeMultipleAction->addAction(closeAboveAction); connect(closeAboveAction, &QAction::triggered, this, [this, &activeItem](bool checked) { Q_UNUSED(checked); for (int i = 0; i < invisibleRootItem()->childCount(); i++) { auto childItem = invisibleRootItem()->child(i); if (childItem == activeItem) { return; } const QString fileStem = childItem->text(0); if (!mFastFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; return; } mFastFiles.remove(fileStem); CloseFastFile(fileStem); invisibleRootItem()->removeChild(childItem); i--; } }); QAction *closeBelowAction = new QAction("Close All Below"); closeMultipleAction->addAction(closeBelowAction); connect(closeBelowAction, &QAction::triggered, this, [this, &activeItem](bool checked) { Q_UNUSED(checked); bool ready = false; for (int i = 0; i < invisibleRootItem()->childCount(); i++) { auto childItem = invisibleRootItem()->child(i); if (!ready && (childItem != activeItem)) { continue; } if (childItem == activeItem) { ready = true; continue; } const QString fileStem = childItem->text(0); if (!mFastFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; return; } mFastFiles.remove(fileStem); CloseFastFile(fileStem); invisibleRootItem()->removeChild(childItem); i--; } }); contextMenu->addMenu(closeMultipleAction); QAction *closeAction = new QAction("Close File"); contextMenu->addAction(closeAction); connect(closeAction, &QAction::triggered, this, [this, &activeItem, &activeText](bool checked) { Q_UNUSED(checked); const QString fileStem = activeItem->text(0); mFastFiles.remove(fileStem); CloseFastFile(activeText); invisibleRootItem()->removeChild(activeItem); }); QMenu *exportSubmenu = new QMenu("Export...", this); contextMenu->addMenu(exportSubmenu); const FastFile* fastFile = mFastFiles[fileStem]; QAction *exportFastFileAction = new QAction("Export Fast File"); exportSubmenu->addAction(exportFastFileAction); connect(exportFastFileAction, &QAction::triggered, this, [fastFile](bool checked) { Q_UNUSED(checked); const QString fastFilePath = QFileDialog::getSaveFileName( nullptr, "Export Fast File...", QDir::currentPath(), "Fast File (*.ff);;All Files(*.*)"); fastFile->ExportFastFile(fastFilePath); }); QAction *exportZoneFileAction = new QAction("Export Zone File"); exportSubmenu->addAction(exportZoneFileAction); connect(exportZoneFileAction, &QAction::triggered, this, [](bool checked) { Q_UNUSED(checked); // const QString zoneFilePath = QFileDialog::getSaveFileName( // nullptr, "Export Zone File...", QDir::currentPath(), // "Zone File (*.zone);;All Files(*.*)"); //fastFile->GetZoneFile()->SaveZoneFile(zoneFilePath); }); } else if (activeText.contains(".zone")) { const QString fileStem = activeText; if (!mZoneFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Zone File map!"; return; } QMenu *exportSubmenu = new QMenu("Export...", this); contextMenu->addMenu(exportSubmenu); //const ZoneFile* zoneFile = mZoneFiles[fileStem]; QAction *exportZoneFileAction = new QAction("Export Zone File"); exportSubmenu->addAction(exportZoneFileAction); connect(exportZoneFileAction, &QAction::triggered, this, [](bool checked) { Q_UNUSED(checked); }); QAction *exportFastFileAction = new QAction("Export Fast File"); exportSubmenu->addAction(exportFastFileAction); connect(exportFastFileAction, &QAction::triggered, this, [](bool checked) { Q_UNUSED(checked); }); } else if (activeItem && activeText.contains(".wav")) { XTreeWidgetItem *parentItem = dynamic_cast(activeItem->parent()); while (parentItem && !parentItem->text(0).contains(".zone")) { parentItem = dynamic_cast(parentItem->parent()); if (parentItem == invisibleRootItem()) { break; } } if (parentItem && parentItem != invisibleRootItem() && parentItem->text(0).contains(".zone")) { //const QString fileStem = parentItem->text(0).section('.', 0, 0); // QVector LoadedSounds = mZoneFiles[fileStem]->GetAssetMap().sounds; // for (LoadedSound LoadedSound : LoadedSounds) { // for (Sound sound : LoadedSound.sounds) { // if (sound.path.contains(activeText)) { // QMenu *exportSubmenu = new QMenu("Export...", this); // contextMenu->addMenu(exportSubmenu); // QAction *exportWAVAction = new QAction("Export as WAV File"); // exportSubmenu->addAction(exportWAVAction); // connect(exportWAVAction, &QAction::triggered, this, [sound](bool checked) { // Q_UNUSED(checked); // QDir dir = QDir::currentPath(); // if (!dir.exists("exports/")) { // dir.mkdir("exports/"); // } // if (!dir.exists("exports/sounds/")) { // dir.mkdir("exports/sounds/"); // } // const QString fileName = "exports/sounds/" + sound.path.split('/').last(); // QFile wavFile(fileName); // if (!wavFile.open(QIODevice::WriteOnly)) { // qDebug() << "Failed to write wav file!"; // return; // } // wavFile.write(sound.data); // wavFile.close(); // }); // break; // } // } // } } } else if (activeItem && activeText == "Sounds") { XTreeWidgetItem *parentItem = dynamic_cast(activeItem->parent()); while (parentItem && !parentItem->text(0).contains(".zone")) { parentItem = dynamic_cast(parentItem->parent()); if (parentItem == invisibleRootItem()) { break; } } if (parentItem && parentItem != invisibleRootItem() && parentItem->text(0).contains(".zone")) { const QString fileStem = parentItem->text(0).section('.', 0, 0); //auto zoneFile = mZoneFiles[fileStem]; QMenu *exportSubmenu = new QMenu("Export...", this); contextMenu->addMenu(exportSubmenu); QAction *exportAllWAVAction = new QAction("Export ALL as WAV Files"); exportSubmenu->addAction(exportAllWAVAction); connect(exportAllWAVAction, &QAction::triggered, this, [](bool checked) { Q_UNUSED(checked); // for (LoadedSound LoadedSound : zoneFile->GetAssetMap().sounds) { // for (Sound sound : LoadedSound.sounds) { // if (!sound.dataLength) { continue; } // QDir dir = QDir::currentPath(); // if (!dir.exists("exports/")) { // dir.mkdir("exports/"); // } // if (!dir.exists("exports/sounds/")) { // dir.mkdir("exports/sounds/"); // } // const QString fileName = "exports/sounds/" + sound.path.split('/').last(); // QFile wavFile(fileName); // if (!wavFile.open(QIODevice::WriteOnly)) { // qDebug() << "Failed to write wav file!"; // return; // } // wavFile.write(sound.data); // wavFile.close(); // } // } }); } } QPoint pt(pos); contextMenu->exec(mapToGlobal(pt)); delete contextMenu; } void XTreeWidget::ItemSelectionChanged() { if (selectedItems().isEmpty()) { return; } XTreeWidgetItem *selectedItem = dynamic_cast(selectedItems().first()); if (!selectedItem) { return; } if (selectedItem->text(0).isEmpty()) { return; } QString selectedText = selectedItem->text(0); emit ItemSelected(selectedText); switch (selectedItem->AssetType()) { case ASSET_TYPE_NONE: if (selectedText.contains(".ff")) { if (!mFastFiles.contains(selectedText)) { LogManager::instance().addError("Could not find " + selectedText + " in Fast File map!"); return; } emit FastFileSelected(mFastFiles[selectedText], selectedText); } else if (selectedText.contains(".zone")) { if (!mZoneFiles.contains(selectedText)) { LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!"); return; } emit ZoneFileSelected(mZoneFiles[selectedText], selectedText); } break; case ASSET_TYPE_TECHNIQUE_SET: emit TechSetSelected(dynamic_cast(selectedItem->AssetPtr()), selectedText); break; case ASSET_TYPE_MATERIAL: emit MaterialSelected(dynamic_cast(selectedItem->AssetPtr()), selectedText); break; case ASSET_TYPE_RAWFILE: emit RawFileSelected(dynamic_cast(selectedItem->AssetPtr()), selectedText); break; default: break; }; } const ZoneFile* XTreeWidget::FindZoneFile(const QString aStem) { foreach (auto zoneFile, mZoneFiles) { if (zoneFile->GetStem() == aStem) { return zoneFile; } } return nullptr; } const FastFile *XTreeWidget::FindFastFile(const QString aStem) { foreach (auto fastFile, mFastFiles) { if (fastFile->GetStem() == aStem) { return fastFile; } } return nullptr; } bool XTreeWidget::HasZoneFile(const QString aStem) { return FindZoneFile(aStem) != nullptr; } bool XTreeWidget::HasFastFile(const QString aStem) { return FindFastFile(aStem) != nullptr; } // void XTreeWidget::AddIWIFile(IWIFile* aIWIFile) { // const QString iwiFileName = QString(aIWIFile->fileStem + ".iwi"); // for (int i = 0; i < invisibleRootItem()->childCount(); i++) { // auto iwiFileItem = invisibleRootItem()->child(i); // if (iwiFileItem->text(0) == iwiFileName) { // delete iwiFileItem; // } // } // XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this); // iwiItem->setIcon(0, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); // iwiItem->setText(0, iwiFileName); // mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile; // } // void XTreeWidget::AddDDSFile(DDSFile* aDDSFile) { // const QString ddsFileName = QString(aDDSFile->fileStem + ".dds"); // for (int i = 0; i < invisibleRootItem()->childCount(); i++) { // auto ddsFileItem = invisibleRootItem()->child(i); // if (ddsFileItem->text(0) == ddsFileName) { // delete ddsFileItem; // } // } // XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this); // ddsItem->setIcon(0, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); // ddsItem->setText(0, ddsFileName); // mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile; // }