From 6892c11e9f287dcfb1e698f8f46233a01fb7abb6 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Sat, 7 Sep 2013 04:00:58 +0200 Subject: Move a good chunk of the singleton objects into a new QApplication subclass. --- AppSettings.cpp | 72 -------- AppSettings.h | 29 ---- AppVersion.cpp | 46 ----- AppVersion.h | 65 ------- CMakeLists.txt | 21 +-- MultiMC.cpp | 222 +++++++++++++++++++++++ MultiMC.h | 68 ++++++++ MultiMCVersion.h | 63 +++++++ depends/classparser/src/javautils.cpp | 1 - depends/settings/include/settingsobject.h | 10 +- depends/settings/src/settingsobject.cpp | 2 - gui/IconPickerDialog.cpp | 15 +- gui/aboutdialog.cpp | 8 +- gui/mainwindow.cpp | 52 +++--- gui/mainwindow.h | 1 - gui/newinstancedialog.cpp | 9 +- gui/settingsdialog.cpp | 8 +- logic/BaseInstance.cpp | 3 + logic/IconListModel.cpp | 280 ------------------------------ logic/IconListModel.h | 41 ----- logic/InstanceLauncher.cpp | 74 ++++++++ logic/InstanceLauncher.h | 28 +++ logic/LegacyInstance.cpp | 8 +- logic/LegacyUpdate.cpp | 14 +- logic/lists/IconList.cpp | 257 +++++++++++++++++++++++++++ logic/lists/IconList.h | 38 ++++ logic/lists/InstanceList.cpp | 11 +- logic/lists/LwjglVersionList.cpp | 6 +- logic/lists/MinecraftVersionList.cpp | 6 +- logic/net/DownloadJob.cpp | 6 +- logic/net/NetWorker.cpp | 30 ---- logic/net/NetWorker.h | 31 ---- logic/tasks/LoginTask.cpp | 8 +- main.cpp | 224 ------------------------ multimc_pragma.h | 49 ------ 35 files changed, 833 insertions(+), 973 deletions(-) delete mode 100644 AppSettings.cpp delete mode 100644 AppSettings.h delete mode 100644 AppVersion.cpp delete mode 100644 AppVersion.h create mode 100644 MultiMC.cpp create mode 100644 MultiMC.h create mode 100644 MultiMCVersion.h delete mode 100644 logic/IconListModel.cpp delete mode 100644 logic/IconListModel.h create mode 100644 logic/InstanceLauncher.cpp create mode 100644 logic/InstanceLauncher.h create mode 100644 logic/lists/IconList.cpp create mode 100644 logic/lists/IconList.h delete mode 100644 logic/net/NetWorker.cpp delete mode 100644 logic/net/NetWorker.h delete mode 100644 main.cpp delete mode 100644 multimc_pragma.h diff --git a/AppSettings.cpp b/AppSettings.cpp deleted file mode 100644 index 403af1dc..00000000 --- a/AppSettings.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright 2013 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 "AppSettings.h" - -#include - -#include -#include -//#include - -AppSettings::AppSettings(QObject *parent) : - INISettingsObject(QApplication::applicationDirPath() + "/multimc.cfg",parent) -{ - // Updates - registerSetting(new Setting("UseDevBuilds", false)); - registerSetting(new Setting("AutoUpdate", true)); - - // Folders - registerSetting(new Setting("InstanceDir", "instances")); - registerSetting(new Setting("CentralModsDir", "mods")); - registerSetting(new Setting("LWJGLDir", "lwjgl")); - - // Console - registerSetting(new Setting("ShowConsole", true)); - registerSetting(new Setting("AutoCloseConsole", true)); - - // Toolbar settings - registerSetting(new Setting("InstanceToolbarVisible", true)); - registerSetting(new Setting("InstanceToolbarPosition", QPoint())); - - // Console Colors -// registerSetting(new Setting("SysMessageColor", QColor(Qt::blue))); -// registerSetting(new Setting("StdOutColor", QColor(Qt::black))); -// registerSetting(new Setting("StdErrColor", QColor(Qt::red))); - - // Window Size - registerSetting(new Setting("LaunchMaximized", false)); - registerSetting(new Setting("MinecraftWinWidth", 854)); - registerSetting(new Setting("MinecraftWinHeight", 480)); - - // Auto login - registerSetting(new Setting("AutoLogin", false)); - - // Memory - registerSetting(new Setting("MinMemAlloc", 512)); - registerSetting(new Setting("MaxMemAlloc", 1024)); - registerSetting(new Setting("PermGen", 64)); - - // Java Settings - registerSetting(new Setting("JavaPath", "java")); - registerSetting(new Setting("JvmArgs", "")); - - // Custom Commands - registerSetting(new Setting("PreLaunchCommand", "")); - registerSetting(new Setting("PostExitCommand", "")); - - // The cat - registerSetting(new Setting("TheCat", false)); -} diff --git a/AppSettings.h b/AppSettings.h deleted file mode 100644 index d8f21de1..00000000 --- a/AppSettings.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2013 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 - -#include - -class AppSettings : public INISettingsObject -{ - Q_OBJECT -public: - explicit AppSettings(QObject *parent = 0); -}; - - diff --git a/AppVersion.cpp b/AppVersion.cpp deleted file mode 100644 index 86b00920..00000000 --- a/AppVersion.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright 2013 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 "AppVersion.h" - -#include "config.h" - -AppVersion AppVersion::current(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD); - -AppVersion::AppVersion(int major, int minor, int revision, int build, QObject *parent) : - QObject(parent) -{ - this->major = major; - this->minor = minor; - this->revision = revision; - this->build = build; -} - -AppVersion::AppVersion(const AppVersion& ver) -{ - this->major = ver.major; - this->minor = ver.minor; - this->revision = ver.revision; - this->build = ver.build; -} - -QString AppVersion::toString() const -{ - return QString("%1.%2.%3.%4").arg( - QString::number(major), - QString::number(minor), - QString::number(revision), - QString::number(build)); -} diff --git a/AppVersion.h b/AppVersion.h deleted file mode 100644 index 86f53950..00000000 --- a/AppVersion.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2013 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 - -/*! - * \brief The Version class represents a MultiMC version number. - */ -class AppVersion : public QObject -{ - Q_OBJECT -public: - explicit AppVersion(int major = 0, int minor = 0, int revision = 0, - int build = 0, QObject *parent = 0); - - AppVersion(const AppVersion& ver); - - /*! - * \brief Converts the Version to a string. - * \return The version number in string format (major.minor.revision.build). - */ - QString toString() const; - - /*! - * \brief The major version number. - * For MultiMC 5, this will always be 5. - */ - int major; - - /*! - * \brief The minor version number. - * This number is incremented when major features are added. - */ - int minor; - - /*! - * \brief The revision number. - * This number is incremented for bugfixes and small features. - */ - int revision; - - /*! - * \brief The build number. - * This number is automatically set by Jenkins. It is incremented every time - * a new build is run. - */ - int build; - - static AppVersion current; -}; - diff --git a/CMakeLists.txt b/CMakeLists.txt index f8f76c8c..27f8eaba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,9 +147,8 @@ ADD_DEFINITIONS(-DLIBGROUPVIEW_STATIC) ######## Headers ######## SET(MULTIMC_HEADERS -multimc_pragma.h -AppVersion.h -AppSettings.h +MultiMC.h +MultiMCVersion.h gui/mainwindow.h gui/settingsdialog.h @@ -181,9 +180,11 @@ logic/MinecraftProcess.h logic/Mod.h logic/ModList.h +# Basic instance launcher for starting from terminal +logic/InstanceLauncher.h + # network stuffs logic/net/DownloadJob.h -logic/net/NetWorker.h logic/net/HttpMetaCache.h # legacy instances @@ -208,7 +209,7 @@ logic/lists/InstanceList.h logic/lists/InstVersionList.h logic/lists/MinecraftVersionList.h logic/lists/LwjglVersionList.h -logic/IconListModel.h +logic/lists/IconList.h # Tasks logic/tasks/Task.h @@ -218,9 +219,7 @@ logic/tasks/LoginTask.h ######## Sources ######## SET(MULTIMC_SOURCES -main.cpp -AppVersion.cpp -AppSettings.cpp +MultiMC.cpp gui/mainwindow.cpp gui/settingsdialog.cpp @@ -249,8 +248,10 @@ logic/MinecraftProcess.cpp logic/Mod.cpp logic/ModList.cpp +# Basic instance launcher for starting from terminal +logic/InstanceLauncher.cpp + # network stuffs - to be moved into a depend lib ~_~ -logic/net/NetWorker.cpp logic/net/DownloadJob.cpp logic/net/HttpMetaCache.cpp @@ -274,7 +275,7 @@ logic/lists/InstanceList.cpp logic/lists/InstVersionList.cpp logic/lists/MinecraftVersionList.cpp logic/lists/LwjglVersionList.cpp -logic/IconListModel.cpp +logic/lists/IconList.cpp # Tasks logic/tasks/Task.cpp diff --git a/MultiMC.cpp b/MultiMC.cpp new file mode 100644 index 00000000..88eb3e62 --- /dev/null +++ b/MultiMC.cpp @@ -0,0 +1,222 @@ + +#include "MultiMC.h" +#include +#include +#include + +#include "gui/mainwindow.h" +#include "logic/lists/InstanceList.h" +#include "logic/lists/IconList.h" +#include "logic/InstanceLauncher.h" + + +#include "pathutils.h" +#include "cmdutils.h" +#include +#include + +#include "config.h" +using namespace Util::Commandline; + +MultiMC::MultiMC ( int& argc, char** argv ) + :QApplication ( argc, argv ) +{ + setOrganizationName("Forkk"); + setApplicationName("MultiMC 5"); + + // Print app header + std::cout << "MultiMC 5" << std::endl; + std::cout << "(c) 2013 MultiMC Contributors" << std::endl << std::endl; + + // Commandline parsing + QHash args; + { + Parser parser(FlagStyle::GNU, ArgumentStyle::SpaceAndEquals); + + // --help + parser.addSwitch("help"); + parser.addShortOpt("help", 'h'); + parser.addDocumentation("help", "display this help and exit."); + // --version + parser.addSwitch("version"); + parser.addShortOpt("version", 'V'); + parser.addDocumentation("version", "display program version and exit."); + // --dir + parser.addOption("dir", applicationDirPath()); + parser.addShortOpt("dir", 'd'); + parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of the binary location (use '.' for current)"); + // --update + parser.addOption("update"); + parser.addShortOpt("update", 'u'); + parser.addDocumentation("update", "replaces the given file with the running executable", ""); + // --quietupdate + parser.addSwitch("quietupdate"); + parser.addShortOpt("quietupdate", 'U'); + parser.addDocumentation("quietupdate", "doesn't restart MultiMC after installing updates"); + // --launch + parser.addOption("launch"); + parser.addShortOpt("launch", 'l'); + parser.addDocumentation("launch", "tries to launch the given instance", ""); + + // parse the arguments + try + { + args = parser.parse(arguments()); + } + catch(ParsingError e) + { + std::cerr << "CommandLineError: " << e.what() << std::endl; + std::cerr << "Try '%1 -h' to get help on MultiMC's command line parameters." << std::endl; + m_status = MultiMC::Failed; + return; + } + + // display help and exit + if (args["help"].toBool()) + { + std::cout << qPrintable(parser.compileHelp(arguments()[0])); + m_status = MultiMC::Succeeded; + return; + } + + // display version and exit + if (args["version"].toBool()) + { + std::cout << "Version " << VERSION_STR << std::endl; + std::cout << "Git " << GIT_COMMIT << std::endl; + std::cout << "Tag: " << JENKINS_BUILD_TAG << " " << (ARCH==x64?"x86_64":"x86") << std::endl; + m_status = MultiMC::Succeeded; + return; + } + + // update + // Note: cwd is always the current executable path! + if (!args["update"].isNull()) + { + std::cout << "Performing MultiMC update: " << qPrintable(args["update"].toString()) << std::endl; + QString cwd = QDir::currentPath(); + QDir::setCurrent(applicationDirPath()); + QFile file(applicationFilePath()); + file.copy(args["update"].toString()); + if(args["quietupdate"].toBool()) + { + m_status = MultiMC::Succeeded; + return; + } + QDir::setCurrent(cwd); + } + } + + // change directory + QDir::setCurrent(args["dir"].toString()); + + // load settings + initGlobalSettings(); + // and instances + m_instances = new InstanceList(m_settings->get("InstanceDir").toString(),this); + std::cout << "Loading Instances..." << std::endl; + m_instances->loadList(); + // network manager + m_qnam = new QNetworkAccessManager(this); + + // Register meta types. + qRegisterMetaType("LoginResponse"); + + // launch instance, if that's what should be done + if (!args["launch"].isNull()) + { + if(InstanceLauncher(args["launch"].toString()).launch()) + m_status = MultiMC::Succeeded; + else + m_status = MultiMC::Failed; + return; + } + m_status = MultiMC::Initialized; +} + +MultiMC::~MultiMC() +{ + delete m_settings; +} + +void MultiMC::initGlobalSettings() +{ + m_settings = new INISettingsObject(applicationDirPath() + "/multimc.cfg", this); + // Updates + m_settings->registerSetting(new Setting("UseDevBuilds", false)); + m_settings->registerSetting(new Setting("AutoUpdate", true)); + + // Folders + m_settings->registerSetting(new Setting("InstanceDir", "instances")); + m_settings->registerSetting(new Setting("CentralModsDir", "mods")); + m_settings->registerSetting(new Setting("LWJGLDir", "lwjgl")); + + // Console + m_settings->registerSetting(new Setting("ShowConsole", true)); + m_settings->registerSetting(new Setting("AutoCloseConsole", true)); + + // Toolbar settings + m_settings->registerSetting(new Setting("InstanceToolbarVisible", true)); + m_settings->registerSetting(new Setting("InstanceToolbarPosition", QPoint())); + + // Console Colors +// m_settings->registerSetting(new Setting("SysMessageColor", QColor(Qt::blue))); +// m_settings->registerSetting(new Setting("StdOutColor", QColor(Qt::black))); +// m_settings->registerSetting(new Setting("StdErrColor", QColor(Qt::red))); + + // Window Size + m_settings->registerSetting(new Setting("LaunchMaximized", false)); + m_settings->registerSetting(new Setting("MinecraftWinWidth", 854)); + m_settings->registerSetting(new Setting("MinecraftWinHeight", 480)); + + // Auto login + m_settings->registerSetting(new Setting("AutoLogin", false)); + + // Memory + m_settings->registerSetting(new Setting("MinMemAlloc", 512)); + m_settings->registerSetting(new Setting("MaxMemAlloc", 1024)); + m_settings->registerSetting(new Setting("PermGen", 64)); + + // Java Settings + m_settings->registerSetting(new Setting("JavaPath", "java")); + m_settings->registerSetting(new Setting("JvmArgs", "")); + + // Custom Commands + m_settings->registerSetting(new Setting("PreLaunchCommand", "")); + m_settings->registerSetting(new Setting("PostExitCommand", "")); + + // The cat + m_settings->registerSetting(new Setting("TheCat", false)); +} + +IconList* MultiMC::icons() +{ + if ( !m_icons ) + { + m_icons = new IconList; + } + return m_icons; +} + + +int main(int argc, char *argv[]) +{ + // initialize Qt + MultiMC app(argc, argv); + + // show main window + MainWindow mainWin; + mainWin.show(); + + switch(app.status()) + { + case MultiMC::Initialized: + return app.exec(); + case MultiMC::Failed: + return 1; + case MultiMC::Succeeded: + return 0; + } +} + +#include "MultiMC.moc" \ No newline at end of file diff --git a/MultiMC.h b/MultiMC.h new file mode 100644 index 00000000..99d90b99 --- /dev/null +++ b/MultiMC.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include "MultiMCVersion.h" +#include "config.h" + +class SettingsObject; +class InstanceList; +class IconList; +class QNetworkAccessManager; + +#if defined(MMC) +#undef MMC +#endif +#define MMC (static_cast(QCoreApplication::instance())) + +class MultiMC : public QApplication +{ + Q_OBJECT +public: + enum Status + { + Failed, + Succeeded, + Initialized, + }; + +public: + MultiMC ( int& argc, char** argv ); + virtual ~MultiMC(); + + SettingsObject * settings() + { + return m_settings; + }; + + InstanceList * instances() + { + return m_instances; + }; + + IconList * icons(); + + Status status() + { + return m_status; + } + + MultiMCVersion version() + { + return m_version; + } + + QNetworkAccessManager * qnam() + { + return m_qnam; + } +private: + void initGlobalSettings(); + +private: + SettingsObject * m_settings = nullptr; + InstanceList * m_instances = nullptr; + IconList * m_icons = nullptr; + QNetworkAccessManager * m_qnam = nullptr; + Status m_status = MultiMC::Failed; + MultiMCVersion m_version = {VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD}; +}; \ No newline at end of file diff --git a/MultiMCVersion.h b/MultiMCVersion.h new file mode 100644 index 00000000..70a2259e --- /dev/null +++ b/MultiMCVersion.h @@ -0,0 +1,63 @@ +/* Copyright 2013 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 + +/*! + * \brief The Version class represents a MultiMC version number. + */ +struct MultiMCVersion +{ + /*! + * \brief Converts the Version to a string. + * \return The version number in string format (major.minor.revision.build). + */ + QString toString() const + { + return QString("%1.%2.%3.%4").arg( + QString::number(major), + QString::number(minor), + QString::number(revision), + QString::number(build)); + } + + /*! + * \brief The major version number. + * For MultiMC 5, this will always be 5. + */ + int major; + + /*! + * \brief The minor version number. + * This number is incremented when major features are added. + */ + int minor; + + /*! + * \brief The revision number. + * This number is incremented for bugfixes and small features. + */ + int revision; + + /*! + * \brief The build number. + * This number is automatically set by Jenkins. It is incremented every time + * a new build is run. + */ + int build; +}; + diff --git a/depends/classparser/src/javautils.cpp b/depends/classparser/src/javautils.cpp index 4a359031..3a5c6934 100644 --- a/depends/classparser/src/javautils.cpp +++ b/depends/classparser/src/javautils.cpp @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "multimc_pragma.h" #include "classfile.h" #include "javautils.h" diff --git a/depends/settings/include/settingsobject.h b/depends/settings/include/settingsobject.h index a2f03699..e8bf5c83 100644 --- a/depends/settings/include/settingsobject.h +++ b/depends/settings/include/settingsobject.h @@ -13,8 +13,7 @@ * limitations under the License. */ -#ifndef SETTINGSOBJECT_H -#define SETTINGSOBJECT_H +#pragma once #include #include @@ -183,10 +182,3 @@ protected: private: QMap m_settings; }; - -/*! - * \brief A global settings object. - */ -LIBSETTINGS_EXPORT extern SettingsObject *globalSettings; - -#endif // SETTINGSOBJECT_H diff --git a/depends/settings/src/settingsobject.cpp b/depends/settings/src/settingsobject.cpp index bf7b8825..2ca544ad 100644 --- a/depends/settings/src/settingsobject.cpp +++ b/depends/settings/src/settingsobject.cpp @@ -18,8 +18,6 @@ #include -SettingsObject *globalSettings; - SettingsObject::SettingsObject(QObject *parent) : QObject(parent) { diff --git a/gui/IconPickerDialog.cpp b/gui/IconPickerDialog.cpp index b75eb30c..2dd80292 100644 --- a/gui/IconPickerDialog.cpp +++ b/gui/IconPickerDialog.cpp @@ -1,7 +1,8 @@ +#include #include "IconPickerDialog.h" #include "instancedelegate.h" #include "ui_IconPickerDialog.h" -#include "logic/IconListModel.h" +#include "logic/lists/IconList.h" #include #include #include @@ -38,8 +39,7 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) : contentsWidget->installEventFilter(this); - IconList * list = IconList::instance(); - contentsWidget->setModel(list); + contentsWidget->setModel(MMC->icons()); auto buttonAdd = ui->buttonBox->addButton("Add Icon",QDialogButtonBox::ResetRole); auto buttonRemove = ui->buttonBox->addButton("Remove Icon",QDialogButtonBox::ResetRole); @@ -71,7 +71,6 @@ bool IconPickerDialog::eventFilter ( QObject* obj, QEvent* evt) return QDialog::eventFilter(obj ,evt); } QKeyEvent *keyEvent = static_cast(evt); - IconList * list = IconList::instance(); switch(keyEvent->key()) { case Qt::Key_Delete: @@ -89,14 +88,12 @@ bool IconPickerDialog::eventFilter ( QObject* obj, QEvent* evt) void IconPickerDialog::addNewIcon() { QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Icons", QString(), "Icons (*.png *.jpg *.jpeg)"); - IconList * list = IconList::instance(); - list->installIcons(fileNames); + MMC->icons()->installIcons(fileNames); } void IconPickerDialog::removeSelectedIcon() { - IconList * list = IconList::instance(); - list->deleteIcon(selectedIconKey); + MMC->icons()->deleteIcon(selectedIconKey); } @@ -119,7 +116,7 @@ void IconPickerDialog::selectionChanged ( QItemSelection selected, QItemSelectio int IconPickerDialog::exec ( QString selection ) { - IconList * list = IconList::instance(); + IconList * list = MMC->icons(); auto contentsWidget = ui->iconView; selectedIconKey = selection; diff --git a/gui/aboutdialog.cpp b/gui/aboutdialog.cpp index 873cc175..9792d4fe 100644 --- a/gui/aboutdialog.cpp +++ b/gui/aboutdialog.cpp @@ -1,9 +1,7 @@ #include "aboutdialog.h" #include "ui_aboutdialog.h" -#include - #include -#include +#include AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), @@ -12,10 +10,10 @@ AboutDialog::AboutDialog(QWidget *parent) : ui->setupUi(this); ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64)); - ui->title->setText("MultiMC " + AppVersion::current.toString()); + ui->title->setText("MultiMC " + MMC->version().toString()); connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); - QApplication::instance()->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt())); + MMC->connect(ui->aboutQt, SIGNAL(clicked()), SLOT(aboutQt())); } AboutDialog::~AboutDialog() diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 4ccc12b6..82483bf2 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -16,6 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "mainwindow.h" #include "ui_mainwindow.h" @@ -23,7 +24,7 @@ #include #include #include -#include + #include #include #include @@ -48,33 +49,30 @@ #include "gui/consolewindow.h" #include "gui/instancesettings.h" -#include "AppSettings.h" -#include "AppVersion.h" - #include "logic/lists/InstanceList.h" +#include "logic/lists/MinecraftVersionList.h" +#include "logic/lists/LwjglVersionList.h" +#include "logic/lists/IconList.h" + #include "logic/tasks/LoginTask.h" #include "logic/BaseInstance.h" #include "logic/InstanceFactory.h" #include "logic/MinecraftProcess.h" #include "logic/OneSixAssets.h" #include "logic/OneSixUpdate.h" -#include "logic/lists/MinecraftVersionList.h" -#include "logic/lists/LwjglVersionList.h" -#include -#include + +#include "logic/LegacyInstance.h" #include "instancedelegate.h" #include "IconPickerDialog.h" #include "LabeledToolButton.h" #include "EditNotesDialog.h" -MainWindow::MainWindow ( QWidget *parent ) : - QMainWindow ( parent ), - ui ( new Ui::MainWindow ), - instList ( globalSettings->get ( "InstanceDir" ).toString() ) +MainWindow::MainWindow ( QWidget *parent ) + :QMainWindow ( parent ), ui ( new Ui::MainWindow ) { ui->setupUi ( this ); - setWindowTitle ( QString ( "MultiMC %1" ).arg ( AppVersion::current.toString() ) ); + setWindowTitle ( QString ( "MultiMC %1" ).arg ( MMC->version().toString() ) ); // Set the selected instance to null m_selectedInstance = nullptr; @@ -126,7 +124,7 @@ MainWindow::MainWindow ( QWidget *parent ) : //proxymodel->setDynamicSortFilter ( true ); // FIXME: instList should be global-ish, or at least not tied to the main window... maybe the application itself? - proxymodel->setSourceModel ( &instList ); + proxymodel->setSourceModel ( MMC->instances() ); proxymodel->sort ( 0 ); view->setFrameShape ( QFrame::NoFrame ); view->setModel ( proxymodel ); @@ -135,7 +133,7 @@ MainWindow::MainWindow ( QWidget *parent ) : } // The cat background { - bool cat_enable = globalSettings->get("TheCat").toBool(); + bool cat_enable = MMC->settings()->get("TheCat").toBool(); ui->actionCAT->setChecked(cat_enable); connect(ui->actionCAT, SIGNAL(toggled(bool)), SLOT(onCatToggled(bool))); setCatBackground(cat_enable); @@ -151,12 +149,11 @@ MainWindow::MainWindow ( QWidget *parent ) : ); // model reset -> selection is invalid. All the instance pointers are wrong. // FIXME: stop using POINTERS everywhere - connect(&instList,SIGNAL(dataIsInvalid()),SLOT(selectionBad())); + connect(MMC->instances() ,SIGNAL(dataIsInvalid()),SLOT(selectionBad())); // run the things that load and download other things... FIXME: this is NOT the place // FIXME: invisible actions in the background = NOPE. { - instList.loadList(); if (!MinecraftVersionList::getMainList().isLoaded()) { m_versionLoadTask = MinecraftVersionList::getMainList().getLoadTask(); @@ -212,7 +209,7 @@ bool MainWindow::eventFilter ( QObject* obj, QEvent* ev ) void MainWindow::onCatToggled ( bool state ) { setCatBackground(state); - globalSettings->set("TheCat", state); + MMC->settings()->set("TheCat", state); } void MainWindow::setCatBackground ( bool enabled ) @@ -264,7 +261,7 @@ void MainWindow::on_actionAddInstance_triggered() BaseInstance *newInstance = NULL; QString instDirName = DirNameFromString(newInstDlg.instName()); - QString instDir = PathCombine(globalSettings->get("InstanceDir").toString(), instDirName); + QString instDir = PathCombine(MMC->settings()->get("InstanceDir").toString(), instDirName); auto &loader = InstanceFactory::get(); @@ -275,7 +272,7 @@ void MainWindow::on_actionAddInstance_triggered() case InstanceFactory::NoCreateError: newInstance->setName(newInstDlg.instName()); newInstance->setIconKey(newInstDlg.iconKey()); - instList.add(InstancePtr(newInstance)); + MMC->instances()->add(InstancePtr(newInstance)); return; case InstanceFactory::InstExists: @@ -305,8 +302,7 @@ void MainWindow::on_actionChangeInstIcon_triggered() if(dlg.result() == QDialog::Accepted) { m_selectedInstance->setIconKey(dlg.selectedIconKey); - IconList * iconListModel = IconList::instance(); - auto ico =iconListModel->getIcon(dlg.selectedIconKey); + auto ico = MMC->icons()->getIcon(dlg.selectedIconKey); ui->actionChangeInstIcon->setIcon(ico); } } @@ -328,18 +324,18 @@ void MainWindow::on_actionChangeInstGroup_triggered() void MainWindow::on_actionViewInstanceFolder_triggered() { - QString str = globalSettings->get ( "InstanceDir" ).toString(); + QString str = MMC->settings()->get ( "InstanceDir" ).toString(); openDirInDefaultProgram ( str ); } void MainWindow::on_actionRefresh_triggered() { - instList.loadList(); + MMC->instances()->loadList(); } void MainWindow::on_actionViewCentralModsFolder_triggered() { - openDirInDefaultProgram ( globalSettings->get ( "CentralModsDir" ).toString() , true); + openDirInDefaultProgram ( MMC->settings()->get ( "CentralModsDir" ).toString() , true); } void MainWindow::on_actionConfig_Folder_triggered() @@ -632,8 +628,7 @@ void MainWindow::instanceChanged( const QModelIndex& current, const QModelIndex& ui->actionEditInstMods->setEnabled(m_selectedInstance->menuActionEnabled("actionEditInstMods")); statusBar()->clearMessage(); statusBar()->showMessage(m_selectedInstance->getStatusbarDescription()); - IconList * iconListModel = IconList::instance(); - auto ico =iconListModel->getIcon(iconKey); + auto ico =MMC->icons()->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); } else @@ -649,8 +644,7 @@ void MainWindow::selectionBad() statusBar()->clearMessage(); ui->instanceToolBar->setEnabled(false); renameButton->setText("Rename Instance"); - IconList * iconListModel = IconList::instance(); - auto ico =iconListModel->getIcon(iconKey); + auto ico = MMC->icons()->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); } diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 42f118b1..3612dd0c 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -132,7 +132,6 @@ private: KCategoryDrawer * drawer; KCategorizedView * view; InstanceProxyModel * proxymodel; - InstanceList instList; MinecraftProcess *proc; ConsoleWindow *console; OneSixAssets *assets_downloader; diff --git a/gui/newinstancedialog.cpp b/gui/newinstancedialog.cpp index f0a70a1b..ac3bcd7d 100644 --- a/gui/newinstancedialog.cpp +++ b/gui/newinstancedialog.cpp @@ -13,12 +13,13 @@ * limitations under the License. */ +#include #include "newinstancedialog.h" #include "ui_newinstancedialog.h" #include "logic/InstanceFactory.h" #include "logic/InstanceVersion.h" -#include "logic/IconListModel.h" +#include "logic/lists/IconList.h" #include "logic/lists/MinecraftVersionList.h" #include "logic/tasks/Task.h" @@ -49,8 +50,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) : */ setSelectedVersion(MinecraftVersionList::getMainList().getLatestStable()); InstIconKey = "infinity"; - IconList * list = IconList::instance(); - ui->iconButton->setIcon(list->getIcon(InstIconKey)); + ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); } NewInstanceDialog::~NewInstanceDialog() @@ -113,9 +113,8 @@ void NewInstanceDialog::on_iconButton_clicked() if(dlg.result() == QDialog::Accepted) { - IconList * list = IconList::instance(); InstIconKey = dlg.selectedIconKey; - ui->iconButton->setIcon(list->getIcon(InstIconKey)); + ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); } } diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 52093039..a1fbb8e7 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -16,8 +16,8 @@ #include "settingsdialog.h" #include "ui_settingsdialog.h" -#include "AppSettings.h" - +#include +#include #include #include @@ -27,7 +27,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : { ui->setupUi(this); - loadSettings(globalSettings); + loadSettings(MMC->settings()); updateCheckboxStuff(); } @@ -85,7 +85,7 @@ void SettingsDialog::on_maximizedCheckBox_clicked(bool checked) void SettingsDialog::on_buttonBox_accepted() { - applySettings(globalSettings); + applySettings(MMC->settings()); } void SettingsDialog::applySettings(SettingsObject *s) diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index bd3229c8..e166449f 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "inisettingsobject.h" #include "setting.h" @@ -52,6 +53,8 @@ BaseInstance::BaseInstance( BaseInstancePrivate* d_in, settings().registerSetting(new Setting("UseCustomBaseJar", true)); settings().registerSetting(new Setting("CustomBaseJar", "")); + auto globalSettings = MMC->settings(); + // Java Settings settings().registerSetting(new Setting("OverrideJava", false)); settings().registerSetting(new OverrideSetting("JavaPath", globalSettings->getSetting("JavaPath"))); diff --git a/logic/IconListModel.cpp b/logic/IconListModel.cpp deleted file mode 100644 index 4a5795d6..00000000 --- a/logic/IconListModel.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include "IconListModel.h" -#include -#include -#include -#include -#include -#include -#define MAX_SIZE 1024 -IconList* IconList::m_Instance = 0; -QMutex IconList::mutex; - -struct entry -{ - QString key; - QString name; - QIcon icon; - bool is_builtin; - QString filename; -}; - -class Private : public QObject -{ - Q_OBJECT -public: - QMap index; - QVector icons; - Private() - { - } -}; - - -IconList::IconList() : QAbstractListModel(), d(new Private()) -{ - QDir instance_icons(":/icons/instances/"); - auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); - for(auto file_info: file_info_list) - { - QString key = file_info.baseName(); - addIcon(key, key, file_info.absoluteFilePath(), true); - } - - // FIXME: get from settings - ensureFolderPathExists("icons"); - QDir user_icons("icons"); - file_info_list = user_icons.entryInfoList(QDir::Files, QDir::Name); - for(auto file_info: file_info_list) - { - QString filename = file_info.absoluteFilePath(); - QString key = file_info.baseName(); - addIcon(key, key, filename); - } -} - -IconList::~IconList() -{ - delete d; - d = nullptr; -} - -QStringList IconList::mimeTypes() const -{ - QStringList types; - types << "text/uri-list"; - return types; -} -Qt::DropActions IconList::supportedDropActions() const -{ - return Qt::CopyAction; -} - -bool IconList::dropMimeData ( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ) -{ - if (action == Qt::IgnoreAction) - return true; - // check if the action is supported - if (!data || !(action & supportedDropActions())) - return false; - - // files dropped from outside? - if(data->hasUrls()) - { - /* - bool was_watching = is_watching; - if(was_watching) - stopWatching(); - */ - auto urls = data->urls(); - QStringList iconFiles; - for(auto url: urls) - { - // only local files may be dropped... - if(!url.isLocalFile()) - continue; - iconFiles += url.toLocalFile(); - } - installIcons(iconFiles); - /* - if(was_watching) - startWatching(); - */ - return true; - } - return false; -} - -Qt::ItemFlags IconList::flags ( const QModelIndex& index ) const -{ - Qt::ItemFlags defaultFlags = QAbstractListModel::flags ( index ); - if (index.isValid()) - return Qt::ItemIsDropEnabled | defaultFlags; - else - return Qt::ItemIsDropEnabled | defaultFlags; -} - -QVariant IconList::data ( const QModelIndex& index, int role ) const -{ - if(!index.isValid()) - return QVariant(); - - int row = index.row(); - - if(row < 0 || row >= d->icons.size()) - return QVariant(); - - switch(role) - { - case Qt::DecorationRole: - return d->icons[row].icon; - case Qt::DisplayRole: - return d->icons[row].name; - case Qt::UserRole: - return d->icons[row].key; - default: - return QVariant(); - } -} - -int IconList::rowCount ( const QModelIndex& parent ) const -{ - return d->icons.size(); -} - -void IconList::installIcons ( QStringList iconFiles ) -{ - for(QString file: iconFiles) - { - QFileInfo fileinfo(file); - if(!fileinfo.isReadable() || !fileinfo.isFile()) - continue; - QString target = PathCombine("icons", fileinfo.fileName()); - - QString suffix = fileinfo.suffix(); - if(suffix != "jpeg" && suffix != "png" && suffix != "jpg") - continue; - - if(!QFile::copy(file, target)) - continue; - - QString key = fileinfo.baseName(); - addIcon(key, key, target); - } -} - -bool IconList::deleteIcon ( QString key ) -{ - int iconIdx = getIconIndex(key); - if(iconIdx == -1) - return false; - auto & iconEntry = d->icons[iconIdx]; - if(iconEntry.is_builtin) - return false; - if(QFile::remove(iconEntry.filename)) - { - beginRemoveRows(QModelIndex(), iconIdx, iconIdx); - d->icons.remove(iconIdx); - reindex(); - endRemoveRows(); - } - return true; -} - -bool IconList::addIcon ( QString key, QString name, QString path, bool is_builtin ) -{ - auto iter = d->index.find(key); - if(iter != d->index.end()) - { - if(d->icons[*iter].is_builtin) - return false; - - QIcon icon(path); - if(icon.isNull()) - return false; - - auto & oldOne = d->icons[*iter]; - - if(!QFile::remove(oldOne.filename)) - return false; - - // replace the icon - oldOne = {key, name, icon, is_builtin, path}; - dataChanged(index(*iter),index(*iter)); - return true; - } - else - { - QIcon icon(path); - if(icon.isNull()) return false; - - // add a new icon - beginInsertRows(QModelIndex(), d->icons.size(),d->icons.size()); - d->icons.push_back({key, name, icon, is_builtin, path}); - d->index[key] = d->icons.size() - 1; - endInsertRows(); - return true; - } -} - -void IconList::reindex() -{ - d->index.clear(); - int i = 0; - for(auto& iter: d->icons) - { - d->index[iter.key] = i; - i++; - } -} - - -QIcon IconList::getIcon ( QString key ) -{ - int icon_index = getIconIndex(key); - - if(icon_index != -1) - return d->icons[icon_index].icon; - - // Fallback for icons that don't exist. - icon_index = getIconIndex("infinity"); - - if(icon_index != -1) - return d->icons[icon_index].icon; - return QIcon(); -} - -int IconList::getIconIndex ( QString key ) -{ - if(key == "default") - key = "infinity"; - - auto iter = d->index.find(key); - if(iter != d->index.end()) - return *iter; - - - return -1; -} - - -void IconList::drop() -{ - mutex.lock(); - delete m_Instance; - m_Instance = 0; - mutex.unlock(); -} - -IconList* IconList::instance() -{ - if ( !m_Instance ) - { - mutex.lock(); - if ( !m_Instance ) - m_Instance = new IconList; - mutex.unlock(); - } - return m_Instance; -} - -#include "IconListModel.moc" \ No newline at end of file diff --git a/logic/IconListModel.h b/logic/IconListModel.h deleted file mode 100644 index 907dfd81..00000000 --- a/logic/IconListModel.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include - -class Private; - -class IconList : public QAbstractListModel -{ -public: - static IconList* instance(); - static void drop(); - QIcon getIcon ( QString key ); - int getIconIndex ( QString key ); - - virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const; - virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; - - bool addIcon(QString key, QString name, QString path, bool is_builtin = false); - bool deleteIcon(QString key); - - virtual QStringList mimeTypes() const; - virtual Qt::DropActions supportedDropActions() const; - virtual bool dropMimeData ( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ); - virtual Qt::ItemFlags flags ( const QModelIndex& index ) const; - - void installIcons ( QStringList iconFiles ); - -private: - virtual ~IconList(); - IconList(); - // hide copy constructor - IconList ( const IconList & ) = delete; - // hide assign op - IconList& operator= ( const IconList & ) = delete; - void reindex(); - static IconList* m_Instance; - static QMutex mutex; - Private* d; -}; diff --git a/logic/InstanceLauncher.cpp b/logic/InstanceLauncher.cpp new file mode 100644 index 00000000..312f4c69 --- /dev/null +++ b/logic/InstanceLauncher.cpp @@ -0,0 +1,74 @@ +#include "InstanceLauncher.h" +#include "MultiMC.h" + +#include +#include "gui/logindialog.h" +#include "gui/taskdialog.h" +#include "gui/consolewindow.h" +#include "logic/tasks/LoginTask.h" +#include "logic/MinecraftProcess.h" +#include "lists/InstanceList.h" + + +InstanceLauncher::InstanceLauncher ( QString instId ) + :QObject(), instId ( instId ) +{} + +void InstanceLauncher::onTerminated() +{ + std::cout << "Minecraft exited" << std::endl; + MMC->quit(); +} + +void InstanceLauncher::onLoginComplete() +{ + LoginTask * task = ( LoginTask * ) QObject::sender(); + auto result = task->getResult(); + auto instance = MMC->instances()->getInstanceById(instId); + proc = instance->prepareForLaunch ( result.username, result.sessionID ); + if ( !proc ) + { + //FIXME: report error + return; + } + console = new ConsoleWindow(); + console->show(); + + connect ( proc, SIGNAL ( ended() ), SLOT ( onTerminated() ) ); + connect ( proc, SIGNAL ( log ( QString,MessageLevel::Enum ) ), console, SLOT ( write ( QString,MessageLevel::Enum ) ) ); + + proc->launch(); +} + +void InstanceLauncher::doLogin ( const QString& errorMsg ) +{ + LoginDialog* loginDlg = new LoginDialog ( nullptr, errorMsg ); + loginDlg->exec(); + if ( loginDlg->result() == QDialog::Accepted ) + { + UserInfo uInfo {loginDlg->getUsername(), loginDlg->getPassword() }; + + TaskDialog* tDialog = new TaskDialog ( nullptr ); + LoginTask* loginTask = new LoginTask ( uInfo, tDialog ); + connect ( loginTask, SIGNAL ( succeeded() ),SLOT ( onLoginComplete() ), Qt::QueuedConnection ); + connect ( loginTask, SIGNAL ( failed ( QString ) ),SLOT ( doLogin ( QString ) ), Qt::QueuedConnection ); + tDialog->exec ( loginTask ); + } + //onLoginComplete(LoginResponse("Offline","Offline", 1)); +} + +int InstanceLauncher::launch() +{ + std::cout << "Launching Instance '" << qPrintable ( instId ) << "'" << std::endl; + auto instance = MMC->instances()->getInstanceById(instId); + if ( instance.isNull() ) + { + std::cout << "Could not find instance requested. note that you have to specify the ID, not the NAME" << std::endl; + return 1; + } + + std::cout << "Logging in..." << std::endl; + doLogin ( "" ); + + return MMC->exec(); +} diff --git a/logic/InstanceLauncher.h b/logic/InstanceLauncher.h new file mode 100644 index 00000000..de93e3d7 --- /dev/null +++ b/logic/InstanceLauncher.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +class MinecraftProcess; +class ConsoleWindow; + +// Commandline instance launcher +class InstanceLauncher : public QObject +{ + Q_OBJECT + +private: + QString instId; + MinecraftProcess *proc; + ConsoleWindow *console; + +public: + InstanceLauncher(QString instId); + +private slots: + void onTerminated(); + void onLoginComplete(); + void doLogin(const QString &errorMsg); + +public: + int launch(); +}; diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 124cdfcb..0672d2c8 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -2,7 +2,7 @@ #include "LegacyInstance_p.h" #include "MinecraftProcess.h" #include "LegacyUpdate.h" -#include "IconListModel.h" +#include "lists/IconList.h" #include #include #include @@ -10,6 +10,7 @@ #include #include #include +#include #define LAUNCHER_FILE "MultiMCLauncher.jar" @@ -32,8 +33,7 @@ MinecraftProcess* LegacyInstance::prepareForLaunch(QString user, QString session { MinecraftProcess * proc = new MinecraftProcess(this); - IconList * list = IconList::instance(); - QIcon icon = list->getIcon(iconKey()); + QIcon icon = MMC->icons()->getIcon(iconKey()); auto pixmap = icon.pixmap(128,128); pixmap.save(PathCombine(minecraftRoot(), "icon.png"),"PNG"); @@ -66,7 +66,7 @@ MinecraftProcess* LegacyInstance::prepareForLaunch(QString user, QString session args << QString("-Xdock:name=\"%1\"").arg(windowTitle); #endif - QString lwjgl = QDir(globalSettings->get("LWJGLDir").toString() + "/" + lwjglVersion()).absolutePath(); + QString lwjgl = QDir(MMC->settings()->get("LWJGLDir").toString() + "/" + lwjglVersion()).absolutePath(); // launcher arguments args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt()); diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 3d286373..626ad1e0 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -3,7 +3,7 @@ #include "lists/MinecraftVersionList.h" #include "BaseInstance.h" #include "LegacyInstance.h" -#include "net/NetWorker.h" +#include "MultiMC.h" #include "ModList.h" #include #include @@ -52,15 +52,15 @@ void LegacyUpdate::lwjglStart() QString url = version->url(); QUrl realUrl(url); QString hostname = realUrl.host(); - auto &worker = NetWorker::qnam(); + auto worker = MMC->qnam(); QNetworkRequest req(realUrl); req.setRawHeader("Host", hostname.toLatin1()); req.setHeader(QNetworkRequest::UserAgentHeader, "Wget/1.14 (linux-gnu)"); - QNetworkReply * rep = worker.get ( req ); + QNetworkReply * rep = worker->get ( req ); m_reply = QSharedPointer (rep, &QObject::deleteLater); connect(rep, SIGNAL(downloadProgress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); - connect(&worker, SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*))); + connect(worker, SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*))); //connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); } @@ -77,13 +77,13 @@ void LegacyUpdate::lwjglFinished(QNetworkReply* reply) "\nSometimes you have to wait a bit if you download many LWJGL versions in a row. YMMV"); return; } - auto &worker = NetWorker::qnam(); + auto *worker = MMC->qnam(); //Here i check if there is a cookie for me in the reply and extract it QList cookies = qvariant_cast>(reply->header(QNetworkRequest::SetCookieHeader)); if(cookies.count() != 0) { //you must tell which cookie goes with which url - worker.cookieJar()->setCookiesFromUrl(cookies, QUrl("sourceforge.net")); + worker->cookieJar()->setCookiesFromUrl(cookies, QUrl("sourceforge.net")); } //here you can check for the 302 or whatever other header i need @@ -96,7 +96,7 @@ void LegacyUpdate::lwjglFinished(QNetworkReply* reply) QNetworkRequest req(redirectedTo); req.setRawHeader("Host", hostname.toLatin1()); req.setHeader(QNetworkRequest::UserAgentHeader, "Wget/1.14 (linux-gnu)"); - QNetworkReply * rep = worker.get(req); + QNetworkReply * rep = worker->get(req); connect(rep, SIGNAL(downloadProgress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); m_reply = QSharedPointer (rep, &QObject::deleteLater); return; diff --git a/logic/lists/IconList.cpp b/logic/lists/IconList.cpp new file mode 100644 index 00000000..6988d02f --- /dev/null +++ b/logic/lists/IconList.cpp @@ -0,0 +1,257 @@ +#include "IconList.h" +#include +#include +#include +#include +#include +#include +#define MAX_SIZE 1024 + +struct entry +{ + QString key; + QString name; + QIcon icon; + bool is_builtin; + QString filename; +}; + +class Private : public QObject +{ + Q_OBJECT +public: + QMap index; + QVector icons; + Private() + { + } +}; + + +IconList::IconList() : QAbstractListModel(), d(new Private()) +{ + QDir instance_icons(":/icons/instances/"); + auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); + for(auto file_info: file_info_list) + { + QString key = file_info.baseName(); + addIcon(key, key, file_info.absoluteFilePath(), true); + } + + // FIXME: get from settings + ensureFolderPathExists("icons"); + QDir user_icons("icons"); + file_info_list = user_icons.entryInfoList(QDir::Files, QDir::Name); + for(auto file_info: file_info_list) + { + QString filename = file_info.absoluteFilePath(); + QString key = file_info.baseName(); + addIcon(key, key, filename); + } +} + +IconList::~IconList() +{ + delete d; + d = nullptr; +} + +QStringList IconList::mimeTypes() const +{ + QStringList types; + types << "text/uri-list"; + return types; +} +Qt::DropActions IconList::supportedDropActions() const +{ + return Qt::CopyAction; +} + +bool IconList::dropMimeData ( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ) +{ + if (action == Qt::IgnoreAction) + return true; + // check if the action is supported + if (!data || !(action & supportedDropActions())) + return false; + + // files dropped from outside? + if(data->hasUrls()) + { + /* + bool was_watching = is_watching; + if(was_watching) + stopWatching(); + */ + auto urls = data->urls(); + QStringList iconFiles; + for(auto url: urls) + { + // only local files may be dropped... + if(!url.isLocalFile()) + continue; + iconFiles += url.toLocalFile(); + } + installIcons(iconFiles); + /* + if(was_watching) + startWatching(); + */ + return true; + } + return false; +} + +Qt::ItemFlags IconList::flags ( const QModelIndex& index ) const +{ + Qt::ItemFlags defaultFlags = QAbstractListModel::flags ( index ); + if (index.isValid()) + return Qt::ItemIsDropEnabled | defaultFlags; + else + return Qt::ItemIsDropEnabled | defaultFlags; +} + +QVariant IconList::data ( const QModelIndex& index, int role ) const +{ + if(!index.isValid()) + return QVariant(); + + int row = index.row(); + + if(row < 0 || row >= d->icons.size()) + return QVariant(); + + switch(role) + { + case Qt::DecorationRole: + return d->icons[row].icon; + case Qt::DisplayRole: + return d->icons[row].name; + case Qt::UserRole: + return d->icons[row].key; + default: + return QVariant(); + } +} + +int IconList::rowCount ( const QModelIndex& parent ) const +{ + return d->icons.size(); +} + +void IconList::installIcons ( QStringList iconFiles ) +{ + for(QString file: iconFiles) + { + QFileInfo fileinfo(file); + if(!fileinfo.isReadable() || !fileinfo.isFile()) + continue; + QString target = PathCombine("icons", fileinfo.fileName()); + + QString suffix = fileinfo.suffix(); + if(suffix != "jpeg" && suffix != "png" && suffix != "jpg") + continue; + + if(!QFile::copy(file, target)) + continue; + + QString key = fileinfo.baseName(); + addIcon(key, key, target); + } +} + +bool IconList::deleteIcon ( QString key ) +{ + int iconIdx = getIconIndex(key); + if(iconIdx == -1) + return false; + auto & iconEntry = d->icons[iconIdx]; + if(iconEntry.is_builtin) + return false; + if(QFile::remove(iconEntry.filename)) + { + beginRemoveRows(QModelIndex(), iconIdx, iconIdx); + d->icons.remove(iconIdx); + reindex(); + endRemoveRows(); + } + return true; +} + +bool IconList::addIcon ( QString key, QString name, QString path, bool is_builtin ) +{ + auto iter = d->index.find(key); + if(iter != d->index.end()) + { + if(d->icons[*iter].is_builtin) + return false; + + QIcon icon(path); + if(icon.isNull()) + return false; + + auto & oldOne = d->icons[*iter]; + + if(!QFile::remove(oldOne.filename)) + return false; + + // replace the icon + oldOne = {key, name, icon, is_builtin, path}; + dataChanged(index(*iter),index(*iter)); + return true; + } + else + { + QIcon icon(path); + if(icon.isNull()) return false; + + // add a new icon + beginInsertRows(QModelIndex(), d->icons.size(),d->icons.size()); + d->icons.push_back({key, name, icon, is_builtin, path}); + d->index[key] = d->icons.size() - 1; + endInsertRows(); + return true; + } +} + +void IconList::reindex() +{ + d->index.clear(); + int i = 0; + for(auto& iter: d->icons) + { + d->index[iter.key] = i; + i++; + } +} + + +QIcon IconList::getIcon ( QString key ) +{ + int icon_index = getIconIndex(key); + + if(icon_index != -1) + return d->icons[icon_index].icon; + + // Fallback for icons that don't exist. + icon_index = getIconIndex("infinity"); + + if(icon_index != -1) + return d->icons[icon_index].icon; + return QIcon(); +} + +int IconList::getIconIndex ( QString key ) +{ + if(key == "default") + key = "infinity"; + + auto iter = d->index.find(key); + if(iter != d->index.end()) + return *iter; + + + return -1; +} + +#include "IconList.moc" \ No newline at end of file diff --git a/logic/lists/IconList.h b/logic/lists/IconList.h new file mode 100644 index 00000000..cad80cdf --- /dev/null +++ b/logic/lists/IconList.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +class Private; + +class IconList : public QAbstractListModel +{ +public: + IconList(); + virtual ~IconList(); + + QIcon getIcon ( QString key ); + int getIconIndex ( QString key ); + + virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const; + virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; + + bool addIcon(QString key, QString name, QString path, bool is_builtin = false); + bool deleteIcon(QString key); + + virtual QStringList mimeTypes() const; + virtual Qt::DropActions supportedDropActions() const; + virtual bool dropMimeData ( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ); + virtual Qt::ItemFlags flags ( const QModelIndex& index ) const; + + void installIcons ( QStringList iconFiles ); + +private: + // hide copy constructor + IconList ( const IconList & ) = delete; + // hide assign op + IconList& operator= ( const IconList & ) = delete; + void reindex(); + Private* d; +}; diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp index 1d13e3f2..b930f781 100644 --- a/logic/lists/InstanceList.cpp +++ b/logic/lists/InstanceList.cpp @@ -22,13 +22,13 @@ #include #include #include +#include +#include "MultiMC.h" #include "logic/lists/InstanceList.h" +#include "logic/lists/IconList.h" #include "logic/BaseInstance.h" #include "logic/InstanceFactory.h" -#include - -#include "pathutils.h" const static int GROUP_FILE_FORMAT_VERSION = 1; @@ -81,9 +81,8 @@ QVariant InstanceList::data ( const QModelIndex& index, int role ) const } case Qt::DecorationRole: { - IconList * ic = IconList::instance(); QString key = pdata->iconKey(); - return ic->getIcon(key); + return MMC->icons()->getIcon(key); } // for now. case KCategorizedSortFilterProxyModel::CategorySortRole: @@ -413,5 +412,3 @@ bool InstanceProxyModel::subSortLessThan (const QModelIndex& left, const QModelI return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0; //return pdataLeft->name() < pdataRight->name(); } - -#include "InstanceList.moc" \ No newline at end of file diff --git a/logic/lists/LwjglVersionList.cpp b/logic/lists/LwjglVersionList.cpp index c0854628..d7826a82 100644 --- a/logic/lists/LwjglVersionList.cpp +++ b/logic/lists/LwjglVersionList.cpp @@ -14,7 +14,7 @@ */ #include "LwjglVersionList.h" -#include "logic/net/NetWorker.h" +#include "MultiMC.h" #include @@ -91,8 +91,8 @@ void LWJGLVersionList::loadList() Q_ASSERT_X(!m_loading, "loadList", "list is already loading (m_loading is true)"); setLoading(true); - auto & worker = NetWorker::qnam(); - reply = worker.get(QNetworkRequest(QUrl(RSS_URL))); + auto worker = MMC->qnam(); + reply = worker->get(QNetworkRequest(QUrl(RSS_URL))); connect(reply, SIGNAL(finished()), SLOT(netRequestComplete())); } diff --git a/logic/lists/MinecraftVersionList.cpp b/logic/lists/MinecraftVersionList.cpp index 4444f5b0..42fb1b50 100644 --- a/logic/lists/MinecraftVersionList.cpp +++ b/logic/lists/MinecraftVersionList.cpp @@ -14,7 +14,7 @@ */ #include "MinecraftVersionList.h" -#include +#include #include @@ -151,8 +151,8 @@ MCVListLoadTask::~MCVListLoadTask() void MCVListLoadTask::executeTask() { setStatus("Loading instance version list..."); - auto & worker = NetWorker::qnam(); - vlistReply = worker.get(QNetworkRequest(QUrl(QString(MCVLIST_URLBASE) + "versions.json"))); + auto worker = MMC->qnam(); + vlistReply = worker->get(QNetworkRequest(QUrl(QString(MCVLIST_URLBASE) + "versions.json"))); connect(vlistReply, SIGNAL(finished()), this, SLOT(list_downloaded())); } diff --git a/logic/net/DownloadJob.cpp b/logic/net/DownloadJob.cpp index b87d3dc9..cad9ae72 100644 --- a/logic/net/DownloadJob.cpp +++ b/logic/net/DownloadJob.cpp @@ -1,6 +1,6 @@ #include "DownloadJob.h" #include "pathutils.h" -#include "NetWorker.h" +#include "MultiMC.h" Download::Download (QUrl url, QString target_path, QString expected_md5 ) :Job() @@ -49,8 +49,8 @@ void Download::start() QNetworkRequest request ( m_url ); request.setRawHeader(QString("If-None-Match").toLatin1(), m_expected_md5.toLatin1()); - auto &worker = NetWorker::qnam(); - QNetworkReply * rep = worker.get ( request ); + auto worker = MMC->qnam(); + QNetworkReply * rep = worker->get ( request ); m_reply = QSharedPointer ( rep, &QObject::deleteLater ); connect ( rep, SIGNAL ( downloadProgress ( qint64,qint64 ) ), SLOT ( downloadProgress ( qint64,qint64 ) ) ); diff --git a/logic/net/NetWorker.cpp b/logic/net/NetWorker.cpp deleted file mode 100644 index c5943348..00000000 --- a/logic/net/NetWorker.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "NetWorker.h" -#include - -class NetWorker::Private -{ -public: - QNetworkAccessManager manager; -}; - -NetWorker::NetWorker ( QObject* parent ) : QObject ( parent ) -{ - d = new Private(); -} - -QNetworkAccessManager& NetWorker::qnam() -{ - auto & w = worker(); - return w.d->manager; -} - - -NetWorker& NetWorker::worker() -{ - static QThreadStorage storage; - if (!storage.hasLocalData()) - { - storage.setLocalData(new NetWorker()); - } - return *storage.localData(); -} diff --git a/logic/net/NetWorker.h b/logic/net/NetWorker.h deleted file mode 100644 index cf7e72e1..00000000 --- a/logic/net/NetWorker.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - _.ooo-._ - .OOOP _ '. - dOOOO (_) \ - OOOOOb | - OOOOOOb. | - OOOOOOOOb | - YOO(_)OOO / - 'OOOOOY _.' - '""""'' -*/ -#pragma once - -#include -#include - -class NetWorker : public QObject -{ - Q_OBJECT -public: - // for high level access to the sevices (preferred) - static NetWorker &worker(); - // for low-level access to the network manager object - static QNetworkAccessManager &qnam(); -public: - -private: - explicit NetWorker ( QObject* parent = 0 ); - class Private; - Private * d; -}; \ No newline at end of file diff --git a/logic/tasks/LoginTask.cpp b/logic/tasks/LoginTask.cpp index 4e2f0fb7..ad9de7f5 100644 --- a/logic/tasks/LoginTask.cpp +++ b/logic/tasks/LoginTask.cpp @@ -14,7 +14,7 @@ */ #include "LoginTask.h" -#include "logic/net/NetWorker.h" +#include "MultiMC.h" #include @@ -29,8 +29,8 @@ LoginTask::LoginTask( const UserInfo& uInfo, QObject* parent ) : Task(parent), u void LoginTask::executeTask() { setStatus("Logging in..."); - auto & worker = NetWorker::qnam(); - connect(&worker, SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*))); + auto worker = MMC->qnam(); + connect(worker, SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*))); QUrl loginURL("https://login.minecraft.net/"); QNetworkRequest netRequest(loginURL); @@ -41,7 +41,7 @@ void LoginTask::executeTask() params.addQueryItem("password", uInfo.password); params.addQueryItem("version", "13"); - netReply = worker.post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8()); + netReply = worker->post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8()); } void LoginTask::processNetReply(QNetworkReply *reply) diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 72b0f225..00000000 --- a/main.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* Copyright 2013 MultiMC Contributors - * - * Authors: Andrew Okin - * Orochimarufan - * - * 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 - -#include -#include - -#include "gui/mainwindow.h" -#include "gui/logindialog.h" -#include "gui/taskdialog.h" -#include "gui/consolewindow.h" - -#include "AppSettings.h" -#include "logic/lists/InstanceList.h" -#include "logic/tasks/LoginTask.h" -#include "logic/MinecraftProcess.h" - -#include "pathutils.h" -#include "cmdutils.h" - -#include "config.h" - -using namespace Util::Commandline; - -// Commandline instance launcher -class InstanceLauncher : public QObject -{ - Q_OBJECT -private: - InstanceList instances; - QString instId; - InstancePtr instance; - MinecraftProcess *proc; - ConsoleWindow *console; -public: - InstanceLauncher(QString instId) : QObject(), instances(globalSettings->get("InstanceDir").toString()) - { - this->instId = instId; - } - -private slots: - void onTerminated() - { - std::cout << "Minecraft exited" << std::endl; - QApplication::instance()->quit(); - } - - void onLoginComplete() - { - LoginTask * task = (LoginTask *) QObject::sender(); - auto result = task->getResult(); - proc = instance->prepareForLaunch(result.username, result.sessionID); - if(!proc) - { - //FIXME: report error - return; - } - console = new ConsoleWindow(); - console->show(); - - connect(proc, SIGNAL(ended()), SLOT(onTerminated())); - connect(proc, SIGNAL(log(QString,MessageLevel::Enum)), console, SLOT(write(QString,MessageLevel::Enum))); - - proc->launch(); - } - - void doLogin(const QString &errorMsg) - { - LoginDialog* loginDlg = new LoginDialog(nullptr, errorMsg); - loginDlg->exec(); - if (loginDlg->result() == QDialog::Accepted) - { - UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; - - TaskDialog* tDialog = new TaskDialog(nullptr); - LoginTask* loginTask = new LoginTask(uInfo, tDialog); - connect(loginTask, SIGNAL(succeeded()),SLOT(onLoginComplete()), Qt::QueuedConnection); - connect(loginTask, SIGNAL(failed(QString)),SLOT(doLogin(QString)), Qt::QueuedConnection); - tDialog->exec(loginTask); - } - //onLoginComplete(LoginResponse("Offline","Offline", 1)); - } - -public: - int launch() - { - std