diff options
| author | Tannin <devnull@localhost> | 2014-01-16 20:43:42 +0100 |
|---|---|---|
| committer | Tannin <devnull@localhost> | 2014-01-16 20:43:42 +0100 |
| commit | 40d20ab294ad7afd4b5747b306e45d0f8712a386 (patch) | |
| tree | ca97a4b4c404fc426e3239b0d0262624cca6c65d | |
| parent | 6ed82866b07414e91dfe0c47ee5f580bfd4fe479 (diff) | |
- added an about dialog
- updated json library
| -rw-r--r-- | src/aboutdialog.cpp | 82 | ||||
| -rw-r--r-- | src/aboutdialog.h | 69 | ||||
| -rw-r--r-- | src/aboutdialog.ui | 295 | ||||
| -rw-r--r-- | src/downloadmanager.cpp | 1 | ||||
| -rw-r--r-- | src/json.cpp | 1110 | ||||
| -rw-r--r-- | src/json.h | 298 | ||||
| -rw-r--r-- | src/logbuffer.cpp | 1 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 9 | ||||
| -rw-r--r-- | src/mainwindow.h | 1 | ||||
| -rw-r--r-- | src/modinfodialog.cpp | 3 | ||||
| -rw-r--r-- | src/modlist.cpp | 2 | ||||
| -rw-r--r-- | src/nexusinterface.cpp | 5 | ||||
| -rw-r--r-- | src/organizer.pro | 16 | ||||
| -rw-r--r-- | src/resources/emblem-favorite - 64.png | bin | 0 -> 3710 bytes |
14 files changed, 1087 insertions, 805 deletions
diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp new file mode 100644 index 00000000..94e4e54c --- /dev/null +++ b/src/aboutdialog.cpp @@ -0,0 +1,82 @@ +/*
+Copyright (C) 2014 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 <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "aboutdialog.h"
+#include "ui_aboutdialog.h"
+#include <utility.h>
+
+
+AboutDialog::AboutDialog(const QString &version, QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::AboutDialog)
+{
+ ui->setupUi(this);
+
+ m_LicenseFiles[LICENSE_LGPL3] = "lgpl-3.0.txt";
+ m_LicenseFiles[LICENSE_GPL3] = "gpl-3.0.txt";
+ m_LicenseFiles[LICENSE_BSD3] = "bsd3.txt";
+ m_LicenseFiles[LICENSE_BOOST] = "boost.txt";
+ m_LicenseFiles[LICENSE_CCBY3] = "by-sa3.txt";
+ m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
+
+ addLicense("Qt 4.8.5", LICENSE_LGPL3);
+ addLicense("Qt Json", LICENSE_GPL3);
+ addLicense("Boost Library", LICENSE_BOOST);
+ addLicense("Tango Icon Theme", LICENSE_NONE);
+ addLicense("RRZE Icon Set", LICENSE_CCBY3);
+ addLicense("7-zip", LICENSE_LGPL3);
+ addLicense("ZLib", LICENSE_ZLIB);
+ addLicense("NIF File Format Library", LICENSE_BSD3);
+
+ ui->nameLabel->setText(QString("<span style=\"font-size:12pt; font-weight:600;\">%1 %2</span>").arg(ui->nameLabel->text()).arg(version));
+#ifdef HGID
+ ui->revisionLabel->setText(ui->revisionLabel->text() + " " + HGID);
+#else
+ ui->revisionLabel->setText(ui->revisionLabel->text() + " unknown");
+#endif
+}
+
+
+AboutDialog::~AboutDialog()
+{
+ delete ui;
+}
+
+
+void AboutDialog::addLicense(const QString &name, Licenses license)
+{
+ QListWidgetItem *item = new QListWidgetItem(name);
+ item->setData(Qt::UserRole, license);
+ ui->creditsList->addItem(item);
+}
+
+
+void AboutDialog::on_creditsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem*)
+{
+ auto iter = m_LicenseFiles.find(current->data(Qt::UserRole).toInt());
+ if (iter != m_LicenseFiles.end()) {
+ QString filePath = qApp->applicationDirPath() + "/license/" + iter->second;
+qDebug("%s", qPrintable(filePath));
+ QString text = MOBase::readFileText(filePath);
+ ui->licenseText->setText(text);
+ } else {
+ ui->licenseText->setText(tr("No license"));
+ }
+}
diff --git a/src/aboutdialog.h b/src/aboutdialog.h new file mode 100644 index 00000000..9c0901a8 --- /dev/null +++ b/src/aboutdialog.h @@ -0,0 +1,69 @@ +#ifndef ABOUTDIALOG_H
+/*
+Copyright (C) 2014 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 <http://www.gnu.org/licenses/>.
+*/
+
+
+#define ABOUTDIALOG_H
+
+#include <QDialog>
+#include <QListWidgetItem>
+#include <map>
+#include <vector>
+#include <utility>
+
+namespace Ui {
+ class AboutDialog;
+}
+
+class AboutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit AboutDialog(const QString &version, QWidget *parent = 0);
+ ~AboutDialog();
+
+private:
+
+ enum Licenses {
+ LICENSE_NONE,
+ LICENSE_LGPL3,
+ LICENSE_GPL3,
+ LICENSE_BSD3,
+ LICENSE_BOOST,
+ LICENSE_CCBY3,
+ LICENSE_ZLIB
+ };
+
+private:
+
+ void addLicense(const QString &name, Licenses license);
+
+private slots:
+ void on_creditsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
+
+private:
+
+ Ui::AboutDialog *ui;
+
+ std::map<int, QString> m_LicenseFiles;
+
+};
+
+#endif // ABOUTDIALOG_H
diff --git a/src/aboutdialog.ui b/src/aboutdialog.ui new file mode 100644 index 00000000..985700db --- /dev/null +++ b/src/aboutdialog.ui @@ -0,0 +1,295 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDialog</class>
+ <widget class="QDialog" name="AboutDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>508</width>
+ <height>335</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>About</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QLabel" name="iconLabel">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="resources.qrc">:/MO/gui/mo_icon.ico</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="about">
+ <attribute name="title">
+ <string>About</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="nameLabel">
+ <property name="text">
+ <string notr="true">Mod Organizer</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="revisionLabel">
+ <property name="text">
+ <string>Revision:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string notr="true">Copyright 2011-2014 Sebastian Herbord</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string notr="true"><html><head/><body><p>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.</p><p>See the GNU General Public License for more details.</p></body></html></string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="software">
+ <attribute name="title">
+ <string>Used Software</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QListWidget" name="creditsList"/>
+ </item>
+ <item>
+ <widget class="QTextBrowser" name="licenseText"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="credits">
+ <attribute name="title">
+ <string>Credits</string>
+ </attribute>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Translators</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QListWidget" name="listWidget_2">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::NoSelection</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">pndrev (German)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">DaWul (Spanish)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Fiama (Spanish)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Alyndiar (French)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Jlkawaii (French)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Rigoletto (French)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Scythe1912 (Chinese)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">yc0620shen (Chinese)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">miraclefreak (Czech)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">tokcdk (Russian)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Others</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QListWidget" name="listWidget">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::NoSelection</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string notr="true">blacksol</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">DoubleYou</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">deathneko11</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Bridger</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">GSDFan</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Uhuru</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">Wolverine2710</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">z929669</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="resources.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AboutDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>460</x>
+ <y>313</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>253</x>
+ <y>167</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index fdc825f1..dd320f70 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -37,7 +37,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QCoreApplication> -using QtJson::Json; using namespace MOBase; diff --git a/src/json.cpp b/src/json.cpp index 7bfaed39..ca2d728f 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -1,588 +1,522 @@ -/* Copyright 2011 Eeli Reilin. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL EELI REILIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of Eeli Reilin.
- */
-
-/**
- * \file json.cpp
- */
-
-#include "json.h"
-#include <iostream>
-
-namespace QtJson
-{
-
-
-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;
-}
-
-/**
- * parse
- */
-QVariant Json::parse(const QString &json)
-{
- bool success = true;
- return Json::parse(json, success);
-}
-
-/**
- * parse
- */
-QVariant Json::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 = Json::parseValue(data, index, success);
-
- //Return the parsed value
- return value;
- }
- else
- {
- //Return the empty QVariant
- return QVariant();
- }
-}
-
-QByteArray Json::serialize(const QVariant &data)
-{
- bool success = true;
- return Json::serialize(data, success);
-}
-
-QByteArray Json::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::Map) // variant is a map?
- {
- const QVariantMap vmap = data.toMap();
- QMapIterator<QString, QVariant> it( vmap );
- str = "{ ";
- QList<QByteArray> pairs;
- while(it.hasNext())
- {
- it.next();
- QByteArray serializedValue = serialize(it.value());
- if(serializedValue.isNull())
- {
- success = false;
- break;
- }
- pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
- }
- str += join(pairs, ", ");
- str += " }";
- }
- 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?
- {
- str = QByteArray::number(data.toDouble());
- if(!str.contains(".") && ! str.contains("e"))
- {
- str += ".0";
- }
- }
- 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>())
- {
- str = sanitizeString(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();
- }
-}
-
-/**
- * parseValue
- */
-QVariant Json::parseValue(const QString &json, int &index, bool &success)
-{
- //Determine what kind of data we should parse by
- //checking out the upcoming token
- switch(Json::lookAhead(json, index))
- {
- case JsonTokenString:
- return Json::parseString(json, index, success);
- case JsonTokenNumber:
- return Json::parseNumber(json, index);
- case JsonTokenCurlyOpen:
- return Json::parseObject(json, index, success);
- case JsonTokenSquaredOpen:
- return Json::parseArray(json, index, success);
- case JsonTokenTrue:
- Json::nextToken(json, index);
- return QVariant(true);
- case JsonTokenFalse:
- Json::nextToken(json, index);
- return QVariant(false);
- case JsonTokenNull:
- Json::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
- */
-QVariant Json::parseObject(const QString &json, int &index, bool &success)
-{
- QVariantMap map;
- int token;
-
- //Get rid of the whitespace and increment index
- Json::nextToken(json, index);
-
- //Loop through all of the key/value pairs of the object
- bool done = false;
- while(!done)
- {
- //Get the upcoming token
- token = Json::lookAhead(json, index);
-
- if(token == JsonTokenNone)
- {
- success = false;
- return QVariantMap();
- }
- else if(token == JsonTokenComma)
- {
- Json::nextToken(json, index);
- }
- else if(token == JsonTokenCurlyClose)
- {
- Json::nextToken(json, index);
- return map;
- }
- else
- {
- //Parse the key/value pair's name
- QString name = Json::parseString(json, index, success).toString();
-
- if(!success)
- {
- return QVariantMap();
- }
-
- //Get the next token
- token = Json::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 = Json::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
- */
-QVariant Json::parseArray(const QString &json, int &index, bool &success)
-{
- QVariantList list;
-
- Json::nextToken(json, index);
-
- bool done = false;
- while(!done)
- {
- int token = Json::lookAhead(json, index);
-
- if(token == JsonTokenNone)
- {
- success = false;
- return QVariantList();
- }
- else if(token == JsonTokenComma)
- {
- Json::nextToken(json, index);
- }
- else if(token == JsonTokenSquaredClose)
- {
- Json::nextToken(json, index);
- break;
- }
- else
- {
- QVariant value = Json::parseValue(json, index, success);
-
- if(!success)
- {
- return QVariantList();
- }
-
- list.push_back(value);
- }
- }
-
- return QVariant(list);
-}
-
-/**
- * parseString
- */
-QVariant Json::parseString(const QString &json, int &index, bool &success)
-{
- QString s;
- QChar c;
-
- Json::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
- */
-QVariant Json::parseNumber(const QString &json, int &index)
-{
- Json::eatWhitespace(json, index);
-
- int lastIndex = Json::lastIndexOfNumber(json, index);
- int charLength = (lastIndex - index) + 1;
- QString numberStr;
-
- numberStr = json.mid(index, charLength);
-
- index = lastIndex + 1;
-
- if (numberStr.contains('.')) {
- return QVariant(numberStr.toDouble(NULL));
- } else if (numberStr.startsWith('-')) {
- return QVariant(numberStr.toLongLong(NULL));
- } else {
- return QVariant(numberStr.toULongLong(NULL));
- }
-}
-
-/**
- * lastIndexOfNumber
- */
-int Json::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
- */
-void Json::eatWhitespace(const QString &json, int &index)
-{
- for(; index < json.size(); index++)
- {
- if(QString(" \t\n\r").indexOf(json[index]) == -1)
- {
- break;
- }
- }
-}
-
-/**
- * lookAhead
- */
-int Json::lookAhead(const QString &json, int index)
-{
- int saveIndex = index;
- return Json::nextToken(json, saveIndex);
-}
-
-/**
- * nextToken
- */
-int Json::nextToken(const QString &json, int &index)
-{
- Json::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--;
-
- 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
+/** + * 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(NULL)); + } 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 @@ -1,204 +1,94 @@ -/* Copyright 2011 Eeli Reilin. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL EELI REILIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of Eeli Reilin.
- */
-
-/**
- * \file json.h
- */
-
-#ifndef JSON_H
-#define JSON_H
-
-#include <QVariant>
-#include <QString>
-
-namespace QtJson
-{
-
-/**
- * \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
-};
-
-/**
- * \class Json
- * \brief A JSON data parser
- *
- * Json parses a JSON data into a QVariant hierarchy.
- */
-class Json
-{
- public:
- /**
- * Parse a JSON string
- *
- * \param json The JSON data
- */
- static QVariant parse(const QString &json);
-
- /**
- * Parse a JSON string
- *
- * \param json The JSON data
- * \param success The success of the parsing
- */
- static QVariant parse(const QString &json, bool &success);
-
- /**
- * This method generates a textual JSON representation
- *
- * \param data The JSON data generated by the parser.
- * \param success The success of the serialization
- */
- static 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
- */
- static QByteArray serialize(const QVariant &data, bool &success);
-
- private:
- /**
- * Parses a value starting from index
- *
- * \param json The JSON data
- * \param index The start index
- * \param success The success of the parse process
- *
- * \return QVariant The parsed value
- */
- static QVariant parseValue(const QString &json, int &index,
- bool &success);
-
- /**
- * Parses an object starting from index
- *
- * \param json The JSON data
- * \param index The start index
- * \param success The success of the object parse
- *
- * \return QVariant The parsed object map
- */
- static QVariant parseObject(const QString &json, int &index,
- bool &success);
-
- /**
- * Parses an array starting from index
- *
- * \param json The JSON data
- * \param index The starting index
- * \param success The success of the array parse
- *
- * \return QVariant The parsed variant array
- */
- static QVariant parseArray(const QString &json, int &index,
- bool &success);
-
- /**
- * Parses a string starting from index
- *
- * \param json The JSON data
- * \param index The starting index
- * \param success The success of the string parse
- *
- * \return QVariant The parsed string
- */
- static QVariant parseString(const QString &json, int &index,
- bool &success);
-
- /**
- * Parses a number starting from index
- *
- * \param json The JSON data
- * \param index The starting index
- *
- * \return QVariant The parsed number
- */
- static QVariant parseNumber(const QString &json, int &index);
-
- /**
- * Get the last index of a number starting from index
- *
- * \param json The JSON data
- * \param index The starting index
- *
- * \return The last index of the number
- */
- static int lastIndexOfNumber(const QString &json, int index);
-
- /**
- * Skip unwanted whitespace symbols starting from index
- *
- * \param json The JSON data
- * \param index The start index
- */
- static void eatWhitespace(const QString &json, int &index);
-
- /**
- * Check what token lies ahead
- *
- * \param json The JSON data
- * \param index The starting index
- *
- * \return int The upcoming token
- */
- static int lookAhead(const QString &json, int index);
-
- /**
- * Get the next JSON token
- *
- * \param json The JSON data
- * \param index The starting index
- *
- * \return int The next JSON token
- */
- static int nextToken(const QString &json, int &index);
-};
-
-
-} //end namespace
-
-#endif //JSON_H
+/** + * 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/logbuffer.cpp b/src/logbuffer.cpp index 6f3f640f..4f72e551 100644 --- a/src/logbuffer.cpp +++ b/src/logbuffer.cpp @@ -120,6 +120,7 @@ char LogBuffer::msgTypeID(QtMsgType type) case QtWarningMsg: return 'W'; case QtCriticalMsg: return 'C'; case QtFatalMsg: return 'F'; + default: return '?'; } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 76bff3a0..14e27e76 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -56,6 +56,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "savetextasdialog.h" #include "problemsdialog.h" #include "previewdialog.h" +#include "aboutdialog.h" #include <gameinfo.h> #include <appconfig.h> #include <utility.h> @@ -547,6 +548,12 @@ bool MainWindow::checkForProblems() return false; } +void MainWindow::about() +{ + AboutDialog dialog(m_Updater.getVersion().displayString(), this); + dialog.exec(); +} + void MainWindow::createHelpWidget() { @@ -604,6 +611,8 @@ void MainWindow::createHelpWidget() } buttonMenu->addMenu(tutorialMenu); + buttonMenu->addAction(tr("About"), this, SLOT(about())); + buttonMenu->addAction(tr("About Qt"), qApp, SLOT(aboutQt())); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 59bee7bb..e7b3f7e1 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -527,6 +527,7 @@ private slots: void refreshSavesIfOpen(); void expandDataTreeItem(QTreeWidgetItem *item); + void about(); private slots: // ui slots // actions diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 7f221bdc..3657d48a 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -22,7 +22,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "report.h" #include "utility.h" -#include "json.h" #include "messagedialog.h" #include "bbcode.h" #include "questionboxmemory.h" @@ -41,8 +40,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QInputDialog> -using QtJson::Json; - using namespace MOBase; using namespace MOShared; diff --git a/src/modlist.cpp b/src/modlist.cpp index 7f09654d..e2cb7cf0 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -305,7 +305,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const return QString(); } } else if (column == COL_VERSION) { - QString text = tr("installed version: %1, newest version: %2").arg(modInfo->getVersion().displayString()).arg(modInfo->getNewestVersion().displayString()); + QString text = tr("installed version: \"%1\", newest version: \"%2\"").arg(modInfo->getVersion().displayString()).arg(modInfo->getNewestVersion().displayString()); if (modInfo->downgradeAvailable()) { text += "<br>" + tr("The newest version on Nexus seems to be older than the one you have installed. This could either mean the version you have has been withdrawn " "(i.e. due to a bug) or the author uses a non-standard versioning scheme and that newest version is actually newer. " diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index 309915aa..6b87822a 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -20,14 +20,13 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "nexusinterface.h" #include "nxmaccessmanager.h" #include "utility.h" -#include "json.h" +#include <json.h> #include "selectiondialog.h" #include <QApplication> #include <utility.h> #include <regex> #include <util.h> -using QtJson::Json; using namespace MOBase; using namespace MOShared; @@ -458,7 +457,7 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter) emit nxmRequestFailed(iter->m_ModID, iter->m_UserData, iter->m_ID, nexusError); } else { bool ok; - QVariant result = Json::parse(data, ok); + QVariant result = QtJson::parse(data, ok); if (result.isValid() && ok) { switch (iter->m_Type) { case NXMRequestInfo::TYPE_DESCRIPTION: { diff --git a/src/organizer.pro b/src/organizer.pro index dd745edb..fd72dea3 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -47,7 +47,6 @@ SOURCES += \ logbuffer.cpp \
lockeddialog.cpp \
loadmechanism.cpp \
- json.cpp \
installationmanager.cpp \
helper.cpp \
filedialogmemory.cpp \
@@ -80,7 +79,9 @@ SOURCES += \ ../esptk/subrecord.cpp \
noeditdelegate.cpp \
previewgenerator.cpp \
- previewdialog.cpp
+ previewdialog.cpp \
+ aboutdialog.cpp \
+ json.cpp
HEADERS += \
@@ -116,7 +117,6 @@ HEADERS += \ logbuffer.h \
lockeddialog.h \
loadmechanism.h \
- json.h \
installationmanager.h \
helper.h \
filedialogmemory.h \
@@ -150,7 +150,9 @@ HEADERS += \ ../esptk/espexceptions.h \
noeditdelegate.h \
previewgenerator.h \
- previewdialog.h
+ previewdialog.h \
+ aboutdialog.h \
+ json.h
FORMS += \
transfersavesdialog.ui \
@@ -180,7 +182,8 @@ FORMS += \ profileinputdialog.ui \
savetextasdialog.ui \
problemsdialog.ui \
- previewdialog.ui
+ previewdialog.ui \
+ aboutdialog.ui
INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk "$(BOOSTPATH)"
@@ -246,6 +249,9 @@ DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS NOMINMAX DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
#DEFINES += QMLJSDEBUGGER
+HGID = $$system(hg id -i)
+DEFINES += HGID=\\\"$${HGID}\\\"
+
SRCDIR = $$PWD
SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g
OUTDIR ~= s,/,$$QMAKE_DIR_SEP,g
diff --git a/src/resources/emblem-favorite - 64.png b/src/resources/emblem-favorite - 64.png Binary files differnew file mode 100644 index 00000000..97b507ed --- /dev/null +++ b/src/resources/emblem-favorite - 64.png |
