Added support for exporting Trilogy and Wii de Asobu builds

This commit is contained in:
Aruki 2017-07-24 21:08:12 -06:00
parent 305fbbdeed
commit e4d7c37541
13 changed files with 11430 additions and 494 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,12 +17,14 @@
#define USE_ASSET_NAME_MAP 1 #define USE_ASSET_NAME_MAP 1
#define EXPORT_COOKED 1 #define EXPORT_COOKED 1
CGameExporter::CGameExporter(EGame Game, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion) CGameExporter::CGameExporter(EDiscType DiscType, EGame Game, bool FrontEnd, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion)
: mGame(Game) : mGame(Game)
, mRegion(Region) , mRegion(Region)
, mGameName(rkGameName) , mGameName(rkGameName)
, mGameID(rkGameID) , mGameID(rkGameID)
, mBuildVersion(BuildVersion) , mBuildVersion(BuildVersion)
, mDiscType(DiscType)
, mFrontEnd(FrontEnd)
, mpProgress(nullptr) , mpProgress(nullptr)
{ {
ASSERT(mGame != eUnknownGame); ASSERT(mGame != eUnknownGame);
@ -96,6 +98,70 @@ void CGameExporter::LoadResource(const CAssetID& rkID, std::vector<u8>& rBuffer)
if (pInst) LoadResource(*pInst, rBuffer); if (pInst) LoadResource(*pInst, rBuffer);
} }
bool CGameExporter::ShouldExportDiscNode(const nod::Node *pkNode, bool IsInRoot)
{
if (IsInRoot && mDiscType != eDT_Normal)
{
// Directories - exclude the filesystem for other games
if (pkNode->getKind() == nod::Node::Kind::Directory)
{
// Frontend is always included; this is for compatibility with Dolphin
if (pkNode->getName() == "fe")
return true;
else if (mFrontEnd)
return false;
switch (mGame)
{
case ePrime:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "MP1JPN") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "MP1") );
case eEchoes:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "MP2JPN") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "MP2") );
case eCorruption:
return (mDiscType == eDT_Trilogy && pkNode->getName() == "MP3");
default:
return false;
}
}
// Files - exclude the DOLs for other games
else
{
// Again - always include frontend. Always include opening.bnr as well.
if (pkNode->getName() == "rs5fe_p.dol" || pkNode->getName() == "opening.bnr")
return true;
else if (mFrontEnd)
return false;
switch (mGame)
{
case ePrime:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "rs5mp1jpn_p.dol") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp1_p.dol") );
case eEchoes:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "rs5mp2jpn_p.dol") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp2_p.dol") );
case eCorruption:
return (mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp3_p.dol");
default:
return false;
}
}
}
return true;
}
// ************ PROTECTED ************ // ************ PROTECTED ************
bool CGameExporter::ExtractDiscData() bool CGameExporter::ExtractDiscData()
{ {
@ -122,7 +188,7 @@ bool CGameExporter::ExtractDiscData()
TString FilesDir = AbsDiscDir + "files/"; TString FilesDir = AbsDiscDir + "files/";
FileUtil::MakeDirectory(FilesDir); FileUtil::MakeDirectory(FilesDir);
bool Success = ExtractDiscNodeRecursive(&pDataPartition->getFSTRoot(), FilesDir, Context); bool Success = ExtractDiscNodeRecursive(&pDataPartition->getFSTRoot(), FilesDir, true, Context);
if (!Success) return false; if (!Success) return false;
if (!mpProgress->ShouldCancel()) if (!mpProgress->ShouldCancel())
@ -150,18 +216,25 @@ bool CGameExporter::ExtractDiscData()
return false; return false;
} }
bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, const nod::ExtractionContext& rkContext) bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, bool RootNode, const nod::ExtractionContext& rkContext)
{ {
for (nod::Node::DirectoryIterator Iter = pkNode->begin(); Iter != pkNode->end(); ++Iter) for (nod::Node::DirectoryIterator Iter = pkNode->begin(); Iter != pkNode->end(); ++Iter)
{ {
if (!ShouldExportDiscNode(&*Iter, RootNode))
continue;
if (Iter->getKind() == nod::Node::Kind::File) if (Iter->getKind() == nod::Node::Kind::File)
{ {
TString FilePath = rkDir + Iter->getName(); TString FilePath = rkDir + Iter->getName();
bool Success = Iter->extractToDirectory(*rkDir.ToUTF16(), rkContext); bool Success = Iter->extractToDirectory(*rkDir.ToUTF16(), rkContext);
if (!Success) return false; if (!Success) return false;
if (FilePath.GetFileExtension() == "pak") if (FilePath.GetFileExtension().CaseInsensitiveCompare("pak"))
mPaks.push_back(FilePath); {
// For multi-game Wii discs, don't track packages for frontend unless we're exporting frontend
if (mDiscType == eDT_Normal || mFrontEnd || pkNode->getName() != "fe")
mPaks.push_back(FilePath);
}
} }
else else
@ -170,7 +243,7 @@ bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TStr
bool Success = FileUtil::MakeDirectory(Subdir); bool Success = FileUtil::MakeDirectory(Subdir);
if (!Success) return false; if (!Success) return false;
Success = ExtractDiscNodeRecursive(&*Iter, Subdir, rkContext); Success = ExtractDiscNodeRecursive(&*Iter, Subdir, false, rkContext);
if (!Success) return false; if (!Success) return false;
} }
} }

