Added ability to display referencers/dependencies of assets

This commit is contained in:
Aruki 2017-07-20 20:56:29 -06:00
parent 905173a0a0
commit 89d668a810
14 changed files with 363 additions and 79 deletions

View File

@ -25,6 +25,12 @@ bool IDependencyNode::HasDependency(const CAssetID& rkID) const
return false; return false;
} }
void IDependencyNode::GetAllResourceReferences(std::set<CAssetID>& rOutSet) const
{
for (u32 iChild = 0; iChild < mChildren.size(); iChild++)
mChildren[iChild]->GetAllResourceReferences(rOutSet);
}
// ************ CDependencyTree ************ // ************ CDependencyTree ************
EDependencyNodeType CDependencyTree::Type() const EDependencyNodeType CDependencyTree::Type() const
{ {
@ -75,6 +81,11 @@ void CResourceDependency::Serialize(IArchive& rArc)
rArc << SERIAL("ID", mID); rArc << SERIAL("ID", mID);
} }
void CResourceDependency::GetAllResourceReferences(std::set<CAssetID>& rOutSet) const
{
rOutSet.insert(mID);
}
bool CResourceDependency::HasDependency(const CAssetID& rkID) const bool CResourceDependency::HasDependency(const CAssetID& rkID) const
{ {
return (mID == rkID); return (mID == rkID);

View File

@ -37,6 +37,7 @@ public:
virtual ~IDependencyNode(); virtual ~IDependencyNode();
virtual EDependencyNodeType Type() const = 0; virtual EDependencyNodeType Type() const = 0;
virtual void Serialize(IArchive& rArc) = 0; virtual void Serialize(IArchive& rArc) = 0;
virtual void GetAllResourceReferences(std::set<CAssetID>& rOutSet) const;
virtual bool HasDependency(const CAssetID& rkID) const; virtual bool HasDependency(const CAssetID& rkID) const;
// Accessors // Accessors
@ -71,6 +72,7 @@ public:
virtual EDependencyNodeType Type() const; virtual EDependencyNodeType Type() const;
virtual void Serialize(IArchive& rArc); virtual void Serialize(IArchive& rArc);
virtual void GetAllResourceReferences(std::set<CAssetID>& rOutSet) const;
virtual bool HasDependency(const CAssetID& rkID) const; virtual bool HasDependency(const CAssetID& rkID) const;
// Accessors // Accessors

View File

@ -78,6 +78,17 @@ TString CWorld::AreaInGameName(u32 AreaIndex) const
return "!!" + rkArea.InternalName; return "!!" + rkArea.InternalName;
} }
u32 CWorld::AreaIndex(CAssetID AreaID) const
{
for (u32 AreaIdx = 0; AreaIdx < mAreas.size(); AreaIdx++)
{
if (mAreas[AreaIdx].AreaResID == AreaID)
return AreaIdx;
}
return -1;
}
// ************ SERIALIZATION ************ // ************ SERIALIZATION ************
void CWorld::Serialize(IArchive& rArc) void CWorld::Serialize(IArchive& rArc)
{ {

View File

@ -94,6 +94,7 @@ public:
void SetAreaLayerInfo(CGameArea *pArea); void SetAreaLayerInfo(CGameArea *pArea);
TString InGameName() const; TString InGameName() const;
TString AreaInGameName(u32 AreaIndex) const; TString AreaInGameName(u32 AreaIndex) const;
u32 AreaIndex(CAssetID AreaID) const;
// Serialization // Serialization
virtual void Serialize(IArchive& rArc); virtual void Serialize(IArchive& rArc);

View File

@ -127,6 +127,24 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
switch (pEntry->ResourceType()) switch (pEntry->ResourceType())
{ {
case eArea:
// We can't open an area on its own. Find a world that contains this area.
for (TResourceIterator<eWorld> It; It; ++It)
{
if (It->Dependencies()->HasDependency(pEntry->ID()))
{
CWorld *pWorld = (CWorld*) It->Load();
u32 AreaIdx = pWorld->AreaIndex(pEntry->ID());
if (AreaIdx != -1)
{
mpWorldEditor->SetArea(pWorld, AreaIdx);
break;
}
}
}
break;
case eModel: case eModel:
pEd = new CModelEditorWindow((CModel*) pRes, mpWorldEditor); pEd = new CModelEditorWindow((CModel*) pRes, mpWorldEditor);
break; break;
@ -141,7 +159,7 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
pEd->show(); pEd->show();
mEditingMap[pEntry] = pEd; mEditingMap[pEntry] = pEd;
} }
else else if (pEntry->ResourceType() != eArea)
UICommon::InfoMsg(mpWorldEditor, "Unsupported Resource", "This resource type is currently unsupported for editing."); UICommon::InfoMsg(mpWorldEditor, "Unsupported Resource", "This resource type is currently unsupported for editing.");
} }
} }

View File

