Skip to content

Commit a8e9681

Browse files
committed
Merge branch 'config-button-2026' into 'master'
Add list of config directories and ability to open them from the launcher Closes #7493 See merge request OpenMW/openmw!5139
2 parents ecb0cd1 + 911bfc1 commit a8e9681

File tree

12 files changed

+509
-14
lines changed

12 files changed

+509
-14
lines changed

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,14 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_CXX_COMPILER_FRONTEND_VARIANT
646646
add_compile_options("/wd${d}")
647647
endforeach(d)
648648

649+
set(WARNINGS_EXTRA
650+
4855 # implicit capture of 'this' via '[=]' is deprecated in 'version'
651+
)
652+
653+
foreach(d ${WARNINGS_EXTRA})
654+
add_compile_options("/w1${d}")
655+
endforeach(d)
656+
649657
if(OPENMW_MSVC_WERROR)
650658
add_compile_options("/WX")
651659
endif()

apps/launcher/maindialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void Launcher::MainDialog::createPages()
121121
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
122122
mGraphicsPage = new GraphicsPage(this);
123123
mImportPage = new ImportPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
124-
mSettingsPage = new SettingsPage(mGameSettings, this);
124+
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, this);
125125

126126
// Add the pages to the stacked widget
127127
pagesWidget->addWidget(mDataFilesPage);

apps/launcher/settingspage.cpp

Lines changed: 177 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#include <string>
66

77
#include <QCompleter>
8+
#include <QDesktopServices>
89
#include <QFileDialog>
10+
#include <QMenu>
911
#include <QString>
1012

1113
#include <components/config/gamesettings.hpp>
12-
14+
#include <components/files/qtconversion.hpp>
1315
#include <components/settings/values.hpp>
1416

1517
#include "utils/openalutil.hpp"
@@ -69,10 +71,39 @@ namespace
6971
}
7072
return 0;
7173
}
74+
75+
enum FileTypeRoles
76+
{
77+
Role_ThisFile = Qt::ItemDataRole::UserRole,
78+
Role_IsMainUserConfigDirectory,
79+
Role_ConfigDirectory,
80+
Role_LauncherLog,
81+
Role_OpenMWCfg,
82+
Role_OpenMWLog,
83+
Role_OpenMWCSLog,
84+
Role_SettingsCfg,
85+
};
86+
87+
struct FileType
88+
{
89+
FileTypeRoles itemDataRole;
90+
const char* name;
91+
bool showInAllConfigDirectories;
92+
};
93+
94+
const std::array configDirectoryFiles{
95+
FileType{ Role_LauncherLog, "launcher.log", false },
96+
FileType{ Role_OpenMWCfg, "openmw.cfg", true },
97+
FileType{ Role_OpenMWLog, "openmw.log", false },
98+
FileType{ Role_OpenMWCSLog, "openmw-cs.log", false },
99+
FileType{ Role_SettingsCfg, "settings.cfg", true },
100+
};
72101
}
73102

