From cffd9eb4e21f0ddcddca68d8eb0f1c80c8ac6ae1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 5 Oct 2013 14:20:48 +0200 Subject: - hook.dll now doesn't inject to certain applications (currently steam, chrome and firefox) - versioning system improved. Will now report "downgrades" for mods and support a different versioning system (requires manual switch) - updates can now be ignored until a new version is uploaded - new splash screen - bugfix: a few memory leaks (shouldn't account for much) - bugfix: result of GetModuleHandle wasn't zero-terminated in some cases --- src/modlistsortproxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 53c03c6a..c7c3ab28 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -211,7 +211,7 @@ bool ModListSortProxy::filterMatches(ModInfo::Ptr info, bool enabled) const if (enabled) return false; } break; case CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE: { - if (!info->updateAvailable()) return false; + if (!info->updateAvailable() && !info->downgradeAvailable()) return false; } break; case CategoryFactory::CATEGORY_SPECIAL_NOCATEGORY: { if (info->getCategories().size() > 0) return false; -- cgit v1.3.1 From d73b1e38c8c4dd817fc833fee44216244c87da43 Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 17 Oct 2013 19:21:22 +0200 Subject: - mod sorting now always uses priority as secondary sorting - added missing ipluginlist.h --- src/modinfo.h | 17 ---------------- src/modlistsortproxy.cpp | 51 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 30 deletions(-) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/modinfo.h b/src/modinfo.h index e408e812..59030350 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -80,23 +80,6 @@ public: ENDORSED_UNKNOWN, ENDORSED_NEVER }; -/* - struct NexusFileInfo { - NexusFileInfo(const QString &data); - NexusFileInfo(int id, const QString &name, const QString &url, const QString &version, - const QString &description, int category, int size) - : id(id), name(name), url(url), version(version), description(description), - category(category), size(size) {} - int id; - QString name; - QString url; - QString version; - QString description; - int category; - int size; - - QString toString() const; - };*/ public: diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index c7c3ab28..888ecdb8 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -137,10 +137,30 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, 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(); + } + switch (left.column()) { - case ModList::COL_FLAGS: lt = leftMod->getFlags().size() < rightMod->getFlags().size(); break; - case ModList::COL_NAME: lt = QString::compare(leftMod->name(), rightMod->name(), Qt::CaseInsensitive) < 0; break; + case ModList::COL_FLAGS: { + if (leftMod->getFlags().size() != rightMod->getFlags().size()) + lt = leftMod->getFlags().size() < rightMod->getFlags().size(); + } break; + case ModList::COL_NAME: { + int comp = QString::compare(leftMod->name(), rightMod->name(), Qt::CaseInsensitive); + if (comp != 0) + lt = comp < 0; + } break; case ModList::COL_CATEGORY: { + if (leftMod->getPrimaryCategory() != rightMod->getPrimaryCategory()) { if (leftMod->getPrimaryCategory() < 0) lt = false; else if (rightMod->getPrimaryCategory() < 0) lt = true; else { @@ -153,19 +173,24 @@ bool ModListSortProxy::lessThan(const QModelIndex &left, qCritical("failed to compare categories: %s", e.what()); } } - } break; - case ModList::COL_MODID: lt = leftMod->getNexusID() < rightMod->getNexusID(); break; - case ModList::COL_VERSION: lt = leftMod->getVersion() < rightMod->getVersion(); break; - case ModList::COL_PRIORITY: { - QVariant leftPrio = left.data(); - if (!leftPrio.isValid()) leftPrio = left.data(Qt::UserRole); - QVariant rightPrio = right.data(); - if (!rightPrio.isValid()) rightPrio = right.data(Qt::UserRole); - - return leftPrio.toInt() < rightPrio.toInt(); + } + } break; + case ModList::COL_MODID: { + if (leftMod->getNexusID() != rightMod->getNexusID()) + lt = leftMod->getNexusID() < rightMod->getNexusID(); + } break; + case ModList::COL_VERSION: { + if (leftMod->getVersion() != rightMod->getVersion()) + lt = leftMod->getVersion() < rightMod->getVersion(); } break; case ModList::COL_INSTALLTIME: { - return left.data().toDateTime() < right.data().toDateTime(); + QDateTime leftTime = left.data().toDateTime(); + QDateTime rightTime = right.data().toDateTime(); + if (leftTime != rightTime) + return leftTime < rightTime; + } break; + case ModList::COL_PRIORITY: { + // nop, already compared by priority } break; } return lt; -- cgit v1.3.1 From daf4ae44faee3e641a743cc9f4e0c56f016faad4 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 1 Dec 2013 23:50:24 +0100 Subject: - added second context menu for changing categories that applies only changes to the selected mods instead of replacing the existing set of categories (thanks to Ross!) - bugfix: category filtering didn't work correctly when grouping was also active --- src/mainwindow.cpp | 109 ++++++++++++++++++++++++++++++++++++++++------- src/mainwindow.h | 22 ++++++++-- src/modlistsortproxy.cpp | 24 +++++++++-- src/modlistsortproxy.h | 9 +--- 4 files changed, 134 insertions(+), 30 deletions(-) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 31ee1ae7..d5330017 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3309,7 +3309,7 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index) } } -bool MainWindow::addCategories(QMenu *menu, int targetID) +bool MainWindow::populateMenuCategories(QMenu *menu, int targetID) { ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); const std::set &categories = modInfo->getCategories(); @@ -3338,7 +3338,7 @@ bool MainWindow::addCategories(QMenu *menu, int targetID) targetMenu->addAction(checkableAction.take()); if (m_CategoryFactory.hasChildren(i)) { - if (addCategories(targetMenu, m_CategoryFactory.getCategoryID(i)) || enabled) { + if (populateMenuCategories(targetMenu, m_CategoryFactory.getCategoryID(i)) || enabled) { targetMenu->setIcon(QIcon(":/MO/gui/resources/check.png")); } } @@ -3347,12 +3347,12 @@ bool MainWindow::addCategories(QMenu *menu, int targetID) return childEnabled; } -void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow) +void MainWindow::replaceCategoriesFromMenu(QMenu *menu, int modRow) { ModInfo::Ptr modInfo = ModInfo::getByIndex(modRow); foreach (QAction* action, menu->actions()) { if (action->menu() != NULL) { - saveCategoriesFromMenu(action->menu(), modRow); + replaceCategoriesFromMenu(action->menu(), modRow); } else { QWidgetAction *widgetAction = qobject_cast(action); if (widgetAction != NULL) { @@ -3363,8 +3363,35 @@ void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow) } } -void MainWindow::saveCategories() +void MainWindow::addRemoveCategoriesFromMenu(QMenu *menu, int modRow) { + if (m_ContextRow != -1 && m_ContextRow != modRow) { + ModInfo::Ptr editedModInfo = ModInfo::getByIndex(m_ContextRow); + foreach (QAction* action, menu->actions()) { + if (action->menu() != NULL) { + addRemoveCategoriesFromMenu(action->menu(), modRow); + } else { + QWidgetAction *widgetAction = qobject_cast(action); + if (widgetAction != NULL) { + QCheckBox *checkbox = qobject_cast(widgetAction->defaultWidget()); + int categoryId = widgetAction->data().toInt(); + bool checkedBefore = editedModInfo->categorySet(categoryId); + bool checkedAfter = checkbox->isChecked(); + + if (checkedBefore != checkedAfter) { // only update if the category was changed on the edited mod + ModInfo::Ptr currentModInfo = ModInfo::getByIndex(modRow); + currentModInfo->setCategory(categoryId, checkedAfter); + } + } + } + } + } else { + //This block shouldn't be reached, but if it is then fall back to replace (context row is invalid or replacing edited mod) + replaceCategoriesFromMenu(menu, modRow); + } +} + +void MainWindow::addRemoveCategories_MenuHandler() { QMenu *menu = qobject_cast(sender()); if (menu == NULL) { qCritical("not a menu?"); @@ -3383,11 +3410,58 @@ void MainWindow::saveCategories() selectedMods.append(temp.data().toString()); if (temp.row() < min) min = temp.row(); if (temp.row() > max) max = temp.row(); - saveCategoriesFromMenu(menu, mapToModel(&m_ModList, selected.at(i)).row()); + // save the currently selected mod for last... then we can use it as a pattern for what is changing... + int modRow = m_ModListSortProxy->mapToSource(selected.at(i)).row(); + if (modRow != m_ContextRow) { + addRemoveCategoriesFromMenu(menu,modRow); + } } - //m_ModList.notifyChange(min, max); + //come back to the currently selected mod, after the others have been set + replaceCategoriesFromMenu(menu, m_ContextRow); + + m_ModList.notifyChange(-1); + + // find mods by their name because indices are invalidated + QAbstractItemModel *model = ui->modList->model(); + Q_FOREACH(const QString &mod, selectedMods) { + QModelIndexList matches = model->match(model->index(0, 0), Qt::DisplayRole, mod, 1, + Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive); + if (matches.size() > 0) { + ui->modList->selectionModel()->select(matches.at(0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + } + } + } else { + //For single mod selections, just do a replace + replaceCategoriesFromMenu(menu, m_ContextRow); + m_ModList.notifyChange(m_ContextRow); + } + + refreshFilters(); +} + +void MainWindow::replaceCategories_MenuHandler() { + QMenu *menu = qobject_cast(sender()); + if (menu == NULL) { + qCritical("not a menu?"); + return; + } + + QModelIndexList selected = ui->modList->selectionModel()->selectedRows(); + + if (selected.size() > 0) { + int min = INT_MAX; + int max = INT_MIN; + + QStringList selectedMods; + for (int i = 0; i < selected.size(); ++i) { + QModelIndex temp = mapToModel(&m_ModList, selected.at(i)); + selectedMods.append(temp.data().toString()); + if (temp.row() < min) min = temp.row(); + if (temp.row() > max) max = temp.row(); + replaceCategoriesFromMenu(menu, mapToModel(&m_ModList, selected.at(i)).row()); + } + m_ModList.notifyChange(-1); -// refreshModList(); // find mods by their name because indices are invalidated QAbstractItemModel *model = ui->modList->model(); @@ -3399,7 +3473,8 @@ void MainWindow::saveCategories() } } } else { - saveCategoriesFromMenu(menu, m_ContextRow); + //For single mod selections, just do a replace + replaceCategoriesFromMenu(menu, m_ContextRow); m_ModList.notifyChange(m_ContextRow); } @@ -3567,7 +3642,7 @@ void MainWindow::exportModListCSV() bool enabled = m_CurrentProfile->modEnabled(i); if ((selection.getChoiceData().toInt() == 1) && !enabled) { continue; - } else if ((selection.getChoiceData().toInt() == 2) && !m_ModListSortProxy->filterMatches(info, enabled)) { + } else if ((selection.getChoiceData().toInt() == 2) && !m_ModListSortProxy->filterMatchesMod(info, enabled)) { continue; } std::vector flags = info->getFlags(); @@ -3633,11 +3708,15 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) menu.addAction(tr("Restore Backup"), this, SLOT(restoreBackup_clicked())); menu.addAction(tr("Remove Backup..."), this, SLOT(removeMod_clicked())); } else { - // Set categories is a separate menu connected to a push button. This way it doesn't simply close every time you hover the mouse outside - QMenu *addCategoryMenu = new QMenu(tr("Set Category")); - addCategories(addCategoryMenu, 0); - connect(addCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(saveCategories())); - addMenuAsPushButton(&menu, addCategoryMenu); + QMenu *addRemoveCategoriesMenu = new QMenu(tr("Add/Remove Categories")); + populateMenuCategories(addRemoveCategoriesMenu, 0); + connect(addRemoveCategoriesMenu, SIGNAL(aboutToHide()), this, SLOT(addRemoveCategories_MenuHandler())); + addMenuAsPushButton(&menu, addRemoveCategoriesMenu); + + QMenu *replaceCategoriesMenu = new QMenu(tr("Replace Categories")); + populateMenuCategories(replaceCategoriesMenu, 0); + connect(replaceCategoriesMenu, SIGNAL(aboutToHide()), this, SLOT(replaceCategories_MenuHandler())); + addMenuAsPushButton(&menu, replaceCategoriesMenu); QMenu *primaryCategoryMenu = new QMenu(tr("Primary Category")); connect(primaryCategoryMenu, SIGNAL(aboutToShow()), this, SLOT(addPrimaryCategoryCandidates())); diff --git a/src/mainwindow.h b/src/mainwindow.h index dfd2e571..27a56812 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -230,9 +230,23 @@ private: void refreshFilters(); - void saveCategoriesFromMenu(QMenu *menu, int modRow); + /** + * Sets category selections from menu; for multiple mods, this will only apply + * the changes made in the menu (which is the delta between the current menu selection and the reference mod) + * @param menu the menu after editing by the user + * @param modRow index of the mod to edit + */ + void addRemoveCategoriesFromMenu(QMenu *menu, int modRow); + + /** + * Sets category selections from menu; for multiple mods, this will completely + * replace the current set of categories on each selected with those selected in the menu + * @param menu the menu after editing by the user + * @param modRow index of the mod to edit + */ + void replaceCategoriesFromMenu(QMenu *menu, int modRow); - bool addCategories(QMenu *menu, int targetID); + bool populateMenuCategories(QMenu *menu, int targetID); void updateDownloadListDelegate(); @@ -431,7 +445,9 @@ private slots: void originModified(int originID); - void saveCategories(); + void addRemoveCategories_MenuHandler(); + void replaceCategories_MenuHandler(); + void savePrimaryCategory(); void addPrimaryCategoryCandidates(); diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 888ecdb8..4d767230 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -220,7 +220,7 @@ bool ModListSortProxy::hasConflictFlag(const std::vector &flags) } -bool ModListSortProxy::filterMatches(ModInfo::Ptr info, bool enabled) const +bool ModListSortProxy::filterMatchesMod(ModInfo::Ptr info, bool enabled) const { if (!m_CurrentFilter.isEmpty() && !info->name().contains(m_CurrentFilter, Qt::CaseInsensitive)) { @@ -258,7 +258,7 @@ bool ModListSortProxy::filterMatches(ModInfo::Ptr info, bool enabled) const } -bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex&) const +bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex &parent) const { if (m_Profile == NULL) { return false; @@ -268,9 +268,25 @@ bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex&) const qWarning("invalid row idx %d", row); return false; } - bool modEnabled = m_Profile->modEnabled(row); - return filterMatches(ModInfo::getByIndex(row), modEnabled); + QModelIndex idx = sourceModel()->index(row, 0, parent); + if (!idx.isValid()) { + qDebug("invalid index"); + return false; + } + if (idx.isValid() && sourceModel()->hasChildren(idx)) { + for (int i = 0; i < sourceModel()->rowCount(idx); ++i) { + if (filterAcceptsRow(i, idx)) { + return true; + } + } + + return false; + } else { + bool modEnabled = idx.sibling(row, 0).data(Qt::CheckStateRole).toInt() == Qt::Checked; + unsigned int index = idx.data(Qt::UserRole + 1).toInt(); + return filterMatchesMod(ModInfo::getByIndex(index), modEnabled); + } } diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index dd968b9e..3e18ea4e 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -52,14 +52,7 @@ public: **/ void disableAllVisible(); - bool filterMatches(ModInfo::Ptr info, bool enabled) const; - -/* - virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const { - int rc = QSortFilterProxyModel::rowCount(parent); - qDebug() << parent << " - " << rc; - return rc; - }*/ + bool filterMatchesMod(ModInfo::Ptr info, bool enabled) const; virtual bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const { return rowCount(parent) > 0; -- cgit v1.3.1