Added type filtering to the resource browser
This commit is contained in:
parent
c53352c290
commit
7f9bed653b
|
@ -141,7 +141,7 @@ void CVirtualDirectory::AddChild(const TWideString &rkPath, CResourceEntry *pEnt
|
|||
mSubdirectories.push_back(pSubdir);
|
||||
|
||||
std::sort(mSubdirectories.begin(), mSubdirectories.end(), [](CVirtualDirectory *pLeft, CVirtualDirectory *pRight) -> bool {
|
||||
return (pLeft->Name() < pRight->Name());
|
||||
return (pLeft->Name().ToUpper() < pRight->Name().ToUpper());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,6 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes()
|
|||
CResTypeInfo *pType = new CResTypeInfo(eAnimation, "Animation");
|
||||
AddExtension(pType, "ANIM", ePrimeDemo, eReturns);
|
||||
pType->mRawExtension = "ani";
|
||||
pType->mHidden = true;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimCollisionPrimData, "Animation Collision Primitive Data");
|
||||
|
@ -171,7 +170,6 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes()
|
|||
CResTypeInfo *pType = new CResTypeInfo(eBinaryData, "Generic Data");
|
||||
AddExtension(pType, "DUMB", ePrimeDemo, eCorruption);
|
||||
pType->mRawExtension = "dat";
|
||||
pType->mHidden = true;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eBurstFireData, "Burst Fire Data");
|
||||
|
@ -206,7 +204,6 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes()
|
|||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eHintSystem, "Hint System Data");
|
||||
AddExtension(pType, "HINT", ePrime, eCorruption);
|
||||
pType->mHidden = true;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapArea, "Area Map");
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Editor/CEditorApplication.h"
|
||||
#include <Core/GameProject/AssetNameGeneration.h>
|
||||
#include <Core/GameProject/CAssetNameMap.h>
|
||||
#include <QCheckBox>
|
||||
#include <QFileDialog>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
@ -13,6 +14,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
, mpSelectedEntry(nullptr)
|
||||
, mpStore(gpResourceStore)
|
||||
, mpSelectedDir(nullptr)
|
||||
, mAssetListMode(true)
|
||||
, mSearching(false)
|
||||
{
|
||||
mpUI->setupUi(this);
|
||||
|
@ -35,6 +37,31 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
|
||||
RefreshResources();
|
||||
|
||||
// Set up filter checkboxes
|
||||
mpFilterBoxesLayout = new QVBoxLayout();
|
||||
mpFilterBoxesLayout->setContentsMargins(2, 2, 2, 2);
|
||||
mpFilterBoxesLayout->setSpacing(1);
|
||||
|
||||
mpFilterBoxesContainerWidget = new QWidget(this);
|
||||
mpFilterBoxesContainerWidget->setLayout(mpFilterBoxesLayout);
|
||||
|
||||
mpUI->FilterCheckboxScrollArea->setWidget(mpFilterBoxesContainerWidget);
|
||||
mpUI->FilterCheckboxScrollArea->setBackgroundRole(QPalette::AlternateBase);
|
||||
|
||||
mFilterBoxFont = font();
|
||||
mFilterBoxFont.setPointSize(mFilterBoxFont.pointSize() - 1);
|
||||
|
||||
QFont AllBoxFont = mFilterBoxFont;
|
||||
AllBoxFont.setBold(true);
|
||||
|
||||
mpFilterAllBox = new QCheckBox(this);
|
||||
mpFilterAllBox->setChecked(true);
|
||||
mpFilterAllBox->setFont(AllBoxFont);
|
||||
mpFilterAllBox->setText("All");
|
||||
mpFilterBoxesLayout->addWidget(mpFilterAllBox);
|
||||
|
||||
CreateFilterCheckboxes();
|
||||
|
||||
// Set up Import Names menu
|
||||
QMenu *pImportNamesMenu = new QMenu(this);
|
||||
mpUI->ImportNamesButton->setMenu(pImportNamesMenu);
|
||||
|
@ -53,6 +80,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
// Set up connections
|
||||
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateStore()));
|
||||
connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged()));
|
||||
connect(mpUI->DisplayTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnDisplayModeChanged(int)));
|
||||
connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int)));
|
||||
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex,QModelIndex)));
|
||||
connect(mpUI->ResourceTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnDoubleClickTable(QModelIndex)));
|
||||
|
@ -61,6 +89,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
connect(pImportFromAssetNameMapAction, SIGNAL(triggered()), this, SLOT(OnImportNamesFromAssetNameMap()));
|
||||
connect(mpUI->ExportNamesButton, SIGNAL(clicked()), this, SLOT(ExportAssetNames()));
|
||||
connect(&mUpdateFilterTimer, SIGNAL(timeout()), this, SLOT(UpdateFilter()));
|
||||
connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool)));
|
||||
|
||||
#if !PUBLIC_RELEASE
|
||||
connect(pGenerateAssetNamesAction, SIGNAL(triggered()), this, SLOT(OnGenerateAssetNames()));
|
||||
|
@ -101,10 +130,51 @@ void CResourceBrowser::SelectDirectory(CVirtualDirectory *pDir)
|
|||
mpUI->DirectoryTreeView->selectionModel()->setCurrentIndex(Index, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
|
||||
void CResourceBrowser::CreateFilterCheckboxes()
|
||||
{
|
||||
// Delete existing checkboxes
|
||||
foreach (const SResourceType& rkType, mTypeList)
|
||||
delete rkType.pFilterCheckBox;
|
||||
|
||||
mTypeList.clear();
|
||||
|
||||
// No store - leave empty
|
||||
if (!mpStore) return;
|
||||
|
||||
// Get new type list
|
||||
std::list<CResTypeInfo*> TypeList;
|
||||
CResTypeInfo::GetAllTypesInGame(mpStore->Game(), TypeList);
|
||||
|
||||
for (auto Iter = TypeList.begin(); Iter != TypeList.end(); Iter++)
|
||||
{
|
||||
CResTypeInfo *pType = *Iter;
|
||||
|
||||
if (pType->IsVisibleInBrowser())
|
||||
{
|
||||
QCheckBox *pCheck = new QCheckBox(this);
|
||||
pCheck->setFont(mFilterBoxFont);
|
||||
pCheck->setText(TO_QSTRING(pType->TypeName()));
|
||||
mTypeList << SResourceType { pType, pCheck };
|
||||
}
|
||||
}
|
||||
|
||||
qSort(mTypeList.begin(), mTypeList.end(), [](const SResourceType& rkLeft, const SResourceType& rkRight) -> bool {
|
||||
return rkLeft.pTypeInfo->TypeName().ToUpper() < rkRight.pTypeInfo->TypeName().ToUpper();
|
||||
});
|
||||
|
||||
// Add sorted checkboxes to the UI
|
||||
foreach (const SResourceType& rkType, mTypeList)
|
||||
{
|
||||
QCheckBox *pCheck = rkType.pFilterCheckBox;
|
||||
mpFilterBoxesLayout->addWidget(rkType.pFilterCheckBox);
|
||||
connect(pCheck, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool)));
|
||||
}
|
||||
}
|
||||
|
||||
void CResourceBrowser::RefreshResources()
|
||||
{
|
||||
// Fill resource table
|
||||
mpModel->FillEntryList(mpSelectedDir, mSearching);
|
||||
mpModel->FillEntryList(mpSelectedDir, InAssetListMode());
|
||||
|
||||
// Mark directories to span all three columns
|
||||
mpUI->ResourceTableView->clearSpans();
|
||||
|
@ -116,6 +186,8 @@ void CResourceBrowser::RefreshResources()
|
|||
void CResourceBrowser::UpdateDescriptionLabel()
|
||||
{
|
||||
QString Desc;
|
||||
Desc += (mAssetListMode ? "[Assets]" : "[Filesystem]");
|
||||
Desc += " ";
|
||||
|
||||
bool ValidDir = mpSelectedDir && !mpSelectedDir->IsRoot();
|
||||
QString Path = (ValidDir ? '\\' + TO_QSTRING(mpSelectedDir->FullPath()) : "");
|
||||
|
@ -123,7 +195,7 @@ void CResourceBrowser::UpdateDescriptionLabel()
|
|||
if (mSearching)
|
||||
{
|
||||
QString SearchText = mpUI->SearchBar->text();
|
||||
Desc = QString("Searching \"%1\"").arg(SearchText);
|
||||
Desc += QString("Searching \"%1\"").arg(SearchText);
|
||||
|
||||
if (ValidDir)
|
||||
Desc += QString(" in %1").arg(Path);
|
||||
|
@ -131,7 +203,9 @@ void CResourceBrowser::UpdateDescriptionLabel()
|
|||
else
|
||||
{
|
||||
if (ValidDir)
|
||||
Desc = Path;
|
||||
Desc += Path;
|
||||
else
|
||||
Desc += "Root";
|
||||
}
|
||||
|
||||
mpUI->TableDescriptionLabel->setText(Desc);
|
||||
|
@ -146,6 +220,9 @@ void CResourceBrowser::UpdateStore()
|
|||
{
|
||||
mpStore = pNewStore;
|
||||
|
||||
// Refresh type filter list
|
||||
CreateFilterCheckboxes();
|
||||
|
||||
// Refresh directory tree
|
||||
mpDirectoryModel->SetRoot(mpStore ? mpStore->RootDirectory() : nullptr);
|
||||
QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex());
|
||||
|
@ -155,6 +232,15 @@ void CResourceBrowser::UpdateStore()
|
|||
}
|
||||
}
|
||||
|
||||
void CResourceBrowser::OnDisplayModeChanged(int Index)
|
||||
{
|
||||
bool OldIsAssetList = InAssetListMode();
|
||||
mAssetListMode = Index == 0;
|
||||
|
||||
if (InAssetListMode() != OldIsAssetList)
|
||||
RefreshResources();
|
||||
}
|
||||
|
||||
void CResourceBrowser::OnSortModeChanged(int Index)
|
||||
{
|
||||
CResourceProxyModel::ESortMode Mode = (Index == 0 ? CResourceProxyModel::eSortByName : CResourceProxyModel::eSortBySize);
|
||||
|
@ -251,15 +337,60 @@ void CResourceBrowser::ExportAssetNames()
|
|||
|
||||
void CResourceBrowser::UpdateFilter()
|
||||
{
|
||||
bool OldIsAssetList = InAssetListMode();
|
||||
QString SearchText = mpUI->SearchBar->text();
|
||||
bool NewSearching = !SearchText.isEmpty();
|
||||
mSearching = !SearchText.isEmpty();
|
||||
|
||||
if (mSearching != NewSearching)
|
||||
if (InAssetListMode() != OldIsAssetList)
|
||||
{
|
||||
mSearching = NewSearching;
|
||||
RefreshResources();
|
||||
}
|
||||
|
||||
UpdateDescriptionLabel();
|
||||
mpProxyModel->SetSearchString( TO_TWIDESTRING(mpUI->SearchBar->text()) );
|
||||
mpProxyModel->invalidate();
|
||||
}
|
||||
|
||||
void CResourceBrowser::ResetTypeFilter()
|
||||
{
|
||||
mpFilterAllBox->setChecked(true);
|
||||
}
|
||||
|
||||
void CResourceBrowser::OnFilterTypeBoxTicked(bool Checked)
|
||||
{
|
||||
static bool ReentrantGuard = false;
|
||||
if (ReentrantGuard) return;
|
||||
ReentrantGuard = true;
|
||||
|
||||
if (sender() == mpFilterAllBox)
|
||||
{
|
||||
if (!Checked && !mpProxyModel->HasTypeFilter())
|
||||
mpFilterAllBox->setChecked(true);
|
||||
|
||||
else if (Checked)
|
||||
{
|
||||
foreach (const SResourceType& rkType, mTypeList)
|
||||
{
|
||||
rkType.pFilterCheckBox->setChecked(false);
|
||||
mpProxyModel->SetTypeFilter(rkType.pTypeInfo, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
foreach (const SResourceType& rkType, mTypeList)
|
||||
{
|
||||
if (rkType.pFilterCheckBox == sender())
|
||||
{
|
||||
mpProxyModel->SetTypeFilter(rkType.pTypeInfo, Checked);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mpFilterAllBox->setChecked(!mpProxyModel->HasTypeFilter());
|
||||
}
|
||||
|
||||
mpProxyModel->invalidate();
|
||||
ReentrantGuard = false;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
#include "CResourceProxyModel.h"
|
||||
#include "CResourceTableModel.h"
|
||||
#include "CVirtualDirectoryModel.h"
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace Ui {
|
||||
class CResourceBrowser;
|
||||
|
@ -22,21 +24,39 @@ class CResourceBrowser : public QDialog
|
|||
CVirtualDirectory *mpSelectedDir;
|
||||
CVirtualDirectoryModel *mpDirectoryModel;
|
||||
QTimer mUpdateFilterTimer;
|
||||
bool mAssetListMode;
|
||||
bool mSearching;
|
||||
|
||||
// Type Filter
|
||||
QWidget *mpFilterBoxesContainerWidget;
|
||||
QVBoxLayout *mpFilterBoxesLayout;
|
||||
QCheckBox *mpFilterAllBox;
|
||||
QFont mFilterBoxFont;
|
||||
|
||||
struct SResourceType
|
||||
{
|
||||
CResTypeInfo *pTypeInfo;
|
||||
QCheckBox *pFilterCheckBox;
|
||||
};
|
||||
QList<SResourceType> mTypeList;
|
||||
|
||||
public:
|
||||
explicit CResourceBrowser(QWidget *pParent = 0);
|
||||
~CResourceBrowser();
|
||||
|
||||
void SelectResource(CResourceEntry *pEntry);
|
||||
void SelectDirectory(CVirtualDirectory *pDir);
|
||||
void CreateFilterCheckboxes();
|
||||
|
||||
// Accessors
|
||||
inline CResourceEntry* SelectedEntry() const { return mpSelectedEntry; }
|
||||
inline bool InAssetListMode() const { return mAssetListMode || mSearching; }
|
||||
|
||||
public slots:
|
||||
void RefreshResources();
|
||||
void UpdateDescriptionLabel();
|
||||
void UpdateStore();
|
||||
void OnDisplayModeChanged(int Index);
|
||||
void OnSortModeChanged(int Index);
|
||||
void OnSearchStringChanged();
|
||||
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
|
||||
|
@ -48,6 +68,9 @@ public slots:
|
|||
void ExportAssetNames();
|
||||
void UpdateFilter();
|
||||
|
||||
void ResetTypeFilter();
|
||||
void OnFilterTypeBoxTicked(bool Checked);
|
||||
|
||||
signals:
|
||||
void SelectedResourceChanged(CResourceEntry *pNewRes);
|
||||
};
|
||||
|
|
|
@ -79,6 +79,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="DisplayTypeComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Asset List</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Filesystem</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="SortComboBox">
|
||||
<property name="sizePolicy">
|
||||
|
@ -99,8 +113,37 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="FilterCheckboxScrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>189</width>
|
||||
<height>128</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="DirectoryTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>2</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define CRESOURCEPROXYMODEL
|
||||
|
||||
#include "CResourceTableModel.h"
|
||||
#include <QSet>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class CResourceProxyModel : public QSortFilterProxyModel
|
||||
|
@ -16,15 +17,14 @@ public:
|
|||
|
||||
private:
|
||||
CResourceTableModel *mpModel;
|
||||
CVirtualDirectory *mpDirectory;
|
||||
TWideString mSearchString;
|
||||
ESortMode mSortMode;
|
||||
QSet<CResTypeInfo*> mTypeFilter;
|
||||
|
||||
public:
|
||||
explicit CResourceProxyModel(QObject *pParent = 0)
|
||||
: QSortFilterProxyModel(pParent)
|
||||
, mpModel(nullptr)
|
||||
, mpDirectory(nullptr)
|
||||
{
|
||||
SetSortMode(eSortByName);
|
||||
}
|
||||
|
@ -66,6 +66,9 @@ public:
|
|||
CVirtualDirectory *pDir = mpModel->IndexDirectory(Index);
|
||||
CResourceEntry *pEntry = mpModel->IndexEntry(Index);
|
||||
|
||||
if (pEntry && HasTypeFilter() && !mTypeFilter.contains(pEntry->TypeInfo()))
|
||||
return false;
|
||||
|
||||
if (!mSearchString.IsEmpty())
|
||||
{
|
||||
if (pDir)
|
||||
|
@ -77,6 +80,24 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
inline void SetTypeFilter(CResTypeInfo *pInfo, bool Allow)
|
||||
{
|
||||
if (Allow)
|
||||
mTypeFilter.insert(pInfo);
|
||||
else
|
||||
mTypeFilter.remove(pInfo);
|
||||
}
|
||||
|
||||
inline void ClearTypeFilter()
|
||||
{
|
||||
mTypeFilter.clear();
|
||||
}
|
||||
|
||||
inline bool HasTypeFilter() const
|
||||
{
|
||||
return !mTypeFilter.isEmpty();
|
||||
}
|
||||
|
||||
inline void SetSortMode(ESortMode Mode)
|
||||
{
|
||||
if (mSortMode != Mode)
|
||||
|
@ -86,17 +107,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
inline void SetDirectory(CVirtualDirectory *pDir)
|
||||
{
|
||||
mpDirectory = pDir;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetSearchString(const TWideString& rkString)
|
||||
{
|
||||
mSearchString = rkString.ToUpper();
|
||||
invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
return rkIndex.row() < mDirectories.size();
|
||||
}
|
||||
|
||||
void FillEntryList(CVirtualDirectory *pDir, bool IsSearching)
|
||||
void FillEntryList(CVirtualDirectory *pDir, bool AssetListMode)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
|
@ -126,8 +126,8 @@ public:
|
|||
|
||||
if (pDir)
|
||||
{
|
||||
// When not searching, show only subdirectories and assets in the current directory.
|
||||
if (!IsSearching)
|
||||
// In filesystem mode, show only subdirectories and assets in the current directory.
|
||||
if (!AssetListMode)
|
||||
{
|
||||
if (!pDir->IsRoot())
|
||||
{
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// When searching, do not show subdirectories and show all assets in current directory + all subdirectories.
|
||||
// In asset list mode, do not show subdirectories and show all assets in current directory + all subdirectories.
|
||||
else
|
||||
RecursiveAddDirectoryContents(pDir);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue