Added context menu to the resource browser; fixed search results not displaying correctly

This commit is contained in:
Aruki 2017-07-13 01:41:46 -06:00
parent 137c10f28f
commit fe9a074029
8 changed files with 205 additions and 65 deletions

View File

@ -186,7 +186,8 @@ HEADERS += \
CUIRelay.h \ CUIRelay.h \
Widgets/CSelectResourcePanel.h \ Widgets/CSelectResourcePanel.h \
Widgets/CFilteredResourceModel.h \ Widgets/CFilteredResourceModel.h \
ResourceBrowser/CResourceDelegate.h ResourceBrowser/CResourceDelegate.h \
ResourceBrowser/CResourceTableContextMenu.h
# Source Files # Source Files
SOURCES += \ SOURCES += \
@ -255,7 +256,8 @@ SOURCES += \
WorldEditor/CWorldEditorSidebar.cpp \ WorldEditor/CWorldEditorSidebar.cpp \
CProgressDialog.cpp \ CProgressDialog.cpp \
Widgets/CSelectResourcePanel.cpp \ Widgets/CSelectResourcePanel.cpp \
ResourceBrowser/CResourceDelegate.cpp ResourceBrowser/CResourceDelegate.cpp \
ResourceBrowser/CResourceTableContextMenu.cpp
# UI Files # UI Files
FORMS += \ FORMS += \

View File

@ -2,9 +2,11 @@
#include "ui_CResourceBrowser.h" #include "ui_CResourceBrowser.h"
#include "CProgressDialog.h" #include "CProgressDialog.h"
#include "CResourceDelegate.h" #include "CResourceDelegate.h"
#include "CResourceTableContextMenu.h"
#include "Editor/CEditorApplication.h" #include "Editor/CEditorApplication.h"
#include <Core/GameProject/AssetNameGeneration.h> #include <Core/GameProject/AssetNameGeneration.h>
#include <Core/GameProject/CAssetNameMap.h> #include <Core/GameProject/CAssetNameMap.h>
#include <QCheckBox> #include <QCheckBox>
#include <QFileDialog> #include <QFileDialog>
#include <QMenu> #include <QMenu>
@ -109,8 +111,11 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
pGroup->addAction(pEdStoreAction); pGroup->addAction(pEdStoreAction);
#endif #endif
// Create context menu for the resource table
new CResourceTableContextMenu(this, mpUI->ResourceTableView, mpModel, mpProxyModel);
// Set up connections // Set up connections
connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged())); connect(mpUI->SearchBar, SIGNAL(StoppedTyping(QString)), this, SLOT(OnSearchStringChanged(QString)));
connect(mpUI->ResourceTreeButton, SIGNAL(pressed()), this, SLOT(SetResourceTreeView())); connect(mpUI->ResourceTreeButton, SIGNAL(pressed()), this, SLOT(SetResourceTreeView()));
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)));
@ -118,7 +123,6 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
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, QModelIndex)));
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(&mUpdateFilterTimer, SIGNAL(timeout()), this, SLOT(UpdateFilter()));
connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool))); connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool)));
connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(UpdateStore())); connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(UpdateStore()));
} }
@ -202,7 +206,7 @@ void CResourceBrowser::CreateFilterCheckboxes()
void CResourceBrowser::RefreshResources() void CResourceBrowser::RefreshResources()
{ {
// Fill resource table // Fill resource table
mpModel->FillEntryList(mpSelectedDir, mAssetListMode); mpModel->FillEntryList(mpSelectedDir, mAssetListMode || mSearching);
} }
void CResourceBrowser::RefreshDirectories() void CResourceBrowser::RefreshDirectories()
@ -261,10 +265,22 @@ void CResourceBrowser::OnSortModeChanged(int Index)
mpProxyModel->SetSortMode(Mode); mpProxyModel->SetSortMode(Mode);
} }
void CResourceBrowser::OnSearchStringChanged() void CResourceBrowser::OnSearchStringChanged(QString SearchString)
{ {
const int kUpdateWaitTime = 500; bool WasSearching = mSearching;
mUpdateFilterTimer.start(kUpdateWaitTime); mSearching = !SearchString.isEmpty();
// Check if we need to change to/from asset list mode to display/stop displaying search results
if (!mAssetListMode)
{
if ( (mSearching && !WasSearching) ||
(!mSearching && WasSearching) )
{
RefreshResources();
}
}
UpdateFilter();
} }
void CResourceBrowser::OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/) void CResourceBrowser::OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& /*rkPrevIndex*/)
@ -320,6 +336,10 @@ void CResourceBrowser::UpdateStore()
{ {
mpStore = pNewStore; mpStore = pNewStore;
// Clear search
mpUI->SearchBar->clear();
mSearching = false;
// Refresh type filter list // Refresh type filter list
CreateFilterCheckboxes(); CreateFilterCheckboxes();

View File

@ -24,7 +24,6 @@ class CResourceBrowser : public QWidget
CResourceBrowserDelegate *mpDelegate; CResourceBrowserDelegate *mpDelegate;
CVirtualDirectory *mpSelectedDir; CVirtualDirectory *mpSelectedDir;
CVirtualDirectoryModel *mpDirectoryModel; CVirtualDirectoryModel *mpDirectoryModel;
QTimer mUpdateFilterTimer;
bool mEditorStore; bool mEditorStore;
bool mAssetListMode; bool mAssetListMode;
bool mSearching; bool mSearching;
@ -51,6 +50,7 @@ public:
void CreateFilterCheckboxes(); void CreateFilterCheckboxes();
// Accessors // Accessors
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; }
@ -61,7 +61,7 @@ public slots:
void SetResourceTreeView(); void SetResourceTreeView();
void SetResourceListView(); void SetResourceListView();
void OnSortModeChanged(int Index); void OnSortModeChanged(int Index);
void OnSearchStringChanged(); void OnSearchStringChanged(QString SearchString);
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex); void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);
void OnDoubleClickTable(QModelIndex Index); void OnDoubleClickTable(QModelIndex Index);
void OnResourceSelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex); void OnResourceSelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);