74-
Launcher::SettingsPage::SettingsPage(Config::GameSettings& gameSettings, QWidget* parent)
103+
Launcher::SettingsPage::SettingsPage(
104+
const Files::ConfigurationManager& configurationManager, Config::GameSettings& gameSettings, QWidget* parent)
75105
: QWidget(parent)
106+
, mCfgMgr(configurationManager)
76107
, mGameSettings(gameSettings)
77108
{
78109
setObjectName("SettingsPage");
@@ -91,6 +122,53 @@ Launcher::SettingsPage::SettingsPage(Config::GameSettings& gameSettings, QWidget
91122

92123
mCellNameCompleter.setModel(&mCellNameCompleterModel);
93124
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
125+
126+
connect(configsList, &QTreeWidget::itemActivated, this, &SettingsPage::slotOpenFile);
127+
128+
auto actionOpenDir = new QAction(tr("Open Directory"), configsList);
129+
connect(actionOpenDir, &QAction::triggered, [this]() {
130+
QUrl configFolderUrl = configsList->currentItem()->data(0, Role_ConfigDirectory).toUrl();
131+
QDesktopServices::openUrl(configFolderUrl);
132+
});
133+
134+
QList<QAction*> openFileActions;
135+
openFileActions.reserve(configDirectoryFiles.size());
136+
for (const auto& fileType : configDirectoryFiles)
137+
{
138+
QAction* action = new QAction(tr("Open %1").arg(fileType.name), configsList);
139+
connect(action, &QAction::triggered, [this, role = fileType.itemDataRole]() {
140+
QVariant fileUrl = configsList->currentItem()->data(0, role);
141+
if (fileUrl.isValid())
142+
QDesktopServices::openUrl(fileUrl.toUrl());
143+
});
144+
openFileActions.push_back(action);
145+
}
146+
147+
connect(configsList, &QTreeWidget::customContextMenuRequested, [=, this](const QPoint& pos) {
148+
if (configsList->currentItem())
149+
{
150+
QMenu contextMenu;
151+
152+
contextMenu.addAction(actionOpenDir);
153+
154+
bool topLevel = !configsList->currentItem()->parent();
155+
156+
for (qsizetype i = 0; i < openFileActions.size(); ++i)
157+
{
158+
if (configsList->currentItem()->data(0, Role_IsMainUserConfigDirectory).toBool()
159+
|| configDirectoryFiles[i].showInAllConfigDirectories)
160+
{
161+
QVariant fileUrl = configsList->currentItem()->data(0, configDirectoryFiles[i].itemDataRole);
162+
bool fileExists = fileUrl.isValid();
163+
openFileActions[i]->setEnabled(fileExists);
164+
openFileActions[i]->setVisible(topLevel || fileExists);
165+
contextMenu.addAction(openFileActions[i]);
166+
}
167+
}
168+
169+
contextMenu.exec(configsList->mapToGlobal(pos));
170+
}
171+
});
94172
}
95173

96174
void Launcher::SettingsPage::loadCellsForAutocomplete(QStringList cellNames)
@@ -331,6 +409,8 @@ bool Launcher::SettingsPage::loadSettings()
331409
screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString));
332410

333411
loadSettingBool(Settings::general().mNotifyOnSavedScreenshot, *notifyOnSavedScreenshotCheckBox);
412+
413+
populateLoadedConfigs();
334414
}
335415

336416
// Testing
@@ -351,6 +431,95 @@ bool Launcher::SettingsPage::loadSettings()
351431
return true;
352432
}
353433

