Browse Source

Port plResBrowser to Qt5

Michael Hansen 10 years ago
parent
commit
42661cc247
  1. 85
      Sources/Tools/plResBrowser/CMakeLists.txt
  2. 418
      Sources/Tools/plResBrowser/plResBrowser.cpp
  3. 76
      Sources/Tools/plResBrowser/plResBrowser.h
  4. 432
      Sources/Tools/plResBrowser/plResBrowserWndProc.cpp
  5. 497
      Sources/Tools/plResBrowser/plResTreeView.cpp
  6. 51
      Sources/Tools/plResBrowser/plResTreeView.h
  7. 73
      Sources/Tools/plResBrowser/plWinRegistryTools.cpp
  8. 21
      Sources/Tools/plResBrowser/plWinRegistryTools.h
  9. 76
      Sources/Tools/plResBrowser/res/FindDialog.ui
  10. 591
      Sources/Tools/plResBrowser/res/ResBrowser.ui
  11. 5
      Sources/Tools/plResBrowser/res/plResBrowser.qrc
  12. 203
      Sources/Tools/plResBrowser/res/plResBrowser.rc
  13. 68
      Sources/Tools/plResBrowser/res/resource.h

85
Sources/Tools/plResBrowser/CMakeLists.txt

@ -8,64 +8,55 @@ include_directories("../../Plasma/PubUtilLib/inc")
include_directories("../../Plasma/PubUtilLib")
set(plResBrowser_HEADERS
plResTreeView.h
plWinRegistryTools.h
plResBrowser.h
plResTreeView.h
)
qt5_wrap_cpp(plResBrowser_MOC ${plResBrowser_HEADERS})
set(plResBrowser_SOURCES
plResBrowser.cpp
plResBrowserWndProc.cpp
plResTreeView.cpp
plWinRegistryTools.cpp
)
set(plResBrowser_RESOURCES
res/plResBrowser.rc
res/resource.h
plResBrowser.cpp
plResTreeView.cpp
)
if(WIN32)
set(plResBrowser_HEADERS ${plResBrowser_HEADERS}
plWinRegistryTools.h
)
set(plResBrowser_SOURCES ${plResBrowser_SOURCES}
res/plResBrowser.rc
plWinRegistryTools.cpp
)
endif()
set(plResBrowser_RCC_SOURCES
res/plResBrowser.qrc
)
qt5_add_resources(plResBrowser_RCC ${plResBrowser_RCC_SOURCES})
set(plResBrowser_UIC_SOURCES
res/FindDialog.ui
res/ResBrowser.ui
)
qt5_wrap_ui(plResBrowser_UIC ${plResBrowser_UIC_SOURCES})
res/dataicon.ico
res/icon1.ico
res/icon2.ico
res/indexico.ico
res/mergedda.ico
res/mergedin.ico
)
add_executable(plResBrowser WIN32 ${plResBrowser_SOURCES} ${plResBrowser_HEADERS} ${plResBrowser_RESOURCES})
# For generated ui_*.h files
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(plResBrowser WIN32 ${plResBrowser_SOURCES} ${plResBrowser_HEADERS}
${plResBrowser_RCC} ${plResBrowser_UIC} ${plResBrowser_MOC})
target_link_libraries(plResBrowser CoreLib)
target_link_libraries(plResBrowser plFile)
target_link_libraries(plResBrowser plMessage)
target_link_libraries(plResBrowser plResMgr)
target_link_libraries(plResBrowser plScene)
target_link_libraries(plResBrowser plStatusLog)
target_link_libraries(plResBrowser plUnifiedTime)
target_link_libraries(plResBrowser pnDispatch)
target_link_libraries(plResBrowser pnFactory)
target_link_libraries(plResBrowser pnKeyedObject)
target_link_libraries(plResBrowser pnMessage)
target_link_libraries(plResBrowser pnNetCommon)
target_link_libraries(plResBrowser pnNucleusInc)
target_link_libraries(plResBrowser pnSceneObject)
target_link_libraries(plResBrowser pnTimer)
target_link_libraries(plResBrowser pnUtils)
target_link_libraries(plResBrowser pnUUID)
if (WIN32)
target_link_libraries(plResBrowser rpcrt4)
target_link_libraries(plResBrowser version)
target_link_libraries(plResBrowser vfw32)
target_link_libraries(plResBrowser ws2_32)
target_link_libraries(plResBrowser winmm)
target_link_libraries(plResBrowser strmiids)
target_link_libraries(plResBrowser comctl32)
target_link_libraries(plResBrowser shlwapi)
endif(WIN32)
target_link_libraries(plResBrowser Qt5::Widgets)
if(USE_VLD)
target_link_libraries(plResBrowser ${VLD_LIBRARY})
endif()
source_group("Source Files" FILES ${plResBrowser_SOURCES})
source_group("Source Files" FILES ${plResBrowser_SOURCES} ${plResBrowser_MOC})
source_group("Header Files" FILES ${plResBrowser_HEADERS})
source_group("Resource Files" FILES ${plResBrowser_RESOURCES})
source_group("Resource Files" FILES ${plResBrowser_RCC_SOURCES} ${plResBrowser_RCC}
${plResBrowser_UIC_SOURCES} ${plResBrowser_UIC})

418
Sources/Tools/plResBrowser/plResBrowser.cpp