View File

@ -12,6 +12,13 @@
#include <map> #include <map>
#include <nod/nod.hpp> #include <nod/nod.hpp>
enum EDiscType
{
eDT_Normal,
eDT_WiiDeAsobu,
eDT_Trilogy
};
class CGameExporter class CGameExporter
{ {
// Project Data // Project Data
@ -33,6 +40,8 @@ class CGameExporter
// Files // Files
nod::DiscBase *mpDisc; nod::DiscBase *mpDisc;
EDiscType mDiscType;
bool mFrontEnd;
// Resources // Resources
TStringList mPaks; TStringList mPaks;
@ -65,15 +74,16 @@ class CGameExporter
}; };
public: public:
CGameExporter(EGame Game, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion); CGameExporter(EDiscType DiscType, EGame Game, bool FrontEnd, ERegion Region, const TString& rkGameName, const TString& rkGameID, float BuildVersion);
bool Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAssetNameMap *pNameMap, CGameInfo *pGameInfo, IProgressNotifier *pProgress); bool Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAssetNameMap *pNameMap, CGameInfo *pGameInfo, IProgressNotifier *pProgress);
void LoadResource(const CAssetID& rkID, std::vector<u8>& rBuffer); void LoadResource(const CAssetID& rkID, std::vector<u8>& rBuffer);
bool ShouldExportDiscNode(const nod::Node *pkNode, bool IsInRoot);
inline TString ProjectPath() const { return mProjectPath; } inline TString ProjectPath() const { return mProjectPath; }
protected: protected:
bool ExtractDiscData(); bool ExtractDiscData();
bool ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, const nod::ExtractionContext& rkContext); bool ExtractDiscNodeRecursive(const nod::Node *pkNode, const TString& rkDir, bool RootNode, const nod::ExtractionContext& rkContext);
void LoadPaks(); void LoadPaks();
void LoadResource(const SResourceInstance& rkResource, std::vector<u8>& rBuffer); void LoadResource(const SResourceInstance& rkResource, std::vector<u8>& rBuffer);
void ExportCookedResources(); void ExportCookedResources();

View File