434+
void Launcher::SettingsPage::populateLoadedConfigs()
435+
{
436+
configsList->clear();
437+
438+
for (const auto& path : mCfgMgr.getActiveConfigPaths())
439+
{
440+
QString configPath = QDir(Files::pathToQString(path)).absolutePath();
441+
QString toolTipText;
442+
443+
bool isMainUserConfig = path == mCfgMgr.getUserConfigPath();
444+
445+
if (path == mCfgMgr.getLocalPath())
446+
{
447+
if (isMainUserConfig)
448+
toolTipText = tr(
449+
"Local config directory used because it contains an openmw.cfg.\n"
450+
"Logs and settings changed through the launcher and in-game will be saved here.");
451+
else
452+
toolTipText = tr("Local config directory used because it contains an openmw.cfg.");
453+
}
454+
else if (path == mCfgMgr.getGlobalPath())
455+
{
456+
if (isMainUserConfig)
457+
toolTipText = tr(
458+
"Global config directory used because local directory did not contain an openmw.cfg.\n"
459+
"Logs and settings changed through the launcher and in-game will be saved here.\n"
460+
"This is typically a symptom of a broken OpenMW installation or bad package.");
461+
else
462+
toolTipText = tr("Global config directory used because local directory did not contain an openmw.cfg.");
463+
}
464+
else
465+
{
466+
Config::SettingValue configSetting;
467+
for (const auto& v : mGameSettings.values(QString("config")))
468+
{
469+
if (Files::pathFromQString(v.value) == path)
470+
{
471+
configSetting = v;
472+
break;
473+
}
474+
}
475+
476+
if (!configSetting.value.isEmpty())
477+
{
478+
const QFileInfo configPathInfo = QFileInfo(configSetting.context + "/openmw.cfg");
479+
if (isMainUserConfig)
480+
toolTipText = tr(
481+
"User config directory used because %1 contains the line config=%2.\n"
482+
"Logs and settings changed through the launcher and in-game will be saved here.")
483+
.arg(configPathInfo.absoluteFilePath(), configSetting.originalRepresentation);
484+
else
485+
toolTipText = tr("User config directory used because %1 contains the line config=%2.")
486+
.arg(configPathInfo.absoluteFilePath(), configSetting.originalRepresentation);
487+
}
488+
else if (isMainUserConfig)
489+
toolTipText = tr("Logs and settings changed through the launcher and in-game will be saved here.");
490+
}
491+
492+
QTreeWidgetItem* configItem = new QTreeWidgetItem(configsList);
493+
configItem->setText(0, configPath);
494+
configItem->setToolTip(0, toolTipText);
495+
configItem->setExpanded(true);
496+
497+
QUrl directoryUrl = QUrl::fromLocalFile(configPath);
498+
configItem->setData(0, Role_ThisFile, directoryUrl);
499+
configItem->setData(0, Role_IsMainUserConfigDirectory, isMainUserConfig);
500+
configItem->setData(0, Role_ConfigDirectory, directoryUrl);
501+
502+
for (const auto& fileType : configDirectoryFiles)
503+
{
504+
if ((isMainUserConfig || fileType.showInAllConfigDirectories)
505+
&& std::filesystem::exists(path / fileType.name))
506+
{
507+
QTreeWidgetItem* fileItem = new QTreeWidgetItem(configItem);
508+
fileItem->setText(0, fileType.name);
509+
510+
QUrl url = QUrl::fromLocalFile(Files::pathToQString(path / fileType.name));
511+
512+
fileItem->setData(0, Role_ThisFile, url);
513+
fileItem->setData(0, fileType.itemDataRole, url);
514+
fileItem->setData(0, Role_IsMainUserConfigDirectory, isMainUserConfig);
515+
fileItem->setData(0, Role_ConfigDirectory, directoryUrl);
516+
517+
configItem->setData(0, fileType.itemDataRole, url);
518+
}
519+
}
520+
}
521+
}
522+
354523
void Launcher::SettingsPage::saveSettings()
355524
{
356525
// Game mechanics
@@ -588,3 +757,9 @@ void Launcher::SettingsPage::slotDistantLandToggled(bool checked)
588757
activeGridObjectPagingCheckBox->setEnabled(checked);
589758
objectPagingMinSizeComboBox->setEnabled(checked);
590759
}
760+
761+
void Launcher::SettingsPage::slotOpenFile(QTreeWidgetItem* item)
762+
{
763+
QUrl configFolderUrl = item->data(0, Role_ThisFile).toUrl();
764+
QDesktopServices::openUrl(configFolderUrl);
765+
}

apps/launcher/settingspage.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <QCompleter>
55
#include <QStringListModel>
66

7+
#include <components/files/configurationmanager.hpp>
8+
79
#include "ui_settingspage.h"
810

911
namespace Config
@@ -18,7 +20,8 @@ namespace Launcher
1820
Q_OBJECT
1921

2022
public:
21-
explicit SettingsPage(Config::GameSettings& gameSettings, QWidget* parent = nullptr);
23+
explicit SettingsPage(const Files::ConfigurationManager& configurationManager,
24+
Config::GameSettings& gameSettings, QWidget* parent = nullptr);
2225

2326
bool loadSettings();
2427
void saveSettings();
@@ -35,8 +38,13 @@ namespace Launcher
3538
void slotShadowDistLimitToggled(bool checked);
3639
void slotDistantLandToggled(bool checked);
3740
void slotControllerMenusToggled(bool checked);
41+
void slotOpenFile(QTreeWidgetItem* item);
3842

3943
private:
44+
void populateLoadedConfigs();
45+
46+
const Files::ConfigurationManager& mCfgMgr;
47+
4048
Config::GameSettings& mGameSettings;
4149
QCompleter mCellNameCompleter;
4250
QStringListModel mCellNameCompleterModel;