@ -39,12 +39,13 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#define CLASSNAME "plResBrowser" // Used in WinInit()
#define WINDOWNAME "plResBrowser"
#include "HeadSpin.h"
#include "hsWindows.h"
#include "res/resource.h"
#include "plResBrowser.h"
#include "ui_ResBrowser.h"
#if HS_BUILD_FOR_WIN32
# include "plWinRegistryTools.h"
#endif
#include "pnAllCreatables.h"
#include "plResMgr/plResMgrCreatable.h"
@ -53,81 +54,374 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plMessage/plResMgrHelperMsg.h"
REGISTER_CREATABLE(plResMgrHelperMsg);
#include "plResMgr/plRegistryHelpers.h"
#include "plResMgr/plRegistryNode.h"
#include "plResMgr/plPageInfo.h"
#include "pnKeyedObject/plUoid.h"
#include "pnKeyedObject/plKey.h"
#include "pnKeyedObject/plKeyImp.h"
#include <QApplication>
#include <QDialog>
#include <QMessageBox>
#include <QFileDialog>
#include <QDragEnterEvent>
#include <QMimeData>
#include <functional>
HINSTANCE gInstance;
char *gCommandLine = nil;
HWND gMainWindow = nil;
static void IAboutDialog(QWidget *parent)
{
QDialog dlg(parent);
QLabel *image = new QLabel(&dlg);
image->setPixmap(QPixmap(":/icon1.ico"));
QLabel *text = new QLabel(QObject::tr(R"(plResBrowser
A simple Plasma 2.0 packfile browsing utility
Copyright (C) 2002 Cyan Worlds, Inc.
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
BOOL WinInit( HINSTANCE hInst, int nCmdShow );
Who needs log files?)"), &dlg);
QPushButton *ok = new QPushButton(QObject::tr("OK"), &dlg);
ok->setDefault(true);
QHBoxLayout *layout = new QHBoxLayout(&dlg);
layout->setMargin(8);
layout->setSpacing(10);
layout->addWidget(image);
layout->addWidget(text);
layout->addWidget(ok);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
dlg.connect(ok, &QPushButton::clicked, &dlg, &QDialog::accept);
dlg.exec();
}
plResBrowser::plResBrowser()
: QMainWindow()
{
MSG msg;
HACCEL accelTable = LoadAccelerators( hInstance, MAKEINTRESOURCE( IDR_ACCELERATOR1 ) );
fUI = new Ui_ResBrowser;
fUI->setupUi(this);
setAcceptDrops(true);
plResMgrSettings::Get().SetFilterNewerPageVersions( false );
plResMgrSettings::Get().SetFilterOlderPageVersions( false );
// Use window background color for read-only text fields
// Note that we don't set them disabled, so you can still copy their contents
QPalette pal = fUI->fAgeName->palette();
pal.setColor(QPalette::Text, fUI->label->palette().color(QPalette::Text));
pal.setColor(QPalette::Base, fUI->label->palette().color(QPalette::Window));
fUI->fAgeName->setPalette(pal);
fUI->fPageName->setPalette(pal);
fUI->fLocation->setPalette(pal);
fUI->fDataVersion->setPalette(pal);
fUI->fChecksum->setPalette(pal);
fUI->fChecksumType->setPalette(pal);
fUI->fObjectName->setPalette(pal);
fUI->fObjectClass->setPalette(pal);
fUI->fStartPos->setPalette(pal);
fUI->fObjectSize->setPalette(pal);
gCommandLine = (char *)lpCmdLine;
plResManager *rMgr = new plResManager;
hsgResMgr::Init( rMgr );
connect(fUI->fOpenAction, SIGNAL(triggered()), SLOT(OpenFile()));
connect(fUI->fOpenDirectoryAction, SIGNAL(triggered()), SLOT(OpenDirectory()));
connect(fUI->fSaveSelectedAction, SIGNAL(triggered()), SLOT(SaveSelectedObject()));
connect(fUI->fFindAction, SIGNAL(triggered()), fUI->fTreeView, SLOT(FindObject()));
connect(fUI->fFindNextAction, SIGNAL(triggered()), fUI->fTreeView, SLOT(FindNextObject()));
connect(fUI->fShowOnlyLoadableAction, SIGNAL(triggered()), SLOT(RefreshTree()));
connect(fUI->fExitAction, SIGNAL(triggered()), SLOT(close()));
connect(fUI->fAboutAction, &QAction::triggered, std::bind(&IAboutDialog, this));
connect(fUI->fTreeView, &QTreeWidget::currentItemChanged,
std::bind(&plResBrowser::UpdateInfoPage, this));
connect(fUI->fHexValues, SIGNAL(clicked()), SLOT(UpdateInfoPage()));
connect(fUI->fFindButton, SIGNAL(clicked()), fUI->fTreeView, SLOT(FindObject()));
connect(fUI->fFindNextButton, SIGNAL(clicked()), fUI->fTreeView, SLOT(FindNextObject()));
connect(fUI->fSaveButton, SIGNAL(clicked()), SLOT(SaveSelectedObject()));
RegisterFileTypes();
plResMgrSettings::Get().SetLoadPagesOnInit(false);
QStringList args = qApp->arguments();
if (args.size() > 1)
{
plFileName path = args[1].toUtf8().constData();
if (path.GetFileExt() == "prp")
LoadPrpFile(args[1]);
}
}
plResBrowser::~plResBrowser()
{
delete fUI;
}
void plResBrowser::SetWindowTitle(const QString &title)
{
setWindowTitle(QString("plResBrowser%1").arg(title.isEmpty() ? "" : " - " + title));
}
void plResBrowser::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls())
event->acceptProposedAction();
}
void plResBrowser::dropEvent(QDropEvent *event)
{
QList<QUrl> urls = event->mimeData()->urls();
if (urls.size() == 0)
return;
fUI->fTreeView->clear();
hsgResMgr::Reset();
plResManager *mgr = static_cast<plResManager *>(hsgResMgr::ResMgr());
QString path = urls[0].toLocalFile();
if (urls.size() == 1 && urls[0].isLocalFile() && path.lastIndexOf('.') == -1)
{
// Must be a directory
std::vector<plFileName> prpFiles = plFileSystem::ListDir(path.toUtf8().constData(), "*.prp");
for (auto iter = prpFiles.begin(); iter != prpFiles.end(); ++iter)
mgr->AddSinglePage(*iter);
}
else
{
for (const QUrl &url : urls)
{
if (!url.isLocalFile())
continue;
plFileName fileName = url.toLocalFile().toUtf8().constData();
if (fileName.GetFileExt() == "prp")
{
mgr->AddSinglePage(fileName);
path = fileName.StripFileName().AsString().c_str();
}
}
}
fUI->fTreeView->LoadFromRegistry(fUI->fShowOnlyLoadableAction->isChecked());
SetWindowTitle(path);
}
void plResBrowser::OpenFile()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to browse"),
QString(), "Plasma 2 Pack Files (*.prp);;All files (*.*)");
if( !WinInit( hInstance, nCmdShow ) )
return -1;
if (!fileName.isEmpty())
LoadPrpFile(fileName);
}
while( GetMessage( &msg, NULL, 0, 0 ) )
void plResBrowser::OpenDirectory()
{
QString path = QFileDialog::getExistingDirectory(this,
tr("Select a Plasma 2 Data Directory:"),
QDir::current().absolutePath(),
QFileDialog::ShowDirsOnly | QFileDialog::ReadOnly);
if (!path.isEmpty())
LoadResourcePath(path);
}
void plResBrowser::SaveSelectedObject()
{
plResTreeViewItem *item = static_cast<plResTreeViewItem *>(fUI->fTreeView->currentItem());
plKey itemKey = item ? item->GetKey() : nullptr;
if (!itemKey)
return;
QString fileName = QFileDialog::getSaveFileName(this, tr("Export object"),
QString("%1.bin").arg(itemKey->GetName().c_str()),
"Binary Files (*.bin);;All files (*.*)");
if (!fileName.isEmpty())
{
if( !TranslateAccelerator( gMainWindow, accelTable, &msg ) )
plKeyImp *keyImp = static_cast<plKeyImp *>(itemKey);
if (keyImp->GetDataLen() <= 0)
return;
plResManager *resMgr = static_cast<plResManager *>(hsgResMgr::ResMgr());
plRegistryPageNode *pageNode = resMgr->FindPage(keyImp->GetUoid().GetLocation());
hsStream *stream = pageNode->OpenStream();
if (!stream)
return;
uint8_t *buffer = new uint8_t[keyImp->GetDataLen()];
if (buffer)
{
TranslateMessage( &msg );
DispatchMessage( &msg );
stream->SetPosition(keyImp->GetStartPos());
stream->Read(keyImp->GetDataLen(), buffer);
}
if (!buffer)
return;
hsUNIXStream outStream;
outStream.Open(fileName.toUtf8().constData(), "wb");
outStream.Write(keyImp->GetDataLen(), buffer);
outStream.Close();
delete[] buffer;
}
}
hsgResMgr::Shutdown();
void plResBrowser::RefreshTree()
{
fUI->fTreeView->clear();
fUI->fTreeView->LoadFromRegistry(fUI->fShowOnlyLoadableAction->isChecked());
}
void plResBrowser::UpdateInfoPage()
{
const bool showAsHex = fUI->fHexValues->isChecked();
fUI->fObjectName->setText("");
fUI->fObjectClass->setText("");
fUI->fObjectSize->setText("");
fUI->fStartPos->setText("");
fUI->fSaveSelectedAction->setEnabled(false);
fUI->fSaveButton->setEnabled(false);
plResTreeViewItem *item = static_cast<plResTreeViewItem *>(fUI->fTreeView->currentItem());
if (item)
{
if (item->GetPage())
{
const plPageInfo &pageInfo = item->GetPage()->GetPageInfo();
fUI->fAgeName->setText(pageInfo.GetAge().c_str());
fUI->fPageName->setText(pageInfo.GetPage().c_str());
fUI->fLocation->setText(pageInfo.GetLocation().StringIze().c_str());
fUI->fReserved->setChecked((pageInfo.GetLocation().GetFlags() & plLocation::kReserved) != 0);
fUI->fBuiltIn->setChecked((pageInfo.GetLocation().GetFlags() & plLocation::kBuiltIn) != 0);
fUI->fVolatile->setChecked((pageInfo.GetLocation().GetFlags() & plLocation::kVolatile) != 0);
fUI->fLocalOnly->setChecked((pageInfo.GetLocation().GetFlags() & plLocation::kLocalOnly) != 0);
fUI->fDataVersion->setText(QString::number(pageInfo.GetMajorVersion()));
if (showAsHex)
fUI->fChecksum->setText(QString("0x%1").arg(pageInfo.GetChecksum(), 0, 16));
else
fUI->fChecksum->setText(QString::number(pageInfo.GetChecksum()));
fUI->fChecksumType->setText("Basic (file size)");
}
if (item->GetKey())
{
plKey key = item->GetKey();
fUI->fObjectName->setText(key->GetUoid().GetObjectName().c_str());
const char *cname = plFactory::GetNameOfClass(key->GetUoid().GetClassType());
fUI->fObjectClass->setText(QString("%1 (%2)").arg(cname ? cname : "<unknown>")
.arg(key->GetUoid().GetClassType()));
plKeyImp *imp = static_cast<plKeyImp *>(key);
if (showAsHex)
fUI->fStartPos->setText(QString("0x%1").arg(imp->GetStartPos(), 0, 16));
else
fUI->fStartPos->setText(QString::number(imp->GetStartPos()));
if (imp->GetDataLen() < 1024)
fUI->fObjectSize->setText(QString("%1 bytes").arg(imp->GetDataLen()));
else if (imp->GetDataLen() < 1024 * 1024)
fUI->fObjectSize->setText(QString("%1 kB").arg(imp->GetDataLen() / 1024.f, 0, 'f', 2));
else
fUI->fObjectSize->setText(QString("%1 MB").arg(imp->GetDataLen() / 1024.f / 1024.f, 0, 'f', 2));
fUI->fSaveSelectedAction->setEnabled(true);
fUI->fSaveButton->setEnabled(true);
}
}
}
void plResBrowser::RegisterFileTypes()
{
// Only meaningful on Windows currently... For Linux, consider creating
// a .desktop file as part of the make install process
#if HS_BUILD_FOR_WIN32
static bool sFileTypesRegistered = false;
if (sFileTypesRegistered)
return;
// Make sure our file types are created
QString path = QCoreApplication::applicationFilePath();
//plWinRegistryTools::AssociateFileType("PlasmaIdxFile", "Plasma 2 Index File", path, 1);
//plWinRegistryTools::AssociateFileType("PlasmaDatFile", "Plasma 2 Data File", path, 2);
//plWinRegistryTools::AssociateFileType("PlasmaPatchFile", "Plasma 2 Patch File", path, 3);
plWinRegistryTools::AssociateFileType("PlasmaPackFile", "Plasma 2 Packfile", path, 4);
return 0;
// Check our file extensions
QString prpAssoc = plWinRegistryTools::GetCurrentFileExtensionAssociation(".prp");
if (prpAssoc != "PlasmaPackFile")
{
int retn = QMessageBox::question(this, tr("plResBrowser File Type Association"),
tr("The Plasma 2 packed data file extension .prp is not currently associated "
"with plResBrowser. Would you like to associate it now?"));
if (retn == QMessageBox::Yes)
{
// Associate 'em
plWinRegistryTools::AssociateFileExtension(".prp", "PlasmaPackFile");
}
}
sFileTypesRegistered = true;
#endif
}
BOOL WinInit(HINSTANCE hInst, int nCmdShow)
void plResBrowser::LoadPrpFile(const QString &fileName)
{
gInstance = hInst;
// Fill out WNDCLASS info
WNDCLASS wndClass;
wndClass.style = 0; // CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInst;
wndClass.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_APPICON ) );
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetSysColorBrush( COLOR_3DFACE );
wndClass.lpszMenuName = MAKEINTRESOURCE( IDR_APPMENU );
wndClass.lpszClassName = CLASSNAME;
// can only run one at a time anyway, so just quit if another is running
if (!RegisterClass(&wndClass))
return FALSE;
DWORD dwStyle = WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
DWORD dwExStyle = WS_EX_ACCEPTFILES;
// Create a window
gMainWindow = CreateWindowEx(dwExStyle, CLASSNAME, WINDOWNAME,
dwStyle, 10, 10,
800,
600,
NULL, NULL, hInst, NULL);
return TRUE;
fUI->fTreeView->clear();
hsgResMgr::Reset();
// Load that source
plResManager *mgr = static_cast<plResManager *>(hsgResMgr::ResMgr());
mgr->AddSinglePage(fileName.toUtf8().constData());
fUI->fTreeView->LoadFromRegistry(fUI->fShowOnlyLoadableAction->isChecked());
SetWindowTitle(fileName);
}
/* Enable themes in Windows XP and later */
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
void plResBrowser::LoadResourcePath(const QString &path)
{
fUI->fTreeView->clear();
hsgResMgr::Reset();
// Load that source
plResManager *mgr = static_cast<plResManager *>(hsgResMgr::ResMgr());
std::vector<plFileName> prpFiles = plFileSystem::ListDir(path.toUtf8().constData(), "*.prp");
for (auto iter = prpFiles.begin(); iter != prpFiles.end(); ++iter)
mgr->AddSinglePage(*iter);
fUI->fTreeView->LoadFromRegistry(fUI->fShowOnlyLoadableAction->isChecked());
SetWindowTitle(path);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
app.setApplicationName("plResBrowser");
app.setWindowIcon(QIcon(":/icon1.ico"));
plResMgrSettings::Get().SetFilterNewerPageVersions(false);
plResMgrSettings::Get().SetFilterOlderPageVersions(false);
plResManager *rMgr = new plResManager;
hsgResMgr::Init(rMgr);
int retn;
{
plResBrowser mainWindow;
mainWindow.show();
retn = app.exec();
}
hsgResMgr::Shutdown();
return retn;
}

