summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/downloadmanager.cpp26
-rw-r--r--src/downloadmanager.h5
-rw-r--r--src/mainwindow.cpp113
-rw-r--r--src/mainwindow.h22
-rw-r--r--src/modinfo.cpp7
-rw-r--r--src/modinfo.h2
-rw-r--r--src/modinfodialog.ui46
-rw-r--r--src/modlistsortproxy.cpp24
-rw-r--r--src/modlistsortproxy.h9
-rw-r--r--src/nexusinterface.cpp59
-rw-r--r--src/nexusinterface.h7
-rw-r--r--src/problemsdialog.ui4
-rw-r--r--src/selfupdater.cpp1
-rw-r--r--src/shared/fallout3info.cpp4
-rw-r--r--src/shared/fallout3info.h1
-rw-r--r--src/shared/falloutnvinfo.cpp4
-rw-r--r--src/shared/falloutnvinfo.h1
-rw-r--r--src/shared/gameinfo.h1
-rw-r--r--src/shared/oblivioninfo.cpp4
-rw-r--r--src/shared/oblivioninfo.h1
-rw-r--r--src/shared/skyriminfo.cpp4
-rw-r--r--src/shared/skyriminfo.h1
-rw-r--r--src/transfersavesdialog.ui4
23 files changed, 259 insertions, 91 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index 779b052c..48484d24 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -153,7 +153,8 @@ QString DownloadManager::DownloadInfo::currentURL()
DownloadManager::DownloadManager(NexusInterface *nexusInterface, QObject *parent)
- : IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_ShowHidden(false)
+ : IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_ShowHidden(false),
+ m_DateExpression("/Date\\((\\d+)\\)/")
{
connect(&m_DirWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
}
@@ -851,7 +852,6 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
setState(info, STATE_PAUSED);
} else {
if (bytesTotal > info->m_TotalSize) {
- qDebug("file size %s: %lld", qPrintable(info->m_FileName), bytesTotal);
info->m_TotalSize = bytesTotal;
}
int oldProgress = info->m_Progress;
@@ -883,6 +883,7 @@ void DownloadManager::createMetaFile(DownloadInfo *info)
metaFile.setValue("name", info->m_NexusInfo.m_Name);
metaFile.setValue("modName", info->m_NexusInfo.m_ModName);
metaFile.setValue("version", info->m_NexusInfo.m_Version);
+ metaFile.setValue("fileTime", info->m_NexusInfo.m_FileTime);
metaFile.setValue("fileCategory", info->m_NexusInfo.m_FileCategory);
metaFile.setValue("newestVersion", info->m_NexusInfo.m_NewestVersion);
metaFile.setValue("category", info->m_NexusInfo.m_Category);
@@ -914,11 +915,9 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
DownloadInfo *info = downloadInfoByID(userData.toInt());
if (info == NULL) return;
-
info->m_NexusInfo.m_Category = result["category_id"].toInt();
info->m_NexusInfo.m_ModName = result["name"].toString().trimmed();
info->m_NexusInfo.m_NewestVersion = result["version"].toString();
-
if (info->m_FileID != 0) {
setState(info, STATE_READY);
} else {
@@ -927,6 +926,17 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
}
+QDateTime DownloadManager::matchDate(const QString &timeString)
+{
+ if (m_DateExpression.exactMatch(timeString)) {
+ return QDateTime::fromMSecsSinceEpoch(m_DateExpression.cap(1).toLongLong());
+ } else {
+ qWarning("date not matched: %s", qPrintable(timeString));
+ return QDateTime::currentDateTime();
+ }
+}
+
+
void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultData, int requestID)
{
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
@@ -960,7 +970,11 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
(fileNameVariant == info->m_FileName) || (fileNameVariant == alternativeLocalName)) {
info->m_NexusInfo.m_Name = fileInfo["name"].toString();
info->m_NexusInfo.m_Version = fileInfo["version"].toString();
+ if (info->m_NexusInfo.m_Version.isEmpty()) {
+ info->m_NexusInfo.m_Version = info->m_NexusInfo.m_NewestVersion;
+ }
info->m_NexusInfo.m_FileCategory = fileInfo["category_id"].toInt();
+ info->m_NexusInfo.m_FileTime = matchDate(fileInfo["date"].toString());
info->m_FileID = fileInfo["id"].toInt();
found = true;
break;
@@ -1014,7 +1028,11 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD
info.m_Name = result["name"].toString();
info.m_Version = result["version"].toString();
+ if (info.m_Version.isEmpty()) {
+ info.m_Version = info.m_NewestVersion;
+ }
info.m_FileName = result["uri"].toString();
+ info.m_FileTime = matchDate(result["date"].toString());
if (userData.isValid()) {
m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(info), userData.toString()));
diff --git a/src/downloadmanager.h b/src/downloadmanager.h
index e82ea064..099e6084 100644
--- a/src/downloadmanager.h
+++ b/src/downloadmanager.h
@@ -46,6 +46,7 @@ struct NexusInfo {
QString m_NewestVersion;
QString m_FileName;
QVariantList m_DownloadMap;
+ QDateTime m_FileTime;
bool m_Set;
};
Q_DECLARE_METATYPE(NexusInfo)
@@ -437,6 +438,8 @@ private:
DownloadInfo *downloadInfoByID(unsigned int id);
+ QDateTime matchDate(const QString &timeString);
+
private:
static const int AUTOMATIC_RETRIES = 3;
@@ -458,6 +461,8 @@ private:
bool m_ShowHidden;
+ QRegExp m_DateExpression;
+
};
#endif // DOWNLOADMANAGER_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 102c798e..3eefffa9 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -3216,7 +3216,7 @@ void MainWindow::visitOnNexus_clicked()
{
int modID = m_ModList.data(m_ModList.index(m_ContextRow, 0), Qt::UserRole).toInt();
if (modID > 0) {
- nexusLinkActivated(QString("%1/downloads/file.php?id=%2").arg(ToQString(GameInfo::instance().getNexusPage())).arg(modID));
+ nexusLinkActivated(QString("%1/mods/%2").arg(ToQString(GameInfo::instance().getNexusPage())).arg(modID));
} else {
MessageDialog::showMessage(tr("Nexus ID for this Mod is unknown"), this);
}
@@ -3259,7 +3259,7 @@ void MainWindow::createModFromOverwrite()
bool ok;
name.update(QInputDialog::getText(this, tr("Create Mod..."),
tr("This will move all files from overwrite into a new, regular mod.\n"
- "Please enter a name: "), QLineEdit::Normal, "", &ok),
+ "Please enter a name:"), QLineEdit::Normal, "", &ok),
GUESS_USER);
if (!ok) {
return;
@@ -3311,7 +3311,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<int> &categories = modInfo->getCategories();
@@ -3340,7 +3340,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"));
}
}
@@ -3349,12 +3349,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<QWidgetAction*>(action);
if (widgetAction != NULL) {
@@ -3365,8 +3365,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<QWidgetAction*>(action);
+ if (widgetAction != NULL) {
+ QCheckBox *checkbox = qobject_cast<QCheckBox*>(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<QMenu*>(sender());
if (menu == NULL) {
qCritical("not a menu?");
@@ -3385,11 +3412,16 @@ 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);
-// refreshModList();
// find mods by their name because indices are invalidated
QAbstractItemModel *model = ui->modList->model();
@@ -3401,7 +3433,50 @@ 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);
+ }
+
+ refreshFilters();
+}
+
+void MainWindow::replaceCategories_MenuHandler() {
+ QMenu *menu = qobject_cast<QMenu*>(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);
+
+ // 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);
}
@@ -3569,7 +3644,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<ModInfo::EFlag> flags = info->getFlags();
@@ -3635,11 +3710,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 197ac73c..31fbeef3 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();
@@ -432,7 +446,9 @@ private slots:
void originModified(int originID);
- void saveCategories();
+ void addRemoveCategories_MenuHandler();
+ void replaceCategories_MenuHandler();
+
void savePrimaryCategory();
void addPrimaryCategoryCandidates();
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index f436eba8..6569f897 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -541,6 +541,13 @@ bool ModInfoRegular::setName(const QString &name)
void ModInfoRegular::setNotes(const QString &notes)
{
m_Notes = notes;
+ m_MetaInfoChanged = true;
+}
+
+void ModInfoRegular::setNexusID(int modID)
+{
+ m_NexusID = modID;
+ m_MetaInfoChanged = true;
}
void ModInfoRegular::setVersion(const VersionInfo &version)
diff --git a/src/modinfo.h b/src/modinfo.h
index 6de0275b..677d8a82 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -570,7 +570,7 @@ public:
*
* @param modID the nexus mod id
**/
- void setNexusID(int modID) { m_NexusID = modID; }
+ void setNexusID(int modID);
/**
* @brief set the version of this mod
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui
index d0039a95..7b95e011 100644
--- a/src/modinfodialog.ui
+++ b/src/modinfodialog.ui
@@ -209,7 +209,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>676</width>
+ <width>668</width>
<height>126</height>
</rect>
</property>
@@ -223,7 +223,16 @@
<property name="spacing">
<number>0</number>
</property>
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -284,7 +293,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<string/>
</property>
<property name="icon">
- <iconset>
+ <iconset resource="resources.qrc">
<normaloff>:/MO/gui/resources/go-up.png</normaloff>:/MO/gui/resources/go-up.png</iconset>
</property>
<property name="iconSize">
@@ -313,7 +322,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<string/>
</property>
<property name="icon">
- <iconset>
+ <iconset resource="resources.qrc">
<normaloff>:/MO/gui/resources/go-down.png</normaloff>:/MO/gui/resources/go-down.png</iconset>
</property>
<property name="iconSize">
@@ -395,6 +404,9 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
</property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
<property name="animated">
<bool>true</bool>
</property>
@@ -405,13 +417,13 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<number>2</number>
</property>
<attribute name="headerDefaultSectionSize">
- <number>500</number>
+ <number>365</number>
</attribute>
<attribute name="headerHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="headerMinimumSectionSize">
- <number>300</number>
+ <number>200</number>
</attribute>
<column>
<property name="text">
@@ -451,14 +463,17 @@ Most mods do not have optional esps, so chances are good you are looking at an e
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
</property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
<property name="animated">
<bool>true</bool>
</property>
<attribute name="headerDefaultSectionSize">
- <number>500</number>
+ <number>365</number>
</attribute>
<attribute name="headerMinimumSectionSize">
- <number>300</number>
+ <number>200</number>
</attribute>
<column>
<property name="text">
@@ -533,7 +548,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
</widget>
<widget class="QWidget" name="tabNexus_2">
<attribute name="icon">
- <iconset>
+ <iconset resource="resources.qrc">
<normaloff>:/MO/gui/resources/internet-web-browser.png</normaloff>:/MO/gui/resources/internet-web-browser.png</iconset>
</attribute>
<attribute name="title">
@@ -625,7 +640,7 @@ p, li { white-space: pre-wrap; }
<string/>
</property>
<property name="icon">
- <iconset>
+ <iconset resource="resources.qrc">
<normaloff>:/MO/gui/refresh</normaloff>:/MO/gui/refresh</iconset>
</property>
</widget>
@@ -651,9 +666,8 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot;-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;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot;-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;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
@@ -687,7 +701,7 @@ p, li { white-space: pre-wrap; }
<string>Endorse</string>
</property>
<property name="icon">
- <iconset>
+ <iconset resource="resources.qrc">
<normaloff>:/MO/gui/icon_favorite</normaloff>:/MO/gui/icon_favorite</iconset>
</property>
</widget>
@@ -782,6 +796,8 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="resources.qrc"/>
+ </resources>
<connections/>
</ui>
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<ModInfo::EFlag> &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;
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index 6a4ae046..6b5cf19c 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -380,29 +380,33 @@ void NexusInterface::nextRequest()
info.m_Timeout->setInterval(60000);
QString url;
- switch (info.m_Type) {
- case NXMRequestInfo::TYPE_DESCRIPTION: {
- url = QString("%1/Mods/%2/").arg(info.m_URL).arg(info.m_ModID);
- } break;
- case NXMRequestInfo::TYPE_FILES: {
- url = QString("%1/Files/indexfrommod/%2/").arg(info.m_URL).arg(info.m_ModID);
- } break;
- case NXMRequestInfo::TYPE_FILEINFO: {
- url = QString("%1/Files/%2/").arg(info.m_URL).arg(info.m_FileID);
- } break;
- case NXMRequestInfo::TYPE_DOWNLOADURL: {
- url = QString("%1/Files/download/%2").arg(info.m_URL).arg(info.m_FileID);
- } break;
- case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: {
- url = QString("%1/Mods/toggleendorsement/%2?lvote=%3").arg(info.m_URL).arg(info.m_ModID).arg(!info.m_Endorse);
- } break;
- case NXMRequestInfo::TYPE_GETUPDATES: {
- QString modIDList = VectorJoin<int>(info.m_ModIDList, ",");
- modIDList = "[" + modIDList + "]";
- url = QString("%1/Mods/GetUpdates?ModList=%2").arg(info.m_URL).arg(modIDList);
- } break;
+ if (!info.m_Reroute) {
+ switch (info.m_Type) {
+ case NXMRequestInfo::TYPE_DESCRIPTION: {
+ url = QString("%1/Mods/%2/").arg(info.m_URL).arg(info.m_ModID);
+ } break;
+ case NXMRequestInfo::TYPE_FILES: {
+ url = QString("%1/Files/indexfrommod/%2/").arg(info.m_URL).arg(info.m_ModID);
+ } break;
+ case NXMRequestInfo::TYPE_FILEINFO: {
+ url = QString("%1/Files/%2/").arg(info.m_URL).arg(info.m_FileID);
+ } break;
+ case NXMRequestInfo::TYPE_DOWNLOADURL: {
+ url = QString("%1/Files/download/%2").arg(info.m_URL).arg(info.m_FileID);
+ } break;
+ case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: {
+ url = QString("%1/Mods/toggleendorsement/%2?lvote=%3").arg(info.m_URL).arg(info.m_ModID).arg(!info.m_Endorse);
+ } break;
+ case NXMRequestInfo::TYPE_GETUPDATES: {
+ QString modIDList = VectorJoin<int>(info.m_ModIDList, ",");
+ modIDList = "[" + modIDList + "]";
+ url = QString("%1/Mods/GetUpdates?ModList=%2").arg(info.m_URL).arg(modIDList);
+ } break;
+ }
+ url.append(QString("?game_id=%1").arg(GameInfo::instance().getNexusGameID()));
+ } else {
+ url = info.m_URL;
}
-
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml");
request.setRawHeader("User-Agent",
@@ -433,13 +437,21 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter)
qWarning("request failed: %s", reply->errorString().toUtf8().constData());
emit nxmRequestFailed(iter->m_ModID, iter->m_UserData, iter->m_ID, reply->errorString());
} else {
+ int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ if (statusCode == 301) {
+ // redirect request, return request to queue
+ iter->m_URL = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
+ iter->m_Reroute = true;
+ m_RequestQueue.enqueue(*iter);
+ nextRequest();
+ return;
+ }
QByteArray data = reply->readAll();
if (data.isNull() || data.isEmpty() || (strcmp(data.constData(), "null") == 0)) {
QString nexusError(reply->rawHeader("NexusErrorInfo"));
if (nexusError.length() == 0) {
nexusError = tr("empty response");
}
-
emit nxmRequestFailed(iter->m_ModID, iter->m_UserData, iter->m_ID, nexusError);
} else {
bool ok;
@@ -509,7 +521,6 @@ void NexusInterface::requestTimeout()
qWarning("invalid sender type");
return;
}
- qWarning("request timeout");
for (std::list<NXMRequestInfo>::iterator iter = m_ActiveRequest.begin(); iter != m_ActiveRequest.end(); ++iter) {
if (iter->m_Timeout == timer) {
// this abort causes a "request failed" which cleans up the rest
diff --git a/src/nexusinterface.h b/src/nexusinterface.h
index da5fe02a..e7a01b0f 100644
--- a/src/nexusinterface.h
+++ b/src/nexusinterface.h
@@ -270,18 +270,19 @@ private:
QVariant m_UserData;
QTimer *m_Timeout;
QString m_URL;
+ bool m_Reroute;
int m_ID;
int m_Endorse;
NXMRequestInfo(int modID, Type type, QVariant userData, const QString &url)
: m_ModID(modID), m_FileID(0), m_Reply(NULL), m_Type(type), m_UserData(userData),
- m_Timeout(NULL), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
+ m_Timeout(NULL), m_Reroute(false), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
NXMRequestInfo(std::vector<int> modIDList, Type type, QVariant userData, const QString &url)
: m_ModID(-1), m_ModIDList(modIDList), m_FileID(0), m_Reply(NULL), m_Type(type), m_UserData(userData),
- m_Timeout(NULL), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
+ m_Timeout(NULL), m_Reroute(false), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
NXMRequestInfo(int modID, int fileID, Type type, QVariant userData, const QString &url)
: m_ModID(modID), m_FileID(fileID), m_Reply(NULL), m_Type(type), m_UserData(userData),
- m_Timeout(NULL), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
+ m_Timeout(NULL), m_Reroute(false), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
private:
static QAtomicInt s_NextID;
diff --git a/src/problemsdialog.ui b/src/problemsdialog.ui
index d3a0d959..99c3f3aa 100644
--- a/src/problemsdialog.ui
+++ b/src/problemsdialog.ui
@@ -49,8 +49,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot;-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;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp
index bdace814..2a9ca893 100644
--- a/src/selfupdater.cpp
+++ b/src/selfupdater.cpp
@@ -436,6 +436,7 @@ void SelfUpdater::nxmRequestFailed(int, QVariant, int requestID, const QString &
QTimer::singleShot(60000, this, SLOT(testForUpdate()));
--m_Attempts;
} else {
+ qWarning("Failed to retrieve update information: %s", qPrintable(errorMessage));
MessageDialog::showMessage(tr("Failed to retrieve update information: %1").arg(errorMessage), m_Parent);
}
}
diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp
index c673fa1b..864a67be 100644
--- a/src/shared/fallout3info.cpp
+++ b/src/shared/fallout3info.cpp
@@ -155,13 +155,13 @@ std::wstring Fallout3Info::getSEName()
std::wstring Fallout3Info::getNexusPage()
{
- return L"http://fallout3.nexusmods.com";
+ return L"http://www.nexusmods.com/fallout3";
}
std::wstring Fallout3Info::getNexusInfoUrlStatic()
{
- return L"http://fallout3.nexusmods.com";
+ return L"http://www.nexusmods.com/fallout3";
}
diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h
index 0fa97d41..4bcb9d37 100644
--- a/src/shared/fallout3info.h
+++ b/src/shared/fallout3info.h
@@ -76,6 +76,7 @@ public:
virtual std::wstring getNexusInfoUrl() { return Fallout3Info::getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
virtual int getNexusModID() { return Fallout3Info::getNexusModIDStatic(); }
+ virtual int getNexusGameID() { return 120; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
virtual void repairProfile(const std::wstring &directory);
diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp
index 7d7f0098..8df9607d 100644
--- a/src/shared/falloutnvinfo.cpp
+++ b/src/shared/falloutnvinfo.cpp
@@ -209,13 +209,13 @@ std::wstring FalloutNVInfo::getSEName()
std::wstring FalloutNVInfo::getNexusPage()
{
- return L"http://newvegas.nexusmods.com";
+ return L"http://www.nexusmods.com/newvegas";
}
std::wstring FalloutNVInfo::getNexusInfoUrlStatic()
{
- return L"http://newvegas.nexusmods.com";
+ return L"http://www.nexusmods.com/newvegas";
}
diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h
index 3960c951..e25d2e02 100644
--- a/src/shared/falloutnvinfo.h
+++ b/src/shared/falloutnvinfo.h
@@ -77,6 +77,7 @@ public:
virtual std::wstring getNexusInfoUrl() { return FalloutNVInfo::getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
virtual int getNexusModID() { return FalloutNVInfo::getNexusModIDStatic(); }
+ virtual int getNexusGameID() { return 130; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
virtual void repairProfile(const std::wstring &directory);
diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h
index 0221dd1b..d517fc1b 100644
--- a/src/shared/gameinfo.h
+++ b/src/shared/gameinfo.h
@@ -145,6 +145,7 @@ public:
virtual std::wstring getNexusPage() = 0;
virtual std::wstring getNexusInfoUrl() = 0;
virtual int getNexusModID() = 0;
+ virtual int getNexusGameID() = 0;
// clone relevant files to the specified directory
virtual void createProfile(const std::wstring &directory, bool useDefaults) = 0;
diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp
index b3e65e59..1438de0a 100644
--- a/src/shared/oblivioninfo.cpp
+++ b/src/shared/oblivioninfo.cpp
@@ -191,13 +191,13 @@ std::wstring OblivionInfo::getSEName()
std::wstring OblivionInfo::getNexusPage()
{
- return L"http://oblivion.nexusmods.com";
+ return L"http://www.nexusmods.com/oblivion";
}
std::wstring OblivionInfo::getNexusInfoUrlStatic()
{
- return L"http://oblivion.nexusmods.com";
+ return L"http://www.nexusmods.com/oblivion";
}
diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h
index 6a9f56ca..dfa53575 100644
--- a/src/shared/oblivioninfo.h
+++ b/src/shared/oblivioninfo.h
@@ -73,6 +73,7 @@ public:
virtual std::wstring getNexusInfoUrl() { return OblivionInfo::getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
virtual int getNexusModID() { return OblivionInfo::getNexusModIDStatic(); }
+ virtual int getNexusGameID() { return 101; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
virtual void repairProfile(const std::wstring &directory);
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp
index 0a0dd98d..a8b9a433 100644
--- a/src/shared/skyriminfo.cpp
+++ b/src/shared/skyriminfo.cpp
@@ -183,13 +183,13 @@ std::wstring SkyrimInfo::getSEName()
std::wstring SkyrimInfo::getNexusPage()
{
- return L"http://skyrim.nexusmods.com";
+ return L"http://www.nexusmods.com/skyrim";
}
std::wstring SkyrimInfo::getNexusInfoUrlStatic()
{
- return L"http://skyrim.nexusmods.com";
+ return L"http://www.nexusmods.com/skyrim";
}
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h
index ae5ab81f..7da523a1 100644
--- a/src/shared/skyriminfo.h
+++ b/src/shared/skyriminfo.h
@@ -81,6 +81,7 @@ public:
virtual std::wstring getNexusInfoUrl() { return SkyrimInfo::getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
virtual int getNexusModID() { return SkyrimInfo::getNexusModIDStatic(); }
+ virtual int getNexusGameID() { return 110; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
virtual void repairProfile(const std::wstring &directory);
diff --git a/src/transfersavesdialog.ui b/src/transfersavesdialog.ui
index 7cd1c4b5..1fcad54d 100644
--- a/src/transfersavesdialog.ui
+++ b/src/transfersavesdialog.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Dialog</string>
+ <string>Transfer Savegames</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -35,7 +35,7 @@ On Windows Vista/Windows 7:
C:\Users\[UserName]\Documents\My Games\Skyrim\Saves
On Windows XP:
- C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves
+ C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves
</string>
</property>
</widget>