From f2d8469ed6cd0fafc22097cdba2ee8f325f00513 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 31 Dec 2020 21:02:04 +0100 Subject: Start moving stuff from MainWindow to PluginListView. --- src/modelutils.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/modelutils.cpp (limited to 'src/modelutils.cpp') diff --git a/src/modelutils.cpp b/src/modelutils.cpp new file mode 100644 index 00000000..43aa6b99 --- /dev/null +++ b/src/modelutils.cpp @@ -0,0 +1,58 @@ +#include "modelutils.h" + +#include + +QModelIndex indexModelToView(const QModelIndex& index, const QAbstractItemView* view) +{ + // we need to stack the proxy + std::vector proxies; + { + auto* currentModel = view->model(); + while (auto* proxy = qobject_cast(currentModel)) { + proxies.push_back(proxy); + currentModel = proxy->sourceModel(); + } + } + + if (proxies.empty() || proxies.back()->sourceModel() != index.model()) { + return QModelIndex(); + } + + auto qindex = index; + for (auto rit = proxies.rbegin(); rit != proxies.rend(); ++rit) { + qindex = (*rit)->mapFromSource(qindex); + } + + return qindex; +} + +QModelIndexList indexModelToView(const QModelIndexList& index, const QAbstractItemView* view) +{ + QModelIndexList result; + for (auto& idx : index) { + result.append(indexModelToView(idx, view)); + } + return result; +} + +QModelIndex indexViewToModel(const QModelIndex& index, const QAbstractItemModel* model) +{ + if (index.model() == model) { + return index; + } + else if (auto* proxy = qobject_cast(index.model())) { + return indexViewToModel(proxy->mapToSource(index), model); + } + else { + return QModelIndex(); + } +} + +QModelIndexList indexViewToModel(const QModelIndexList& index, const QAbstractItemModel* model) +{ + QModelIndexList result; + for (auto& idx : index) { + result.append(indexViewToModel(idx, model)); + } + return result; +} -- cgit v1.3.1 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/modelutils.cpp | 11 +++++++++++ src/modelutils.h | 4 ++++ src/modlistview.cpp | 15 ++------------- src/modlistview.h | 5 ----- src/settings.cpp | 17 +++-------------- src/viewmarkingscrollbar.cpp | 9 ++++++--- 6 files changed, 26 insertions(+), 35 deletions(-) (limited to 'src/modelutils.cpp') diff --git a/src/modelutils.cpp b/src/modelutils.cpp index 43aa6b99..d464bb91 100644 --- a/src/modelutils.cpp +++ b/src/modelutils.cpp @@ -2,6 +2,17 @@ #include +QModelIndexList flatIndex( + const QAbstractItemModel* model, int column, const QModelIndex& parent) +{ + QModelIndexList index; + for (std::size_t i = 0; i < model->rowCount(parent); ++i) { + index.append(model->index(i, column, parent)); + index.append(flatIndex(model, column, index.back())); + } + return index; +} + QModelIndex indexModelToView(const QModelIndex& index, const QAbstractItemView* view) { // we need to stack the proxy diff --git a/src/modelutils.h b/src/modelutils.h index f355c0d6..b5becb6c 100644 --- a/src/modelutils.h +++ b/src/modelutils.h @@ -4,6 +4,10 @@ #include #include +// retrieve all the row index under the given parent +QModelIndexList flatIndex( + const QAbstractItemModel* model, int column = 0, const QModelIndex& parent = QModelIndex()); + // convert back-and-forth through model proxies QModelIndex indexModelToView(const QModelIndex& index, const QAbstractItemView* view); QModelIndexList indexModelToView(const QModelIndexList& index, const QAbstractItemView* view); diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 42627e3f..c92b65ef 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -169,12 +169,12 @@ std::optional ModListView::prevMod(unsigned int modIndex) const void ModListView::enableAllVisible() { - m_core->modList()->setActive(indexViewToModel(allIndex(model())), true); + m_core->modList()->setActive(indexViewToModel(flatIndex(model())), true); } void ModListView::disableAllVisible() { - m_core->modList()->setActive(indexViewToModel(allIndex(model())), false); + m_core->modList()->setActive(indexViewToModel(flatIndex(model())), false); } void ModListView::setFilterCriteria(const std::vector& criteria) @@ -254,17 +254,6 @@ QModelIndex ModListView::prevIndex(const QModelIndex& index) const return prev; } -QModelIndexList ModListView::allIndex( - const QAbstractItemModel* model, int column, const QModelIndex& parent) const -{ - QModelIndexList index; - for (std::size_t i = 0; i < model->rowCount(parent); ++i) { - index.append(model->index(i, column, parent)); - index.append(allIndex(model, column, index.back())); - } - return index; -} - std::pair ModListView::selected() const { return { indexViewToModel(currentIndex()), indexViewToModel(selectionModel()->selectedRows()) }; diff --git a/src/modlistview.h b/src/modlistview.h index 098466bc..c0d96f3f 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -124,11 +124,6 @@ protected: QModelIndex nextIndex(const QModelIndex& index) const; QModelIndex prevIndex(const QModelIndex& index) const; - // all index for the given model under the given index, recursively - // - QModelIndexList allIndex( - const QAbstractItemModel* model, int column = 0, const QModelIndex& index = QModelIndex()) const; - // re-implemented to fake the return value to allow drag-and-drop on // itself for separators // diff --git a/src/settings.cpp b/src/settings.cpp index b6961807..0e2de9d7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -24,6 +24,7 @@ along with Mod Organizer. If not, see . #include "instancemanager.h" #include "shared/appconfig.h" #include "env.h" +#include "modelutils.h" #include "envmetrics.h" #include #include @@ -1063,22 +1064,10 @@ WidgetSettings::WidgetSettings(QSettings& s, bool globalInstance) } } -std::vector WidgetSettings::allIndex(const QAbstractItemModel* model, int column, const QModelIndex& parent) const -{ - std::vector index; - for (std::size_t i = 0; i < model->rowCount(parent); ++i) { - index.push_back(model->index(i, column, parent)); - - auto cindex = allIndex(model, column, index.back()); - index.insert(index.end(), cindex.begin(), cindex.end()); - } - return index; -} - void WidgetSettings::saveTreeState(const QTreeView* tv, int role) { QVariantList expanded; - for (auto index : allIndex(tv->model())) { + for (auto index : flatIndex(tv->model())) { if (tv->isExpanded(index)) { expanded.append(index.data(role)); } @@ -1090,7 +1079,7 @@ void WidgetSettings::restoreTreeState(QTreeView* tv, int role) const { if (auto expanded = getOptional(m_Settings, "Widgets", indexSettingName(tv))) { tv->collapseAll(); - for (auto index : allIndex(tv->model())) { + for (auto index : flatIndex(tv->model())) { if (expanded->contains(index.data(role))) { tv->expand(index); } 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 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/modelutils.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/modelutils.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