76
Sources/Tools/plResBrowser/plResBrowser.h

@ -0,0 +1,76 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _plResBrowser_h
#define _plResBrowser_h
#include <QMainWindow>
class plResBrowser : public QMainWindow
{
Q_OBJECT
public:
plResBrowser();
virtual ~plResBrowser();
void SetWindowTitle(const QString &title);
protected:
virtual void dragEnterEvent(QDragEnterEvent *event) override;
virtual void dropEvent(QDropEvent *event) override;
private slots:
void OpenFile();
void OpenDirectory();
void SaveSelectedObject();
void RefreshTree();
void UpdateInfoPage();
private:
class Ui_ResBrowser *fUI;
void RegisterFileTypes();
void LoadPrpFile(const QString &fileName);
void LoadResourcePath(const QString &path);
};
#endif

432
Sources/Tools/plResBrowser/plResBrowserWndProc.cpp

@ -1,432 +0,0 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsWindows.h"
#include "hsTemplates.h"
#include "res/resource.h"
#include <commdlg.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlwapi.h>
#include <shlobj.h>
#include "plResTreeView.h"
#include "plResMgr/plResManager.h"
#include "plResMgr/plResMgrSettings.h"
#include "plWinRegistryTools.h"
#define IDC_REGTREEVIEW 1000
extern HINSTANCE gInstance;
extern char *gCommandLine;
HWND gTreeView;
HWND gInfoDlg;
class plWaitCursor
{
HCURSOR fOrig;
public:
plWaitCursor()
{
fOrig = ::SetCursor( ::LoadCursor( nil, IDC_WAIT ) );
}
~plWaitCursor()
{
::SetCursor( fOrig );
}
};
void SetWindowTitle( HWND hWnd, char *path )
{
char fun[ MAX_PATH + 50 ];
sprintf( fun, "plResBrowser%s%s", path != nil ? " - " : "", path != nil ? path : "" );
SetWindowText( hWnd, fun );
}
INT_PTR CALLBACK AboutDialogProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
if( msg == WM_COMMAND )
EndDialog( hWnd, 0 );
return 0;
}
LRESULT CALLBACK HandleCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
OPENFILENAME openInfo;
char fileName[ MAX_PATH ];
char path[ MAX_PATH ];
static bool filter = true;
switch( LOWORD( wParam ) )
{
case ID_FILE_EXIT:
PostQuitMessage( 0 );
break;
case ID_FILE_OPENDIRECTORY:
BROWSEINFO bInfo;
LPITEMIDLIST itemList;
LPMALLOC shMalloc;
memset( &bInfo, 0, sizeof( bInfo ) );
bInfo.hwndOwner = hWnd;
bInfo.pidlRoot = NULL;
bInfo.pszDisplayName = path;
bInfo.lpszTitle = "Select a Plasma 2 Data Directory:";
bInfo.ulFlags = BIF_EDITBOX;
itemList = SHBrowseForFolder( &bInfo );
if( itemList != NULL )
{
plWaitCursor myWaitCursor;
SHGetPathFromIDList( itemList, path );
SHGetMalloc( &shMalloc );
shMalloc->Free( itemList );
shMalloc->Release();
hsgResMgr::Reset();
plResTreeView::ClearTreeView( gTreeView );
// Load that source
plResManager *mgr = (plResManager *)hsgResMgr::ResMgr();
std::vector<plFileName> prpFiles = plFileSystem::ListDir(path, "*.prp");
for (auto iter = prpFiles.begin(); iter != prpFiles.end(); ++iter)
mgr->AddSinglePage(*iter);
plResTreeView::FillTreeViewFromRegistry( gTreeView );
SetWindowTitle( hWnd, path );
}
break;
case ID_FILE_OPEN:
fileName[ 0 ] = 0;
memset( &openInfo, 0, sizeof( OPENFILENAME ) );
openInfo.hInstance = gInstance;
openInfo.hwndOwner = hWnd;
openInfo.lStructSize = sizeof( OPENFILENAME );
openInfo.lpstrFile = fileName;
openInfo.nMaxFile = sizeof( fileName );
openInfo.lpstrFilter = "Plasma 2 Pack Files\0*.prp\0All Files\0*.*\0";
openInfo.lpstrTitle = "Choose a file to browse:";
openInfo.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if( GetOpenFileName( &openInfo ) )
{
plWaitCursor myWaitCursor;
hsgResMgr::Reset();
plResTreeView::ClearTreeView( gTreeView );
// Load that source
plResManager *mgr = (plResManager *)hsgResMgr::ResMgr();
mgr->AddSinglePage(fileName);
plResTreeView::FillTreeViewFromRegistry( gTreeView );
SetWindowTitle( hWnd, fileName );
}
break;
case ID_FILE_ABOUT:
DialogBox( gInstance, MAKEINTRESOURCE( IDD_ABOUT ), hWnd, AboutDialogProc );
break;
case ID_FILE_FINDOBJECT:
plResTreeView::FindObject( gTreeView );
break;
case ID_FILE_FINDNEXT:
plResTreeView::FindNextObject( gTreeView );
break;
case ID_FILE_VERIFYPAGE:
plResTreeView::VerifyCurrentPage( gTreeView );
break;
case IDC_SHOWASHEX:
plResTreeView::UpdateInfoDlg( gTreeView );
break;
case ID_FILE_ONLYLOAD:
filter = !filter;
plResTreeView::FilterLoadables( filter, gTreeView );
{
HMENU menu = ::GetMenu( hWnd );
menu = ::GetSubMenu( menu, 0 );
::CheckMenuItem( menu, ID_FILE_ONLYLOAD, MF_BYCOMMAND | ( filter ? MF_CHECKED : MF_UNCHECKED ) );
}
break;
case ID_FILE_SAVESELECTED:
plResTreeView::SaveSelectedObject(gTreeView);
break;
default:
return DefWindowProc( hWnd, WM_COMMAND, wParam, lParam );
}
return 0;
}
void SizeControls( HWND parent )
{
RECT clientRect, infoRect;
GetClientRect( parent, &clientRect );
GetClientRect( gInfoDlg, &infoRect );
SetWindowPos( gTreeView, NULL, 0, 0, clientRect.right - infoRect.right - 4, clientRect.bottom, 0 );
OffsetRect( &infoRect, clientRect.right - infoRect.right, ( clientRect.bottom >> 1 ) - ( infoRect.bottom >> 1 ) );
SetWindowPos( gInfoDlg, NULL, infoRect.left, infoRect.top, 0, 0, SWP_NOSIZE );
}
void InitWindowControls( HWND hWnd )
{
RECT clientRect;
GetClientRect( hWnd, &clientRect );
gTreeView = CreateWindowEx( WS_EX_CLIENTEDGE, WC_TREEVIEW, "Tree View", WS_VISIBLE | WS_CHILD | WS_BORDER |
TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS,
0, 0, 0, 0,
hWnd, (HMENU)IDC_REGTREEVIEW, gInstance, NULL );
gInfoDlg = CreateDialog( gInstance, MAKEINTRESOURCE( IDD_INFODLG ), hWnd, plResTreeView::InfoDlgProc );
SizeControls( hWnd );
}
static bool sFileTypesRegistered = false;
void RegisterFileTypes( HWND mainWnd )
{
if( sFileTypesRegistered )
return;
// Make sure our file types are created
char path[ MAX_PATH ];
if( ::GetModuleFileName( nil, path, sizeof( path ) ) == 0 )
return;
//plWinRegistryTools::AssociateFileType( "PlasmaIdxFile", "Plasma 2 Index File", path, 1 );
//plWinRegistryTools::AssociateFileType( "PlasmaDatFile", "Plasma 2 Data File", path, 2 );
//plWinRegistryTools::AssociateFileType( "PlasmaPatchFile", "Plasma 2 Patch File", path, 3 );
plWinRegistryTools::AssociateFileType( "PlasmaPackFile", "Plasma 2 Packfile", path, 4 );
// Check our file extensions
char prpAssoc[ 512 ];
bool needToRegister = true;
if( plWinRegistryTools::GetCurrentFileExtensionAssociation( ".prp", prpAssoc, sizeof( prpAssoc ) ) )
{
if( strcmp( prpAssoc, "PlasmaPackFile" ) == 0 )
needToRegister = false;
}
if( needToRegister )
{
if( MessageBox( nil, "The Plasma 2 packed data file extension .prp is not currently associated with "
"plResBrowser. Would you like to associate it now?", "plResBrowser File Type Association",
MB_YESNO | MB_ICONQUESTION) == IDYES )
{
// Associate 'em
plWinRegistryTools::AssociateFileExtension( ".prp", "PlasmaPackFile" );
}
}
sFileTypesRegistered = true;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_CREATE:
InitCommonControls();
InitWindowControls( hWnd );
RegisterFileTypes( hWnd );
plResMgrSettings::Get().SetLoadPagesOnInit(false);
{
plResTreeView::FilterLoadables( true, gTreeView );
HMENU menu = ::GetMenu( hWnd );
menu = ::GetSubMenu( menu, 0 );
::CheckMenuItem( menu, ID_FILE_ONLYLOAD, MF_BYCOMMAND | MF_CHECKED );
}
if( gCommandLine != nil )
{
plWaitCursor myWaitCursor;
char path[ MAX_PATH ];
if( gCommandLine[ 0 ] == '"' )
{
strcpy( path, gCommandLine + 1 );
char *c = strchr( path, '"' );
if( c != nil )
*c = 0;
}
else
strcpy( path, gCommandLine );
if( stricmp( PathFindExtension( path ), ".prp" ) == 0 )
{
hsgResMgr::Reset();
plResTreeView::ClearTreeView( gTreeView );
plResManager *mgr = (plResManager *)hsgResMgr::ResMgr();
mgr->AddSinglePage(path);
plResTreeView::FillTreeViewFromRegistry( gTreeView );
SetWindowTitle( hWnd, path );
}
}
break;
case WM_CLOSE:
DestroyWindow( hWnd );
break;
case WM_DESTROY:
plResTreeView::ClearTreeView( gTreeView );
PostQuitMessage(0);
break;
case WM_SIZING:
case WM_SIZE:
SizeControls( hWnd );
break;
case WM_NOTIFY:
if( wParam == IDC_REGTREEVIEW )
{
NMHDR *hdr = (NMHDR *)lParam;
if( hdr->code == TVN_SELCHANGED )
{
plResTreeView::UpdateInfoDlg( gTreeView );
//NMTREEVIEW *tv = (NMTREEVIEW *)hdr;
}
else if( hdr->code == NM_DBLCLK )
{
plResTreeView::SelectionDblClicked( gTreeView );
}
}
break;
case WM_DROPFILES:
{
int i, j, fileCount = DragQueryFile( (HDROP)wParam, -1, nil, 0 );
char path[ MAX_PATH ];
plWaitCursor myWaitCursor;
hsgResMgr::Reset();
plResTreeView::ClearTreeView( gTreeView );
plResManager *mgr = (plResManager *)hsgResMgr::ResMgr();
if( fileCount == 1 && DragQueryFile( (HDROP)wParam, 0, path, sizeof( path ) ) > 0 &&
( (char *)PathFindExtension( path ) )[ 0 ] == 0 )
{
// Must be a directory
std::vector<plFileName> prpFiles = plFileSystem::ListDir(path, "*.prp");
for (auto iter = prpFiles.begin(); iter != prpFiles.end(); ++iter)
mgr->AddSinglePage(*iter);
}
else
{
hsTArray<char *> filesAdded;
filesAdded.Reset();
for( i = 0; i < fileCount; i++ )
{
if( DragQueryFile( (HDROP)wParam, i, path, sizeof( path ) ) > 0 )
{
// Check for duplicates
for( j = 0; j < filesAdded.GetCount(); j++ )
{
if( stricmp( filesAdded[ j ], path ) == 0 )
break;
}
if( j < filesAdded.GetCount() )
continue;
if( stricmp( PathFindExtension( path ), ".prp" ) == 0 )
{
mgr->AddSinglePage(path);
filesAdded.Append( hsStrcpy( path ) );
}
}
}
for( j = 0; j < filesAdded.GetCount(); j++ )
delete [] filesAdded[ j ];
}
plResTreeView::FillTreeViewFromRegistry( gTreeView );
PathRemoveFileSpec( path );
SetWindowTitle( hWnd, path );
}
break;
case WM_COMMAND:
return HandleCommand( hWnd, wParam, lParam );
}
return DefWindowProc( hWnd, message, wParam, lParam );
}