@ -27,6 +27,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
, mEditorStore(false) , mEditorStore(false)
, mAssetListMode(false) , mAssetListMode(false)
, mSearching(false) , mSearching(false)
, mpInspectedEntry(nullptr)
{ {
mpUI->setupUi(this); mpUI->setupUi(this);
@ -70,6 +71,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
mpUI->DirectoryTreeView->setModel(mpDirectoryModel); mpUI->DirectoryTreeView->setModel(mpDirectoryModel);
RefreshResources(); RefreshResources();
UpdateDescriptionLabel();
// Set up filter checkboxes // Set up filter checkboxes
mpFilterBoxesLayout = new QVBoxLayout(); mpFilterBoxesLayout = new QVBoxLayout();
@ -142,9 +144,12 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
connect(mpUI->ResourceListButton, SIGNAL(pressed()), this, SLOT(SetResourceListView())); connect(mpUI->ResourceListButton, SIGNAL(pressed()), this, SLOT(SetResourceListView()));
connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int))); connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int)));
connect(mpUI->NewFolderButton, SIGNAL(pressed()), this, SLOT(CreateDirectory())); connect(mpUI->NewFolderButton, SIGNAL(pressed()), this, SLOT(CreateDirectory()));
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex,QModelIndex))); connect(mpUI->ClearButton, SIGNAL(pressed()), this, SLOT(OnClearButtonPressed()));
connect(mpUI->DirectoryTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex)));
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex)));
connect(mpUI->ResourceTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnDoubleClickTable(QModelIndex))); connect(mpUI->ResourceTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnDoubleClickTable(QModelIndex)));
connect(mpUI->ResourceTableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnResourceSelectionChanged(QModelIndex, QModelIndex))); connect(mpUI->ResourceTableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnResourceSelectionChanged(QModelIndex)));
connect(mpProxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), mpUI->ResourceTableView, SLOT(resizeRowsToContents())); connect(mpProxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), mpUI->ResourceTableView, SLOT(resizeRowsToContents()));
connect(mpProxyModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), mpUI->ResourceTableView, SLOT(resizeRowsToContents())); connect(mpProxyModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), mpUI->ResourceTableView, SLOT(resizeRowsToContents()));
connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool))); connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool)));
@ -156,12 +161,28 @@ CResourceBrowser::~CResourceBrowser()
delete mpUI; delete mpUI;
} }
void CResourceBrowser::SetActiveDirectory(CVirtualDirectory *pDir)
{
if (mpSelectedDir != pDir || mpModel->IsDisplayingUserEntryList())
{
mpSelectedDir = pDir;
RefreshResources();
UpdateDescriptionLabel();
if (sender() != mpUI->DirectoryTreeView)
{
QModelIndex Index = mpDirectoryModel->GetIndexForDirectory(pDir);
mpUI->DirectoryTreeView->selectionModel()->setCurrentIndex(Index, QItemSelectionModel::ClearAndSelect);
}
}
}
void CResourceBrowser::SelectResource(CResourceEntry *pEntry) void CResourceBrowser::SelectResource(CResourceEntry *pEntry)
{ {
ASSERT(pEntry); ASSERT(pEntry);
// Select target directory // Set directory active
SelectDirectory(pEntry->Directory()); SetActiveDirectory(pEntry->Directory());
// Clear search // Clear search
if (!mpUI->SearchBar->text().isEmpty()) if (!mpUI->SearchBar->text().isEmpty())
@ -173,14 +194,37 @@ void CResourceBrowser::SelectResource(CResourceEntry *pEntry)
// Select resource // Select resource
QModelIndex SourceIndex = mpModel->GetIndexForEntry(pEntry); QModelIndex SourceIndex = mpModel->GetIndexForEntry(pEntry);
QModelIndex ProxyIndex = mpProxyModel->mapFromSource(SourceIndex); QModelIndex ProxyIndex = mpProxyModel->mapFromSource(SourceIndex);
mpUI->ResourceTableView->selectionModel()->select(ProxyIndex, QItemSelectionModel::ClearAndSelect);
mpUI->ResourceTableView->scrollTo(ProxyIndex, QAbstractItemView::PositionAtCenter); if (ProxyIndex.isValid())
{
// Note: We have to call scrollToBottom() first or else sometimes scrollTo() doesn't work at all
// in large folders (like Uncategorized). Dumb but the only solution I've been able to figure out.
mpUI->ResourceTableView->selectionModel()->select(ProxyIndex, QItemSelectionModel::ClearAndSelect);
mpUI->ResourceTableView->scrollToBottom();
mpUI->ResourceTableView->scrollTo(ProxyIndex, QAbstractItemView::PositionAtCenter);
}
} }
void CResourceBrowser::SelectDirectory(CVirtualDirectory *pDir) void CResourceBrowser::SelectDirectory(CVirtualDirectory *pDir)
{ {
QModelIndex Index = mpDirectoryModel->GetIndexForDirectory(pDir); ASSERT(pDir);
mpUI->DirectoryTreeView->selectionModel()->setCurrentIndex(Index, QItemSelectionModel::ClearAndSelect); ASSERT(!pDir->IsRoot());
// Set parent directory active
SetActiveDirectory(pDir->Parent());
// Clear search
if (!mpUI->SearchBar->text().isEmpty())
{
mpUI->SearchBar->clear();
UpdateFilter();
}
// Select directory
QModelIndex SourceIndex = mpModel->GetIndexForDirectory(pDir);
QModelIndex ProxyIndex = mpProxyModel->mapFromSource(SourceIndex);
mpUI->ResourceTableView->selectionModel()->select(ProxyIndex, QItemSelectionModel::ClearAndSelect);
mpUI->ResourceTableView->scrollTo(ProxyIndex, QAbstractItemView::PositionAtCenter);
} }
void CResourceBrowser::CreateFilterCheckboxes() void CResourceBrowser::CreateFilterCheckboxes()
@ -353,30 +397,27 @@ void CResourceBrowser::RefreshDirectories()
void CResourceBrowser::UpdateDescriptionLabel() void CResourceBrowser::UpdateDescriptionLabel()
{ {
// Update main description label
QString Desc; QString Desc;
Desc += (mAssetListMode ? "[Assets]" : "[Filesystem]");
Desc += " ";
bool ValidDir = mpSelectedDir && !mpSelectedDir->IsRoot(); if (mpStore)
QString Path = (ValidDir ? '/' + TO_QSTRING(mpSelectedDir->FullPath()) : "");
if (mSearching)
{ {
QString SearchText = mpUI->SearchBar->text(); QString ModelDesc = mpModel->ModelDescription();
Desc += QString("Searching \"%1\"").arg(SearchText);
if (ValidDir) if (mSearching)
Desc += QString(" in %1").arg(Path); {
} QString SearchText = mpUI->SearchBar->text();
else Desc = QString("Searching \"%1\" in: %2").arg(SearchText).arg(ModelDesc);
{ }
if (ValidDir)
Desc += Path;
else else
Desc += "Root"; Desc = QString("Displaying: %1").arg(ModelDesc);
} }
mpUI->TableDescriptionLabel->setText(Desc); mpUI->TableDescriptionLabel->setText(Desc);
// Update clear button status
bool EnableClearButton = (!mpUI->SearchBar->text().isEmpty() || mpModel->IsDisplayingUserEntryList() || (mpSelectedDir && !mpSelectedDir->IsRoot()));
mpUI->ClearButton->setEnabled(EnableClearButton);
} }
void CResourceBrowser::SetResourceTreeView() void CResourceBrowser::SetResourceTreeView()
@ -391,6 +432,30 @@ void CResourceBrowser::SetResourceListView()
RefreshResources(); RefreshResources();
} }
void CResourceBrowser::OnClearButtonPressed()
{
if (!mpUI->SearchBar->text().isEmpty())
{
ResetSearch();
}
else if (mpModel->IsDisplayingUserEntryList())
{
RefreshResources();
if (mpInspectedEntry)
{
SelectResource(mpInspectedEntry);
mpInspectedEntry = nullptr;
}
}
else
{
SelectDirectory(mpSelectedDir);
}
UpdateDescriptionLabel();
}
void CResourceBrowser::OnSortModeChanged(int Index) void CResourceBrowser::OnSortModeChanged(int Index)
{ {
CResourceProxyModel::ESortMode Mode = (Index == 0 ? CResourceProxyModel::eSortByName : CResourceProxyModel::eSortBySize); CResourceProxyModel::ESortMode Mode = (Index == 0 ? CResourceProxyModel::eSortByName : CResourceProxyModel::eSortBySize);
@ -461,31 +526,29 @@ bool CResourceBrowser::DeleteDirectories(const QList<CVirtualDirectory*>& rkDirs
void CResourceBrowser::OnSearchStringChanged(QString SearchString) void CResourceBrowser::OnSearchStringChanged(QString SearchString)
{ {
bool WasSearching = mSearching; bool WasAssetList = InAssetListMode();
mSearching = !SearchString.isEmpty(); mSearching = !SearchString.isEmpty();
bool IsAssetList = InAssetListMode();
// Check if we need to change to/from asset list mode to display/stop displaying search results // Check if we need to change to/from asset list mode to display/stop displaying search results
if (!mAssetListMode) if (WasAssetList != IsAssetList)
{ {
if ( (mSearching && !WasSearching) || RefreshResources();
(!mSearching && WasSearching) )
{
RefreshResources();
}
} }
UpdateFilter(); UpdateFilter();
} }
void CResourceBrowser::OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/) void CResourceBrowser::OnDirectorySelectionChanged(const QModelIndex& rkNewIndex)
{ {
if (rkNewIndex.isValid()) CVirtualDirectory *pDir = nullptr;
mpSelectedDir = mpDirectoryModel->IndexDirectory(rkNewIndex);
else
mpSelectedDir = mpStore ? mpStore->RootDirectory() : nullptr;
UpdateDescriptionLabel(); if (rkNewIndex.isValid())
RefreshResources(); pDir = mpDirectoryModel->IndexDirectory(rkNewIndex);
else
pDir = mpStore ? mpStore->RootDirectory() : nullptr;
SetActiveDirectory(pDir);
} }
void CResourceBrowser::OnDoubleClickTable(QModelIndex Index) void CResourceBrowser::OnDoubleClickTable(QModelIndex Index)
@ -496,7 +559,11 @@ void CResourceBrowser::OnDoubleClickTable(QModelIndex Index)
if (mpModel->IsIndexDirectory(SourceIndex)) if (mpModel->IsIndexDirectory(SourceIndex))
{ {
CVirtualDirectory *pDir = mpModel->IndexDirectory(SourceIndex); CVirtualDirectory *pDir = mpModel->IndexDirectory(SourceIndex);
SelectDirectory(pDir); CVirtualDirectory *pOldDir = mpSelectedDir;
SetActiveDirectory(pDir);
if (pOldDir->Parent() == pDir)
SelectDirectory(pOldDir);
} }
// Resource - open resource for editing // Resource - open resource for editing
@ -507,7 +574,7 @@ void CResourceBrowser::OnDoubleClickTable(QModelIndex Index)
} }
} }
void CResourceBrowser::OnResourceSelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/) void CResourceBrowser::OnResourceSelectionChanged(const QModelIndex& rkNewIndex)
{ {
QModelIndex SourceIndex = mpProxyModel->mapToSource(rkNewIndex); QModelIndex SourceIndex = mpProxyModel->mapToSource(rkNewIndex);
mpSelectedEntry = mpModel->IndexEntry(SourceIndex); mpSelectedEntry = mpModel->IndexEntry(SourceIndex);
@ -542,7 +609,7 @@ void CResourceBrowser::UpdateStore()
QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex()); QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex());
mpUI->DirectoryTreeView->expand(RootIndex); mpUI->DirectoryTreeView->expand(RootIndex);
mpUI->DirectoryTreeView->clearSelection(); mpUI->DirectoryTreeView->clearSelection();
OnDirectorySelectionChanged(QModelIndex(), QModelIndex()); OnDirectorySelectionChanged(QModelIndex());
} }
} }
@ -562,7 +629,7 @@ void CResourceBrowser::ImportPackageContentsList()
{ {
QStringList PathList = UICommon::OpenFilesDialog(this, "Open package contents list", "*.pak.contents.txt"); QStringList PathList = UICommon::OpenFilesDialog(this, "Open package contents list", "*.pak.contents.txt");
if (PathList.isEmpty()) return; if (PathList.isEmpty()) return;
SelectDirectory(nullptr); SetActiveDirectory(nullptr);
foreach(const QString& rkPath, PathList) foreach(const QString& rkPath, PathList)
mpStore->ImportNamesFromPakContentsTxt(TO_TSTRING(rkPath), false); mpStore->ImportNamesFromPakContentsTxt(TO_TSTRING(rkPath), false);
@ -573,7 +640,7 @@ void CResourceBrowser::ImportPackageContentsList()
void CResourceBrowser::GenerateAssetNames() void CResourceBrowser::GenerateAssetNames()
{ {
SelectDirectory(nullptr); SetActiveDirectory(nullptr);
CProgressDialog Dialog("Generating asset names", true, true, this); CProgressDialog Dialog("Generating asset names", true, true, this);
Dialog.DisallowCanceling(); Dialog.DisallowCanceling();
@ -607,7 +674,7 @@ void CResourceBrowser::ImportAssetNameMap()
return; return;
} }
SelectDirectory(nullptr); SetActiveDirectory(nullptr);
for (CResourceIterator It(mpStore); It; ++It) for (CResourceIterator It(mpStore); It; ++It)
{ {
@ -660,19 +727,29 @@ void CResourceBrowser::RebuildResourceDB()
} }
} }
void CResourceBrowser::UpdateFilter() void CResourceBrowser::ClearFilters()
{ {
QString SearchText = mpUI->SearchBar->text(); ResetSearch();
mSearching = !SearchText.isEmpty(); ResetTypeFilter();
}
UpdateDescriptionLabel(); void CResourceBrowser::ResetSearch()
mpProxyModel->SetSearchString( TO_TSTRING(mpUI->SearchBar->text()) ); {
mpProxyModel->invalidate(); bool WasAssetList = InAssetListMode();
mpUI->SearchBar->clear();
mSearching = false;
bool IsAssetList = InAssetListMode();
if (IsAssetList != WasAssetList)
RefreshResources();
UpdateFilter();
} }
void CResourceBrowser::ResetTypeFilter() void CResourceBrowser::ResetTypeFilter()
{ {
mpFilterAllBox->setChecked(true); mpFilterAllBox->setChecked(true);
UpdateFilter();
} }
void CResourceBrowser::OnFilterTypeBoxTicked(bool Checked) void CResourceBrowser::OnFilterTypeBoxTicked(bool Checked)
@ -715,6 +792,16 @@ void CResourceBrowser::OnFilterTypeBoxTicked(bool Checked)
ReentrantGuard = false; ReentrantGuard = false;
} }
void CResourceBrowser::UpdateFilter()
{
QString SearchText = mpUI->SearchBar->text();
mSearching = !SearchText.isEmpty();
UpdateDescriptionLabel();
mpProxyModel->SetSearchString( TO_TSTRING(mpUI->SearchBar->text()) );
mpProxyModel->invalidate();
}
void CResourceBrowser::UpdateUndoActionStates() void CResourceBrowser::UpdateUndoActionStates()
{ {
// Make sure that the undo actions are only enabled when the table view has focus. // Make sure that the undo actions are only enabled when the table view has focus.

View File

@ -48,10 +48,14 @@ class CResourceBrowser : public QWidget
QAction *mpRedoAction; QAction *mpRedoAction;
QWidget *mpActionContainerWidget; QWidget *mpActionContainerWidget;
// Misc
CResourceEntry *mpInspectedEntry; // Entry being "inspected" (viewing dependencies/referencers, etc)
public: public:
explicit CResourceBrowser(QWidget *pParent = 0); explicit CResourceBrowser(QWidget *pParent = 0);
~CResourceBrowser(); ~CResourceBrowser();
void SetActiveDirectory(CVirtualDirectory *pDir);
void SelectResource(CResourceEntry *pEntry); void SelectResource(CResourceEntry *pEntry);
void SelectDirectory(CVirtualDirectory *pDir); void SelectDirectory(CVirtualDirectory *pDir);
void CreateFilterCheckboxes(); void CreateFilterCheckboxes();
@ -66,7 +70,9 @@ public:
// Accessors // Accessors
inline CResourceStore* CurrentStore() const { return mpStore; } inline CResourceStore* CurrentStore() const { return mpStore; }
inline CResourceEntry* SelectedEntry() const { return mpSelectedEntry; } inline CResourceEntry* SelectedEntry() const { return mpSelectedEntry; }
inline bool InAssetListMode() const { return mAssetListMode || mSearching; } inline bool InAssetListMode() const { return mAssetListMode || mSearching || mpModel->IsDisplayingUserEntryList(); }
inline void SetInspectedEntry(CResourceEntry *pEntry) { mpInspectedEntry = pEntry; }
public slots: public slots:
void RefreshResources(); void RefreshResources();
@ -74,13 +80,14 @@ public slots:
void UpdateDescriptionLabel(); void UpdateDescriptionLabel();
void SetResourceTreeView(); void SetResourceTreeView();
void SetResourceListView(); void SetResourceListView();
void OnClearButtonPressed();
void OnSortModeChanged(int Index); void OnSortModeChanged(int Index);
bool CreateDirectory(); bool CreateDirectory();
bool DeleteDirectories(const QList<CVirtualDirectory*>& rkDirs); bool DeleteDirectories(const QList<CVirtualDirectory*>& rkDirs);
void OnSearchStringChanged(QString SearchString); void OnSearchStringChanged(QString SearchString);
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex); void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex);
void OnDoubleClickTable(QModelIndex Index); void OnDoubleClickTable(QModelIndex Index);
void OnResourceSelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex); void OnResourceSelectionChanged(const QModelIndex& rkNewIndex);
void SetAssetIdDisplayEnabled(bool Enable); void SetAssetIdDisplayEnabled(bool Enable);
void UpdateStore(); void UpdateStore();
@ -91,10 +98,12 @@ public slots:
void ImportAssetNameMap(); void ImportAssetNameMap();
void ExportAssetNames(); void ExportAssetNames();
void RebuildResourceDB(); void RebuildResourceDB();
void UpdateFilter();
void ClearFilters();
void ResetSearch();
void ResetTypeFilter(); void ResetTypeFilter();
void OnFilterTypeBoxTicked(bool Checked); void OnFilterTypeBoxTicked(bool Checked);
void UpdateFilter();
void UpdateUndoActionStates(); void UpdateUndoActionStates();
void Undo(); void Undo();

