From e883cf2359428a46970437d0fa5fee676f130fcd Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 2 Jul 2021 09:19:55 +1000 Subject: [PATCH] GH-2529 Move data path on macOS to MultiMC.app/Data macOS seems to dislike changing files in the APPBUNDLE.app/Contents directory because it has to re-scan the directory every launch. As a result, large amounts of data there seems to cause freezes of MultiMC. Moving the default location outside of this directory, and thus the data, stops these freezes. There is also a dialogue when the user first opens the app that asks them if they'd like to migrate their data folder, if they select yes it will move it, and if they select no it will not move it and allow them to move it later with an option in settings. --- application/MultiMC.cpp | 61 ++++++++++++++++++++++++ application/pages/global/MultiMCPage.cpp | 17 +++++++ application/pages/global/MultiMCPage.h | 1 + application/pages/global/MultiMCPage.ui | 7 +++ 4 files changed, 86 insertions(+) diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index 2dd4f83fd..932c7a765 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -262,6 +262,10 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); dataPath = xdgDataHome + "/multimc"; adjustedBy += "XDG standard " + dataPath; +#elif defined(Q_OS_MAC) + QDir foo(FS::PathCombine(applicationDirPath(), "../../Data")); + dataPath = foo.absolutePath(); + adjustedBy += "Fallback to special Mac location " + dataPath; #else dataPath = applicationDirPath(); adjustedBy += "Fallback to binary path " + dataPath; @@ -306,6 +310,63 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) return; } +#if defined(Q_OS_MAC) + // move user data to new location if on macOS and it still exists in Contents/MacOS + QDir fi(applicationDirPath()); + QString originalData = fi.absolutePath(); + // if the config file exists in Contents/MacOS, then user data is still there and needs to moved + if (QFileInfo::exists(FS::PathCombine(originalData, "multimc.cfg"))) + { + if (!QFileInfo::exists(FS::PathCombine(originalData, "dontmovemacdata"))) + { + QMessageBox::StandardButton askMoveDialogue; + askMoveDialogue = QMessageBox::question(nullptr, "MultiMC 5", "Would you like to move application data to a new data location? It will improve MultiMC's performance, but if you switch to older versions it will look like instances have disappeared. If you select no, you can migrate later in settings. You should select yes unless you're commonly switching between different versions of MultiMC (eg. develop and stable).", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (askMoveDialogue == QMessageBox::Yes) + { + qDebug() << "On macOS and found config file in old location, moving user data..."; + QDir dir; + QStringList dataFiles { + "*.log", // MultiMC-@.log + "accounts.json", + "accounts", + "assets", + "cache", + "icons", + "instances", + "libraries", + "meta", + "metacache", + "mods", + "multimc.cfg", + "themes", + "translations" + }; + QDirIterator files(originalData, dataFiles); + while (files.hasNext()) { + QString filePath(files.next()); + QString fileName(files.fileName()); + if (!dir.rename(filePath, FS::PathCombine(dataPath, fileName))) + { + qWarning() << "Failed to move " << fileName; + } + } + } + else + { + dataPath = originalData; + QDir::setCurrent(dataPath); + QFile file(originalData + "/dontmovemacdata"); + file.open(QIODevice::WriteOnly); + } + } + else + { + dataPath = originalData; + QDir::setCurrent(dataPath); + } + } +#endif + /* * Establish the mechanism for communication with an already running MultiMC that uses the same data path. * If there is one, tell it what the user actually wanted to do and exit. diff --git a/application/pages/global/MultiMCPage.cpp b/application/pages/global/MultiMCPage.cpp index 80d5c5442..d383e6edb 100644 --- a/application/pages/global/MultiMCPage.cpp +++ b/application/pages/global/MultiMCPage.cpp @@ -29,6 +29,9 @@ #include "BuildConfig.h" #include "themes/ITheme.h" +#include +#include + // FIXME: possibly move elsewhere enum InstSortMode { @@ -78,6 +81,13 @@ MultiMCPage::MultiMCPage(QWidget *parent) : QWidget(parent), ui(new Ui::MultiMCP } connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview())); connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview())); + + //move mac data button + QFile file(QDir::current().absolutePath() + "/dontmovemacdata"); + if (!file.exists()) + { + ui->migrateDataFolderMacBtn->setVisible(false); + } } MultiMCPage::~MultiMCPage() @@ -146,6 +156,13 @@ void MultiMCPage::on_modsDirBrowseBtn_clicked() ui->modsDirTextBox->setText(cooked_dir); } } +void MultiMCPage::on_migrateDataFolderMacBtn_clicked() +{ + QFile file(QDir::current().absolutePath() + "/dontmovemacdata"); + file.remove(); + QProcess::startDetached(qApp->arguments()[0]); + qApp->quit(); +} void MultiMCPage::refreshUpdateChannelList() { diff --git a/application/pages/global/MultiMCPage.h b/application/pages/global/MultiMCPage.h index e81832eb3..fae75bf22 100644 --- a/application/pages/global/MultiMCPage.h +++ b/application/pages/global/MultiMCPage.h @@ -67,6 +67,7 @@ slots: void on_instDirBrowseBtn_clicked(); void on_modsDirBrowseBtn_clicked(); void on_iconsDirBrowseBtn_clicked(); + void on_migrateDataFolderMacBtn_clicked(); /*! * Updates the list of update channels in the combo box. diff --git a/application/pages/global/MultiMCPage.ui b/application/pages/global/MultiMCPage.ui index ea0349193..4ad202425 100644 --- a/application/pages/global/MultiMCPage.ui +++ b/application/pages/global/MultiMCPage.ui @@ -157,6 +157,13 @@ + + + + Move MultiMC data to new location (will restart MultiMC) + + +