497
Sources/Tools/plResBrowser/plResTreeView.cpp

@ -40,9 +40,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsWindows.h"
#include "plResTreeView.h"
#include "ui_FindDialog.h"
#include "plResMgr/plResManager.h"
#include "plResMgr/plRegistryHelpers.h"
@ -53,470 +53,141 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "pnKeyedObject/plKeyImp.h"
#include "pnFactory/plFactory.h"
#include <commctrl.h>
#include <shlwapi.h>
#include "res/resource.h"
extern HINSTANCE gInstance;
HWND plResTreeView::fInfoDlg = nil;
bool plResTreeView::fFilter = false;
static char gSearchString[ 512 ];
static HTREEITEM fFoundItem = nil;
extern void ViewPatchDetails( plKey &patchKey );
INT_PTR CALLBACK FindDialogProc( HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_INITDIALOG:
return true;
case WM_COMMAND:
if( LOWORD( wParam ) == IDOK )
{
GetDlgItemText( dlg, IDC_SEARCHSTRING, gSearchString, sizeof( gSearchString ) );
fFoundItem = nil;
EndDialog( dlg, IDOK );
}
else if( LOWORD( wParam ) == IDCANCEL )
EndDialog( dlg, IDCANCEL );
return -1;
}
return 0;
}
#include <QDialog>
#include <QLayout>
#include <QMessageBox>
struct plKeyInfo
{
plKey fKey;
plRegistryPageNode *fPage;
plKeyInfo( plKey k, plRegistryPageNode *p ) : fKey( k ), fPage( p ) {}
};
// How's this for functionality?
class plResDlgLoader : public plRegistryPageIterator, public plRegistryKeyIterator
{
protected:
HWND fTree;
HTREEITEM fCurrItem, fCurrTypeItem;
uint16_t fCurrType;
bool fFilter;
plRegistryPageNode *fCurrPage;
HTREEITEM AddLeaf(HWND hTree, HTREEITEM hParent, const char *text, plKeyInfo *info )
{
TVITEM tvi = {0};
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.pszText = text ? (char*)text : (char*)"<NULL>";
tvi.cchTextMax = text ? strlen(text) : 7;
tvi.lParam = (LPARAM)info;
TVINSERTSTRUCT tvins = {0};
tvins.item = tvi;
tvins.hParent = hParent;
tvins.hInsertAfter = TVI_SORT;
return TreeView_InsertItem(hTree, &tvins);
}
public:
plResDlgLoader( HWND hTree, bool filter )
{
fFilter = filter;
fTree = hTree;
((plResManager *)hsgResMgr::ResMgr())->IterateAllPages( this );
}
virtual bool EatPage( plRegistryPageNode *page )
{
char str[ 512 ];
fCurrPage = page;
const plPageInfo &info = page->GetPageInfo();
sprintf( str, "%s->%s", info.GetAge().c_str(), info.GetPage().c_str());
fCurrItem = AddLeaf( fTree, NULL, str, new plKeyInfo( nil, fCurrPage ) );
fCurrType = (uint16_t)-1;
page->LoadKeys();
page->IterateKeys( this );
return true;
}
virtual bool EatKey( const plKey& key )
{
if( fCurrType != key->GetUoid().GetClassType() )
{
fCurrType = key->GetUoid().GetClassType();
const char *className = plFactory::GetNameOfClass( fCurrType );
fCurrTypeItem = AddLeaf( fTree, fCurrItem, className != nil ? className : "<unknown>", nil );
}
if( !fFilter )
AddLeaf( fTree, fCurrTypeItem, key->GetUoid().GetObjectName().c_str(), new plKeyInfo( key, fCurrPage ) );
return true;
}
plRegistryPageNode *fPage;
};
void plResTreeView::FillTreeViewFromRegistry( HWND hWnd )
plResTreeViewItem::~plResTreeViewItem()
{
plResDlgLoader loader( hWnd, fFilter );
delete fData;
}
HTREEITEM IGetNextTreeItem( HWND tree, HTREEITEM item )
plKey plResTreeViewItem::GetKey() const
{
// First try child items of this one
HTREEITEM next = TreeView_GetChild( tree, item );
if( next == nil )
// If no child items, try next sibling
next = TreeView_GetNextSibling( tree, item );
if( next == nil )
{
// If no siblings, go up to the parent and keep searching until we find a parent with a sibling
next = item;
while( true )
{
next = TreeView_GetParent( tree, next );
if( next == nil )
{
// No parent; not found, so stop
break;
}
else if( TreeView_GetNextSibling( tree, next ) != nil )
{
next = TreeView_GetNextSibling( tree, next );
break;
}
}
}
return next;
return fData ? fData->fKey : nullptr;
}
void plResTreeView::FindNextObject( HWND tree )
plRegistryPageNode *plResTreeViewItem::GetPage() const
{
if( fFoundItem == nil )
FindObject( tree );
else
{
fFoundItem = IGetNextTreeItem( tree, fFoundItem );
IFindNextObject( tree );
}
return fData ? fData->fPage : nullptr;
}
void plResTreeView::FindObject( HWND tree )
// How's this for functionality?
class plResDlgLoader : public plRegistryPageIterator, public plRegistryKeyIterator
{
if( DialogBox( gInstance, MAKEINTRESOURCE( IDD_FINDOBJ ), tree, FindDialogProc ) == IDOK )
protected:
plResTreeView *fTree;
plResTreeViewItem *fCurrItem;
plResTreeViewItem *fCurrTypeItem;
uint16_t fCurrType;
bool fFilter;
plRegistryPageNode *fCurrPage;
public:
plResDlgLoader(plResTreeView *tree, bool filter)
: fFilter(filter), fTree(tree)
{
fFoundItem = TreeView_GetRoot( tree );
IFindNextObject( tree );
static_cast<plResManager *>(hsgResMgr::ResMgr())->IterateAllPages(this);
}
}
void plResTreeView::IFindNextObject( HWND tree )
{
while( fFoundItem != nil )
virtual bool EatPage(plRegistryPageNode *page)
{
// Get the item
TVITEM itemInfo;
itemInfo.mask = TVIF_PARAM | TVIF_HANDLE;
itemInfo.hItem = fFoundItem;
TreeView_GetItem( tree, &itemInfo );
plKeyInfo *keyInfo = (plKeyInfo *)itemInfo.lParam;
if( keyInfo != nil && keyInfo->fKey != nil )
{
if( keyInfo->fKey->GetUoid().GetObjectName().Compare( gSearchString, plString::kCaseInsensitive ) >= 0 )
{
/// FOUND
TreeView_SelectItem( tree, fFoundItem );
return;
}
}
// Keep searching. First try child items of this one
fFoundItem = IGetNextTreeItem( tree, fFoundItem );
fCurrPage = page;
const plPageInfo &info = page->GetPageInfo();
QString name = QString("%1->%2").arg(info.GetAge().c_str()).arg(info.GetPage().c_str());
fCurrItem = new plResTreeViewItem(fTree, name, new plKeyInfo { nullptr, fCurrPage });
fCurrType = static_cast<uint16_t>(-1);
page->LoadKeys();
page->IterateKeys(this);
return true;
}
MessageBox( tree, "No objects found", "Find Object", MB_OK );
}
void IDeleteRecurse( HWND tree, HTREEITEM item )
{
while( item != nil )
virtual bool EatKey(const plKey &key)
{
HTREEITEM child = TreeView_GetChild( tree, item );
if( child != nil )
IDeleteRecurse( tree, child );
TVITEM itemInfo;
itemInfo.mask = TVIF_PARAM | TVIF_HANDLE;
itemInfo.hItem = item;
TreeView_GetItem( tree, &itemInfo );
plKeyInfo *keyInfo = (plKeyInfo *)itemInfo.lParam;
if( keyInfo != nil )
if (fCurrType != key->GetUoid().GetClassType())
{
delete keyInfo;
itemInfo.lParam = 0;
TreeView_SetItem( tree, &itemInfo );
fCurrType = key->GetUoid().GetClassType();
const char *className = plFactory::GetNameOfClass(fCurrType);
fCurrTypeItem = new plResTreeViewItem(fCurrItem, className ? className : "<unknown>", nullptr);
}
item = TreeView_GetNextSibling( tree, item );
if (!fFilter) {
new plResTreeViewItem(fCurrTypeItem, key->GetUoid().GetObjectName().c_str(),
new plKeyInfo { key, fCurrPage });
}
return true;
}
}
};
void plResTreeView::ClearTreeView( HWND hWnd )
void plResTreeView::LoadFromRegistry(bool filter)
{
HTREEITEM root = TreeView_GetRoot( hWnd );
if( root != nil )
IDeleteRecurse( hWnd, root );
TreeView_DeleteAllItems( hWnd );
plResDlgLoader loader(this, filter);
sortItems(0, Qt::AscendingOrder);
}
void plResTreeView::SelectionDblClicked( HWND treeCtrl )
static QTreeWidgetItem *IGetNextTreeItem(QTreeWidgetItem *item)
{
HTREEITEM sel = TreeView_GetSelection( treeCtrl );
if( sel != nil )
{
TVITEM item;
item.mask = TVIF_PARAM | TVIF_HANDLE;
item.hItem = sel;
if( !TreeView_GetItem( treeCtrl, &item ) )
return;
}
}
if (!item)
return nullptr;
void plResTreeView::FilterLoadables( bool filter, HWND treeCtrl )
{
fFilter = filter;
ClearTreeView( treeCtrl );
FillTreeViewFromRegistry( treeCtrl );
QTreeWidgetItemIterator iter(item);
return *(++iter);
}
INT_PTR CALLBACK plResTreeView::InfoDlgProc( HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam )
void plResTreeView::FindObject()
{
switch( msg )
{
case WM_INITDIALOG:
fInfoDlg = dlg;
break;
case WM_COMMAND:
return SendMessage( GetParent( dlg ), msg, wParam, lParam );
}
QDialog findDialog(this);
Ui_FindDialog ui;
ui.setupUi(&findDialog);
return 0;
}
findDialog.layout()->setSizeConstraint(QLayout::SetFixedSize);
void plResTreeView::VerifyCurrentPage( HWND treeCtrl )
{
HTREEITEM sel = TreeView_GetSelection( treeCtrl );
if( sel != nil )
if (findDialog.exec() == QDialog::Accepted)
{
TVITEM item;
item.mask = TVIF_PARAM | TVIF_HANDLE;
item.hItem = sel;
if( !TreeView_GetItem( treeCtrl, &item ) )
return;
plKeyInfo *info = (plKeyInfo *)item.lParam;
if( info != nil )
{
if( info->fPage != nil )
{
// TODO: FIXME
/*
/// HACK. Live with it
class plHackResManager : public plResManager
{
public:
plRegistry *GetRegistry( void ) { return IGetRegistry(); }
};
plRegistry *registry = ((plHackResManager *)hsgResMgr::ResMgr())->GetRegistry();
plRegistry::plPageCond result = registry->VerifyOnePage( info->fPage );
char msg[ 512 ];
if( result == plRegistry::kOK || result == plRegistry::kTooNew )
strcpy( msg, "Page verifies OK" );
else if( result == plRegistry::kChecksumInvalid )
strcpy( msg, "Checksums for page are invalid" );
else if( result == plRegistry::kOutOfDate )
strcpy( msg, "Page is older than the current data version" );
hsMessageBox( msg, "Verification Results", hsMessageBoxNormal );
*/
}
}
fFoundItem = invisibleRootItem();
fSearchString = ui.fObjectName->text().toUtf8().constData();
IFindNextObject();
}
}
void plResTreeView::UpdateInfoDlg( HWND treeCtrl )
void plResTreeView::FindNextObject()
{
bool showAsHex = (bool)IsDlgButtonChecked( fInfoDlg, IDC_SHOWASHEX );
SetDlgItemText( fInfoDlg, IDC_NAME, "" );
SetDlgItemText( fInfoDlg, IDC_CLASS, "" );
SetDlgItemText( fInfoDlg, IDC_LENGTH, "" );
SetDlgItemText( fInfoDlg, IDC_STARTPOS, "" );
EnableWindow( GetDlgItem( fInfoDlg, ID_FILE_VERIFYPAGE ), FALSE );
HTREEITEM sel = TreeView_GetSelection( treeCtrl );
if( sel != nil )
if (!fFoundItem)
FindObject();
else
{
TVITEM item;
item.mask = TVIF_PARAM | TVIF_HANDLE;
item.hItem = sel;
if( !TreeView_GetItem( treeCtrl, &item ) )
return;
plKeyInfo *info = (plKeyInfo *)item.lParam;
if( info != nil )
{
if( info->fPage != nil )
{
const plPageInfo &pageInfo = info->fPage->GetPageInfo();
char tempStr[ 32 ];
SetDlgItemText( fInfoDlg, IDC_AGE, pageInfo.GetAge().c_str());
SetDlgItemText( fInfoDlg, IDC_PAGE, pageInfo.GetPage().c_str());
SetDlgItemText( fInfoDlg, IDC_LOCATION, pageInfo.GetLocation().StringIze().c_str() );
CheckDlgButton(fInfoDlg, IDC_RESERVED, (pageInfo.GetLocation().GetFlags() & plLocation::kReserved) ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(fInfoDlg, IDC_BUILTIN, (pageInfo.GetLocation().GetFlags() & plLocation::kBuiltIn) ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(fInfoDlg, IDC_VOLATILE, (pageInfo.GetLocation().GetFlags() & plLocation::kVolatile) ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(fInfoDlg, IDC_LOCAL_ONLY, (pageInfo.GetLocation().GetFlags() & plLocation::kLocalOnly) ? BST_CHECKED : BST_UNCHECKED);
sprintf( tempStr, "%d", pageInfo.GetMajorVersion());
SetDlgItemText( fInfoDlg, IDC_DATAVERSION, tempStr );
SetDlgItemText( fInfoDlg, IDC_CHECKSUMTYPE, "Basic (file size)" );
EnableWindow( GetDlgItem( fInfoDlg, ID_FILE_VERIFYPAGE ), TRUE );
}
if( info->fKey != nil )
{
char str[ 128 ];
SetDlgItemText( fInfoDlg, IDC_NAME, info->fKey->GetUoid().GetObjectName().c_str() );
const char *name = plFactory::GetNameOfClass( info->fKey->GetUoid().GetClassType() );
sprintf( str, "%s (%d)", name != nil ? name : "<unknown>", info->fKey->GetUoid().GetClassType() );
SetDlgItemText( fInfoDlg, IDC_CLASS, str );
plKeyImp *imp = (plKeyImp *)info->fKey;
EnableWindow( GetDlgItem( fInfoDlg, IDC_STARTPOS_LABEL ), true );
EnableWindow( GetDlgItem( fInfoDlg, IDC_SIZE_LABEL ), true );
if( showAsHex )
sprintf( str, "0x%X", imp->GetStartPos() );
else
sprintf( str, "%d", imp->GetStartPos() );
SetDlgItemText( fInfoDlg, IDC_STARTPOS, str );
if( imp->GetDataLen() < 1024 )
sprintf( str, "%d bytes", imp->GetDataLen() );
else if( imp->GetDataLen() < 1024 * 1024 )
sprintf( str, "%4.2f kB", imp->GetDataLen() / 1024.f );
else
sprintf( str, "%4.2f MB", imp->GetDataLen() / 1024.f / 1024.f );
SetDlgItemText( fInfoDlg, IDC_LENGTH, str );
}
}
fFoundItem = IGetNextTreeItem(fFoundItem);
IFindNextObject();
}
}
#include "hsStream.h"
#include <commdlg.h>
void plResTreeView::SaveSelectedObject(HWND treeCtrl)
void plResTreeView::IFindNextObject()
{
// TODO: FIXME
/*
plKey itemKey = nil;
HTREEITEM sel = TreeView_GetSelection(treeCtrl);
if (sel != nil)
while (fFoundItem)
{
TVITEM item;
item.mask = TVIF_PARAM | TVIF_HANDLE;
item.hItem = sel;
if (TreeView_GetItem(treeCtrl, &item))
// Get the item
plKey key = fFoundItem->type() == plResTreeViewItem::Type
? static_cast<plResTreeViewItem *>(fFoundItem)->GetKey()
: nullptr;
if (key && key->GetUoid().GetObjectName().Find(fSearchString, plString::kCaseInsensitive) >= 0)
{
plKeyInfo *info = (plKeyInfo*)item.lParam;
if (info != nil)
itemKey = info->fKey;
}
}
if (!itemKey)
return;
char fileName[MAX_PATH];
sprintf(fileName, "%s.bin", itemKey->GetName());
OPENFILENAME openInfo;
memset( &openInfo, 0, sizeof( OPENFILENAME ) );
// openInfo.hInstance = gInstance;
// openInfo.hwndOwner = hWnd;
openInfo.lStructSize = sizeof( OPENFILENAME );
openInfo.lpstrFile = fileName;
openInfo.nMaxFile = sizeof( fileName );
openInfo.lpstrFilter = "Binary Files\0*.bin\0All Files\0*.*\0";
// openInfo.lpstrTitle = "Choose a pack index file to browse:";
// openInfo.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if (GetSaveFileName(&openInfo))
{
plKeyImp* keyImp = (plKeyImp*)itemKey;
if (keyImp->GetDataLen() <= 0)
/// FOUND
setCurrentItem(fFoundItem);
return;
plResManager* resMgr = (plResManager*)hsgResMgr::ResMgr();
const plPageInfo& pageInfo = resMgr->FindPage(keyImp->GetUoid().GetLocation())->GetPageInfo();
plRegistryDataStream *stream = registry->OpenPageDataStream( keyImp->GetUoid().GetLocation(), false );
if( stream == nil )
return;
hsStream *dataStream = stream->GetStream();
uint8_t *buffer = new uint8_t[ keyImp->GetDataLen() ];
if( buffer != nil )
{
dataStream->SetPosition( keyImp->GetStartPos() );
dataStream->Read( keyImp->GetDataLen(), buffer );
}
delete stream;
if( buffer == nil )
return;
hsUNIXStream outStream;
outStream.Open(fileName, "wb");
outStream.Write(keyImp->GetDataLen(), buffer);
outStream.Close();
delete [] buffer;
// Keep searching. First try child items of this one
fFoundItem = IGetNextTreeItem(fFoundItem);
}
*/
}
QMessageBox::critical(this, tr("Find Objects"), tr("No objects found"));
}

51
Sources/Tools/plResBrowser/plResTreeView.h

@ -42,34 +42,53 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#ifndef _plResTreeView_h
#define _plResTreeView_h
class plResTreeView
#include "plString.h"
#include <QTreeWidget>
struct plKeyInfo;
class plKey;
class plRegistryPageNode;
class plResTreeViewItem : public QTreeWidgetItem
{
protected:
public:
enum { Type = UserType };
static HWND fInfoDlg;
static bool fFilter;
plResTreeViewItem(QTreeWidget *parent, const QString &text, plKeyInfo *key)
: QTreeWidgetItem(parent, QStringList { text }, Type), fData(key) { }
plResTreeViewItem(QTreeWidgetItem *parent, const QString &text, plKeyInfo *key)
: QTreeWidgetItem(parent, QStringList { text }, Type), fData(key) { }
static void IFindNextObject( HWND tree );
virtual ~plResTreeViewItem();
public:
plKey GetKey() const;
plRegistryPageNode *GetPage() const;
static void FindObject( HWND tree );
static void FindNextObject( HWND tree );
private:
plKeyInfo *fData;
};
static void FillTreeViewFromRegistry( HWND hWnd );
static void ClearTreeView( HWND hWnd );
static INT_PTR CALLBACK InfoDlgProc( HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam );
class plResTreeView : public QTreeWidget
{
Q_OBJECT
static void UpdateInfoDlg( HWND treeCtrl );
public:
plResTreeView(QWidget *parent = nullptr)
: QTreeWidget(parent), fFoundItem(nullptr) { }
static void VerifyCurrentPage( HWND treeCtrl );
void LoadFromRegistry(bool filter);
static void SelectionDblClicked( HWND treeCtrl );
public slots:
void FindObject();
void FindNextObject();
static void FilterLoadables( bool filter, HWND treeCtrl );
private:
QTreeWidgetItem *fFoundItem;
plString fSearchString;
static void SaveSelectedObject(HWND treeCtrl);
void IFindNextObject();
};
#endif //_plResTreeView_h

73
Sources/Tools/plResBrowser/plWinRegistryTools.cpp

@ -52,6 +52,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsWindows.h"
#include "plWinRegistryTools.h"
#include <QString>
#include <string>
//////////////////////////////////////////////////////////////////////////////
@ -62,27 +64,31 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
// Sets the given registry key to the given string value. If valueName = nil,
// sets the (default) value
static bool ISetRegKey( const char *keyName, const char *value, const char *valueName = nil )
static bool ISetRegKey(const QString &keyName, const QString &value, const QString &valueName = QString())
{
HKEY regKey;
DWORD result;
// Create the key (just opens if it already exists)
if( ::RegCreateKeyEx( HKEY_CLASSES_ROOT, keyName, 0, nil, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
nil, &regKey, &result ) != ERROR_SUCCESS )
if (::RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName.toStdWString().c_str(), 0,
nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
nullptr, &regKey, &result) != ERROR_SUCCESS)
{
hsStatusMessageF( "Warning: Registry database open failed for key '%s'.\n", keyName );
hsStatusMessageF("Warning: Registry database open failed for key '%s'.\n", qPrintable(keyName));
return false;
}
// Assign the "default" subkey value
LONG lResult = ::RegSetValueEx( regKey, valueName, 0, REG_SZ, (const BYTE *)value, ( lstrlen( value ) + 1 ) * sizeof( TCHAR ) );
std::wstring wValue = value.toStdWString();
LONG lResult = ::RegSetValueExW(regKey, valueName.toStdWString().c_str(), 0,
REG_SZ, reinterpret_cast<const BYTE *>(wValue.c_str()),
(wValue.size() + 1) * sizeof(wchar_t));
if( ::RegCloseKey( regKey ) == ERROR_SUCCESS && lResult == ERROR_SUCCESS )
if (::RegCloseKey(regKey) == ERROR_SUCCESS && lResult == ERROR_SUCCESS)
return true;
hsStatusMessageF( "Warning: Registry database update failed for key '%s'.\n", keyName );
hsStatusMessageF("Warning: Registry database update failed for key '%s'.\n", qPrintable(keyName));
return false;
}
@ -108,28 +114,26 @@ static bool ISetRegKey( const char *keyName, const char *value, const char *
// |--- command (value = command line)
//
bool plWinRegistryTools::AssociateFileType( const char *fileTypeID, const char *fileTypeName, const char *appPath, int iconIndex )
bool plWinRegistryTools::AssociateFileType(const QString &fileTypeID, const QString &fileTypeName,
const QString &appPath, int iconIndex)
{
char keyName[ 512 ], keyValue[ 512 ];
// Root key
if( !ISetRegKey( fileTypeID, fileTypeName ) )
if (!ISetRegKey(fileTypeID, fileTypeName))
return false;
// DefaultIcon key, if we want one
if( iconIndex != -1 )
if (iconIndex != -1)
{
sprintf( keyName, "%s\\DefaultIcon", fileTypeID );
sprintf( keyValue, "%s,%d", appPath, iconIndex );
if( !ISetRegKey( keyName, keyValue ) )
QString keyName = QString(R"(%1\DefaultIcon)").arg(fileTypeID);
QString keyValue = QString("%1,%2").arg(appPath).arg(iconIndex);
if (!ISetRegKey(keyName, keyValue))
return false;
}
// shell/open/command key
sprintf( keyName, "%s\\shell\\open\\command", fileTypeID );
sprintf( keyValue, "\"%s\" \"%%1\"", appPath );
if( !ISetRegKey( keyName, keyValue ) )
QString keyName = QString(R"(%1\shell\open\command)").arg(fileTypeID);
QString keyValue = QString(R"("%1" "%2")").arg(appPath, "%1");
if (!ISetRegKey(keyName, keyValue))
return false;
// Success!
@ -148,32 +152,33 @@ bool plWinRegistryTools::AssociateFileType( const char *fileTypeID, const cha
// where fileExtension includes the leading . and fileTypeID is the same
// typeID registered with the above function
bool plWinRegistryTools::AssociateFileExtension( const char *fileExtension, const char *fileTypeID )
bool plWinRegistryTools::AssociateFileExtension(const QString &fileExtension, const QString &fileTypeID)
{
return ISetRegKey( fileExtension, fileTypeID );
return ISetRegKey(fileExtension, fileTypeID);
}
//// GetCurrentFileExtensionAssociation //////////////////////////////////////
// Obtains the current fileTypeID associated with the given file extension,
// or a null string if it isn't yet associated.
bool plWinRegistryTools::GetCurrentFileExtensionAssociation( const char *extension, char *buffer, int bufferLen )
QString plWinRegistryTools::GetCurrentFileExtensionAssociation(const QString &extension)
{
long dataLen;
buffer[ 0 ] = 0;
dataLen = bufferLen;
long dataLen = 512;
wchar_t buffer[512];
buffer[0] = 0;
LONG retVal = ::RegQueryValue( HKEY_CLASSES_ROOT, extension, buffer, &dataLen );
if( retVal != ERROR_SUCCESS )
LONG retVal = ::RegQueryValueW(HKEY_CLASSES_ROOT, extension.toStdWString().c_str(), buffer, &dataLen);
if (retVal != ERROR_SUCCESS)
{
char msg[ 512 ];
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, retVal, 0, msg, sizeof( msg ), nil );
hsStatusMessageF( "Error querying registry key '%s' : %s\n", extension, msg );
return false;
char msg[512];
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, retVal, 0, msg, arrsize(msg), nullptr);
hsStatusMessageF("Error querying registry key '%s' : %s\n", qPrintable(extension), msg);
return QString();
}
return true;
if (dataLen < 512 && buffer[dataLen] == 0)
dataLen -= 1;
return QString::fromWCharArray(buffer, dataLen);
}

21
Sources/Tools/plResBrowser/plWinRegistryTools.h

@ -51,18 +51,25 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#ifndef _plWinRegistryTools_h
#define _plWinRegistryTools_h
class QString;
class plWinRegistryTools
{
public:
// Associates a given file type in the Win32 registry with the given application. Also assigns a default icon if iconIndex != -1
static bool AssociateFileType( const char *fileTypeID, const char *fileTypeName, const char *appPath, int iconIndex = -1 );
/* Associates a given file type in the Win32 registry with the given
application. Also assigns a default icon if iconIndex != -1 */
static bool AssociateFileType(const QString &fileTypeID, const QString &fileTypeName,
const QString &appPath, int iconIndex = -1);
// Assigns a given file extension to a previously registered Win32 file type (using the above function)
static bool AssociateFileExtension( const char *fileExtension, const char *fileTypeID );
/* Assigns a given file extension to a previously registered Win32
file type (using the above function) */
static bool AssociateFileExtension(const QString &fileExtension,
const QString &fileTypeID);
// Obtains the current fileTypeID associated with the given file extension, or a null string if it isn't yet associated
static bool GetCurrentFileExtensionAssociation( const char *extension, char *buffer, int bufferLen );
/* Obtains the current fileTypeID associated with the given file
extension, or a null string if it isn't yet associated */
static QString GetCurrentFileExtensionAssociation(const QString &extension);
};
#endif //_plWinRegistryTools_h
#endif //_plWinRegistryTools_h

76
Sources/Tools/plResBrowser/res/FindDialog.ui

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FindDialog</class>
<widget class="QDialog" name="FindDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>71</height>
</rect>
</property>
<property name="windowTitle">
<string>Find Object</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Object Name</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="fObjectName"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FindDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FindDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

591
Sources/Tools/plResBrowser/res/ResBrowser.ui

@ -0,0 +1,591 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ResBrowser</class>
<widget class="QMainWindow" name="ResBrowser">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>plResBrowser</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="plResTreeView" name="fTreeView">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="fOpenAction"/>
<addaction name="fOpenDirectoryAction"/>
<addaction name="separator"/>
<addaction name="fSaveSelectedAction"/>
<addaction name="separator"/>
<addaction name="fFindAction"/>
<addaction name="fFindNextAction"/>
<addaction name="fShowOnlyLoadableAction"/>
<addaction name="separator"/>
<addaction name="fExitAction"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="fAboutAction"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Help"/>
</widget>
<widget class="QDockWidget" name="dockWidget">
<property name="minimumSize">
<size>
<width>300</width>
<height>520</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Properties</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Page Information</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Age:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="fAgeName">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="fLocation">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Data Version:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Page</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="fPageName">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="fDataVersion">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="fChecksum">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Checksum:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="fLocalOnly">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="fVolatile">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="fReserved">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="fBuiltIn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Local Only</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Reserved</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Volatile</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_14">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Built-In</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="fChecksumType">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Checksum Type:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Object Information</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Start Pos:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Name:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Class:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="fStartPos">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="5">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="4">
<widget class="QLineEdit" name="fObjectSize">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4">
<widget class="QLineEdit" name="fObjectName">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QLineEdit" name="fObjectClass">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="fHexValues">
<property name="text">
<string>View values as he&amp;x</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="fFindButton">
<property name="text">
<string>Fin&amp;d</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fFindNextButton">
<property name="text">
<string>Find &amp;Next</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="fSaveButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Save Object</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<action name="fOpenAction">
<property name="text">
<string>&amp;Open...</string>
</property>
</action>
<action name="fOpenDirectoryAction">
<property name="text">
<string>Open &amp;Directory...</string>
</property>
</action>
<action name="fSaveSelectedAction">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Save Selected Object</string>
</property>
</action>
<action name="fFindAction">
<property name="text">
<string>&amp;Find Object...</string>
</property>
<property name="shortcut">
<string>Ctrl+F</string>
</property>
</action>
<action name="fFindNextAction">
<property name="text">
<string>Find &amp;Next</string>
</property>
<property name="shortcut">
<string>F3</string>
</property>
</action>
<action name="fShowOnlyLoadableAction">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Show Only &amp;Loadable</string>
</property>
</action>
<action name="fExitAction">
<property name="text">
<string>E&amp;xit</string>
</property>
</action>
<action name="fAboutAction">
<property name="text">
<string>&amp;About...</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>plResTreeView</class>
<extends>QTreeWidget</extends>
<header>plResTreeView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

5
Sources/Tools/plResBrowser/res/plResBrowser.qrc

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>icon1.ico</file>
</qresource>
</RCC>

203
Sources/Tools/plResBrowser/res/plResBrowser.rc

@ -1,25 +1,15 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define IDC_STATIC (-1) // all static controls
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
// Icons
//
#define IDI_APPICON 101
#define IDI_INDEXICON 108
#define IDI_DATAICON 109
#define IDI_PATCHICON 110
#define IDI_MERGEDDATAICON 111
#define IDI_MERGEDINDEXICON 112
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "icon1.ico"
@ -28,180 +18,3 @@ IDI_DATAICON ICON "indexico.ico"
IDI_PATCHICON ICON "dataicon.ico"
IDI_MERGEDDATAICON ICON "mergedda.ico"
IDI_MERGEDINDEXICON ICON "mergedin.ico"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_APPMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...", ID_FILE_OPEN
MENUITEM "Open &Directory...", ID_FILE_OPENDIRECTORY
MENUITEM SEPARATOR
MENUITEM "Save Selected Object", ID_FILE_SAVESELECTED
MENUITEM SEPARATOR
MENUITEM "Find Object...\tCtrl+F", ID_FILE_FINDOBJECT
MENUITEM "Find Next\tF3", ID_FILE_FINDNEXT
MENUITEM "Show Only Loadable", ID_FILE_ONLYLOAD
MENUITEM SEPARATOR
MENUITEM "About...", ID_FILE_ABOUT
MENUITEM "Exit", ID_FILE_EXIT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_INFODLG DIALOGEX 0, 0, 186, 281
STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
GROUPBOX "Object Information",IDC_STATIC,4,168,178,67
RTEXT "Name:",IDC_STATIC,17,180,22,8
LTEXT "",IDC_NAME,42,179,129,10,SS_SUNKEN | NOT WS_GROUP
GROUPBOX "Page Information",IDC_STATIC,4,2,178,163
RTEXT "Age:",IDC_STATIC,45,14,16,8
LTEXT "",IDC_AGE,63,14,107,10,SS_SUNKEN | NOT WS_GROUP
RTEXT "Page:",IDC_STATIC,41,28,20,8
LTEXT "",IDC_PAGE,63,28,107,10,SS_SUNKEN | NOT WS_GROUP
RTEXT "Location:",IDC_STATIC,31,43,30,8
LTEXT "",IDC_LOCATION,64,43,74,10,SS_SUNKEN | NOT WS_GROUP
CONTROL "Reserved",IDC_RESERVED,"Button",BS_AUTOCHECKBOX |
WS_DISABLED | WS_TABSTOP,64,66,10,10
RTEXT "Class:",IDC_STATIC,19,195,20,8
LTEXT "",IDC_CLASS,42,194,129,10,SS_SUNKEN | NOT WS_GROUP
RTEXT "Start Pos:",IDC_STARTPOS_LABEL,7,221,32,8
LTEXT "",IDC_STARTPOS,42,220,55,10,SS_SUNKEN | NOT WS_GROUP
RTEXT "Size:",IDC_SIZE_LABEL,103,221,17,8
LTEXT "",IDC_LENGTH,124,220,47,10,SS_SUNKEN | NOT WS_GROUP
LTEXT "Reserved",IDC_STATIC,76,67,31,8
PUSHBUTTON "Find",ID_FILE_FINDOBJECT,4,259,50,14
PUSHBUTTON "Find Next",ID_FILE_FINDNEXT,58,259,50,14
RTEXT "Data Version:",IDC_STATIC,17,79,44,8
LTEXT "",IDC_DATAVERSION,64,79,48,10,SS_SUNKEN | NOT WS_GROUP
RTEXT "Checksum:",IDC_STATIC,25,139,36,8
LTEXT "",IDC_IDXCHECKSUM,64,139,53,10,SS_SUNKEN | NOT WS_GROUP
PUSHBUTTON "Verify Page",ID_FILE_VERIFYPAGE,130,259,50,14
RTEXT "Checksum type:",IDC_STATIC,9,151,52,8
LTEXT "",IDC_CHECKSUMTYPE,64,152,89,10,SS_SUNKEN | NOT
WS_GROUP
CONTROL "View values as hex",IDC_SHOWASHEX,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,105,241,77,10
CONTROL "",IDC_LOCAL_ONLY,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
WS_TABSTOP,64,57,11,8
LTEXT "Local Only",IDC_STATIC,76,57,34,8
CONTROL "",IDC_BUILTIN,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
WS_TABSTOP,116,67,11,8
CONTROL "",IDC_VOLATILE,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
WS_TABSTOP,116,57,11,8
LTEXT "Built-In",IDC_STATIC,129,67,22,8
LTEXT "Volatile",IDC_STATIC,129,57,24,8
END
IDD_ABOUT DIALOG 0, 0, 247, 57
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About plResBrowser"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,190,7,50,14
ICON IDI_APPICON,IDC_STATIC,11,8,21,20
LTEXT "plResBrowser\nA simple Plasma 2.0 packfile browsing utility\nCopyright (C) 2002 Cyan Worlds, Inc.\n\nWho needs log files?",
IDC_STATIC,40,7,140,43
END
IDD_FINDOBJ DIALOG 0, 0, 228, 46
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Find Object"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_SEARCHSTRING,13,19,146,14,ES_AUTOHSCROLL
DEFPUSHBUTTON "Find",IDOK,171,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,171,24,50,14
GROUPBOX "Object Name",IDC_STATIC,7,7,157,32
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 240
TOPMARGIN, 7
BOTTOMMARGIN, 50
END
IDD_FINDOBJ, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 221
TOPMARGIN, 7
BOTTOMMARGIN, 39
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_ACCELERATOR1 ACCELERATORS
BEGIN
"F", ID_FILE_FINDOBJECT, VIRTKEY, CONTROL, NOINVERT
VK_F3, ID_FILE_FINDNEXT, VIRTKEY, NOINVERT
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

68
Sources/Tools/plResBrowser/res/resource.h

@ -1,68 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by plResBrowser.rc
//
#define IDI_ICON1 101
#define IDI_APPICON 101
#define IDR_APPMENU 102
#define IDD_INFODLG 103
#define IDD_ABOUT 104
#define IDR_ACCELERATOR1 106
#define IDD_FINDOBJ 107
#define IDI_INDEXICON 108
#define IDI_DATAICON 109
#define IDI_PATCHICON 110
#define IDI_MERGEDDATAICON 111
#define IDI_MERGEDINDEXICON 112
#define IDC_NAME 1000
#define IDC_AGE 1001
#define IDC_CHAPTER 1002
#define IDC_PAGE 1003
#define IDC_LOCATION 1004
#define IDC_RESERVED 1005
#define IDC_CLASS 1006
#define IDC_STARTPOS 1007
#define IDC_LENGTH 1008
#define IDC_CANLOAD 1009
#define IDC_STARTPOS_LABEL 1010
#define IDC_SIZE_LABEL 1011
#define IDC_INTERLEAVED 1012
#define IDC_RELVERSION 1013
#define IDC_SEARCHSTRING 1014
#define IDC_DATAVERSION 1014
#define IDC_IDXCHECKSUM 1015
#define IDC_DATACHECKSUM 1016
#define IDC_CHECKSUMTYPE 1017
#define IDC_SHOWASHEX 1018
#define IDC_SCROLLBAR 1019
#define IDC_PARTIALPATCH 1019
#define IDC_FRAME 1020
#define IDC_HEADERPATCH 1020
#define IDC_COPIED 1021
#define IDC_NEW 1022
#define IDC_ZOOM 1023
#define IDC_ZOOMSLIDER 1024
#define IDC_SEGINFO 1025
#define IDC_LOCAL_ONLY 1025
#define IDC_BUILTIN 1026
#define IDC_VOLATILE 1027
#define ID_FILE_OPEN 40001
#define ID_FILE_EXIT 40002
#define ID_FILE_OPENDIRECTORY 40003
#define ID_FILE_ABOUT 40004
#define ID_FILE_FINDOBJECT 40005
#define ID_FILE_FINDNEXT 40006
#define ID_FILE_VERIFYPAGE 40007
#define ID_FILE_ONLYLOAD 40008
#define ID_FILE_SAVESELECTED 40009
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 110
#define _APS_NEXT_COMMAND_VALUE 40010
#define _APS_NEXT_CONTROL_VALUE 1026
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Loading…
Cancel
Save