Rework launcher UI
|
@ -33,6 +33,7 @@
|
|||
Bug #7088: Deleting last save game of last character doesn't clear character name/details
|
||||
Feature #5492: Let rain and snow collide with statics
|
||||
Feature #6447: Add LOD support to Object Paging
|
||||
Feature #6922: Improve launcher appearance
|
||||
Feature #6933: Support high-resolution cursor textures
|
||||
Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData
|
||||
Feature #6979: Add support of loading and displaying LOD assets purely based on their filename extension
|
||||
|
|
|
@ -820,12 +820,20 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
|||
get_filename_component(QT_COCOA_PLUGIN_GROUP "${QT_COCOA_PLUGIN_DIR}" NAME)
|
||||
get_filename_component(QT_COCOA_PLUGIN_NAME "${QT_COCOA_PLUGIN_PATH}" NAME)
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
|
||||
get_property(QT_QMACSTYLE_PLUGIN_PATH TARGET Qt5::QMacStylePlugin PROPERTY LOCATION_RELEASE)
|
||||
get_filename_component(QT_QMACSTYLE_PLUGIN_DIR "${QT_QMACSTYLE_PLUGIN_PATH}" DIRECTORY)
|
||||
get_filename_component(QT_QMACSTYLE_PLUGIN_GROUP "${QT_QMACSTYLE_PLUGIN_DIR}" NAME)
|
||||
get_filename_component(QT_QMACSTYLE_PLUGIN_NAME "${QT_QMACSTYLE_PLUGIN_PATH}" NAME)
|
||||
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
||||
|
||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${APP_BUNDLE_DIR}/Contents/Resources/qt.conf" COPYONLY)
|
||||
|
||||
if (BUILD_OPENCS)
|
||||
get_property(OPENCS_BUNDLE_NAME_TMP TARGET openmw-cs PROPERTY OUTPUT_NAME)
|
||||
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
|
||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY)
|
||||
endif ()
|
||||
|
||||
|
@ -895,7 +903,9 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
|||
install_plugins_for_bundle("${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
|
||||
|
||||
set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
|
||||
set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}")
|
||||
set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
|
||||
set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}")
|
||||
|
||||
install(CODE "
|
||||
function(gp_item_default_embedded_path_override item default_embedded_path_var)
|
||||
|
|
|
@ -4,10 +4,9 @@ set(LAUNCHER
|
|||
sdlinit.cpp
|
||||
main.cpp
|
||||
maindialog.cpp
|
||||
playpage.cpp
|
||||
textslotmsgbox.cpp
|
||||
importpage.cpp
|
||||
settingspage.cpp
|
||||
advancedpage.cpp
|
||||
|
||||
utils/cellnameloader.cpp
|
||||
utils/profilescombobox.cpp
|
||||
|
@ -23,10 +22,9 @@ set(LAUNCHER_HEADER
|
|||
graphicspage.hpp
|
||||
sdlinit.hpp
|
||||
maindialog.hpp
|
||||
playpage.hpp
|
||||
textslotmsgbox.hpp
|
||||
importpage.hpp
|
||||
settingspage.hpp
|
||||
advancedpage.hpp
|
||||
|
||||
utils/cellnameloader.hpp
|
||||
utils/profilescombobox.hpp
|
||||
|
@ -40,10 +38,9 @@ set(LAUNCHER_UI
|
|||
${CMAKE_SOURCE_DIR}/files/ui/datafilespage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/graphicspage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/mainwindow.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/playpage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/importpage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/settingspage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/advancedpage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/directorypicker.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
|
|
@ -112,6 +112,12 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager& cfg, Config:
|
|||
const QString encoding = mGameSettings.value("encoding", "win1252");
|
||||
mSelector->setEncoding(encoding);
|
||||
|
||||
QStringList languages;
|
||||
languages << tr("English") << tr("French") << tr("German") << tr("Italian") << tr("Polish") << tr("Russian")
|
||||
<< tr("Spanish");
|
||||
|
||||
mSelector->languageBox()->addItems(languages);
|
||||
|
||||
mNewProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
||||
mCloneProfileDialog = new TextInputDialog(tr("Clone Content List"), tr("Content List name:"), this);
|
||||
|
||||
|
@ -196,6 +202,11 @@ bool Launcher::DataFilesPage::loadSettings()
|
|||
if (!currentProfile.isEmpty())
|
||||
addProfile(currentProfile, true);
|
||||
|
||||
QString language(mLauncherSettings.value(QLatin1String("Settings/language")));
|
||||
int index = mSelector->languageBox()->findText(language);
|
||||
if (index != -1)
|
||||
mSelector->languageBox()->setCurrentIndex(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -340,6 +351,23 @@ void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
|||
}
|
||||
mLauncherSettings.setContentList(profileName, dirList, selectedArchivePaths(), fileNames);
|
||||
mGameSettings.setContentList(dirList, selectedArchivePaths(), fileNames);
|
||||
|
||||
QString language(mSelector->languageBox()->currentText());
|
||||
|
||||
mLauncherSettings.setValue(QLatin1String("Settings/language"), language);
|
||||
|
||||
if (language == QLatin1String("Polish"))
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1250"));
|
||||
}
|
||||
else if (language == QLatin1String("Russian"))
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1251"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252"));
|
||||
}
|
||||
}
|
||||
|
||||
QStringList Launcher::DataFilesPage::selectedDirectoriesPaths() const
|
||||
|
|
229
apps/launcher/importpage.cpp
Normal file
|
@ -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;
|
||||
}
|
64
apps/launcher/importpage.hpp
Normal file
|
@ -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
|
|
@ -15,10 +15,9 @@
|
|||
#include <components/files/qtconversion.hpp>
|
||||
#include <components/misc/utf8qtextstream.hpp>
|
||||
|
||||
#include "advancedpage.hpp"
|
||||
#include "datafilespage.hpp"
|
||||
#include "graphicspage.hpp"
|
||||
#include "playpage.hpp"
|
||||
#include "importpage.hpp"
|
||||
#include "settingspage.hpp"
|
||||
|
||||
using namespace Process;
|
||||
|
@ -47,21 +46,13 @@ Launcher::MainDialog::MainDialog(QWidget* parent)
|
|||
connect(mWizardInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&MainDialog::wizardFinished);
|
||||
|
||||
iconWidget->setViewMode(QListView::IconMode);
|
||||
iconWidget->setWrapping(false);
|
||||
iconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure
|
||||
iconWidget->setIconSize(QSize(48, 48));
|
||||
iconWidget->setMovement(QListView::Static);
|
||||
|
||||
iconWidget->setSpacing(4);
|
||||
iconWidget->setCurrentRow(0);
|
||||
iconWidget->setFlow(QListView::LeftToRight);
|
||||
|
||||
auto* helpButton = new QPushButton(tr("Help"));
|
||||
auto* playButton = new QPushButton(tr("Play"));
|
||||
buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close"));
|
||||
buttonBox->addButton(helpButton, QDialogButtonBox::HelpRole);
|
||||
buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole);
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setText(tr(" Launch OpenMW "));
|
||||
buttonBox->button(QDialogButtonBox::Help)->setText(tr("Help"));
|
||||
|
||||
// Order of buttons can be different on different setups,
|
||||
// so make sure that the Play button has a focus by default.
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setFocus();
|
||||
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &MainDialog::close);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &MainDialog::play);
|
||||
|
@ -84,37 +75,10 @@ void Launcher::MainDialog::createIcons()
|
|||
if (!QIcon::hasThemeIcon("document-new"))
|
||||
QIcon::setThemeName("tango");
|
||||
|
||||
auto* playButton = new QListWidgetItem(iconWidget);
|
||||
playButton->setIcon(QIcon(":/images/openmw.png"));
|
||||
playButton->setText(tr("Play"));
|
||||
playButton->setTextAlignment(Qt::AlignCenter);
|
||||
playButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
auto* dataFilesButton = new QListWidgetItem(iconWidget);
|
||||
dataFilesButton->setIcon(QIcon(":/images/openmw-plugin.png"));
|
||||
dataFilesButton->setText(tr("Data Files"));
|
||||
dataFilesButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
auto* graphicsButton = new QListWidgetItem(iconWidget);
|
||||
graphicsButton->setIcon(QIcon(":/images/preferences-video.png"));
|
||||
graphicsButton->setText(tr("Graphics"));
|
||||
graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute);
|
||||
graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
auto* settingsButton = new QListWidgetItem(iconWidget);
|
||||
settingsButton->setIcon(QIcon(":/images/preferences.png"));
|
||||
settingsButton->setText(tr("Settings"));
|
||||
settingsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
settingsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
auto* advancedButton = new QListWidgetItem(iconWidget);
|
||||
advancedButton->setIcon(QIcon(":/images/preferences-advanced.png"));
|
||||
advancedButton->setText(tr("Advanced"));
|
||||
advancedButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
connect(iconWidget, &QListWidget::currentItemChanged, this, &MainDialog::changePage);
|
||||
connect(dataAction, &QAction::triggered, this, &MainDialog::enableDataPage);
|
||||
connect(graphicsAction, &QAction::triggered, this, &MainDialog::enableGraphicsPage);
|
||||
connect(settingsAction, &QAction::triggered, this, &MainDialog::enableSettingsPage);
|
||||
connect(importAction, &QAction::triggered, this, &MainDialog::enableImportPage);
|
||||
}
|
||||
|
||||
void Launcher::MainDialog::createPages()
|
||||
|
@ -123,33 +87,23 @@ void Launcher::MainDialog::createPages()
|
|||
if (pagesWidget->count() != 0)
|
||||
return;
|
||||
|
||||
mPlayPage = new PlayPage(this);
|
||||
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mGraphicsPage = new GraphicsPage(this);
|
||||
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mAdvancedPage = new AdvancedPage(mGameSettings, this);
|
||||
|
||||
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
||||
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
||||
mPlayPage->setProfilesIndex(mDataFilesPage->profilesIndex());
|
||||
mImportPage = new ImportPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mSettingsPage = new SettingsPage(mGameSettings, this);
|
||||
|
||||
// Add the pages to the stacked widget
|
||||
pagesWidget->addWidget(mPlayPage);
|
||||
pagesWidget->addWidget(mDataFilesPage);
|
||||
pagesWidget->addWidget(mGraphicsPage);
|
||||
pagesWidget->addWidget(mSettingsPage);
|
||||
pagesWidget->addWidget(mAdvancedPage);
|
||||
pagesWidget->addWidget(mImportPage);
|
||||
|
||||
// Select the first page
|
||||
iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select);
|
||||
dataAction->setChecked(true);
|
||||
|
||||
connect(mPlayPage, &PlayPage::playButtonClicked, this, &MainDialog::play);
|
||||
|
||||
connect(mPlayPage, &PlayPage::signalProfileChanged, mDataFilesPage, &DataFilesPage::slotProfileChanged);
|
||||
connect(mDataFilesPage, &DataFilesPage::signalProfileChanged, mPlayPage, &PlayPage::setProfilesIndex);
|
||||
// Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread
|
||||
connect(mDataFilesPage, &DataFilesPage::signalLoadedCellsChanged, mAdvancedPage,
|
||||
&AdvancedPage::slotLoadedCellsChanged, Qt::QueuedConnection);
|
||||
connect(mDataFilesPage, &DataFilesPage::signalLoadedCellsChanged, mSettingsPage,
|
||||
&SettingsPage::slotLoadedCellsChanged, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
||||
|
@ -270,7 +224,7 @@ bool Launcher::MainDialog::reloadSettings()
|
|||
if (!setupGraphicsSettings())
|
||||
return false;
|
||||
|
||||
if (!mSettingsPage->loadSettings())
|
||||
if (!mImportPage->loadSettings())
|
||||
return false;
|
||||
|
||||
if (!mDataFilesPage->loadSettings())
|
||||
|
@ -279,20 +233,50 @@ bool Launcher::MainDialog::reloadSettings()
|
|||
if (!mGraphicsPage->loadSettings())
|
||||
return false;
|
||||
|
||||
if (!mAdvancedPage->loadSettings())
|
||||
if (!mSettingsPage->loadSettings())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Launcher::MainDialog::changePage(QListWidgetItem* current, QListWidgetItem* previous)
|
||||
void Launcher::MainDialog::enableDataPage()
|
||||
{
|
||||
if (!current)
|
||||
current = previous;
|
||||
pagesWidget->setCurrentIndex(0);
|
||||
mImportPage->resetProgressBar();
|
||||
dataAction->setChecked(true);
|
||||
graphicsAction->setChecked(false);
|
||||
importAction->setChecked(false);
|
||||
settingsAction->setChecked(false);
|
||||
}
|
||||
|
||||
int currentIndex = iconWidget->row(current);
|
||||
pagesWidget->setCurrentIndex(currentIndex);
|
||||
mSettingsPage->resetProgressBar();
|
||||
void Launcher::MainDialog::enableGraphicsPage()
|
||||
{
|
||||
pagesWidget->setCurrentIndex(1);
|
||||
mImportPage->resetProgressBar();
|
||||
dataAction->setChecked(false);
|
||||
graphicsAction->setChecked(true);
|
||||
settingsAction->setChecked(false);
|
||||
importAction->setChecked(false);
|
||||
}
|
||||
|
||||
void Launcher::MainDialog::enableSettingsPage()
|
||||
{
|
||||
pagesWidget->setCurrentIndex(2);
|
||||
mImportPage->resetProgressBar();
|
||||
dataAction->setChecked(false);
|
||||
graphicsAction->setChecked(false);
|
||||
settingsAction->setChecked(true);
|
||||
importAction->setChecked(false);
|
||||
}
|
||||
|
||||
void Launcher::MainDialog::enableImportPage()
|
||||
{
|
||||
pagesWidget->setCurrentIndex(3);
|
||||
mImportPage->resetProgressBar();
|
||||
dataAction->setChecked(false);
|
||||
graphicsAction->setChecked(false);
|
||||
settingsAction->setChecked(false);
|
||||
importAction->setChecked(true);
|
||||
}
|
||||
|
||||
bool Launcher::MainDialog::setupLauncherSettings()
|
||||
|
@ -490,8 +474,8 @@ bool Launcher::MainDialog::writeSettings()
|
|||
saveSettings();
|
||||
mDataFilesPage->saveSettings();
|
||||
mGraphicsPage->saveSettings();
|
||||
mImportPage->saveSettings();
|
||||
mSettingsPage->saveSettings();
|
||||
mAdvancedPage->saveSettings();
|
||||
|
||||
const auto& userPath = mCfgMgr.getUserConfigPath();
|
||||
|
||||
|
|
|
@ -20,12 +20,11 @@ class QString;
|
|||
|
||||
namespace Launcher
|
||||
{
|
||||
class PlayPage;
|
||||
class GraphicsPage;
|
||||
class DataFilesPage;
|
||||
class UnshieldThread;
|
||||
class ImportPage;
|
||||
class SettingsPage;
|
||||
class AdvancedPage;
|
||||
|
||||
enum FirstRunDialogResult
|
||||
{
|
||||
|
@ -52,7 +51,10 @@ namespace Launcher
|
|||
bool writeSettings();
|
||||
|
||||
public slots:
|
||||
void changePage(QListWidgetItem* current, QListWidgetItem* previous);
|
||||
void enableDataPage();
|
||||
void enableGraphicsPage();
|
||||
void enableSettingsPage();
|
||||
void enableImportPage();
|
||||
void play();
|
||||
void help();
|
||||
|
||||
|
@ -84,11 +86,10 @@ namespace Launcher
|
|||
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
PlayPage* mPlayPage;
|
||||
GraphicsPage* mGraphicsPage;
|
||||
DataFilesPage* mDataFilesPage;
|
||||
ImportPage* mImportPage;
|
||||
SettingsPage* mSettingsPage;
|
||||
AdvancedPage* mAdvancedPage;
|
||||
|
||||
Process::ProcessInvoker* mGameInvoker;
|
||||
Process::ProcessInvoker* mWizardInvoker;
|
||||
|
|
|
@ -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 <array>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <QCompleter>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
|
||||
#include <components/files/qtconversion.hpp>
|
||||
#include <components/config/gamesettings.hpp>
|
||||
|
||||
#include "utils/textinputdialog.hpp"
|
||||
#include "utils/openalutil.hpp"
|
||||
|
||||
using namespace Process;
|
||||
|
||||
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");
|
||||
|
||||
languageComboBox->addItems(languages);
|
||||
|
||||
mWizardInvoker = new ProcessInvoker();
|
||||
mImporterInvoker = new ProcessInvoker();
|
||||
resetProgressBar();
|
||||
|
||||
connect(mWizardInvoker->getProcess(), &QProcess::started, this, &SettingsPage::wizardStarted);
|
||||
|
||||
connect(mWizardInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&SettingsPage::wizardFinished);
|
||||
|
||||
connect(mImporterInvoker->getProcess(), &QProcess::started, this, &SettingsPage::importerStarted);
|
||||
|
||||
connect(mImporterInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||
&SettingsPage::importerFinished);
|
||||
|
||||
mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
||||
|
||||
connect(mProfileDialog->lineEdit(), &LineEdit::textChanged, this, &SettingsPage::updateOkButton);
|
||||
|
||||
// Detect Morrowind configuration files
|
||||
QStringList iniPaths;
|
||||
|
||||
for (const QString& path : mGameSettings.getDataDirs())
|
||||
for (const std::string& name : Launcher::enumerateOpenALDevices())
|
||||
{
|
||||
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")));
|
||||
}
|
||||
audioDeviceSelectorComboBox->addItem(QString::fromStdString(name), QString::fromStdString(name));
|
||||
}
|
||||
|
||||
if (!iniPaths.isEmpty())
|
||||
for (const std::string& name : Launcher::enumerateOpenALDevicesHrtf())
|
||||
{
|
||||
settingsComboBox->addItems(iniPaths);
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
importerButton->setEnabled(false);
|
||||
hrtfProfileSelectorComboBox->addItem(QString::fromStdString(name), QString::fromStdString(name));
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
|
||||
mCellNameCompleter.setModel(&mCellNameCompleterModel);
|
||||
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
||||
}
|
||||
|
||||
Launcher::SettingsPage::~SettingsPage()
|
||||
void Launcher::SettingsPage::loadCellsForAutocomplete(QStringList cellNames)
|
||||
{
|
||||
delete mWizardInvoker;
|
||||
delete mImporterInvoker;
|
||||
// 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::SettingsPage::on_wizardButton_clicked()
|
||||
void Launcher::SettingsPage::on_skipMenuCheckBox_stateChanged(int state)
|
||||
{
|
||||
mMain->writeSettings();
|
||||
|
||||
if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false))
|
||||
return;
|
||||
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
||||
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::on_importerButton_clicked()
|
||||
void Launcher::SettingsPage::on_runScriptAfterStartupBrowseButton_clicked()
|
||||
{
|
||||
mMain->writeSettings();
|
||||
QString scriptFile = QFileDialog::getOpenFileName(
|
||||
this, QObject::tr("Select script file"), QDir::currentPath(), QString(tr("Text file (*.txt)")));
|
||||
|
||||
// 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::SettingsPage::on_browseButton_clicked()
|
||||
{
|
||||
QString iniFile = QFileDialog::getOpenFileName(this, QObject::tr("Select configuration file"), QDir::currentPath(),
|
||||
QString(tr("Morrowind configuration file (*.ini)")));
|
||||
|
||||
if (iniFile.isEmpty())
|
||||
if (scriptFile.isEmpty())
|
||||
return;
|
||||
|
||||
QFileInfo info(iniFile);
|
||||
QFileInfo info(scriptFile);
|
||||
|
||||
if (!info.exists() || !info.isReadable())
|
||||
return;
|
||||
|
||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
runScriptAfterStartupField->setText(path);
|
||||
}
|
||||
|
||||
if (settingsComboBox->findText(path) == -1)
|
||||
namespace
|
||||
{
|
||||
constexpr double CellSizeInUnits = 8192;
|
||||
|
||||
double convertToCells(double unitRadius)
|
||||
{
|
||||
settingsComboBox->addItem(path);
|
||||
settingsComboBox->setCurrentIndex(settingsComboBox->findText(path));
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::wizardStarted()
|
||||
{
|
||||
mMain->hide(); // Hide the launcher
|
||||
|
||||
wizardButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::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::SettingsPage::importerStarted()
|
||||
{
|
||||
importerButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::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();
|
||||
return unitRadius / CellSizeInUnits;
|
||||
}
|
||||
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::resetProgressBar()
|
||||
{
|
||||
// set progress bar to 0 %
|
||||
progressBar->reset();
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::updateOkButton(const QString& text)
|
||||
{
|
||||
// We do this here because we need to access the profiles
|
||||
if (text.isEmpty())
|
||||
int convertToUnits(double CellGridRadius)
|
||||
{
|
||||
mProfileDialog->setOkButtonEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const QStringList profiles(mLauncherSettings.getContentLists());
|
||||
|
||||
(profiles.contains(text)) ? mProfileDialog->setOkButtonEnabled(false) : mProfileDialog->setOkButtonEnabled(true);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::saveSettings()
|
||||
{
|
||||
QString language(languageComboBox->currentText());
|
||||
|
||||
mLauncherSettings.setValue(QLatin1String("Settings/language"), language);
|
||||
|
||||
if (language == QLatin1String("Polish"))
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1250"));
|
||||
}
|
||||
else if (language == QLatin1String("Russian"))
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1251"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252"));
|
||||
return static_cast<int>(CellSizeInUnits * CellGridRadius);
|
||||
}
|
||||
}
|
||||
|
||||
bool Launcher::SettingsPage::loadSettings()
|
||||
{
|
||||
QString language(mLauncherSettings.value(QLatin1String("Settings/language")));
|
||||
// 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);
|
||||
}
|
||||
|
||||
int index = languageComboBox->findText(language);
|
||||
// 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, &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 (index != -1)
|
||||
languageComboBox->setCurrentIndex(index);
|
||||
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"));
|
||||
}
|
||||
|
||||
// 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::SettingsPage::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::SettingsPage::loadSettingBool(QCheckBox* checkbox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
if (Settings::Manager::getBool(setting, group))
|
||||
checkbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::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::SettingsPage::loadSettingInt(QComboBox* comboBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
int currentIndex = Settings::Manager::getInt(setting, group);
|
||||
comboBox->setCurrentIndex(currentIndex);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::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::SettingsPage::loadSettingInt(QSpinBox* spinBox, const std::string& setting, const std::string& group)
|
||||
{
|
||||
int value = Settings::Manager::getInt(setting, group);
|
||||
spinBox->setValue(value);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::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::SettingsPage::slotLoadedCellsChanged(QStringList cellNames)
|
||||
{
|
||||
loadCellsForAutocomplete(cellNames);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::slotAnimSourcesToggled(bool checked)
|
||||
{
|
||||
weaponSheathingCheckBox->setEnabled(checked);
|
||||
shieldSheathingCheckBox->setEnabled(checked);
|
||||
if (!checked)
|
||||
{
|
||||
weaponSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||
shieldSheathingCheckBox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::slotPostProcessToggled(bool checked)
|
||||
{
|
||||
postprocessTransparentPostpassCheckBox->setEnabled(checked);
|
||||
postprocessHDRTimeComboBox->setEnabled(checked);
|
||||
postprocessHDRTimeLabel->setEnabled(checked);
|
||||
}
|
||||
|
||||
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;
|
||||
QCompleter mCellNameCompleter;
|
||||
QStringListModel mCellNameCompleterModel;
|
||||
|
||||
MainDialog* mMain;
|
||||
TextInputDialog* mProfileDialog;
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -9,9 +9,7 @@ LineEdit::LineEdit(QWidget* parent)
|
|||
void LineEdit::setupClearButton()
|
||||
{
|
||||
mClearButton = new QToolButton(this);
|
||||
QPixmap pixmap(":images/clear.png");
|
||||
mClearButton->setIcon(QIcon(pixmap));
|
||||
mClearButton->setIconSize(pixmap.size());
|
||||
mClearButton->setIcon(QIcon::fromTheme("edit-clear"));
|
||||
mClearButton->setCursor(Qt::ArrowCursor);
|
||||
mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
||||
mClearButton->hide();
|
||||
|
|
|
@ -13,6 +13,12 @@ ContentSelectorView::ContentSelector::ContentSelector(QWidget* parent, bool show
|
|||
ui.setupUi(parent);
|
||||
ui.addonView->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
|
||||
if (!showOMWScripts)
|
||||
{
|
||||
ui.languageComboBox->setHidden(true);
|
||||
ui.refreshButton->setHidden(true);
|
||||
}
|
||||
|
||||
buildContentModel(showOMWScripts);
|
||||
buildGameFileView();
|
||||
buildAddonView();
|
||||
|
|
|
@ -43,6 +43,8 @@ namespace ContentSelectorView
|
|||
|
||||
QWidget* uiWidget() const { return ui.contentGroupBox; }
|
||||
|
||||
QComboBox* languageBox() const { return ui.languageComboBox; }
|
||||
|
||||
QToolButton* refreshButton() const { return ui.refreshButton; }
|
||||
|
||||
QLineEdit* searchFilter() const { return ui.searchFilter; }
|
||||
|
|
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 |
BIN
files/launcher/icons/tango/16x16/view-refresh.png
Normal file
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 |
|
@ -2,10 +2,7 @@
|
|||
Name=Tango
|
||||
Comment=Tango Theme
|
||||
Inherits=default
|
||||
Directories=16x16,48x48
|
||||
Directories=16x16
|
||||
|
||||
[16x16]
|
||||
Size=16
|
||||
|
||||
[48x48]
|
||||
Size=48
|
||||
Size=16
|
Before Width: | Height: | Size: 362 B |
BIN
files/launcher/images/openmw-header.png
Normal file → Executable file
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>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>518</width>
|
||||
<width>614</width>
|
||||
<height>436</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -66,6 +66,19 @@
|
|||
<item>
|
||||
<widget class="QLineEdit" name="searchFilter"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="languageComboBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select language used by ESM/ESP content files to allow OpenMW to detect their encoding. </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="refreshButton">
|
||||
<property name="enabled">
|
||||
|
|
|
@ -48,57 +48,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="directoryAddSubdirsButton">
|
||||
<property name="toolTip">
|
||||
<string>Scan directories for likely data directories and append them at the end of the list.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Append</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="directoryInsertButton">
|
||||
<property name="toolTip">
|
||||
<string>Scan directories for likely data directories and insert them above the selected position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Insert Above</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="directoryUpButton">
|
||||
<property name="toolTip">
|
||||
<string>Move selected directory one position up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="directoryDownButton">
|
||||
<property name="toolTip">
|
||||
<string>Move selected directory one position down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="directoryRemoveButton">
|
||||
<property name="toolTip">
|
||||
<string>Remove selected directory</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="27" column="0" colspan="2">
|
||||
<item row="32" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
|
@ -111,6 +61,116 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="directoryAddSubdirsButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Scan directories for likely data directories and append them at the end of the list.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Append</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="directoryInsertButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Scan directories for likely data directories and insert them above the selected position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Insert Above</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QPushButton" name="directoryUpButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Move selected directory one position up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QPushButton" name="directoryDownButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Move selected directory one position down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QPushButton" name="directoryRemoveButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove selected directory</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="archiveTab">
|
||||
|
@ -127,6 +187,18 @@
|
|||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="archiveUpButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>33</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Move selected archive one position up</string>
|
||||
</property>
|
||||
|
@ -135,8 +207,27 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="27" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-style:italic;">note: archives that are not part of current Content List are </span><span style=" font-style:italic; background-color:#00ff00;">highlighted</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="archiveDownButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>33</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Move selected archive one position down</string>
|
||||
</property>
|
||||
|
@ -145,13 +236,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="27" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-style:italic;">note: archives that are not part of current Content List are </span><span style=" font-style:italic; background-color:#00ff00;">highlighted</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
|
@ -339,8 +423,7 @@
|
|||
<action name="newProfileAction">
|
||||
<property name="icon">
|
||||
<iconset theme="document-new">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New Content List</string>
|
||||
|
@ -355,8 +438,7 @@
|
|||
<action name="cloneProfileAction">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-copy">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clone Content List</string>
|
||||
|
@ -374,8 +456,7 @@
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="edit-delete">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete Content List</string>
|
||||
|
@ -403,8 +484,7 @@
|
|||
<action name="refreshDataFilesAction">
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh Data Files</string>
|
||||
|
|
146
files/ui/importpage.ui
Normal file
|
@ -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>
|
|
@ -25,32 +25,6 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QListWidget" name="iconWidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#iconWidget {
|
||||
background-image: url(":/images/openmw-header.png");
|
||||
background-color: palette(base);
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: scroll;
|
||||
background-position: right;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="pagesWidget"/>
|
||||
</item>
|
||||
|
@ -86,7 +60,7 @@
|
|||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -94,6 +68,119 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QToolBar {
|
||||
background-attachment: fixed;
|
||||
background-image: url(:/images/openmw-header.png);
|
||||
background-repeat: none;
|
||||
background-position: right;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
QToolButton {
|
||||
min-width: 70px;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="dataAction"/>
|
||||
<addaction name="graphicsAction"/>
|
||||
<addaction name="settingsAction"/>
|
||||
<addaction name="importAction"/>
|
||||
</widget>
|
||||
<action name="dataAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../launcher/launcher.qrc">
|
||||
<normaloff>:/images/openmw-plugin.png</normaloff>:/images/openmw-plugin.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Data Files</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Allows to setup data files and directories</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string/>
|
||||
</property>
|
||||
</action>
|
||||
<action name="graphicsAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../launcher/launcher.qrc">
|
||||
<normaloff>:/images/preferences-video.png</normaloff>:/images/preferences-video.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Graphics</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Allows to change graphics settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="settingsAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../launcher/launcher.qrc">
|
||||
<normaloff>:/images/preferences.png</normaloff>:/images/preferences.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Allows to tweak engine settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="importAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../launcher/launcher.qrc">
|
||||
<normaloff>:/images/preferences-advanced.png</normaloff>:/images/preferences-advanced.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Allows to import data from original engine</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../launcher/launcher.qrc"/>
|
||||
|
|
|
@ -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>
|