@ -100,6 +100,7 @@ public:
inline float BuildVersion() const { return mBuildVersion; } inline float BuildVersion() const { return mBuildVersion; }
inline bool IsWiiBuild() const { return mBuildVersion >= 3.f; } inline bool IsWiiBuild() const { return mBuildVersion >= 3.f; }
inline bool IsTrilogy() const { return mGame <= eCorruption && mBuildVersion >= 3.593f; } inline bool IsTrilogy() const { return mGame <= eCorruption && mBuildVersion >= 3.593f; }
inline bool IsWiiDeAsobu() const { return mGame < eCorruption && mBuildVersion >= 3.f && mBuildVersion < 3.593f; }
}; };
#endif // CGAMEPROJECT_H #endif // CGAMEPROJECT_H

View File

@ -170,9 +170,14 @@ bool CVirtualDirectory::AddChild(const TString &rkPath, CResourceEntry *pEntry)
{ {
// Create new subdirectory // Create new subdirectory
pSubdir = new CVirtualDirectory(this, DirName, mpStore); pSubdir = new CVirtualDirectory(this, DirName, mpStore);
FileUtil::MakeDirectory(mpStore->ResourcesDir() + pSubdir->FullPath());
mSubdirectories.push_back(pSubdir);
if (!pSubdir->CreateFilesystemDirectory())
{
delete pSubdir;
return false;
}
mSubdirectories.push_back(pSubdir);
std::sort(mSubdirectories.begin(), mSubdirectories.end(), [](CVirtualDirectory *pLeft, CVirtualDirectory *pRight) -> bool { std::sort(mSubdirectories.begin(), mSubdirectories.end(), [](CVirtualDirectory *pLeft, CVirtualDirectory *pRight) -> bool {
return (pLeft->Name().ToUpper() < pRight->Name().ToUpper()); return (pLeft->Name().ToUpper() < pRight->Name().ToUpper());
}); });
@ -184,6 +189,13 @@ bool CVirtualDirectory::AddChild(const TString &rkPath, CResourceEntry *pEntry)
for (auto Iter = Components.begin(); Iter != Components.end(); Iter++) for (auto Iter = Components.begin(); Iter != Components.end(); Iter++)
{ {
pSubdir = new CVirtualDirectory(pSubdir, *Iter, mpStore); pSubdir = new CVirtualDirectory(pSubdir, *Iter, mpStore);
if (!pSubdir->CreateFilesystemDirectory())
{
delete pSubdir;
return false;
}
pSubdir->Parent()->mSubdirectories.push_back(pSubdir); pSubdir->Parent()->mSubdirectories.push_back(pSubdir);
} }
@ -307,6 +319,23 @@ void CVirtualDirectory::DeleteEmptySubdirectories()
} }
} }
bool CVirtualDirectory::CreateFilesystemDirectory()
{
TString AbsPath = AbsolutePath();
if (!FileUtil::Exists(AbsPath))
{
bool CreateSuccess = FileUtil::MakeDirectory(AbsPath);
if (!CreateSuccess)
Log::Error("FAILED to create filesystem directory: " + AbsPath);
return CreateSuccess;
}
return true;
}
bool CVirtualDirectory::SetParent(CVirtualDirectory *pParent) bool CVirtualDirectory::SetParent(CVirtualDirectory *pParent)
{ {
ASSERT(!pParent->IsDescendantOf(this)); ASSERT(!pParent->IsDescendantOf(this));

View File

@ -39,6 +39,7 @@ public:
bool Rename(const TString& rkNewName); bool Rename(const TString& rkNewName);
bool Delete(); bool Delete();
void DeleteEmptySubdirectories(); void DeleteEmptySubdirectories();
bool CreateFilesystemDirectory();
bool SetParent(CVirtualDirectory *pParent); bool SetParent(CVirtualDirectory *pParent);
static bool IsValidDirectoryName(const TString& rkName); static bool IsValidDirectoryName(const TString& rkName);

View File

@ -21,9 +21,13 @@
CExportGameDialog::CExportGameDialog(const QString& rkIsoPath, const QString& rkExportDir, QWidget *pParent /*= 0*/) CExportGameDialog::CExportGameDialog(const QString& rkIsoPath, const QString& rkExportDir, QWidget *pParent /*= 0*/)
: QDialog(pParent) : QDialog(pParent)
, mpUI(new Ui::CExportGameDialog) , mpUI(new Ui::CExportGameDialog)
, mpDisc(nullptr)
, mpExporter(nullptr)
, mDiscType(eDT_Normal)
, mGame(eUnknownGame) , mGame(eUnknownGame)
, mRegion(eRegion_Unknown) , mRegion(eRegion_Unknown)
, mTrilogy(false) , mBuildVer(0.f)
, mWiiFrontend(false)
, mExportSuccess(false) , mExportSuccess(false)
{ {
mpUI->setupUi(this); mpUI->setupUi(this);
@ -35,25 +39,19 @@ CExportGameDialog::CExportGameDialog(const QString& rkIsoPath, const QString& rk
if (ValidateGame()) if (ValidateGame())
{ {
mBuildVer = FindBuildVersion(); mBuildVer = FindBuildVersion();
mpExporter = new CGameExporter(mDiscType, mGame, mWiiFrontend, mRegion, mGameTitle, mGameID, mBuildVer);
InitUI(rkExportDir); InitUI(rkExportDir);
TString IsoName = TO_TSTRING(rkIsoPath).GetFileName(); TString IsoName = TO_TSTRING(rkIsoPath).GetFileName();
setWindowTitle(QString("Export Settings - %1").arg( TO_QSTRING(IsoName) )); setWindowTitle(QString("Export Settings - %1").arg( TO_QSTRING(IsoName) ));
} }
else
{
if (!mTrilogy)
UICommon::ErrorMsg(this, "Invalid ISO!");
delete mpDisc;
mpDisc = nullptr;
}
} }
CExportGameDialog::~CExportGameDialog() CExportGameDialog::~CExportGameDialog()
{ {
delete mpUI; delete mpUI;
delete mpDisc; delete mpDisc;
delete mpExporter;
} }
void RecursiveAddToTree(const nod::Node *pkNode, QTreeWidgetItem *pParent); void RecursiveAddToTree(const nod::Node *pkNode, QTreeWidgetItem *pParent);
@ -89,13 +87,12 @@ void CExportGameDialog::InitUI(QString ExportDir)
nod::Partition *pPartition = mpDisc->getDataPartition(); nod::Partition *pPartition = mpDisc->getDataPartition();
ASSERT(pPartition); ASSERT(pPartition);
const nod::Node *pkDiscRoot = &pPartition->getFSTRoot();
if (mTrilogy)
pkDiscRoot = &*pkDiscRoot->find( GetGameShortName(mGame).ToStdString() );
QTreeWidgetItem *pTreeRoot = new QTreeWidgetItem((QTreeWidgetItem*) nullptr, QStringList(QString("Disc"))); QTreeWidgetItem *pTreeRoot = new QTreeWidgetItem((QTreeWidgetItem*) nullptr, QStringList(QString("Disc")));
mpUI->DiscFstTreeWidget->addTopLevelItem(pTreeRoot); mpUI->DiscFstTreeWidget->addTopLevelItem(pTreeRoot);
const nod::Node *pkDiscRoot = &pPartition->getFSTRoot();
RecursiveAddToTree(pkDiscRoot, pTreeRoot); RecursiveAddToTree(pkDiscRoot, pTreeRoot);
pTreeRoot->setIcon(0, QIcon(":/icons/Disc_16px.png")); pTreeRoot->setIcon(0, QIcon(":/icons/Disc_16px.png"));
pTreeRoot->setExpanded(true); pTreeRoot->setExpanded(true);
@ -175,14 +172,28 @@ bool CExportGameDialog::ValidateGame()
case FOURCC('R3MX'): case FOURCC('R3MX'):
// Trilogy // Trilogy
mTrilogy = true; mDiscType = eDT_Trilogy;
if (!RequestTrilogyGame()) return false; if (!RequestWiiPortGame()) return false;
// Force change game name so it isn't "Metroid Prime Trilogy"
if (!mWiiFrontend)
mGameTitle = GetGameName(mGame);
break; break;
case FOURCC('R3IX'): case FOURCC('R3IX'):
// MP1 Wii de Asobu // MP1 Wii de Asobu
mGame = ePrime;
mDiscType = eDT_WiiDeAsobu;
if (!RequestWiiPortGame()) return false;
break;
case FOURCC('R32X'): case FOURCC('R32X'):
// MP2 Wii de Asobu mGame = eEchoes;
mDiscType = eDT_WiiDeAsobu;
if (!RequestWiiPortGame()) return false;
break;
default: default:
// Unrecognized game ID // Unrecognized game ID
return false; return false;
@ -191,16 +202,25 @@ bool CExportGameDialog::ValidateGame()
return true; return true;
} }
bool CExportGameDialog::RequestTrilogyGame() bool CExportGameDialog::RequestWiiPortGame()
{ {
QDialog Dialog; QDialog Dialog;
Dialog.setWindowTitle("Select Trilogy Game"); Dialog.setWindowTitle("Select Game");
bool IsTrilogy = (mGame == eUnknownGame);
bool HasMP1 = (IsTrilogy || mGame == ePrime);
bool HasMP2 = (IsTrilogy || mGame == eEchoes);
bool HasMP3 = IsTrilogy;
QString GameName = (IsTrilogy ? "Metroid Prime: Trilogy" : "Wii de Asobu");
QString LabelText = QString("You have selected a %1 ISO. Please pick a game to export:").arg(GameName);
QLabel Label(LabelText, &Dialog);
QLabel Label("You have selected a Metroid Prime: Trilogy ISO. Please pick a game to export:", &Dialog);
QComboBox ComboBox(&Dialog); QComboBox ComboBox(&Dialog);
ComboBox.addItem("Metroid Prime"); ComboBox.addItem("Front End");
ComboBox.addItem("Metroid Prime 2: Echoes"); if (HasMP1) ComboBox.addItem("Metroid Prime");
ComboBox.addItem("Metroid Prime 3: Corruption"); if (HasMP2) ComboBox.addItem("Metroid Prime 2: Echoes");
if (HasMP3) ComboBox.addItem("Metroid Prime 3: Corruption");
QDialogButtonBox ButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &Dialog); QDialogButtonBox ButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &Dialog);
connect(&ButtonBox, SIGNAL(accepted()), &Dialog, SLOT(accept())); connect(&ButtonBox, SIGNAL(accepted()), &Dialog, SLOT(accept()));
connect(&ButtonBox, SIGNAL(rejected()), &Dialog, SLOT(reject())); connect(&ButtonBox, SIGNAL(rejected()), &Dialog, SLOT(reject()));
@ -217,10 +237,24 @@ bool CExportGameDialog::RequestTrilogyGame()
{ {
switch (ComboBox.currentIndex()) switch (ComboBox.currentIndex())
{ {
case 0: mGame = ePrime; break; case 0:
case 1: mGame = eEchoes; break; mGame = eCorruption;
case 2: mGame = eCorruption; break; mWiiFrontend = true;
break;
case 1:
mGame = (HasMP1 ? ePrime : eEchoes);
break;
case 2:
mGame = eEchoes;
break;
case 3:
mGame = eCorruption;
break;
} }
return true; return true;
} }
else return false; else return false;
@ -263,7 +297,7 @@ float CExportGameDialog::FindBuildVersion()
return 0.f; return 0.f;
} }
void RecursiveAddToTree(const nod::Node *pkNode, QTreeWidgetItem *pParent) void CExportGameDialog::RecursiveAddToTree(const nod::Node *pkNode, QTreeWidgetItem *pParent)
{ {
// Get sorted list of nodes // Get sorted list of nodes
std::list<const nod::Node*> NodeList; std::list<const nod::Node*> NodeList;
@ -285,6 +319,10 @@ void RecursiveAddToTree(const nod::Node *pkNode, QTreeWidgetItem *pParent)
for (auto Iter = NodeList.begin(); Iter != NodeList.end(); Iter++) for (auto Iter = NodeList.begin(); Iter != NodeList.end(); Iter++)
{ {
const nod::Node *pkNode = *Iter; const nod::Node *pkNode = *Iter;
if (!mpExporter->ShouldExportDiscNode(pkNode, pParent->parent() == nullptr))
continue;
bool IsDir = pkNode->getKind() == nod::Node::Kind::Directory; bool IsDir = pkNode->getKind() == nod::Node::Kind::Directory;
QTreeWidgetItem *pItem = new QTreeWidgetItem(pParent, QStringList(QString::fromStdString(pkNode->getName())) ); QTreeWidgetItem *pItem = new QTreeWidgetItem(pParent, QStringList(QString::fromStdString(pkNode->getName())) );
@ -382,12 +420,11 @@ void CExportGameDialog::Export()
// Do export // Do export
close(); close();
CGameExporter Exporter(mGame, mRegion, mGameTitle, mGameID, mBuildVer);
TString StrExportDir = TO_TSTRING(ExportDir); TString StrExportDir = TO_TSTRING(ExportDir);
StrExportDir.EnsureEndsWith('/'); StrExportDir.EnsureEndsWith('/');
CProgressDialog Dialog("Creating new game project", false, true, parentWidget()); CProgressDialog Dialog("Creating new game project", false, true, parentWidget());
QFuture<bool> Future = QtConcurrent::run(&Exporter, &CGameExporter::Export, mpDisc, StrExportDir, &NameMap, &GameInfo, &Dialog); QFuture<bool> Future = QtConcurrent::run(mpExporter, &CGameExporter::Export, mpDisc, StrExportDir, &NameMap, &GameInfo, &Dialog);
mExportSuccess = Dialog.WaitForResults(Future); mExportSuccess = Dialog.WaitForResults(Future);
if (!mExportSuccess) if (!mExportSuccess)
@ -396,5 +433,5 @@ void CExportGameDialog::Export()
UICommon::ErrorMsg(this, "Export failed!"); UICommon::ErrorMsg(this, "Export failed!");
} }
else else
mNewProjectPath = TO_QSTRING(Exporter.ProjectPath()); mNewProjectPath = TO_QSTRING(mpExporter->ProjectPath());
} }