View File

@ -70,7 +70,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="SearchBar"> <widget class="CTimedLineEdit" name="SearchBar">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>5</horstretch> <horstretch>5</horstretch>
@ -185,7 +185,7 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QWidget" name=""> <widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QScrollArea" name="FilterCheckboxScrollArea"> <widget class="QScrollArea" name="FilterCheckboxScrollArea">
@ -269,6 +269,9 @@
<pointsize>8</pointsize> <pointsize>8</pointsize>
</font> </font>
</property> </property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
</property> </property>
@ -301,6 +304,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>CTimedLineEdit</class>
<extends>QLineEdit</extends>
<header>Editor/Widgets/CTimedLineEdit.h</header>
</customwidget>
</customwidgets>
<resources> <resources>
<include location="../Icons.qrc"/> <include location="../Icons.qrc"/>
</resources> </resources>

View File

@ -0,0 +1,96 @@
#include "CResourceTableContextMenu.h"
#include "CResourceBrowser.h"
#include "Editor/CEditorApplication.h"
#include <QClipboard>
CResourceTableContextMenu::CResourceTableContextMenu(CResourceBrowser *pBrowser, QTableView *pView, CResourceTableModel *pModel, CResourceProxyModel *pProxy)
: QMenu(pView)
, mpBrowser(pBrowser)
, mpTable(pView)
, mpModel(pModel)
, mpProxy(pProxy)
, mpEntry(nullptr)
, mpDirectory(nullptr)
{
// Connect to the view
connect(pView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(ShowMenu(QPoint)));
// Create actions
mpOpenAction = addAction("Open", this, SLOT(Open()));
mpOpenInExternalAppAction = addAction("Open in external application", this, SLOT(OpenInExternalApp()));
mpOpenContainingFolderAction = addAction("Open containing folder", this, SLOT(OpenContainingFolder()));
addSeparator();
mpCopyNameAction = addAction("Copy name", this, SLOT(CopyName()));
mpCopyPathAction = addAction("Copy path", this, SLOT(CopyPath()));
mpCopyIDAction = addAction("Copy asset ID", this, SLOT(CopyID()));
}
void CResourceTableContextMenu::ShowMenu(const QPoint& rkPos)
{
// Fetch the entry/directory
QModelIndex ProxyIndex = mpTable->indexAt(rkPos);
mIndex = mpProxy->mapToSource(ProxyIndex);
mpEntry = mpModel->IndexEntry(mIndex);
mpDirectory = mpModel->IndexDirectory(mIndex);
// Show/hide menu options
bool IsRes = (mpEntry != nullptr);
mpOpenInExternalAppAction->setVisible(IsRes);
mpCopyIDAction->setVisible(IsRes);
// Exec menu
QPoint GlobalPos = mpTable->viewport()->mapToGlobal(rkPos);
exec(GlobalPos);
}
// Menu Options
void CResourceTableContextMenu::Open()
{
if (mpEntry)
gpEdApp->EditResource(mpEntry);
else
mpBrowser->SelectDirectory(mpDirectory);
}
void CResourceTableContextMenu::OpenInExternalApp()
{
ASSERT(mpEntry);
UICommon::OpenInExternalApplication( TO_QSTRING(mpEntry->CookedAssetPath()) );
}
void CResourceTableContextMenu::OpenContainingFolder()
{
if (mpEntry)
{
QString Path = TO_QSTRING( mpEntry->CookedAssetPath() );
UICommon::OpenContainingFolder(Path);
}
else
{
TString BasePath = mpBrowser->CurrentStore()->ResourcesDir();
QString Path = TO_QSTRING( BasePath + mpDirectory->FullPath() );
UICommon::OpenContainingFolder(Path);
}
}
void CResourceTableContextMenu::CopyName()
{
if (mpEntry)
gpEdApp->clipboard()->setText( TO_QSTRING(mpEntry->Name()) );
else
gpEdApp->clipboard()->setText( TO_QSTRING(mpDirectory->Name()) );
}
void CResourceTableContextMenu::CopyPath()
{
if (mpEntry)
gpEdApp->clipboard()->setText( TO_QSTRING(mpEntry->CookedAssetPath(true)) );
else
gpEdApp->clipboard()->setText( TO_QSTRING(mpDirectory->FullPath()) );
}
void CResourceTableContextMenu::CopyID()
{
ASSERT(mpEntry);
gpEdApp->clipboard()->setText( TO_QSTRING(mpEntry->ID().ToString()) );
}

