aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--application/CMakeLists.txt2
-rw-r--r--application/MainWindow.cpp3
-rw-r--r--application/MultiMC.cpp34
-rw-r--r--application/MultiMC.h5
-rw-r--r--application/main.cpp1
-rw-r--r--application/pages/VersionPage.cpp10
-rw-r--r--application/pages/global/AccountListPage.h2
-rw-r--r--application/resources/multimc/150x150/hourglass.pngbin0 -> 11831 bytes
-rw-r--r--application/resources/multimc/16x16/hourglass.pngbin0 -> 705 bytes
-rw-r--r--application/resources/multimc/22x22/hourglass.pngbin0 -> 1037 bytes
-rw-r--r--application/resources/multimc/32x32/hourglass.pngbin0 -> 1574 bytes
-rw-r--r--application/resources/multimc/48x48/hourglass.pngbin0 -> 2679 bytes
-rw-r--r--application/resources/multimc/index.theme3
-rw-r--r--application/resources/multimc/multimc.qrc7
-rw-r--r--application/widgets/ProgressWidget.cpp74
-rw-r--r--application/widgets/ProgressWidget.h32
-rw-r--r--logic/AbstractCommonModel.cpp133
-rw-r--r--logic/AbstractCommonModel.h462
-rw-r--r--logic/BaseConfigObject.cpp119
-rw-r--r--logic/BaseConfigObject.h50
-rw-r--r--logic/CMakeLists.txt30
-rw-r--r--logic/Env.cpp3
-rw-r--r--logic/Exception.h41
-rw-r--r--logic/FileSystem.cpp56
-rw-r--r--logic/FileSystem.h13
-rw-r--r--logic/Json.cpp278
-rw-r--r--logic/Json.h239
-rw-r--r--logic/MMCError.h25
-rw-r--r--logic/MMCJson.cpp142
-rw-r--r--logic/MMCJson.h101
-rw-r--r--logic/QObjectPtr.h5
-rw-r--r--logic/forge/ForgeInstaller.cpp3
-rw-r--r--logic/liteloader/LiteLoaderInstaller.cpp3
-rw-r--r--logic/liteloader/LiteLoaderVersionList.cpp4
-rw-r--r--logic/minecraft/JarMod.cpp4
-rw-r--r--logic/minecraft/MinecraftProfile.cpp7
-rw-r--r--logic/minecraft/MinecraftVersionList.cpp31
-rw-r--r--logic/minecraft/OneSixInstance.cpp3
-rw-r--r--logic/minecraft/OneSixProfileStrategy.cpp4
-rw-r--r--logic/minecraft/OneSixUpdate.cpp3
-rw-r--r--logic/minecraft/ParseUtils.cpp1
-rw-r--r--logic/minecraft/ProfileUtils.cpp10
-rw-r--r--logic/minecraft/RawLibrary.cpp6
-rw-r--r--logic/minecraft/VersionBuildError.h8
-rw-r--r--logic/minecraft/VersionFile.cpp4
-rw-r--r--logic/minecraft/VersionFile.h3
-rw-r--r--logic/net/CacheDownload.h29
-rw-r--r--logic/resources/IconResourceHandler.cpp60
-rw-r--r--logic/resources/IconResourceHandler.h22
-rw-r--r--logic/resources/Resource.cpp121
-rw-r--r--logic/resources/Resource.h116
-rw-r--r--logic/resources/ResourceHandler.cpp28
-rw-r--r--logic/resources/ResourceHandler.h33
-rw-r--r--logic/resources/ResourceObserver.cpp55
-rw-r--r--logic/resources/ResourceObserver.h67
-rw-r--r--logic/resources/ResourceProxyModel.cpp103
-rw-r--r--logic/resources/ResourceProxyModel.h36
-rw-r--r--logic/resources/WebResourceHandler.cpp67
-rw-r--r--logic/resources/WebResourceHandler.h23
-rw-r--r--logic/tasks/StandardTask.cpp120
-rw-r--r--logic/tasks/StandardTask.h43
-rw-r--r--logic/tasks/Task.cpp1
-rw-r--r--logic/tasks/Task.h2
-rw-r--r--tests/tst_Resource.cpp101
65 files changed, 2661 insertions, 333 deletions
diff --git a/.travis.yml b/.travis.yml
index ad0bdee5..9ed7a045 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,6 @@ before_script:
- cd build
- cmake -DCMAKE_PREFIX_PATH=/opt/qt53/lib/cmake ..
script:
- - make -j4
- - make test ARGS="-V"
+ - make -j4 && make test ARGS="-V"
notifications:
email: false
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt
index d7cb5777..d3962819 100644
--- a/application/CMakeLists.txt
+++ b/application/CMakeLists.txt
@@ -251,6 +251,8 @@ SET(MULTIMC_SOURCES
widgets/ServerStatus.h
widgets/VersionListView.cpp
widgets/VersionListView.h
+ widgets/ProgressWidget.h
+ widgets/ProgressWidget.cpp
# GUI - instance group view
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 9ff120bd..99c94bf8 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -383,6 +383,7 @@ namespace Ui {
#include "JavaCommon.h"
#include "InstancePageProvider.h"
#include "minecraft/SkinUtils.h"
+#include "resources/Resource.h"
//#include "minecraft/LegacyInstance.h"
@@ -1758,7 +1759,7 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
this->hide();
console = new ConsoleWindow(proc);
- connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
+ connect(console, &ConsoleWindow::isClosing, this, &MainWindow::instanceEnded);
proc->setHeader("MultiMC version: " + BuildConfig.printableVersionString() + "\n\n");
proc->arm();
diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp
index 39cc8503..2c6b387c 100644
--- a/application/MultiMC.cpp
+++ b/application/MultiMC.cpp
@@ -40,6 +40,8 @@
#include "settings/Setting.h"
#include "trans/TranslationDownloader.h"
+#include "resources/Resource.h"
+#include "resources/IconResourceHandler.h"
#include "ftb/FTBPlugin.h"
@@ -331,6 +333,37 @@ void MultiMC::initIcons()
{
ENV.m_icons->directoryChanged(value.toString());
});
+
+ Resource::registerTransformer([](const QVariantMap &map) -> QIcon
+ {
+ QIcon icon;
+ for (auto it = map.constBegin(); it != map.constEnd(); ++it)
+ {
+ icon.addFile(it.key(), QSize(it.value().toInt(), it.value().toInt()));
+ }
+ return icon;
+ });
+ Resource::registerTransformer([](const QVariantMap &map) -> QPixmap
+ {
+ QVariantList sizes = map.values();
+ if (sizes.isEmpty())
+ {
+ return QPixmap();
+ }
+ std::sort(sizes.begin(), sizes.end());
+ if (sizes.last().toInt() != -1) // only scalable available
+ {
+ return QPixmap(map.key(sizes.last()));
+ }
+ else
+ {
+ return QPixmap();
+ }
+ });
+ Resource::registerTransformer([](const QByteArray &data) -> QPixmap
+ { return QPixmap::fromImage(QImage::fromData(data)); });
+ Resource::registerTransformer([](const QByteArray &data) -> QIcon
+ { return QIcon(QPixmap::fromImage(QImage::fromData(data))); });
}
@@ -610,6 +643,7 @@ void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags)
void MultiMC::setIconTheme(const QString& name)
{
XdgIcon::setThemeName(name);
+ IconResourceHandler::setTheme(name);
}
QIcon MultiMC::getThemedIcon(const QString& name)
diff --git a/application/MultiMC.h b/application/MultiMC.h
index 8215e4ad..e4a54115 100644
--- a/application/MultiMC.h
+++ b/application/MultiMC.h
@@ -146,13 +146,10 @@ private slots:
private:
void initLogger();
-
void initIcons();
-
void initGlobalSettings(bool test_mode);
-
void initTranslations();
- void initSSL();
+ void initSSL();
private:
friend class UpdateCheckerTest;
diff --git a/application/main.cpp b/application/main.cpp
index 111a61ac..12c97f09 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -13,7 +13,6 @@ int main_gui(MultiMC &app)
mainWin.checkInstancePathForProblems();
return app.exec();
}
-
int main(int argc, char *argv[])
{
// initialize Qt
diff --git a/application/pages/VersionPage.cpp b/application/pages/VersionPage.cpp
index cbb5c107..efc0b446 100644
--- a/application/pages/VersionPage.cpp
+++ b/application/pages/VersionPage.cpp
@@ -47,7 +47,7 @@
#include <minecraft/MinecraftVersion.h>
#include <minecraft/MinecraftVersionList.h>
#include "icons/IconList.h"
-
+#include "Exception.h"
QIcon VersionPage::icon() const
{
@@ -118,7 +118,7 @@ bool VersionPage::reloadMinecraftProfile()
m_inst->reloadProfile();
return true;
}
- catch (MMCError &e)
+ catch (Exception &e)
{
QMessageBox::critical(this, tr("Error"), e.cause());
return false;
@@ -199,7 +199,7 @@ void VersionPage::on_resetOrderBtn_clicked()
{
m_version->resetOrder();
}
- catch (MMCError &e)
+ catch (Exception &e)
{
QMessageBox::critical(this, tr("Error"), e.cause());
}
@@ -212,7 +212,7 @@ void VersionPage::on_moveUpBtn_clicked()
{
m_version->move(currentRow(), MinecraftProfile::MoveUp);
}
- catch (MMCError &e)
+ catch (Exception &e)
{
QMessageBox::critical(this, tr("Error"), e.cause());
}
@@ -225,7 +225,7 @@ void VersionPage::on_moveDownBtn_clicked()
{
m_version->move(currentRow(), MinecraftProfile::MoveDown);
}
- catch (MMCError &e)
+ catch (Exception &e)
{
QMessageBox::critical(this, tr("Error"), e.cause());
}
diff --git a/application/pages/global/AccountListPage.h b/application/pages/global/AccountListPage.h
index bfadc1bd..7803e044 100644
--- a/application/pages/global/AccountListPage.h
+++ b/application/pages/global/AccountListPage.h
@@ -21,7 +21,7 @@
#include "pages/BasePage.h"
#include "auth/MojangAccountList.h"
-#include <MultiMC.h>
+#include "MultiMC.h"
namespace Ui
{
diff --git a/application/resources/multimc/150x150/hourglass.png b/application/resources/multimc/150x150/hourglass.png
new file mode 100644
index 00000000..f2623d1e
--- /dev/null
+++ b/application/resources/multimc/150x150/hourglass.png
Binary files differ
diff --git a/application/resources/multimc/16x16/hourglass.png b/application/resources/multimc/16x16/hourglass.png
new file mode 100644
index 00000000..ab36234b
--- /dev/null
+++ b/application/resources/multimc/16x16/hourglass.png
Binary files differ
diff --git a/application/resources/multimc/22x22/hourglass.png b/application/resources/multimc/22x22/hourglass.png
new file mode 100644
index 00000000..8cb343ac
--- /dev/null
+++ b/application/resources/multimc/22x22/hourglass.png
Binary files differ
diff --git a/application/resources/multimc/32x32/hourglass.png b/application/resources/multimc/32x32/hourglass.png
new file mode 100644
index 00000000..a558ec99
--- /dev/null
+++ b/application/resources/multimc/32x32/hourglass.png
Binary files differ
diff --git a/application/resources/multimc/48x48/hourglass.png b/application/resources/multimc/48x48/hourglass.png
new file mode 100644
index 00000000..8f10ab7a
--- /dev/null
+++ b/application/resources/multimc/48x48/hourglass.png
Binary files differ
diff --git a/application/resources/multimc/index.theme b/application/resources/multimc/index.theme
index 5f7d3f3f..a21fea2c 100644
--- a/application/resources/multimc/index.theme
+++ b/application/resources/multimc/index.theme
@@ -35,6 +35,9 @@ Size=64
[256x256]
Size=256
+[150x150]
+Size=150
+
[scalable]
Size=48
Type=Scalable
diff --git a/application/resources/multimc/multimc.qrc b/application/resources/multimc/multimc.qrc
index 4ced586a..31a7b44f 100644
--- a/application/resources/multimc/multimc.qrc
+++ b/application/resources/multimc/multimc.qrc
@@ -207,6 +207,13 @@
<file>48x48/log.png</file>
<file>64x64/log.png</file>
+ <!-- Hour glass, CC-BY, http://findicons.com/icon/84653/hourglass?id=360551 -->
+ <file>16x16/hourglass.png</file>
+ <file>22x22/hourglass.png</file>
+ <file>32x32/hourglass.png</file>
+ <file>48x48/hourglass.png</file>
+ <file>150x150/hourglass.png</file>
+
<!-- placeholder when loading screenshot images -->
<file>scalable/screenshot-placeholder.svg</file>
</qresource>
diff --git a/application/widgets/ProgressWidget.cpp b/application/widgets/ProgressWidget.cpp
new file mode 100644
index 00000000..7b51eca0
--- /dev/null
+++ b/application/widgets/ProgressWidget.cpp
@@ -0,0 +1,74 @@
+// Licensed under the Apache-2.0 license. See README.md for details.
+
+#include "ProgressWidget.h"
+
+#include <QProgressBar>
+#include <QLabel>
+#include <QVBoxLayout>
+#include <QEventLoop>
+
+#include "tasks/Task.h"
+
+ProgressWidget::ProgressWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ m_label = new QLabel(this);
+ m_label->setWordWrap(true);
+ m_bar = new QProgressBar(this);
+ m_bar->setMinimum(0);
+ m_bar->setMaximum(100);
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(m_label);
+ layout->addWidget(m_bar);
+ layout->addStretch();
+ setLayout(layout);
+}
+
+void ProgressWidget::start(std::shared_ptr<Task> task)
+{
+ if (m_task)
+ {
+ disconnect(m_task.get(), 0, this, 0);
+ }
+ m_task = task;
+ connect(m_task.get(), &Task::finished, this, &ProgressWidget::handleTaskFinish);
+ connect(m_task.get(), &Task::status, this, &ProgressWidget::handleTaskStatus);
+ connect(m_task.get(), &Task::progress, this, &ProgressWidget::handleTaskProgress);
+ connect(m_task.get(), &Task::destroyed, this, &ProgressWidget::taskDestroyed);
+ if (!m_task->isRunning())
+ {
+ QMetaObject::invokeMethod(m_task.get(), "start", Qt::QueuedConnection);
+ }
+}
+bool ProgressWidget::exec(std::shared_ptr<Task> task)
+{
+ QEventLoop loop;
+ connect(task.get(), &Task::finished, &loop, &QEventLoop::quit);
+ start(task);
+ if (task->isRunning())
+ {
+ loop.exec();
+ }
+ return task->successful();
+}
+
+void ProgressWidget::handleTaskFinish()
+{
+ if (!m_task->successful())
+ {
+ m_label->setText(m_task->failReason());
+ }
+}
+void ProgressWidget::handleTaskStatus(const QString &status)
+{
+ m_label->setText(status);
+}
+void ProgressWidget::handleTaskProgress(qint64 current, qint64 total)
+{
+ m_bar->setMaximum(total);
+ m_bar->setValue(current);
+}
+void ProgressWidget::taskDestroyed()
+{
+ m_task = nullptr;
+}
diff --git a/application/widgets/ProgressWidget.h b/application/widgets/ProgressWidget.h
new file mode 100644
index 00000000..08d8a157
--- /dev/null
+++ b/application/widgets/ProgressWidget.h
@@ -0,0 +1,32 @@
+// Licensed under the Apache-2.0 license. See README.md for details.
+
+#pragma once
+
+#include <QWidget>
+#include <memory>
+
+class Task;
+class QProgressBar;
+class QLabel;
+
+class ProgressWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit ProgressWidget(QWidget *parent = nullptr);
+
+public slots:
+ void start(std::shared_ptr<Task> task);
+ bool exec(std::shared_ptr<Task> task);
+
+private slots:
+ void handleTaskFinish();
+ void handleTaskStatus(const QString &status);
+ void handleTaskProgress(qint64 current, qint64 total);
+ void taskDestroyed();
+
+private:
+ QLabel *m_label;
+ QProgressBar *m_bar;
+ std::shared_ptr<Task> m_task;
+};
diff --git a/logic/AbstractCommonModel.cpp b/logic/AbstractCommonModel.cpp
new file mode 100644
index 00000000..71d75829
--- /dev/null
+++ b/logic/AbstractCommonModel.cpp
@@ -0,0 +1,133 @@
+/* Copyright 2015 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AbstractCommonModel.h"
+
+BaseAbstractCommonModel::BaseAbstractCommonModel(const Qt::Orientation orientation, QObject *parent)
+ : QAbstractListModel(parent), m_orientation(orientation)
+{
+}
+
+int BaseAbstractCommonModel::rowCount(const QModelIndex &parent) const
+{
+ return m_orientation == Qt::Horizontal ? entryCount() : size();
+}
+int BaseAbstractCommonModel::columnCount(const QModelIndex &parent) const
+{
+ return m_orientation == Qt::Horizontal ? size() : entryCount();
+}
+QVariant BaseAbstractCommonModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ {
+ return QVariant();
+ }
+ const int i = m_orientation == Qt::Horizontal ? index.column() : index.row();
+ const int entry = m_orientation == Qt::Horizontal ? index.row() : index.column();
+ return formatData(i, role, get(i, entry, role));
+}
+QVariant BaseAbstractCommonModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation != m_orientation && role == Qt::DisplayRole)
+ {
+ return entryTitle(section);
+ }
+ else
+ {
+ return QVariant();
+ }
+}
+bool BaseAbstractCommonModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int i = m_orientation == Qt::Horizontal ? index.column() : index.row();
+ const int entry = m_orientation == Qt::Horizontal ? index.row() : index.column();
+ const bool result = set(i, entry, role, sanetizeData(i, role, value));
+ if (result)
+ {
+ emit dataChanged(index, index, QVector<int>() << role);
+ }
+ return result;
+}
+Qt::ItemFlags BaseAbstractCommonModel::flags(const QModelIndex &index) const
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ {
+ return Qt::NoItemFlags;
+ }
+
+ const int entry = m_orientation == Qt::Horizontal ? index.row() : index.column();
+ if (canSet(entry))
+ {
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ }
+ else
+ {
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+}
+
+void BaseAbstractCommonModel::notifyAboutToAddObject(const int at)
+{
+ if (m_orientation == Qt::Horizontal)
+ {
+ beginInsertColumns(QModelIndex(), at, at);
+ }
+ else
+ {
+ beginInsertRows(QModelIndex(), at, at);
+ }
+}
+void BaseAbstractCommonModel::notifyObjectAdded()
+{
+ if (m_orientation == Qt::Horizontal)
+ {
+ endInsertColumns();
+ }
+ else
+ {
+ endInsertRows();
+ }
+}
+void BaseAbstractCommonModel::notifyAboutToRemoveObject(const int at)
+{
+ if (m_orientation == Qt::Horizontal)
+ {
+ beginRemoveColumns(QModelIndex(), at, at);
+ }
+ else
+ {
+ beginRemoveRows(QModelIndex(), at, at);
+ }
+}
+void BaseAbstractCommonModel::notifyObjectRemoved()
+{
+ if (m_orientation == Qt::Horizontal)
+ {
+ endRemoveColumns();
+ }
+ else
+ {
+ endRemoveRows();
+ }
+}
+
+void BaseAbstractCommonModel::notifyBeginReset()
+{
+ beginResetModel();
+}
+void BaseAbstractCommonModel::notifyEndReset()
+{
+ endResetModel();
+}
diff --git a/logic/AbstractCommonModel.h b/logic/AbstractCommonModel.h
new file mode 100644
index 00000000..31b86a23
--- /dev/null
+++ b/logic/AbstractCommonModel.h
@@ -0,0 +1,462 @@
+/* Copyright 2015 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QAbstractListModel>
+#include <type_traits>
+#include <functional>
+#include <memory>
+
+class BaseAbstractCommonModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ explicit BaseAbstractCommonModel(const Qt::Orientation orientation, QObject *parent = nullptr);
+
+ // begin QAbstractItemModel interface
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ // end QAbstractItemModel interface
+
+ virtual int size() const = 0;
+ virtual int entryCount() const = 0;
+
+ virtual QVariant formatData(const int index, int role, const QVariant &data) const { return data; }
+ virtual QVariant sanetizeData(const int index, int role, const QVariant &data) const { return data; }
+
+protected:
+ virtual QVariant get(const int index, const int entry, const int role) const = 0;
+ virtual bool set(const int index, const int entry, const int role, const QVariant &value) = 0;
+ virtual bool canSet(const int entry) const = 0;
+ virtual QString entryTitle(const int entry) const = 0;
+
+ void notifyAboutToAddObject(const int at);
+ void notifyObjectAdded();
+ void notifyAboutToRemoveObject(const int at);
+ void notifyObjectRemoved();
+ void notifyBeginReset();
+ void notifyEndReset();
+
+ const Qt::Orientation m_orientation;
+};
+
+template<typename Object>
+class AbstractCommonModel : public BaseAbstractCommonModel
+{
+public:
+ explicit AbstractCommonModel(const Qt::Orientation orientation)
+ : BaseAbstractCommonModel(orientation) {}
+ virtual ~AbstractCommonModel() {}
+
+ int size() const override { return m_objects.size(); }
+ int entryCount() const override { return m_entries.size(); }
+
+ void append(const Object &object)
+ {
+ notifyAboutToAddObject(size());
+ m_objects.append(object);
+ notifyObjectAdded();
+ }
+ void prepend(const Object &object)
+ {
+ notifyAboutToAddObject(0);
+ m_objects.prepend(object);
+ notifyObjectAdded();