From 87dac464d9ec488737b16839b0f06586eadb837e Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 31 Dec 2020 23:36:14 +0100 Subject: Fix position of markers in scrollbar for non-flat models. --- src/viewmarkingscrollbar.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/viewmarkingscrollbar.cpp') diff --git a/src/viewmarkingscrollbar.cpp b/src/viewmarkingscrollbar.cpp index 2452d0e3..ed17120b 100644 --- a/src/viewmarkingscrollbar.cpp +++ b/src/viewmarkingscrollbar.cpp @@ -1,4 +1,5 @@ #include "viewmarkingscrollbar.h" +#include "modelutils.h" #include #include #include @@ -27,11 +28,13 @@ void ViewMarkingScrollBar::paintEvent(QPaintEvent *event) QRect handleRect = style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, QStyle::SC_ScrollBarSlider, this); QRect innerRect = style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, QStyle::SC_ScrollBarGroove, this); + auto indices = flatIndex(m_Model, 0, QModelIndex()); + painter.translate(innerRect.topLeft() + QPoint(0, 3)); - qreal scale = static_cast(innerRect.height() - 3) / static_cast(m_Model->rowCount()); + qreal scale = static_cast(innerRect.height() - 3) / static_cast(indices.size()); - for (int i = 0; i < m_Model->rowCount(); ++i) { - QVariant data = m_Model->data(m_Model->index(i, 0), m_Role); + for (int i = 0; i < indices.size(); ++i) { + QVariant data = indices[i].data(m_Role); if (data.isValid()) { QColor col = data.value(); painter.setPen(col); -- cgit v1.3.1 From e02ba3b26d30ffb5010394992c69e94b287eacd7 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Fri, 1 Jan 2021 12:24:57 +0100 Subject: Some cleaning. Avoid using Qt::UserRole. --- src/modconflicticondelegate.cpp | 7 +++-- src/modflagicondelegate.cpp | 7 +++-- src/modlist.cpp | 64 ++++++++++++++++++++++++++++------------- src/modlist.h | 32 +++++++++++++++++++-- src/modlistcontextmenu.cpp | 15 ++++++---- src/modlistsortproxy.cpp | 13 +-------- src/modlistview.cpp | 24 +++++++++------- src/pluginlist.cpp | 2 +- src/pluginlistview.cpp | 4 +-- src/viewmarkingscrollbar.cpp | 14 ++++----- src/viewmarkingscrollbar.h | 14 ++++----- 11 files changed, 121 insertions(+), 75 deletions(-) (limited to 'src/viewmarkingscrollbar.cpp') diff --git a/src/modconflicticondelegate.cpp b/src/modconflicticondelegate.cpp index 2ccf3363..9680aca3 100644 --- a/src/modconflicticondelegate.cpp +++ b/src/modconflicticondelegate.cpp @@ -1,4 +1,5 @@ #include "modconflicticondelegate.h" +#include "modlist.h" #include #include @@ -96,7 +97,7 @@ QList ModConflictIconDelegate::getIconsForFlags( QList ModConflictIconDelegate::getIcons(const QModelIndex &index) const { - QVariant modid = index.data(Qt::UserRole + 1); + QVariant modid = index.data(ModList::IndexRole); if (modid.isValid()) { ModInfo::Ptr info = ModInfo::getByIndex(modid.toInt()); @@ -127,7 +128,7 @@ QString ModConflictIconDelegate::getFlagIcon(ModInfo::EConflictFlag flag) size_t ModConflictIconDelegate::getNumIcons(const QModelIndex &index) const { - unsigned int modIdx = index.data(Qt::UserRole + 1).toInt(); + unsigned int modIdx = index.data(ModList::IndexRole).toInt(); if (modIdx < ModInfo::getNumMods()) { ModInfo::Ptr info = ModInfo::getByIndex(modIdx); std::vector flags = info->getConflictFlags(); @@ -145,7 +146,7 @@ size_t ModConflictIconDelegate::getNumIcons(const QModelIndex &index) const QSize ModConflictIconDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &modelIndex) const { size_t count = getNumIcons(modelIndex); - unsigned int index = modelIndex.data(Qt::UserRole + 1).toInt(); + unsigned int index = modelIndex.data(ModList::IndexRole).toInt(); QSize result; if (index < ModInfo::getNumMods()) { result = QSize(static_cast(count) * 40, 20); diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp index bec3c97d..3ac1085e 100644 --- a/src/modflagicondelegate.cpp +++ b/src/modflagicondelegate.cpp @@ -1,4 +1,5 @@ #include "modflagicondelegate.h" +#include "modlist.h" #include #include @@ -39,7 +40,7 @@ QList ModFlagIconDelegate::getIconsForFlags( QList ModFlagIconDelegate::getIcons(const QModelIndex &index) const { - QVariant modid = index.data(Qt::UserRole + 1); + QVariant modid = index.data(ModList::IndexRole); if (modid.isValid()) { ModInfo::Ptr info = ModInfo::getByIndex(modid.toInt()); @@ -71,7 +72,7 @@ QString ModFlagIconDelegate::getFlagIcon(ModInfo::EFlag flag) size_t ModFlagIconDelegate::getNumIcons(const QModelIndex &index) const { - unsigned int modIdx = index.data(Qt::UserRole + 1).toInt(); + unsigned int modIdx = index.data(ModList::IndexRole).toInt(); if (modIdx < ModInfo::getNumMods()) { ModInfo::Ptr info = ModInfo::getByIndex(modIdx); std::vector flags = info->getFlags(); @@ -85,7 +86,7 @@ size_t ModFlagIconDelegate::getNumIcons(const QModelIndex &index) const QSize ModFlagIconDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &modelIndex) const { size_t count = getNumIcons(modelIndex); - unsigned int index = modelIndex.data(Qt::UserRole + 1).toInt(); + unsigned int index = modelIndex.data(ModList::IndexRole).toInt(); QSize result; if (index < ModInfo::getNumMods()) { result = QSize(static_cast(count) * 40, 20); diff --git a/src/modlist.cpp b/src/modlist.cpp index 077f4af3..26581ba5 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -61,6 +61,8 @@ along with Mod Organizer. If not, see . using namespace MOBase; +const int ModList::ModUserRole = Qt::UserRole + QMetaEnum::fromType().keyCount(); + ModList::ModList(PluginContainer *pluginContainer, OrganizerCore *organizer) : QAbstractItemModel(organizer) , m_Organizer(organizer) @@ -130,7 +132,7 @@ QVariant ModList::getOverwriteData(int column, int role) const } } break; case Qt::TextAlignmentRole: return QVariant(Qt::AlignCenter | Qt::AlignVCenter); - case Qt::UserRole: return -1; + case GroupingRole: return -1; case Qt::ForegroundRole: return QBrush(Qt::red); case Qt::ToolTipRole: return tr("This entry contains files that have been created inside the virtual data tree (i.e. by the construction kit)"); default: return QVariant(); @@ -298,7 +300,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { return QVariant(); } - } else if (role == Qt::TextAlignmentRole) { + } + else if (role == Qt::TextAlignmentRole) { auto flags = modInfo->getFlags(); if (column == COL_NAME) { if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_CENTER) { @@ -313,7 +316,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { return QVariant(Qt::AlignCenter | Qt::AlignVCenter); } - } else if (role == Qt::UserRole) { + } + else if (role == GroupingRole) { if (column == COL_CATEGORY) { QVariantList categoryNames; std::set categories = modInfo->getCategories(); @@ -326,7 +330,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { return QVariant(); } - } else if (column == COL_PRIORITY) { + } + else if (column == COL_PRIORITY) { int priority = modInfo->getFixedPriority(); if (priority != INT_MIN) { return priority; @@ -336,9 +341,11 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { return modInfo->nexusId(); } - } else if (role == IndexRole) { + } + else if (role == IndexRole) { return modIndex; - } else if (role == Qt::UserRole + 2) { + } + else if (role == AggrRole) { switch (column) { case COL_MODID: return QtGroupingProxy::AGGR_FIRST; case COL_VERSION: return QtGroupingProxy::AGGR_MAX; @@ -346,11 +353,23 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const case COL_PRIORITY: return QtGroupingProxy::AGGR_MIN; default: return QtGroupingProxy::AGGR_NONE; } - } else if (role == Qt::UserRole + 3) { + } + else if (role == ContentsRole) { return contentsToIcons(modInfo->getContents()); - } else if (role == Qt::UserRole + 4) { + } + else if (role == NameRole) { return modInfo->gameName(); - } else if (role == Qt::FontRole) { + } + else if (role == PriorityRole) { + int priority = modInfo->getFixedPriority(); + if (priority != std::numeric_limits::min()) { + return priority; + } + else { + return m_Profile->getModPriority(modIndex); + } + } + else if (role == Qt::FontRole) { QFont result; auto flags = modInfo->getFlags(); if (column == COL_NAME) { @@ -374,7 +393,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } } return result; - } else if (role == Qt::DecorationRole) { + } + else if (role == Qt::DecorationRole) { if (column == COL_VERSION) { if (modInfo->updateAvailable()) { return QIcon(":/MO/gui/update_available"); @@ -385,7 +405,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } } return QVariant(); - } else if (role == Qt::ForegroundRole) { + } + else if (role == Qt::ForegroundRole) { if ((modInfo->hasFlag(ModInfo::FLAG_SEPARATOR) || (column == COL_NOTES)) && modInfo->color().isValid()) { return ColorSettings::idealTextColor(modInfo->color()); } else if (column == COL_NAME) { @@ -404,8 +425,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } } return QVariant(); - } else if ((role == Qt::BackgroundRole) - || (role == ViewMarkingScrollBar::DEFAULT_ROLE)) { + } + else if (role == Qt::BackgroundRole || role == ScrollMarkRole) { bool overwrite = m_Overwrite.find(modIndex) != m_Overwrite.end(); bool archiveOverwrite = m_ArchiveOverwrite.find(modIndex) != m_ArchiveOverwrite.end(); bool archiveLooseOverwrite = m_ArchiveLooseOverwrite.find(modIndex) != m_ArchiveLooseOverwrite.end(); @@ -424,15 +445,15 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return Settings::instance().colors().modlistOverwritingArchive(); } else if (archiveOverwrite) { return Settings::instance().colors().modlistOverwrittenArchive(); - } else if (modInfo->hasFlag(ModInfo::FLAG_SEPARATOR) - && modInfo->color().isValid() - && ((role != ViewMarkingScrollBar::DEFAULT_ROLE) - || Settings::instance().colors().colorSeparatorScrollbar())) { + } else if (modInfo->isSeparator() && modInfo->color().isValid() + && (role != ScrollMarkRole + || Settings::instance().colors().colorSeparatorScrollbar())) { return modInfo->color(); } else { return QVariant(); } - } else if (role == Qt::ToolTipRole) { + } + else if (role == Qt::ToolTipRole) { if (column == COL_FLAGS) { QString result; @@ -507,7 +528,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const } else { return QVariant(); } - } else { + } + else { return QVariant(); } } @@ -1366,7 +1388,9 @@ QModelIndex ModList::parent(const QModelIndex&) const QMap ModList::itemData(const QModelIndex &index) const { QMap result = QAbstractItemModel::itemData(index); - result[Qt::UserRole] = data(index, Qt::UserRole); + for (int role = Qt::UserRole; role < ModUserRole; ++role) { + result[role] = data(index, role); + } return result; } diff --git a/src/modlist.h b/src/modlist.h index 4b0e0157..e77ceb1f 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -31,6 +31,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #ifndef Q_MOC_RUN #include @@ -56,9 +57,34 @@ class ModList : public QAbstractItemModel public: - // role of the index of the mod - // - constexpr static int IndexRole = Qt::UserRole + 1; + enum ModListRole { + + // data(GroupingRole) contains the "group" role - This is used by the + // category and Nexus ID grouping proxy (but not the ByPriority proxy) + GroupingRole = Qt::UserRole, + + IndexRole = Qt::UserRole + 1, + + // data(AggrRole) contains aggregation information (for + // grouping I assume?) + AggrRole = Qt::UserRole + 2, + + // data(ContentsRole) contains mod data contents as a QVariantList + // containing icon paths + ContentsRole = Qt::UserRole + 3, + + NameRole = Qt::UserRole + 4, + + PriorityRole = Qt::UserRole + 5, + + // marking role for the scrollbar + ScrollMarkRole = Qt::UserRole + 6 + }; + + Q_ENUM(ModListRole) + + // this is the first available role + static const int ModUserRole; enum EColumn { COL_NAME, diff --git a/src/modlistcontextmenu.cpp b/src/modlistcontextmenu.cpp index 303362ba..01c4b471 100644 --- a/src/modlistcontextmenu.cpp +++ b/src/modlistcontextmenu.cpp @@ -159,23 +159,26 @@ ModListContextMenu::ModListContextMenu( m_selected = { index }; } + ModInfo::Ptr info = ModInfo::getByIndex(index.data(ModList::IndexRole).toInt()); + QMenu* allMods = new ModListGlobalContextMenu(core, view, view); allMods->setTitle(tr("All Mods")); addMenu(allMods); - if (view->hasCollapsibleSeparators()) { + auto viewIndex = view->indexModelToView(m_index); + if (view->model()->hasChildren(viewIndex)) { + bool expanded = view->isExpanded(viewIndex); addAction(tr("Collapse all"), view, &QTreeView::collapseAll); + addAction(tr("Collapse others"), [=]() { + m_view->collapseAll(); + m_view->setExpanded(viewIndex, expanded); + }); addAction(tr("Expand all"), view, &QTreeView::expandAll); } addSeparator(); // Add type-specific items - ModInfo::Ptr info = ModInfo::getByIndex(index.data(ModList::IndexRole).toInt()); - - // TODO: - // - Don't forget to check for the sort priority for "Send To... " - if (info->isOverwrite()) { addOverwriteActions(info); } diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 455daa76..054b980c 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -120,18 +120,7 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, ModInfo::Ptr leftMod = ModInfo::getByIndex(leftIndex); ModInfo::Ptr rightMod = ModInfo::getByIndex(rightIndex); - bool lt = false; - - { - QModelIndex leftPrioIdx = left.sibling(left.row(), ModList::COL_PRIORITY); - QVariant leftPrio = leftPrioIdx.data(); - if (!leftPrio.isValid()) leftPrio = left.data(Qt::UserRole); - QModelIndex rightPrioIdx = right.sibling(right.row(), ModList::COL_PRIORITY); - QVariant rightPrio = rightPrioIdx.data(); - if (!rightPrio.isValid()) rightPrio = right.data(Qt::UserRole); - - lt = leftPrio.toInt() < rightPrio.toInt(); - } + bool lt = left.data(ModList::PriorityRole).toInt() < right.data(ModList::PriorityRole).toInt(); switch (left.column()) { case ModList::COL_FLAGS: { diff --git a/src/modlistview.cpp b/src/modlistview.cpp index f62089b5..80aa6495 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -67,7 +67,7 @@ ModListView::ModListView(QWidget* parent) , m_byPriorityProxy(nullptr) , m_byCategoryProxy(nullptr) , m_byNexusIdProxy(nullptr) - , m_scrollbar(new ViewMarkingScrollBar(this->model(), this)) + , m_scrollbar(new ViewMarkingScrollBar(this->model(), ModList::ScrollMarkRole, this)) { setVerticalScrollBar(m_scrollbar); MOBase::setCustomizableColumns(this); @@ -79,6 +79,13 @@ ModListView::ModListView(QWidget* parent) connect(this, &ModListView::customContextMenuRequested, this, &ModListView::onCustomContextMenuRequested); } +void ModListView::setModel(QAbstractItemModel* model) +{ + QTreeView::setModel(model); + setVerticalScrollBar(new ViewMarkingScrollBar(model, ModList::ScrollMarkRole, this)); +} + + void ModListView::refresh() { updateGroupByProxy(-1); @@ -593,12 +600,13 @@ void ModListView::setup(OrganizerCore& core, CategoryFactory& factory, MainWindo connect(m_byPriorityProxy, &ModListByPriorityProxy::expandItem, this, &ModListView::expandItem); m_byCategoryProxy = new QtGroupingProxy(core.modList(), QModelIndex(), ModList::COL_CATEGORY, - Qt::UserRole, 0, Qt::UserRole + 2); + ModList::GroupingRole, 0, ModList::AggrRole); connect(this, &QTreeView::expanded, m_byCategoryProxy, &QtGroupingProxy::expanded); connect(this, &QTreeView::collapsed, m_byCategoryProxy, &QtGroupingProxy::collapsed); connect(m_byCategoryProxy, &QtGroupingProxy::expandItem, this, &ModListView::expandItem); - m_byNexusIdProxy = new QtGroupingProxy(core.modList(), QModelIndex(), ModList::COL_MODID, Qt::DisplayRole, - QtGroupingProxy::FLAG_NOGROUPNAME | QtGroupingProxy::FLAG_NOSINGLE, Qt::UserRole + 2); + m_byNexusIdProxy = new QtGroupingProxy(core.modList(), QModelIndex(), ModList::COL_MODID, + ModList::GroupingRole, QtGroupingProxy::FLAG_NOGROUPNAME | QtGroupingProxy::FLAG_NOSINGLE, + ModList::AggrRole); connect(this, &QTreeView::expanded, m_byNexusIdProxy, &QtGroupingProxy::expanded); connect(this, &QTreeView::collapsed, m_byNexusIdProxy, &QtGroupingProxy::collapsed); connect(m_byNexusIdProxy, &QtGroupingProxy::expandItem, this, &ModListView::expandItem); @@ -627,7 +635,7 @@ 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, Qt::UserRole + 3, ModList::COL_CONTENT, 150); + 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); @@ -722,12 +730,6 @@ void ModListView::saveState(Settings& s) const m_filters->saveState(s); } -void ModListView::setModel(QAbstractItemModel* model) -{ - QTreeView::setModel(model); - setVerticalScrollBar(new ViewMarkingScrollBar(model, this)); -} - QRect ModListView::visualRect(const QModelIndex& index) const { // this shift the visualRect() from QTreeView to match the new actual diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 4d648a46..9e101f84 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -990,7 +990,7 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const return checkstateData(modelIndex); } else if (role == Qt::ForegroundRole) { return foregroundData(modelIndex); - } else if (role == Qt::BackgroundRole || (role == ViewMarkingScrollBar::DEFAULT_ROLE)) { + } else if (role == Qt::BackgroundRole) { return backgroundData(modelIndex); } else if (role == Qt::FontRole) { return fontData(modelIndex); diff --git a/src/pluginlistview.cpp b/src/pluginlistview.cpp index f95226fc..589c5737 100644 --- a/src/pluginlistview.cpp +++ b/src/pluginlistview.cpp @@ -21,7 +21,7 @@ using namespace MOBase; PluginListView::PluginListView(QWidget *parent) : QTreeView(parent) , m_sortProxy(nullptr) - , m_Scrollbar(new ViewMarkingScrollBar(this->model(), this)) + , m_Scrollbar(new ViewMarkingScrollBar(this->model(), Qt::BackgroundRole, this)) , m_didUpdateMasterList(false) { setVerticalScrollBar(m_Scrollbar); @@ -31,7 +31,7 @@ PluginListView::PluginListView(QWidget *parent) void PluginListView::setModel(QAbstractItemModel *model) { QTreeView::setModel(model); - setVerticalScrollBar(new ViewMarkingScrollBar(model, this)); + setVerticalScrollBar(new ViewMarkingScrollBar(model, Qt::BackgroundRole, this)); } int PluginListView::sortColumn() const diff --git a/src/viewmarkingscrollbar.cpp b/src/viewmarkingscrollbar.cpp index ed17120b..0991f171 100644 --- a/src/viewmarkingscrollbar.cpp +++ b/src/viewmarkingscrollbar.cpp @@ -4,18 +4,18 @@ #include #include -ViewMarkingScrollBar::ViewMarkingScrollBar(QAbstractItemModel *model, QWidget *parent, int role) +ViewMarkingScrollBar::ViewMarkingScrollBar(QAbstractItemModel* model, int role, QWidget *parent) : QScrollBar(parent) - , m_Model(model) - , m_Role(role) + , m_model(model) + , m_role(role) { // not implemented for horizontal sliders Q_ASSERT(this->orientation() == Qt::Vertical); } -void ViewMarkingScrollBar::paintEvent(QPaintEvent *event) +void ViewMarkingScrollBar::paintEvent(QPaintEvent* event) { - if (m_Model == nullptr) { + if (m_model == nullptr) { return; } QScrollBar::paintEvent(event); @@ -28,13 +28,13 @@ void ViewMarkingScrollBar::paintEvent(QPaintEvent *event) QRect handleRect = style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, QStyle::SC_ScrollBarSlider, this); QRect innerRect = style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, QStyle::SC_ScrollBarGroove, this); - auto indices = flatIndex(m_Model, 0, QModelIndex()); + auto indices = flatIndex(m_model, 0, QModelIndex()); painter.translate(innerRect.topLeft() + QPoint(0, 3)); qreal scale = static_cast(innerRect.height() - 3) / static_cast(indices.size()); for (int i = 0; i < indices.size(); ++i) { - QVariant data = indices[i].data(m_Role); + QVariant data = indices[i].data(m_role); if (data.isValid()) { QColor col = data.value(); painter.setPen(col); diff --git a/src/viewmarkingscrollbar.h b/src/viewmarkingscrollbar.h index 12a297d1..88d77039 100644 --- a/src/viewmarkingscrollbar.h +++ b/src/viewmarkingscrollbar.h @@ -1,21 +1,21 @@ #ifndef VIEWMARKINGSCROLLBAR_H #define VIEWMARKINGSCROLLBAR_H -#include #include +#include class ViewMarkingScrollBar : public QScrollBar { public: - static const int DEFAULT_ROLE = Qt::UserRole + 42; -public: - ViewMarkingScrollBar(QAbstractItemModel *model, QWidget *parent = 0, int role = DEFAULT_ROLE); + ViewMarkingScrollBar(QAbstractItemModel *model, int role, QWidget* parent = nullptr); + protected: - virtual void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; + private: - QAbstractItemModel *m_Model; - int m_Role; + QAbstractItemModel* m_model; + int m_role; }; -- cgit v1.3.1 From e5f43788e874e638e1d4dbab20451c36e52df10d Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Fri, 1 Jan 2021 13:51:36 +0100 Subject: Visual fixes for the modlist. - Fix invalid positions of markers in the scrollbar. - Use color from children for collapsed elements (background and markers). --- src/icondelegate.cpp | 9 +++++-- src/modelutils.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++ src/modelutils.h | 12 +++++++++ src/modlistbypriorityproxy.cpp | 46 +++++++++++++++++++++++++++++++++ src/modlistbypriorityproxy.h | 1 + src/modlistview.cpp | 17 +++++++------ src/modlistview.h | 1 - src/pluginlistview.cpp | 16 ++++-------- src/pluginlistview.h | 1 - src/settings.cpp | 1 + src/viewmarkingscrollbar.cpp | 30 +++++++++++++++------- src/viewmarkingscrollbar.h | 6 ++--- 12 files changed, 163 insertions(+), 35 deletions(-) (limited to 'src/viewmarkingscrollbar.cpp') diff --git a/src/icondelegate.cpp b/src/icondelegate.cpp index 03964263..901b5731 100644 --- a/src/icondelegate.cpp +++ b/src/icondelegate.cpp @@ -27,7 +27,7 @@ along with Mod Organizer. If not, see . using namespace MOBase; -IconDelegate::IconDelegate(QObject *parent) +IconDelegate::IconDelegate(QObject* parent) : QStyledItemDelegate(parent) { } @@ -66,7 +66,12 @@ void IconDelegate::paintIcons( void IconDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QStyledItemDelegate::paint(painter, option, index); + if (auto* w = qobject_cast(parent())) { + w->itemDelegate()->paint(painter, option, index); + } + else { + QStyledItemDelegate::paint(painter, option, index); + } paintIcons(painter, option, index, getIcons(index)); } diff --git a/src/modelutils.cpp b/src/modelutils.cpp index d464bb91..7b54d258 100644 --- a/src/modelutils.cpp +++ b/src/modelutils.cpp @@ -2,6 +2,8 @@ #include +namespace MOShared { + QModelIndexList flatIndex( const QAbstractItemModel* model, int column, const QModelIndex& parent) { @@ -13,6 +15,26 @@ QModelIndexList flatIndex( return index; } +static QModelIndexList visibleIndexImpl(QTreeView* view, int column, const QModelIndex& parent) +{ + if (parent.isValid() && !view->isExpanded(parent)) { + return {}; + } + + auto* model = view->model(); + QModelIndexList index; + for (std::size_t i = 0; i < model->rowCount(parent); ++i) { + index.append(model->index(i, column, parent)); + index.append(visibleIndexImpl(view, column, index.back())); + } + return index; +} + +QModelIndexList visibleIndex(QTreeView* view, int column) +{ + return visibleIndexImpl(view, column, QModelIndex()); +} + QModelIndex indexModelToView(const QModelIndex& index, const QAbstractItemView* view) { // we need to stack the proxy @@ -67,3 +89,39 @@ QModelIndexList indexViewToModel(const QModelIndexList& index, const QAbstractIt } return result; } + +QColor childrenColor(const QModelIndex& index, QTreeView* view, int role) +{ + auto* model = view->model(); + auto rowIndex = index.sibling(index.row(), 0); + + if (model->hasChildren(rowIndex) && !view->isExpanded(rowIndex)) { + + // this is a non-expanded item + std::vector colors; + for (int i = 0; i < model->rowCount(rowIndex); ++i) { + auto childData = model->data(model->index(i, index.column(), rowIndex), role); + if (childData.isValid() && childData.canConvert()) { + colors.push_back(childData.value()); + } + } + + if (colors.empty()) { + return QColor(); + } + + int r = 0, g = 0, b = 0, a = 0; + for (auto& color : colors) { + r += color.red(); + g += color.green(); + b += color.blue(); + a += color.alpha(); + } + + return QColor(r / colors.size(), g / colors.size(), b / colors.size(), a / colors.size()); + } + + return QColor(); +} + +} diff --git a/src/modelutils.h b/src/modelutils.h index b5becb6c..cb7c9394 100644 --- a/src/modelutils.h +++ b/src/modelutils.h @@ -3,16 +3,28 @@ #include #include +#include + +namespace MOShared { // retrieve all the row index under the given parent QModelIndexList flatIndex( const QAbstractItemModel* model, int column = 0, const QModelIndex& parent = QModelIndex()); +// retrieve all the visible index in the given view +QModelIndexList visibleIndex(QTreeView* view, int column = 0); + // convert back-and-forth through model proxies QModelIndex indexModelToView(const QModelIndex& index, const QAbstractItemView* view); QModelIndexList indexModelToView(const QModelIndexList& index, const QAbstractItemView* view); QModelIndex indexViewToModel(const QModelIndex& index, const QAbstractItemModel* model); QModelIndexList indexViewToModel(const QModelIndexList& index, const QAbstractItemModel* model); +// retrieve the color of the children of the given index for the given, or an invalid +// color if the item is expanded or the children do not have colors for the given role +// +QColor childrenColor(const QModelIndex& index, QTreeView* view, int role); + +} #endif diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index 749991d0..7ef540b0 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -181,6 +181,52 @@ bool ModListByPriorityProxy::hasChildren(const QModelIndex& parent) const return item->children.size() > 0; } +QVariant ModListByPriorityProxy::data(const QModelIndex& index, int role) const +{ + auto sourceIndex = mapToSource(index); + if (!sourceIndex.isValid()) { + return QVariant(); + } + + auto sourceData = sourceModel()->data(sourceIndex, role); + if (role != Qt::BackgroundRole && role != ModList::ScrollMarkRole) { + return sourceData; + } + + if (!hasChildren(index)) { + return sourceData; + } + + bool expanded = !m_CollapsedItems.contains(index.sibling(index.row(), 0).data(Qt::DisplayRole).toString()); + + if (expanded) { + return sourceData; + } + + // this is a non-expanded item + std::vector colors; + for (int i = 0; i < rowCount(index); ++i) { + auto childData = sourceModel()->data(mapToSource(this->index(i, index.column(), index)), role); + if (childData.isValid() && childData.canConvert()) { + colors.push_back(childData.value()); + } + } + + if (true || colors.empty()) { + return sourceData; + } + + int r = 0, g = 0, b = 0, a = 0; + for (auto& color : colors) { + r += color.red(); + g += color.green(); + b += color.blue(); + a += color.alpha(); + } + + return QColor(r / colors.size(), g / colors.size(), b / colors.size(), a / colors.size()); +} + bool ModListByPriorityProxy::setData(const QModelIndex& index, const QVariant& value, int role) { // only care about the "name" column diff --git a/src/modlistbypriorityproxy.h b/src/modlistbypriorityproxy.h index e5a8adff..5149b7a2 100644 --- a/src/modlistbypriorityproxy.h +++ b/src/modlistbypriorityproxy.h @@ -37,6 +37,7 @@ public: int columnCount(const QModelIndex& index) const override; bool hasChildren(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role) const override; bool setData(const QModelIndex& index, const QVariant& value, int role) override; bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override; bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 80aa6495..da4d79cf 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -28,6 +28,7 @@ #include "modelutils.h" using namespace MOBase; +using namespace MOShared; // delegate to remove indentation for mods when using collapsible // separator @@ -57,6 +58,13 @@ public: } } QStyledItemDelegate::paint(painter, opt, index); + + auto color = childrenColor(index, m_view, Qt::BackgroundRole); + if (color.isValid()) { + // int shift = 3 * opt.rect.height() / 4; + // opt.rect.adjust(0, shift, 0, 0); + painter->fillRect(opt.rect, color); + } } }; @@ -67,7 +75,7 @@ ModListView::ModListView(QWidget* parent) , m_byPriorityProxy(nullptr) , m_byCategoryProxy(nullptr) , m_byNexusIdProxy(nullptr) - , m_scrollbar(new ViewMarkingScrollBar(this->model(), ModList::ScrollMarkRole, this)) + , m_scrollbar(new ViewMarkingScrollBar(this, ModList::ScrollMarkRole)) { setVerticalScrollBar(m_scrollbar); MOBase::setCustomizableColumns(this); @@ -79,13 +87,6 @@ ModListView::ModListView(QWidget* parent) connect(this, &ModListView::customContextMenuRequested, this, &ModListView::onCustomContextMenuRequested); } -void ModListView::setModel(QAbstractItemModel* model) -{ - QTreeView::setModel(model); - setVerticalScrollBar(new ViewMarkingScrollBar(model, ModList::ScrollMarkRole, this)); -} - - void ModListView::refresh() { updateGroupByProxy(-1); diff --git a/src/modlistview.h b/src/modlistview.h index c0d96f3f..dac96822 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -38,7 +38,6 @@ public: public: explicit ModListView(QWidget* parent = 0); - void setModel(QAbstractItemModel* model) override; void setup(OrganizerCore& core, CategoryFactory& factory, MainWindow* mw, Ui::MainWindow* mwui); diff --git a/src/pluginlistview.cpp b/src/pluginlistview.cpp index 589c5737..d17b4a2f 100644 --- a/src/pluginlistview.cpp +++ b/src/pluginlistview.cpp @@ -21,19 +21,13 @@ using namespace MOBase; PluginListView::PluginListView(QWidget *parent) : QTreeView(parent) , m_sortProxy(nullptr) - , m_Scrollbar(new ViewMarkingScrollBar(this->model(), Qt::BackgroundRole, this)) + , m_Scrollbar(new ViewMarkingScrollBar(this, Qt::BackgroundRole)) , m_didUpdateMasterList(false) { setVerticalScrollBar(m_Scrollbar); MOBase::setCustomizableColumns(this); } -void PluginListView::setModel(QAbstractItemModel *model) -{ - QTreeView::setModel(model); - setVerticalScrollBar(new ViewMarkingScrollBar(model, Qt::BackgroundRole, this)); -} - int PluginListView::sortColumn() const { return m_sortProxy ? m_sortProxy->sortColumn() : -1; @@ -41,22 +35,22 @@ int PluginListView::sortColumn() const QModelIndex PluginListView::indexModelToView(const QModelIndex& index) const { - return ::indexModelToView(index, this); + return MOShared::indexModelToView(index, this); } QModelIndexList PluginListView::indexModelToView(const QModelIndexList& index) const { - return ::indexModelToView(index, this); + return MOShared::indexModelToView(index, this); } QModelIndex PluginListView::indexViewToModel(const QModelIndex& index) const { - return ::indexViewToModel(index, m_core->pluginList()); + return MOShared::indexViewToModel(index, m_core->pluginList()); } QModelIndexList PluginListView::indexViewToModel(const QModelIndexList& index) const { - return ::indexViewToModel(index, m_core->pluginList()); + return MOShared::indexViewToModel(index, m_core->pluginList()); } void PluginListView::updatePluginCount() diff --git a/src/pluginlistview.h b/src/pluginlistview.h index e5dc15e7..6470ced9 100644 --- a/src/pluginlistview.h +++ b/src/pluginlistview.h @@ -19,7 +19,6 @@ class PluginListView : public QTreeView Q_OBJECT public: explicit PluginListView(QWidget* parent = nullptr); - void setModel(QAbstractItemModel* model) override; void setup(OrganizerCore& core, MainWindow* mw, Ui::MainWindow* mwui); diff --git a/src/settings.cpp b/src/settings.cpp index 0e2de9d7..e379a819 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -31,6 +31,7 @@ along with Mod Organizer. If not, see . #include using namespace MOBase; +using namespace MOShared; EndorsementState endorsementStateFromString(const QString& s) diff --git a/src/viewmarkingscrollbar.cpp b/src/viewmarkingscrollbar.cpp index 0991f171..fb165922 100644 --- a/src/viewmarkingscrollbar.cpp +++ b/src/viewmarkingscrollbar.cpp @@ -4,9 +4,11 @@ #include #include -ViewMarkingScrollBar::ViewMarkingScrollBar(QAbstractItemModel* model, int role, QWidget *parent) - : QScrollBar(parent) - , m_model(model) +using namespace MOShared; + +ViewMarkingScrollBar::ViewMarkingScrollBar(QTreeView* view, int role) + : QScrollBar(view) + , m_view(view) , m_role(role) { // not implemented for horizontal sliders @@ -15,7 +17,7 @@ ViewMarkingScrollBar::ViewMarkingScrollBar(QAbstractItemModel* model, int role, void ViewMarkingScrollBar::paintEvent(QPaintEvent* event) { - if (m_model == nullptr) { + if (m_view->model() == nullptr) { return; } QScrollBar::paintEvent(event); @@ -28,17 +30,27 @@ void ViewMarkingScrollBar::paintEvent(QPaintEvent* event) QRect handleRect = style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, QStyle::SC_ScrollBarSlider, this); QRect innerRect = style()->subControlRect(QStyle::CC_ScrollBar, &styleOption, QStyle::SC_ScrollBarGroove, this); - auto indices = flatIndex(m_model, 0, QModelIndex()); + auto indices = visibleIndex(m_view, 0); painter.translate(innerRect.topLeft() + QPoint(0, 3)); qreal scale = static_cast(innerRect.height() - 3) / static_cast(indices.size()); for (int i = 0; i < indices.size(); ++i) { QVariant data = indices[i].data(m_role); - if (data.isValid()) { - QColor col = data.value(); - painter.setPen(col); - painter.setBrush(col); + QColor color; + + if (data.canConvert()) { + color = data.value(); + } + + auto childrenColor = MOShared::childrenColor(indices[i], m_view, m_role); + if (childrenColor.isValid()) { + color = childrenColor; + } + + if (color.isValid()) { + painter.setPen(color); + painter.setBrush(color); painter.drawRect(QRect(2, i * scale - 2, handleRect.width() - 5, 3)); } } diff --git a/src/viewmarkingscrollbar.h b/src/viewmarkingscrollbar.h index 88d77039..6947a018 100644 --- a/src/viewmarkingscrollbar.h +++ b/src/viewmarkingscrollbar.h @@ -1,20 +1,20 @@ #ifndef VIEWMARKINGSCROLLBAR_H #define VIEWMARKINGSCROLLBAR_H -#include +#include #include class ViewMarkingScrollBar : public QScrollBar { public: - ViewMarkingScrollBar(QAbstractItemModel *model, int role, QWidget* parent = nullptr); + ViewMarkingScrollBar(QTreeView* view, int role); protected: void paintEvent(QPaintEvent *event) override; private: - QAbstractItemModel* m_model; + QTreeView* m_view; int m_role; }; -- cgit v1.3.1 From 8de7b79a2b211805a4ba348e490a7ab8eac15eef Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 2 Jan 2021 20:26:39 +0100 Subject: Move markers management for overwrite/overwritten to ModListView. --- src/modelutils.cpp | 34 ---------- src/modelutils.h | 5 -- src/modlist.cpp | 51 +-------------- src/modlist.h | 11 ---- src/modlistbypriorityproxy.cpp | 46 -------------- src/modlistbypriorityproxy.h | 1 - src/modlistview.cpp | 140 +++++++++++++++++++++++++++++++++++++---- src/modlistview.h | 27 +++++++- src/viewmarkingscrollbar.cpp | 22 +++---- src/viewmarkingscrollbar.h | 4 ++ 10 files changed, 168 insertions(+), 173 deletions(-) (limited to 'src/viewmarkingscrollbar.cpp') diff --git a/src/modelutils.cpp b/src/modelutils.cpp index 7b54d258..83054806 100644 --- a/src/modelutils.cpp +++ b/src/modelutils.cpp @@ -90,38 +90,4 @@ QModelIndexList indexViewToModel(const QModelIndexList& index, const QAbstractIt return result; } -QColor childrenColor(const QModelIndex& index, QTreeView* view, int role) -{ - auto* model = view->model(); - auto rowIndex = index.sibling(index.row(), 0); - - if (model->hasChildren(rowIndex) && !view->isExpanded(rowIndex)) { - - // this is a non-expanded item - std::vector colors; - for (int i = 0; i < model->rowCount(rowIndex); ++i) { - auto childData = model->data(model->index(i, index.column(), rowIndex), role); - if (childData.isValid() && childData.canConvert()) { - colors.push_back(childData.value()); - } - } - - if (colors.empty()) { - return QColor(); - } - - int r = 0, g = 0, b = 0, a = 0; - for (auto& color : colors) { - r += color.red(); - g += color.green(); - b += color.blue(); - a += color.alpha(); - } - - return QColor(r / colors.size(), g / colors.size(), b / colors.size(), a / colors.size()); - } - - return QColor(); -} - } diff --git a/src/modelutils.h b/src/modelutils.h index cb7c9394..e6510941 100644 --- a/src/modelutils.h +++ b/src/modelutils.h @@ -20,11 +20,6 @@ QModelIndexList indexModelToView(const QModelIndexList& index, const QAbstractIt QModelIndex indexViewToModel(const QModelIndex& index, const QAbstractItemModel* model); QModelIndexList indexViewToModel(const QModelIndexList& index, const QAbstractItemModel* model); -// retrieve the color of the children of the given index for the given, or an invalid -// color if the item is expanded or the children do not have colors for the given role -// -QColor childrenColor(const QModelIndex& index, QTreeView* view, int role); - } #endif diff --git a/src/modlist.cpp b/src/modlist.cpp index a2e59b62..155a094f 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -464,33 +464,11 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return QVariant(); } else if (role == Qt::BackgroundRole || role == ScrollMarkRole) { - bool overwrite = m_Overwrite.find(modIndex) != m_Overwrite.end(); - bool archiveOverwrite = m_ArchiveOverwrite.find(modIndex) != m_ArchiveOverwrite.end(); - bool archiveLooseOverwrite = m_ArchiveLooseOverwrite.find(modIndex) != m_ArchiveLooseOverwrite.end(); - bool overwritten = m_Overwritten.find(modIndex) != m_Overwritten.end(); - bool archiveOverwritten = m_ArchiveOverwritten.find(modIndex) != m_ArchiveOverwritten.end(); - bool archiveLooseOverwritten = m_ArchiveLooseOverwritten.find(modIndex) != m_ArchiveLooseOverwritten.end(); if (column == COL_NOTES && modInfo->color().isValid()) { return modInfo->color(); } - else if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_PLUGIN) { - return Settings::instance().colors().modlistContainsPlugin(); - } - else if (overwritten || archiveLooseOverwritten) { - return Settings::instance().colors().modlistOverwritingLoose(); - } - else if (overwrite || archiveLooseOverwrite) { - return Settings::instance().colors().modlistOverwrittenLoose(); - } - else if (archiveOverwritten) { - return Settings::instance().colors().modlistOverwritingArchive(); - } - else if (archiveOverwrite) { - return Settings::instance().colors().modlistOverwrittenArchive(); - } else if (modInfo->isSeparator() && modInfo->color().isValid() - && (role != ScrollMarkRole - || Settings::instance().colors().colorSeparatorScrollbar())) { + && (role != ScrollMarkRole || Settings::instance().colors().colorSeparatorScrollbar())) { return modInfo->color(); } else { @@ -851,27 +829,6 @@ void ModList::changeModPriority(int sourceIndex, int newPriority) emit modPrioritiesChanged({ index(sourceIndex, 0) }); } -void ModList::setOverwriteMarkers(const std::set &overwrite, const std::set &overwritten) -{ - m_Overwrite = overwrite; - m_Overwritten = overwritten; - notifyChange(0, rowCount() - 1); -} - -void ModList::setArchiveOverwriteMarkers(const std::set &overwrite, const std::set &overwritten) -{ - m_ArchiveOverwrite = overwrite; - m_ArchiveOverwritten = overwritten; - notifyChange(0, rowCount() - 1); -} - -void ModList::setArchiveLooseOverwriteMarkers(const std::set &overwrite, const std::set &overwritten) -{ - m_ArchiveLooseOverwrite = overwrite; - m_ArchiveLooseOverwritten = overwritten; - notifyChange(0, rowCount() - 1); -} - void ModList::setPluginContainer(PluginContainer *pluginContianer) { m_PluginContainer = pluginContianer; @@ -1393,12 +1350,6 @@ void ModList::notifyChange(int rowStart, int rowEnd) Guard g([&]{ m_InNotifyChange = false; }); if (rowStart < 0) { - m_Overwrite.clear(); - m_Overwritten.clear(); - m_ArchiveOverwrite.clear(); - m_ArchiveOverwritten.clear(); - m_ArchiveLooseOverwrite.clear(); - m_ArchiveLooseOverwritten.clear(); beginResetModel(); endResetModel(); } else { diff --git a/src/modlist.h b/src/modlist.h index 22703923..afbef7af 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -142,12 +142,8 @@ public: void changeModPriority(int sourceIndex, int newPriority); void changeModPriority(std::vector sourceIndices, int newPriority); - void setOverwriteMarkers(const std::set &overwrite, const std::set &overwritten); void setPluginContainer(PluginContainer *pluginContainer); - void setArchiveOverwriteMarkers(const std::set &overwrite, const std::set &overwritten); - void setArchiveLooseOverwriteMarkers(const std::set &overwrite, const std::set &overwritten); - bool modInfoAboutToChange(ModInfo::Ptr info); void modInfoChanged(ModInfo::Ptr info); @@ -420,13 +416,6 @@ private: QFontMetrics m_FontMetrics; - std::set m_Overwrite; - std::set m_Overwritten; - std::set m_ArchiveOverwrite; - std::set m_ArchiveOverwritten; - std::set m_ArchiveLooseOverwrite; - std::set m_ArchiveLooseOverwritten; - TModInfoChange m_ChangeInfo; SignalModInstalled m_ModInstalled; diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index 7ef540b0..749991d0 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -181,52 +181,6 @@ bool ModListByPriorityProxy::hasChildren(const QModelIndex& parent) const return item->children.size() > 0; } -QVariant ModListByPriorityProxy::data(const QModelIndex& index, int role) const -{ - auto sourceIndex = mapToSource(index); - if (!sourceIndex.isValid()) { - return QVariant(); - } - - auto sourceData = sourceModel()->data(sourceIndex, role); - if (role != Qt::BackgroundRole && role != ModList::ScrollMarkRole) { - return sourceData; - } - - if (!hasChildren(index)) { - return sourceData; - } - - bool expanded = !m_CollapsedItems.contains(index.sibling(index.row(), 0).data(Qt::DisplayRole).toString()); - - if (expanded) { - return sourceData; - } - - // this is a non-expanded item - std::vector colors; - for (int i = 0; i < rowCount(index); ++i) { - auto childData = sourceModel()->data(mapToSource(this->index(i, index.column(), index)), role); - if (childData.isValid() && childData.canConvert()) { - colors.push_back(childData.value()); - } - } - - if (true || colors.empty()) { - return sourceData; - } - - int r = 0, g = 0, b = 0, a = 0; - for (auto& color : colors) { - r += color.red(); - g += color.green(); - b += color.blue(); - a += color.alpha(); - } - - return QColor(r / colors.size(), g / colors.size(), b / colors.size(), a / colors.size()); -} - bool ModListByPriorityProxy::setData(const QModelIndex& index, const QVariant& value, int role) { // only care about the "name" column diff --git a/src/modlistbypriorityproxy.h b/src/modlistbypriorityproxy.h index 5149b7a2..e5a8adff 100644 --- a/src/modlistbypriorityproxy.h +++ b/src/modlistbypriorityproxy.h @@ -37,7 +37,6 @@ public: int columnCount(const QModelIndex& index) const override; bool hasChildren(const QModelIndex& parent) const override; - QVariant data(const QModelIndex& index, int role) const override; bool setData(const QModelIndex& index, const QVariant& value, int role) override; bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override; bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; diff --git a/src/modlistview.cpp b/src/modlistview.cpp index a460e4a4..f7db64e6 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -75,7 +75,7 @@ public: // compute required color from children, otherwise fallback to the // color from the model, and draw the background here - auto color = childrenColor(index, m_view, Qt::BackgroundRole); + auto color = m_view->markerColor(index); if (!color.isValid()) { color = index.data(Qt::BackgroundRole).value(); } @@ -98,6 +98,24 @@ public: } }; +class ModListViewMarkingScrollBar : public ViewMarkingScrollBar { + ModListView* m_view; +public: + ModListViewMarkingScrollBar(ModListView* view) : + ViewMarkingScrollBar(view, ModList::ScrollMarkRole), m_view(view) { } + + + QColor color(const QModelIndex& index) const override + { + auto color = m_view->markerColor(index); + if (!color.isValid()) { + color = ViewMarkingScrollBar::color(index); + } + return color; + } + +}; + ModListView::ModListView(QWidget* parent) : QTreeView(parent) , m_core(nullptr) @@ -105,7 +123,8 @@ ModListView::ModListView(QWidget* parent) , m_byPriorityProxy(nullptr) , m_byCategoryProxy(nullptr) , m_byNexusIdProxy(nullptr) - , m_scrollbar(new ViewMarkingScrollBar(this, ModList::ScrollMarkRole)) + , m_overwrite{ {}, {}, {}, {}, {}, {} } + , m_scrollbar(new ModListViewMarkingScrollBar(this)) { setVerticalScrollBar(m_scrollbar); MOBase::setCustomizableColumns(this); @@ -386,10 +405,7 @@ void ModListView::onModPrioritiesChanged(const QModelIndexList& indices) } // update conflict check on the moved mod modInfo->doConflictCheck(); - m_core->modList()->setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten()); - m_core->modList()->setArchiveOverwriteMarkers(modInfo->getModArchiveOverwrite(), modInfo->getModArchiveOverwritten()); - m_core->modList()->setArchiveLooseOverwriteMarkers(modInfo->getModArchiveLooseOverwrite(), modInfo->getModArchiveLooseOverwritten()); - verticalScrollBar()->repaint(); + setOverwriteMarkers(modInfo); } } } @@ -681,6 +697,7 @@ void ModListView::setup(OrganizerCore& core, CategoryFactory& factory, MainWindo connect(core.modList(), &ModList::modPrioritiesChanged, [=](auto&& indices) { onModPrioritiesChanged(indices); }); connect(core.modList(), &ModList::clearOverwrite, [=] { m_actions->clearOverwrite(); }); connect(core.modList(), &ModList::modStatesChanged, [=] { updateModCount(); }); + connect(core.modList(), &ModList::modelReset, [=] { clearOverwriteMarkers(); }); m_byPriorityProxy = new ModListByPriorityProxy(core.currentProfile(), core, this); m_byPriorityProxy->setSourceModel(core.modList()); @@ -935,6 +952,108 @@ void ModListView::onDoubleClicked(const QModelIndex& index) closePersistentEditor(index); } +void ModListView::clearOverwriteMarkers() +{ + m_overwrite.overwrite.clear(); + m_overwrite.overwritten.clear(); + m_overwrite.archiveOverwrite.clear(); + m_overwrite.archiveOverwritten.clear(); + m_overwrite.archiveLooseOverwrite.clear(); + m_overwrite.archiveLooseOverwritten.clear(); +} + +void ModListView::setOverwriteMarkers(const std::set& overwrite, const std::set& overwritten) +{ + m_overwrite.overwrite = overwrite; + m_overwrite.overwritten = overwritten; +} + +void ModListView::setArchiveOverwriteMarkers(const std::set& overwrite, const std::set& overwritten) +{ + m_overwrite.archiveOverwrite = overwrite; + m_overwrite.archiveOverwritten = overwritten; +} + +void ModListView::setArchiveLooseOverwriteMarkers(const std::set& overwrite, const std::set& overwritten) +{ + m_overwrite.archiveLooseOverwrite = overwrite; + m_overwrite.archiveLooseOverwritten = overwritten; +} + +void ModListView::setOverwriteMarkers(ModInfo::Ptr mod) +{ + if (mod) { + setOverwriteMarkers(mod->getModOverwrite(), mod->getModOverwritten()); + setArchiveOverwriteMarkers(mod->getModArchiveOverwrite(), mod->getModArchiveOverwritten()); + setArchiveLooseOverwriteMarkers(mod->getModArchiveLooseOverwrite(), mod->getModArchiveLooseOverwritten()); + } + else { + setOverwriteMarkers({}, {}); + setArchiveOverwriteMarkers({}, {}); + setArchiveLooseOverwriteMarkers({}, {}); + } + dataChanged(model()->index(0, 0), model()->index(model()->rowCount(), model()->columnCount())); + verticalScrollBar()->repaint(); +} + +QColor ModListView::markerColor(const QModelIndex& index) const +{ + unsigned int modIndex = index.data(ModList::IndexRole).toInt(); + ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex); + bool overwrite = m_overwrite.overwrite.find(modIndex) != m_overwrite.overwrite.end(); + bool archiveOverwrite = m_overwrite.archiveOverwrite.find(modIndex) != m_overwrite.archiveOverwrite.end(); + bool archiveLooseOverwrite = m_overwrite.archiveOverwritten.find(modIndex) != m_overwrite.archiveOverwritten.end(); + bool overwritten = m_overwrite.overwritten.find(modIndex) != m_overwrite.overwritten.end(); + bool archiveOverwritten = m_overwrite.archiveOverwritten.find(modIndex) != m_overwrite.archiveOverwritten.end(); + bool archiveLooseOverwritten = m_overwrite.archiveLooseOverwritten.find(modIndex) != m_overwrite.archiveLooseOverwritten.end(); + + // TODO: Move this here + if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_PLUGIN) { + return Settings::instance().colors().modlistContainsPlugin(); + } + else if (overwritten || archiveLooseOverwritten) { + return Settings::instance().colors().modlistOverwritingLoose(); + } + else if (overwrite || archiveLooseOverwrite) { + return Settings::instance().colors().modlistOverwrittenLoose(); + } + else if (archiveOverwritten) { + return Settings::instance().colors().modlistOverwritingArchive(); + } + else if (archiveOverwrite) { + return Settings::instance().colors().modlistOverwrittenArchive(); + } + + // collapsed separator + auto rowIndex = index.sibling(index.row(), 0); + if (hasCollapsibleSeparators() && model()->hasChildren(rowIndex) && !isExpanded(rowIndex)) { + + std::vector colors; + for (int i = 0; i < model()->rowCount(rowIndex); ++i) { + auto childColor = markerColor(model()->index(i, index.column(), rowIndex)); + if (childColor.isValid()) { + colors.push_back(childColor); + } + } + + if (colors.empty()) { + return QColor(); + } + + int r = 0, g = 0, b = 0, a = 0; + for (auto& color : colors) { + r += color.red(); + g += color.green(); + b += color.blue(); + a += color.alpha(); + } + + return QColor(r / colors.size(), g / colors.size(), b / colors.size(), a / colors.size()); + } + + return QColor(); +} + void ModListView::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { if (hasCollapsibleSeparators()) { @@ -948,16 +1067,11 @@ void ModListView::onSelectionChanged(const QItemSelection& selected, const QItem if (selected.count()) { auto index = selected.indexes().last(); ModInfo::Ptr selectedMod = ModInfo::getByIndex(index.data(ModList::IndexRole).toInt()); - m_core->modList()->setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten()); - m_core->modList()->setArchiveOverwriteMarkers(selectedMod->getModArchiveOverwrite(), selectedMod->getModArchiveOverwritten()); - m_core->modList()->setArchiveLooseOverwriteMarkers(selectedMod->getModArchiveLooseOverwrite(), selectedMod->getModArchiveLooseOverwritten()); + setOverwriteMarkers(selectedMod); } else { - m_core->modList()->setOverwriteMarkers({}, {}); - m_core->modList()->setArchiveOverwriteMarkers({}, {}); - m_core->modList()->setArchiveLooseOverwriteMarkers({}, {}); + setOverwriteMarkers(nullptr); } - verticalScrollBar()->repaint(); } diff --git a/src/modlistview.h b/src/modlistview.h index d67f2940..bf705573 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -166,10 +166,27 @@ protected slots: private: + friend class ModListStyledItemDelegated; + friend class ModListViewMarkingScrollBar; + void onModPrioritiesChanged(const QModelIndexList& indices); void onModInstalled(const QString& modName); void onModFilterActive(bool filterActive); + // overwrite markers + void clearOverwriteMarkers(); + void setOverwriteMarkers(const std::set& overwrite, const std::set& overwritten); + void setArchiveOverwriteMarkers(const std::set& overwrite, const std::set& overwritten); + void setArchiveLooseOverwriteMarkers(const std::set& overwrite, const std::set& overwritten); + + // set overwrite markers from the mod and repaint (if mod is nullptr, clear overwrite and repaint) + // + void setOverwriteMarkers(ModInfo::Ptr mod); + + // retrieve the marker color for the given index + // + QColor markerColor(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 // @@ -219,10 +236,18 @@ private: ModListSortProxy* m_sortProxy; ModListByPriorityProxy* m_byPriorityProxy; - QtGroupingProxy* m_byCategoryProxy; QtGroupingProxy* m_byNexusIdProxy; + struct OverwriteInfo { + std::set overwrite; + std::set overwritten; + std::set archiveOverwrite; + std::set archiveOverwritten; + std::set archiveLooseOverwrite; + std::set archiveLooseOverwritten; + } m_overwrite; + ViewMarkingScrollBar* m_scrollbar; bool m_inDragMoveEvent = false; diff --git a/src/viewmarkingscrollbar.cpp b/src/viewmarkingscrollbar.cpp index fb165922..56754237 100644 --- a/src/viewmarkingscrollbar.cpp +++ b/src/viewmarkingscrollbar.cpp @@ -15,6 +15,15 @@ ViewMarkingScrollBar::ViewMarkingScrollBar(QTreeView* view, int role) Q_ASSERT(this->orientation() == Qt::Vertical); } +QColor ViewMarkingScrollBar::color(const QModelIndex& index) const +{ + auto data = index.data(m_role); + if (data.canConvert()) { + return data.value(); + } + return QColor(); +} + void ViewMarkingScrollBar::paintEvent(QPaintEvent* event) { if (m_view->model() == nullptr) { @@ -36,18 +45,7 @@ void ViewMarkingScrollBar::paintEvent(QPaintEvent* event) qreal scale = static_cast(innerRect.height() - 3) / static_cast(indices.size()); for (int i = 0; i < indices.size(); ++i) { - QVariant data = indices[i].data(m_role); - QColor color; - - if (data.canConvert()) { - color = data.value(); - } - - auto childrenColor = MOShared::childrenColor(indices[i], m_view, m_role); - if (childrenColor.isValid()) { - color = childrenColor; - } - + QColor color = this->color(indices[i]); if (color.isValid()) { painter.setPen(color); painter.setBrush(color); diff --git a/src/viewmarkingscrollbar.h b/src/viewmarkingscrollbar.h index 6947a018..01b5a8c0 100644 --- a/src/viewmarkingscrollbar.h +++ b/src/viewmarkingscrollbar.h @@ -13,6 +13,10 @@ public: protected: void paintEvent(QPaintEvent *event) override; + // retrieve the color of the marker for the given index + // + virtual QColor color(const QModelIndex& index) const; + private: QTreeView* m_view; int m_role; -- cgit v1.3.1