From 1ac3f4d8e8ee7461f047d34e196df40499e89557 Mon Sep 17 00:00:00 2001 From: Mikaƫl Capelle Date: Wed, 6 Jan 2021 19:43:21 +0100 Subject: Display children contents in collapsed separator. --- src/CMakeLists.txt | 1 + src/genericicondelegate.cpp | 16 ++------- src/genericicondelegate.h | 5 ++- src/icondelegate.cpp | 11 ++++-- src/icondelegate.h | 22 +++++++++--- src/modconflicticondelegate.cpp | 33 +++++------------- src/modconflicticondelegate.h | 15 ++++----- src/modcontenticondelegate.cpp | 57 +++++++++++++++++++++++++++++++ src/modcontenticondelegate.h | 30 +++++++++++++++++ src/modflagicondelegate.cpp | 16 ++------- src/modflagicondelegate.h | 22 ++++++------ src/modlist.cpp | 30 ----------------- src/modlist.h | 17 +++------- src/modlistview.cpp | 75 +++++++++++++++++++++++++++++++++++------ src/modlistview.h | 7 ++++ 15 files changed, 222 insertions(+), 135 deletions(-) create mode 100644 src/modcontenticondelegate.cpp create mode 100644 src/modcontenticondelegate.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a068f1a8..c274f989 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -149,6 +149,7 @@ add_filter(NAME src/modlist/view GROUPS modlistviewactions modlistcontextmenu modflagicondelegate + modcontenticondelegate modconflicticondelegate ) diff --git a/src/genericicondelegate.cpp b/src/genericicondelegate.cpp index 1e00f0e9..7afaca3f 100644 --- a/src/genericicondelegate.cpp +++ b/src/genericicondelegate.cpp @@ -4,28 +4,18 @@ #include -GenericIconDelegate::GenericIconDelegate(QObject *parent, int role, int logicalIndex, int compactSize) - : IconDelegate(parent) +GenericIconDelegate::GenericIconDelegate(QTreeView* parent, int role, int logicalIndex, int compactSize) + : IconDelegate(parent, logicalIndex, compactSize) , m_Role(role) - , m_LogicalIndex(logicalIndex) - , m_CompactSize(compactSize) - , m_Compact(false) { } -void GenericIconDelegate::columnResized(int logicalIndex, int, int newSize) -{ - if (logicalIndex == m_LogicalIndex) { - m_Compact = newSize < m_CompactSize; - } -} - QList GenericIconDelegate::getIcons(const QModelIndex &index) const { QList result; if (index.isValid()) { for (const QVariant &var : index.data(m_Role).toList()) { - if (!m_Compact || !var.toString().isEmpty()) { + if (!compact() || !var.toString().isEmpty()) { result.append(var.toString()); } } diff --git a/src/genericicondelegate.h b/src/genericicondelegate.h index 98605250..52db2bb6 100644 --- a/src/genericicondelegate.h +++ b/src/genericicondelegate.h @@ -20,9 +20,8 @@ public: * of the view, the delegate will turn off this behaviour if the column is smaller than "compactSize" * @param compactSize see explanation of logicalIndex */ - GenericIconDelegate(QObject *parent = nullptr, int role = Qt::UserRole + 1, int logicalIndex = -1, int compactSize = 150); -public slots: - void columnResized(int logicalIndex, int oldSize, int newSize); + GenericIconDelegate(QTreeView* parent, int role = Qt::UserRole + 1, int logicalIndex = -1, int compactSize = 150); + private: virtual QList getIcons(const QModelIndex &index) const; virtual size_t getNumIcons(const QModelIndex &index) const; diff --git a/src/icondelegate.cpp b/src/icondelegate.cpp index 901b5731..813395a2 100644 --- a/src/icondelegate.cpp +++ b/src/icondelegate.cpp @@ -27,9 +27,16 @@ along with Mod Organizer. If not, see . using namespace MOBase; -IconDelegate::IconDelegate(QObject* parent) - : QStyledItemDelegate(parent) +IconDelegate::IconDelegate(QTreeView* view, int column, int compactSize) : + QStyledItemDelegate(view), m_column(column), m_compactSize(compactSize), m_compact(false) { + if (view) { + connect(view->header(), &QHeaderView::sectionResized, [=](int column, int, int size) { + if (column == m_column) { + m_compact = size < m_compactSize; + } + }); + } } void IconDelegate::paintIcons( diff --git a/src/icondelegate.h b/src/icondelegate.h index bac71a62..a123470e 100644 --- a/src/icondelegate.h +++ b/src/icondelegate.h @@ -20,9 +20,9 @@ along with Mod Organizer. If not, see . #ifndef ICONDELEGATE_H #define ICONDELEGATE_H -#include "modinfo.h" -#include #include +#include +#include class IconDelegate : public QStyledItemDelegate @@ -30,16 +30,28 @@ class IconDelegate : public QStyledItemDelegate Q_OBJECT; public: - explicit IconDelegate(QObject *parent = 0); - virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + explicit IconDelegate(QTreeView* view, int column = -1, int compactSize = 100); + + void paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + +protected: + + // check if icons should be compacted or not + // + bool compact() const { return m_compact; } static void paintIcons( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index, const QList& icons); -protected: virtual QList getIcons(const QModelIndex &index) const = 0; virtual size_t getNumIcons(const QModelIndex &index) const = 0; + +private: + + int m_column; + int m_compactSize; + bool m_compact; }; #endif // ICONDELEGATE_H diff --git a/src/modconflicticondelegate.cpp b/src/modconflicticondelegate.cpp index 73c47a03..fc0ee48a 100644 --- a/src/modconflicticondelegate.cpp +++ b/src/modconflicticondelegate.cpp @@ -7,21 +7,10 @@ using namespace MOBase; ModConflictIconDelegate::ModConflictIconDelegate(ModListView* view, int logicalIndex, int compactSize) - : IconDelegate(view) - , m_View(view) - , m_LogicalIndex(logicalIndex) - , m_CompactSize(compactSize) - , m_Compact(false) + : IconDelegate(view, logicalIndex, compactSize), m_view(view) { } -void ModConflictIconDelegate::columnResized(int logicalIndex, int, int newSize) -{ - if (logicalIndex == m_LogicalIndex) { - m_Compact = newSize < m_CompactSize; - } -} - QList ModConflictIconDelegate::getIconsForFlags( std::vector flags, bool compact) { @@ -94,8 +83,8 @@ QList ModConflictIconDelegate::getIcons(const QModelIndex &index) const } bool compact; - auto flags = m_View->conflictFlags(index, &compact); - return getIconsForFlags(flags, compact || m_Compact); + auto flags = m_view->conflictFlags(index, &compact); + return getIconsForFlags(flags, compact || this->compact()); } QString ModConflictIconDelegate::getFlagIcon(ModInfo::EConflictFlag flag) @@ -119,19 +108,13 @@ QString ModConflictIconDelegate::getFlagIcon(ModInfo::EConflictFlag flag) size_t ModConflictIconDelegate::getNumIcons(const QModelIndex &index) const { - unsigned int modIdx = index.data(ModList::IndexRole).toInt(); - if (modIdx < ModInfo::getNumMods()) { - ModInfo::Ptr info = ModInfo::getByIndex(modIdx); - std::vector flags = info->getConflictFlags(); - size_t count = flags.size(); - if (std::find_first_of(flags.begin(), flags.end(), - s_ConflictFlags.begin(), s_ConflictFlags.end()) == flags.end()) { - ++count; - } - return count; - } else { + QVariant modIndex = index.data(ModList::IndexRole); + + if (!modIndex.isValid()) { return 0; } + + return m_view->conflictFlags(index, nullptr).size(); } QSize ModConflictIconDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &modelIndex) const diff --git a/src/modconflicticondelegate.h b/src/modconflicticondelegate.h index a44ce89b..fd524444 100644 --- a/src/modconflicticondelegate.h +++ b/src/modconflicticondelegate.h @@ -4,6 +4,7 @@ #include #include "icondelegate.h" +#include "modinfo.h" class ModListView; @@ -12,12 +13,9 @@ class ModConflictIconDelegate : public IconDelegate Q_OBJECT; public: - explicit ModConflictIconDelegate(ModListView* parent = nullptr, int logicalIndex = -1, int compactSize = 80); + explicit ModConflictIconDelegate(ModListView* view, int logicalIndex = -1, int compactSize = 80); QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex &index) const override; -public slots: - void columnResized(int logicalIndex, int oldSize, int newSize); - protected: static QList getIconsForFlags(std::vector flags, bool compact); @@ -26,6 +24,10 @@ protected: QList getIcons(const QModelIndex &index) const override; size_t getNumIcons(const QModelIndex &index) const override; + // constructor for color table + // + ModConflictIconDelegate() : ModConflictIconDelegate(nullptr) { } + private: static constexpr std::array s_ConflictFlags{ ModInfo::FLAG_CONFLICT_MIXED, @@ -43,10 +45,7 @@ private: ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITTEN }; - ModListView* m_View; - int m_LogicalIndex; - int m_CompactSize; - bool m_Compact; + ModListView* m_view; }; #endif // MODCONFLICTICONDELEGATE_H diff --git a/src/modcontenticondelegate.cpp b/src/modcontenticondelegate.cpp new file mode 100644 index 00000000..57a4dc6d --- /dev/null +++ b/src/modcontenticondelegate.cpp @@ -0,0 +1,57 @@ +#include "modcontenticondelegate.h" + +#include "modlistview.h" + +ModContentIconDelegate::ModContentIconDelegate(ModListView* view, int column, int compactSize) + : IconDelegate(view, column, compactSize), m_view(view) +{ +} + +QList ModContentIconDelegate::getIcons(const QModelIndex& index) const +{ + QVariant modIndex = index.data(ModList::IndexRole); + + if (!modIndex.isValid()) { + return {}; + } + + bool compact; + auto icons = m_view->contentsIcons(index, &compact); + + if (compact || this->compact()) { + icons.removeAll(QString()); + } + + return icons; +} + +size_t ModContentIconDelegate::getNumIcons(const QModelIndex& index) const +{ + return getIcons(index).size(); +} + +bool ModContentIconDelegate::helpEvent( + QHelpEvent* event, QAbstractItemView* view, const QStyleOptionViewItem& option, const QModelIndex& index) +{ + if (!event || !view) { + return false; + } + if (event->type() == QEvent::ToolTip) { + // this code is from QAbstractItemDelegate::helpEvent, only the the way + // text is retrieved has been changed + QHelpEvent* he = static_cast(event); + const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp + const QString tooltip = index.isValid() ? m_view->contentsTooltip(index) : QString(); + QRect rect; + if (index.isValid()) { + const QRect r = view->visualRect(index); + rect = QRect(view->mapToGlobal(r.topLeft()), r.size()); + } + QToolTip::showText(he->globalPos(), tooltip, view, rect); + event->setAccepted(!tooltip.isEmpty()); + return true; + } + else { + return IconDelegate::helpEvent(event, view, option, index); + } +} diff --git a/src/modcontenticondelegate.h b/src/modcontenticondelegate.h new file mode 100644 index 00000000..c195df18 --- /dev/null +++ b/src/modcontenticondelegate.h @@ -0,0 +1,30 @@ +#ifndef MODCONTENTICONDELEGATE_H +#define MODCONTENTICONDELEGATE_H + +#include "icondelegate.h" + +class ModListView; + +class ModContentIconDelegate : public IconDelegate +{ + Q_OBJECT +public: + + explicit ModContentIconDelegate(ModListView* view, int column = -1, int compactSize = 150); + + bool helpEvent(QHelpEvent* event, QAbstractItemView* view, + const QStyleOptionViewItem& option, const QModelIndex& index) override; + +protected: + QList getIcons(const QModelIndex& index) const override; + size_t getNumIcons(const QModelIndex& index) const override; + + // constructor for color table + // + ModContentIconDelegate() : ModContentIconDelegate(nullptr) { } + +private: + ModListView* m_view; +}; + +#endif // GENERICICONDELEGATE_H diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp index 3ac1085e..c709f30d 100644 --- a/src/modflagicondelegate.cpp +++ b/src/modflagicondelegate.cpp @@ -5,21 +5,11 @@ using namespace MOBase; -ModFlagIconDelegate::ModFlagIconDelegate(QObject *parent, int logicalIndex, int compactSize) - : IconDelegate(parent) - , m_LogicalIndex(logicalIndex) - , m_CompactSize(compactSize) - , m_Compact(false) +ModFlagIconDelegate::ModFlagIconDelegate(QTreeView* view, int column, int compactSize) + : IconDelegate(view, column, compactSize) { } -void ModFlagIconDelegate::columnResized(int logicalIndex, int, int newSize) -{ - if (logicalIndex == m_LogicalIndex) { - m_Compact = newSize < m_CompactSize; - } -} - QList ModFlagIconDelegate::getIconsForFlags( std::vector flags, bool compact) { @@ -44,7 +34,7 @@ QList ModFlagIconDelegate::getIcons(const QModelIndex &index) const if (modid.isValid()) { ModInfo::Ptr info = ModInfo::getByIndex(modid.toInt()); - return getIconsForFlags(info->getFlags(), m_Compact); + return getIconsForFlags(info->getFlags(), compact()); } return {}; diff --git a/src/modflagicondelegate.h b/src/modflagicondelegate.h index c6c7c3e8..63ab8978 100644 --- a/src/modflagicondelegate.h +++ b/src/modflagicondelegate.h @@ -1,32 +1,30 @@ #ifndef MODFLAGICONDELEGATE_H #define MODFLAGICONDELEGATE_H +#include + #include "icondelegate.h" +#include "modinfo.h" class ModFlagIconDelegate : public IconDelegate { Q_OBJECT; public: - explicit ModFlagIconDelegate(QObject *parent = 0, int logicalIndex = -1, int compactSize = 120); + explicit ModFlagIconDelegate(QTreeView* view, int column = -1, int compactSize = 120); QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; - static QList getIconsForFlags( - std::vector flags, bool compact); - +protected: + static QList getIconsForFlags(std::vector flags, bool compact); static QString getFlagIcon(ModInfo::EFlag flag); -public slots: - void columnResized(int logicalIndex, int oldSize, int newSize); - -protected: QList getIcons(const QModelIndex &index) const override; size_t getNumIcons(const QModelIndex &index) const override; -private: - int m_LogicalIndex; - int m_CompactSize; - bool m_Compact; + // constructor for color table + // + ModFlagIconDelegate() : ModFlagIconDelegate(nullptr) { } + }; #endif // MODFLAGICONDELEGATE_H diff --git a/src/modlist.cpp b/src/modlist.cpp index ea1d2754..055778f3 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -194,30 +194,6 @@ QString ModList::getConflictFlagText(ModInfo::EConflictFlag flag, ModInfo::Ptr m } } - -QVariantList ModList::contentsToIcons(const std::set &contents) const -{ - QVariantList result; - m_Organizer->modDataContents().forEachContentInOrOut( - contents, - [&result](auto const& content) { result.append(content.icon()); }, - [&result](auto const&) { result.append(QString()); }); - return result; -} - -QString ModList::contentsToToolTip(const std::set &contents) const -{ - QString result(""); - m_Organizer->modDataContents().forEachContentIn(contents, [&result](auto const& content) { - result.append(QString("" - "") - .arg(content.icon()).arg(content.name())); - }); - result.append("
%2
"); - return result; -} - - QVariant ModList::data(const QModelIndex &modelIndex, int role) const { if (m_Profile == nullptr) return QVariant(); @@ -385,9 +361,6 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const default: return QtGroupingProxy::AGGR_NONE; } } - else if (role == ContentsRole) { - return contentsToIcons(modInfo->getContents()); - } else if (role == GameNameRole) { return modInfo->gameName(); } @@ -494,9 +467,6 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return result; } - else if (column == COL_CONTENT) { - return contentsToToolTip(modInfo->getContents()); - } else if (column == COL_NAME) { try { return modInfo->getDescription(); diff --git a/src/modlist.h b/src/modlist.h index 1d94749c..5c7f28ee 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -69,19 +69,14 @@ public: // grouping I assume?) AggrRole = Qt::UserRole + 2, - // data(ContentsRole) contains mod data contents as a QVariantList - // containing icon paths - ContentsRole = Qt::UserRole + 3, - - GameNameRole = Qt::UserRole + 4, - - PriorityRole = Qt::UserRole + 5, + GameNameRole = Qt::UserRole + 3, + PriorityRole = Qt::UserRole + 4, // marking role for the scrollbar - ScrollMarkRole = Qt::UserRole + 6, + ScrollMarkRole = Qt::UserRole + 5, // this is the first available role - ModUserRole = Qt::UserRole + 7 + ModUserRole = Qt::UserRole + 6 }; enum EColumn { @@ -354,10 +349,6 @@ private: QString getColumnToolTip(int column) const; - QVariantList contentsToIcons(const std::set &contentIds) const; - - QString contentsToToolTip(const std::set &contentsIds) const; - ModList::EColumn getEnabledColumn(int index) const; QVariant categoryData(int categoryID, int column, int role) const; diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 4b285733..63999ce9 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -18,6 +18,7 @@ #include "log.h" #include "modflagicondelegate.h" #include "modconflicticondelegate.h" +#include "modcontenticondelegate.h" #include "modlistviewactions.h" #include "modlistdropinfo.h" #include "modlistcontextmenu.h" @@ -741,17 +742,9 @@ void ModListView::setup(OrganizerCore& core, CategoryFactory& factory, MainWindo connect(header(), &QHeaderView::sectionResized, [=](int logicalIndex, int oldSize, int newSize) { m_sortProxy->setColumnVisible(logicalIndex, newSize != 0); }); - GenericIconDelegate* contentDelegate = new GenericIconDelegate(this, ModList::ContentsRole, ModList::COL_CONTENT, 150); - ModFlagIconDelegate* flagDelegate = new ModFlagIconDelegate(this, ModList::COL_FLAGS, 120); - ModConflictIconDelegate* conflictFlagDelegate = new ModConflictIconDelegate(this, ModList::COL_CONFLICTFLAGS, 80); - - connect(header(), &QHeaderView::sectionResized, contentDelegate, &GenericIconDelegate::columnResized); - connect(header(), &QHeaderView::sectionResized, flagDelegate, &ModFlagIconDelegate::columnResized); - connect(header(), &QHeaderView::sectionResized, conflictFlagDelegate, &ModConflictIconDelegate::columnResized); - - setItemDelegateForColumn(ModList::COL_FLAGS, flagDelegate); - setItemDelegateForColumn(ModList::COL_CONFLICTFLAGS, conflictFlagDelegate); - setItemDelegateForColumn(ModList::COL_CONTENT, contentDelegate); + setItemDelegateForColumn(ModList::COL_FLAGS, new ModFlagIconDelegate(this, ModList::COL_FLAGS, 120)); + setItemDelegateForColumn(ModList::COL_CONFLICTFLAGS, new ModConflictIconDelegate(this, ModList::COL_CONFLICTFLAGS, 80)); + setItemDelegateForColumn(ModList::COL_CONTENT, new ModContentIconDelegate(this, ModList::COL_CONTENT, 150)); if (m_core->settings().geometry().restoreState(header())) { // hack: force the resize-signal to be triggered because restoreState doesn't seem to do that @@ -1118,6 +1111,66 @@ std::vector ModListView::conflictFlags(const QModelIndex return flags; } +std::set ModListView::contents(const QModelIndex& index, bool* includeChildren) const +{ + auto modIndex = index.data(ModList::IndexRole); + if (!modIndex.isValid()) { + return {}; + } + ModInfo::Ptr info = ModInfo::getByIndex(index.data(ModList::IndexRole).toInt()); + auto contents = info->getContents(); + bool children = false; + + if (info->isSeparator() + && hasCollapsibleSeparators() + && m_core->settings().interface().collapsibleSeparatorsConflicts() + && !isExpanded(index.sibling(index.row(), 0))) { + + // combine the child contents + std::set eContents(contents.begin(), contents.end()); + for (int i = 0; i < model()->rowCount(index); ++i) { + auto cIndex = model()->index(i, index.column(), index).data(ModList::IndexRole).toInt(); + auto cContents = ModInfo::getByIndex(cIndex)->getContents(); + eContents.insert(cContents.begin(), cContents.end()); + } + contents = { eContents.begin(), eContents.end() }; + children = true; + } + + if (includeChildren) { + *includeChildren = children; + } + + return contents; +} + +QList ModListView::contentsIcons(const QModelIndex& index, bool* forceCompact) const +{ + auto contents = this->contents(index, forceCompact); + QList result; + m_core->modDataContents().forEachContentInOrOut( + contents, + [&result](auto const& content) { result.append(content.icon()); }, + [&result](auto const&) { result.append(QString()); }); + return result; +} + +QString ModListView::contentsTooltip(const QModelIndex& index) const +{ + auto contents = this->contents(index, nullptr); + if (contents.empty()) { + return {}; + } + QString result(""); + m_core->modDataContents().forEachContentIn(contents, [&result](auto const& content) { + result.append(QString("" + "") + .arg(content.icon()).arg(content.name())); + }); + result.append("
%2
"); + return result; +} + void ModListView::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { if (hasCollapsibleSeparators()) { diff --git a/src/modlistview.h b/src/modlistview.h index 2fed4969..48e003bd 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -173,6 +173,7 @@ protected slots: private: friend class ModConflictIconDelegate; + friend class ModContentIconDelegate; friend class ModListStyledItemDelegated; friend class ModListViewMarkingScrollBar; @@ -199,6 +200,12 @@ private: std::vector conflictFlags( const QModelIndex& index, bool* forceCompact = nullptr) const; + // retrieve the content icons and tooltip for the given index + // + std::set contents(const QModelIndex& index, bool* includeChildren) const; + QList contentsIcons(const QModelIndex& index, bool* forceCompact = nullptr) const; + QString contentsTooltip(const QModelIndex& index) const; + // get/set the selected items on the view, this method return/take indices // from the mod list model, not the view, so it's safe to restore // -- cgit v1.3.1