From 9db6a9d7931edbb08e74cd1e110794f47d46df3e Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 28 Dec 2020 14:25:47 +0100 Subject: Save collapse state of separator. --- src/settings.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/settings.h') diff --git a/src/settings.h b/src/settings.h index 4d1258bf..3f60fc7b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -202,6 +202,12 @@ public: // WidgetSettings(QSettings& s, bool globalInstance); + // tree state - this saves the list of expanded items based on the given role + // + std::vector allIndex(const QAbstractItemModel* model, int column = 0, const QModelIndex& parent = QModelIndex()) const; + void saveTreeState(const QTreeView* tv, int role = Qt::DisplayRole); + void restoreTreeState(QTreeView* tv, int role = Qt::DisplayRole) const; + // selected index for a combobox // std::optional index(const QComboBox* cb) const; -- cgit v1.3.1 From 095348c16f58d757f2d9549d06fd12d5ed14a1d2 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Tue, 29 Dec 2020 21:40:22 +0100 Subject: Add option to disable collapsible separators. --- src/mainwindow.cpp | 2 +- src/modlistview.cpp | 7 +++++-- src/modlistview.h | 5 ++--- src/settings.cpp | 10 ++++++++++ src/settings.h | 5 +++++ src/settingsdialog.ui | 37 +++++++++++++++++++++++++++++++++++++ src/settingsdialoggeneral.cpp | 2 ++ 7 files changed, 62 insertions(+), 6 deletions(-) (limited to 'src/settings.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e54c24e1..63c9a8be 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -692,7 +692,6 @@ void MainWindow::allowListResize() void MainWindow::updateStyle(const QString&) { resetActionIcons(); - ui->modList->refreshStyle(); } void MainWindow::resizeEvent(QResizeEvent *event) @@ -4619,6 +4618,7 @@ void MainWindow::on_actionSettings_triggered() fixCategories(); refreshFilters(); + ui->modList->refresh(); if (settings.paths().profiles() != oldProfilesDirectory) { refreshProfiles(); diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 643b1971..dbd09884 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -76,8 +76,10 @@ ModListView::ModListView(QWidget* parent) setItemDelegate(new ModListStyledItemDelegated(this)); } -void ModListView::refreshStyle() +void ModListView::refresh() { + updateGroupByProxy(-1); + // maybe there is a better way but I did not find one QString sheet = styleSheet(); setStyleSheet("QTreeView { }"); @@ -496,7 +498,8 @@ void ModListView::updateGroupByProxy(int groupIndex) m_byNexusIdProxy->setGroupedColumn(ModList::COL_MODID); m_sortProxy->setSourceModel(m_byNexusIdProxy); } - else if (m_sortProxy->sortColumn() == ModList::COL_PRIORITY + else if (m_core->settings().interface().collapsibleSeparators() + && m_sortProxy->sortColumn() == ModList::COL_PRIORITY && m_sortProxy->sortOrder() == Qt::AscendingOrder) { m_sortProxy->setSourceModel(m_byPriorityProxy); m_byPriorityProxy->refresh(); diff --git a/src/modlistview.h b/src/modlistview.h index 3520bfc4..2ea5891c 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -65,10 +65,9 @@ public: // QRect visualRect(const QModelIndex& index) const override; - // refresh the style of the mod list, this needs to be called when the - // stylesheet is changed + // refresh the view (to call when settings have been changed) // - void refreshStyle(); + void refresh(); signals: diff --git a/src/settings.cpp b/src/settings.cpp index 04cfafc9..b6961807 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2162,6 +2162,16 @@ void InterfaceSettings::setStyleName(const QString& name) set(m_Settings, "Settings", "style", name); } +bool InterfaceSettings::collapsibleSeparators() const +{ + return get(m_Settings, "Settings", "collapsible_separators", true); +} + +void InterfaceSettings::setCollapsibleSeparators(bool b) +{ + set(m_Settings, "Settings", "collapsible_separators", b); +} + bool InterfaceSettings::compactDownloads() const { return get(m_Settings, "Settings", "compact_downloads", false); diff --git a/src/settings.h b/src/settings.h index 3f60fc7b..5506bbf8 100644 --- a/src/settings.h +++ b/src/settings.h @@ -617,6 +617,11 @@ public: std::optional styleName() const; void setStyleName(const QString& name); + // whether to use collapsible separators when possible + // + bool collapsibleSeparators() const; + void setCollapsibleSeparators(bool b); + // whether to show compact downloads // bool compactDownloads() const; diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index 43af5e9f..6d62228d 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -338,6 +338,43 @@ + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Use collapsible separators + + + true + + + false + + + + + + diff --git a/src/settingsdialoggeneral.cpp b/src/settingsdialoggeneral.cpp index f29e1d24..47388c96 100644 --- a/src/settingsdialoggeneral.cpp +++ b/src/settingsdialoggeneral.cpp @@ -27,6 +27,7 @@ GeneralSettingsTab::GeneralSettingsTab(Settings& s, SettingsDialog& d) ui->checkForUpdates->setChecked(settings().checkForUpdates()); ui->usePrereleaseBox->setChecked(settings().usePrereleases()); ui->colorSeparatorsBox->setChecked(settings().colors().colorSeparatorScrollbar()); + ui->collapsibleSeparatorsBox->setChecked(settings().interface().collapsibleSeparators()); QObject::connect(ui->exploreStyles, &QPushButton::clicked, [&]{ onExploreStyles(); }); @@ -70,6 +71,7 @@ void GeneralSettingsTab::update() settings().setCheckForUpdates(ui->checkForUpdates->isChecked()); settings().setUsePrereleases(ui->usePrereleaseBox->isChecked()); settings().colors().setColorSeparatorScrollbar(ui->colorSeparatorsBox->isChecked()); + settings().interface().setCollapsibleSeparators(ui->collapsibleSeparatorsBox->isChecked()); } void GeneralSettingsTab::addLanguages() -- cgit v1.3.1 From 071974c243d97a19e5a73f368ce25f8decd00183 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 2 Jan 2021 17:14:09 +0100 Subject: Save/restore filter list state between run. --- src/filterlist.cpp | 50 +++++++++++++++++++++++++++++++++++++++----------- src/mainwindow.cpp | 2 +- src/modlistview.cpp | 4 ++-- src/settings.cpp | 27 +++++++++++++++++++++++++-- src/settings.h | 10 +++++++--- 5 files changed, 74 insertions(+), 19 deletions(-) (limited to 'src/settings.h') diff --git a/src/filterlist.cpp b/src/filterlist.cpp index c3f169a6..14813312 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -12,7 +12,14 @@ using Criteria = ModListSortProxy::Criteria; class FilterList::CriteriaItem : public QTreeWidgetItem { + + static constexpr int IDRole = Qt::UserRole; + static constexpr int TypeRole = Qt::UserRole + 1; + public: + + static constexpr int StateRole = Qt::UserRole + 2; + enum States { FirstState = 0, @@ -58,27 +65,41 @@ public: void nextState() { - m_state = static_cast(m_state + 1); - if (m_state > LastState) { - m_state = FirstState; + auto s = static_cast(m_state + 1); + if (s > LastState) { + s = FirstState; } - - updateState(); + setState(s); } void previousState() { - m_state = static_cast(m_state - 1); - if (m_state < FirstState) { - m_state = LastState; + auto s = static_cast(m_state - 1); + if (s < FirstState) { + s = LastState; } + setState(s); + } - updateState(); + QVariant data(int column, int role) const + { + if (role == StateRole) { + return m_state; + } + return QTreeWidgetItem::data(column, role); + } + + void setData(int column, int role, const QVariant& value) { + if (role == StateRole) { + MOBase::log::debug("setData: {}, {}, {}", column, role, value.toInt()); + setState(static_cast(value.toInt())); + } + else { + QTreeWidgetItem::setData(column, role, value); + } } private: - const int IDRole = Qt::UserRole; - const int TypeRole = Qt::UserRole + 1; FilterList* m_list; States m_state; @@ -212,10 +233,17 @@ FilterList::FilterList(Ui::MainWindow* ui, OrganizerCore& core, CategoryFactory& void FilterList::restoreState(const Settings& s) { s.widgets().restoreIndex(ui->filtersSeparators); + s.widgets().restoreChecked(ui->filtersAnd); + s.widgets().restoreChecked(ui->filtersOr); + s.widgets().restoreTreeCheckState(ui->filters, CriteriaItem::StateRole); + checkCriteria(); } void FilterList::saveState(Settings& s) const { + s.widgets().saveTreeCheckState(ui->filters, CriteriaItem::StateRole); + s.widgets().saveChecked(ui->filtersAnd); + s.widgets().saveChecked(ui->filtersOr); s.widgets().saveIndex(ui->filtersSeparators); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6929a009..2b2685c4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1170,8 +1170,8 @@ void MainWindow::showEvent(QShowEvent *event) QMainWindow::showEvent(event); if (!m_WasVisible) { - readSettings(); ui->modList->refreshFilters(); + readSettings(); // this needs to be connected here instead of in the constructor because the // actual changing of the stylesheet is done by MOApplication, which diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 0898fe3c..a460e4a4 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -804,7 +804,7 @@ void ModListView::restoreState(const Settings& s) s.geometry().restoreState(header()); s.widgets().restoreIndex(ui.groupBy); - s.widgets().restoreTreeState(this); + s.widgets().restoreTreeExpandState(this); m_filters->restoreState(s); } @@ -814,7 +814,7 @@ void ModListView::saveState(Settings& s) const s.geometry().saveState(header()); s.widgets().saveIndex(ui.groupBy); - s.widgets().saveTreeState(this); + s.widgets().saveTreeExpandState(this); m_filters->saveState(s); } diff --git a/src/settings.cpp b/src/settings.cpp index e379a819..3cc026cf 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1065,7 +1065,30 @@ WidgetSettings::WidgetSettings(QSettings& s, bool globalInstance) } } -void WidgetSettings::saveTreeState(const QTreeView* tv, int role) +void WidgetSettings::saveTreeCheckState(const QTreeView* tv, int role) +{ + QVariantList data; + for (auto index : flatIndex(tv->model())) { + data.append(index.data(role)); + } + set(m_Settings, "Widgets", indexSettingName(tv), data); +} + +void WidgetSettings::restoreTreeCheckState(QTreeView* tv, int role) const +{ + if (auto states = getOptional(m_Settings, "Widgets", indexSettingName(tv))) { + auto allIndex = flatIndex(tv->model()); + MOBase::log::debug("restoreTreeCheckState: {}, {}", states->size(), allIndex.size()); + if (states->size() != allIndex.size()) { + return; + } + for (int i = 0; i < states->size(); ++i) { + tv->model()->setData(allIndex[i], states->at(i), role); + } + } +} + +void WidgetSettings::saveTreeExpandState(const QTreeView* tv, int role) { QVariantList expanded; for (auto index : flatIndex(tv->model())) { @@ -1076,7 +1099,7 @@ void WidgetSettings::saveTreeState(const QTreeView* tv, int role) set(m_Settings, "Widgets", indexSettingName(tv), expanded); } -void WidgetSettings::restoreTreeState(QTreeView* tv, int role) const +void WidgetSettings::restoreTreeExpandState(QTreeView* tv, int role) const { if (auto expanded = getOptional(m_Settings, "Widgets", indexSettingName(tv))) { tv->collapseAll(); diff --git a/src/settings.h b/src/settings.h index 5506bbf8..9c3765c2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -202,11 +202,15 @@ public: // WidgetSettings(QSettings& s, bool globalInstance); + // tree item check - this saves the list of expanded items based on the given role + // + void saveTreeCheckState(const QTreeView* tv, int role = Qt::CheckStateRole); + void restoreTreeCheckState(QTreeView* tv, int role = Qt::CheckStateRole) const; + // tree state - this saves the list of expanded items based on the given role // - std::vector allIndex(const QAbstractItemModel* model, int column = 0, const QModelIndex& parent = QModelIndex()) const; - void saveTreeState(const QTreeView* tv, int role = Qt::DisplayRole); - void restoreTreeState(QTreeView* tv, int role = Qt::DisplayRole) const; + void saveTreeExpandState(const QTreeView* tv, int role = Qt::DisplayRole); + void restoreTreeExpandState(QTreeView* tv, int role = Qt::DisplayRole) const; // selected index for a combobox // -- cgit v1.3.1 From fbd7e777d76c2032d8c4df418e5550b14b9c2943 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sun, 3 Jan 2021 16:30:35 +0100 Subject: Add option to enable/disable displaying conflicts on collapsed separators. --- src/modconflicticondelegate.cpp | 25 +++---------------------- src/modlistview.cpp | 35 ++++++++++++++++++++++++++++++++++- src/modlistview.h | 6 ++++++ src/settings.cpp | 10 ++++++++++ src/settings.h | 5 +++++ src/settingsdialog.ui | 19 +++++++++++++++++++ src/settingsdialoggeneral.cpp | 7 +++++++ 7 files changed, 84 insertions(+), 23 deletions(-) (limited to 'src/settings.h') diff --git a/src/modconflicticondelegate.cpp b/src/modconflicticondelegate.cpp index cbc32037..73c47a03 100644 --- a/src/modconflicticondelegate.cpp +++ b/src/modconflicticondelegate.cpp @@ -93,28 +93,9 @@ QList ModConflictIconDelegate::getIcons(const QModelIndex &index) const return {}; } - ModInfo::Ptr info = ModInfo::getByIndex(modIndex.toInt()); - - auto flags = info->getConflictFlags(); - bool compact = m_Compact; - if (info->isSeparator() - && m_View->hasCollapsibleSeparators() - && !m_View->isExpanded(index.sibling(index.row(), 0))) { - - // combine the child conflicts - std::set eFlags(flags.begin(), flags.end()); - for (int i = 0; i < m_View->model()->rowCount(index); ++i) { - auto cIndex = m_View->model()->index(i, index.column(), index).data(ModList::IndexRole).toInt(); - auto cFlags = ModInfo::getByIndex(cIndex)->getConflictFlags(); - eFlags.insert(cFlags.begin(), cFlags.end()); - } - flags = { eFlags.begin(), eFlags.end() }; - - // force compact because there can be a lots of flags here - compact = true; - } - - return getIconsForFlags(flags, compact); + bool compact; + auto flags = m_View->conflictFlags(index, &compact); + return getIconsForFlags(flags, compact || m_Compact); } QString ModConflictIconDelegate::getFlagIcon(ModInfo::EConflictFlag flag) diff --git a/src/modlistview.cpp b/src/modlistview.cpp index e6d78bab..531a8d43 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -1045,7 +1045,9 @@ QColor ModListView::markerColor(const QModelIndex& index) const // collapsed separator auto rowIndex = index.sibling(index.row(), 0); - if (hasCollapsibleSeparators() && model()->hasChildren(rowIndex) && !isExpanded(rowIndex)) { + if (hasCollapsibleSeparators() + && m_core->settings().interface().collapsibleSeparatorsConflicts() + && model()->hasChildren(rowIndex) && !isExpanded(rowIndex)) { std::vector colors; for (int i = 0; i < model()->rowCount(rowIndex); ++i) { @@ -1073,6 +1075,37 @@ QColor ModListView::markerColor(const QModelIndex& index) const return QColor(); } +std::vector ModListView::conflictFlags(const QModelIndex& index, bool* forceCompact) const +{ + ModInfo::Ptr info = ModInfo::getByIndex(index.data(ModList::IndexRole).toInt()); + + auto flags = info->getConflictFlags(); + bool compact = false; + if (info->isSeparator() + && hasCollapsibleSeparators() + && m_core->settings().interface().collapsibleSeparatorsConflicts() + && !isExpanded(index.sibling(index.row(), 0))) { + + // combine the child conflicts + std::set eFlags(flags.begin(), flags.end()); + for (int i = 0; i < model()->rowCount(index); ++i) { + auto cIndex = model()->index(i, index.column(), index).data(ModList::IndexRole).toInt(); + auto cFlags = ModInfo::getByIndex(cIndex)->getConflictFlags(); + eFlags.insert(cFlags.begin(), cFlags.end()); + } + flags = { eFlags.begin(), eFlags.end() }; + + // force compact because there can be a lots of flags here + compact = true; + } + + if (forceCompact) { + *forceCompact = true; + } + + return flags; +} + void ModListView::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { if (hasCollapsibleSeparators()) { diff --git a/src/modlistview.h b/src/modlistview.h index 9712deab..faa33b6a 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -170,6 +170,7 @@ protected slots: private: + friend class ModConflictIconDelegate; friend class ModListStyledItemDelegated; friend class ModListViewMarkingScrollBar; @@ -191,6 +192,11 @@ private: // QColor markerColor(const QModelIndex& index) const; + // retrieve the conflicts flags for the given index + // + std::vector conflictFlags( + const QModelIndex& index, bool* forceCompact = nullptr) 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 // diff --git a/src/settings.cpp b/src/settings.cpp index 3cc026cf..e04cd0c1 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2185,6 +2185,16 @@ void InterfaceSettings::setCollapsibleSeparators(bool b) set(m_Settings, "Settings", "collapsible_separators", b); } +bool InterfaceSettings::collapsibleSeparatorsConflicts() const +{ + return get(m_Settings, "Settings", "collapsible_separators_conflicts", true); +} + +void InterfaceSettings::setCollapsibleSeparatorsConflicts(bool b) +{ + set(m_Settings, "Settings", "collapsible_separators_conflicts", b); +} + bool InterfaceSettings::compactDownloads() const { return get(m_Settings, "Settings", "compact_downloads", false); diff --git a/src/settings.h b/src/settings.h index 9c3765c2..043b22a4 100644 --- a/src/settings.h +++ b/src/settings.h @@ -626,6 +626,11 @@ public: bool collapsibleSeparators() const; void setCollapsibleSeparators(bool b); + // whether to display mod conflicts on separators when collapsed + // + bool collapsibleSeparatorsConflicts() const; + void setCollapsibleSeparatorsConflicts(bool b); + // whether to show compact downloads // bool compactDownloads() const; diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index 6655ca97..ae4f4f34 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -403,6 +403,9 @@ + + Allow collapsing separators when sorting by ascending priority. + Use collapsible separators @@ -414,6 +417,22 @@ + + + + Display mod conflicts on separator when collapsed. + + + Display mod conflicts on separator when collapsed. + + + Show conflicts on separators + + + true + + + diff --git a/src/settingsdialoggeneral.cpp b/src/settingsdialoggeneral.cpp index 47388c96..7b854260 100644 --- a/src/settingsdialoggeneral.cpp +++ b/src/settingsdialoggeneral.cpp @@ -19,6 +19,11 @@ GeneralSettingsTab::GeneralSettingsTab(Settings& s, SettingsDialog& d) ui->colorTable->load(s); + // connect before setting to trigger + QObject::connect(ui->collapsibleSeparatorsBox, &QCheckBox::stateChanged, [=](auto&& state) { + ui->collapsibleSeparatorsConflictsBox->setEnabled(state == Qt::Checked); + }); + ui->centerDialogs->setChecked(settings().geometry().centerDialogs()); ui->changeGameConfirmation->setChecked(settings().interface().showChangeGameConfirmation()); ui->doubleClickPreviews->setChecked(settings().interface().doubleClicksOpenPreviews()); @@ -27,6 +32,7 @@ GeneralSettingsTab::GeneralSettingsTab(Settings& s, SettingsDialog& d) ui->checkForUpdates->setChecked(settings().checkForUpdates()); ui->usePrereleaseBox->setChecked(settings().usePrereleases()); ui->colorSeparatorsBox->setChecked(settings().colors().colorSeparatorScrollbar()); + ui->collapsibleSeparatorsConflictsBox->setChecked(settings().interface().collapsibleSeparatorsConflicts()); ui->collapsibleSeparatorsBox->setChecked(settings().interface().collapsibleSeparators()); QObject::connect(ui->exploreStyles, &QPushButton::clicked, [&]{ onExploreStyles(); }); @@ -72,6 +78,7 @@ void GeneralSettingsTab::update() settings().setUsePrereleases(ui->usePrereleaseBox->isChecked()); settings().colors().setColorSeparatorScrollbar(ui->colorSeparatorsBox->isChecked()); settings().interface().setCollapsibleSeparators(ui->collapsibleSeparatorsBox->isChecked()); + settings().interface().setCollapsibleSeparatorsConflicts(ui->collapsibleSeparatorsConflictsBox->isChecked()); } void GeneralSettingsTab::addLanguages() -- cgit v1.3.1