View File

@ -2,6 +2,7 @@
#define CEXPORTGAMEDIALOG_H #define CEXPORTGAMEDIALOG_H
#include <Common/EGame.h> #include <Common/EGame.h>
#include <Core/GameProject/CGameExporter.h>
#include <Core/GameProject/CGameProject.h> #include <Core/GameProject/CGameProject.h>
#include <QDialog> #include <QDialog>
#include <QString> #include <QString>
@ -17,13 +18,17 @@ class CExportGameDialog : public QDialog
Ui::CExportGameDialog *mpUI; Ui::CExportGameDialog *mpUI;
nod::DiscBase *mpDisc; nod::DiscBase *mpDisc;
CGameExporter *mpExporter;
TString mGameTitle; TString mGameTitle;
TString mGameID; TString mGameID;
// Build Info
EDiscType mDiscType;
EGame mGame; EGame mGame;
ERegion mRegion; ERegion mRegion;
float mBuildVer; float mBuildVer;
bool mTrilogy; bool mWiiFrontend;
bool mExportSuccess; bool mExportSuccess;
QString mNewProjectPath; QString mNewProjectPath;
@ -34,9 +39,12 @@ public:
void InitUI(QString ExportDir); void InitUI(QString ExportDir);
bool ValidateGame(); bool ValidateGame();
bool RequestTrilogyGame(); bool RequestWiiPortGame();
float FindBuildVersion(); float FindBuildVersion();
// Disc Tree
void RecursiveAddToTree(const nod::Node *pkNode, class QTreeWidgetItem *pParent);
// Accessors // Accessors
inline bool HasValidDisc() const { return mpDisc != nullptr; } inline bool HasValidDisc() const { return mpDisc != nullptr; }
inline bool ExportSucceeded() const { return mExportSuccess; } inline bool ExportSucceeded() const { return mExportSuccess; }

