diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index bcaaa02b67..a7faea36f6 100644 --- a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // AzQtComponents #include @@ -83,6 +84,9 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTableViewWidget->setVisible(false); m_ui->m_toggleDisplayViewBtn->setVisible(false); m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250)); + + m_assetBrowserModel->SetFilterModel(m_filterModel.data()); + if (ed_useNewAssetBrowserTableView) { m_ui->m_toggleDisplayViewBtn->setVisible(true); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp index 08d79adcf5..1c361b050d 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include "OutlinerDisplayOptionsMenu.h" #include "OutlinerSortFilterProxyModel.hxx" @@ -252,17 +253,7 @@ QVariant OutlinerListModel::dataForName(const QModelIndex& index, int role) cons if (s_paintingName && !m_filterString.empty()) { // highlight characters in filter - int highlightTextIndex = 0; - do - { - highlightTextIndex = label.lastIndexOf(QString(m_filterString.c_str()), highlightTextIndex - 1, Qt::CaseInsensitive); - if (highlightTextIndex >= 0) - { - const QString BACKGROUND_COLOR{ "#707070" }; - label.insert(static_cast(highlightTextIndex + m_filterString.length()), ""); - label.insert(highlightTextIndex, ""); - } - } while(highlightTextIndex > 0); + label = AzToolsFramework::RichTextHighlighter::HighlightText(label, m_filterString.c_str()); } return label; } @@ -2609,16 +2600,11 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optionV4.widget->style()->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter); // Now we setup a Text Document so it can draw the rich text - QTextDocument textDoc; - textDoc.setDefaultFont(optionV4.font); - textDoc.setDefaultStyleSheet("body {color: white}"); - textDoc.setHtml("" + entityNameRichText + ""); int verticalOffset = GetEntityNameVerticalOffset(entityId); painter->translate(textRect.topLeft() + QPoint(0, verticalOffset)); - textDoc.setTextWidth(textRect.width()); - textDoc.drawContents(painter, QRectF(0, 0, textRect.width(), textRect.height())); - painter->restore(); + AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect); + OutlinerListModel::s_paintingName = false; } else diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index c6772ea2d7..21229e5570 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -68,6 +68,11 @@ namespace AzToolsFramework } } + QSharedPointer AssetBrowserFilterModel::GetStringFilter() const + { + return m_stringFilter; + } + bool AssetBrowserFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { //get the source idx, if invalid early out diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 5d3ad0e1b0..cafe694ad6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -48,7 +48,7 @@ namespace AzToolsFramework // AssetBrowserComponentNotificationBus ////////////////////////////////////////////////////////////////////////// void OnAssetBrowserComponentReady() override; - + QSharedPointer GetStringFilter() const; Q_SIGNALS: void filterChanged(); ////////////////////////////////////////////////////////////////////////// @@ -70,7 +70,7 @@ namespace AzToolsFramework //Asset source name match filter FilterConstType m_filter; AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' - QWeakPointer m_stringFilter; + QSharedPointer m_stringFilter; QWeakPointer m_assetTypeFilter; QCollator m_collator; // cache the collator as its somewhat expensive to constantly create and destroy one. AZ_POP_DISABLE_WARNING diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp index f0e1520aab..fd05543097 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QRegularExpression::d': class 'QExplicitlySharedDataPointer' needs to have dll-interface to be used by clients of class 'QRegularExpression' @@ -268,6 +269,21 @@ namespace AzToolsFramework m_rootEntry = rootEntry; } + AssetBrowserFilterModel* AssetBrowserModel::GetFilterModel() + { + return m_filterModel; + } + + const AssetBrowserFilterModel* AssetBrowserModel::GetFilterModel() const + { + return m_filterModel; + } + + void AssetBrowser::AssetBrowserModel::SetFilterModel(AssetBrowserFilterModel* filterModel) + { + m_filterModel = filterModel; + } + QModelIndex AssetBrowserModel::parent(const QModelIndex& child) const { if (!child.isValid()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h index c46b73417c..2905844a23 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h @@ -35,6 +35,7 @@ namespace AzToolsFramework class AssetBrowserEntry; class RootAssetBrowserEntry; class AssetEntryChangeset; + class AssetBrowserFilterModel; class AssetBrowserModel : public QAbstractItemModel @@ -75,7 +76,7 @@ namespace AzToolsFramework void EndAddEntry(AssetBrowserEntry* parent) override; void BeginRemoveEntry(AssetBrowserEntry* entry) override; void EndRemoveEntry() override; - + ////////////////////////////////////////////////////////////////////////// // TickBus ////////////////////////////////////////////////////////////////////////// @@ -84,10 +85,16 @@ namespace AzToolsFramework AZStd::shared_ptr GetRootEntry() const; void SetRootEntry(AZStd::shared_ptr rootEntry); + AssetBrowserFilterModel* GetFilterModel(); + const AssetBrowserFilterModel* GetFilterModel() const; + void SetFilterModel(AssetBrowserFilterModel* filterModel); + static void SourceIndexesToAssetIds(const QModelIndexList& indexes, AZStd::vector& assetIds); static void SourceIndexesToAssetDatabaseEntries(const QModelIndexList& indexes, AZStd::vector& entries); private: + //Non owning pointer + AssetBrowserFilterModel* m_filterModel = nullptr; AZStd::shared_ptr m_rootEntry; bool m_loaded; bool m_addingEntry; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp index d617638632..4ec26d4c3d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp @@ -229,6 +229,11 @@ namespace AzToolsFramework Q_EMIT updatedSignal(); } + QString StringFilter::GetFilterString() const + { + return m_filterString; + } + QString StringFilter::GetNameInternal() const { return m_filterString; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h index 94f47e0599..1d93d4d0cf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h @@ -106,6 +106,7 @@ namespace AzToolsFramework ~StringFilter() override = default; void SetFilterString(const QString& filterString); + QString GetFilterString() const; protected: QString GetNameInternal() const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index cfcac579ff..a913009da0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -66,6 +66,7 @@ namespace AzToolsFramework m_tableModel = qobject_cast(model); AZ_Assert(m_tableModel, "Expecting AssetBrowserTableModel"); m_sourceFilterModel = qobject_cast(m_tableModel->sourceModel()); + m_delegate->Init(); AzQtComponents::TableView::setModel(model); connect(m_tableModel, &AssetBrowserTableModel::layoutChanged, this, &AssetBrowserTableView::layoutChangedSlot); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index 8b58791e68..8e69d5f788 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -9,12 +9,16 @@ #include #include #include +#include #include #include #include #include +#include #include +#include + AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // 4251: class 'QScopedPointer' needs to have dll-interface to be used by clients of class 'QBrush' // 4800: 'uint': forcing value to bool 'true' or 'false' (performance warning) #include @@ -160,13 +164,20 @@ namespace AzToolsFramework LoadBranchPixMaps(); } + void SearchEntryDelegate::Init() + { + AssetBrowserModel* assetBrowserModel; + AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel); + AZ_Assert(assetBrowserModel, "Failed to get filebrowser model"); + m_assetBrowserFilerModel = assetBrowserModel->GetFilterModel(); + } + void SearchEntryDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { auto data = index.data(AssetBrowserModel::Roles::EntryRole); if (data.canConvert()) { bool isEnabled = (option.state & QStyle::State_Enabled) != 0; - bool isSelected = (option.state & QStyle::State_Selected) != 0; QStyle* style = option.widget ? option.widget->style() : QApplication::style(); @@ -265,13 +276,21 @@ namespace AzToolsFramework remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail remainingRect.adjust(EntrySpacingLeftPixels, 0, 0, 0); // bump it to the right by the spacing. } + QString displayString = index.column() == aznumeric_cast(AssetBrowserEntry::Column::Name) ? qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Name))) : qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Path))); - style->drawItemText( - painter, remainingRect, option.displayAlignment, actualPalette, isEnabled, displayString, - isSelected ? QPalette::HighlightedText : QPalette::Text); + QStyleOptionViewItem optionV4{ option }; + initStyleOption(&optionV4, index); + optionV4.state &= ~(QStyle::State_HasFocus | QStyle::State_Selected); + + if (m_assetBrowserFilerModel && m_assetBrowserFilerModel->GetStringFilter() + && !m_assetBrowserFilerModel->GetStringFilter()->GetFilterString().isEmpty()) + { + displayString = RichTextHighlighter::HighlightText(displayString, m_assetBrowserFilerModel->GetStringFilter()->GetFilterString()); + } + RichTextHighlighter::PaintHighlightedRichText(displayString, painter, optionV4, remainingRect); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h index ac68c19248..7c7d919f2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h @@ -70,7 +70,7 @@ namespace AzToolsFramework Q_OBJECT public: explicit SearchEntryDelegate(QWidget* parent = nullptr); - + void Init(); void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: @@ -78,6 +78,7 @@ namespace AzToolsFramework void DrawBranchPixMap(EntryBranchType branchType, QPainter* painter, const QPoint& point, const QSize& size) const; private: + AssetBrowserFilterModel* m_assetBrowserFilerModel; QMap m_branchIcons; }; } // namespace AssetBrowser diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp new file mode 100644 index 0000000000..8b28298c3d --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "RichTextHighlighter.h" + +namespace AzToolsFramework +{ + + QString RichTextHighlighter::HighlightText(const QString& displayString, const QString& matchingSubstring) + { + QString highlightedString = displayString; + int highlightTextIndex = 0; + do + { + highlightTextIndex = highlightedString.lastIndexOf(matchingSubstring, highlightTextIndex - 1, Qt::CaseInsensitive); + if (highlightTextIndex >= 0) + { + const QString backgroundColor{ "#707070" }; + highlightedString.insert(static_cast(highlightTextIndex + matchingSubstring.length()), ""); + highlightedString.insert(highlightTextIndex, ""); + } + } while (highlightTextIndex > 0); + + return highlightedString; + } + + void RichTextHighlighter::PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect) + { + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + // Now we setup a Text Document so it can draw the rich text + QTextDocument textDoc; + textDoc.setDefaultFont(option.font); + if (option.state & QStyle::State_Enabled) + { + textDoc.setDefaultStyleSheet("body {color: white}"); + } + else + { + textDoc.setDefaultStyleSheet("body {color: #7C7C7C}"); + } + textDoc.setHtml("" + highlightedString + ""); + painter->translate(availableRect.topLeft()); + textDoc.setTextWidth(availableRect.width()); + textDoc.drawContents(painter, QRectF(0, 0, availableRect.width(), availableRect.height())); + + painter->restore(); + } +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h new file mode 100644 index 0000000000..b5c1859497 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800,"-Wunknown-warning-option") // 4251: class 'QScopedPointer' needs to have dll-interface to be used + // by clients of class 'QBrush' 4800: 'uint': forcing value to bool 'true' or 'false' (performance warning) +#include +AZ_POP_DISABLE_WARNING + +namespace AzToolsFramework +{ + //! @class RichTextHighlighter + //! @brief Highlights a given string given a matching substring. + class RichTextHighlighter + { + public: + AZ_CLASS_ALLOCATOR(RichTextHighlighter, AZ::SystemAllocator, 0); + RichTextHighlighter() = delete; + + static QString HighlightText(const QString& displayString, const QString& matchingSubstring); + static void PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect); + + }; +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index 056f16c52f..e0060e2b42 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -66,6 +66,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////// // EntityOutlinerListModel @@ -259,17 +260,7 @@ namespace AzToolsFramework if (s_paintingName && !m_filterString.empty()) { // highlight characters in filter - int highlightTextIndex = 0; - do - { - highlightTextIndex = label.lastIndexOf(QString(m_filterString.c_str()), highlightTextIndex - 1, Qt::CaseInsensitive); - if (highlightTextIndex >= 0) - { - const QString BACKGROUND_COLOR{ "#707070" }; - label.insert(highlightTextIndex + static_cast(m_filterString.length()), ""); - label.insert(highlightTextIndex, ""); - } - } while(highlightTextIndex > 0); + label = AzToolsFramework::RichTextHighlighter::HighlightText(label, m_filterString.c_str()); } return label; } @@ -2375,23 +2366,8 @@ namespace AzToolsFramework optionV4.text.clear(); optionV4.widget->style()->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter); - // Now we setup a Text Document so it can draw the rich text - QTextDocument textDoc; - textDoc.setDefaultFont(optionV4.font); - if (option.state & QStyle::State_Enabled) - { - textDoc.setDefaultStyleSheet("body {color: white}"); - } - else - { - textDoc.setDefaultStyleSheet("body {color: #7C7C7C}"); - } - textDoc.setHtml("" + entityNameRichText + ""); - painter->translate(textRect.topLeft()); - textDoc.setTextWidth(textRect.width()); - textDoc.drawContents(painter, QRectF(0, 0, textRect.width(), textRect.height())); + AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect); - painter->restore(); EntityOutlinerListModel::s_paintingName = false; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 05c07afecd..0d7bf05211 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -123,6 +123,8 @@ set(FILES ContainerEntity/ContainerEntitySystemComponent.h Editor/EditorContextMenuBus.h Editor/EditorSettingsAPIBus.h + Editor/RichTextHighlighter.h + Editor/RichTextHighlighter.cpp Entity/EditorEntityStartStatus.h Entity/EditorEntityAPIBus.h Entity/EditorEntityContextComponent.cpp