From 127db7799ed4847b151a35a16cefab6c494128ef Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 23 Dec 2019 23:16:36 -0600 Subject: WIP: Category QObj refactor --- src/categoriesdialog.ui | 75 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 22 deletions(-) (limited to 'src/categoriesdialog.ui') diff --git a/src/categoriesdialog.ui b/src/categoriesdialog.ui index 582a7608..03209d53 100644 --- a/src/categoriesdialog.ui +++ b/src/categoriesdialog.ui @@ -6,19 +6,32 @@ 0 0 - 553 + 735 444 Categories - - + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + Qt::CustomContextMenu + + true + false @@ -26,7 +39,7 @@ false - QAbstractItemView::NoDragDrop + QAbstractItemView::DropOnly Qt::IgnoreAction @@ -46,15 +59,15 @@ true + + 26 + 100 true - - 26 - false @@ -85,7 +98,15 @@ - Nexus IDs + Parent ID + + + If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. + + + + + Nexus Categories Comma-Separated list of Nexus IDs to be matched to the internal ID. @@ -100,24 +121,34 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> - - - Parent ID - - - If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. - - - - - - Qt::Horizontal + + + + Qt::LeftToRight - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + Nexus Categories + + + + + + 0 + 0 + + + + true + + + QAbstractItemView::DragOnly + + + + -- cgit v1.3.1 From f764271b1f1fa457af9dd4f7d044005d46fcd84b Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 24 Dec 2019 15:15:45 -0600 Subject: WIP: Refactor cat dialog and implement nex cat updates --- src/categoriesdialog.cpp | 58 +++++++--- src/categoriesdialog.h | 12 +- src/categoriesdialog.ui | 29 +++-- src/filterlist.cpp | 7 +- src/filterlist.h | 4 +- src/mainwindow.cpp | 2 +- src/nexusinterface.cpp | 263 ++++++++++++++++++------------------------ src/settingsdialog.cpp | 3 +- src/settingsdialoggeneral.cpp | 6 +- src/settingsdialoggeneral.h | 7 +- 10 files changed, 197 insertions(+), 194 deletions(-) (limited to 'src/categoriesdialog.ui') diff --git a/src/categoriesdialog.cpp b/src/categoriesdialog.cpp index 03a7fc59..08397cb8 100644 --- a/src/categoriesdialog.cpp +++ b/src/categoriesdialog.cpp @@ -22,6 +22,7 @@ along with Mod Organizer. If not, see . #include "settings.h" #include "ui_categoriesdialog.h" #include "utility.h" +#include "nexusinterface.h" #include #include #include @@ -102,8 +103,8 @@ private: QValidator* m_Validator; }; -CategoriesDialog::CategoriesDialog(QWidget* parent) - : TutorableDialog("Categories", parent), ui(new Ui::CategoriesDialog) +CategoriesDialog::CategoriesDialog(PluginContainer* pluginContainer, QWidget* parent) + : TutorableDialog("Categories", parent), ui(new Ui::CategoriesDialog), m_PluginContainer(pluginContainer) { ui->setupUi(this); fillTable(); @@ -172,6 +173,7 @@ void CategoriesDialog::fillTable() { CategoryFactory* categories = CategoryFactory::instance(); QTableWidget* table = ui->categoriesTable; + QListWidget* list = ui->nexusCategoryList; #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); @@ -180,23 +182,9 @@ void CategoriesDialog::fillTable() table->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); table->verticalHeader()->setSectionsMovable(true); table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); -#else - table->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed); - table->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch); - table->horizontalHeader()->setResizeMode(2, QHeaderView::Fixed); - table->horizontalHeader()->setResizeMode(3, QHeaderView::Fixed); - table->verticalHeader()->setMovable(true); - table->verticalHeader()->setResizeMode(QHeaderView::Fixed); -#endif - - table->setItemDelegateForColumn( - 0, new ValidatingDelegate(this, new NewIDValidator(m_IDs))); - table->setItemDelegateForColumn( - 2, new ValidatingDelegate(this, - new QRegularExpressionValidator( - QRegularExpression("([0-9]+)?(,[0-9]+)*"), this))); - table->setItemDelegateForColumn( - 3, new ValidatingDelegate(this, new ExistingIDValidator(m_IDs))); + table->setItemDelegateForColumn(0, new ValidatingDelegate(this, new NewIDValidator(m_IDs))); + table->setItemDelegateForColumn(2, new ValidatingDelegate(this, new QRegExpValidator(QRegExp("([0-9]+)?(,[0-9]+)*"), this))); + table->setItemDelegateForColumn(3, new ValidatingDelegate(this, new ExistingIDValidator(m_IDs))); int row = 0; for (std::vector::const_iterator iter = categories->m_Categories.begin(); @@ -233,6 +221,14 @@ void CategoriesDialog::fillTable() table->setItem(row, 3, parentIDItem.take()); } + for (auto nexusCat : categories->m_NexusMap) + { + QScopedPointer nexusItem(new QListWidgetItem()); + nexusItem->setData(Qt::DisplayRole, nexusCat.first.m_Name); + nexusItem->setData(Qt::UserRole, nexusCat.first.m_ID); + list->addItem(nexusItem.take()); + } + refreshIDs(); } @@ -253,6 +249,30 @@ void CategoriesDialog::removeCategory_clicked() ui->categoriesTable->removeRow(m_ContextRow); } + +void CategoriesDialog::nexusRefresh_clicked() +{ + NexusInterface *nexus = NexusInterface::instance(m_PluginContainer); + nexus->requestGameInfo(Settings::instance().game().plugin()->gameShortName(), this, QVariant(), QString()); +} + +void CategoriesDialog::nxmGameInfoAvailable(QString gameName, QVariant, QVariant resultData, int) +{ + QVariantMap result = resultData.toMap(); + QVariantList categories = result["categories"].toList().first().toList(); + auto catFactory = CategoryFactory::instance(); + QListWidget* list = ui->nexusCategoryList; + list->clear(); + for (auto category : categories) { + auto catMap = category.toMap(); + QScopedPointer nexusItem(new QListWidgetItem()); + nexusItem->setData(Qt::DisplayRole, catMap["name"].toString()); + nexusItem->setData(Qt::UserRole, catMap["category_id"].toInt()); + list->addItem(nexusItem.take()); + } +} + + void CategoriesDialog::on_categoriesTable_customContextMenuRequested(const QPoint& pos) { m_ContextRow = ui->categoriesTable->rowAt(pos.y()); diff --git a/src/categoriesdialog.h b/src/categoriesdialog.h index c1c1c673..b6fe832f 100644 --- a/src/categoriesdialog.h +++ b/src/categoriesdialog.h @@ -22,6 +22,7 @@ along with Mod Organizer. If not, see . #include "tutorabledialog.h" #include "categories.h" +#include "plugincontainer.h" #include namespace Ui @@ -37,7 +38,7 @@ class CategoriesDialog : public MOBase::TutorableDialog Q_OBJECT public: - explicit CategoriesDialog(QWidget* parent = 0); + explicit CategoriesDialog(PluginContainer* pluginContainer, QWidget* parent = 0); ~CategoriesDialog(); // also saves and restores geometry @@ -50,11 +51,19 @@ public: **/ void commitChanges(); +public slots: + + void nxmGameInfoAvailable(QString gameName, QVariant, QVariant resultData, int); + +signals: + void refreshNexusCategories(); + private slots: void on_categoriesTable_customContextMenuRequested(const QPoint& pos); void addCategory_clicked(); void removeCategory_clicked(); + void nexusRefresh_clicked(); void cellChanged(int row, int column); private: @@ -63,6 +72,7 @@ private: private: Ui::CategoriesDialog* ui; + PluginContainer* m_PluginContainer; int m_ContextRow; int m_HighestID; diff --git a/src/categoriesdialog.ui b/src/categoriesdialog.ui index 03209d53..993de2ad 100644 --- a/src/categoriesdialog.ui +++ b/src/categoriesdialog.ui @@ -14,16 +14,6 @@ Categories - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -123,6 +113,16 @@ p, li { white-space: pre-wrap; } + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + @@ -133,7 +133,7 @@ p, li { white-space: pre-wrap; } - + 0 @@ -151,6 +151,13 @@ p, li { white-space: pre-wrap; } + + + + Refresh Nexus Categories + + + diff --git a/src/filterlist.cpp b/src/filterlist.cpp index 54853227..8ac4040c 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -2,6 +2,7 @@ #include "categories.h" #include "categoriesdialog.h" #include "organizercore.h" +#include "plugincontainer.h" #include "settings.h" #include "ui_mainwindow.h" #include @@ -188,8 +189,8 @@ private: }; -FilterList::FilterList(Ui::MainWindow* ui, OrganizerCore* organizer, CategoryFactory* factory) - : ui(ui), m_Organizer(organizer), m_factory(factory) +FilterList::FilterList(Ui::MainWindow* ui, OrganizerCore* organizer, PluginContainer* pluginContainer, CategoryFactory* factory) + : ui(ui), m_Organizer(organizer), m_pluginContainer(pluginContainer, m_factory(factory) { auto* eventFilter = new CriteriaItemFilter(ui->filters, [&](auto* item, int dir) { return cycleItem(item, dir); @@ -425,7 +426,7 @@ void FilterList::checkCriteria() void FilterList::editCategories() { - CategoriesDialog dialog(qApp->activeWindow()); + CategoriesDialog dialog(m_pluginContainer, qApp->activeWindow()); if (dialog.exec() == QDialog::Accepted) { dialog.commitChanges(); diff --git a/src/filterlist.h b/src/filterlist.h index 7bcbdc0f..823a63c2 100644 --- a/src/filterlist.h +++ b/src/filterlist.h @@ -9,6 +9,7 @@ namespace Ui class MainWindow; }; class CategoryFactory; +class PluginContainer; class Settings; class OrganizerCore; @@ -17,7 +18,7 @@ class FilterList : public QObject Q_OBJECT; public: - FilterList(Ui::MainWindow* ui, OrganizerCore* organizer, CategoryFactory* factory); + FilterList(Ui::MainWindow* ui, OrganizerCore* organizer, PluginContainer* pluginContainer, CategoryFactory* factory); void restoreState(const Settings& s); void saveState(Settings& s) const; @@ -37,6 +38,7 @@ private: Ui::MainWindow* ui; OrganizerCore* m_Organizer; CategoryFactory* m_factory; + PluginContainer* m_pluginContainer; bool onClick(QMouseEvent* e); void onItemActivated(QTreeWidgetItem* item); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e9106caa..2b653059 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -293,7 +293,7 @@ MainWindow::MainWindow(Settings& settings, OrganizerCore& organizerCore, languageChange(settings.interface().language()); m_CategoryFactory->loadCategories(); - m_Filters.reset(new FilterList(ui, &m_OrganizerCore, m_CategoryFactory)); + m_Filters.reset(new FilterList(ui, &m_OrganizerCore, &m_PluginContainer, m_CategoryFactory)); connect( m_Filters.get(), &FilterList::criteriaChanged, diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index 00ecdae3..cece6745 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -868,101 +868,72 @@ void NexusInterface::nextRequest() if (!info.m_Reroute) { bool hasParams = false; switch (info.m_Type) { - case NXMRequestInfo::TYPE_DESCRIPTION: - case NXMRequestInfo::TYPE_MODINFO: { - url = QString("%1/games/%2/mods/%3") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(info.m_ModID); - } break; - case NXMRequestInfo::TYPE_CHECKUPDATES: { - QString period; - switch (info.m_UpdatePeriod) { - case UpdatePeriod::DAY: - period = "1d"; - break; - case UpdatePeriod::WEEK: - period = "1w"; - break; - case UpdatePeriod::MONTH: - period = "1m"; - break; - } - url = QString("%1/games/%2/mods/updated?period=%3") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(period); - } break; - case NXMRequestInfo::TYPE_FILES: - case NXMRequestInfo::TYPE_GETUPDATES: { - url = QString("%1/games/%2/mods/%3/files") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(info.m_ModID); - } break; - case NXMRequestInfo::TYPE_FILEINFO: { - url = QString("%1/games/%2/mods/%3/files/%4") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(info.m_ModID) - .arg(info.m_FileID); - } break; - case NXMRequestInfo::TYPE_DOWNLOADURL: { - ModRepositoryFileInfo* fileInfo = qobject_cast( - qvariant_cast(info.m_UserData)); - if (m_User.type() == APIUserAccountTypes::Premium) { - url = QString("%1/games/%2/mods/%3/files/%4/download_link") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(info.m_ModID) - .arg(info.m_FileID); - } else if (!fileInfo->nexusKey.isEmpty() && fileInfo->nexusExpires && - fileInfo->nexusDownloadUser == m_User.id().toInt()) { - url = QString("%1/games/%2/mods/%3/files/%4/download_link?key=%5&expires=%6") + case NXMRequestInfo::TYPE_DESCRIPTION: + case NXMRequestInfo::TYPE_MODINFO: { + url = QString("%1/games/%2/mods/%3") .arg(info.m_URL) .arg(info.m_GameName) - .arg(info.m_ModID) - .arg(info.m_FileID) - .arg(fileInfo->nexusKey) - .arg(fileInfo->nexusExpires); - } else { - log::warn("{}", tr("Aborting download: Either you clicked on a premium-only " - "link and your account is not premium, " - "or the download link was generated by a different account " - "than the one stored in Mod Organizer.")); - return; - } - } break; - case NXMRequestInfo::TYPE_ENDORSEMENTS: { - url = QString("%1/user/endorsements").arg(info.m_URL); - } break; - case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: { - QString endorse = info.m_Endorse ? "endorse" : "abstain"; - url = QString("%1/games/%2/mods/%3/%4") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(info.m_ModID) - .arg(endorse); - postObject.insert("Version", info.m_ModVersion); - postData.setObject(postObject); - } break; - case NXMRequestInfo::TYPE_TOGGLETRACKING: { - url = QStringLiteral("%1/user/tracked_mods?domain_name=%2") - .arg(info.m_URL) - .arg(info.m_GameName); - postObject.insert("mod_id", info.m_ModID); - postData.setObject(postObject); - requestIsDelete = !info.m_Track; - } break; - case NXMRequestInfo::TYPE_TRACKEDMODS: { - url = QStringLiteral("%1/user/tracked_mods").arg(info.m_URL); - } break; - case NXMRequestInfo::TYPE_FILEINFO_MD5: { - url = QStringLiteral("%1/games/%2/mods/md5_search/%3") - .arg(info.m_URL) - .arg(info.m_GameName) - .arg(QString(info.m_Hash.toHex())); - } + .arg(info.m_ModID); + } break; + case NXMRequestInfo::TYPE_CHECKUPDATES: { + QString period; + switch (info.m_UpdatePeriod) { + case UpdatePeriod::DAY: + period = "1d"; + break; + case UpdatePeriod::WEEK: + period = "1w"; + break; + case UpdatePeriod::MONTH: + period = "1m"; + break; + } + url = QString("%1/games/%2/mods/updated?period=%3").arg(info.m_URL).arg(info.m_GameName).arg(period); + } break; + case NXMRequestInfo::TYPE_FILES: + case NXMRequestInfo::TYPE_GETUPDATES: { + url = QString("%1/games/%2/mods/%3/files").arg(info.m_URL).arg(info.m_GameName).arg(info.m_ModID); + } break; + case NXMRequestInfo::TYPE_FILEINFO: { + url = QString("%1/games/%2/mods/%3/files/%4").arg(info.m_URL).arg(info.m_GameName).arg(info.m_ModID).arg(info.m_FileID); + } break; + case NXMRequestInfo::TYPE_DOWNLOADURL: { + ModRepositoryFileInfo *fileInfo = qobject_cast(qvariant_cast(info.m_UserData)); + if (m_User.type() == APIUserAccountTypes::Premium) { + url = QString("%1/games/%2/mods/%3/files/%4/download_link").arg(info.m_URL).arg(info.m_GameName).arg(info.m_ModID).arg(info.m_FileID); + } else if (!fileInfo->nexusKey.isEmpty() && fileInfo->nexusExpires && fileInfo->nexusDownloadUser == m_User.id().toInt()) { + url = QString("%1/games/%2/mods/%3/files/%4/download_link?key=%5&expires=%6") + .arg(info.m_URL).arg(info.m_GameName).arg(info.m_ModID).arg(info.m_FileID).arg(fileInfo->nexusKey).arg(fileInfo->nexusExpires); + } else { + log::warn("{}", tr("Aborting download: Either you clicked on a premium-only link and your account is not premium, " + "or the download link was generated by a different account than the one stored in Mod Organizer.")); + return; + } + } break; + case NXMRequestInfo::TYPE_ENDORSEMENTS: { + url = QString("%1/user/endorsements").arg(info.m_URL); + } break; + case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: { + QString endorse = info.m_Endorse ? "endorse" : "abstain"; + url = QString("%1/games/%2/mods/%3/%4").arg(info.m_URL).arg(info.m_GameName).arg(info.m_ModID).arg(endorse); + postObject.insert("Version", info.m_ModVersion); + postData.setObject(postObject); + } break; + case NXMRequestInfo::TYPE_TOGGLETRACKING: { + url = QStringLiteral("%1/user/tracked_mods?domain_name=%2").arg(info.m_URL).arg(info.m_GameName); + postObject.insert("mod_id", info.m_ModID); + postData.setObject(postObject); + requestIsDelete = !info.m_Track; + } break; + case NXMRequestInfo::TYPE_TRACKEDMODS: { + url = QStringLiteral("%1/user/tracked_mods").arg(info.m_URL); + } break; + case NXMRequestInfo::TYPE_FILEINFO_MD5: { + url = QStringLiteral("%1/games/%2/mods/md5_search/%3").arg(info.m_URL).arg(info.m_GameName).arg(QString(info.m_Hash.toHex())); + } break; + case NXMRequestInfo::TYPE_GAMEINFO: { + url = QStringLiteral("%1/games/%2").arg(info.m_URL).arg(info.m_GameName); + } break; } } else { url = info.m_URL; @@ -1074,65 +1045,53 @@ void NexusInterface::requestFinished(std::list::iterator iter) if (!responseDoc.isNull()) { QVariant result = responseDoc.toVariant(); switch (iter->m_Type) { - case NXMRequestInfo::TYPE_DESCRIPTION: { - emit nxmDescriptionAvailable(iter->m_GameName, iter->m_ModID, - iter->m_UserData, result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_MODINFO: { - emit nxmModInfoAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, - result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_CHECKUPDATES: { - emit nxmUpdateInfoAvailable(iter->m_GameName, iter->m_UserData, result, - iter->m_ID); - } break; - case NXMRequestInfo::TYPE_FILES: { - emit nxmFilesAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, - result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_GETUPDATES: { - emit nxmUpdatesAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, - result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_FILEINFO: { - emit nxmFileInfoAvailable(iter->m_GameName, iter->m_ModID, iter->m_FileID, - iter->m_UserData, result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_DOWNLOADURL: { - emit nxmDownloadURLsAvailable(iter->m_GameName, iter->m_ModID, iter->m_FileID, - iter->m_UserData, result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_ENDORSEMENTS: { - emit nxmEndorsementsAvailable(iter->m_UserData, result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: { - emit nxmEndorsementToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, - result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_TOGGLETRACKING: { - auto results = result.toMap(); - auto message = results["message"].toString(); - if (message.contains( - QRegularExpression("User [0-9]+ is already Tracking Mod: [0-9]+")) || - message.contains( - QRegularExpression("User [0-9]+ is now Tracking Mod: [0-9]+"))) { - emit nxmTrackingToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, - true, iter->m_ID); - } else if (message.contains(QRegularExpression( - "User [0-9]+ is no longer tracking [0-9]+")) || - message.contains(QRegularExpression( - "Users is not tracking mod. Unable to untrack."))) { - emit nxmTrackingToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, - false, iter->m_ID); - } - } break; - case NXMRequestInfo::TYPE_TRACKEDMODS: { - emit nxmTrackedModsAvailable(iter->m_UserData, result, iter->m_ID); - } break; - case NXMRequestInfo::TYPE_FILEINFO_MD5: { - emit nxmFileInfoFromMd5Available(iter->m_GameName, iter->m_UserData, result, - iter->m_ID); - } break; + case NXMRequestInfo::TYPE_DESCRIPTION: { + emit nxmDescriptionAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_MODINFO: { + emit nxmModInfoAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_CHECKUPDATES: { + emit nxmUpdateInfoAvailable(iter->m_GameName, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_FILES: { + emit nxmFilesAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_GETUPDATES: { + emit nxmUpdatesAvailable(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_FILEINFO: { + emit nxmFileInfoAvailable(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_DOWNLOADURL: { + emit nxmDownloadURLsAvailable(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_ENDORSEMENTS: { + emit nxmEndorsementsAvailable(iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: { + emit nxmEndorsementToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_TOGGLETRACKING: { + auto results = result.toMap(); + auto message = results["message"].toString(); + if (message.contains(QRegularExpression("User [0-9]+ is already Tracking Mod: [0-9]+")) || + message.contains(QRegularExpression("User [0-9]+ is now Tracking Mod: [0-9]+"))) { + emit nxmTrackingToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, true, iter->m_ID); + } else if (message.contains(QRegularExpression("User [0-9]+ is no longer tracking [0-9]+")) || + message.contains(QRegularExpression("Users is not tracking mod. Unable to untrack."))) { + emit nxmTrackingToggled(iter->m_GameName, iter->m_ModID, iter->m_UserData, false, iter->m_ID); + } + } break; + case NXMRequestInfo::TYPE_TRACKEDMODS: { + emit nxmTrackedModsAvailable(iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_FILEINFO_MD5: { + emit nxmFileInfoFromMd5Available(iter->m_GameName, iter->m_UserData, result, iter->m_ID); + } break; + case NXMRequestInfo::TYPE_GAMEINFO: { + emit nxmGameInfoAvailable(iter->m_GameName, iter->m_UserData, result, iter->m_ID); + } break; } m_User.limits(parseLimits(reply)); diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 425a1cb8..6ad6fdea 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -37,8 +37,7 @@ SettingsDialog::SettingsDialog(PluginContainer* pluginContainer, Settings& setti { ui->setupUi(this); - m_tabs.push_back( - std::unique_ptr(new GeneralSettingsTab(settings, *this))); + m_tabs.push_back(std::unique_ptr(new GeneralSettingsTab(settings, m_pluginContainer, *this))); m_tabs.push_back(std::unique_ptr(new ThemeSettingsTab(settings, *this))); m_tabs.push_back( std::unique_ptr(new ModListSettingsTab(settings, *this))); diff --git a/src/settingsdialoggeneral.cpp b/src/settingsdialoggeneral.cpp index 7acaa190..95580723 100644 --- a/src/settingsdialoggeneral.cpp +++ b/src/settingsdialoggeneral.cpp @@ -8,8 +8,8 @@ using namespace MOBase; -GeneralSettingsTab::GeneralSettingsTab(Settings& s, SettingsDialog& d) - : SettingsTab(s, d) +GeneralSettingsTab::GeneralSettingsTab(Settings& s, PluginContainer* pluginContainer, SettingsDialog& d) + : SettingsTab(s, d), m_PluginContainer(pluginContainer) { // language addLanguages(); @@ -159,7 +159,7 @@ void GeneralSettingsTab::resetDialogs() void GeneralSettingsTab::onEditCategories() { - CategoriesDialog catDialog(&dialog()); + CategoriesDialog dialog(m_PluginContainer, &dialog()); if (catDialog.exec() == QDialog::Accepted) { catDialog.commitChanges(); diff --git a/src/settingsdialoggeneral.h b/src/settingsdialoggeneral.h index 61938190..ffbeb50c 100644 --- a/src/settingsdialoggeneral.h +++ b/src/settingsdialoggeneral.h @@ -3,11 +3,12 @@ #include "settings.h" #include "settingsdialog.h" +#include "plugincontainer.h" class GeneralSettingsTab : public SettingsTab { public: - GeneralSettingsTab(Settings& settings, SettingsDialog& dialog); + GeneralSettingsTab(Settings& settings, PluginContainer *pluginContainer, SettingsDialog& dialog); void update(); @@ -19,6 +20,10 @@ private: void onEditCategories(); void onResetDialogs(); + +private: + PluginContainer* m_PluginContainer; + }; #endif // SETTINGSDIALOGGENERAL_H -- cgit v1.3.1 From 2f7478f8fc3ab047eaab44cd666bcc06bf15a127 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 31 Dec 2019 02:42:00 -0600 Subject: WIP: Fix data storage and fix loading --- src/categories.cpp | 62 +++++++++++++++------------- src/categories.h | 3 +- src/categoriesdialog.cpp | 103 ++++++++++++++++++++++++++++++++++------------- src/categoriesdialog.h | 1 + src/categoriesdialog.ui | 49 +++++++++++++--------- src/mainwindow.cpp | 61 +++++++++++++++++++++++++++- src/mainwindow.h | 7 ++++ 7 files changed, 210 insertions(+), 76 deletions(-) (limited to 'src/categoriesdialog.ui') diff --git a/src/categories.cpp b/src/categories.cpp index cf8008e5..59b26c07 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -114,18 +114,25 @@ void CategoryFactory::loadCategories() QByteArray nexLine = nexusMapFile.readLine(); ++nexLineNum; QList nexCells = nexLine.split('|'); - std::vector nexusCats; - QString nexName = nexCells[1]; - bool ok = false; - int nexID = nexCells[2].toInt(&ok); - if (!ok) { - log::error(tr("invalid nexus ID {}").toStdString(), nexCells[2].constData()); - } - int catID = nexCells[0].toInt(&ok); - if (!ok) { - log::error(tr("invalid category id {}").toStdString(), nexCells[0].constData()); + if (nexCells.count() == 3) { + std::vector nexusCats; + QString nexName = nexCells[1]; + bool ok = false; + int nexID = nexCells[2].toInt(&ok); + if (!ok) { + log::error(tr("invalid nexus ID {}").toStdString(), nexCells[2].constData()); + } + int catID = nexCells[0].toInt(&ok); + if (!ok) { + log::error(tr("invalid category id {}").toStdString(), nexCells[0].constData()); + } + m_NexusMap.insert_or_assign(nexID, NexusCategory(nexName, nexID)); + m_NexusMap.at(nexID).m_CategoryID = catID; + } else { + log::error( + tr("invalid nexus category line {}: {} ({} cells)").toStdString(), + lineNum, nexLine.constData(), nexCells.count()); } - m_NexusMap[NexusCategory(nexName, nexID)] = catID; } } nexusMapFile.close(); @@ -206,14 +213,14 @@ void CategoryFactory::saveCategories() } 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); + QByteArray line; + line.append(QByteArray::number(iter->second.m_CategoryID)).append("|"); + line.append(iter->second.m_Name.toUtf8()).append("|"); + line.append(QByteArray::number(iter->second.m_ID)).append("\n"); + nexusMapFile.write(line); } - categoryFile.close(); + nexusMapFile.close(); } unsigned int @@ -250,7 +257,8 @@ void CategoryFactory::addCategory(int id, const QString& name, int parentID) void CategoryFactory::addCategory(int id, const QString& name, const std::vector& nexusCats, int parentID) { for (auto nexusCat : nexusCats) { - m_NexusMap[nexusCat] = id; + m_NexusMap.insert_or_assign(nexusCat.m_ID, nexusCat); + m_NexusMap.at(nexusCat.m_ID).m_CategoryID = id; } int index = static_cast(m_Categories.size()); m_Categories.push_back(Category(index, id, name, parentID, nexusCats)); @@ -262,11 +270,11 @@ void CategoryFactory::loadDefaultCategories() { // the order here is relevant as it defines the order in which the // mods appear in the combo box - 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(); - } + //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(); + //} } @@ -432,12 +440,10 @@ int CategoryFactory::getCategoryID(const QString& name) const unsigned int CategoryFactory::resolveNexusID(int nexusID) const { - auto result = std::find_if(m_NexusMap.begin(), m_NexusMap.end(), [nexusID](const std::pair el) { - return el.first.m_ID == nexusID; - }); + auto result = m_NexusMap.find(nexusID); if (result != m_NexusMap.end()) { - log::debug(tr("nexus category id {} maps to internal {}").toStdString(), nexusID, result->second); - return result->second; + log::debug(tr("nexus category id {} maps to internal {}").toStdString(), nexusID, result->second.m_ID); + return m_IDMap.at(result->second.m_CategoryID); } else { log::debug(tr("nexus category id {} not mapped").toStdString(), nexusID); return 0U; diff --git a/src/categories.h b/src/categories.h index e9f00726..63d72672 100644 --- a/src/categories.h +++ b/src/categories.h @@ -58,6 +58,7 @@ public: : m_Name(name), m_ID(nexusID) {} QString m_Name; int m_ID; + int m_CategoryID = -1; friend bool operator==(const NexusCategory& LHS, const NexusCategory& RHS) { return LHS.m_ID == RHS.m_ID; @@ -232,7 +233,7 @@ private: private: std::vector m_Categories; std::map m_IDMap; - std::map m_NexusMap; + std::map m_NexusMap; private: // called by isDescendantOf() diff --git a/src/categoriesdialog.cpp b/src/categoriesdialog.cpp index 08397cb8..a94484ae 100644 --- a/src/categoriesdialog.cpp +++ b/src/categoriesdialog.cpp @@ -109,7 +109,9 @@ CategoriesDialog::CategoriesDialog(PluginContainer* pluginContainer, QWidget* pa ui->setupUi(this); fillTable(); connect(ui->categoriesTable, SIGNAL(cellChanged(int, int)), this, - SLOT(cellChanged(int, int))); + SLOT(cellChanged(int,int))); + connect(ui->nexusRefresh, SIGNAL(clicked()), this, SLOT(nexusRefresh_clicked())); + connect(ui->nexusImportButton, SIGNAL(clicked()), this, SLOT(nexusImport_clicked())); } CategoriesDialog::~CategoriesDialog() @@ -138,19 +140,17 @@ void CategoriesDialog::commitChanges() for (int i = 0; i < ui->categoriesTable->rowCount(); ++i) { int index = ui->categoriesTable->verticalHeader()->logicalIndex(i); - QVariantList nexusData = ui->categoriesTable->item(index, 2)->data(Qt::UserRole).toList(); + QVariantList nexusData = ui->categoriesTable->item(index, 3)->data(Qt::UserRole).toList(); std::vector nexusCats; - for (QVariantList::iterator iter = nexusData.begin(); - iter != nexusData.end(); ++iter) { - QVariantList nexusInfo = iter->toList(); - nexusCats.push_back(CategoryFactory::NexusCategory(nexusInfo[0].toString(), nexusInfo[1].toInt())); + for (auto nexusCat : nexusData) { + nexusCats.push_back(CategoryFactory::NexusCategory(nexusCat.toList()[0].toString(), nexusCat.toList()[1].toInt())); } categories->addCategory( ui->categoriesTable->item(index, 0)->text().toInt(), ui->categoriesTable->item(index, 1)->text(), nexusCats, - ui->categoriesTable->item(index, 3)->text().toInt()); + ui->categoriesTable->item(index, 2)->text().toInt()); } categories->setParents(); @@ -179,12 +179,12 @@ void CategoriesDialog::fillTable() table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed); - table->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Fixed); + table->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); table->verticalHeader()->setSectionsMovable(true); table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); table->setItemDelegateForColumn(0, new ValidatingDelegate(this, new NewIDValidator(m_IDs))); - table->setItemDelegateForColumn(2, new ValidatingDelegate(this, new QRegExpValidator(QRegExp("([0-9]+)?(,[0-9]+)*"), this))); - table->setItemDelegateForColumn(3, new ValidatingDelegate(this, new ExistingIDValidator(m_IDs))); + table->setItemDelegateForColumn(2, new ValidatingDelegate(this, new ExistingIDValidator(m_IDs))); + table->setItemDelegateForColumn(3, new ValidatingDelegate(this, new QRegExpValidator(QRegExp("([0-9]+)?(,[0-9]+)*"), this))); int row = 0; for (std::vector::const_iterator iter = categories->m_Categories.begin(); @@ -201,32 +201,36 @@ void CategoriesDialog::fillTable() idItem->setData(Qt::DisplayRole, category.m_ID); QScopedPointer nameItem(new QTableWidgetItem(category.m_Name)); - QStringList nexusLabel; - QVariantList nexusData; - for (auto iter = category.m_NexusCats.begin(); iter < category.m_NexusCats.end(); ++iter) { - nexusLabel.append(iter->m_Name); - QVariantList data; - data.append(QVariant(iter->m_Name)); - data.append(QVariant(iter->m_ID)); - nexusData.append(data); - } - QScopedPointer nexusCatItem(new QTableWidgetItem(nexusLabel.join(", "))); - nexusCatItem->setData(Qt::UserRole, nexusData); QScopedPointer parentIDItem(new QTableWidgetItem()); parentIDItem->setData(Qt::DisplayRole, category.m_ParentID); + QScopedPointer nexusCatItem(new QTableWidgetItem()); table->setItem(row, 0, idItem.take()); table->setItem(row, 1, nameItem.take()); - table->setItem(row, 2, nexusCatItem.take()); - table->setItem(row, 3, parentIDItem.take()); + table->setItem(row, 2, parentIDItem.take()); + table->setItem(row, 3, nexusCatItem.take()); } for (auto nexusCat : categories->m_NexusMap) { QScopedPointer nexusItem(new QListWidgetItem()); - nexusItem->setData(Qt::DisplayRole, nexusCat.first.m_Name); - nexusItem->setData(Qt::UserRole, nexusCat.first.m_ID); + nexusItem->setData(Qt::DisplayRole, nexusCat.second.m_Name); + nexusItem->setData(Qt::UserRole, nexusCat.second.m_ID); list->addItem(nexusItem.take()); + auto item = table->item(categories->resolveNexusID(nexusCat.first)-1, 3); + if (item != nullptr) { + auto itemData = item->data(Qt::UserRole).toList(); + QVariantList newData; + newData.append(nexusCat.second.m_Name); + newData.append(nexusCat.second.m_ID); + itemData.insert(itemData.length(), newData); + QStringList names; + for (auto cat : itemData) { + names.append(categories->getCategoryName(categories->resolveNexusID(cat.toList()[1].toInt()))); + } + item->setData(Qt::UserRole, itemData); + item->setData(Qt::DisplayRole, names.join(", ")); + } } refreshIDs(); @@ -240,8 +244,8 @@ void CategoriesDialog::addCategory_clicked() ui->categoriesTable->setItem(row, 0, new QTableWidgetItem(QString::number(++m_HighestID))); ui->categoriesTable->setItem(row, 1, new QTableWidgetItem("new")); - ui->categoriesTable->setItem(row, 2, new QTableWidgetItem("")); - ui->categoriesTable->setItem(row, 3, new QTableWidgetItem("0")); + ui->categoriesTable->setItem(row, 2, new QTableWidgetItem("0")); + ui->categoriesTable->setItem(row, 3, new QTableWidgetItem("")); } void CategoriesDialog::removeCategory_clicked() @@ -256,10 +260,53 @@ void CategoriesDialog::nexusRefresh_clicked() nexus->requestGameInfo(Settings::instance().game().plugin()->gameShortName(), this, QVariant(), QString()); } + +void CategoriesDialog::nexusImport_clicked() +{ + if (QMessageBox::question(nullptr, tr("Import Nexus Categories?"), + tr("This will overwrite your existing categories with the loaded Nexus categories."), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + QTableWidget* table = ui->categoriesTable; + QListWidget* list = ui->nexusCategoryList; + + table->setRowCount(0); + refreshIDs(); + int row = 0; + for (int i = 0; i < list->count(); ++i) { + row = table->rowCount(); + table->insertRow(table->rowCount()); + // table->setVerticalHeaderItem(row, new QTableWidgetItem(" ")); + + QScopedPointer idItem(new QTableWidgetItem()); + idItem->setData(Qt::DisplayRole, ++m_HighestID); + + QScopedPointer nameItem(new QTableWidgetItem(list->item(i)->data(Qt::DisplayRole).toString())); + QStringList nexusLabel; + QVariantList nexusData; + nexusLabel.append(list->item(i)->data(Qt::DisplayRole).toString()); + QVariantList data; + data.append(QVariant(list->item(i)->data(Qt::DisplayRole).toString())); + data.append(QVariant(list->item(i)->data(Qt::UserRole).toInt())); + nexusData.insert(nexusData.size(), data); + QScopedPointer nexusCatItem(new QTableWidgetItem(nexusLabel.join(", "))); + nexusCatItem->setData(Qt::UserRole, nexusData); + QScopedPointer parentIDItem(new QTableWidgetItem()); + parentIDItem->setData(Qt::DisplayRole, 0); + + table->setItem(row, 0, idItem.take()); + table->setItem(row, 1, nameItem.take()); + table->setItem(row, 2, parentIDItem.take()); + table->setItem(row, 3, nexusCatItem.take()); + } + refreshIDs(); + } +} + + void CategoriesDialog::nxmGameInfoAvailable(QString gameName, QVariant, QVariant resultData, int) { QVariantMap result = resultData.toMap(); - QVariantList categories = result["categories"].toList().first().toList(); + QVariantList categories = result["categories"].toList(); auto catFactory = CategoryFactory::instance(); QListWidget* list = ui->nexusCategoryList; list->clear(); diff --git a/src/categoriesdialog.h b/src/categoriesdialog.h index b6fe832f..49749a0f 100644 --- a/src/categoriesdialog.h +++ b/src/categoriesdialog.h @@ -64,6 +64,7 @@ private slots: void addCategory_clicked(); void removeCategory_clicked(); void nexusRefresh_clicked(); + void nexusImport_clicked(); void cellChanged(int row, int column); private: diff --git a/src/categoriesdialog.ui b/src/categoriesdialog.ui index 993de2ad..d2fbf537 100644 --- a/src/categoriesdialog.ui +++ b/src/categoriesdialog.ui @@ -14,6 +14,36 @@ Categories + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Refresh from Nexus + + + + + + + + 0 + 0 + + + + <-- Import Nexus Cats + + + @@ -113,17 +143,7 @@ p, li { white-space: pre-wrap; } - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - + Qt::LeftToRight @@ -151,13 +171,6 @@ p, li { white-space: pre-wrap; } - - - - Refresh Nexus Categories - - - diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2b653059..76b7e37f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -419,7 +419,7 @@ MainWindow::MainWindow(Settings& settings, OrganizerCore& organizerCore, connect(&NexusInterface::instance(), SIGNAL(needLogin()), &m_OrganizerCore, SLOT(nexusApi())); - connect(CategoryFactory::instance(), SIGNAL(requestNexusCategories()), &m_OrganizerCore, SLOT(requestNexusCategories())); + connect(CategoryFactory::instance(), SIGNAL(requestNexusCategories()), this, SLOT(requestNexusCategories())); connect( NexusInterface::instance(&pluginContainer)->getAccessManager(), @@ -3913,6 +3913,65 @@ void MainWindow::originModified(int originID) DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure()); } + +void MainWindow::enableSelectedPlugins_clicked() +{ + m_OrganizerCore.pluginList()->enableSelected(ui->espList->selectionModel()); +} + + +void MainWindow::disableSelectedPlugins_clicked() +{ + m_OrganizerCore.pluginList()->disableSelected(ui->espList->selectionModel()); +} + +void MainWindow::sendSelectedPluginsToTop_clicked() +{ + m_OrganizerCore.pluginList()->sendToPriority(ui->espList->selectionModel(), 0); +} + +void MainWindow::sendSelectedPluginsToBottom_clicked() +{ + m_OrganizerCore.pluginList()->sendToPriority(ui->espList->selectionModel(), INT_MAX); +} + +void MainWindow::sendSelectedPluginsToPriority_clicked() +{ + bool ok; + int newPriority = QInputDialog::getInt(this, + tr("Set Priority"), tr("Set the priority of the selected plugins"), + 0, 0, INT_MAX, 1, &ok); + if (!ok) return; + + m_OrganizerCore.pluginList()->sendToPriority(ui->espList->selectionModel(), newPriority); +} + +void MainWindow::requestNexusCategories() +{ + CategoriesDialog dialog(&m_PluginContainer, this); + + if (dialog.exec() == QDialog::Accepted) { + dialog.commitChanges(); + } +} + +void MainWindow::enableSelectedMods_clicked() +{ + m_OrganizerCore.modList()->enableSelected(ui->modList->selectionModel()); + if (m_ModListSortProxy != nullptr) { + m_ModListSortProxy->invalidate(); + } +} + + +void MainWindow::disableSelectedMods_clicked() +{ + m_OrganizerCore.modList()->disableSelected(ui->modList->selectionModel()); + if (m_ModListSortProxy != nullptr) { + m_ModListSortProxy->invalidate(); + } +} + void MainWindow::updateAvailable() { ui->actionUpdate->setEnabled(true); diff --git a/src/mainwindow.h b/src/mainwindow.h index 42ffc83e..50ff893f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -157,6 +157,13 @@ public: public slots: void refresherProgress(const DirectoryRefreshProgress* p); + void directory_refreshed(); + + void toolPluginInvoke(); + void modPagePluginInvoke(); + + void requestNexusCategories(); + signals: // emitted after the information dialog has been closed, used by tutorials // -- cgit v1.3.1 From 375b8e613eda4be77f01eb9a079caa741b958112 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 9 Jan 2020 18:06:07 -0600 Subject: Implement drag & drop nexus cat assignment --- src/CMakeLists.txt | 1 + src/categoriesdialog.cpp | 2 +- src/categoriesdialog.ui | 12 +++++++- src/categoriestable.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ src/categoriestable.h | 37 +++++++++++++++++++++++ 5 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 src/categoriestable.cpp create mode 100644 src/categoriestable.h (limited to 'src/categoriesdialog.ui') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 500b0ca5..125b6ebd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ mo2_add_filter(NAME src/browser GROUPS mo2_add_filter(NAME src/core GROUPS categories + categoriestable archivefiletree installationmanager nexusinterface diff --git a/src/categoriesdialog.cpp b/src/categoriesdialog.cpp index a94484ae..3f4ea034 100644 --- a/src/categoriesdialog.cpp +++ b/src/categoriesdialog.cpp @@ -226,7 +226,7 @@ void CategoriesDialog::fillTable() itemData.insert(itemData.length(), newData); QStringList names; for (auto cat : itemData) { - names.append(categories->getCategoryName(categories->resolveNexusID(cat.toList()[1].toInt()))); + names.append(cat.toList()[0].toString()); } item->setData(Qt::UserRole, itemData); item->setData(Qt::DisplayRole, names.join(", ")); diff --git a/src/categoriesdialog.ui b/src/categoriesdialog.ui index d2fbf537..04aa5704 100644 --- a/src/categoriesdialog.ui +++ b/src/categoriesdialog.ui @@ -45,7 +45,7 @@ - + Qt::CustomContextMenu @@ -145,6 +145,9 @@ p, li { white-space: pre-wrap; } + + Drag & drop nexus categories from this pane onto the target category on the left. + Qt::LeftToRight @@ -173,6 +176,13 @@ p, li { white-space: pre-wrap; } + + + CategoriesTable + QTableWidget +
categoriestable.h
+
+
diff --git a/src/categoriestable.cpp b/src/categoriestable.cpp new file mode 100644 index 00000000..ed45826f --- /dev/null +++ b/src/categoriestable.cpp @@ -0,0 +1,76 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#include "categoriestable.h" + +CategoriesTable::CategoriesTable(QWidget* parent) : QTableWidget(parent) {} + +bool CategoriesTable::dropMimeData(int row, int column, const QMimeData* data, Qt::DropAction action) +{ + if (row == -1) + return false; + + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat("application/x-qabstractitemmodeldatalist")) + return false; + + QByteArray encoded = data->data("application/x-qabstractitemmodeldatalist"); + QDataStream stream(&encoded, QIODevice::ReadOnly); + + while (!stream.atEnd()) + { + int curRow, curCol; + QMap roleDataMap; + stream >> curRow >> curCol >> roleDataMap; + + for (auto item : findItems(roleDataMap.value(Qt::DisplayRole).toString(), Qt::MatchContains | Qt::MatchWrap)) + { + if (item->column() != 3) continue; + QVariantList newData; + for (auto nexData : item->data(Qt::UserRole).toList()) { + if (nexData.toList()[1].toInt() != roleDataMap.value(Qt::UserRole)) { + newData.insert(newData.length(), nexData); + } + } + QStringList names; + for (auto nexData : newData) { + names.append(nexData.toList()[0].toString()); + } + item->setData(Qt::DisplayRole, names.join(", ")); + item->setData(Qt::UserRole, newData); + } + + auto nexusItem = item(row, 3); + auto itemData = nexusItem->data(Qt::UserRole).toList(); + QVariantList newData; + newData.append(roleDataMap.value(Qt::DisplayRole).toString()); + newData.append(roleDataMap.value(Qt::UserRole).toInt()); + itemData.insert(itemData.length(), newData); + QStringList names; + for (auto cat : itemData) { + names.append(cat.toList()[0].toString()); + } + nexusItem->setData(Qt::UserRole, itemData); + nexusItem->setData(Qt::DisplayRole, names.join(", ")); + } + + return true; +} diff --git a/src/categoriestable.h b/src/categoriestable.h new file mode 100644 index 00000000..7aaf62a9 --- /dev/null +++ b/src/categoriestable.h @@ -0,0 +1,37 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#ifndef CATEGORIESTABLE_H +#define CATEGORIESTABLE_H + +#include +#include + +class CategoriesTable : public QTableWidget +{ + Q_OBJECT +public: + CategoriesTable(QWidget *parent = 0); + +protected: + virtual bool dropMimeData(int row, int column, const QMimeData* data, Qt::DropAction action); + +}; + +#endif // CATEGORIESTABLE_H -- cgit v1.3.1 From 59bc9e316797346b34ebfbcfe15c96f45c370dab Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 19 Sep 2023 02:59:40 -0500 Subject: Make the category table sortable --- src/categoriesdialog.ui | 439 ++++++++++++++++++++++++------------------------ src/organizer_en.ts | 40 +++-- 2 files changed, 247 insertions(+), 232 deletions(-) (limited to 'src/categoriesdialog.ui') diff --git a/src/categoriesdialog.ui b/src/categoriesdialog.ui index 04aa5704..d1966867 100644 --- a/src/categoriesdialog.ui +++ b/src/categoriesdialog.ui @@ -1,221 +1,226 @@ - CategoriesDialog - - - - 0 - 0 - 735 - 444 - - - - Categories - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Refresh from Nexus - - - - - - - - 0 - 0 - - - - <-- Import Nexus Cats - - - - - - - Qt::CustomContextMenu - - - true - - - false - - - false - - - QAbstractItemView::DropOnly - - - Qt::IgnoreAction - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - Qt::DashLine - - - false - - - true - - - 26 - - - 100 - - - true - - - false - - - true - - - - ID - - - Internal ID for the category. - - - Internal ID for the category. The categories a mod belongs to are stored by this ID. It is recommended you use new IDs for categories you add instead of re-using existing ones. - - - - - Name - - - Name of the Categorie used for display. - - - Name of the Categorie used for display. - - - - - Parent ID - - - If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. - - - - - Nexus Categories - - - Comma-Separated list of Nexus IDs to be matched to the internal ID. - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> - - - - - - - - Drag & drop nexus categories from this pane onto the target category on the left. - - - Qt::LeftToRight - - - Nexus Categories - - - - - - - 0 - 0 - - - - true - - - QAbstractItemView::DragOnly - - + CategoriesDialog + + + + 0 + 0 + 735 + 444 + + + + Categories + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + - - - - - - - - CategoriesTable - QTableWidget -
categoriestable.h
-
-
- - - - buttonBox - accepted() - CategoriesDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - CategoriesDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - + + + + Refresh from Nexus + + + + + + + + 0 + 0 + + + + <-- Import Nexus Cats + + + + + + + Qt::CustomContextMenu + + + true + + + false + + + false + + + QAbstractItemView::DropOnly + + + Qt::IgnoreAction + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::DashLine + + + true + + + false + + + true + + + 26 + + + 100 + + + true + + + false + + + true + + + + ID + + + Internal ID for the category. + + + Internal ID for the category. The categories a mod belongs to are stored by this ID. It is recommended you use new IDs for categories you add instead of re-using existing ones. + + + + + Name + + + The display name of the category. + + + The display name of the category. + + + + + Parent ID + + + If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. + + + + + Nexus Categories + + + Comma-Separated list of Nexus IDs to be matched to the internal ID. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> + p, li { white-space: pre-wrap; } + </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> + <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> + <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> + <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> + + + + + + + + + Drag & drop nexus categories from this pane onto the target category on the left. + + + Qt::LeftToRight + + + Nexus Categories + + + + + + + 0 + 0 + + + + true + + + QAbstractItemView::DragOnly + + + + + + +
+
+ + + CategoriesTable + QTableWidget +
categoriestable.h
+
+
+ + + + buttonBox + accepted() + CategoriesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CategoriesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + +
diff --git a/src/organizer_en.ts b/src/organizer_en.ts index 228b275a..9eef07f7 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -234,65 +234,75 @@ p, li { white-space: pre-wrap; } - + ID - + Internal ID for the category. - + Internal ID for the category. The categories a mod belongs to are stored by this ID. It is recommended you use new IDs for categories you add instead of re-using existing ones. - + Name - - Name of the Categorie used for display. + + The display name of the category. + Name of the Categorie used for display. - + Parent ID - + If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. - - + + Nexus Categories - + Comma-Separated list of Nexus IDs to be matched to the internal ID. - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> + p, li { white-space: pre-wrap; } + </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> + <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> + <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> + <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> - + Drag & drop nexus categories from this pane onto the target category on the left. -- cgit v1.3.1 From e18452ee76b69ddbc1b6140b8f79b2378982c5b3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 21 Sep 2023 00:02:52 -0500 Subject: Category dialog tweaks for clarity --- src/categoriesdialog.ui | 446 +++++++++++++++++++++++++----------------------- 1 file changed, 232 insertions(+), 214 deletions(-) (limited to 'src/categoriesdialog.ui') diff --git a/src/categoriesdialog.ui b/src/categoriesdialog.ui index d1966867..4f96d8a6 100644 --- a/src/categoriesdialog.ui +++ b/src/categoriesdialog.ui @@ -1,141 +1,147 @@ - CategoriesDialog - - - - 0 - 0 - 735 - 444 - - - - Categories - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Refresh from Nexus - - - - - - - - 0 - 0 - - - - <-- Import Nexus Cats - - - - - - - Qt::CustomContextMenu - - - true - - - false - - - false - - - QAbstractItemView::DropOnly - - - Qt::IgnoreAction - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - Qt::DashLine - - - true - - - false - - - true - - - 26 - - - 100 - - - true - - - false - - - true - - - - ID - - - Internal ID for the category. - - - Internal ID for the category. The categories a mod belongs to are stored by this ID. It is recommended you use new IDs for categories you add instead of re-using existing ones. - - - - - Name - - - The display name of the category. - - - The display name of the category. - - - - - Parent ID - - - If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. - - - - - Nexus Categories - - - Comma-Separated list of Nexus IDs to be matched to the internal ID. - - - + CategoriesDialog + + + + 0 + 0 + 711 + 434 + + + + Categories + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Refresh from Nexus + + + + + + + + 0 + 0 + + + + <-- Import Nexus Cats + + + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + true + + + false + + + false + + + QAbstractItemView::DropOnly + + + Qt::IgnoreAction + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + Qt::DashLine + + + true + + + false + + + true + + + 26 + + + 100 + + + true + + + false + + + true + + + + ID + + + Internal ID for the category. + + + Internal ID for the category. The categories a mod belongs to are stored by this ID. It is recommended you use new IDs for categories you add instead of re-using existing ones. + + + + + Name + + + The display name of the category. + + + The display name of the category. + + + + + Parent ID + + + If set, the category is defined as a sub-category of another one. Parent ID needs to be a valid category ID. + + + + + Nexus Categories + + + Comma-Separated list of Nexus IDs to be matched to the internal ID. + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -144,83 +150,95 @@ <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html> - - - - - - - - Drag & drop nexus categories from this pane onto the target category on the left. - - - Qt::LeftToRight - - - Nexus Categories - - - - - - - 0 - 0 - - - - true - - - QAbstractItemView::DragOnly - - - - - + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Drag & drop nexus categories from this pane onto the target category on the left. + + + Qt::LeftToRight + + + Nexus Categories (Drag && Drop to Assign) + + + + + + + 0 + 0 + + + + true + + + QAbstractItemView::DragOnly + + - - - - - CategoriesTable - QTableWidget -
categoriestable.h
-
-
- - - - buttonBox - accepted() - CategoriesDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - CategoriesDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - +
+
+ + + + + + CategoriesTable + QTableWidget +
categoriestable.h
+
+
+ + + + buttonBox + accepted() + CategoriesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CategoriesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + +
-- cgit v1.3.1