aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/MacOSXBundleInfo.plist.in8
-rw-r--r--launcher/InstanceList.cpp11
-rw-r--r--launcher/LaunchController.cpp2
-rw-r--r--launcher/icons/IconList.cpp24
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp7
-rw-r--r--launcher/minecraft/launch/LauncherPartLaunch.cpp6
-rw-r--r--launcher/minecraft/mod/LocalModParseTask.cpp54
-rw-r--r--launcher/modplatform/flame/FlamePackIndex.cpp2
-rw-r--r--launcher/ui/MainWindow.cpp51
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.cpp19
-rw-r--r--launcher/ui/pages/instance/InstanceSettingsPage.ui29
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.cpp27
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.h1
-rw-r--r--program_info/App.entitlements14
14 files changed, 219 insertions, 36 deletions
diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in
index 0e3a43c6..9e663d31 100644
--- a/cmake/MacOSXBundleInfo.plist.in
+++ b/cmake/MacOSXBundleInfo.plist.in
@@ -2,10 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>NSCameraUsageDescription</key>
- <string>A Minecraft mod wants to access your camera.</string>
- <key>NSMicrophoneUsageDescription</key>
- <string>A Minecraft mod wants to access your microphone.</string>
+ <key>NSCameraUsageDescription</key>
+ <string>A Minecraft mod wants to access your camera.</string>
+ <key>NSMicrophoneUsageDescription</key>
+ <string>A Minecraft mod wants to access your microphone.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index 6e37e3d8..847d897e 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -38,6 +38,10 @@
#include "ExponentialSeries.h"
#include "WatchLock.h"
+#ifdef Q_OS_WIN32
+#include <Windows.h>
+#endif
+
const static int GROUP_FILE_FORMAT_VERSION = 1;
InstanceList::InstanceList(SettingsObjectPtr settings, const QString & instDir, QObject *parent)
@@ -851,13 +855,18 @@ Task * InstanceList::wrapInstanceTask(InstanceTask * task)
QString InstanceList::getStagedInstancePath()
{
QString key = QUuid::createUuid().toString();
- QString relPath = FS::PathCombine("_LAUNCHER_TEMP/" , key);
+ QString tempDir = ".LAUNCHER_TEMP/";
+ QString relPath = FS::PathCombine(tempDir, key);
QDir rootPath(m_instDir);
auto path = FS::PathCombine(m_instDir, relPath);
if(!rootPath.mkpath(relPath))
{
return QString();
}
+#ifdef Q_OS_WIN32
+ auto tempPath = FS::PathCombine(m_instDir, tempDir);
+ SetFileAttributesA(tempPath.toStdString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+#endif
return path;
}
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 4cb62e69..002c08b9 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -93,7 +93,7 @@ void LaunchController::decideAccount()
auto reply = CustomMessageBox::selectable(
m_parentWidget,
tr("No Accounts"),
- tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
+ tr("In order to play Minecraft, you must have at least one Mojang or Microsoft "
"account logged in. "
"Would you like to open the account manager to add an account now?"),
QMessageBox::Information,
diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp
index 584edd69..c269d10a 100644
--- a/launcher/icons/IconList.cpp
+++ b/launcher/icons/IconList.cpp
@@ -36,7 +36,7 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren
auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
for (auto file_info : file_info_list)
{
- builtinNames.insert(file_info.baseName());
+ builtinNames.insert(file_info.completeBaseName());
}
}
for(auto & builtinName : builtinNames)
@@ -51,6 +51,9 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren
connect(m_watcher.get(), SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString)));
directoryChanged(path);
+
+ // Forces the UI to update, so that lengthy icon names are shown properly from the start
+ emit iconUpdated({});
}
void IconList::directoryChanged(const QString &path)
@@ -94,7 +97,13 @@ void IconList::directoryChanged(const QString &path)
{
qDebug() << "Removing " << remove;
QFileInfo rmfile(remove);
- QString key = rmfile.baseName();
+ QString key = rmfile.completeBaseName();
+
+ QString suffix = rmfile.suffix();
+ // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well
+ if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif")
+ key = rmfile.fileName();
+
int idx = getIconIndex(key);
if (idx == -1)
continue;
@@ -117,8 +126,15 @@ void IconList::directoryChanged(const QString &path)
for (auto add : to_add)
{
qDebug() << "Adding " << add;
+
QFileInfo addfile(add);
- QString key = addfile.baseName();
+ QString key = addfile.completeBaseName();
+
+ QString suffix = addfile.suffix();
+ // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well
+ if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif")
+ key = addfile.fileName();
+
if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased))
{
m_watcher->addPath(add);
@@ -133,7 +149,7 @@ void IconList::fileChanged(const QString &path)
QFileInfo checkfile(path);
if (!checkfile.exists())
return;
- QString key = checkfile.baseName();
+ QString key = checkfile.completeBaseName();
int idx = getIconIndex(key);
if (idx == -1)
return;
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 3ba79178..e20dc24c 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -162,6 +162,11 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
m_settings->registerSetting("JoinServerOnLaunch", false);
m_settings->registerSetting("JoinServerOnLaunchAddress", "");
+ // Miscellaneous
+ auto miscellaneousOverride = m_settings->registerSetting("OverrideMiscellaneous", false);
+ m_settings->registerOverride(globalSettings->getSetting("CloseAfterLaunch"), miscellaneousOverride);
+ m_settings->registerOverride(globalSettings->getSetting("QuitAfterGameStop"), miscellaneousOverride);
+
m_components.reset(new PackProfile(this));
}
@@ -984,7 +989,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
{
process->setCensorFilter(createCensorFilterFromSession(session));
}
- if(APPLICATION->settings()->get("QuitAfterGameStop").toBool())
+ if(m_settings->get("QuitAfterGameStop").toBool())
{
auto step = new QuitAfterGameStop(pptr);
process->appendStep(step);
diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp
index 173f29b5..d7010355 100644
--- a/launcher/minecraft/launch/LauncherPartLaunch.cpp
+++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp
@@ -25,7 +25,8 @@
LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
{
- if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
+ auto instance = parent->instance();
+ if (instance->settings()->get("CloseAfterLaunch").toBool())
{
std::shared_ptr<QMetaObject::Connection> connection{new QMetaObject::Connection};
*connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, MessageLevel::Enum level) {
@@ -168,7 +169,8 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
}
case LoggedProcess::Finished:
{
- if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
+ auto instance = m_parent->instance();
+ if (instance->settings()->get("CloseAfterLaunch").toBool())
APPLICATION->showMainWindow();
m_parent->setPid(-1);
diff --git a/launcher/minecraft/mod/LocalModParseTask.cpp b/launcher/minecraft/mod/LocalModParseTask.cpp
index f01da8ae..631c3abb 100644
--- a/launcher/minecraft/mod/LocalModParseTask.cpp
+++ b/launcher/minecraft/mod/LocalModParseTask.cpp
@@ -8,6 +8,7 @@
#include <quazip/quazipfile.h>
#include <toml.h>
+#include "Json.h"
#include "settings/INIFile.h"
#include "FileSystem.h"
@@ -262,6 +263,44 @@ std::shared_ptr<ModDetails> ReadFabricModInfo(QByteArray contents)
return details;
}
+// https://github.com/QuiltMC/rfcs/blob/master/specification/0002-quilt.mod.json.md
+std::shared_ptr<ModDetails> ReadQuiltModInfo(QByteArray contents)
+{
+ QJsonParseError jsonError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
+ auto object = Json::requireObject(jsonDoc, "quilt.mod.json");
+ auto schemaVersion = Json::ensureInteger(object.value("schema_version"), 0, "Quilt schema_version");
+
+ std::shared_ptr<ModDetails> details = std::make_shared<ModDetails>();
+
+ // https://github.com/QuiltMC/rfcs/blob/be6ba280d785395fefa90a43db48e5bfc1d15eb4/specification/0002-quilt.mod.json.md
+ if (schemaVersion == 1)
+ {
+ auto modInfo = Json::requireObject(object.value("quilt_loader"), "Quilt mod info");
+
+ details->mod_id = Json::requireString(modInfo.value("id"), "Mod ID");
+ details->version = Json::requireString(modInfo.value("version"), "Mod version");
+
+ auto modMetadata = Json::ensureObject(modInfo.value("metadata"));
+
+ details->name = Json::ensureString(modMetadata.value("name"), details->mod_id);
+ details->description = Json::ensureString(modMetadata.value("description"));
+
+ auto modContributors = Json::ensureObject(modMetadata.value("contributors"));
+
+ // We don't really care about the role of a contributor here
+ details->authors += modContributors.keys();
+
+ auto modContact = Json::ensureObject(modMetadata.value("contact"));
+
+ if (modContact.contains("homepage"))
+ {
+ details->homeurl = Json::requireString(modContact.value("homepage"));
+ }
+ }
+ return details;
+}
+
std::shared_ptr<ModDetails> ReadForgeInfo(QByteArray contents)
{
std::shared_ptr<ModDetails> details = std::make_shared<ModDetails>();
@@ -391,7 +430,7 @@ void LocalModParseTask::processAsZip()
zip.close();
return;
}
- else if (zip.setCurrentFile("fabric.mod.json")) // TODO: Support quilt.mod.json
+ else if (zip.setCurrentFile("fabric.mod.json"))
{
if (!file.open(QIODevice::ReadOnly))
{
@@ -404,6 +443,19 @@ void LocalModParseTask::processAsZip()
zip.close();
return;
}
+ else if (zip.setCurrentFile("quilt.mod.json"))
+ {
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ zip.close();
+ return;
+ }
+
+ m_result->details = ReadQuiltModInfo(file.readAll());
+ file.close();
+ zip.close();
+ return;
+ }
else if (zip.setCurrentFile("forgeversion.properties"))
{
if (!file.open(QIODevice::ReadOnly))
diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp
index 549cace6..ac24c647 100644
--- a/launcher/modplatform/flame/FlamePackIndex.cpp
+++ b/launcher/modplatform/flame/FlamePackIndex.cpp
@@ -6,7 +6,7 @@ void Flame::loadIndexedPack(Flame::IndexedPack& pack, QJsonObject& obj)
{
pack.addonId = Json::requireInteger(obj, "id");
pack.name = Json::requireString(obj, "name");
- pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
+ pack.websiteUrl = Json::ensureString(Json::ensureObject(obj, "links"), "websiteUrl", "");
pack.description = Json::ensureString(obj, "summary", "");
auto logo = Json::requireObject(obj, "logo");
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index f34cf1ab..f016dc76 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -238,6 +238,9 @@ public:
TranslatedAction actionREDDIT;
TranslatedAction actionAbout;
+ TranslatedAction actionNoAccountsAdded;
+ TranslatedAction actionNoDefaultAccount;
+
QVector<TranslatedToolButton *> all_toolbuttons;
QWidget *centralWidget = nullptr;
@@ -746,6 +749,9 @@ public:
// disabled until we have an instance selected
instanceToolBar->setEnabled(false);
instanceToolBar->setMovable(true);
+ // Qt doesn't like vertical moving toolbars, so we have to force them...
+ // See https://github.com/PolyMC/PolyMC/issues/493
+ connect(instanceToolBar, &QToolBar::orientationChanged, [=](Qt::Orientation){ instanceToolBar->setOrientation(Qt::Vertical); });
instanceToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
instanceToolBar->setToolButtonStyle(Qt::ToolButtonTextOnly);
instanceToolBar->setFloatable(false);
@@ -828,7 +834,7 @@ public:
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
- void retranslateUi(QMainWindow *MainWindow)
+ void retranslateUi(MainWindow *MainWindow)
{
QString winTitle = tr("%1 - Version %2", "Launcher - Version X").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString());
MainWindow->setWindowTitle(winTitle);
@@ -848,6 +854,12 @@ public:
// submenu buttons
foldersMenuButton->setText(tr("Folders"));
helpMenuButton->setText(tr("Help"));
+
+ // playtime counter
+ if (MainWindow->m_statusCenter)
+ {
+ MainWindow->updateStatusCenter();
+ }
} // retranslateUi
};
@@ -950,6 +962,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
ui->mainToolBar->addWidget(spacer);
accountMenu = new QMenu(this);
+ // Use undocumented property... https://stackoverflow.com/questions/7121718/create-a-scrollbar-in-a-submenu-qt
+ accountMenu->setStyleSheet("QMenu { menu-scrollable: 1; }");
repopulateAccountsMenu();
@@ -1252,10 +1266,14 @@ void MainWindow::repopulateAccountsMenu()
if (accounts->count() <= 0)
{
- QAction *action = new QAction(tr("No accounts added!"), this);
- action->setEnabled(false);
- accountMenu->addAction(action);
- ui->profileMenu->addAction(action);
+ ui->all_actions.removeAll(&ui->actionNoAccountsAdded);
+ ui->actionNoAccountsAdded = TranslatedAction(this);
+ ui->actionNoAccountsAdded->setObjectName(QStringLiteral("actionNoAccountsAdded"));
+ ui->actionNoAccountsAdded.setTextId(QT_TRANSLATE_NOOP("MainWindow", "No accounts added!"));
+ ui->actionNoAccountsAdded->setEnabled(false);
+ accountMenu->addAction(ui->actionNoAccountsAdded);
+ ui->profileMenu->addAction(ui->actionNoAccountsAdded);
+ ui->all_actions.append(&ui->actionNoAccountsAdded);
}
else
{
@@ -1295,18 +1313,23 @@ void MainWindow::repopulateAccountsMenu()
accountMenu->addSeparator();
ui->profileMenu->addSeparator();
- QAction *action = new QAction(tr("No Default Account"), this);
- action->setCheckable(true);
- action->setIcon(APPLICATION->getThemedIcon("noaccount"));
- action->setData(-1);
- action->setShortcut(QKeySequence(tr("Ctrl+0")));
+ ui->all_actions.removeAll(&ui->actionNoDefaultAccount);
+ ui->actionNoDefaultAccount = TranslatedAction(this);
+ ui->actionNoDefaultAccount->setObjectName(QStringLiteral("actionNoDefaultAccount"));
+ ui->actionNoDefaultAccount.setTextId(QT_TRANSLATE_NOOP("MainWindow", "No Default Account"));
+ ui->actionNoDefaultAccount->setCheckable(true);
+ ui->actionNoDefaultAccount->setIcon(APPLICATION->getThemedIcon("noaccount"));
+ ui->actionNoDefaultAccount->setData(-1);
+ ui->actionNoDefaultAccount->setShortcut(QKeySequence(tr("Ctrl+0")));
if (!defaultAccount) {
- action->setChecked(true);
+ ui->actionNoDefaultAccount->setChecked(true);
}
- accountMenu->addAction(action);
- ui->profileMenu->addAction(action);
- connect(action, SIGNAL(triggered(bool)), SLOT(changeActiveAccount()));
+ accountMenu->addAction(ui->actionNoDefaultAccount);
+ ui->profileMenu->addAction(ui->actionNoDefaultAccount);
+ connect(ui->actionNoDefaultAccount, SIGNAL(triggered(bool)), SLOT(changeActiveAccount()));
+ ui->all_actions.append(&ui->actionNoDefaultAccount);
+ ui->actionNoDefaultAccount.retranslate();
accountMenu->addSeparator();
ui->profileMenu->addSeparator();
diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp
index a48c4d69..b4562843 100644
--- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp
+++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp
@@ -101,6 +101,20 @@ void InstanceSettingsPage::applySettings()
{
SettingsObject::Lock lock(m_settings);
+ // Miscellaneous
+ bool miscellaneous = ui->miscellaneousSettingsBox->isChecked();
+ m_settings->set("OverrideMiscellaneous", miscellaneous);
+ if (miscellaneous)
+ {
+ m_settings->set("CloseAfterLaunch", ui->closeAfterLaunchCheck->isChecked());
+ m_settings->set("QuitAfterGameStop", ui->quitAfterGameStopCheck->isChecked());
+ }
+ else
+ {
+ m_settings->reset("CloseAfterLaunch");
+ m_settings->reset("QuitAfterGameStop");
+ }
+
// Console
bool console = ui->consoleSettingsBox->isChecked();
m_settings->set("OverrideConsole", console);
@@ -247,6 +261,11 @@ void InstanceSettingsPage::applySettings()
void InstanceSettingsPage::loadSettings()
{
+ // Miscellaneous
+ ui->miscellaneousSettingsBox->setChecked(m_settings->get("OverrideMiscellaneous").toBool());
+ ui->closeAfterLaunchCheck->setChecked(m_settings->get("CloseAfterLaunch").toBool());
+ ui->quitAfterGameStopCheck->setChecked(m_settings->get("QuitAfterGameStop").toBool());
+
// Console
ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool());
ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool());
diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui
index 5db2d147..cb66b3ce 100644
--- a/launcher/ui/pages/instance/InstanceSettingsPage.ui
+++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui
@@ -350,6 +350,35 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="miscellaneousSettingsBox">
+ <property name="title">
+ <string>Miscellaneous</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_12">
+ <item>
+ <widget class="QCheckBox" name="closeAfterLaunchCheck">
+ <property name="text">
+ <string>Close the launcher after game window opens</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="quitAfterGameStopCheck">
+ <property name="text">
+ <string>Quit the launcher after game window closes</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacerMinecraft_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp
index e694ebe3..2cf17b32 100644
--- a/launcher/ui/pages/instance/ScreenshotsPage.cpp
+++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp
@@ -251,7 +251,7 @@ ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent)
m_model.reset(new QFileSystemModel());
m_filterModel.reset(new FilterModel());
m_filterModel->setSourceModel(m_model.get());
- m_model->setFilter(QDir::Files | QDir::Writable | QDir::Readable);
+ m_model->setFilter(QDir::Files);
m_model->setReadOnly(false);
m_model->setNameFilters({"*.png"});
m_model->setNameFilterDisables(false);
@@ -343,6 +343,29 @@ void ScreenshotsPage::onItemActivated(QModelIndex index)
DesktopServices::openFile(info.absoluteFilePath());
}
+void ScreenshotsPage::onCurrentSelectionChanged(const QItemSelection &selected)
+{
+ bool allReadable = !selected.isEmpty();
+ bool allWritable = !selected.isEmpty();
+
+ for (auto index : selected.indexes())
+ {
+ if (!index.isValid())
+ break;
+ auto info = m_model->fileInfo(index);
+ if (!info.isReadable())
+ allReadable = false;
+ if (!info.isWritable())
+ allWritable = false;
+ }
+
+ ui->actionUpload->setEnabled(allReadable);
+ ui->actionCopy_Image->setEnabled(allReadable);
+ ui->actionCopy_File_s->setEnabled(allReadable);
+ ui->actionDelete->setEnabled(allWritable);
+ ui->actionRename->setEnabled(allWritable);
+}
+
void ScreenshotsPage::on_actionView_Folder_triggered()
{
DesktopServices::openDirectory(m_folder, true);
@@ -503,6 +526,8 @@ void ScreenshotsPage::openedImpl()
if(idx.isValid())
{
ui->listView->setModel(m_filterModel.get());
+ connect(ui->listView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ScreenshotsPage::onCurrentSelectionChanged);
+ onCurrentSelectionChanged(ui->listView->selectionModel()->selection()); // set initial button enable states
ui->listView->setRootIndex(m_filterModel->mapFromSource(idx));
}
else
diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h
index 50cf1a17..c22706af 100644
--- a/launcher/ui/pages/instance/ScreenshotsPage.h
+++ b/launcher/ui/pages/instance/ScreenshotsPage.h
@@ -100,6 +100,7 @@ private slots:
void on_actionRename_triggered();
void on_actionView_Folder_triggered();
void onItemActivated(QModelIndex);
+ void onCurrentSelectionChanged(const QItemSelection &selected);
void ShowContextMenu(const QPoint &pos);
private:
diff --git a/program_info/App.entitlements b/program_info/App.entitlements
index 1850b990..b46e8ff2 100644
--- a/program_info/App.entitlements
+++ b/program_info/App.entitlements
@@ -2,11 +2,13 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>com.apple.security.cs.disable-library-validation</key>
- <true/>
- <key>com.apple.security.device.audio-input</key>
- <true/>
- <key>com.apple.security.device.camera</key>
- <true/>
+ <key>com.apple.security.cs.disable-library-validation</key>
+ <true/>
+ <key>com.apple.security.cs.allow-dyld-environment-variables</key>
+ <true/>
+ <key>com.apple.security.device.audio-input</key>
+ <true/>
+ <key>com.apple.security.device.camera</key>
+ <true/>
</dict>
</plist>