View File

@ -0,0 +1,47 @@
#ifndef CRESOURCETABLECONTEXTMENU_H
#define CRESOURCETABLECONTEXTMENU_H
#include "CResourceTableModel.h"
#include "CResourceProxyModel.h"
#include <QMenu>
#include <QTableView>
class CResourceTableContextMenu : public QMenu
{
Q_OBJECT
CResourceBrowser *mpBrowser;
QTableView *mpTable;
CResourceTableModel *mpModel;
CResourceProxyModel *mpProxy;
QModelIndex mIndex;
CResourceEntry *mpEntry;
CVirtualDirectory *mpDirectory;
// Actions
QAction *mpOpenAction;
QAction *mpOpenInExternalAppAction;
QAction *mpOpenContainingFolderAction;
QAction *mpCopyNameAction;
QAction *mpCopyPathAction;
QAction *mpCopyIDAction;
public:
CResourceTableContextMenu(CResourceBrowser *pBrowser, QTableView *pView, CResourceTableModel *pModel, CResourceProxyModel *pProxy);
public slots:
void ShowMenu(const QPoint& rkPos);
// Menu Options
void Open();
void OpenInExternalApp();
void OpenContainingFolder();
void CopyName();
void CopyPath();
void CopyID();
};
#endif // CRESOURCETABLECONTEXTMENU_H

View File

