Rework launcher UI
@ -1,490 +0,0 @@
|
||||
#include "advancedpage.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <QCompleter>
|
||||
#include <QFileDialog>
|
||||
#include <QString>
|
||||
|
||||
#include <components/config/gamesettings.hpp>
|
||||
|
||||
#include "utils/openalutil.hpp"
|
||||
|
||||
Launcher::AdvancedPage::AdvancedPage(Config::GameSettings& gameSettings, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, mGameSettings(gameSettings)
|
||||
{
|
||||
setObjectName("AdvancedPage");
|
||||
setupUi(this);
|
||||
|
||||
for (const std::string& name : Launcher::enumerateOpenALDevices())
|
||||
{
|
||||
audioDeviceSelectorComboBox->addItem(QString::fromStdString(name), QString::fromStdString(name));
|
||||
}
|
||||
for (const std::string& name : Launcher::enumerateOpenALDevicesHrtf())
|
||||
{
|
||||
hrtfProfileSelectorComboBox->addItem(QString::fromStdString(name), QString::fromStdString(name));
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
|
||||
mCellNameCompleter.setModel(&mCellNameCompleterModel);
|
||||
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames)
|
||||
{
|
||||
// Update the list of suggestions for the "Start default character at" field
|
||||
mCellNameCompleterModel.setStringList(cellNames);
|
||||
mCellNameCompleter.setCompletionMode(QCompleter::PopupCompletion);
|
||||
mCellNameCompleter.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state)
|
||||
{
|
||||
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
||||
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked()
|
||||
{
|
||||
QString scriptFile = QFileDialog::getOpenFileName(
|
||||
this, QObject::tr("Select script file"), QDir::currentPath(), QString(tr("Text file (*.txt)")));
|
||||
|
||||
if (scriptFile.isEmpty())
|
||||
return;
|
||||
|
||||
QFileInfo info(scriptFile);
|
||||
|
||||
if (!info.exists() || !info.isReadable())
|
||||
return;
|
||||
|
||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
runScriptAfterStartupField->setText(path);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr double CellSizeInUnits = 8192;
|
||||
|
||||
double convertToCells(double unitRadius)
|
||||
{
|
||||
return unitRadius / CellSizeInUnits;
|
||||
}
|
||||
|
||||
int convertToUnits(double CellGridRadius)
|
||||
{
|
||||
return static_cast<int>(CellSizeInUnits * CellGridRadius);
|
||||
}
|
||||
}
|
||||
|
||||
bool Launcher::AdvancedPage::loadSettings()
|
||||
{
|
||||
// Game mechanics
|
||||
{
|
||||
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||
loadSettingBool(classicCalmSpellsCheckBox, "classic calm spells behavior", "Game");
|
||||
loadSettingBool(
|
||||
requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||
loadSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||
loadSettingBool(avoidCollisionsCheckBox, "NPCs avoid collisions", "Game");
|
||||
int unarmedFactorsStrengthIndex = Settings::Manager::getInt("strength influences hand to hand", "Game");
|
||||
if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2)
|
||||
unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex);
|
||||
loadSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
||||
loadSettingBool(enableNavigatorCheckBox, "enable", "Navigator");
|
||||
int numPhysicsThreads = Settings::Manager::getInt("async num threads", "Physics");
|
||||
if (numPhysicsThreads >= 0)
|
||||
physicsThreadsSpinBox->setValue(numPhysicsThreads);
|
||||
loadSettingBool(allowNPCToFollowOverWaterSurfaceCheckBox, "allow actors to follow over water surface", "Game");
|
||||
loadSettingBool(unarmedCreatureAttacksDamageArmorCheckBox, "unarmed creature attacks damage armor", "Game");
|
||||
const int actorCollisionShapeType = Settings::Manager::getInt("actor collision shape type", "Game");
|
||||
if (0 <= actorCollisionShapeType && actorCollisionShapeType < actorCollisonShapeTypeComboBox->count())
|
||||
actorCollisonShapeTypeComboBox->setCurrentIndex(actorCollisionShapeType);
|
||||
}
|
||||
|
||||
// Visuals
|
||||
{
|
||||
loadSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders");
|
||||
loadSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders");
|
||||
loadSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders");
|
||||
loadSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders");
|
||||
loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||
loadSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
||||
loadSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
||||
if (Settings::Manager::getInt("antialiasing", "Video") == 0)
|
||||
{
|
||||
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
loadSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
||||
loadSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
|
||||
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||
connect(animSourcesCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotAnimSourcesToggled);
|
||||
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||
if (animSourcesCheckBox->checkState() != Qt::Unchecked)
|
||||
{
|
||||
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||
}
|
||||
loadSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
||||
loadSettingBool(smoothMovementCheckBox, "smooth movement", "Game");
|
||||
|
||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
||||
if (distantTerrain && objectPaging)
|
||||
{
|
||||
distantLandCheckBox->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain");
|
||||
viewingDistanceComboBox->setValue(convertToCells(Settings::Manager::getInt("viewing distance", "Camera")));
|
||||
objectPagingMinSizeComboBox->setValue(Settings::Manager::getDouble("object paging min size", "Terrain"));
|
||||
|
||||
loadSettingBool(nightDaySwitchesCheckBox, "day night switches", "Game");
|
||||
|
||||
connect(postprocessEnabledCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotPostProcessToggled);
|
||||
loadSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing");
|
||||
loadSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing");
|
||||
postprocessHDRTimeComboBox->setValue(Settings::Manager::getDouble("auto exposure speed", "Post Processing"));
|
||||
|
||||
connect(skyBlendingCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotSkyBlendingToggled);
|
||||
loadSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
loadSettingBool(exponentialFogCheckBox, "exponential fog", "Fog");
|
||||
loadSettingBool(skyBlendingCheckBox, "sky blending", "Fog");
|
||||
skyBlendingStartComboBox->setValue(Settings::Manager::getDouble("sky blending start", "Fog"));
|
||||
}
|
||||
|
||||
// Audio
|
||||
{
|
||||
const std::string& selectedAudioDevice = Settings::Manager::getString("device", "Sound");
|
||||
if (selectedAudioDevice.empty() == false)
|
||||
{
|
||||
int audioDeviceIndex = audioDeviceSelectorComboBox->findData(QString::fromStdString(selectedAudioDevice));
|
||||
if (audioDeviceIndex != -1)
|
||||
{
|
||||
audioDeviceSelectorComboBox->setCurrentIndex(audioDeviceIndex);
|
||||
}
|
||||
}
|
||||
int hrtfEnabledIndex = Settings::Manager::getInt("hrtf enable", "Sound");
|
||||
if (hrtfEnabledIndex >= -1 && hrtfEnabledIndex <= 1)
|
||||
{
|
||||
enableHRTFComboBox->setCurrentIndex(hrtfEnabledIndex + 1);
|
||||
}
|
||||
const std::string& selectedHRTFProfile = Settings::Manager::getString("hrtf", "Sound");
|
||||
if (selectedHRTFProfile.empty() == false)
|
||||
{
|
||||
int hrtfProfileIndex = hrtfProfileSelectorComboBox->findData(QString::fromStdString(selectedHRTFProfile));
|
||||
if (hrtfProfileIndex != -1)
|
||||
{
|
||||
hrtfProfileSelectorComboBox->setCurrentIndex(hrtfProfileIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interface Changes
|
||||
{
|
||||
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||
loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||
loadSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI");
|
||||
int showOwnedIndex = Settings::Manager::getInt("show owned", "Game");
|
||||
// Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid.
|
||||
if (showOwnedIndex >= 0 && showOwnedIndex <= 3)
|
||||
showOwnedComboBox->setCurrentIndex(showOwnedIndex);
|
||||
loadSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI");
|
||||
loadSettingBool(useZoomOnMapCheckBox, "allow zooming", "Map");
|
||||
loadSettingBool(graphicHerbalismCheckBox, "graphic herbalism", "Game");
|
||||
scalingSpinBox->setValue(Settings::Manager::getFloat("scaling factor", "GUI"));
|
||||
fontSizeSpinBox->setValue(Settings::Manager::getInt("font size", "GUI"));
|
||||
}
|
||||
|
||||
// Bug fixes
|
||||
{
|
||||
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
loadSettingBool(
|
||||
trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
{
|
||||
// Saves
|
||||
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||
loadSettingInt(maximumQuicksavesComboBox, "max quicksaves", "Saves");
|
||||
|
||||
// Other Settings
|
||||
QString screenshotFormatString
|
||||
= QString::fromStdString(Settings::Manager::getString("screenshot format", "General")).toUpper();
|
||||
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
||||
screenshotFormatComboBox->addItem(screenshotFormatString);
|
||||
screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString));
|
||||
|
||||
loadSettingBool(notifyOnSavedScreenshotCheckBox, "notify on saved screenshot", "General");
|
||||
}
|
||||
|
||||
// Testing
|
||||
{
|
||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
||||
bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1;
|
||||
if (skipMenu)
|
||||
{
|
||||
skipMenuCheckBox->setCheckState(Qt::Checked);
|
||||
}
|
||||
startDefaultCharacterAtLabel->setEnabled(skipMenu);
|
||||
startDefaultCharacterAtField->setEnabled(skipMenu);
|
||||
|
||||
startDefaultCharacterAtField->setText(mGameSettings.value("start"));
|
||||
runScriptAfterStartupField->setText(mGameSettings.value("script-run"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::saveSettings()
|
||||
{
|
||||
// Game mechanics
|
||||
{
|
||||
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||
saveSettingBool(classicCalmSpellsCheckBox, "classic calm spells behavior", "Game");
|
||||
saveSettingBool(
|
||||
requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||
saveSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||
saveSettingBool(avoidCollisionsCheckBox, "NPCs avoid collisions", "Game");
|
||||
saveSettingInt(unarmedFactorsStrengthComboBox, "strength influences hand to hand", "Game");
|
||||
saveSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
||||
saveSettingBool(enableNavigatorCheckBox, "enable", "Navigator");
|
||||
saveSettingInt(physicsThreadsSpinBox, "async num threads", "Physics");
|
||||
saveSettingBool(allowNPCToFollowOverWaterSurfaceCheckBox, "allow actors to follow over water surface", "Game");
|
||||
saveSettingBool(unarmedCreatureAttacksDamageArmorCheckBox, "unarmed creature attacks damage armor", "Game");
|
||||
saveSettingInt(actorCollisonShapeTypeComboBox, "actor collision shape type", "Game");
|
||||
}
|
||||
|
||||
// Visuals
|
||||
{
|
||||
saveSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders");
|
||||
saveSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders");
|
||||
saveSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders");
|
||||
saveSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders");
|
||||
saveSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||
saveSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
saveSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
||||
saveSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
||||
saveSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
||||
saveSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
|
||||
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||
saveSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
||||
saveSettingBool(smoothMovementCheckBox, "smooth movement", "Game");
|
||||
|
||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
||||
const bool wantDistantLand = distantLandCheckBox->checkState();
|
||||
if (wantDistantLand != (distantTerrain && objectPaging))
|
||||
{
|
||||
Settings::Manager::setBool("distant terrain", "Terrain", wantDistantLand);
|
||||
Settings::Manager::setBool("object paging", "Terrain", wantDistantLand);
|
||||
}
|
||||
|
||||
saveSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain");
|
||||
int viewingDistance = convertToUnits(viewingDistanceComboBox->value());
|
||||
if (viewingDistance != Settings::Manager::getInt("viewing distance", "Camera"))
|
||||
{
|
||||
Settings::Manager::setInt("viewing distance", "Camera", viewingDistance);
|
||||
}
|
||||
double objectPagingMinSize = objectPagingMinSizeComboBox->value();
|
||||
if (objectPagingMinSize != Settings::Manager::getDouble("object paging min size", "Terrain"))
|
||||
Settings::Manager::setDouble("object paging min size", "Terrain", objectPagingMinSize);
|
||||
|
||||
saveSettingBool(nightDaySwitchesCheckBox, "day night switches", "Game");
|
||||
|
||||
saveSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing");
|
||||
saveSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing");
|
||||
double hdrExposureTime = postprocessHDRTimeComboBox->value();
|
||||
if (hdrExposureTime != Settings::Manager::getDouble("auto exposure speed", "Post Processing"))
|
||||
Settings::Manager::setDouble("auto exposure speed", "Post Processing", hdrExposureTime);
|
||||
|
||||
saveSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
saveSettingBool(exponentialFogCheckBox, "exponential fog", "Fog");
|
||||
saveSettingBool(skyBlendingCheckBox, "sky blending", "Fog");
|
||||
Settings::Manager::setDouble("sky blending start", "Fog", skyBlendingStartComboBox->value());
|
||||
}
|
||||
|
||||
// Audio
|
||||
{
|
||||
int audioDeviceIndex = audioDeviceSelectorComboBox->currentIndex();
|
||||
const std::string& prevAudioDevice = Settings::Manager::getString("device", "Sound");
|
||||
if (audioDeviceIndex != 0)
|
||||
{
|
||||
const std::string& newAudioDevice = audioDeviceSelectorComboBox->currentText().toUtf8().constData();
|
||||
if (newAudioDevice != prevAudioDevice)
|
||||
Settings::Manager::setString("device", "Sound", newAudioDevice);
|
||||
}
|
||||
else if (!prevAudioDevice.empty())
|
||||
{
|
||||
Settings::Manager::setString("device", "Sound", {});
|
||||
}
|
||||
int hrtfEnabledIndex = enableHRTFComboBox->currentIndex() - 1;
|
||||
if (hrtfEnabledIndex != Settings::Manager::getInt("hrtf enable", "Sound"))
|
||||
{
|
||||
Settings::Manager::setInt("hrtf enable", "Sound", hrtfEnabledIndex);
|
||||
}
|
||||
int selectedHRTFProfileIndex = hrtfProfileSelectorComboBox->currentIndex();
|
||||
const std::string& prevHRTFProfile = Settings::Manager::getString("hrtf", "Sound");
|
||||
if (selectedHRTFProfileIndex != 0)
|
||||
{
|
||||
const std::string& newHRTFProfile = hrtfProfileSelectorComboBox->currentText().toUtf8().constData();
|
||||
if (newHRTFProfile != prevHRTFProfile)
|
||||
Settings::Manager::setString("hrtf", "Sound", newHRTFProfile);
|
||||
}
|
||||
else if (!prevHRTFProfile.empty())
|
||||
{
|
||||
Settings::Manager::setString("hrtf", "Sound", {});
|
||||
}
|
||||
}
|
||||
|
||||
// Interface Changes
|
||||
{
|
||||
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||
saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||
saveSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI");
|
||||
saveSettingInt(showOwnedComboBox, "show owned", "Game");
|
||||
saveSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI");
|
||||
saveSettingBool(useZoomOnMapCheckBox, "allow zooming", "Map");
|
||||
saveSettingBool(graphicHerbalismCheckBox, "graphic herbalism", "Game");
|
||||
|
||||
float uiScalingFactor = scalingSpinBox->value();
|
||||
if (uiScalingFactor != Settings::Manager::getFloat("scaling factor", "GUI"))
|
||||
Settings::Manager::setFloat("scaling factor", "GUI", uiScalingFactor);
|
||||
|
||||
int fontSize = fontSizeSpinBox->value();
|
||||
if (fontSize != Settings::Manager::getInt("font size", "GUI"))
|
||||
Settings::Manager::setInt("font size", "GUI", fontSize);
|
||||
}
|
||||
|
||||
// Bug fixes
|
||||
{
|
||||
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
saveSettingBool(
|
||||
trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
{
|
||||
// Saves Settings
|
||||
saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||
saveSettingInt(maximumQuicksavesComboBox, "max quicksaves", "Saves");
|
||||
|
||||
// Other Settings
|
||||
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
|
||||
if (screenshotFormatString != Settings::Manager::getString("screenshot format", "General"))
|
||||
Settings::Manager::setString("screenshot format", "General", screenshotFormatString);
|
||||
|
||||
saveSettingBool(notifyOnSavedScreenshotCheckBox, "notify on saved screenshot", "General");
|
||||
}
|
||||
|
||||
// Testing
|
||||
{
|
||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
||||
int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked;
|
||||
if (skipMenu != mGameSettings.value("skip-menu").toInt())
|
||||
mGameSettings.setValue("skip-menu", QString::number(skipMenu));
|
||||
|
||||
QString startCell = startDefaultCharacterAtField->text();
|
||||
if (startCell != mGameSettings.value("start"))
|
||||
{
|
||||
mGameSettings.setValue("start", startCell);
|
||||
}
|
||||
QString scriptRun = runScriptAfterStartupField->text();
|
||||
if (scriptRun != mGameSettings.value("script-run"))
|
||||
mGameSettings.setValue("script-run", scriptRun);
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::loadSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
if (Settings::Manager::getBool(setting, group))
|
||||
checkbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::saveSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
bool cValue = checkbox->checkState();
|
||||
if (cValue != Settings::Manager::getBool(setting, group))
|
||||
Settings::Manager::setBool(setting, group, cValue);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::loadSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
int currentIndex = Settings::Manager::getInt(setting, group);
|
||||
comboBox->setCurrentIndex(currentIndex);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::saveSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
int currentIndex = comboBox->currentIndex();
|
||||
if (currentIndex != Settings::Manager::getInt(setting, group))
|
||||
Settings::Manager::setInt(setting, group, currentIndex);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::loadSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
int value = Settings::Manager::getInt(setting, group);
|
||||
spinBox->setValue(value);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::saveSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
int value = spinBox->value();
|
||||
if (value != Settings::Manager::getInt(setting, group))
|
||||
Settings::Manager::setInt(setting, group, value);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::slotLoadedCellsChanged(QStringList cellNames)
|
||||
{
|
||||
loadCellsForAutocomplete(cellNames);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::slotAnimSourcesToggled(bool checked)
|
||||
{
|
||||
weaponSheathingCheckBox->setEnabled(checked);
|
||||
shieldSheathingCheckBox->setEnabled(checked);
|
||||
if (!checked)
|
||||
{
|
||||
weaponSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||
shieldSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::slotPostProcessToggled(bool checked)
|
||||
{
|
||||
postprocessTransparentPostpassCheckBox->setEnabled(checked);
|
||||
postprocessHDRTimeComboBox->setEnabled(checked);
|
||||
postprocessHDRTimeLabel->setEnabled(checked);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::slotSkyBlendingToggled(bool checked)
|
||||
{
|
||||
skyBlendingStartComboBox->setEnabled(checked);
|
||||
skyBlendingStartLabel->setEnabled(checked);
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
#ifndef ADVANCEDPAGE_H
|
||||
#define ADVANCEDPAGE_H
|
||||
|
||||
#include <QCompleter>
|
||||
#include <QStringListModel>
|
||||
|
||||
#include "ui_advancedpage.h"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
class GameSettings;
|
||||
}
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
class AdvancedPage : public QWidget, private Ui::AdvancedPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AdvancedPage(Config::GameSettings& gameSettings, QWidget* parent = nullptr);
|
||||
|
||||
bool loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
public slots:
|
||||
void slotLoadedCellsChanged(QStringList cellNames);
|
||||
|
||||
private slots:
|
||||
void on_skipMenuCheckBox_stateChanged(int state);
|
||||
void on_runScriptAfterStartupBrowseButton_clicked();
|
||||
void slotAnimSourcesToggled(bool checked);
|
||||
void slotPostProcessToggled(bool checked);
|
||||
void slotSkyBlendingToggled(bool checked);
|
||||
|
||||
private:
|
||||
Config::GameSettings& mGameSettings;
|
||||
QCompleter mCellNameCompleter;
|
||||
QStringListModel mCellNameCompleterModel;
|
||||
|
||||
/**
|
||||
* Load the cells associated with the given content files for use in autocomplete
|
||||
* @param filePaths the file paths of the content files to be examined
|
||||
*/
|
||||
void loadCellsForAutocomplete(QStringList filePaths);
|
||||
static void loadSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group);
|
||||
static void saveSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group);
|
||||
static void loadSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group);
|
||||
static void saveSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group);
|
||||
static void loadSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group);
|
||||
static void saveSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group);
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,229 @@
|
||||
#include "importpage.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <components/files/qtconversion.hpp>
|
||||
|
||||
#include "utils/textinputdialog.hpp"
|
||||
|
||||
using namespace Process;
|
||||
|
||||
Launcher::ImportPage::ImportPage(Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings,
|
||||
Config::LauncherSettings& launcherSettings, MainDialog* parent)
|
||||
: QWidget(parent)
|
||||
, mCfgMgr(cfg)
|
||||
, mGameSettings(gameSettings)
|
||||
, mLauncherSettings(launcherSettings)
|
||||
, mMain(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
mWizardInvoker = new ProcessInvoker();
|
||||
mImporterInvoker = new ProcessInvoker();
|
||||
resetProgressBar();
|
||||
|
||||
connect(mWizardInvoker->getProcess(), &QProcess::started, this, &ImportPage::wizardStarted);
|
||||
|
||||
connect(mWizardInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&ImportPage::wizardFinished);
|
||||
|
||||
connect(mImporterInvoker->getProcess(), &QProcess::started, this, &ImportPage::importerStarted);
|
||||
|
||||
connect(mImporterInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&ImportPage::importerFinished);
|
||||
|
||||
// Detect Morrowind configuration files
|
||||
QStringList iniPaths;
|
||||
|
||||
for (const QString& path : mGameSettings.getDataDirs())
|
||||
{
|
||||
QDir dir(path);
|
||||
dir.setPath(dir.canonicalPath()); // Resolve symlinks
|
||||
|
||||
if (dir.exists(QString("Morrowind.ini")))
|
||||
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
||||
else
|
||||
{
|
||||
if (!dir.cdUp())
|
||||
continue; // Cannot move from Data Files
|
||||
|
||||
if (dir.exists(QString("Morrowind.ini")))
|
||||
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
||||
}
|
||||
}
|
||||
|
||||
if (!iniPaths.isEmpty())
|
||||
{
|
||||
settingsComboBox->addItems(iniPaths);
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
importerButton->setEnabled(false);
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
Launcher::ImportPage::~ImportPage()
|
||||
{
|
||||
delete mWizardInvoker;
|
||||
delete mImporterInvoker;
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::on_wizardButton_clicked()
|
||||
{
|
||||
mMain->writeSettings();
|
||||
|
||||
if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false))
|
||||
return;
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::on_importerButton_clicked()
|
||||
{
|
||||
mMain->writeSettings();
|
||||
|
||||
// Create the file if it doesn't already exist, else the importer will fail
|
||||
auto path = mCfgMgr.getUserConfigPath();
|
||||
path /= "openmw.cfg";
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QFile file(path);
|
||||
#else
|
||||
QFile file(Files::pathToQString(path));
|
||||
#endif
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
if (!file.open(QIODevice::ReadWrite))
|
||||
{
|
||||
// File cannot be created
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(
|
||||
tr("<html><head/><body><p><b>Could not open or create %1 for writing </b></p> \
|
||||
<p>Please make sure you have the right permissions \
|
||||
and try again.</p></body></html>")
|
||||
.arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Construct the arguments to run the importer
|
||||
QStringList arguments;
|
||||
|
||||
if (addonsCheckBox->isChecked())
|
||||
arguments.append(QString("--game-files"));
|
||||
|
||||
if (fontsCheckBox->isChecked())
|
||||
arguments.append(QString("--fonts"));
|
||||
|
||||
arguments.append(QString("--encoding"));
|
||||
arguments.append(mGameSettings.value(QString("encoding"), QString("win1252")));
|
||||
arguments.append(QString("--ini"));
|
||||
arguments.append(settingsComboBox->currentText());
|
||||
arguments.append(QString("--cfg"));
|
||||
arguments.append(Files::pathToQString(path));
|
||||
|
||||
qDebug() << "arguments " << arguments;
|
||||
|
||||
// start the progress bar as a "bouncing ball"
|
||||
progressBar->setMaximum(0);
|
||||
progressBar->setValue(0);
|
||||
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
|
||||
{
|
||||
resetProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::on_browseButton_clicked()
|
||||
{
|
||||
QString iniFile = QFileDialog::getOpenFileName(this, QObject::tr("Select configuration file"), QDir::currentPath(),
|
||||
QString(tr("Morrowind configuration file (*.ini)")));
|
||||
|
||||
if (iniFile.isEmpty())
|
||||
return;
|
||||
|
||||
QFileInfo info(iniFile);
|
||||
|
||||
if (!info.exists() || !info.isReadable())
|
||||
return;
|
||||
|
||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
|
||||
if (settingsComboBox->findText(path) == -1)
|
||||
{
|
||||
settingsComboBox->addItem(path);
|
||||
settingsComboBox->setCurrentIndex(settingsComboBox->findText(path));
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::wizardStarted()
|
||||
{
|
||||
mMain->hide(); // Hide the launcher
|
||||
|
||||
wizardButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::wizardFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
if (exitCode != 0 || exitStatus == QProcess::CrashExit)
|
||||
return qApp->quit();
|
||||
|
||||
mMain->reloadSettings();
|
||||
wizardButton->setEnabled(true);
|
||||
|
||||
mMain->show(); // Show the launcher again
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::importerStarted()
|
||||
{
|
||||
importerButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
if (exitCode != 0 || exitStatus == QProcess::CrashExit)
|
||||
{
|
||||
resetProgressBar();
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Importer finished"));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Warning);
|
||||
msgBox.setText(tr("Failed to import settings from INI file."));
|
||||
msgBox.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
// indicate progress finished
|
||||
progressBar->setMaximum(1);
|
||||
progressBar->setValue(1);
|
||||
|
||||
// Importer may have changed settings, so refresh
|
||||
mMain->reloadSettings();
|
||||
}
|
||||
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::resetProgressBar()
|
||||
{
|
||||
// set progress bar to 0 %
|
||||
progressBar->reset();
|
||||
}
|
||||
|
||||
void Launcher::ImportPage::saveSettings() {}
|
||||
|
||||
bool Launcher::ImportPage::loadSettings()
|
||||
{
|
||||
return true;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
#ifndef IMPORTSPAGE_HPP
|
||||
#define IMPORTSPAGE_HPP
|
||||
|
||||
#include <components/process/processinvoker.hpp>
|
||||
|
||||
#include "ui_importpage.h"
|
||||
|
||||
#include "maindialog.hpp"
|
||||
|
||||
namespace Files
|
||||
{
|
||||
struct ConfigurationManager;
|
||||
}
|
||||
namespace Config
|
||||
{
|
||||
class GameSettings;
|
||||
class LauncherSettings;
|
||||
}
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
class TextInputDialog;
|
||||
|
||||
class ImportPage : public QWidget, private Ui::ImportPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImportPage(Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings,
|
||||
Config::LauncherSettings& launcherSettings, MainDialog* parent = nullptr);
|
||||
~ImportPage() override;
|
||||
|
||||
void saveSettings();
|
||||
bool loadSettings();
|
||||
|
||||
/// set progress bar on page to 0%
|
||||
void resetProgressBar();
|
||||
|
||||
private slots:
|
||||
|
||||
void on_wizardButton_clicked();
|
||||
void on_importerButton_clicked();
|
||||
void on_browseButton_clicked();
|
||||
|
||||
void wizardStarted();
|
||||
void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
void importerStarted();
|
||||
void importerFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
private:
|
||||
Process::ProcessInvoker* mWizardInvoker;
|
||||
Process::ProcessInvoker* mImporterInvoker;
|
||||
|
||||
Files::ConfigurationManager& mCfgMgr;
|
||||
|
||||
Config::GameSettings& mGameSettings;
|
||||
Config::LauncherSettings& mLauncherSettings;
|
||||
|
||||
MainDialog* mMain;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // IMPORTSPAGE_HPP
|
@ -1,30 +0,0 @@
|
||||
#include "playpage.hpp"
|
||||
|
||||
#include <QListView>
|
||||
|
||||
Launcher::PlayPage::PlayPage(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setObjectName("PlayPage");
|
||||
setupUi(this);
|
||||
|
||||
profilesComboBox->setView(new QListView());
|
||||
|
||||
connect(profilesComboBox, qOverload<int>(&QComboBox::activated), this, &PlayPage::signalProfileChanged);
|
||||
connect(playButton, &QPushButton::clicked, this, &PlayPage::slotPlayClicked);
|
||||
}
|
||||
|
||||
void Launcher::PlayPage::setProfilesModel(QAbstractItemModel* model)
|
||||
{
|
||||
profilesComboBox->setModel(model);
|
||||
}
|
||||
|
||||
void Launcher::PlayPage::setProfilesIndex(int index)
|
||||
{
|
||||
profilesComboBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void Launcher::PlayPage::slotPlayClicked()
|
||||
{
|
||||
emit playButtonClicked();
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef PLAYPAGE_H
|
||||
#define PLAYPAGE_H
|
||||
|
||||
#include "ui_playpage.h"
|
||||
|
||||
class QComboBox;
|
||||
class QPushButton;
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
class PlayPage : public QWidget, private Ui::PlayPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PlayPage(QWidget* parent = nullptr);
|
||||
void setProfilesModel(QAbstractItemModel* model);
|
||||
|
||||
signals:
|
||||
void signalProfileChanged(int index);
|
||||
void playButtonClicked();
|
||||
|
||||
public slots:
|
||||
void setProfilesIndex(int index);
|
||||
|
||||
private slots:
|
||||
void slotPlayClicked();
|
||||
};
|
||||
}
|
||||
#endif
|
@ -1,278 +1,490 @@
|
||||
#include "settingspage.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <components/files/qtconversion.hpp>
|
||||
#include <QCompleter>
|
||||
#include <QFileDialog>
|
||||
#include <QString>
|
||||
|
||||
#include "utils/textinputdialog.hpp"
|
||||
#include <components/config/gamesettings.hpp>
|
||||
|
||||
using namespace Process;
|
||||
#include "utils/openalutil.hpp"
|
||||
|
||||
Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings,
|
||||
Config::LauncherSettings& launcherSettings, MainDialog* parent)
|
||||
Launcher::SettingsPage::SettingsPage(Config::GameSettings& gameSettings, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, mCfgMgr(cfg)
|
||||
, mGameSettings(gameSettings)
|
||||
, mLauncherSettings(launcherSettings)
|
||||
, mMain(parent)
|
||||
{
|
||||
setObjectName("SettingsPage");
|
||||
setupUi(this);
|
||||
|
||||
QStringList languages;
|
||||
languages << tr("English") << tr("French") << tr("German") << tr("Italian") << tr("Polish") << tr("Russian")
|
||||
<< tr("Spanish");
|
||||
for (const std::string& name : Launcher::enumerateOpenALDevices())
|
||||
{
|
||||
audioDeviceSelectorComboBox->addItem(QString::fromStdString(name), QString::fromStdString(name));
|
||||
}
|
||||
for (const std::string& name : Launcher::enumerateOpenALDevicesHrtf())
|
||||
{
|
||||
hrtfProfileSelectorComboBox->addItem(QString::fromStdString(name), QString::fromStdString(name));
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
|
||||
mCellNameCompleter.setModel(&mCellNameCompleterModel);
|
||||
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::loadCellsForAutocomplete(QStringList cellNames)
|
||||
{
|
||||
// Update the list of suggestions for the "Start default character at" field
|
||||
mCellNameCompleterModel.setStringList(cellNames);
|
||||
mCellNameCompleter.setCompletionMode(QCompleter::PopupCompletion);
|
||||
mCellNameCompleter.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||
}
|
||||
|
||||
languageComboBox->addItems(languages);
|
||||
void Launcher::SettingsPage::on_skipMenuCheckBox_stateChanged(int state)
|
||||
{
|
||||
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
||||
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
mWizardInvoker = new ProcessInvoker();
|
||||
mImporterInvoker = new ProcessInvoker();
|
||||
resetProgressBar();
|
||||
void Launcher::SettingsPage::on_runScriptAfterStartupBrowseButton_clicked()
|
||||
{
|
||||
QString scriptFile = QFileDialog::getOpenFileName(
|
||||
this, QObject::tr("Select script file"), QDir::currentPath(), QString(tr("Text file (*.txt)")));
|
||||
|
||||
connect(mWizardInvoker->getProcess(), &QProcess::started, this, &SettingsPage::wizardStarted);
|
||||
if (scriptFile.isEmpty())
|
||||
return;
|
||||
|
||||
connect(mWizardInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&SettingsPage::wizardFinished);
|
||||
QFileInfo info(scriptFile);
|
||||
|
||||
connect(mImporterInvoker->getProcess(), &QProcess::started, this, &SettingsPage::importerStarted);
|
||||
if (!info.exists() || !info.isReadable())
|
||||
return;
|
||||
|
||||
connect(mImporterInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&SettingsPage::importerFinished);
|
||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
runScriptAfterStartupField->setText(path);
|
||||
}
|
||||
|
||||
mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
||||
namespace
|
||||
{
|
||||
constexpr double CellSizeInUnits = 8192;
|
||||
|
||||
connect(mProfileDialog->lineEdit(), &LineEdit::textChanged, this, &SettingsPage::updateOkButton);
|
||||
double convertToCells(double unitRadius)
|
||||
{
|
||||
return unitRadius / CellSizeInUnits;
|
||||
}
|
||||
|
||||
// Detect Morrowind configuration files
|
||||
QStringList iniPaths;
|
||||
int convertToUnits(double CellGridRadius)
|
||||
{
|
||||
return static_cast<int>(CellSizeInUnits * CellGridRadius);
|
||||
}
|
||||
}
|
||||
|
||||
for (const QString& path : mGameSettings.getDataDirs())
|
||||
bool Launcher::SettingsPage::loadSettings()
|
||||
{
|
||||
// Game mechanics
|
||||
{
|
||||
QDir dir(path);
|
||||
dir.setPath(dir.canonicalPath()); // Resolve symlinks
|
||||
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||
loadSettingBool(classicCalmSpellsCheckBox, "classic calm spells behavior", "Game");
|
||||
loadSettingBool(
|
||||
requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||
loadSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||
loadSettingBool(avoidCollisionsCheckBox, "NPCs avoid collisions", "Game");
|
||||
int unarmedFactorsStrengthIndex = Settings::Manager::getInt("strength influences hand to hand", "Game");
|
||||
if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2)
|
||||
unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex);
|
||||
loadSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
||||
loadSettingBool(enableNavigatorCheckBox, "enable", "Navigator");
|
||||
int numPhysicsThreads = Settings::Manager::getInt("async num threads", "Physics");
|
||||
if (numPhysicsThreads >= 0)
|
||||
physicsThreadsSpinBox->setValue(numPhysicsThreads);
|
||||
loadSettingBool(allowNPCToFollowOverWaterSurfaceCheckBox, "allow actors to follow over water surface", "Game");
|
||||
loadSettingBool(unarmedCreatureAttacksDamageArmorCheckBox, "unarmed creature attacks damage armor", "Game");
|
||||
const int actorCollisionShapeType = Settings::Manager::getInt("actor collision shape type", "Game");
|
||||
if (0 <= actorCollisionShapeType && actorCollisionShapeType < actorCollisonShapeTypeComboBox->count())
|
||||
actorCollisonShapeTypeComboBox->setCurrentIndex(actorCollisionShapeType);
|
||||
}
|
||||
|
||||
if (dir.exists(QString("Morrowind.ini")))
|
||||
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
||||
else
|
||||
// Visuals
|
||||
{
|
||||
loadSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders");
|
||||
loadSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders");
|
||||
loadSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders");
|
||||
loadSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders");
|
||||
loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||
loadSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
||||
loadSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
||||
if (Settings::Manager::getInt("antialiasing", "Video") == 0)
|
||||
{
|
||||
if (!dir.cdUp())
|
||||
continue; // Cannot move from Data Files
|
||||
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
loadSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
||||
loadSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
|
||||
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||
connect(animSourcesCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotAnimSourcesToggled);
|
||||
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||
if (animSourcesCheckBox->checkState() != Qt::Unchecked)
|
||||
{
|
||||
loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||
loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||
}
|
||||
loadSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
||||
loadSettingBool(smoothMovementCheckBox, "smooth movement", "Game");
|
||||
|
||||
if (dir.exists(QString("Morrowind.ini")))
|
||||
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
|
||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
||||
if (distantTerrain && objectPaging)
|
||||
{
|
||||
distantLandCheckBox->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain");
|
||||
viewingDistanceComboBox->setValue(convertToCells(Settings::Manager::getInt("viewing distance", "Camera")));
|
||||
objectPagingMinSizeComboBox->setValue(Settings::Manager::getDouble("object paging min size", "Terrain"));
|
||||
|
||||
loadSettingBool(nightDaySwitchesCheckBox, "day night switches", "Game");
|
||||
|
||||
connect(postprocessEnabledCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotPostProcessToggled);
|
||||
loadSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing");
|
||||
loadSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing");
|
||||
postprocessHDRTimeComboBox->setValue(Settings::Manager::getDouble("auto exposure speed", "Post Processing"));
|
||||
|
||||
connect(skyBlendingCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotSkyBlendingToggled);
|
||||
loadSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
loadSettingBool(exponentialFogCheckBox, "exponential fog", "Fog");
|
||||
loadSettingBool(skyBlendingCheckBox, "sky blending", "Fog");
|
||||
skyBlendingStartComboBox->setValue(Settings::Manager::getDouble("sky blending start", "Fog"));
|
||||
}
|
||||
|
||||
if (!iniPaths.isEmpty())
|
||||
// Audio
|
||||
{
|
||||
settingsComboBox->addItems(iniPaths);
|
||||
importerButton->setEnabled(true);
|
||||
const std::string& selectedAudioDevice = Settings::Manager::getString("device", "Sound");
|
||||
if (selectedAudioDevice.empty() == false)
|
||||
{
|
||||
int audioDeviceIndex = audioDeviceSelectorComboBox->findData(QString::fromStdString(selectedAudioDevice));
|
||||
if (audioDeviceIndex != -1)
|
||||
{
|
||||
audioDeviceSelectorComboBox->setCurrentIndex(audioDeviceIndex);
|
||||
}
|
||||
}
|
||||
int hrtfEnabledIndex = Settings::Manager::getInt("hrtf enable", "Sound");
|
||||
if (hrtfEnabledIndex >= -1 && hrtfEnabledIndex <= 1)
|
||||
{
|
||||
enableHRTFComboBox->setCurrentIndex(hrtfEnabledIndex + 1);
|
||||
}
|
||||
const std::string& selectedHRTFProfile = Settings::Manager::getString("hrtf", "Sound");
|
||||
if (selectedHRTFProfile.empty() == false)
|
||||
{
|
||||
int hrtfProfileIndex = hrtfProfileSelectorComboBox->findData(QString::fromStdString(selectedHRTFProfile));
|
||||
if (hrtfProfileIndex != -1)
|
||||
{
|
||||
hrtfProfileSelectorComboBox->setCurrentIndex(hrtfProfileIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Interface Changes
|
||||
{
|
||||
importerButton->setEnabled(false);
|
||||
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||
loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||
loadSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI");
|
||||
int showOwnedIndex = Settings::Manager::getInt("show owned", "Game");
|
||||
// Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid.
|
||||
if (showOwnedIndex >= 0 && showOwnedIndex <= 3)
|
||||
showOwnedComboBox->setCurrentIndex(showOwnedIndex);
|
||||
loadSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI");
|
||||
loadSettingBool(useZoomOnMapCheckBox, "allow zooming", "Map");
|
||||
loadSettingBool(graphicHerbalismCheckBox, "graphic herbalism", "Game");
|
||||
scalingSpinBox->setValue(Settings::Manager::getFloat("scaling factor", "GUI"));
|
||||
fontSizeSpinBox->setValue(Settings::Manager::getInt("font size", "GUI"));
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
}
|
||||
// Bug fixes
|
||||
{
|
||||
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
loadSettingBool(
|
||||
trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
||||
}
|
||||
|
||||
Launcher::SettingsPage::~SettingsPage()
|
||||
{
|
||||
delete mWizardInvoker;
|
||||
delete mImporterInvoker;
|
||||
}
|
||||
// Miscellaneous
|
||||
{
|
||||
// Saves
|
||||
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||
loadSettingInt(maximumQuicksavesComboBox, "max quicksaves", "Saves");
|
||||
|
||||
// Other Settings
|
||||
QString screenshotFormatString
|
||||
= QString::fromStdString(Settings::Manager::getString("screenshot format", "General")).toUpper();
|
||||
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
||||
screenshotFormatComboBox->addItem(screenshotFormatString);
|
||||
screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString));
|
||||
|
||||
loadSettingBool(notifyOnSavedScreenshotCheckBox, "notify on saved screenshot", "General");
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::on_wizardButton_clicked()
|
||||
{
|
||||
mMain->writeSettings();
|
||||
// Testing
|
||||
{
|
||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
||||
if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false))
|
||||
return;
|
||||
bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1;
|
||||
if (skipMenu)
|
||||
{
|
||||
skipMenuCheckBox->setCheckState(Qt::Checked);
|
||||
}
|
||||
startDefaultCharacterAtLabel->setEnabled(skipMenu);
|
||||
startDefaultCharacterAtField->setEnabled(skipMenu);
|
||||
|
||||
startDefaultCharacterAtField->setText(mGameSettings.value("start"));
|
||||
runScriptAfterStartupField->setText(mGameSettings.value("script-run"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::on_importerButton_clicked()
|
||||
void Launcher::SettingsPage::saveSettings()
|
||||
{
|
||||
mMain->writeSettings();
|
||||
|
||||
// Create the file if it doesn't already exist, else the importer will fail
|
||||
auto path = mCfgMgr.getUserConfigPath();
|
||||
path /= "openmw.cfg";
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QFile file(path);
|
||||
#else
|
||||
QFile file(Files::pathToQString(path));
|
||||
#endif
|
||||
|
||||
if (!file.exists())
|
||||
// Game mechanics
|
||||
{
|
||||
if (!file.open(QIODevice::ReadWrite))
|
||||
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||
saveSettingBool(classicCalmSpellsCheckBox, "classic calm spells behavior", "Game");
|
||||
saveSettingBool(
|
||||
requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||
saveSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||
saveSettingBool(avoidCollisionsCheckBox, "NPCs avoid collisions", "Game");
|
||||
saveSettingInt(unarmedFactorsStrengthComboBox, "strength influences hand to hand", "Game");
|
||||
saveSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game");
|
||||
saveSettingBool(enableNavigatorCheckBox, "enable", "Navigator");
|
||||
saveSettingInt(physicsThreadsSpinBox, "async num threads", "Physics");
|
||||
saveSettingBool(allowNPCToFollowOverWaterSurfaceCheckBox, "allow actors to follow over water surface", "Game");
|
||||
saveSettingBool(unarmedCreatureAttacksDamageArmorCheckBox, "unarmed creature attacks damage armor", "Game");
|
||||
saveSettingInt(actorCollisonShapeTypeComboBox, "actor collision shape type", "Game");
|
||||
}
|
||||
|
||||
// Visuals
|
||||
{
|
||||
saveSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders");
|
||||
saveSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders");
|
||||
saveSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders");
|
||||
saveSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders");
|
||||
saveSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||
saveSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
saveSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
||||
saveSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
||||
saveSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
||||
saveSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
|
||||
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||
saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game");
|
||||
saveSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game");
|
||||
saveSettingBool(smoothMovementCheckBox, "smooth movement", "Game");
|
||||
|
||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
||||
const bool wantDistantLand = distantLandCheckBox->checkState();
|
||||
if (wantDistantLand != (distantTerrain && objectPaging))
|
||||
{
|
||||
// File cannot be created
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(
|
||||
tr("<html><head/><body><p><b>Could not open or create %1 for writing </b></p> \
|
||||
<p>Please make sure you have the right permissions \
|
||||
and try again.</p></body></html>")
|
||||
.arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return;
|
||||
Settings::Manager::setBool("distant terrain", "Terrain", wantDistantLand);
|
||||
Settings::Manager::setBool("object paging", "Terrain", wantDistantLand);
|
||||
}
|
||||
|
||||
file.close();
|
||||
saveSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain");
|
||||
int viewingDistance = convertToUnits(viewingDistanceComboBox->value());
|
||||
if (viewingDistance != Settings::Manager::getInt("viewing distance", "Camera"))
|
||||
{
|
||||
Settings::Manager::setInt("viewing distance", "Camera", viewingDistance);
|
||||
}
|
||||
double objectPagingMinSize = objectPagingMinSizeComboBox->value();
|
||||
if (objectPagingMinSize != Settings::Manager::getDouble("object paging min size", "Terrain"))
|
||||
Settings::Manager::setDouble("object paging min size", "Terrain", objectPagingMinSize);
|
||||
|
||||
saveSettingBool(nightDaySwitchesCheckBox, "day night switches", "Game");
|
||||
|
||||
saveSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing");
|
||||
saveSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing");
|
||||
double hdrExposureTime = postprocessHDRTimeComboBox->value();
|
||||
if (hdrExposureTime != Settings::Manager::getDouble("auto exposure speed", "Post Processing"))
|
||||
Settings::Manager::setDouble("auto exposure speed", "Post Processing", hdrExposureTime);
|
||||
|
||||
saveSettingBool(radialFogCheckBox, "radial fog", "Fog");
|
||||
saveSettingBool(exponentialFogCheckBox, "exponential fog", "Fog");
|
||||
saveSettingBool(skyBlendingCheckBox, "sky blending", "Fog");
|
||||
Settings::Manager::setDouble("sky blending start", "Fog", skyBlendingStartComboBox->value());
|
||||
}
|
||||
|
||||
// Construct the arguments to run the importer
|
||||
QStringList arguments;
|
||||
|
||||
if (addonsCheckBox->isChecked())
|
||||
arguments.append(QString("--game-files"));
|
||||
|
||||
if (fontsCheckBox->isChecked())
|
||||
arguments.append(QString("--fonts"));
|
||||
|
||||
arguments.append(QString("--encoding"));
|
||||
arguments.append(mGameSettings.value(QString("encoding"), QString("win1252")));
|
||||
arguments.append(QString("--ini"));
|
||||
arguments.append(settingsComboBox->currentText());
|
||||
arguments.append(QString("--cfg"));
|
||||
arguments.append(Files::pathToQString(path));
|
||||
// Audio
|
||||
{
|
||||
int audioDeviceIndex = audioDeviceSelectorComboBox->currentIndex();
|
||||
const std::string& prevAudioDevice = Settings::Manager::getString("device", "Sound");
|
||||
if (audioDeviceIndex != 0)
|
||||
{
|
||||
const std::string& newAudioDevice = audioDeviceSelectorComboBox->currentText().toUtf8().constData();
|
||||
if (newAudioDevice != prevAudioDevice)
|
||||
Settings::Manager::setString("device", "Sound", newAudioDevice);
|
||||
}
|
||||
else if (!prevAudioDevice.empty())
|
||||
{
|
||||
Settings::Manager::setString("device", "Sound", {});
|
||||
}
|
||||
int hrtfEnabledIndex = enableHRTFComboBox->currentIndex() - 1;
|
||||
if (hrtfEnabledIndex != Settings::Manager::getInt("hrtf enable", "Sound"))
|
||||
{
|
||||
Settings::Manager::setInt("hrtf enable", "Sound", hrtfEnabledIndex);
|
||||
}
|
||||
int selectedHRTFProfileIndex = hrtfProfileSelectorComboBox->currentIndex();
|
||||
const std::string& prevHRTFProfile = Settings::Manager::getString("hrtf", "Sound");
|
||||
if (selectedHRTFProfileIndex != 0)
|
||||
{
|
||||
const std::string& newHRTFProfile = hrtfProfileSelectorComboBox->currentText().toUtf8().constData();
|
||||
if (newHRTFProfile != prevHRTFProfile)
|
||||
Settings::Manager::setString("hrtf", "Sound", newHRTFProfile);
|
||||
}
|
||||
else if (!prevHRTFProfile.empty())
|
||||
{
|
||||
Settings::Manager::setString("hrtf", "Sound", {});
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "arguments " << arguments;
|
||||
// Interface Changes
|
||||
{
|
||||
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||
saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||
saveSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI");
|
||||
saveSettingInt(showOwnedComboBox, "show owned", "Game");
|
||||
saveSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI");
|
||||
saveSettingBool(useZoomOnMapCheckBox, "allow zooming", "Map");
|
||||
saveSettingBool(graphicHerbalismCheckBox, "graphic herbalism", "Game");
|
||||
|
||||
float uiScalingFactor = scalingSpinBox->value();
|
||||
if (uiScalingFactor != Settings::Manager::getFloat("scaling factor", "GUI"))
|
||||
Settings::Manager::setFloat("scaling factor", "GUI", uiScalingFactor);
|
||||
|
||||
int fontSize = fontSizeSpinBox->value();
|
||||
if (fontSize != Settings::Manager::getInt("font size", "GUI"))
|
||||
Settings::Manager::setInt("font size", "GUI", fontSize);
|
||||
}
|
||||
|
||||
// start the progress bar as a "bouncing ball"
|
||||
progressBar->setMaximum(0);
|
||||
progressBar->setValue(0);
|
||||
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
|
||||
// Bug fixes
|
||||
{
|
||||
resetProgressBar();
|
||||
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
saveSettingBool(
|
||||
trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::on_browseButton_clicked()
|
||||
{
|
||||
QString iniFile = QFileDialog::getOpenFileName(this, QObject::tr("Select configuration file"), QDir::currentPath(),
|
||||
QString(tr("Morrowind configuration file (*.ini)")));
|
||||
// Miscellaneous
|
||||
{
|
||||
// Saves Settings
|
||||
saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||
saveSettingInt(maximumQuicksavesComboBox, "max quicksaves", "Saves");
|
||||
|
||||
if (iniFile.isEmpty())
|
||||
return;
|
||||
// Other Settings
|
||||
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
|
||||
if (screenshotFormatString != Settings::Manager::getString("screenshot format", "General"))
|
||||
Settings::Manager::setString("screenshot format", "General", screenshotFormatString);
|
||||
|
||||
QFileInfo info(iniFile);
|
||||
saveSettingBool(notifyOnSavedScreenshotCheckBox, "notify on saved screenshot", "General");
|
||||
}
|
||||
|
||||
if (!info.exists() || !info.isReadable())
|
||||
return;
|
||||
// Testing
|
||||
{
|
||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked;
|
||||
if (skipMenu != mGameSettings.value("skip-menu").toInt())
|
||||
mGameSettings.setValue("skip-menu", QString::number(skipMenu));
|
||||
|
||||
if (settingsComboBox->findText(path) == -1)
|
||||
{
|
||||
settingsComboBox->addItem(path);
|
||||
settingsComboBox->setCurrentIndex(settingsComboBox->findText(path));
|
||||
importerButton->setEnabled(true);
|
||||
QString startCell = startDefaultCharacterAtField->text();
|
||||
if (startCell != mGameSettings.value("start"))
|
||||
{
|
||||
mGameSettings.setValue("start", startCell);
|
||||
}
|
||||
QString scriptRun = runScriptAfterStartupField->text();
|
||||
if (scriptRun != mGameSettings.value("script-run"))
|
||||
mGameSettings.setValue("script-run", scriptRun);
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::wizardStarted()
|
||||
void Launcher::SettingsPage::loadSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
mMain->hide(); // Hide the launcher
|
||||
|
||||
wizardButton->setEnabled(false);
|
||||
if (Settings::Manager::getBool(setting, group))
|
||||
checkbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::wizardFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
void Launcher::SettingsPage::saveSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
if (exitCode != 0 || exitStatus == QProcess::CrashExit)
|
||||
return qApp->quit();
|
||||
|
||||
mMain->reloadSettings();
|
||||
wizardButton->setEnabled(true);
|
||||
|
||||
mMain->show(); // Show the launcher again
|
||||
bool cValue = checkbox->checkState();
|
||||
if (cValue != Settings::Manager::getBool(setting, group))
|
||||
Settings::Manager::setBool(setting, group, cValue);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::importerStarted()
|
||||
void Launcher::SettingsPage::loadSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
importerButton->setEnabled(false);
|
||||
int currentIndex = Settings::Manager::getInt(setting, group);
|
||||
comboBox->setCurrentIndex(currentIndex);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
void Launcher::SettingsPage::saveSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
if (exitCode != 0 || exitStatus == QProcess::CrashExit)
|
||||
{
|
||||
resetProgressBar();
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Importer finished"));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Warning);
|
||||
msgBox.setText(tr("Failed to import settings from INI file."));
|
||||
msgBox.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
// indicate progress finished
|
||||
progressBar->setMaximum(1);
|
||||
progressBar->setValue(1);
|
||||
|
||||
// Importer may have changed settings, so refresh
|
||||
mMain->reloadSettings();
|
||||
}
|
||||
|
||||
importerButton->setEnabled(true);
|
||||
int currentIndex = comboBox->currentIndex();
|
||||
if (currentIndex != Settings::Manager::getInt(setting, group))
|
||||
Settings::Manager::setInt(setting, group, currentIndex);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::resetProgressBar()
|
||||
void Launcher::SettingsPage::loadSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
// set progress bar to 0 %
|
||||
progressBar->reset();
|
||||
int value = Settings::Manager::getInt(setting, group);
|
||||
spinBox->setValue(value);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::updateOkButton(const QString& text)
|
||||
void Launcher::SettingsPage::saveSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
// We do this here because we need to access the profiles
|
||||
if (text.isEmpty())
|
||||
{
|
||||
mProfileDialog->setOkButtonEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const QStringList profiles(mLauncherSettings.getContentLists());
|
||||
|
||||
(profiles.contains(text)) ? mProfileDialog->setOkButtonEnabled(false) : mProfileDialog->setOkButtonEnabled(true);
|
||||
int value = spinBox->value();
|
||||
if (value != Settings::Manager::getInt(setting, group))
|
||||
Settings::Manager::setInt(setting, group, value);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::saveSettings()
|
||||
void Launcher::SettingsPage::slotLoadedCellsChanged(QStringList cellNames)
|
||||
{
|
||||
QString language(languageComboBox->currentText());
|
||||
|
||||
mLauncherSettings.setValue(QLatin1String("Settings/language"), language);
|
||||
loadCellsForAutocomplete(cellNames);
|
||||
}
|
||||
|
||||
if (language == QLatin1String("Polish"))
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1250"));
|
||||
}
|
||||
else if (language == QLatin1String("Russian"))
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1251"));
|
||||
}
|
||||
else
|
||||
void Launcher::SettingsPage::slotAnimSourcesToggled(bool checked)
|
||||
{
|
||||
weaponSheathingCheckBox->setEnabled(checked);
|
||||
shieldSheathingCheckBox->setEnabled(checked);
|
||||
if (!checked)
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252"));
|
||||
weaponSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||
shieldSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
|
||||
bool Launcher::SettingsPage::loadSettings()
|
||||
void Launcher::SettingsPage::slotPostProcessToggled(bool checked)
|
||||
{
|
||||
QString language(mLauncherSettings.value(QLatin1String("Settings/language")));
|
||||
|
||||
int index = languageComboBox->findText(language);
|
||||
|
||||
if (index != -1)
|
||||
languageComboBox->setCurrentIndex(index);
|
||||
postprocessTransparentPostpassCheckBox->setEnabled(checked);
|
||||
postprocessHDRTimeComboBox->setEnabled(checked);
|
||||
postprocessHDRTimeLabel->setEnabled(checked);
|
||||
}
|
||||
|
||||
return true;
|
||||
void Launcher::SettingsPage::slotSkyBlendingToggled(bool checked)
|
||||
{
|
||||
skyBlendingStartComboBox->setEnabled(checked);
|
||||
skyBlendingStartLabel->setEnabled(checked);
|
||||
}
|
||||
|
@ -1,67 +1,56 @@
|
||||
#ifndef SETTINGSPAGE_HPP
|
||||
#define SETTINGSPAGE_HPP
|
||||
#ifndef SETTINGSPAGE_H
|
||||
#define SETTINGSPAGE_H
|
||||
|
||||
#include <components/process/processinvoker.hpp>
|
||||
#include <QCompleter>
|
||||
#include <QStringListModel>
|
||||
|
||||
#include "ui_settingspage.h"
|
||||
|
||||
#include "maindialog.hpp"
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
struct ConfigurationManager;
|
||||
}
|
||||
namespace Config
|
||||
{
|
||||
class GameSettings;
|
||||
class LauncherSettings;
|
||||
}
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
class TextInputDialog;
|
||||
|
||||
class SettingsPage : public QWidget, private Ui::SettingsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsPage(Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings,
|
||||
Config::LauncherSettings& launcherSettings, MainDialog* parent = nullptr);
|
||||
~SettingsPage() override;
|
||||
explicit SettingsPage(Config::GameSettings& gameSettings, QWidget* parent = nullptr);
|
||||
|
||||
void saveSettings();
|
||||
bool loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
/// set progress bar on page to 0%
|
||||
void resetProgressBar();
|
||||
public slots:
|
||||
void slotLoadedCellsChanged(QStringList cellNames);
|
||||
|
||||
private slots:
|
||||
|
||||
void on_wizardButton_clicked();
|
||||
void on_importerButton_clicked();
|
||||
void on_browseButton_clicked();
|
||||
|
||||
void wizardStarted();
|
||||
void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
void importerStarted();
|
||||
void importerFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
void updateOkButton(const QString& text);
|
||||
void on_skipMenuCheckBox_stateChanged(int state);
|
||||
void on_runScriptAfterStartupBrowseButton_clicked();
|
||||
void slotAnimSourcesToggled(bool checked);
|
||||
void slotPostProcessToggled(bool checked);
|
||||
void slotSkyBlendingToggled(bool checked);
|
||||
|
||||
private:
|
||||
Process::ProcessInvoker* mWizardInvoker;
|
||||
Process::ProcessInvoker* mImporterInvoker;
|
||||
|
||||
Files::ConfigurationManager& mCfgMgr;
|
||||
|
||||
Config::GameSettings& mGameSettings;
|
||||
Config::LauncherSettings& mLauncherSettings;
|
||||
|
||||
MainDialog* mMain;
|
||||
TextInputDialog* mProfileDialog;
|
||||
QCompleter mCellNameCompleter;
|
||||
QStringListModel mCellNameCompleterModel;
|
||||
|
||||
/**
|
||||
* Load the cells associated with the given content files for use in autocomplete
|
||||
* @param filePaths the file paths of the content files to be examined
|
||||
*/
|
||||
void loadCellsForAutocomplete(QStringList filePaths);
|
||||
static void loadSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group);
|
||||
static void saveSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group);
|
||||
static void loadSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group);
|
||||
static void saveSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group);
|
||||
static void loadSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group);
|
||||
static void saveSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SETTINGSPAGE_HPP
|
||||
#endif
|
||||
|
Before Width: | Height: | Size: 699 B After Width: | Height: | Size: 699 B |
Before Width: | Height: | Size: 663 B |
Before Width: | Height: | Size: 683 B |
Before Width: | Height: | Size: 636 B |
Before Width: | Height: | Size: 652 B |
After Width: | Height: | Size: 912 B |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 362 B |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 228 KiB |
@ -1,26 +1,18 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="images">
|
||||
<file alias="clear.png">images/clear.png</file>
|
||||
<file alias="down.png">images/down.png</file>
|
||||
<file alias="openmw.png">images/openmw.png</file>
|
||||
<file alias="openmw-plugin.png">images/openmw-plugin.png</file>
|
||||
<file alias="openmw-header.png">images/openmw-header.png</file>
|
||||
<file alias="openmw-plugin.png">images/openmw-plugin.png</file>
|
||||
<file alias="preferences.png">images/preferences.png</file>
|
||||
<file alias="preferences-advanced.png">images/preferences-advanced.png</file>
|
||||
<file alias="preferences-video.png">images/preferences-video.png</file>
|
||||
<file alias="playpage-background.png">images/playpage-background.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="icons/tango">
|
||||
<file alias="index.theme">icons/tango/index.theme</file>
|
||||
<file alias="48x48/emblem-system.png">icons/tango/48x48/emblem-system.png</file>
|
||||
<file alias="48x48/preferences-system.png">icons/tango/48x48/preferences-system.png</file>
|
||||
<file alias="48x48/video-display.png">icons/tango/48x48/video-display.png</file>
|
||||
<file alias="16x16/document-new.png">icons/tango/16x16/document-new.png</file>
|
||||
<file alias="16x16/edit-clear.png">icons/tango/16x16/edit-clear.png</file>
|
||||
<file alias="16x16/edit-copy.png">icons/tango/16x16/edit-copy.png</file>
|
||||
<file alias="16x16/edit-delete.png">icons/tango/16x16/edit-delete.png</file>
|
||||
<file alias="16x16/go-bottom.png">icons/tango/16x16/go-bottom.png</file>
|
||||
<file alias="16x16/go-down.png">icons/tango/16x16/go-down.png</file>
|
||||
<file alias="16x16/go-top.png">icons/tango/16x16/go-top.png</file>
|
||||
<file alias="16x16/go-up.png">icons/tango/16x16/go-up.png</file>
|
||||
<file alias="16x16/view-refresh.png">icons/tango/16x16/view-refresh.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ImportPage</class>
|
||||
<widget class="QWidget" name="ImportPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>514</width>
|
||||
<height>397</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="wizardGroup">
|
||||
<property name="title">
|
||||
<string>Morrowind Installation Wizard</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3" columnstretch="1,1">
|
||||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="wizardButton">
|
||||
<property name="text">
|
||||
<string>Run &Installation Wizard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="importerGroup">
|
||||
<property name="title">
|
||||
<string>Morrowind Settings Importer</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0" columnstretch="1,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="importerLabel">
|
||||
<property name="text">
|
||||
<string>File to import settings from:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QComboBox" name="settingsComboBox"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="browseButton">
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="addonsCheckBox">
|
||||
<property name="text">
|
||||
<string>Import add-on and plugin selection (creates a new Content List)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="fontsCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Fonts shipped with the original engine are blurry with UI scaling and support only a small amount of characters,
|
||||
so OpenMW provides another set of fonts to avoid these issues. These fonts use TrueType technology and are quite similar
|
||||
to default Morrowind fonts. Check this box if you still prefer original fonts over OpenMW ones or if you use custom bitmap fonts.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import bitmap fonts setup</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="1,1">
|
||||
<item row="2" column="1">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="importerButton">
|
||||
<property name="text">
|
||||
<string>Run &Settings Importer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="maximum">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,189 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PlayPage</class>
|
||||
<widget class="QWidget" name="PlayPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>274</width>
|
||||
<height>317</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="Scroll" native="true">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#Scroll {
|
||||
background-image: url(":/images/playpage-background.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="profilesComboBox">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#profilesComboBox {
|
||||
padding: 1px 18px 1px 3px;
|
||||
|
||||
background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white);
|
||||
border-width: 1px;
|
||||
border-color: rgba(0, 0, 0, 125);
|
||||
border-style: solid;
|
||||
border-radius: 2px;
|
||||
|
||||
font-size: 12pt;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/*QComboBox gets the "on" state when the popup is open */
|
||||
#profilesComboBox:!editable:on {
|
||||
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(0, 0, 0, 75),
|
||||
stop:0.1 rgba(0, 0, 0, 15),
|
||||
stop:0.2 rgba(255, 255, 255, 55));
|
||||
|
||||
border: 1px solid rgba(0, 0, 0, 55);
|
||||
}
|
||||
|
||||
#profilesComboBox:on { /* shift the text when the popup opens */
|
||||
padding-top: 3px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
#profilesComboBox::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
|
||||
border-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-left-color: darkgray;
|
||||
border-left-style: solid; /* just a single line */
|
||||
border-top-right-radius: 3px; /* same radius as the QComboBox */
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
|
||||
#profilesComboBox::down-arrow {
|
||||
image: url(":/images/down.png");
|
||||
}
|
||||
|
||||
#profilesComboBox::down-arrow:on { /* shift the arrow when popup is open */
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
#profilesComboBox QAbstractItemView {
|
||||
border: 0px;
|
||||
}</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="profileLabel">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#profileLabel {
|
||||
font-size: 18pt;
|
||||
color: black;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Current Content List:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="playButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>85</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>85</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#playButton {
|
||||
height: 50px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(255, 255, 255, 200),
|
||||
stop:0.1 rgba(255, 255, 255, 15),
|
||||
stop:0.49 rgba(255, 255, 255, 75),
|
||||
stop:0.5 rgba(0, 0, 0, 0),
|
||||
stop:0.9 rgba(0, 0, 0, 55),
|
||||
stop:1 rgba(0, 0, 0, 100));
|
||||
|
||||
font-size: 26pt;
|
||||
color: black;
|
||||
|
||||
border-right: 1px solid rgba(0, 0, 0, 155);
|
||||
border-left: 1px solid rgba(0, 0, 0, 55);
|
||||
border-top: 1px solid rgba(0, 0, 0, 55);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 155);
|
||||
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#playButton:hover {
|
||||
border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0));
|
||||
border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0));
|
||||
border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0));
|
||||
border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0));
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
#playButton:pressed {
|
||||
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(0, 0, 0, 75),
|
||||
stop:0.1 rgba(0, 0, 0, 15),
|
||||
stop:0.2 rgba(255, 255, 255, 55)
|
||||
stop:0.95 rgba(255, 255, 255, 55),
|
||||
stop:1 rgba(255, 255, 255, 155));
|
||||
|
||||
border: 1px solid rgba(0, 0, 0, 55);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Play</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|