View File

@ -18,15 +18,19 @@ CProgressDialog::CProgressDialog(QString OperationName, bool UseBusyIndicator, b
#if WIN32 #if WIN32
QWinTaskbarButton *pButton = new QWinTaskbarButton(this); QWinTaskbarButton *pButton = new QWinTaskbarButton(this);
QWindow *pWindow = parentWidget()->windowHandle(); QWindow *pWindow = UICommon::FindWidgetWindowHandle( parentWidget() );
ASSERT(pWindow);
pButton->setWindow(pWindow);
mpTaskbarProgress = pButton->progress();
mpTaskbarProgress->setMinimum(0);
mpTaskbarProgress->setMaximum(UseBusyIndicator ? 0 : 10000);
mpTaskbarProgress->show();
if (pWindow)
{
pButton->setWindow(pWindow);
mpTaskbarProgress = pButton->progress();
mpTaskbarProgress->setMinimum(0);
mpTaskbarProgress->setMaximum(UseBusyIndicator ? 0 : 10000);
mpTaskbarProgress->show();
}
else
mpTaskbarProgress = nullptr;
setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
#endif #endif
@ -60,8 +64,11 @@ void CProgressDialog::closeEvent(QCloseEvent *pEvent)
pEvent->accept(); pEvent->accept();
#if WIN32 #if WIN32
mpTaskbarProgress->reset(); if (mpTaskbarProgress)
mpTaskbarProgress->hide(); {
mpTaskbarProgress->reset();
mpTaskbarProgress->hide();
}
#endif #endif
} }
} }
@ -102,7 +109,8 @@ void CProgressDialog::UpdateUI(const QString& rkTaskDesc, const QString& rkStepD
mpUI->ProgressBar->setValue(ProgressValue); mpUI->ProgressBar->setValue(ProgressValue);
#if WIN32 #if WIN32
mpTaskbarProgress->setValue(ProgressValue); if (mpTaskbarProgress)
mpTaskbarProgress->setValue(ProgressValue);
#endif #endif
} }
} }

