Modified resource browser to use a filesystem browser view
This commit is contained in:
parent
c51d79cc42
commit
548fcb2f8e
|
@ -34,7 +34,7 @@ void CEditorApplication::InitEditor()
|
|||
mpWorldEditor = new CWorldEditor();
|
||||
mpResourceBrowser = new CResourceBrowser(mpWorldEditor);
|
||||
mpProjectDialog = new CProjectOverviewDialog();
|
||||
connect(mpProjectDialog, SIGNAL(ActiveProjectChanged(CGameProject*)), mpResourceBrowser, SLOT(RefreshResources()));
|
||||
connect(mpProjectDialog, SIGNAL(ActiveProjectChanged(CGameProject*)), mpResourceBrowser, SLOT(UpdateStore()));
|
||||
}
|
||||
|
||||
void CEditorApplication::EditResource(CResourceEntry *pEntry)
|
||||
|
|
|
@ -666,7 +666,8 @@ void CPropertyDelegate::SetCharacterModelData(QWidget *pEditor, const QModelInde
|
|||
|
||||
if (Type == eAssetProperty)
|
||||
{
|
||||
Params.SetResource( static_cast<CResourceSelector*>(pEditor)->Entry()->ID() );
|
||||
CResourceEntry *pEntry = static_cast<CResourceSelector*>(pEditor)->Entry();
|
||||
Params.SetResource( pEntry ? pEntry->ID() : CAssetID::InvalidID(mpEditor->CurrentGame()) );
|
||||
}
|
||||
|
||||
else if (Type == eEnumProperty)
|
||||
|
|
|
@ -12,6 +12,8 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
, mpUI(new Ui::CResourceBrowser)
|
||||
, mpSelectedEntry(nullptr)
|
||||
, mpStore(gpResourceStore)
|
||||
, mpSelectedDir(nullptr)
|
||||
, mSearching(false)
|
||||
{
|
||||
mpUI->setupUi(this);
|
||||
setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint);
|
||||
|
@ -49,11 +51,11 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
pImportNamesMenu->addAction(pImportFromAssetNameMapAction);
|
||||
|
||||
// Set up connections
|
||||
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(RefreshResources()));
|
||||
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateStore()));
|
||||
connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged()));
|
||||
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(OnDoubleClickResource(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(pImportFromContentsTxtAction, SIGNAL(triggered()), this, SLOT(OnImportPakContentsTxt()));
|
||||
connect(pImportFromAssetNameMapAction, SIGNAL(triggered()), this, SLOT(OnImportNamesFromAssetNameMap()));
|
||||
|
@ -73,16 +75,56 @@ CResourceBrowser::~CResourceBrowser()
|
|||
void CResourceBrowser::RefreshResources()
|
||||
{
|
||||
// Fill resource table
|
||||
mpStore = (mpUI->StoreComboBox->currentIndex() == 0 ? gpResourceStore : gpEditorStore);
|
||||
mpModel->FillEntryList(mpStore);
|
||||
mpModel->FillEntryList(mpSelectedDir, mSearching);
|
||||
|
||||
// Fill directory tree
|
||||
// Mark directories to span all three columns
|
||||
mpUI->ResourceTableView->clearSpans();
|
||||
|
||||
for (u32 iDir = 0; iDir < mpModel->NumDirectories(); iDir++)
|
||||
mpUI->ResourceTableView->setSpan(iDir, 0, 1, 3);
|
||||
}
|
||||
|
||||
void CResourceBrowser::UpdateDescriptionLabel()
|
||||
{
|
||||
QString Desc;
|
||||
|
||||
bool ValidDir = mpSelectedDir && !mpSelectedDir->IsRoot();
|
||||
QString Path = (ValidDir ? '\\' + TO_QSTRING(mpSelectedDir->FullPath()) : "");
|
||||
|
||||
if (mSearching)
|
||||
{
|
||||
QString SearchText = mpUI->SearchBar->text();
|
||||
Desc = QString("Searching \"%1\"").arg(SearchText);
|
||||
|
||||
if (ValidDir)
|
||||
Desc += QString(" in %1").arg(Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ValidDir)
|
||||
Desc = Path;
|
||||
}
|
||||
|
||||
mpUI->TableDescriptionLabel->setText(Desc);
|
||||
}
|
||||
|
||||
void CResourceBrowser::UpdateStore()
|
||||
{
|
||||
int StoreIndex = mpUI->StoreComboBox->currentIndex();
|
||||
CResourceStore *pNewStore = (StoreIndex == 0 ? gpResourceStore : gpEditorStore);
|
||||
|
||||
if (mpStore != pNewStore)
|
||||
{
|
||||
mpStore = pNewStore;
|
||||
|
||||
// Refresh directory tree
|
||||
mpDirectoryModel->SetRoot(mpStore ? mpStore->RootDirectory() : nullptr);
|
||||
QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex());
|
||||
mpUI->DirectoryTreeView->expand(RootIndex);
|
||||
mpUI->DirectoryTreeView->clearSelection();
|
||||
OnDirectorySelectionChanged(QModelIndex(), QModelIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void CResourceBrowser::OnSortModeChanged(int Index)
|
||||
{
|
||||
|
@ -98,20 +140,34 @@ void CResourceBrowser::OnSearchStringChanged()
|
|||
|
||||
void CResourceBrowser::OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/)
|
||||
{
|
||||
CVirtualDirectory *pDir = nullptr;
|
||||
|
||||
if (rkNewIndex.isValid())
|
||||
pDir = mpDirectoryModel->IndexDirectory(rkNewIndex);
|
||||
mpSelectedDir = mpDirectoryModel->IndexDirectory(rkNewIndex);
|
||||
else
|
||||
mpSelectedDir = mpStore ? mpStore->RootDirectory() : nullptr;
|
||||
|
||||
mpProxyModel->SetDirectory(pDir);
|
||||
UpdateDescriptionLabel();
|
||||
RefreshResources();
|
||||
}
|
||||
|
||||
void CResourceBrowser::OnDoubleClickResource(QModelIndex Index)
|
||||
void CResourceBrowser::OnDoubleClickTable(QModelIndex Index)
|
||||
{
|
||||
QModelIndex SourceIndex = mpProxyModel->mapToSource(Index);
|
||||
|
||||
// Directory - switch to the selected directory
|
||||
if (mpModel->IsIndexDirectory(SourceIndex))
|
||||
{
|
||||
CVirtualDirectory *pDir = mpModel->IndexDirectory(SourceIndex);
|
||||
QModelIndex Index = mpDirectoryModel->GetIndexForDirectory(pDir);
|
||||
mpUI->DirectoryTreeView->selectionModel()->setCurrentIndex(Index, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
|
||||
// Resource - open resource for editing
|
||||
else
|
||||
{
|
||||
CResourceEntry *pEntry = mpModel->IndexEntry(SourceIndex);
|
||||
gpEdApp->EditResource(pEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void CResourceBrowser::OnResourceSelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/)
|
||||
{
|
||||
|
@ -167,5 +223,15 @@ void CResourceBrowser::ExportAssetNames()
|
|||
|
||||
void CResourceBrowser::UpdateFilter()
|
||||
{
|
||||
QString SearchText = mpUI->SearchBar->text();
|
||||
bool NewSearching = !SearchText.isEmpty();
|
||||
|
||||
if (mSearching != NewSearching)
|
||||
{
|
||||
mSearching = NewSearching;
|
||||
RefreshResources();
|
||||
}
|
||||
|
||||
UpdateDescriptionLabel();
|
||||
mpProxyModel->SetSearchString( TO_TWIDESTRING(mpUI->SearchBar->text()) );
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@ class CResourceBrowser : public QDialog
|
|||
CResourceStore *mpStore;
|
||||
CResourceTableModel *mpModel;
|
||||
CResourceProxyModel *mpProxyModel;
|
||||
CVirtualDirectory *mpSelectedDir;
|
||||
CVirtualDirectoryModel *mpDirectoryModel;
|
||||
QTimer mUpdateFilterTimer;
|
||||
bool mSearching;
|
||||
|
||||
public:
|
||||
explicit CResourceBrowser(QWidget *pParent = 0);
|
||||
|
@ -31,10 +33,12 @@ public:
|
|||
|
||||
public slots:
|
||||
void RefreshResources();
|
||||
void UpdateDescriptionLabel();
|
||||
void UpdateStore();
|
||||
void OnSortModeChanged(int Index);
|
||||
void OnSearchStringChanged();
|
||||
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
|
||||
void OnDoubleClickResource(QModelIndex Index);
|
||||
void OnDoubleClickTable(QModelIndex Index);
|
||||
void OnResourceSelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
|
||||
void OnImportPakContentsTxt();
|
||||
void OnGenerateAssetNames();
|
||||
|
|
|
@ -149,6 +149,42 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="TableContainerWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<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="QLabel" name="TableDescriptionLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="ResourceTableView">
|
||||
<property name="sizePolicy">
|
||||
|
@ -199,6 +235,9 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -39,25 +39,40 @@ public:
|
|||
|
||||
bool lessThan(const QModelIndex& rkLeft, const QModelIndex& rkRight) const
|
||||
{
|
||||
CResourceEntry *pLeft = mpModel->IndexEntry(rkLeft);
|
||||
CResourceEntry *pRight = mpModel->IndexEntry(rkRight);
|
||||
CVirtualDirectory *pLeftDir = mpModel->IndexDirectory(rkLeft);
|
||||
CVirtualDirectory *pRightDir = mpModel->IndexDirectory(rkRight);
|
||||
CResourceEntry *pLeftRes = mpModel->IndexEntry(rkLeft);
|
||||
CResourceEntry *pRightRes = mpModel->IndexEntry(rkRight);
|
||||
|
||||
if (pLeftDir && !pRightDir)
|
||||
return true;
|
||||
|
||||
else if (pRightDir && !pLeftDir)
|
||||
return false;
|
||||
|
||||
else if (pLeftDir && pRightDir)
|
||||
return rkLeft.row() < rkRight.row(); // leave original directory order intact
|
||||
|
||||
else if (mSortMode == eSortByName)
|
||||
return pLeftRes->UppercaseName() < pRightRes->UppercaseName();
|
||||
|
||||
if (mSortMode == eSortByName)
|
||||
return pLeft->UppercaseName() < pRight->UppercaseName();
|
||||
else
|
||||
return pLeft->Size() < pRight->Size();
|
||||
return pLeftRes->Size() < pRightRes->Size();
|
||||
}
|
||||
|
||||
bool filterAcceptsRow(int SourceRow, const QModelIndex& rkSourceParent) const
|
||||
{
|
||||
QModelIndex Index = mpModel->index(SourceRow, 0, rkSourceParent);
|
||||
CVirtualDirectory *pDir = mpModel->IndexDirectory(Index);
|
||||
CResourceEntry *pEntry = mpModel->IndexEntry(Index);
|
||||
|
||||
if (mpDirectory && !pEntry->IsInDirectory(mpDirectory))
|
||||
return false;
|
||||
|
||||
if (!mSearchString.IsEmpty() && !pEntry->UppercaseName().Contains(mSearchString))
|
||||
if (!mSearchString.IsEmpty())
|
||||
{
|
||||
if (pDir)
|
||||
return false;
|
||||
else
|
||||
return pEntry->UppercaseName().Contains(mSearchString);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
class CResourceTableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QList<CVirtualDirectory*> mDirectories;
|
||||
QList<CResourceEntry*> mEntries;
|
||||
bool mHasParent;
|
||||
|
||||
public:
|
||||
CResourceTableModel(QObject *pParent = 0)
|
||||
|
@ -21,7 +24,7 @@ public:
|
|||
|
||||
int rowCount(const QModelIndex& /*rkParent*/) const
|
||||
{
|
||||
return mEntries.size();
|
||||
return mDirectories.size() + mEntries.size();
|
||||
}
|
||||
|
||||
int columnCount(const QModelIndex& /*rkParent*/) const
|
||||
|
@ -31,9 +34,29 @@ public:
|
|||
|
||||
QVariant data(const QModelIndex& rkIndex, int Role) const
|
||||
{
|
||||
CResourceEntry *pEntry = mEntries[rkIndex.row()];
|
||||
u32 Col = rkIndex.column();
|
||||
|
||||
// Directory
|
||||
if (IsIndexDirectory(rkIndex))
|
||||
{
|
||||
if (Col != 0)
|
||||
return QVariant::Invalid;
|
||||
|
||||
CVirtualDirectory *pDir = IndexDirectory(rkIndex);
|
||||
|
||||
if (Role == Qt::DisplayRole || Role == Qt::ToolTipRole)
|
||||
return (mHasParent && rkIndex.row() == 0 ? ".." : TO_QSTRING(pDir->Name()));
|
||||
|
||||
else if (Role == Qt::DecorationRole)
|
||||
return QIcon(":/icons/Open_24px.png");
|
||||
|
||||
else
|
||||
return QVariant::Invalid;
|
||||
}
|
||||
|
||||
// Resource
|
||||
CResourceEntry *pEntry = IndexEntry(rkIndex);
|
||||
|
||||
if (Role == Qt::DisplayRole)
|
||||
{
|
||||
if (Col == 0)
|
||||
|
@ -64,28 +87,73 @@ public:
|
|||
|
||||
CResourceEntry* IndexEntry(const QModelIndex& rkIndex) const
|
||||
{
|
||||
return mEntries[rkIndex.row()];
|
||||
int Index = rkIndex.row() - mDirectories.size();
|
||||
return (Index >= 0 ? mEntries[Index] : nullptr);
|
||||
}
|
||||
|
||||
void FillEntryList(CResourceStore *pStore)
|
||||
CVirtualDirectory* IndexDirectory(const QModelIndex& rkIndex) const
|
||||
{
|
||||
return (rkIndex.row() < mDirectories.size() ? mDirectories[rkIndex.row()] : nullptr);
|
||||
}
|
||||
|
||||
bool IsIndexDirectory(const QModelIndex& rkIndex) const
|
||||
{
|
||||
return rkIndex.row() < mDirectories.size();
|
||||
}
|
||||
|
||||
void FillEntryList(CVirtualDirectory *pDir, bool IsSearching)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
mEntries.clear();
|
||||
mDirectories.clear();
|
||||
mHasParent = false;
|
||||
|
||||
if (pStore)
|
||||
if (pDir)
|
||||
{
|
||||
for (CResourceIterator It(pStore); It; ++It)
|
||||
// When not searching, show only subdirectories and assets in the current directory.
|
||||
if (!IsSearching)
|
||||
{
|
||||
if (It->IsTransient()) continue;
|
||||
|
||||
CResTypeInfo *pInfo = It->TypeInfo();
|
||||
if (pInfo->IsVisibleInBrowser() && !It->IsHidden())
|
||||
mEntries << *It;
|
||||
if (!pDir->IsRoot())
|
||||
{
|
||||
mDirectories << pDir->Parent();
|
||||
mHasParent = true;
|
||||
}
|
||||
|
||||
for (u32 iDir = 0; iDir < pDir->NumSubdirectories(); iDir++)
|
||||
mDirectories << pDir->SubdirectoryByIndex(iDir);
|
||||
|
||||
for (u32 iRes = 0; iRes < pDir->NumResources(); iRes++)
|
||||
{
|
||||
CResourceEntry *pEntry = pDir->ResourceByIndex(iRes);
|
||||
|
||||
if (pEntry->TypeInfo()->IsVisibleInBrowser() && !pEntry->IsHidden())
|
||||
mEntries << pEntry;
|
||||
}
|
||||
}
|
||||
|
||||
// When searching, do not show subdirectories and show all assets in current directory + all subdirectories.
|
||||
else
|
||||
RecursiveAddDirectoryContents(pDir);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
protected:
|
||||
void RecursiveAddDirectoryContents(CVirtualDirectory *pDir)
|
||||
{
|
||||
for (u32 iRes = 0; iRes < pDir->NumResources(); iRes++)
|
||||
mEntries << pDir->ResourceByIndex(iRes);
|
||||
|
||||
for (u32 iDir = 0; iDir < pDir->NumSubdirectories(); iDir++)
|
||||
RecursiveAddDirectoryContents(pDir->SubdirectoryByIndex(iDir));
|
||||
}
|
||||
|
||||
public:
|
||||
// Accessors
|
||||
inline u32 NumDirectories() const { return mDirectories.size(); }
|
||||
inline u32 NumResources() const { return mEntries.size(); }
|
||||
};
|
||||
|
||||
#endif // CRESOURCELISTMODEL
|
||||
|
|
|
@ -85,6 +85,42 @@ public:
|
|||
return QVariant::Invalid;
|
||||
}
|
||||
|
||||
QModelIndex GetIndexForDirectory(CVirtualDirectory *pDir)
|
||||
{
|
||||
QVector<int> Indices;
|
||||
CVirtualDirectory *pOriginal = pDir;
|
||||
CVirtualDirectory *pParent = pDir->Parent();
|
||||
|
||||
// Get index list
|
||||
while (pParent)
|
||||
{
|
||||
bool Found = false;
|
||||
|
||||
for (u32 iDir = 0; iDir < pParent->NumSubdirectories(); iDir++)
|
||||
{
|
||||
if (pParent->SubdirectoryByIndex(iDir) == pDir)
|
||||
{
|
||||
Indices.push_front(iDir);
|
||||
pDir = pParent;
|
||||
pParent = pParent->Parent();
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(Found); // it should not be possible for this not to work
|
||||
}
|
||||
|
||||
// Traverse hierarchy
|
||||
QModelIndex Out = index(0, 0, QModelIndex());
|
||||
|
||||
foreach (int Idx, Indices)
|
||||
Out = index(Idx, 0, Out);
|
||||
|
||||
ASSERT(IndexDirectory(Out) == pOriginal);
|
||||
return Out;
|
||||
}
|
||||
|
||||
inline CVirtualDirectory* IndexDirectory(const QModelIndex& rkIndex) const
|
||||
{
|
||||
if (!rkIndex.isValid()) return nullptr;
|
||||
|
|
Loading…
Reference in New Issue