From 42d2344f0b81cb1cf8dbe83e8f480b84ed0c3114 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Sun, 28 Oct 2018 02:16:20 +0200 Subject: Added modlist Separators feature: *New modType separator. *Bold, italic and centralized name without _separator at the end. *Added "create separator" option to context menu. *Added "rename separator" option. *Fixed rename separator issue with priority resetting. --- src/mainwindow.cpp | 42 +++++++++++++++++++++++--- src/mainwindow.h | 1 + src/modinfo.cpp | 8 +++-- src/modinfo.h | 3 +- src/modinfodialog.cpp | 17 ++++++++++- src/modinfoseparator.cpp | 36 ++++++++++++++++++++++ src/modinfoseparator.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ src/modlist.cpp | 29 ++++++++++++++++-- 8 files changed, 202 insertions(+), 11 deletions(-) create mode 100644 src/modinfoseparator.cpp create mode 100644 src/modinfoseparator.h (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 04bd96c7..bc25ab70 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2629,8 +2629,9 @@ void MainWindow::modOpenNext(int tab) ModInfo::Ptr mod = ModInfo::getByIndex(m_ContextRow); std::vector flags = mod->getFlags(); if ((std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) || - (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end())) { - // skip overwrite and backups + (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end()) || + (std::find(flags.begin(), flags.end(), ModInfo::FLAG_SEPARATOR) != flags.end())) { + // skip overwrite and backups and separators modOpenNext(tab); } else { displayModInformation(m_ContextRow,tab); @@ -2649,8 +2650,9 @@ void MainWindow::modOpenPrev(int tab) ModInfo::Ptr mod = ModInfo::getByIndex(m_ContextRow); std::vector flags = mod->getFlags(); if ((std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) || - (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end())) { - // skip overwrite and backups + (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end()) || + (std::find(flags.begin(), flags.end(), ModInfo::FLAG_SEPARATOR) != flags.end())) { + // skip overwrite and backups and separators modOpenPrev(tab); } else { displayModInformation(m_ContextRow,tab); @@ -2839,6 +2841,33 @@ void MainWindow::createEmptyMod_clicked() m_OrganizerCore.refreshModList(); } +void MainWindow::createSeparator_clicked() +{ + GuessedValue name; + name.setFilter(&fixDirectoryName); + while (name->isEmpty()) + { + bool ok; + name.update(QInputDialog::getText(this, tr("Create Separator..."), + tr("This will create a new separator.\n" + "Please enter a name:"), QLineEdit::Normal, "", &ok), + GUESS_USER); + if (!ok) { return; } + } + if (m_OrganizerCore.getMod(name) != nullptr) + { + reportError(tr("A separator with this name already exists")); + return; + } + name->append("_separator"); + if (m_OrganizerCore.getMod(name) != nullptr) + { + return; + } + if (m_OrganizerCore.createMod(name) == nullptr) { return; } + m_OrganizerCore.refreshModList(); +} + void MainWindow::createModFromOverwrite() { GuessedValue name; @@ -3579,6 +3608,8 @@ QMenu *MainWindow::modListContextMenu() menu->addAction(tr("Create empty mod"), this, SLOT(createEmptyMod_clicked())); + menu->addAction(tr("Create separator"), this, SLOT(createSeparator_clicked())); + menu->addSeparator(); menu->addAction(tr("Enable all visible"), this, SLOT(enableVisibleMods())); @@ -3623,6 +3654,9 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) } else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end()) { menu->addAction(tr("Restore Backup"), this, SLOT(restoreBackup_clicked())); menu->addAction(tr("Remove Backup..."), this, SLOT(removeMod_clicked())); + } else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_SEPARATOR) != flags.end()){ + menu->addAction(tr("Rename Separator..."), this, SLOT(renameMod_clicked())); + menu->addAction(tr("Remove Separator..."), this, SLOT(removeMod_clicked())); } else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_FOREIGN) != flags.end()) { // nop, nothing to do with this mod } else { diff --git a/src/mainwindow.h b/src/mainwindow.h index 0bf3d3c8..78d374e6 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -404,6 +404,7 @@ private slots: // modlist context menu void installMod_clicked(); void createEmptyMod_clicked(); + void createSeparator_clicked(); void restoreBackup_clicked(); void renameMod_clicked(); void removeMod_clicked(); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 8ce40da3..4c41a114 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see . #include "modinforegular.h" #include "modinfoforeign.h" #include "modinfooverwrite.h" +#include "modinfoseparator.h" #include "installationtester.h" #include "categories.h" @@ -64,11 +65,14 @@ bool ModInfo::ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS) ModInfo::Ptr ModInfo::createFrom(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &dir, DirectoryEntry **directoryStructure) { QMutexLocker locker(&s_Mutex); -// int id = s_NextID++; + // int id = s_NextID++; static QRegExp backupExp(".*backup[0-9]*"); + static QRegExp separatorExp(".*_separator"); ModInfo::Ptr result; if (backupExp.exactMatch(dir.dirName())) { result = ModInfo::Ptr(new ModInfoBackup(pluginContainer, game, dir, directoryStructure)); + } else if(separatorExp.exactMatch(dir.dirName())){ + result = Ptr(new ModInfoSeparator(pluginContainer, game, dir, directoryStructure)); } else { result = ModInfo::Ptr(new ModInfoRegular(pluginContainer, game, dir, directoryStructure)); } @@ -418,4 +422,4 @@ void ModInfo::testValid() while (dirIter.hasNext()) { dirIter.next(); } -} \ No newline at end of file +} diff --git a/src/modinfo.h b/src/modinfo.h index 895105df..9f6c2fbc 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -62,6 +62,7 @@ public: enum EFlag { FLAG_INVALID, FLAG_BACKUP, + FLAG_SEPARATOR, FLAG_OVERWRITE, FLAG_FOREIGN, FLAG_NOTENDORSED, @@ -560,7 +561,7 @@ public: /** * @return true if this mod is considered "valid", that is: it contains data used by the game **/ - bool isValid() const { return m_Valid; } + virtual bool isValid() const { return m_Valid; } /** * @return true if the file has been endorsed on nexus diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index fedddd6c..54910e41 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -134,7 +134,22 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo refreshLists(); - if (unmanaged) { + if (modInfo->hasFlag(ModInfo::FLAG_SEPARATOR)) + { + ui->tabWidget->setTabEnabled(TAB_TEXTFILES, false); + ui->tabWidget->setTabEnabled(TAB_INIFILES, false); + ui->tabWidget->setTabEnabled(TAB_IMAGES, false); + ui->tabWidget->setTabEnabled(TAB_ESPS, false); + ui->tabWidget->setTabEnabled(TAB_CONFLICTS, false); + //ui->tabWidget->setTabEnabled(TAB_CATEGORIES, false); + addCategories(CategoryFactory::instance(), modInfo->getCategories(), ui->categoriesTree->invisibleRootItem(), 0); + refreshPrimaryCategoriesBox(); + ui->tabWidget->setTabEnabled(TAB_NEXUS, false); + //ui->tabWidget->setTabEnabled(TAB_NOTES, false); + ui->tabWidget->setTabEnabled(TAB_FILETREE, false); + } + else if (unmanaged) + { ui->tabWidget->setTabEnabled(TAB_INIFILES, false); ui->tabWidget->setTabEnabled(TAB_CATEGORIES, false); ui->tabWidget->setTabEnabled(TAB_NEXUS, false); diff --git a/src/modinfoseparator.cpp b/src/modinfoseparator.cpp new file mode 100644 index 00000000..60014f66 --- /dev/null +++ b/src/modinfoseparator.cpp @@ -0,0 +1,36 @@ +#include "modinfoseparator.h" + +bool ModInfoSeparator::setName(const QString& name) +{ + return ModInfoRegular::setName(name); +} + +std::vector ModInfoSeparator::getFlags() const +{ + { + auto result = ModInfoRegular::getFlags(); + result.insert(result.begin(), FLAG_SEPARATOR); + return result; + } +} + +int ModInfoSeparator::getHighlight() const +{ + return HIGHLIGHT_CENTER; +} + +QString ModInfoSeparator::getDescription() const +{ + return tr("This is a Separator"); +} + +QString ModInfoSeparator::name() const +{ + return ModInfoRegular::name(); +} + + +ModInfoSeparator::ModInfoSeparator(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, const QDir &path, MOShared::DirectoryEntry **directoryStructure) + : ModInfoRegular(pluginContainer, game, path, directoryStructure) +{ +} diff --git a/src/modinfoseparator.h b/src/modinfoseparator.h new file mode 100644 index 00000000..f215fb17 --- /dev/null +++ b/src/modinfoseparator.h @@ -0,0 +1,77 @@ +#ifndef MODINFOSEPARATOR_H +#define MODINFOSEPARATOR_H + +#include "modinforegular.h" + +class ModInfoSeparator: + public ModInfoRegular +{ + friend class ModInfo; + +public: + + virtual bool updateAvailable() const { return false; } + virtual bool updateIgnored() const { return false; } + virtual bool downgradeAvailable() const { return false; } + virtual bool updateNXMInfo() { return false; } + virtual bool isValid() const { return true; } + //TODO: Fix renaming method to avoid priority reset + virtual bool setName(const QString& name); + + virtual int getNexusID() const { return -1; } + + virtual void setGameName(QString /*gameName*/) + { + } + + virtual void setNexusID(int /*modID*/) + { + } + + virtual void endorse(bool /*doEndorse*/) + { + } + + virtual void ignoreUpdate(bool /*ignore*/) + { + } + + virtual bool canBeUpdated() const { return false; } + virtual bool canBeEnabled() const { return false; } + virtual std::vector getIniTweaks() const { return std::vector(); } + + virtual std::vector getFlags() const; + virtual int getHighlight() const; + + virtual QString getDescription() const; + virtual QString name() const; + virtual QString getGameName() const { return ""; } + virtual QString getInstallationFile() const { return ""; } + virtual QString getURL() const { return ""; } + virtual QString repository() const { return ""; } + + virtual QDateTime getLastNexusQuery() const { return QDateTime(); } + virtual QDateTime creationTime() const { return QDateTime(); } + + virtual void getNexusFiles + ( + QList::const_iterator& /*unused*/, + QList::const_iterator& /*unused*/) + { + } + + virtual QString getNexusDescription() const { return QString(); } + + virtual void addInstalledFile(int /*modId*/, int /*fileId*/) + { + } + +private: + + ModInfoSeparator + ( + PluginContainer* pluginContainer, const MOBase::IPluginGame* game, const QDir& path, + MOShared::DirectoryEntry** directoryStructure); +}; + +#endif diff --git a/src/modlist.cpp b/src/modlist.cpp index c7f6a53b..31ef9ddc 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -45,6 +45,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include @@ -145,6 +146,7 @@ QString ModList::getFlagText(ModInfo::EFlag flag, ModInfo::Ptr modInfo) const { switch (flag) { case ModInfo::FLAG_BACKUP: return tr("Backup"); + case ModInfo::FLAG_SEPARATOR: return tr("Separator"); case ModInfo::FLAG_INVALID: return tr("No valid game data"); case ModInfo::FLAG_NOTENDORSED: return tr("Not endorsed yet"); case ModInfo::FLAG_NOTES: return QString("%1").arg(modInfo->notes().replace("\n", "
")); @@ -203,7 +205,13 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const || (column == COL_CONTENT)) { return QVariant(); } else if (column == COL_NAME) { - return modInfo->name(); + auto flags = modInfo->getFlags(); + if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_SEPARATOR) != flags.end()) + { + return modInfo->name().replace("_separator", ""); + } + else + return modInfo->name(); } else if (column == COL_VERSION) { VersionInfo verInfo = modInfo->getVersion(); QString version = verInfo.displayString(); @@ -277,6 +285,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return QVariant(); } } else if (role == Qt::TextAlignmentRole) { + auto flags = modInfo->getFlags(); if (column == COL_NAME) { if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_CENTER) { return QVariant(Qt::AlignCenter | Qt::AlignVCenter); @@ -327,8 +336,15 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return modInfo->getGameName(); } else if (role == Qt::FontRole) { QFont result; + auto flags = modInfo->getFlags(); if (column == COL_NAME) { - if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_INVALID) { + if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_SEPARATOR) != flags.end()) + { + //result.setCapitalization(QFont::AllUppercase); + result.setItalic(true); + //result.setUnderline(true); + result.setBold(true); + } else if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_INVALID) { result.setItalic(true); } } else if ((column == COL_CATEGORY) && (modInfo->hasFlag(ModInfo::FLAG_FOREIGN))) { @@ -476,6 +492,7 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) ModInfo::Ptr info = ModInfo::getByIndex(modID); IModList::ModStates oldState = state(modID); + bool result = false; emit aboutToChangeData(); @@ -493,7 +510,13 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) } else if (role == Qt::EditRole) { switch (index.column()) { case COL_NAME: { - result = renameMod(modID, value.toString()); + auto flags = info->getFlags(); + if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_SEPARATOR) != flags.end()) + { + result = renameMod(modID, value.toString() + "_separator"); + } + else + result = renameMod(modID, value.toString()); } break; case COL_PRIORITY: { bool ok = false; -- cgit v1.3.1