apps/launcher/ui/mainwindow.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
</property>
5858
</spacer>
5959
</item>
60-
<item>
60+
<item alignment="Qt::AlignRight">
6161
<widget class="QDialogButtonBox" name="buttonBox">
6262
<property name="standardButtons">
6363
<set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>

apps/launcher/ui/settingspage.ui

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>741</width>
10-
<height>503</height>
10+
<height>524</height>
1111
</rect>
1212
</property>
1313
<layout class="QVBoxLayout" name="pageVerticalLayout">
@@ -1538,6 +1538,39 @@
15381538
</layout>
15391539
</widget>
15401540
</item>
1541+
<item>
1542+
<widget class="QGroupBox" name="configsGroup">
1543+
<property name="title">
1544+
<string>Active Config Directories</string>
1545+
</property>
1546+
<layout class="QVBoxLayout" name="verticalLayout_4">
1547+
<item>
1548+
<widget class="QTreeWidget" name="configsList">
1549+
<property name="sizePolicy">
1550+
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
1551+
<horstretch>0</horstretch>
1552+
<verstretch>0</verstretch>
1553+
</sizepolicy>
1554+
</property>
1555+
<property name="contextMenuPolicy">
1556+
<enum>Qt::CustomContextMenu</enum>
1557+
</property>
1558+
<property name="expandsOnDoubleClick">
1559+
<bool>false</bool>
1560+
</property>
1561+
<attribute name="headerVisible">
1562+
<bool>false</bool>
1563+
</attribute>
1564+
<column>
1565+
<property name="text">
1566+
<string notr="true">1</string>
1567+
</property>
1568+
</column>
1569+
</widget>
1570+
</item>
1571+
</layout>
1572+
</widget>
1573+
</item>
15411574
<item>
15421575
<spacer>
15431576
<property name="orientation">

files/lang/launcher_de.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,46 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
574574
<source>Text file (*.txt)</source>
575575
<translation type="unfinished"></translation>
576576
</message>
577+
<message>
578+
<source>Open Directory</source>
579+
<translation type="unfinished"></translation>
580+
</message>
581+
<message>
582+
<source>Open %1</source>
583+
<translation type="unfinished"></translation>
584+
</message>
585+
<message>
586+
<source>Local config directory used because it contains an openmw.cfg.
587+
Logs and settings changed through the launcher and in-game will be saved here.</source>
588+
<translation type="unfinished"></translation>
589+
</message>
590+
<message>
591+
<source>Local config directory used because it contains an openmw.cfg.</source>
592+
<translation type="unfinished"></translation>
593+
</message>
594+
<message>
595+
<source>Logs and settings changed through the launcher and in-game will be saved here.</source>
596+
<translation type="unfinished"></translation>
597+
</message>
598+
<message>
599+
<source>Global config directory used because local directory did not contain an openmw.cfg.
600+
Logs and settings changed through the launcher and in-game will be saved here.
601+
This is typically a symptom of a broken OpenMW installation or bad package.</source>
602+
<translation type="unfinished"></translation>
603+
</message>
604+
<message>
605+
<source>Global config directory used because local directory did not contain an openmw.cfg.</source>
606+
<translation type="unfinished"></translation>
607+
</message>
608+
<message>
609+
<source>User config directory used because %1 contains the line config=%2.
610+
Logs and settings changed through the launcher and in-game will be saved here.</source>
611+
<translation type="unfinished"></translation>
612+
</message>
613+
<message>
614+
<source>User config directory used because %1 contains the line config=%2.</source>
615+
<translation type="unfinished"></translation>
616+
</message>
577617
</context>
578618
<context>
579619
<name>MainWindow</name>
@@ -1475,5 +1515,9 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
14751515
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
14761516
<translation type="unfinished"></translation>
14771517
</message>
1518+
<message>
1519+
<source>Active Config Directories</source>
1520+
<translation type="unfinished"></translation>
1521+
</message>
14781522
</context>
14791523
</TS>

0 commit comments

Comments
 (0)