Merge pull request #781 from aws-lumberyard-dev/LYN-1767-AB

LYN-1767 : Asset Browser Search View
This commit is contained in:
IgnacioMartinezGarrido
2021-06-16 17:05:40 +01:00
committed by GitHub
19 changed files with 733 additions and 92 deletions
@@ -12,6 +12,7 @@
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
#include <AzCore/Console/IConsole.h>
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
@@ -22,6 +23,9 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
#include <QCollator>
AZ_POP_DISABLE_WARNING
AZ_CVAR(
bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null,
"Use the new AssetBrowser TableView for searching assets.");
namespace AzToolsFramework
{
namespace AssetBrowser
@@ -31,7 +35,11 @@ namespace AzToolsFramework
AssetBrowserFilterModel::AssetBrowserFilterModel(QObject* parent)
: QSortFilterProxyModel(parent)
{
m_showColumn.insert(AssetBrowserModel::m_column);
m_showColumn.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName));
if (ed_useNewAssetBrowserTableView)
{
m_showColumn.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::Path));
}
m_collator.setNumericMode(true);
AssetBrowserComponentNotificationBus::Handler::BusConnect();
}
@@ -128,28 +136,58 @@ namespace AzToolsFramework
auto compFilter = qobject_cast<QSharedPointer<const CompositeFilter> >(m_filter);
if (compFilter)
{
auto& subFilters = compFilter->GetSubFilters();
auto it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool
const auto& subFilters = compFilter->GetSubFilters();
const auto compositeFilterIterator = AZStd::find_if(subFilters.cbegin(), subFilters.cend(), [subFilters](FilterConstType filter) -> bool
{
auto assetTypeFilter = qobject_cast<QSharedPointer<const CompositeFilter> >(filter);
const auto assetTypeFilter = qobject_cast<QSharedPointer<const CompositeFilter> >(filter);
return !assetTypeFilter.isNull();
});
if (it != subFilters.end())
if (compositeFilterIterator != subFilters.end())
{
m_assetTypeFilter = qobject_cast<QSharedPointer<const CompositeFilter> >(*it);
m_assetTypeFilter = qobject_cast<QSharedPointer<const CompositeFilter> >(*compositeFilterIterator);
}
it = AZStd::find_if(subFilters.begin(), subFilters.end(), [subFilters](FilterConstType filter) -> bool
const auto compStringFilterIter = AZStd::find_if(subFilters.cbegin(), subFilters.cend(), [](FilterConstType filter) -> bool
{
auto stringFilter = qobject_cast<QSharedPointer<const StringFilter> >(filter);
return !stringFilter.isNull();
//The real StringFilter is really a CompositeFilter with just one StringFilter in its subfilter list
//To know if it is actually a StringFilter we have to get that subfilter and check if it is a Stringfilter.
const auto stringCompositeFilter = qobject_cast<QSharedPointer<const CompositeFilter> >(filter);
bool isStringFilter = false;
if (stringCompositeFilter)
{
const auto& stringSubfilters = stringCompositeFilter->GetSubFilters();
auto canBeCasted = [](FilterConstType filt) -> bool
{
auto strFilter = qobject_cast<QSharedPointer<const StringFilter>>(filt);
return !strFilter.isNull();
};
const auto stringSubfliterConstIter = AZStd::find_if(stringSubfilters.cbegin(), stringSubfilters.cend(), canBeCasted);
//A Composite StringFilter will only have just one subfilter and nothing more.
if (stringSubfliterConstIter != stringSubfilters.end() && stringSubfilters.size() == 1)
{
isStringFilter = true;
}
}
return isStringFilter;
});
if (it != subFilters.end())
if (compStringFilterIter != subFilters.end())
{
m_stringFilter = qobject_cast<QSharedPointer<const StringFilter> >(*it);
const auto compStringFilter = qobject_cast<QSharedPointer<const CompositeFilter>>(*compStringFilterIter);
if (!compStringFilter->GetSubFilters().isEmpty() && compStringFilter->GetSubFilters()[0])
{
m_stringFilter = qobject_cast<QSharedPointer<const StringFilter>>(compStringFilter->GetSubFilters()[0]);
}
}
}
invalidateFilter();
Q_EMIT filterChanged();
emit stringFilterPopulated(!m_stringFilter.isNull());
}
void AssetBrowserFilterModel::filterUpdatedSlot()
@@ -45,15 +45,15 @@ namespace AzToolsFramework
//asset type filtering
void SetFilter(FilterConstType filter);
void FilterUpdatedSlotImmediate();
const FilterConstType& GetFilter() const { return m_filter; }
//////////////////////////////////////////////////////////////////////////
// AssetBrowserComponentNotificationBus
//////////////////////////////////////////////////////////////////////////
void OnAssetBrowserComponentReady() override;
Q_SIGNALS:
void stringFilterPopulated(bool);
void filterChanged();
//////////////////////////////////////////////////////////////////////////
//QSortFilterProxyModel
protected:
@@ -68,7 +68,7 @@ namespace AzToolsFramework
protected:
//set for filtering columns
//if the column is in the set the column is not filtered and is shown
AZStd::fixed_unordered_set<int, 3, static_cast<int>(AssetBrowserEntry::Column::Count)> m_showColumn;
AZStd::fixed_unordered_set<int, 3, aznumeric_cast<int>(AssetBrowserEntry::Column::Count)> m_showColumn;
bool m_alreadyRecomputingFilters = false;
//asset source name match filter
FilterConstType m_filter;
@@ -27,8 +27,6 @@ namespace AzToolsFramework
{
namespace AssetBrowser
{
const int AssetBrowserModel::m_column = static_cast<int>(AssetBrowserEntry::Column::DisplayName);
AssetBrowserModel::AssetBrowserModel(QObject* parent)
: QAbstractItemModel(parent)
, m_rootEntry(nullptr)
@@ -143,8 +141,9 @@ namespace AzToolsFramework
if (parent.isValid())
{
if ((parent.column() != static_cast<int>(AssetBrowserEntry::Column::DisplayName)) &&
(parent.column() != static_cast<int>(AssetBrowserEntry::Column::Name)))
if ((parent.column() != aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName)) &&
(parent.column() != aznumeric_cast<int>(AssetBrowserEntry::Column::Name)) &&
(parent.column() != aznumeric_cast<int>(AssetBrowserEntry::Column::Path)))
{
return 0;
}
@@ -164,7 +163,7 @@ namespace AzToolsFramework
int AssetBrowserModel::columnCount(const QModelIndex& /*parent*/) const
{
return static_cast<int>(AssetBrowserEntry::Column::Count);
return aznumeric_cast<int>(AssetBrowserEntry::Column::Count);
}
QVariant AssetBrowserModel::data(const QModelIndex& index, int role) const
@@ -393,7 +392,7 @@ namespace AzToolsFramework
}
int row = entry->row();
index = createIndex(row, m_column, entry);
index = createIndex(row, aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName), entry);
return true;
}
@@ -91,8 +91,6 @@ namespace AzToolsFramework
static void SourceIndexesToAssetIds(const QModelIndexList& indexes, AZStd::vector<AZ::Data::AssetId>& assetIds);
static void SourceIndexesToAssetDatabaseEntries(const QModelIndexList& indexes, AZStd::vector<AssetBrowserEntry*>& entries);
const static int m_column;
private:
AZStd::shared_ptr<RootAssetBrowserEntry> m_rootEntry;
bool m_loaded;
@@ -0,0 +1,136 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AssetBrowser/AssetBrowserFilterModel.h>
#include <AssetBrowser/AssetBrowserTableModel.h>
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
namespace AzToolsFramework
{
namespace AssetBrowser
{
AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */)
: QSortFilterProxyModel(parent)
{
setDynamicSortFilter(false);
}
void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel)
{
m_filterModel = qobject_cast<AssetBrowserFilterModel*>(sourceModel);
AZ_Assert(
m_filterModel,
"Error in AssetBrowserTableModel initialization, class expects source model to be an AssetBrowserFilterModel.");
QSortFilterProxyModel::setSourceModel(sourceModel);
}
QModelIndex AssetBrowserTableModel::mapToSource(const QModelIndex& proxyIndex) const
{
Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() == this);
if (!proxyIndex.isValid())
{
return QModelIndex();
}
return m_indexMap[proxyIndex.row()];
}
QVariant AssetBrowserTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
return tr(AssetBrowserEntry::m_columnNames[section]);
}
return QSortFilterProxyModel::headerData(section, orientation, role);
}
QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const
{
auto sourceIndex = mapToSource(index);
if (!sourceIndex.isValid())
{
return QVariant();
}
AssetBrowserEntry* entry = GetAssetEntry(sourceIndex);
if (entry == nullptr)
{
AZ_Assert(false, "AssetBrowserTableModel - QModelIndex does not reference an AssetEntry. Source model is not valid.");
return QVariant();
}
return sourceIndex.data(role);
}
QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const
{
return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer());
}
int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const
{
return !parent.isValid() ? m_indexMap.size() : 0;
}
int AssetBrowserTableModel::BuildTableModelMap(
const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/)
{
int rows = model ? model->rowCount(parent) : 0;
for (int i = 0; i < rows; ++i)
{
QModelIndex index = model->index(i, 0, parent);
AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index));
//We only wanna see the source assets.
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
{
beginInsertRows(parent, row, row);
m_indexMap[row] = index;
endInsertRows();
Q_EMIT dataChanged(index, index);
++row;
}
if (model->hasChildren(index))
{
row = BuildTableModelMap(model, index, row);
}
}
return row;
}
AssetBrowserEntry* AssetBrowserTableModel::GetAssetEntry(QModelIndex index) const
{
if (index.isValid())
{
return static_cast<AssetBrowserEntry*>(index.internalPointer());
}
else
{
AZ_Error("AssetBrowser", false, "Invalid Source Index provided to GetAssetEntry.");
return nullptr;
}
}
void AssetBrowserTableModel::UpdateTableModelMaps()
{
emit layoutAboutToBeChanged();
if (!m_indexMap.isEmpty())
{
beginRemoveRows(m_indexMap.first(), m_indexMap.first().row(), m_indexMap.last().row());
m_indexMap.clear();
endRemoveRows();
}
BuildTableModelMap(sourceModel());
emit layoutChanged();
}
} // namespace AssetBrowser
} // namespace AzToolsFramework
#include "AssetBrowser/moc_AssetBrowserTableModel.cpp"
@@ -0,0 +1,59 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Asset/AssetCommon.h>
#include <QSortFilterProxyModel>
#include <QPointer>
#endif
namespace AzToolsFramework
{
namespace AssetBrowser
{
class AssetBrowserFilterModel;
class AssetBrowserEntry;
class AssetBrowserTableModel
: public QSortFilterProxyModel
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0);
explicit AssetBrowserTableModel(QObject* parent = nullptr);
////////////////////////////////////////////////////////////////////
// QSortFilterProxyModel
void setSourceModel(QAbstractItemModel* sourceModel) override;
QModelIndex mapToSource(const QModelIndex& proxyIndex) const override;
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
public Q_SLOTS:
void UpdateTableModelMaps();
protected:
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override;
////////////////////////////////////////////////////////////////////
private:
AssetBrowserEntry* GetAssetEntry(QModelIndex index) const;
int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0);
private:
QPointer<AssetBrowserFilterModel> m_filterModel;
QMap<int, QModelIndex> m_indexMap;
};
} // namespace AssetBrowser
} // namespace AzToolsFramework
@@ -46,6 +46,7 @@ namespace AzToolsFramework
const char* AssetBrowserEntry::m_columnNames[] =
{
"Name",
"Path",
"Source ID",
"Fingerprint",
"Guid",
@@ -128,6 +129,8 @@ namespace AzToolsFramework
return QString::fromUtf8(m_name.c_str());
case Column::DisplayName:
return m_displayName;
case Column::Path:
return m_displayPath;
default:
return QVariant();
}
@@ -68,6 +68,7 @@ namespace AzToolsFramework
enum class Column
{
Name,
Path,
SourceID,
Fingerprint,
Guid,
@@ -135,6 +136,7 @@ namespace AzToolsFramework
protected:
AZStd::string m_name;
QString m_displayName;
QString m_displayPath;
AZStd::string m_relativePath;
AZStd::string m_fullPath;
AZStd::vector<AssetBrowserEntry*> m_children;
@@ -43,6 +43,7 @@ namespace AzToolsFramework
void FolderAssetBrowserEntry::UpdateChildPaths(AssetBrowserEntry* child) const
{
child->m_relativePath = m_relativePath + AZ_CORRECT_DATABASE_SEPARATOR + child->m_name;
child->m_displayPath = QString::fromUtf8(child->m_relativePath.c_str());
child->m_fullPath = m_fullPath + AZ_CORRECT_DATABASE_SEPARATOR + child->m_name;
AssetBrowserEntry::UpdateChildPaths(child);
}
@@ -286,6 +286,9 @@ namespace AzToolsFramework
product->m_assetType = productWithUuidDatabaseEntry.second.m_assetType;
product->m_assetType.ToString(product->m_assetTypeString);
AZ::Data::AssetCatalogRequestBus::BroadcastResult(product->m_relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, assetId);
QString displayPath = QString::fromUtf8(product->m_relativePath.c_str());
displayPath.remove(QString(AZ_CORRECT_DATABASE_SEPARATOR + QString::fromUtf8(product->m_name.c_str())));
product->m_displayPath = displayPath;
EntryCache::GetInstance()->m_productAssetIdMap[assetId] = product;
if (needsAdd)
@@ -0,0 +1,178 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <API/EditorAssetSystemAPI.h>
#include <AzCore/std/containers/vector.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryCache.h>
#include <AzToolsFramework/AssetBrowser/Entries/ProductAssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h>
#include <AzToolsFramework/AssetBrowser/Views/EntryDelegate.h>
AZ_PUSH_DISABLE_WARNING(
4244 4251 4800, "-Wunknown-warning-option") // conversion from 'int' to 'float', possible loss of data, needs to have dll-interface to
// be used by clients of class 'QFlags<QPainter::RenderHint>::Int': forcing value to bool
// 'true' or 'false' (performance warning)
#include <QCoreApplication>
#include <QHeaderView>
#include <QMenu>
#include <QMouseEvent>
#include <QPainter>
#include <QPen>
#include <QTimer>
AZ_POP_DISABLE_WARNING
namespace AzToolsFramework
{
namespace AssetBrowser
{
AssetBrowserTableView::AssetBrowserTableView(QWidget* parent)
: QTableView(parent)
, m_delegate(new EntryDelegate(this))
{
setSortingEnabled(true);
setItemDelegate(m_delegate);
verticalHeader()->hide();
setContextMenuPolicy(Qt::CustomContextMenu);
setMouseTracking(true);
setSortingEnabled(false);
setSelectionMode(QAbstractItemView::SingleSelection);
connect(this, &QTableView::customContextMenuRequested, this, &AssetBrowserTableView::OnContextMenu);
AssetBrowserViewRequestBus::Handler::BusConnect();
AssetBrowserComponentNotificationBus::Handler::BusConnect();
}
AssetBrowserTableView::~AssetBrowserTableView()
{
AssetBrowserViewRequestBus::Handler::BusDisconnect();
AssetBrowserComponentNotificationBus::Handler::BusDisconnect();
}
void AssetBrowserTableView::setModel(QAbstractItemModel* model)
{
m_tableModel = qobject_cast<AssetBrowserTableModel*>(model);
AZ_Assert(m_tableModel, "Expecting AssetBrowserTableModel");
m_sourceFilterModel = qobject_cast<AssetBrowserFilterModel*>(m_tableModel->sourceModel());
QTableView::setModel(model);
connect(m_tableModel, &AssetBrowserTableModel::layoutChanged, this, &AssetBrowserTableView::layoutChangedSlot);
horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch);
horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch);
}
void AssetBrowserTableView::SetName(const QString& name)
{
m_name = name;
bool isAssetBrowserComponentReady = false;
AssetBrowserComponentRequestBus::BroadcastResult(isAssetBrowserComponentReady, &AssetBrowserComponentRequests::AreEntriesReady);
if (isAssetBrowserComponentReady)
{
OnAssetBrowserComponentReady();
}
}
AZStd::vector<AssetBrowserEntry*> AssetBrowserTableView::GetSelectedAssets() const
{
QModelIndexList sourceIndexes;
for (const auto& index : selectedIndexes())
{
if (index.column() == 0)
{
sourceIndexes.push_back(m_sourceFilterModel->mapToSource(m_tableModel->mapToSource(index)));
}
}
AZStd::vector<AssetBrowserEntry*> entries;
AssetBrowserModel::SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries);
return entries;
}
void AssetBrowserTableView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
{
QTableView::selectionChanged(selected, deselected);
Q_EMIT selectionChangedSignal(selected, deselected);
}
void AssetBrowserTableView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
{
// if selected entry is being removed, clear selection so not to select (and attempt to preview) other entries potentially
// marked for deletion
if (selectionModel() && selectionModel()->selectedIndexes().size() == 1)
{
QModelIndex selectedIndex = selectionModel()->selectedIndexes().first();
QModelIndex parentSelectedIndex = selectedIndex.parent();
if (parentSelectedIndex == parent && selectedIndex.row() >= start && selectedIndex.row() <= end)
{
selectionModel()->clear();
}
}
QTableView::rowsAboutToBeRemoved(parent, start, end);
}
void AssetBrowserTableView::layoutChangedSlot(
[[maybe_unused]] const QList<QPersistentModelIndex>& parents, [[maybe_unused]] QAbstractItemModel::LayoutChangeHint hint)
{
scrollToTop();
}
void AssetBrowserTableView::SelectProduct([[maybe_unused]] AZ::Data::AssetId assetID)
{
}
void AssetBrowserTableView::SelectFileAtPath([[maybe_unused]] const AZStd::string& assetPath)
{
}
void AssetBrowserTableView::ClearFilter()
{
emit ClearStringFilter();
emit ClearTypeFilter();
m_sourceFilterModel->FilterUpdatedSlotImmediate();
}
void AssetBrowserTableView::Update()
{
update();
}
void AssetBrowserTableView::OnAssetBrowserComponentReady()
{
}
void AssetBrowserTableView::OnContextMenu([[maybe_unused]] const QPoint& point)
{
const auto& selectedAssets = GetSelectedAssets();
if (selectedAssets.size() != 1)
{
return;
}
QMenu menu(this);
AssetBrowserInteractionNotificationBus::Broadcast(
&AssetBrowserInteractionNotificationBus::Events::AddContextMenuActions, this, &menu, selectedAssets);
if (!menu.isEmpty())
{
menu.exec(QCursor::pos());
}
}
} // namespace AssetBrowser
} // namespace AzToolsFramework
#include "AssetBrowser/Views/moc_AssetBrowserTableView.cpp"
@@ -0,0 +1,84 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/std/containers/vector.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h>
#include <QModelIndex>
#include <QPointer>
#include <QTableView>
#endif
namespace AzToolsFramework
{
namespace AssetBrowser
{
class AssetBrowserEntry;
class AssetBrowserTableModel;
class AssetBrowserFilterModel;
class EntryDelegate;
class AssetBrowserTableView //! Table view that displays the asset browser entries in a list.
: public QTableView
, public AssetBrowserViewRequestBus::Handler
, public AssetBrowserComponentNotificationBus::Handler
{
Q_OBJECT
public:
explicit AssetBrowserTableView(QWidget* parent = nullptr);
~AssetBrowserTableView() override;
void setModel(QAbstractItemModel *model) override;
void SetName(const QString& name);
AZStd::vector<AssetBrowserEntry*> GetSelectedAssets() const;
//////////////////////////////////////////////////////////////////////////
// AssetBrowserViewRequestBus
virtual void SelectProduct(AZ::Data::AssetId assetID) override;
virtual void SelectFileAtPath(const AZStd::string& assetPath) override;
virtual void ClearFilter() override;
virtual void Update() override;
//////////////////////////////////////////////////////////////////////////
// AssetBrowserComponentNotificationBus
void OnAssetBrowserComponentReady() override;
//////////////////////////////////////////////////////////////////////////
Q_SIGNALS:
void selectionChangedSignal(const QItemSelection& selected, const QItemSelection& deselected);
void ClearStringFilter();
void ClearTypeFilter();
protected Q_SLOTS:
void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) override;
void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override;
void layoutChangedSlot(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
private:
QString m_name;
QPointer<AssetBrowserTableModel> m_tableModel = nullptr;
QPointer<AssetBrowserFilterModel> m_sourceFilterModel = nullptr;
EntryDelegate* m_delegate = nullptr;
private Q_SLOTS:
void OnContextMenu(const QPoint& point);
};
} // namespace AssetBrowser
} // namespace AzToolsFramework
@@ -53,6 +53,7 @@ namespace AzToolsFramework
setSortingEnabled(true);
setItemDelegate(m_delegate);
header()->hide();
setContextMenuPolicy(Qt::CustomContextMenu);
setMouseTracking(true);
@@ -99,8 +100,9 @@ namespace AzToolsFramework
AZStd::vector<AssetBrowserEntry*> AssetBrowserTreeView::GetSelectedAssets() const
{
const QModelIndexList& selectedIndexes = selectionModel()->selectedRows();
QModelIndexList sourceIndexes;
for (const auto& index : selectedIndexes())
for (const auto& index : selectedIndexes)
{
sourceIndexes.push_back(m_assetBrowserSortFilterProxyModel->mapToSource(index));
}
@@ -172,6 +174,7 @@ namespace AzToolsFramework
void AssetBrowserTreeView::OnAssetBrowserComponentReady()
{
hideColumn(aznumeric_cast<int>(AssetBrowserEntry::Column::Path));
if (!m_name.isEmpty())
{
auto crc = AZ::Crc32(m_name.toUtf8().data());
@@ -74,34 +74,34 @@ namespace AzToolsFramework
QPoint iconTopLeft(remainingRect.x(), remainingRect.y() + (remainingRect.height() / 2) - (m_iconSize / 2));
auto sourceEntry = azrtti_cast<const SourceAssetBrowserEntry*>(entry);
int thumbX = DrawThumbnail(painter, iconTopLeft, iconSize, entry->GetThumbnailKey());
QPalette actualPalette(option.palette);
if (sourceEntry)
if (index.column() == aznumeric_cast<int>(AssetBrowserEntry::Column::Name))
{
if (m_showSourceControl)
int thumbX = DrawThumbnail(painter, iconTopLeft, iconSize, entry->GetThumbnailKey());
if (sourceEntry)
{
DrawThumbnail(painter, iconTopLeft, iconSize, sourceEntry->GetSourceControlThumbnailKey());
}
// sources with no children should be greyed out.
if (sourceEntry->GetChildCount() == 0)
{
isEnabled = false; // draw in disabled style.
actualPalette.setCurrentColorGroup(QPalette::Disabled);
if (m_showSourceControl)
{
DrawThumbnail(painter, iconTopLeft, iconSize, sourceEntry->GetSourceControlThumbnailKey());
}
// sources with no children should be greyed out.
if (sourceEntry->GetChildCount() == 0)
{
isEnabled = false; // draw in disabled style.
actualPalette.setCurrentColorGroup(QPalette::Disabled);
}
}
remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail
remainingRect.adjust(ENTRY_SPACING_LEFT_PIXELS, 0, 0, 0); // bump it to the right by the spacing.
}
QString displayString = index.column() == aznumeric_cast<int>(AssetBrowserEntry::Column::Name)
? qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::Name)))
: qvariant_cast<QString>(entry->data(aznumeric_cast<int>(AssetBrowserEntry::Column::Path)));
remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail
remainingRect.adjust(ENTRY_SPACING_LEFT_PIXELS, 0, 0, 0); // bump it to the right by the spacing.
style->drawItemText(painter,
remainingRect,
option.displayAlignment,
actualPalette,
isEnabled,
entry->GetDisplayName(),
style->drawItemText(
painter, remainingRect, option.displayAlignment, actualPalette, isEnabled,
displayString,
isSelected ? QPalette::HighlightedText : QPalette::Text);
}
}
@@ -544,6 +544,8 @@ set(FILES
AssetBrowser/AssetBrowserEntry.h
AssetBrowser/AssetBrowserFilterModel.cpp
AssetBrowser/AssetBrowserFilterModel.h
AssetBrowser/AssetBrowserTableModel.cpp
AssetBrowser/AssetBrowserTableModel.h
AssetBrowser/AssetBrowserModel.cpp
AssetBrowser/AssetBrowserModel.h
AssetBrowser/AssetEntryChange.h
@@ -554,6 +556,8 @@ set(FILES
AssetBrowser/EBusFindAssetTypeByName.h
AssetBrowser/Views/AssetBrowserTreeView.cpp
AssetBrowser/Views/AssetBrowserTreeView.h
AssetBrowser/Views/AssetBrowserTableView.cpp
AssetBrowser/Views/AssetBrowserTableView.h
AssetBrowser/Views/EntryDelegate.cpp
AssetBrowser/Views/EntryDelegate.h
AssetBrowser/Views/AssetBrowserFolderWidget.cpp
@@ -1,24 +1,26 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorDefs.h"
#include "AzAssetBrowserWindow.h"
// AzToolsFramework
#include <AzCore/Console/IConsole.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h>
// AzQtComponents
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
@@ -31,6 +33,7 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <AzAssetBrowser/ui_AzAssetBrowserWindow.h>
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView);
class ListenerForShowAssetEditorEvent
: public QObject
@@ -66,32 +69,75 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::AzAssetBrowserWindowClass())
, m_filterModel(new AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent))
, m_tableModel(new AzToolsFramework::AssetBrowser::AssetBrowserTableModel(parent))
{
m_ui->setupUi(this);
m_ui->m_searchWidget->Setup(true, true);
using namespace AzToolsFramework::AssetBrowser;
AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel);
namespace AzAssetBrowser = AzToolsFramework::AssetBrowser;
AzAssetBrowser::AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AzAssetBrowser::AssetBrowserComponentRequests::GetAssetBrowserModel);
AZ_Assert(m_assetBrowserModel, "Failed to get filebrowser model");
m_filterModel->setSourceModel(m_assetBrowserModel);
m_filterModel->SetFilter(m_ui->m_searchWidget->GetFilter());
m_ui->m_viewSwitcherCheckBox->setVisible(false);
m_ui->m_assetBrowserTableViewWidget->setVisible(false);
if (ed_useNewAssetBrowserTableView)
{
m_ui->m_viewSwitcherCheckBox->setVisible(true);
m_tableModel->setFilterRole(Qt::DisplayRole);
m_tableModel->setSourceModel(m_filterModel.data());
m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data());
connect(
m_filterModel.data(), &AzAssetBrowser::AssetBrowserFilterModel::filterChanged, m_tableModel.data(),
&AzAssetBrowser::AssetBrowserTableModel::UpdateTableModelMaps);
connect(
m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::selectionChangedSignal, this,
&AzAssetBrowserWindow::SelectionChangedSlot);
connect(
m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this,
&AzAssetBrowserWindow::DoubleClickedItem);
connect(
m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget,
&AzAssetBrowser::SearchWidget::ClearStringFilter);
connect(
m_ui->m_assetBrowserTableViewWidget, &AzAssetBrowser::AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget,
&AzAssetBrowser::SearchWidget::ClearTypeFilter);
m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main");
connect(m_filterModel.data(), &AzAssetBrowser::AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView);
connect(m_ui->m_viewSwitcherCheckBox, &QCheckBox::stateChanged, this, &AzAssetBrowserWindow::LockToDefaultView);
}
m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel.data());
connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal,
m_filterModel.data(), &AssetBrowserFilterModel::filterUpdatedSlot);
connect(m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this, [this]()
{
const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty();
const bool selectFirstFilteredIndex = false;
m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex);
});
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal,
this, &AzAssetBrowserWindow::SelectionChangedSlot);
connect(
m_ui->m_searchWidget->GetFilter().data(), &AzAssetBrowser::AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(),
&AzAssetBrowser::AssetBrowserFilterModel::filterUpdatedSlot);
connect(
m_filterModel.data(), &AzAssetBrowser::AssetBrowserFilterModel::filterChanged, this,
[this]()
{
const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty();
const bool selectFirstFilteredIndex = false;
m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex);
});
connect(
m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::selectionChangedSignal, this,
&AzAssetBrowserWindow::SelectionChangedSlot);
connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem);
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget, &SearchWidget::ClearStringFilter);
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget, &SearchWidget::ClearTypeFilter);
connect(
m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::ClearStringFilter, m_ui->m_searchWidget,
&AzAssetBrowser::SearchWidget::ClearStringFilter);
connect(
m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::ClearTypeFilter, m_ui->m_searchWidget,
&AzAssetBrowser::SearchWidget::ClearTypeFilter);
m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main");
}
@@ -117,7 +163,10 @@ QObject* AzAssetBrowserWindow::createListenerForShowAssetEditorEvent(QObject* pa
void AzAssetBrowserWindow::UpdatePreview() const
{
auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->isVisible()
? m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()
: m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets();
if (selectedAssets.size() != 1)
{
m_ui->m_previewerFrame->Clear();
@@ -148,8 +197,6 @@ static void ExpandTreeToIndex(QTreeView* treeView, const QModelIndex& index)
void AzAssetBrowserWindow::SelectAsset(const QString& assetPath)
{
using namespace AzToolsFramework::AssetBrowser;
QModelIndex index = m_assetBrowserModel->findIndex(assetPath);
if (index.isValid())
{
@@ -161,18 +208,21 @@ void AzAssetBrowserWindow::SelectAsset(const QString& assetPath)
// interferes with the update from the select and expand, and if you don't
// queue it, the tree doesn't expand reliably.
QTimer::singleShot(0, this, [this, filteredIndex = index] {
// the treeview has a filter model so we have to backwards go from that
QModelIndex index = m_filterModel->mapFromSource(filteredIndex);
QTimer::singleShot(
0, this,
[this, filteredIndex = index]
{
// the treeview has a filter model so we have to backwards go from that
QModelIndex index = m_filterModel->mapFromSource(filteredIndex);
QTreeView* treeView = m_ui->m_assetBrowserTreeViewWidget;
ExpandTreeToIndex(treeView, index);
QTreeView* treeView = m_ui->m_assetBrowserTreeViewWidget;
ExpandTreeToIndex(treeView, index);
treeView->scrollTo(index);
treeView->setCurrentIndex(index);
treeView->scrollTo(index);
treeView->setCurrentIndex(index);
treeView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
});
treeView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
});
}
}
@@ -185,31 +235,34 @@ void AzAssetBrowserWindow::SelectionChangedSlot(const QItemSelection& /*selected
// just becuase on some OS clicking once is activation.
void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex& element)
{
using namespace AzToolsFramework;
using namespace AzToolsFramework::AssetBrowser;
// assumption: Double clicking an item selects it before telling us we double clicked it.
auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
for (const AssetBrowserEntry* entry : selectedAssets)
namespace AzAssetBrowser = AzToolsFramework::AssetBrowser;
const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->isVisible()
? m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()
: m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets();
for (const AzAssetBrowser::AssetBrowserEntry* entry : selectedAssets)
{
AZ::Data::AssetId assetIdToOpen;
AZStd::string fullFilePath;
if (const ProductAssetBrowserEntry* productEntry = azrtti_cast<const ProductAssetBrowserEntry*>(entry))
if (const AzAssetBrowser::ProductAssetBrowserEntry* productEntry = azrtti_cast<const AzAssetBrowser::ProductAssetBrowserEntry*>(entry))
{
assetIdToOpen = productEntry->GetAssetId();
fullFilePath = entry->GetFullPath();
}
else if (const SourceAssetBrowserEntry* sourceEntry = azrtti_cast<const SourceAssetBrowserEntry*>(entry))
else if (const AzAssetBrowser::SourceAssetBrowserEntry* sourceEntry = azrtti_cast<const AzAssetBrowser::SourceAssetBrowserEntry*>(entry))
{
// manufacture an empty AssetID with the source's UUID
assetIdToOpen = AZ::Data::AssetId(sourceEntry->GetSourceUuid(), 0);
fullFilePath = entry->GetFullPath();
}
bool handledBySomeone = false;
if (assetIdToOpen.IsValid())
{
AssetBrowserInteractionNotificationBus::Broadcast(&AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone);
AzAssetBrowser::AssetBrowserInteractionNotificationBus::Broadcast(
&AzAssetBrowser::AssetBrowserInteractionNotifications::OpenAssetInAssociatedEditor, assetIdToOpen, handledBySomeone);
}
if (!handledBySomeone && !fullFilePath.empty())
@@ -217,7 +270,27 @@ void AzAssetBrowserWindow::DoubleClickedItem([[maybe_unused]] const QModelIndex&
AzAssetBrowserRequestHandler::OpenWithOS(fullFilePath);
}
}
}
void AzAssetBrowserWindow::SwitchDisplayView(bool state)
{
m_ui->m_assetBrowserTableViewWidget->setVisible(state);
m_ui->m_assetBrowserTreeViewWidget->setVisible(!state);
}
void AzAssetBrowserWindow::LockToDefaultView(bool state)
{
using AzToolsFramework::AssetBrowser::AssetBrowserFilterModel;
SwitchDisplayView(!state);
if (state == true)
{
disconnect(
m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView);
}
else
{
connect(m_filterModel.data(), &AssetBrowserFilterModel::stringFilterPopulated, this, &AzAssetBrowserWindow::SwitchDisplayView);
}
}
#include <AzAssetBrowser/moc_AzAssetBrowserWindow.cpp>
@@ -29,7 +29,9 @@ namespace AzToolsFramework
namespace AssetBrowser
{
class AssetBrowserFilterModel;
class AssetBrowserTableModel;
class AssetBrowserModel;
class AssetBrowserTableFilterModel;
}
}
@@ -53,6 +55,7 @@ private:
QScopedPointer<Ui::AzAssetBrowserWindowClass> m_ui;
QScopedPointer<AzToolsFramework::AssetBrowser::AssetBrowserFilterModel> m_filterModel;
QScopedPointer<AzToolsFramework::AssetBrowser::AssetBrowserTableModel> m_tableModel;
AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel;
void UpdatePreview() const;
@@ -60,6 +63,8 @@ private:
private Q_SLOTS:
void SelectionChangedSlot(const QItemSelection& selected, const QItemSelection& deselected) const;
void DoubleClickedItem(const QModelIndex& element);
void SwitchDisplayView(bool state);
void LockToDefaultView(bool state);
};
extern const char* AZ_ASSET_BROWSER_PREVIEW_NAME;
@@ -65,6 +65,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="m_viewSwitcherCheckBox">
<property name="text">
<string>Switch View</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -107,6 +114,49 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="AzToolsFramework::AssetBrowser::AssetBrowserTableView" name="m_assetBrowserTableViewWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="AzToolsFramework::AssetBrowser::AssetBrowserTreeView" name="m_assetBrowserTreeViewWidget">
<property name="sizePolicy">
@@ -162,6 +212,11 @@
<header>AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>AzToolsFramework::AssetBrowser::AssetBrowserTableView</class>
<extends>QTableView</extends>
<header>AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
@@ -34,7 +34,7 @@ namespace ScriptCanvasEditor
{
setDynamicSortFilter(true);
m_showColumn.insert(AssetBrowserModel::m_column);
m_showColumn.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName));
UnitTestWidgetNotificationBus::Handler::BusConnect();