View File

@ -180,22 +180,43 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="TableDescriptionLabel"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <widget class="QLabel" name="TableDescriptionLabel">
<horstretch>0</horstretch> <property name="sizePolicy">
<verstretch>0</verstretch> <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
</sizepolicy> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<property name="font"> </sizepolicy>
<font> </property>
<pointsize>8</pointsize> <property name="font">
</font> <font>
</property> <pointsize>8</pointsize>
<property name="text"> </font>
<string/> </property>
</property> <property name="text">
</widget> <string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ClearButton">
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/X_16px.png</normaloff>:/icons/X_16px.png</iconset>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<widget class="QSplitter" name="splitter"> <widget class="QSplitter" name="splitter">
@ -227,7 +248,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>209</width> <width>209</width>
<height>190</height> <height>187</height>
</rect> </rect>
</property> </property>
</widget> </widget>

View File

@ -39,6 +39,17 @@ public:
bool lessThan(const QModelIndex& rkLeft, const QModelIndex& rkRight) const bool lessThan(const QModelIndex& rkLeft, const QModelIndex& rkRight) const
{ {
// Parent directory is always row 0 and should always be at the top
if (mpModel->HasParentDirectoryEntry())
{
if (rkLeft.row() == 0)
return true;
if (rkRight.row() == 0)
return false;
}
// Fetch directories and compare them
CVirtualDirectory *pLeftDir = mpModel->IndexDirectory(rkLeft); CVirtualDirectory *pLeftDir = mpModel->IndexDirectory(rkLeft);
CVirtualDirectory *pRightDir = mpModel->IndexDirectory(rkRight); CVirtualDirectory *pRightDir = mpModel->IndexDirectory(rkRight);
CResourceEntry *pLeftRes = mpModel->IndexEntry(rkLeft); CResourceEntry *pLeftRes = mpModel->IndexEntry(rkLeft);

View File

@ -16,11 +16,22 @@ CResourceTableContextMenu::CResourceTableContextMenu(CResourceBrowser *pBrowser,
connect(pView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(ShowMenu(QPoint))); connect(pView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(ShowMenu(QPoint)));
// Create actions // Create actions
#if WIN32
QString OpenInExplorerString = "Show in Explorer";
#elif __APPLE__
QString OpenInExplorerString = "Show in Finder";
#else
QString OpenInExplorerString = "Show in file manager";
#endif
mpOpenAction = addAction("Open", this, SLOT(Open())); mpOpenAction = addAction("Open", this, SLOT(Open()));
mpOpenInExternalAppAction = addAction("Open in external application", this, SLOT(OpenInExternalApp())); mpOpenInExternalAppAction = addAction("Open in external application", this, SLOT(OpenInExternalApp()));
mpOpenContainingFolderAction = addAction("Open containing folder", this, SLOT(OpenContainingFolder())); mpOpenInExplorerAction = addAction(OpenInExplorerString, this, SLOT(OpenInExplorer()));
mpSelectFolderAction = addAction("Select folder", this, SLOT(SelectFolder()));
addSeparator(); addSeparator();
mpRenameAction = addAction("Rename", this, SLOT(Rename())); mpRenameAction = addAction("Rename", this, SLOT(Rename()));
mpShowReferencersAction = addAction("Show referencers", this, SLOT(ShowReferencers()));
mpShowDependenciesAction = addAction("Show dependencies", this, SLOT(ShowDependencies()));
addSeparator(); addSeparator();
mpCopyNameAction = addAction("Copy name", this, SLOT(CopyName())); mpCopyNameAction = addAction("Copy name", this, SLOT(CopyName()));
mpCopyPathAction = addAction("Copy path", this, SLOT(CopyPath())); mpCopyPathAction = addAction("Copy path", this, SLOT(CopyPath()));
@ -41,6 +52,9 @@ void CResourceTableContextMenu::ShowMenu(const QPoint& rkPos)
// Show/hide menu options // Show/hide menu options
bool IsRes = (mpEntry != nullptr); bool IsRes = (mpEntry != nullptr);
mpOpenInExternalAppAction->setVisible(IsRes); mpOpenInExternalAppAction->setVisible(IsRes);
mpSelectFolderAction->setVisible(mpModel->IsDisplayingAssetList());
mpShowDependenciesAction->setVisible(IsRes);
mpShowReferencersAction->setVisible(IsRes);
mpCopyIDAction->setVisible(IsRes); mpCopyIDAction->setVisible(IsRes);
// Exec menu // Exec menu
@ -55,7 +69,7 @@ void CResourceTableContextMenu::Open()
if (mpEntry) if (mpEntry)
gpEdApp->EditResource(mpEntry); gpEdApp->EditResource(mpEntry);
else else
mpBrowser->SelectDirectory(mpDirectory); mpBrowser->SetActiveDirectory(mpDirectory);
} }
void CResourceTableContextMenu::OpenInExternalApp() void CResourceTableContextMenu::OpenInExternalApp()
@ -64,7 +78,7 @@ void CResourceTableContextMenu::OpenInExternalApp()
UICommon::OpenInExternalApplication( TO_QSTRING(mpEntry->CookedAssetPath()) ); UICommon::OpenInExternalApplication( TO_QSTRING(mpEntry->CookedAssetPath()) );
} }
void CResourceTableContextMenu::OpenContainingFolder() void CResourceTableContextMenu::OpenInExplorer()
{ {
if (mpEntry) if (mpEntry)
{ {
@ -79,11 +93,67 @@ void CResourceTableContextMenu::OpenContainingFolder()
} }
} }
void CResourceTableContextMenu::SelectFolder()
{
CVirtualDirectory *pDir = (mpEntry ? mpEntry->Directory() : mpDirectory->Parent());
mpBrowser->SetActiveDirectory(pDir);
if (mpEntry)
mpBrowser->SelectResource(mpEntry);
else
mpBrowser->SelectDirectory(mpDirectory);
}
void CResourceTableContextMenu::Rename() void CResourceTableContextMenu::Rename()
{ {
mpTable->edit(mProxyIndex); mpTable->edit(mProxyIndex);
} }
void CResourceTableContextMenu::ShowReferencers()
{
ASSERT(mpEntry);
QList<CResourceEntry*> EntryList;
for (CResourceIterator Iter(mpEntry->ResourceStore()); Iter; ++Iter)
{
if (Iter->Dependencies()->HasDependency(mpEntry->ID()))
EntryList << *Iter;
}
if (!mpModel->IsDisplayingUserEntryList())
mpBrowser->SetInspectedEntry(mpEntry);
QString ListDesc = QString("Referencers of \"%1\"").arg( TO_QSTRING(mpEntry->CookedAssetPath().GetFileName()) );
mpModel->DisplayEntryList(EntryList, ListDesc);
mpBrowser->ClearFilters();
}
void CResourceTableContextMenu::ShowDependencies()
{
ASSERT(mpEntry);
std::set<CAssetID> Dependencies;
mpEntry->Dependencies()->GetAllResourceReferences(Dependencies);
QList<CResourceEntry*> EntryList;
for (auto Iter = Dependencies.begin(); Iter != Dependencies.end(); Iter++)
{
CResourceEntry *pEntry = mpEntry->ResourceStore()->FindEntry(*Iter);
if (pEntry)
EntryList << pEntry;
}
if (!mpModel->IsDisplayingUserEntryList())
mpBrowser->SetInspectedEntry(mpEntry);
QString ListDesc = QString("Dependencies of \"%1\"").arg( TO_QSTRING(mpEntry->CookedAssetPath().GetFileName()) );
mpModel->DisplayEntryList(EntryList, ListDesc);
mpBrowser->ClearFilters();
}
void CResourceTableContextMenu::CopyName() void CResourceTableContextMenu::CopyName()
{ {
if (mpEntry) if (mpEntry)

View File

@ -24,9 +24,12 @@ class CResourceTableContextMenu : public QMenu
// Actions // Actions
QAction *mpOpenAction; QAction *mpOpenAction;
QAction *mpOpenInExternalAppAction; QAction *mpOpenInExternalAppAction;
QAction *mpOpenContainingFolderAction; QAction *mpOpenInExplorerAction;
QAction *mpSelectFolderAction;
QAction *mpRenameAction; QAction *mpRenameAction;
QAction *mpShowReferencersAction;
QAction *mpShowDependenciesAction;
QAction *mpCopyNameAction; QAction *mpCopyNameAction;
QAction *mpCopyPathAction; QAction *mpCopyPathAction;
@ -41,8 +44,11 @@ public slots:
// Menu Options // Menu Options
void Open(); void Open();
void OpenInExternalApp(); void OpenInExternalApp();
void OpenContainingFolder(); void OpenInExplorer();
void SelectFolder();
void Rename(); void Rename();
void ShowReferencers();
void ShowDependencies();
void CopyName(); void CopyName();
void CopyPath(); void CopyPath();
void CopyID(); void CopyID();

View File

@ -5,6 +5,7 @@
CResourceTableModel::CResourceTableModel(CResourceBrowser *pBrowser, QObject *pParent /*= 0*/) CResourceTableModel::CResourceTableModel(CResourceBrowser *pBrowser, QObject *pParent /*= 0*/)
: QAbstractTableModel(pParent) : QAbstractTableModel(pParent)
, mpCurrentDir(nullptr) , mpCurrentDir(nullptr)
, mIsDisplayingUserEntryList(false)
{ {
connect(pBrowser, SIGNAL(DirectoryCreated(CVirtualDirectory*)), this, SLOT(CheckAddDirectory(CVirtualDirectory*))); connect(pBrowser, SIGNAL(DirectoryCreated(CVirtualDirectory*)), this, SLOT(CheckAddDirectory(CVirtualDirectory*)));
connect(pBrowser, SIGNAL(DirectoryAboutToBeDeleted(CVirtualDirectory*)), this, SLOT(CheckRemoveDirectory(CVirtualDirectory*))); connect(pBrowser, SIGNAL(DirectoryAboutToBeDeleted(CVirtualDirectory*)), this, SLOT(CheckRemoveDirectory(CVirtualDirectory*)));
@ -189,6 +190,11 @@ bool CResourceTableModel::IsIndexDirectory(const QModelIndex& rkIndex) const
return rkIndex.row() >= 0 && rkIndex.row() < mDirectories.size(); return rkIndex.row() >= 0 && rkIndex.row() < mDirectories.size();
} }
bool CResourceTableModel::HasParentDirectoryEntry() const
{
return !mIsAssetListMode && mpCurrentDir && !mpCurrentDir->IsRoot();
}
void CResourceTableModel::FillEntryList(CVirtualDirectory *pDir, bool AssetListMode) void CResourceTableModel::FillEntryList(CVirtualDirectory *pDir, bool AssetListMode)
{ {
beginResetModel(); beginResetModel();
@ -197,6 +203,7 @@ void CResourceTableModel::FillEntryList(CVirtualDirectory *pDir, bool AssetListM
mEntries.clear(); mEntries.clear();
mDirectories.clear(); mDirectories.clear();
mIsAssetListMode = AssetListMode; mIsAssetListMode = AssetListMode;
mIsDisplayingUserEntryList = false;
if (pDir) if (pDir)
{ {
@ -226,6 +233,22 @@ void CResourceTableModel::FillEntryList(CVirtualDirectory *pDir, bool AssetListM
RecursiveAddDirectoryContents(pDir); RecursiveAddDirectoryContents(pDir);
} }
if (pDir)
mModelDescription = pDir->IsRoot() ? "Root" : TO_QSTRING(pDir->FullPath());
else
mModelDescription = "Nothing";
endResetModel();
}
void CResourceTableModel::DisplayEntryList(QList<CResourceEntry*>& rkEntries, const QString& rkListDescription)
{
beginResetModel();
mEntries = rkEntries;
mDirectories.clear();
mModelDescription = rkListDescription;
mIsAssetListMode = true;
mIsDisplayingUserEntryList = true;
endResetModel(); endResetModel();
} }

View File

@ -16,7 +16,9 @@ class CResourceTableModel : public QAbstractTableModel
CVirtualDirectory *mpCurrentDir; CVirtualDirectory *mpCurrentDir;
QList<CVirtualDirectory*> mDirectories; QList<CVirtualDirectory*> mDirectories;
QList<CResourceEntry*> mEntries; QList<CResourceEntry*> mEntries;
QString mModelDescription;
bool mIsAssetListMode; bool mIsAssetListMode;
bool mIsDisplayingUserEntryList;
public: public:
CResourceTableModel(CResourceBrowser *pBrowser, QObject *pParent = 0); CResourceTableModel(CResourceBrowser *pBrowser, QObject *pParent = 0);
@ -39,15 +41,21 @@ public:
CResourceEntry* IndexEntry(const QModelIndex& rkIndex) const; CResourceEntry* IndexEntry(const QModelIndex& rkIndex) const;
CVirtualDirectory* IndexDirectory(const QModelIndex& rkIndex) const; CVirtualDirectory* IndexDirectory(const QModelIndex& rkIndex) const;
bool IsIndexDirectory(const QModelIndex& rkIndex) const; bool IsIndexDirectory(const QModelIndex& rkIndex) const;
bool HasParentDirectoryEntry() const;
void FillEntryList(CVirtualDirectory *pDir, bool AssetListMode); void FillEntryList(CVirtualDirectory *pDir, bool AssetListMode);
void DisplayEntryList(QList<CResourceEntry*>& rkEntries, const QString& rkListDescription);
protected: protected:
void RecursiveAddDirectoryContents(CVirtualDirectory *pDir); void RecursiveAddDirectoryContents(CVirtualDirectory *pDir);
int EntryListIndex(CResourceEntry *pEntry); int EntryListIndex(CResourceEntry *pEntry);
public: public:
// Accessors // Accessors
inline u32 NumDirectories() const { return mDirectories.size(); } inline u32 NumDirectories() const { return mDirectories.size(); }
inline u32 NumResources() const { return mEntries.size(); } inline u32 NumResources() const { return mEntries.size(); }
inline CVirtualDirectory* CurrentDir() const { return mpCurrentDir; }
inline bool IsDisplayingAssetList() const { return mIsAssetListMode; }
inline bool IsDisplayingUserEntryList() const { return mIsDisplayingUserEntryList; }
inline QString ModelDescription() const { return mModelDescription; }
public slots: public slots:
void CheckAddDirectory(CVirtualDirectory *pDir); void CheckAddDirectory(CVirtualDirectory *pDir);

View File

@ -2,10 +2,16 @@
#define CRESOURCETABLEVIEW_H #define CRESOURCETABLEVIEW_H
#include <QTableView> #include <QTableView>
#include "CResourceTableModel.h"
#include "CResourceProxyModel.h"
class CResourceTableView : public QTableView class CResourceTableView : public QTableView
{ {
Q_OBJECT Q_OBJECT
CResourceTableModel *mpModel;
CResourceProxyModel *mpProxy;
QAction *mpRenameAction; QAction *mpRenameAction;
QAction *mpDeleteAction; QAction *mpDeleteAction;