diff options
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/json.cpp | 522 | ||||
| -rw-r--r-- | src/json.h | 94 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 22 | ||||
| -rw-r--r-- | src/mainwindow.h | 5 | ||||
| -rw-r--r-- | src/mainwindow.ui | 4 | ||||
| -rw-r--r-- | src/modinforegular.cpp | 25 | ||||
| -rw-r--r-- | src/modlist.cpp | 12 | ||||
| -rw-r--r-- | src/nexusinterface.cpp | 14 | ||||
| -rw-r--r-- | src/nxmaccessmanager.cpp | 45 | ||||
| -rw-r--r-- | src/settings.cpp | 14 | ||||
| -rw-r--r-- | src/settings.h | 16 | ||||
| -rw-r--r-- | src/settingsdialog.ui | 10 |
13 files changed, 61 insertions, 724 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc7d7a78..b241d99a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,7 +79,6 @@ SET(organizer_SRCS previewgenerator.cpp previewdialog.cpp aboutdialog.cpp - json.cpp modflagicondelegate.cpp genericicondelegate.cpp organizerproxy.cpp @@ -173,7 +172,6 @@ SET(organizer_HDRS previewgenerator.h previewdialog.h aboutdialog.h - json.h modflagicondelegate.h genericicondelegate.h organizerproxy.h diff --git a/src/json.cpp b/src/json.cpp deleted file mode 100644 index 05a2665a..00000000 --- a/src/json.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/**
- * QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa.
- * Copyright (C) 2011 Eeli Reilin
- *
- * This program 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.
- *
- * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file json.cpp
- */
-
-#include "json.h"
-
-namespace QtJson {
- static QString sanitizeString(QString str);
- static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep);
- static QVariant parseValue(const QString &json, int &index, bool &success);
- static QVariant parseObject(const QString &json, int &index, bool &success);
- static QVariant parseArray(const QString &json, int &index, bool &success);
- static QVariant parseString(const QString &json, int &index, bool &success);
- static QVariant parseNumber(const QString &json, int &index);
- static int lastIndexOfNumber(const QString &json, int index);
- static void eatWhitespace(const QString &json, int &index);
- static int lookAhead(const QString &json, int index);
- static int nextToken(const QString &json, int &index);
-
- template<typename T>
- QByteArray serializeMap(const T &map, bool &success) {
- QByteArray str = "{ ";
- QList<QByteArray> pairs;
- for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) {
- QByteArray serializedValue = serialize(it.value());
- if (serializedValue.isNull()) {
- success = false;
- break;
- }
- pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
- }
-
- str += join(pairs, ", ");
- str += " }";
- return str;
- }
-
-
- /**
- * parse
- */
- QVariant parse(const QString &json) {
- bool success = true;
- return parse(json, success);
- }
-
- /**
- * parse
- */
- QVariant parse(const QString &json, bool &success) {
- success = true;
-
- // Return an empty QVariant if the JSON data is either null or empty
- if (!json.isNull() || !json.isEmpty()) {
- QString data = json;
- // We'll start from index 0
- int index = 0;
-
- // Parse the first value
- QVariant value = parseValue(data, index, success);
-
- // Return the parsed value
- return value;
- } else {
- // Return the empty QVariant
- return QVariant();
- }
- }
-
- QByteArray serialize(const QVariant &data) {
- bool success = true;
- return serialize(data, success);
- }
-
- QByteArray serialize(const QVariant &data, bool &success) {
- QByteArray str;
- success = true;
-
- if (!data.isValid()) { // invalid or null?
- str = "null";
- } else if ((data.type() == QVariant::List) ||
- (data.type() == QVariant::StringList)) { // variant is a list?
- QList<QByteArray> values;
- const QVariantList list = data.toList();
- Q_FOREACH(const QVariant& v, list) {
- QByteArray serializedValue = serialize(v);
- if (serializedValue.isNull()) {
- success = false;
- break;
- }
- values << serializedValue;
- }
-
- str = "[ " + join( values, ", " ) + " ]";
- } else if (data.type() == QVariant::Hash) { // variant is a hash?
- str = serializeMap<>(data.toHash(), success);
- } else if (data.type() == QVariant::Map) { // variant is a map?
- str = serializeMap<>(data.toMap(), success);
- } else if ((data.type() == QVariant::String) ||
- (data.type() == QVariant::ByteArray)) {// a string or a byte array?
- str = sanitizeString(data.toString()).toUtf8();
- } else if (data.type() == QVariant::Double) { // double?
- double value = data.toDouble();
- if ((value - value) == 0.0) {
- str = QByteArray::number(value, 'g');
- if (!str.contains(".") && ! str.contains("e")) {
- str += ".0";
- }
- } else {
- success = false;
- }
- } else if (data.type() == QVariant::Bool) { // boolean value?
- str = data.toBool() ? "true" : "false";
- } else if (data.type() == QVariant::ULongLong) { // large unsigned number?
- str = QByteArray::number(data.value<qulonglong>());
- } else if (data.canConvert<qlonglong>()) { // any signed number?
- str = QByteArray::number(data.value<qlonglong>());
- } else if (data.canConvert<long>()) { //TODO: this code is never executed
- str = QString::number(data.value<long>()).toUtf8();
- } else if (data.canConvert<QString>()) { // can value be converted to string?
- // this will catch QDate, QDateTime, QUrl, ...
- str = sanitizeString(data.toString()).toUtf8();
- } else {
- success = false;
- }
-
- if (success) {
- return str;
- } else {
- return QByteArray();
- }
- }
-
- QString serializeStr(const QVariant &data) {
- return QString::fromUtf8(serialize(data));
- }
-
- QString serializeStr(const QVariant &data, bool &success) {
- return QString::fromUtf8(serialize(data, success));
- }
-
-
- /**
- * \enum JsonToken
- */
- enum JsonToken {
- JsonTokenNone = 0,
- JsonTokenCurlyOpen = 1,
- JsonTokenCurlyClose = 2,
- JsonTokenSquaredOpen = 3,
- JsonTokenSquaredClose = 4,
- JsonTokenColon = 5,
- JsonTokenComma = 6,
- JsonTokenString = 7,
- JsonTokenNumber = 8,
- JsonTokenTrue = 9,
- JsonTokenFalse = 10,
- JsonTokenNull = 11
- };
-
- static QString sanitizeString(QString str) {
- str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
- str.replace(QLatin1String("\""), QLatin1String("\\\""));
- str.replace(QLatin1String("\b"), QLatin1String("\\b"));
- str.replace(QLatin1String("\f"), QLatin1String("\\f"));
- str.replace(QLatin1String("\n"), QLatin1String("\\n"));
- str.replace(QLatin1String("\r"), QLatin1String("\\r"));
- str.replace(QLatin1String("\t"), QLatin1String("\\t"));
- return QString(QLatin1String("\"%1\"")).arg(str);
- }
-
- static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep) {
- QByteArray res;
- Q_FOREACH(const QByteArray &i, list) {
- if (!res.isEmpty()) {
- res += sep;
- }
- res += i;
- }
- return res;
- }
-
- /**
- * parseValue
- */
- static QVariant parseValue(const QString &json, int &index, bool &success) {
- // Determine what kind of data we should parse by
- // checking out the upcoming token
- switch(lookAhead(json, index)) {
- case JsonTokenString:
- return parseString(json, index, success);
- case JsonTokenNumber:
- return parseNumber(json, index);
- case JsonTokenCurlyOpen:
- return parseObject(json, index, success);
- case JsonTokenSquaredOpen:
- return parseArray(json, index, success);
- case JsonTokenTrue:
- nextToken(json, index);
- return QVariant(true);
- case JsonTokenFalse:
- nextToken(json, index);
- return QVariant(false);
- case JsonTokenNull:
- nextToken(json, index);
- return QVariant();
- case JsonTokenNone:
- break;
- }
-
- // If there were no tokens, flag the failure and return an empty QVariant
- success = false;
- return QVariant();
- }
-
- /**
- * parseObject
- */
- static QVariant parseObject(const QString &json, int &index, bool &success) {
- QVariantMap map;
- int token;
-
- // Get rid of the whitespace and increment index
- nextToken(json, index);
-
- // Loop through all of the key/value pairs of the object
- bool done = false;
- while (!done) {
- // Get the upcoming token
- token = lookAhead(json, index);
-
- if (token == JsonTokenNone) {
- success = false;
- return QVariantMap();
- } else if (token == JsonTokenComma) {
- nextToken(json, index);
- } else if (token == JsonTokenCurlyClose) {
- nextToken(json, index);
- return map;
- } else {
- // Parse the key/value pair's name
- QString name = parseString(json, index, success).toString();
-
- if (!success) {
- return QVariantMap();
- }
-
- // Get the next token
- token = nextToken(json, index);
-
- // If the next token is not a colon, flag the failure
- // return an empty QVariant
- if (token != JsonTokenColon) {
- success = false;
- return QVariant(QVariantMap());
- }
-
- // Parse the key/value pair's value
- QVariant value = parseValue(json, index, success);
-
- if (!success) {
- return QVariantMap();
- }
-
- // Assign the value to the key in the map
- map[name] = value;
- }
- }
-
- // Return the map successfully
- return QVariant(map);
- }
-
- /**
- * parseArray
- */
- static QVariant parseArray(const QString &json, int &index, bool &success) {
- QVariantList list;
-
- nextToken(json, index);
-
- bool done = false;
- while(!done) {
- int token = lookAhead(json, index);
-
- if (token == JsonTokenNone) {
- success = false;
- return QVariantList();
- } else if (token == JsonTokenComma) {
- nextToken(json, index);
- } else if (token == JsonTokenSquaredClose) {
- nextToken(json, index);
- break;
- } else {
- QVariant value = parseValue(json, index, success);
- if (!success) {
- return QVariantList();
- }
- list.push_back(value);
- }
- }
-
- return QVariant(list);
- }
-
- /**
- * parseString
- */
- static QVariant parseString(const QString &json, int &index, bool &success) {
- QString s;
- QChar c;
-
- eatWhitespace(json, index);
-
- c = json[index++];
-
- bool complete = false;
- while(!complete) {
- if (index == json.size()) {
- break;
- }
-
- c = json[index++];
-
- if (c == '\"') {
- complete = true;
- break;
- } else if (c == '\\') {
- if (index == json.size()) {
- break;
- }
-
- c = json[index++];
-
- if (c == '\"') {
- s.append('\"');
- } else if (c == '\\') {
- s.append('\\');
- } else if (c == '/') {
- s.append('/');
- } else if (c == 'b') {
- s.append('\b');
- } else if (c == 'f') {
- s.append('\f');
- } else if (c == 'n') {
- s.append('\n');
- } else if (c == 'r') {
- s.append('\r');
- } else if (c == 't') {
- s.append('\t');
- } else if (c == 'u') {
- int remainingLength = json.size() - index;
- if (remainingLength >= 4) {
- QString unicodeStr = json.mid(index, 4);
-
- int symbol = unicodeStr.toInt(0, 16);
-
- s.append(QChar(symbol));
-
- index += 4;
- } else {
- break;
- }
- }
- } else {
- s.append(c);
- }
- }
-
- if (!complete) {
- success = false;
- return QVariant();
- }
-
- return QVariant(s);
- }
-
- /**
- * parseNumber
- */
- static QVariant parseNumber(const QString &json, int &index) {
- eatWhitespace(json, index);
-
- int lastIndex = lastIndexOfNumber(json, index);
- int charLength = (lastIndex - index) + 1;
- QString numberStr;
-
- numberStr = json.mid(index, charLength);
-
- index = lastIndex + 1;
- bool ok;
-
- if (numberStr.contains('.')) {
- return QVariant(numberStr.toDouble(nullptr));
- } else if (numberStr.startsWith('-')) {
- int i = numberStr.toInt(&ok);
- if (!ok) {
- qlonglong ll = numberStr.toLongLong(&ok);
- return ok ? ll : QVariant(numberStr);
- }
- return i;
- } else {
- uint u = numberStr.toUInt(&ok);
- if (!ok) {
- qulonglong ull = numberStr.toULongLong(&ok);
- return ok ? ull : QVariant(numberStr);
- }
- return u;
- }
- }
-
- /**
- * lastIndexOfNumber
- */
- static int lastIndexOfNumber(const QString &json, int index) {
- int lastIndex;
-
- for(lastIndex = index; lastIndex < json.size(); lastIndex++) {
- if (QString("0123456789+-.eE").indexOf(json[lastIndex]) == -1) {
- break;
- }
- }
-
- return lastIndex -1;
- }
-
- /**
- * eatWhitespace
- */
- static void eatWhitespace(const QString &json, int &index) {
- for(; index < json.size(); index++) {
- if (QString(" \t\n\r").indexOf(json[index]) == -1) {
- break;
- }
- }
- }
-
- /**
- * lookAhead
- */
- static int lookAhead(const QString &json, int index) {
- int saveIndex = index;
- return nextToken(json, saveIndex);
- }
-
- /**
- * nextToken
- */
- static int nextToken(const QString &json, int &index) {
- eatWhitespace(json, index);
-
- if (index == json.size()) {
- return JsonTokenNone;
- }
-
- QChar c = json[index];
- index++;
- switch(c.toLatin1()) {
- case '{': return JsonTokenCurlyOpen;
- case '}': return JsonTokenCurlyClose;
- case '[': return JsonTokenSquaredOpen;
- case ']': return JsonTokenSquaredClose;
- case ',': return JsonTokenComma;
- case '"': return JsonTokenString;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '-': return JsonTokenNumber;
- case ':': return JsonTokenColon;
- }
- index--; // ^ WTF?
-
- int remainingLength = json.size() - index;
-
- // True
- if (remainingLength >= 4) {
- if (json[index] == 't' && json[index + 1] == 'r' &&
- json[index + 2] == 'u' && json[index + 3] == 'e') {
- index += 4;
- return JsonTokenTrue;
- }
- }
-
- // False
- if (remainingLength >= 5) {
- if (json[index] == 'f' && json[index + 1] == 'a' &&
- json[index + 2] == 'l' && json[index + 3] == 's' &&
- json[index + 4] == 'e') {
- index += 5;
- return JsonTokenFalse;
- }
- }
-
- // Null
- if (remainingLength >= 4) {
- if (json[index] == 'n' && json[index + 1] == 'u' &&
- json[index + 2] == 'l' && json[index + 3] == 'l') {
- index += 4;
- return JsonTokenNull;
- }
- }
-
- return JsonTokenNone;
- }
-} //end namespace
diff --git a/src/json.h b/src/json.h deleted file mode 100644 index 57842e37..00000000 --- a/src/json.h +++ /dev/null @@ -1,94 +0,0 @@ -/**
- * QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa.
- * Copyright (C) 2011 Eeli Reilin
- *
- * This program 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.
- *
- * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file json.h
- */
-
-#ifndef JSON_H
-#define JSON_H
-
-#include <QVariant>
-#include <QString>
-
-
-/**
- * \namespace QtJson
- * \brief A JSON data parser
- *
- * Json parses a JSON data into a QVariant hierarchy.
- */
-namespace QtJson {
- typedef QVariantMap JsonObject;
- typedef QVariantList JsonArray;
-
- /**
- * Parse a JSON string
- *
- * \param json The JSON data
- */
- QVariant parse(const QString &json);
-
- /**
- * Parse a JSON string
- *
- * \param json The JSON data
- * \param success The success of the parsing
- */
- QVariant parse(const QString &json, bool &success);
-
- /**
- * This method generates a textual JSON representation
- *
- * \param data The JSON data generated by the parser.
- *
- * \return QByteArray Textual JSON representation in UTF-8
- */
- QByteArray serialize(const QVariant &data);
-
- /**
- * This method generates a textual JSON representation
- *
- * \param data The JSON data generated by the parser.
- * \param success The success of the serialization
- *
- * \return QByteArray Textual JSON representation in UTF-8
- */
- QByteArray serialize(const QVariant &data, bool &success);
-
- /**
- * This method generates a textual JSON representation
- *
- * \param data The JSON data generated by the parser.
- *
- * \return QString Textual JSON representation
- */
- QString serializeStr(const QVariant &data);
-
- /**
- * This method generates a textual JSON representation
- *
- * \param data The JSON data generated by the parser.
- * \param success The success of the serialization
- *
- * \return QString Textual JSON representation
- */
- QString serializeStr(const QVariant &data, bool &success);
-}
-
-#endif //JSON_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7592bd1e..1ecb6417 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -749,11 +749,11 @@ void MainWindow::createEndorseWidget() buttonMenu->clear(); QAction *endorseAction = new QAction(tr("Endorse"), buttonMenu); - connect(endorseAction, SIGNAL(triggered()), this, SLOT(on_actionEndorseMO_triggered())); + connect(endorseAction, SIGNAL(triggered()), this, SLOT(actionEndorseMO())); buttonMenu->addAction(endorseAction); QAction *wontEndorseAction = new QAction(tr("Won't Endorse"), buttonMenu); - connect(wontEndorseAction, SIGNAL(triggered()), this, SLOT(on_actionWontEndorseMO_triggered())); + connect(wontEndorseAction, SIGNAL(triggered()), this, SLOT(actionWontEndorseMO())); buttonMenu->addAction(wontEndorseAction); } @@ -1866,9 +1866,21 @@ void MainWindow::processUpdates() { lastHidden = hidden; } } - if (lastVersion < QVersionNumber(2,1,6)) { + if (lastVersion < QVersionNumber(2, 1, 6)) { ui->modList->header()->setSectionHidden(ModList::COL_NOTES, true); } + if (lastVersion < QVersionNumber(2, 2, 0)) { + QSettings &instance = Settings::instance().directInterface(); + instance.beginGroup("Settings"); + instance.remove("steam_password"); + instance.remove("nexus_username"); + instance.remove("nexus_password"); + instance.remove("nexus_api_key"); + instance.endGroup(); + instance.beginGroup("Servers"); + instance.remove(""); + instance.endGroup(); + } } if (currentVersion > lastVersion) { @@ -5366,7 +5378,7 @@ void MainWindow::on_actionUpdate_triggered() } -void MainWindow::on_actionEndorseMO_triggered() +void MainWindow::actionEndorseMO() { // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now IPluginGame * game = m_OrganizerCore.getGame("skyrimse"); @@ -5381,7 +5393,7 @@ void MainWindow::on_actionEndorseMO_triggered() } } -void MainWindow::on_actionWontEndorseMO_triggered() +void MainWindow::actionWontEndorseMO() { // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now IPluginGame * game = m_OrganizerCore.getGame("skyrimse"); diff --git a/src/mainwindow.h b/src/mainwindow.h index a0c043a1..ff23b8fb 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -494,6 +494,9 @@ private slots: void updateAvailable(); + void actionEndorseMO(); + void actionWontEndorseMO(); + void motdReceived(const QString &motd); void originModified(int originID); @@ -621,8 +624,6 @@ private slots: // ui slots void on_actionNotifications_triggered(); void on_actionSettings_triggered(); void on_actionUpdate_triggered(); - void on_actionEndorseMO_triggered(); - void on_actionWontEndorseMO_triggered(); void on_bsaList_customContextMenuRequested(const QPoint &pos); void on_clearFiltersButton_clicked(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index ad6b3e38..5ac8f092 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -550,10 +550,10 @@ p, li { white-space: pre-wrap; } <item> <widget class="QLabel" name="apiRequests"> <property name="toolTip"> - <string>API Queued and Remaining Requests</string> + <string>Nexus API Queued and Remaining Requests</string> </property> <property name="whatsThis"> - <string><html><head/><body><p>This tracks the number of queued Nexus API requests on the left (<span style=" font-weight:600;">Q</span>) and the remaining daily (<span style=" font-weight:600;">D</span>) and hourly (<span style=" font-weight:600;">H</span>) requests on the right. The Nexus API limits you to a pool of <span style=" font-weight:600;">2500</span> requests per day and <span style=" font-weight:600;">100</span> requests per hour. It is dynamically updated every time a request is completed. If you exceed this limit, you will be unable to queue downloads, check updates, parse mod info, or even log in.</p></body></html></string> + <string><html><head/><body><p>This tracks the number of queued Nexus API requests on the left (<span style=" font-weight:600;">Q</span>) and the remaining daily (<span style=" font-weight:600;">D</span>) and hourly (<span style=" font-weight:600;">H</span>) requests on the right. The Nexus API limits you to a pool of requests per day and requests per hour. It is dynamically updated every time a request is completed. If you run out of requests, you will be unable to queue downloads, check updates, parse mod info, or even log in. Both pools must be consumed before this happens.</p></body></html></string> </property> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index ac1c46d6..8bef1c28 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -508,31 +508,6 @@ bool ModInfoRegular::canBeUpdated() const QDateTime ModInfoRegular::getExpires() const { return m_LastNexusUpdate.addSecs(300); - /* - switch (Settings::instance().nexusUpdateStrategy()) { - case Settings::NexusUpdateStrategy::Flexible: { - qint64 diff = m_NexusLastModified.msecsTo(QDateTime::currentDateTimeUtc()); - qint64 year = 31536000000; - qint64 sixMonths = 15768000000; - qint64 threeMonths = 7884000000; - qint64 oneMonth = 1314000000; - - if (diff < oneMonth) - return m_LastNexusUpdate.addSecs(7200); - else if (diff < threeMonths) - return m_LastNexusUpdate.addSecs(14400); - else if (diff < sixMonths) - return m_LastNexusUpdate.addSecs(21600); - else if (diff < year) - return m_LastNexusUpdate.addSecs(43200); - else - return m_LastNexusUpdate.addSecs(86400); - } break; - case Settings::NexusUpdateStrategy::Rigid: { - return m_LastNexusUpdate.addSecs(86400); - } break; - } - */ } std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const diff --git a/src/modlist.cpp b/src/modlist.cpp index 55241492..bb490113 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -466,15 +466,11 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const if (modInfo->getNexusID() > 0) { if (!modInfo->canBeUpdated()) { qint64 remains = QDateTime::currentDateTimeUtc().secsTo(modInfo->getExpires()); - qint64 hours = remains / 3600; - qint64 minutes = (remains % 3600) / 60; - QString remainsStr(tr("%1 hours and %2 minutes").arg(hours).arg(minutes)); - text += "<br>" + tr("This mod was last checked on %1. It will be available to check in %2.") - .arg(modInfo->getLastNexusUpdate().toLocalTime().toString(Qt::DefaultLocaleShortDate)) + qint64 minutes = remains / 60; + qint64 seconds = (remains % 60) / 60; + QString remainsStr(tr("%1 minute(s) and %2 second(s)").arg(minutes).arg(seconds)); + text += "<br>" + tr("This mod will be available to check in %2.") .arg(remainsStr); - } else { - text += "<br>" + tr("This mod is eligible for an update check."); - text += "<br>" + tr("It was last checked on %1").arg(modInfo->getLastNexusUpdate().toLocalTime().toString(Qt::DefaultLocaleShortDate)); } } return text; diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index e657dfc1..265d898c 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -21,7 +21,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "iplugingame.h" #include "nxmaccessmanager.h" -#include "json.h" #include "selectiondialog.h" #include "bbcode.h" #include <utility.h> @@ -613,6 +612,8 @@ void NexusInterface::nextRequest() url = info.m_URL; } QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); request.setRawHeader("APIKEY", m_AccessManager->apiKey().toUtf8()); request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, m_AccessManager->userAgent(info.m_SubModule)); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); @@ -645,7 +646,10 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter) if (reply->error() != QNetworkReply::NoError) { int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (statusCode == 429) { - qWarning("All API requests have been consumed and are now being denied."); + if (reply->rawHeader("x-rl-daily-remaining").toInt() || reply->rawHeader("x-rl-hourly-remaining").toInt()) + qWarning("You appear to be making requests to the Nexus API too quickly and are being throttled. Please inform the MO2 team."); + else + qWarning("All API requests have been consumed and are now being denied."); qWarning("Error: %s", reply->errorString().toUtf8().constData()); } else { qWarning("request failed: %s", reply->errorString().toUtf8().constData()); @@ -670,9 +674,9 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter) qDebug("nexus error: %s", qUtf8Printable(nexusError)); emit nxmRequestFailed(iter->m_GameName, iter->m_ModID, iter->m_FileID, iter->m_UserData, iter->m_ID, reply->error(), nexusError); } else { - bool ok; - QVariant result = QtJson::parse(data, ok); - if (result.isValid() && ok) { + QJsonDocument responseDoc = QJsonDocument::fromJson(data); + 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); diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 1e0ac49b..aca1d785 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -259,33 +259,40 @@ void NXMAccessManager::validateFinished() if (m_ValidateReply != nullptr) { QJsonDocument jdoc = QJsonDocument::fromJson(m_ValidateReply->readAll()); - QJsonObject credentialsData = jdoc.object(); - if (credentialsData.contains("user_id")) { - QString name = credentialsData.value("name").toString(); - bool premium = credentialsData.value("is_premium").toBool(); + if (!jdoc.isNull()) { + QJsonObject credentialsData = jdoc.object(); + if (credentialsData.contains("user_id")) { + QString name = credentialsData.value("name").toString(); + bool premium = credentialsData.value("is_premium").toBool(); - std::tuple<int, int, int, int> limits(std::make_tuple( - m_ValidateReply->rawHeader("x-rl-daily-remaining").toInt(), - m_ValidateReply->rawHeader("x-rl-daily-limit").toInt(), - m_ValidateReply->rawHeader("x-rl-hourly-remaining").toInt(), - m_ValidateReply->rawHeader("x-rl-hourly-limit").toInt() - )); + std::tuple<int, int, int, int> limits(std::make_tuple( + m_ValidateReply->rawHeader("x-rl-daily-remaining").toInt(), + m_ValidateReply->rawHeader("x-rl-daily-limit").toInt(), + m_ValidateReply->rawHeader("x-rl-hourly-remaining").toInt(), + m_ValidateReply->rawHeader("x-rl-hourly-limit").toInt() + )); - emit credentialsReceived(name, premium, limits); + emit credentialsReceived(name, premium, limits); - m_ValidateReply->deleteLater(); - m_ValidateReply = nullptr; + m_ValidateReply->deleteLater(); + m_ValidateReply = nullptr; - m_ValidateState = VALIDATE_VALID; - emit validateSuccessful(true); + m_ValidateState = VALIDATE_VALID; + emit validateSuccessful(true); + } else { + m_ApiKey.clear(); + m_ValidateState = VALIDATE_NOT_VALID; + emit validateFailed(tr("Validation failed, please reauthenticate in the Settings -> Nexus tab: %1").arg(credentialsData.value("message").toString())); + } } else { m_ApiKey.clear(); - m_ValidateState = VALIDATE_NOT_VALID; - emit validateFailed(tr("Validation failed, please reauthenticate in the Settings -> Nexus tab: %1").arg(credentialsData.value("message").toString())); + m_ValidateState = VALIDATE_NOT_CHECKED; + emit validateFailed(tr("Could not parse response. Invalid JSON.")); } - } else { + } + else { m_ApiKey.clear(); m_ValidateState = VALIDATE_NOT_CHECKED; - emit validateFailed(tr("unknown error")); + emit validateFailed(tr("Unknown error.")); } } diff --git a/src/settings.cpp b/src/settings.cpp index 64a39e12..7b4b3a67 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -92,8 +92,6 @@ Settings::Settings(const QSettings &settingsSource) } else { s_Instance = this; } - - qRegisterMetaType<Settings::NexusUpdateStrategy>("NexusUpdateStrategy"); } @@ -416,11 +414,6 @@ int Settings::crashDumpsMax() const return m_Settings.value("Settings/crash_dumps_max", 5).toInt(); } -Settings::NexusUpdateStrategy Settings::nexusUpdateStrategy() const -{ - return static_cast<NexusUpdateStrategy>(m_Settings.value("Settings/nexus_update_strategy", std::rand() / ((RAND_MAX + 1u) / 2)).toInt()); -} - QColor Settings::modlistOverwrittenLooseColor() const { return m_Settings.value("Settings/overwrittenLooseFilesColor", QColor(0, 255, 0, 64)).value<QColor>(); @@ -1042,10 +1035,7 @@ Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog) , m_preferredServersList( dialog.findChild<QListWidget *>("preferredServersList")) , m_endorsementBox(dialog.findChild<QCheckBox *>("endorsementBox")) - , m_updateStrategyBox(dialog.findChild<QCheckBox *>("updateStrategy")) { - qRegisterMetaType<Settings::NexusUpdateStrategy>("NexusUpdateStrategy"); - if (!deObfuscate("APIKEY").isEmpty()) { m_nexusConnect->setText("Nexus API Key Stored"); m_nexusConnect->setDisabled(true); @@ -1054,8 +1044,6 @@ Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog) m_offlineBox->setChecked(parent->offlineMode()); m_proxyBox->setChecked(parent->useProxy()); m_endorsementBox->setChecked(parent->endorsementIntegration()); - if (parent->nexusUpdateStrategy() == Settings::NexusUpdateStrategy::Flexible) - m_updateStrategyBox->setChecked(true); // display server preferences @@ -1101,8 +1089,6 @@ void Settings::NexusTab::update() m_Settings.setValue("Settings/offline_mode", m_offlineBox->isChecked()); m_Settings.setValue("Settings/use_proxy", m_proxyBox->isChecked()); m_Settings.setValue("Settings/endorsement_integration", m_endorsementBox->isChecked()); - m_Settings.setValue("Settings/nexus_update_strategy", m_updateStrategyBox->isChecked() - ? Settings::NexusUpdateStrategy::Flexible : Settings::NexusUpdateStrategy::Rigid); // store server preference m_Settings.beginGroup("Servers"); diff --git a/src/settings.h b/src/settings.h index ddb7cac0..2cd3f0b6 100644 --- a/src/settings.h +++ b/src/settings.h @@ -65,14 +65,6 @@ class Settings : public QObject { Q_OBJECT - Q_ENUMS(NexusUpdateStrategy) - -public: - - enum NexusUpdateStrategy { - Rigid, - Flexible - }; public: @@ -239,11 +231,6 @@ public: */ int crashDumpsMax() const; - /** - * @return the configured Nexus update strategy - */ - NexusUpdateStrategy nexusUpdateStrategy() const; - QColor modlistOverwrittenLooseColor() const; QColor modlistOverwritingLooseColor() const; @@ -499,7 +486,6 @@ private: QListWidget *m_knownServersList; QListWidget *m_preferredServersList; QCheckBox *m_endorsementBox; - QCheckBox *m_updateStrategyBox; }; /** Display/store the configuration in the 'steam' tab of the settings dialogue */ @@ -578,6 +564,4 @@ private: }; -Q_DECLARE_METATYPE(Settings::NexusUpdateStrategy) - #endif // SETTINGS_H diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index cfbcf429..127c94c7 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -578,16 +578,6 @@ p, li { white-space: pre-wrap; } </property> </widget> </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="updateStrategy"> - <property name="toolTip"> - <string><html><head/><body><p>Rather than a global <span style=" font-weight:600;">1 day</span> cache, update caches will expire at different rates depending on how recently a mod has been updated on Nexus.</p><p><br/></p><p>Less than a month: <span style=" font-style:italic;">2 hours</span></p><p>Less than three months: <span style=" font-style:italic;">4 hours</span></p><p>Less than six months: <span style=" font-style:italic;">6 hours</span></p><p>Less than one year: <span style=" font-style:italic;">12 hours</span></p><p>More than one year: <span style=" font-style:italic;">1 day</span></p></body></html></string> - </property> - <property name="text"> - <string>Use dynamic update timeouts</string> - </property> - </widget> - </item> </layout> </item> <item> |
