diff options
Diffstat (limited to 'src/categories.cpp')
| -rw-r--r-- | src/categories.cpp | 208 |
1 files changed, 115 insertions, 93 deletions
diff --git a/src/categories.cpp b/src/categories.cpp index 70efd706..e64d35c3 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -29,6 +29,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QList> #include <QObject> +#include "nexusinterface.h" + using namespace MOBase; CategoryFactory* CategoryFactory::s_Instance = nullptr; @@ -38,6 +40,13 @@ QString CategoryFactory::categoriesFilePath() return qApp->property("dataPath").toString() + "/categories.dat"; } + +QString CategoryFactory::nexusMappingFilePath() +{ + return qApp->property("dataPath").toString() + "/nexuscatmap.dat"; +} + + CategoryFactory::CategoryFactory() { atexit(&cleanup); @@ -48,20 +57,18 @@ void CategoryFactory::loadCategories() reset(); QFile categoryFile(categoriesFilePath()); + bool needLoad = false; if (!categoryFile.open(QIODevice::ReadOnly)) { - loadDefaultCategories(); + needLoad = true; } else { int lineNum = 0; while (!categoryFile.atEnd()) { QByteArray line = categoryFile.readLine(); ++lineNum; QList<QByteArray> cells = line.split('|'); - if (cells.count() != 4) { - log::error("invalid category line {}: {} ({} cells)", lineNum, line.constData(), - cells.count()); - } else { - std::vector<int> nexusIDs; + if (cells.count() == 4) { + std::vector<NexusCategory> nexusCats; if (cells[2].length() > 0) { QList<QByteArray> nexusIDStrings = cells[2].split(','); for (QList<QByteArray>::iterator iter = nexusIDStrings.begin(); @@ -69,9 +76,9 @@ void CategoryFactory::loadCategories() bool ok = false; int temp = iter->toInt(&ok); if (!ok) { - log::error("invalid category id {}", iter->constData()); + log::error(tr("invalid category id {}"), iter->constData()); } - nexusIDs.push_back(temp); + nexusCats.push_back(NexusCategory("Unknown", temp)); } } bool cell0Ok = true; @@ -79,23 +86,63 @@ void CategoryFactory::loadCategories() int id = cells[0].toInt(&cell0Ok); int parentID = cells[3].trimmed().toInt(&cell3Ok); if (!cell0Ok || !cell3Ok) { - log::error("invalid category line {}: {}", lineNum, line.constData()); + log::error(tr("invalid category line {}: {}"), lineNum, line.constData()); } - addCategory(id, QString::fromUtf8(cells[1].constData()), nexusIDs, parentID); + addCategory(id, QString::fromUtf8(cells[1].constData()), nexusCats, parentID); + } else if (cells.count() == 3) { + bool cell0Ok = true; + bool cell3Ok = true; + int id = cells[0].toInt(&cell0Ok); + int parentID = cells[2].trimmed().toInt(&cell3Ok); + if (!cell0Ok || !cell3Ok) { + log::error(tr("invalid category line {}: {}"), lineNum, line.constData()); + } + + addCategory(id, QString::fromUtf8(cells[1].constData()), std::vector<NexusCategory>(), parentID); + } else { + log::error( + tr("invalid category line {}: {} ({} cells)"), + lineNum, line.constData(), cells.count()); } } categoryFile.close(); + + QFile nexusMapFile(nexusMappingFilePath()); + if (!nexusMapFile.open(QIODevice::ReadOnly)) { + needLoad = true; + } else { + int nexLineNum = 0; + while (!nexusMapFile.atEnd()) { + QByteArray nexLine = nexusMapFile.readLine(); + ++nexLineNum; + QList<QByteArray> nexCells = nexLine.split('|'); + std::vector<NexusCategory> nexusCats; + QString nexName = nexCells[1]; + bool ok = false; + int nexID = nexCells[2].toInt(&ok); + if (!ok) { + log::error(tr("invalid nexus ID {}"), nexCells[2].constData()); + } + int catID = nexCells[0].toInt(&ok); + if (!ok) { + log::error(tr("invalid category id {}"), nexCells[0].constData()); + } + m_NexusMap[NexusCategory(nexName, nexID)] = catID; + } + } + nexusMapFile.close(); } std::sort(m_Categories.begin(), m_Categories.end()); setParents(); + if (needLoad) loadDefaultCategories(); } -CategoryFactory& CategoryFactory::instance() +CategoryFactory* CategoryFactory::instance() { if (s_Instance == nullptr) { s_Instance = new CategoryFactory; } - return *s_Instance; + return s_Instance; } void CategoryFactory::reset() @@ -106,7 +153,7 @@ void CategoryFactory::reset() // 43 = Savegames (makes no sense to install them through MO) // 45 = Videos and trailers // 87 = Miscelanous - addCategory(0, "None", {4, 28, 43, 45, 87}, 0); + addCategory(0, "None", std::vector<NexusCategory>(), 0); } void CategoryFactory::setParents() @@ -139,7 +186,7 @@ void CategoryFactory::saveCategories() QFile categoryFile(categoriesFilePath()); if (!categoryFile.open(QIODevice::WriteOnly)) { - reportError(QObject::tr("Failed to save custom categories")); + reportError(tr("Failed to save custom categories")); return; } @@ -154,13 +201,28 @@ void CategoryFactory::saveCategories() .append("|") .append(iter->m_Name.toUtf8()) .append("|") - .append(VectorJoin(iter->m_NexusIDs, ",").toUtf8()) - .append("|") .append(QByteArray::number(iter->m_ParentID)) .append("\n"); categoryFile.write(line); } categoryFile.close(); + + QFile nexusMapFile(nexusMappingFilePath()); + + if (!nexusMapFile.open(QIODevice::WriteOnly)) { + reportError(tr("Failed to save nexus category mappings")); + return; + } + + nexusMapFile.resize(0); + QByteArray line; + for (auto iter = m_NexusMap.begin(); iter != m_NexusMap.end(); ++iter) { + line.append(iter->first.m_Name).append("|"); + line.append(iter->first.m_ID).append("|"); + line.append(iter->second).append("\n"); + categoryFile.write(line); + } + categoryFile.close(); } unsigned int @@ -175,97 +237,55 @@ CategoryFactory::countCategories(std::function<bool(const Category& category)> f return result; } -int CategoryFactory::addCategory(const QString& name, const std::vector<int>& nexusIDs, - int parentID) +int CategoryFactory::addCategory(const QString& name, const std::vector<NexusCategory>& nexusCats, int parentID) { int id = 1; while (m_IDMap.find(id) != m_IDMap.end()) { ++id; } - addCategory(id, name, nexusIDs, parentID); + addCategory(id, name, nexusCats, parentID); saveCategories(); return id; } -void CategoryFactory::addCategory(int id, const QString& name, - const std::vector<int>& nexusIDs, int parentID) +void CategoryFactory::addCategory(int id, const QString& name, int parentID) { int index = static_cast<int>(m_Categories.size()); - m_Categories.push_back(Category(index, id, name, nexusIDs, parentID)); - for (int nexusID : nexusIDs) { - m_NexusMap[nexusID] = index; - } + m_Categories.push_back(Category(index, id, name, parentID)); m_IDMap[id] = index; } +void CategoryFactory::addCategory(int id, const QString& name, const std::vector<NexusCategory>& nexusCats, int parentID) +{ + for (auto nexusCat : nexusCats) { + m_NexusMap[nexusCat] = id; + } + addCategory(id, name, parentID); +} + + void CategoryFactory::loadDefaultCategories() { // the order here is relevant as it defines the order in which the // mods appear in the combo box - addCategory(1, "Animations", {2, 4, 51}, 0); - addCategory(52, "Poses", {1, 29}, 1); - addCategory(2, "Armour", {2, 5, 54}, 0); - addCategory(53, "Power Armor", {1, 53}, 2); - addCategory(3, "Audio", {3, 33, 35, 106}, 0); - addCategory(38, "Music", {2, 34, 61}, 0); - addCategory(39, "Voice", {2, 36, 107}, 0); - addCategory(5, "Clothing", {2, 9, 60}, 0); - addCategory(41, "Jewelry", {1, 102}, 5); - addCategory(42, "Backpacks", {1, 49}, 5); - addCategory(6, "Collectables", {2, 10, 92}, 0); - addCategory(28, "Companions", {3, 11, 66, 96}, 0); - addCategory(7, "Creatures, Mounts, & Vehicles", {4, 12, 65, 83, 101}, 0); - addCategory(8, "Factions", {2, 16, 25}, 0); - addCategory(9, "Gameplay", {2, 15, 24}, 0); - addCategory(27, "Combat", {1, 77}, 9); - addCategory(43, "Crafting", {2, 50, 100}, 9); - addCategory(48, "Overhauls", {2, 24, 79}, 9); - addCategory(49, "Perks", {1, 27}, 9); - addCategory(54, "Radio", {1, 31}, 9); - addCategory(55, "Shouts", {1, 104}, 9); - addCategory(22, "Skills & Levelling", {2, 46, 73}, 9); - addCategory(58, "Weather & Lighting", {1, 56}, 9); - addCategory(44, "Equipment", {1, 44}, 43); - addCategory(45, "Home/Settlement", {1, 45}, 43); - addCategory(10, "Body, Face, & Hair", {2, 17, 26}, 0); - addCategory(56, "Tattoos", {1, 57}, 10); - addCategory(40, "Character Presets", {1, 58}, 0); - addCategory(11, "Items", {2, 27, 85}, 0); - addCategory(32, "Mercantile", {2, 23, 69}, 0); - addCategory(37, "Ammo", {1, 3}, 11); - addCategory(19, "Weapons", {2, 41, 55}, 11); - addCategory(36, "Weapon & Armour Sets", {1, 42}, 11); - addCategory(23, "Player Homes", {2, 28, 67}, 0); - addCategory(25, "Castles & Mansions", {1, 68}, 23); - addCategory(51, "Settlements", {1, 48}, 23); - addCategory(12, "Locations", {10, 20, 21, 22, 30, 47, 70, 88, 89, 90, 91}, 0); - addCategory(4, "Cities", {1, 53}, 12); - addCategory(31, "Landscape Changes", {1, 58}, 0); - addCategory(29, "Environment", {2, 14, 74}, 0); - addCategory(30, "Immersion", {2, 51, 78}, 0); - addCategory(20, "Magic", {3, 75, 93, 94}, 0); - addCategory(21, "Models & Textures", {2, 19, 29}, 0); - addCategory(33, "Modders resources", {2, 18, 82}, 0); - addCategory(13, "NPCs", {3, 22, 33, 99}, 0); - addCategory(24, "Bugfixes", {2, 6, 95}, 0); - addCategory(14, "Patches", {2, 25, 84}, 24); - addCategory(35, "Utilities", {2, 38, 39}, 0); - addCategory(26, "Cheats", {1, 8}, 0); - addCategory(15, "Quests", {2, 30, 35}, 0); - addCategory(16, "Races & Classes", {1, 34}, 0); - addCategory(34, "Stealth", {1, 76}, 0); - addCategory(17, "UI", {2, 37, 42}, 0); - addCategory(18, "Visuals", {2, 40, 62}, 0); - addCategory(50, "Pip-Boy", {1, 52}, 18); - addCategory(46, "Shader Presets", {3, 13, 97, 105}, 0); - addCategory(47, "Miscellaneous", {2, 2, 28}, 0); + if (QMessageBox::question(nullptr, tr("Load Nexus Categories?"), + tr("This is either a new or old instance which lacks modern Nexus category mappings. Would you like to import and map categories from Nexus now?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + emit requestNexusCategories(); + } +} + + +void CategoryFactory::mapNexusCategories(QString, QVariant, QVariant result) +{ + } int CategoryFactory::getParentID(unsigned int index) const { if (index >= m_Categories.size()) { - throw MyException(QObject::tr("invalid category index: %1").arg(index)); + throw MyException(tr("invalid category index: %1").arg(index)); } return m_Categories[index].m_ParentID; @@ -303,7 +323,7 @@ bool CategoryFactory::isDescendantOfImpl(int id, int parentID, return isDescendantOfImpl(m_Categories[index].m_ParentID, parentID, seen); } } else { - log::warn("{} is no valid category id", id); + log::warn(tr("{} is no valid category id"), id); return false; } } @@ -311,7 +331,7 @@ bool CategoryFactory::isDescendantOfImpl(int id, int parentID, bool CategoryFactory::hasChildren(unsigned int index) const { if (index >= m_Categories.size()) { - throw MyException(QObject::tr("invalid category index: %1").arg(index)); + throw MyException(tr("invalid category index: %1").arg(index)); } return m_Categories[index].m_HasChildren; @@ -320,7 +340,7 @@ bool CategoryFactory::hasChildren(unsigned int index) const QString CategoryFactory::getCategoryName(unsigned int index) const { if (index >= m_Categories.size()) { - throw MyException(QObject::tr("invalid category index: %1").arg(index)); + throw MyException(tr("invalid category index: %1").arg(index)); } return m_Categories[index].m_Name; @@ -388,7 +408,7 @@ QString CategoryFactory::getCategoryNameByID(int id) const int CategoryFactory::getCategoryID(unsigned int index) const { if (index >= m_Categories.size()) { - throw MyException(QObject::tr("invalid category index: %1").arg(index)); + throw MyException(tr("invalid category index: %1").arg(index)); } return m_Categories[index].m_ID; @@ -398,7 +418,7 @@ int CategoryFactory::getCategoryIndex(int ID) const { std::map<int, unsigned int>::const_iterator iter = m_IDMap.find(ID); if (iter == m_IDMap.end()) { - throw MyException(QObject::tr("invalid category id: %1").arg(ID)); + throw MyException(tr("invalid category id: %1").arg(ID)); } return iter->second; } @@ -419,12 +439,14 @@ int CategoryFactory::getCategoryID(const QString& name) const unsigned int CategoryFactory::resolveNexusID(int nexusID) const { - std::map<int, unsigned int>::const_iterator iter = m_NexusMap.find(nexusID); - if (iter != m_NexusMap.end()) { - log::debug("nexus category id {} maps to internal {}", nexusID, iter->second); - return iter->second; + auto result = std::find_if(m_NexusMap.begin(), m_NexusMap.end(), [nexusID](const std::pair<NexusCategory, unsigned int> el) { + return el.first.m_ID == nexusID; + }); + if (result != m_NexusMap.end()) { + log::debug(tr("nexus category id {} maps to internal {}"), nexusID, result->second); + return result->second; } else { - log::debug("nexus category id {} not mapped", nexusID); + log::debug(tr("nexus category id {} not mapped"), nexusID); return 0U; } } |