@ -1,61 +1,24 @@
#include "UICommon.h" #include "UICommon.h"
#include <QDesktopServices>
#include <QProcess>
namespace UICommon namespace UICommon
{ {
QMap<QString,QString> FilterMap = { void OpenContainingFolder(const QString& rkPath)
{ "AFSM", "AI Finite State Machine (*.AFSM)" },
{ "ANIM", "Animation (*.ANIM)" },
{ "ANCS", "Animation Character Set (*.ANCS)" },
{ "AGSC", "Audio Group (*.AGSC)" },
{ "ATBL", "Audio Lookup Table (*.ATBL)" },
{ "CAUD", "Audio Metadata (*.CAUD)" },
{ "CHAR", "Character (*.CHAR)" },
{ "CINF", "Skeleton (*.CINF)" },
{ "CMDL", "Model (*.CMDL)" },
{ "CRSC", "Collision Response Data (*.CRSC)" },
{ "CSKR", "Skin Rules (*.CSKR)" },
{ "CSMP", "Audio Sample (*.CSMP)" },
{ "CSNG", "MIDI Data (*.CSNG)" },
{ "CTWK", "Tweaks (*.CTWK)" },
{ "DCLN", "Collision Mesh (*.DCLN)" },
{ "DGRP", "Dependency Group (*.DGRP)" },
{ "DPSC", "Decal (*.DPSC)" },
{ "DSP" , "Music Track (*.DSP)" },
{ "DUMB", "Binary Data Dump (*.DUMB)" },
{ "ELSC", "Electric Particle (*.ELSC)" },
{ "EVNT", "Animation Event Data (*.EVNT)" },
{ "FRME", "GUI Frame (*.FRME)" },
{ "FSM2", "AI Finite State Machine (*.FSM2)" },
{ "FONT", "Font (*.FONT)" },
{ "HINT", "Hint System Data (*.HINT)" },
{ "MAPA", "Area Map (*.MAPA)" },
{ "MAPW", "World Map (*.MAPW)" },
{ "MAPU", "Universe Map (*.MAPU)" },
{ "MLVL", "World (*.MLVL)" },
{ "MREA", "Area (*.MREA)" },
{ "NTWK", "Tweaks (*.NTWK)" },
{ "PATH", "AI Navigation Mesh (*.PATH)" },
{ "PAK" , "Package (*.pak)" },
{ "PART", "Particle (*.PART)" },
{ "SAVW", "World Save Data (*.SAVW)" },
{ "SCAN", "Scannable Object Info (*.SCAN)" },
{ "STRG", "String Table (*.STRG)" },
{ "STRM", "Audio Stream (*.STRM)" },
{ "SWHC", "Swoosh Particle (*.SWHC)" },
{ "THP" , "Video (*.thp)" },
{ "TXTR", "Texture (*.TXTR)" },
{ "WPSC", "Projectile (*.WPSC)" }
};
QString ExtensionFilterString(const QString& rkExtension)
{ {
QMap<QString,QString>::const_iterator it = FilterMap.find(rkExtension.toUpper()); #if WIN32
QStringList Args;
Args << "/select," << QDir::toNativeSeparators(rkPath);
QProcess::startDetached("explorer", Args);
#else
#error OpenContainingFolder() not implemented!
#endif
}
if (it != FilterMap.end()) bool OpenInExternalApplication(const QString& rkPath)
return it.value(); {
else return QDesktopServices::openUrl( QString("file:///") + QDir::toNativeSeparators(rkPath) );
return "Unknown Extension (*." + rkExtension + ")";
} }
} }

View File

@ -38,8 +38,10 @@
namespace UICommon namespace UICommon
{ {
extern QMap<QString,QString> FilterMap;
QString ExtensionFilterString(const QString& rkExtension); // Utility
void OpenContainingFolder(const QString& rkPath);
bool OpenInExternalApplication(const QString& rkPath);
// TString/TWideString <-> QString // TString/TWideString <-> QString
inline QString ToQString(const TString& rkStr) inline QString ToQString(const TString& rkStr)