View File

@ -107,7 +107,7 @@ public:
for (u32 Shift = 0; Shift <= MaxShift; Shift += 4) for (u32 Shift = 0; Shift <= MaxShift; Shift += 4)
{ {
u64 ShiftCompare = mCompareID << Shift; u64 ShiftCompare = mCompareID << Shift;
u32 Mask = mCompareMask << Shift; u64 Mask = mCompareMask << Shift;
if ((ID & Mask) == ShiftCompare) if ((ID & Mask) == ShiftCompare)
{ {

View File

@ -5,6 +5,14 @@
namespace UICommon namespace UICommon
{ {
QWindow* FindWidgetWindowHandle(QWidget *pWidget)
{
while (pWidget && !pWidget->windowHandle())
pWidget = pWidget->parentWidget();
return pWidget ? pWidget->windowHandle() : nullptr;
}
void OpenContainingFolder(const QString& rkPath) void OpenContainingFolder(const QString& rkPath)
{ {
#if WIN32 #if WIN32

View File

@ -40,6 +40,7 @@ namespace UICommon
{ {
// Utility // Utility
QWindow* FindWidgetWindowHandle(QWidget *pWidget);
void OpenContainingFolder(const QString& rkPath); void OpenContainingFolder(const QString& rkPath);
bool OpenInExternalApplication(const QString& rkPath); bool OpenInExternalApplication(const QString& rkPath);