mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-06-06 06:33:39 +00:00
324 lines
9.6 KiB
C++
324 lines
9.6 KiB
C++
#include "CResourceTableModel.h"
|
|
#include "CResourceBrowser.h"
|
|
#include "CResourceMimeData.h"
|
|
|
|
CResourceTableModel::CResourceTableModel(CResourceBrowser *pBrowser, QObject *pParent /*= 0*/)
|
|
: QAbstractTableModel(pParent)
|
|
, mpCurrentDir(nullptr)
|
|
{
|
|
connect(pBrowser, SIGNAL(ResourceMoved(CResourceEntry*,CVirtualDirectory*,TString)), this, SLOT(OnResourceMoved(CResourceEntry*,CVirtualDirectory*,TString)));
|
|
connect(pBrowser, SIGNAL(DirectoryMoved(CVirtualDirectory*,CVirtualDirectory*,TString)), this, SLOT(OnDirectoryMoved(CVirtualDirectory*,CVirtualDirectory*,TString)));
|
|
}
|
|
|
|
// ************ INTERFACE ************
|
|
int CResourceTableModel::rowCount(const QModelIndex&) const
|
|
{
|
|
return mDirectories.size() + mEntries.size();
|
|
}
|
|
|
|
int CResourceTableModel::columnCount(const QModelIndex&) const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
QVariant CResourceTableModel::data(const QModelIndex& rkIndex, int Role) const
|
|
{
|
|
if (rkIndex.column() != 0)
|
|
return QVariant::Invalid;
|
|
|
|
// Directory
|
|
if (IsIndexDirectory(rkIndex))
|
|
{
|
|
CVirtualDirectory *pDir = IndexDirectory(rkIndex);
|
|
|
|
if (Role == Qt::DisplayRole || Role == Qt::ToolTipRole)
|
|
return ( (mpCurrentDir && !mpCurrentDir->IsRoot() && 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)
|
|
return TO_QSTRING(pEntry->Name());
|
|
|
|
else if (Role == Qt::ToolTipRole)
|
|
return TO_QSTRING(pEntry->CookedAssetPath(true));
|
|
|
|
else if (Role == Qt::DecorationRole)
|
|
return QIcon(":/icons/Sphere Preview.png");
|
|
|
|
return QVariant::Invalid;
|
|
}
|
|
|
|
Qt::ItemFlags CResourceTableModel::flags(const QModelIndex& rkIndex) const
|
|
{
|
|
Qt::ItemFlags Out = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled;
|
|
|
|
if (IsIndexDirectory(rkIndex))
|
|
Out |= Qt::ItemIsDropEnabled;
|
|
|
|
return Out;
|
|
}
|
|
|
|
bool CResourceTableModel::canDropMimeData(const QMimeData *pkData, Qt::DropAction, int Row, int Column, const QModelIndex& rkParent) const
|
|
{
|
|
const CResourceMimeData *pkMimeData = qobject_cast<const CResourceMimeData*>(pkData);
|
|
|
|
if (pkMimeData)
|
|
{
|
|
// Make sure we're dropping onto a directory
|
|
QModelIndex Index = (rkParent.isValid() ? rkParent : index(Row, Column, rkParent));
|
|
|
|
if (Index.isValid())
|
|
{
|
|
CVirtualDirectory *pDir = IndexDirectory(Index);
|
|
|
|
if (pDir)
|
|
{
|
|
// Make sure this directory isn't part of the mime data, or a subdirectory of a directory in the mime data
|
|
foreach (CVirtualDirectory *pMimeDir, pkMimeData->Directories())
|
|
{
|
|
if (pDir == pMimeDir || pDir->IsDescendantOf(pMimeDir))
|
|
return false;
|
|
}
|
|
|
|
// Valid directory
|
|
return true;
|
|
}
|
|
}
|
|
else return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CResourceTableModel::dropMimeData(const QMimeData *pkData, Qt::DropAction, int Row, int Column, const QModelIndex& rkParent)
|
|
{
|
|
const CResourceMimeData *pkMimeData = qobject_cast<const CResourceMimeData*>(pkData);
|
|
|
|
QModelIndex Index = (rkParent.isValid() ? rkParent : index(Row, Column, rkParent));
|
|
CVirtualDirectory *pDir = IndexDirectory(Index);
|
|
ASSERT(pDir);
|
|
|
|
gpEdApp->ResourceBrowser()->MoveResources( pkMimeData->Resources(), pkMimeData->Directories(), pDir );
|
|
return true;
|
|
}
|
|
|
|
QMimeData* CResourceTableModel::mimeData(const QModelIndexList& rkIndexes) const
|
|
{
|
|
if (rkIndexes.isEmpty())
|
|
return nullptr;
|
|
|
|
QList<CResourceEntry*> Resources;
|
|
QList<CVirtualDirectory*> Dirs;
|
|
|
|
foreach(QModelIndex Index, rkIndexes)
|
|
{
|
|
CResourceEntry *pEntry = IndexEntry(Index);
|
|
CVirtualDirectory *pDir = IndexDirectory(Index);
|
|
|
|
if (pEntry) Resources << pEntry;
|
|
else Dirs << pDir;
|
|
}
|
|
|
|
return new CResourceMimeData(Resources, Dirs);
|
|
}
|
|
|
|
Qt::DropActions CResourceTableModel::supportedDragActions() const
|
|
{
|
|
return Qt::MoveAction | Qt::CopyAction;
|
|
}
|
|
|
|
Qt::DropActions CResourceTableModel::supportedDropActions() const
|
|
{
|
|
return Qt::MoveAction;
|
|
}
|
|
|
|
// ************ FUNCTIONALITY ************
|
|
QModelIndex CResourceTableModel::GetIndexForEntry(CResourceEntry *pEntry) const
|
|
{
|
|
auto Iter = qBinaryFind(mEntries, pEntry);
|
|
|
|
if (Iter == mEntries.end())
|
|
return QModelIndex();
|
|
|
|
else
|
|
{
|
|
int Index = Iter - mEntries.begin();
|
|
return index(mDirectories.size() + Index, 0, QModelIndex());
|
|
}
|
|
}
|
|
|
|
QModelIndex CResourceTableModel::GetIndexForDirectory(CVirtualDirectory *pDir) const
|
|
{
|
|
for (int DirIdx = 0; DirIdx < mDirectories.size(); DirIdx++)
|
|
{
|
|
if (mDirectories[DirIdx] == pDir)
|
|
return index(DirIdx, 0, QModelIndex());
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
CResourceEntry* CResourceTableModel::IndexEntry(const QModelIndex& rkIndex) const
|
|
{
|
|
int Index = rkIndex.row() - mDirectories.size();
|
|
return (Index >= 0 ? mEntries[Index] : nullptr);
|
|
}
|
|
|
|
CVirtualDirectory* CResourceTableModel::IndexDirectory(const QModelIndex& rkIndex) const
|
|
{
|
|
return (IsIndexDirectory(rkIndex) ? mDirectories[rkIndex.row()] : nullptr);
|
|
}
|
|
|
|
bool CResourceTableModel::IsIndexDirectory(const QModelIndex& rkIndex) const
|
|
{
|
|
return rkIndex.row() >= 0 && rkIndex.row() < mDirectories.size();
|
|
}
|
|
|
|
void CResourceTableModel::FillEntryList(CVirtualDirectory *pDir, bool AssetListMode)
|
|
{
|
|
beginResetModel();
|
|
|
|
mpCurrentDir = pDir;
|
|
mEntries.clear();
|
|
mDirectories.clear();
|
|
mIsAssetListMode = AssetListMode;
|
|
|
|
if (pDir)
|
|
{
|
|
// In filesystem mode, show only subdirectories and assets in the current directory.
|
|
if (!mIsAssetListMode)
|
|
{
|
|
if (!pDir->IsRoot())
|
|
mDirectories << pDir->Parent();
|
|
|
|
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())
|
|
{
|
|
int Index = EntryListIndex(pEntry);
|
|
mEntries.insert(Index, pEntry);
|
|
}
|
|
}
|
|
}
|
|
|
|
// In asset list mode, do not show subdirectories and show all assets in current directory + all subdirectories.
|
|
else
|
|
RecursiveAddDirectoryContents(pDir);
|
|
}
|
|
|
|
endResetModel();
|
|
}
|
|
|
|
void CResourceTableModel::RecursiveAddDirectoryContents(CVirtualDirectory *pDir)
|
|
{
|
|
for (u32 iRes = 0; iRes < pDir->NumResources(); iRes++)
|
|
{
|
|
CResourceEntry *pEntry = pDir->ResourceByIndex(iRes);
|
|
|
|
if (pEntry->TypeInfo()->IsVisibleInBrowser() && !pEntry->IsHidden())
|
|
{
|
|
int Index = EntryListIndex(pEntry);
|
|
mEntries.insert(Index, pEntry);
|
|
}
|
|
}
|
|
|
|
for (u32 iDir = 0; iDir < pDir->NumSubdirectories(); iDir++)
|
|
RecursiveAddDirectoryContents(pDir->SubdirectoryByIndex(iDir));
|
|
}
|
|
|
|
int CResourceTableModel::EntryListIndex(CResourceEntry *pEntry)
|
|
{
|
|
return qLowerBound(mEntries, pEntry) - mEntries.constBegin();
|
|
}
|
|
|
|
void CResourceTableModel::OnResourceMoved(CResourceEntry *pEntry, CVirtualDirectory *pOldDir, TString OldName)
|
|
{
|
|
CVirtualDirectory *pNewDir = pEntry->Directory();
|
|
bool WasInModel = (pOldDir == mpCurrentDir || (mIsAssetListMode && pOldDir->IsDescendantOf(mpCurrentDir)));
|
|
bool IsInModel = (pNewDir == mpCurrentDir || (mIsAssetListMode && pNewDir->IsDescendantOf(mpCurrentDir)));
|
|
|
|
// Handle rename
|
|
if (WasInModel && IsInModel && pEntry->Name() != OldName)
|
|
{
|
|
int ResIdx = EntryListIndex(pEntry);
|
|
int Row = ResIdx + mDirectories.size();
|
|
QModelIndex Index = index(Row, 0, QModelIndex());
|
|
emit dataChanged(Index, Index);
|
|
}
|
|
|
|
else if (pNewDir != pOldDir)
|
|
{
|
|
// Remove
|
|
if (WasInModel && !IsInModel)
|
|
{
|
|
int Pos = EntryListIndex(pEntry);
|
|
int Row = mDirectories.size() + Pos;
|
|
|
|
beginRemoveRows(QModelIndex(), Row, Row);
|
|
mEntries.removeAt(Pos);
|
|
endRemoveRows();
|
|
}
|
|
|
|
// Add
|
|
else if (!WasInModel && IsInModel)
|
|
{
|
|
int Index = EntryListIndex(pEntry);
|
|
int Row = mDirectories.size() + Index;
|
|
|
|
beginInsertRows(QModelIndex(), Row, Row);
|
|
mEntries.insert(Index, pEntry);
|
|
endInsertRows();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CResourceTableModel::OnDirectoryMoved(CVirtualDirectory *pDir, CVirtualDirectory *pOldDir, TString OldName)
|
|
{
|
|
CVirtualDirectory *pNewDir = pDir->Parent();
|
|
bool WasInModel = !mIsAssetListMode && pOldDir == mpCurrentDir;
|
|
bool IsInModel = !mIsAssetListMode && pNewDir == mpCurrentDir;
|
|
|
|
// Handle rename
|
|
if (WasInModel && IsInModel && pDir->Name() != OldName)
|
|
{
|
|
QModelIndex Index = GetIndexForDirectory(pDir);
|
|
emit dataChanged(Index, Index);
|
|
}
|
|
|
|
else if (pNewDir != pOldDir)
|
|
{
|
|
// Remove
|
|
if (WasInModel && !IsInModel)
|
|
{
|
|
QModelIndex Index = GetIndexForDirectory(pDir);
|
|
|
|
beginRemoveRows(QModelIndex(), Index.row(), Index.row());
|
|
mDirectories.removeOne(pDir);
|
|
endRemoveRows();
|
|
}
|
|
|
|
// Add
|
|
else if (!WasInModel && !IsInModel)
|
|
{
|
|
// Just append to the end, let the proxy handle sorting
|
|
beginInsertRows(QModelIndex(), mDirectories.size(), mDirectories.size());
|
|
mDirectories << pDir;
|
|
endInsertRows();
|
|
}
|
|
}
|
|
}
|