Change Background Image for games (#2334)

* Added opacity change instead of blur for background image

* Fixed integer overflow when refreshing grid list

* Added slider to control background image opacity

* Added show background image button

* Added UI code for checkbox and English and Spanish translations for new UI elements

* Removed background image caching

* Background image update on apply/save

* Only recompute image if opacity or game changes

* Fixed segfault when trying to change opacity after table refresh

* Placed background image settings under GUI in settings file
This commit is contained in:
pdaloxd 2025-02-04 08:33:38 +01:00 committed by GitHub
parent 363604c6f0
commit b6ad512e34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 279 additions and 56 deletions

View file

@ -95,6 +95,8 @@ std::vector<std::string> m_pkg_viewer;
std::vector<std::string> m_elf_viewer; std::vector<std::string> m_elf_viewer;
std::vector<std::string> m_recent_files; std::vector<std::string> m_recent_files;
std::string emulator_language = "en"; std::string emulator_language = "en";
static int backgroundImageOpacity = 50;
static bool showBackgroundImage = true;
// Language // Language
u32 m_language = 1; // english u32 m_language = 1; // english
@ -611,6 +613,22 @@ u32 GetLanguage() {
return m_language; return m_language;
} }
int getBackgroundImageOpacity() {
return backgroundImageOpacity;
}
void setBackgroundImageOpacity(int opacity) {
backgroundImageOpacity = std::clamp(opacity, 0, 100);
}
bool getShowBackgroundImage() {
return showBackgroundImage;
}
void setShowBackgroundImage(bool show) {
showBackgroundImage = show;
}
void load(const std::filesystem::path& path) { void load(const std::filesystem::path& path) {
// If the configuration file does not exist, create it and return // If the configuration file does not exist, create it and return
std::error_code error; std::error_code error;
@ -731,6 +749,8 @@ void load(const std::filesystem::path& path) {
m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {}); m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
m_table_mode = toml::find_or<int>(gui, "gameTableMode", 0); m_table_mode = toml::find_or<int>(gui, "gameTableMode", 0);
emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en"); emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en");
backgroundImageOpacity = toml::find_or<int>(gui, "backgroundImageOpacity", 50);
showBackgroundImage = toml::find_or<bool>(gui, "showBackgroundImage", true);
} }
if (data.contains("Settings")) { if (data.contains("Settings")) {
@ -821,6 +841,8 @@ void save(const std::filesystem::path& path) {
data["GUI"]["addonInstallDir"] = data["GUI"]["addonInstallDir"] =
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
data["GUI"]["emulatorLanguage"] = emulator_language; data["GUI"]["emulatorLanguage"] = emulator_language;
data["GUI"]["backgroundImageOpacity"] = backgroundImageOpacity;
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
data["Settings"]["consoleLanguage"] = m_language; data["Settings"]["consoleLanguage"] = m_language;
std::ofstream file(path, std::ios::binary); std::ofstream file(path, std::ios::binary);
@ -914,6 +936,8 @@ void setDefaultValues() {
separateupdatefolder = false; separateupdatefolder = false;
compatibilityData = false; compatibilityData = false;
checkCompatibilityOnStartup = false; checkCompatibilityOnStartup = false;
backgroundImageOpacity = 50;
showBackgroundImage = true;
} }
constexpr std::string_view GetDefaultKeyboardConfig() { constexpr std::string_view GetDefaultKeyboardConfig() {

View file

@ -30,6 +30,8 @@ bool getEnableDiscordRPC();
bool getSeparateUpdateEnabled(); bool getSeparateUpdateEnabled();
bool getCompatibilityEnabled(); bool getCompatibilityEnabled();
bool getCheckCompatibilityOnStartup(); bool getCheckCompatibilityOnStartup();
int getBackgroundImageOpacity();
bool getShowBackgroundImage();
std::string getLogFilter(); std::string getLogFilter();
std::string getLogType(); std::string getLogType();
@ -88,6 +90,8 @@ void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_insta
void setSaveDataPath(const std::filesystem::path& path); void setSaveDataPath(const std::filesystem::path& path);
void setCompatibilityEnabled(bool use); void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use); void setCheckCompatibilityOnStartup(bool use);
void setBackgroundImageOpacity(int opacity);
void setShowBackgroundImage(bool show);
void setCursorState(s16 cursorState); void setCursorState(s16 cursorState);
void setCursorHideTimeout(int newcursorHideTimeout); void setCursorHideTimeout(int newcursorHideTimeout);

View file

@ -38,17 +38,34 @@ GameGridFrame::GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get,
void GameGridFrame::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, void GameGridFrame::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow,
int previousColumn) { int previousColumn) {
crtRow = currentRow; // Early exit for invalid indices
crtColumn = currentColumn; if (currentRow < 0 || currentColumn < 0) {
columnCnt = this->columnCount();
auto itemID = (crtRow * columnCnt) + currentColumn;
if (itemID > m_game_info->m_games.count() - 1) {
cellClicked = false; cellClicked = false;
validCellSelected = false; validCellSelected = false;
BackgroundMusicPlayer::getInstance().stopMusic(); BackgroundMusicPlayer::getInstance().stopMusic();
return; return;
} }
crtRow = currentRow;
crtColumn = currentColumn;
columnCnt = this->columnCount();
// Prevent integer overflow
if (columnCnt <= 0 || crtRow > (std::numeric_limits<int>::max() / columnCnt)) {
cellClicked = false;
validCellSelected = false;
BackgroundMusicPlayer::getInstance().stopMusic();
return;
}
auto itemID = (crtRow * columnCnt) + currentColumn;
if (itemID < 0 || itemID > m_game_info->m_games.count() - 1) {
cellClicked = false;
validCellSelected = false;
BackgroundMusicPlayer::getInstance().stopMusic();
return;
}
cellClicked = true; cellClicked = true;
validCellSelected = true; validCellSelected = true;
SetGridBackgroundImage(crtRow, crtColumn); SetGridBackgroundImage(crtRow, crtColumn);
@ -65,6 +82,8 @@ void GameGridFrame::PlayBackgroundMusic(QString path) {
} }
void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool fromSearch) { void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool fromSearch) {
this->crtRow = -1;
this->crtColumn = -1;
QVector<GameInfo> m_games_; QVector<GameInfo> m_games_;
this->clearContents(); this->clearContents();
if (fromSearch) if (fromSearch)
@ -136,44 +155,49 @@ void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool from
} }
void GameGridFrame::SetGridBackgroundImage(int row, int column) { void GameGridFrame::SetGridBackgroundImage(int row, int column) {
int itemID = (row * this->columnCount()) + column; int itemID = (row * this->columnCount()) + column;
QWidget* item = this->cellWidget(row, column); QWidget* item = this->cellWidget(row, column);
if (item) { if (!item) {
QString pic1Path; // handle case where no item was clicked
Common::FS::PathToQString(pic1Path, (*m_games_shared)[itemID].pic_path); return;
const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
(*m_games_shared)[itemID].serial / "pic1.png";
QString blurredPic1PathQt;
Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path);
backgroundImage = QImage(blurredPic1PathQt);
if (backgroundImage.isNull()) {
QImage image(pic1Path);
backgroundImage = m_game_list_utils.BlurImage(image, image.rect(), 16);
std::filesystem::path img_path =
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
(*m_games_shared)[itemID].serial;
std::filesystem::create_directories(img_path);
if (!backgroundImage.save(blurredPic1PathQt, "PNG")) {
// qDebug() << "Error: Unable to save image.";
}
} }
// If background images are hidden, clear the background image
if (!Config::getShowBackgroundImage()) {
backgroundImage = QImage();
m_last_opacity = -1; // Reset opacity tracking when disabled
m_current_game_path.clear(); // Reset current game path
RefreshGridBackgroundImage(); RefreshGridBackgroundImage();
return;
} }
const auto& game = (*m_games_shared)[itemID];
const int opacity = Config::getBackgroundImageOpacity();
// Recompute if opacity changed or we switched to a different game
if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
QImage original_image(QString::fromStdString(game.pic_path.string()));
if (!original_image.isNull()) {
backgroundImage = m_game_list_utils.ChangeImageOpacity(
original_image, original_image.rect(), opacity / 100.0f);
m_last_opacity = opacity;
m_current_game_path = game.pic_path;
}
}
RefreshGridBackgroundImage();
} }
void GameGridFrame::RefreshGridBackgroundImage() { void GameGridFrame::RefreshGridBackgroundImage() {
if (!backgroundImage.isNull()) {
QPalette palette; QPalette palette;
if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) {
palette.setBrush(QPalette::Base, palette.setBrush(QPalette::Base,
QBrush(backgroundImage.scaled(size(), Qt::IgnoreAspectRatio))); QBrush(backgroundImage.scaled(size(), Qt::IgnoreAspectRatio)));
}
QColor transparentColor = QColor(135, 206, 235, 40); QColor transparentColor = QColor(135, 206, 235, 40);
palette.setColor(QPalette::Highlight, transparentColor); palette.setColor(QPalette::Highlight, transparentColor);
this->setPalette(palette); this->setPalette(palette);
} }
}
bool GameGridFrame::IsValidCellSelected() { bool GameGridFrame::IsValidCellSelected() {
return validCellSelected; return validCellSelected;

View file

@ -33,6 +33,8 @@ private:
std::shared_ptr<CompatibilityInfoClass> m_compat_info; std::shared_ptr<CompatibilityInfoClass> m_compat_info;
std::shared_ptr<QVector<GameInfo>> m_games_shared; std::shared_ptr<QVector<GameInfo>> m_games_shared;
bool validCellSelected = false; bool validCellSelected = false;
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
std::filesystem::path m_current_game_path; // Track current game path to detect changes
public: public:
explicit GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, explicit GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get,

View file

@ -89,6 +89,7 @@ void GameListFrame::onCurrentCellChanged(int currentRow, int currentColumn, int
if (!item) { if (!item) {
return; return;
} }
m_current_item = item; // Store current item
SetListBackgroundImage(item); SetListBackgroundImage(item);
PlayBackgroundMusic(item); PlayBackgroundMusic(item);
} }
@ -104,6 +105,7 @@ void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
} }
void GameListFrame::PopulateGameList(bool isInitialPopulation) { void GameListFrame::PopulateGameList(bool isInitialPopulation) {
this->m_current_item = nullptr;
// Do not show status column if it is not enabled // Do not show status column if it is not enabled
this->setColumnHidden(2, !Config::getCompatibilityEnabled()); this->setColumnHidden(2, !Config::getCompatibilityEnabled());
this->setColumnHidden(6, !Config::GetLoadGameSizeEnabled()); this->setColumnHidden(6, !Config::GetLoadGameSizeEnabled());
@ -167,39 +169,42 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
return; return;
} }
QString pic1Path; // If background images are hidden, clear the background image
Common::FS::PathToQString(pic1Path, m_game_info->m_games[item->row()].pic_path); if (!Config::getShowBackgroundImage()) {
const auto blurredPic1Path = Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / backgroundImage = QImage();
m_game_info->m_games[item->row()].serial / "pic1.png"; m_last_opacity = -1; // Reset opacity tracking when disabled
QString blurredPic1PathQt; m_current_game_path.clear(); // Reset current game path
Common::FS::PathToQString(blurredPic1PathQt, blurredPic1Path); RefreshListBackgroundImage();
return;
}
backgroundImage = QImage(blurredPic1PathQt); const auto& game = m_game_info->m_games[item->row()];
if (backgroundImage.isNull()) { const int opacity = Config::getBackgroundImageOpacity();
QImage image(pic1Path);
backgroundImage = m_game_list_utils.BlurImage(image, image.rect(), 16);
std::filesystem::path img_path = // Recompute if opacity changed or we switched to a different game
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
m_game_info->m_games[item->row()].serial; QImage original_image(QString::fromStdString(game.pic_path.string()));
std::filesystem::create_directories(img_path); if (!original_image.isNull()) {
if (!backgroundImage.save(blurredPic1PathQt, "PNG")) { backgroundImage = m_game_list_utils.ChangeImageOpacity(
// qDebug() << "Error: Unable to save image."; original_image, original_image.rect(), opacity / 100.0f);
m_last_opacity = opacity;
m_current_game_path = game.pic_path;
} }
} }
RefreshListBackgroundImage(); RefreshListBackgroundImage();
} }
void GameListFrame::RefreshListBackgroundImage() { void GameListFrame::RefreshListBackgroundImage() {
if (!backgroundImage.isNull()) {
QPalette palette; QPalette palette;
if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) {
palette.setBrush(QPalette::Base, palette.setBrush(QPalette::Base,
QBrush(backgroundImage.scaled(size(), Qt::IgnoreAspectRatio))); QBrush(backgroundImage.scaled(size(), Qt::IgnoreAspectRatio)));
}
QColor transparentColor = QColor(135, 206, 235, 40); QColor transparentColor = QColor(135, 206, 235, 40);
palette.setColor(QPalette::Highlight, transparentColor); palette.setColor(QPalette::Highlight, transparentColor);
this->setPalette(palette); this->setPalette(palette);
} }
}
void GameListFrame::SortNameAscending(int columnIndex) { void GameListFrame::SortNameAscending(int columnIndex) {
std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(), std::sort(m_game_info->m_games.begin(), m_game_info->m_games.end(),
@ -392,3 +397,7 @@ QString GameListFrame::GetPlayTime(const std::string& serial) {
file.close(); file.close();
return playTime; return playTime;
} }
QTableWidgetItem* GameListFrame::GetCurrentItem() {
return m_current_item;
}

View file

@ -44,11 +44,14 @@ private:
QList<QAction*> m_columnActs; QList<QAction*> m_columnActs;
GameInfoClass* game_inf_get = nullptr; GameInfoClass* game_inf_get = nullptr;
bool ListSortedAsc = true; bool ListSortedAsc = true;
QTableWidgetItem* m_current_item = nullptr;
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
std::filesystem::path m_current_game_path; // Track current game path to detect changes
public: public:
void PopulateGameList(bool isInitialPopulation = true); void PopulateGameList(bool isInitialPopulation = true);
void ResizeIcons(int iconSize); void ResizeIcons(int iconSize);
QTableWidgetItem* GetCurrentItem();
QImage backgroundImage; QImage backgroundImage;
GameListUtils m_game_list_utils; GameListUtils m_game_list_utils;
GuiContextMenus m_gui_context_menus; GuiContextMenus m_gui_context_menus;

View file

@ -201,4 +201,30 @@ public:
return result; return result;
} }
// Opacity is a float between 0 and 1
static QImage ChangeImageOpacity(const QImage& image, const QRect& rect, float opacity) {
// Convert to ARGB32 format to ensure alpha channel support
QImage result = image.convertToFormat(QImage::Format_ARGB32);
// Ensure opacity is between 0 and 1
opacity = std::clamp(opacity, 0.0f, 1.0f);
// Convert opacity to integer alpha value (0-255)
int alpha = static_cast<int>(opacity * 255);
// Process only the specified rectangle area
for (int y = rect.top(); y <= rect.bottom(); ++y) {
QRgb* line = reinterpret_cast<QRgb*>(result.scanLine(y));
for (int x = rect.left(); x <= rect.right(); ++x) {
// Get current pixel
QRgb pixel = line[x];
// Keep RGB values, but modify alpha while preserving relative transparency
int newAlpha = (qAlpha(pixel) * alpha) / 255;
line[x] = qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), newAlpha);
}
}
return result;
}
}; };

View file

@ -297,6 +297,23 @@ void MainWindow::CreateConnects() {
connect(settingsDialog, &SettingsDialog::CompatibilityChanged, this, connect(settingsDialog, &SettingsDialog::CompatibilityChanged, this,
&MainWindow::RefreshGameTable); &MainWindow::RefreshGameTable);
connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this,
[this](int opacity) {
Config::setBackgroundImageOpacity(opacity);
if (m_game_list_frame) {
QTableWidgetItem* current = m_game_list_frame->GetCurrentItem();
if (current) {
m_game_list_frame->SetListBackgroundImage(current);
}
}
if (m_game_grid_frame) {
if (m_game_grid_frame->IsValidCellSelected()) {
m_game_grid_frame->SetGridBackgroundImage(m_game_grid_frame->crtRow,
m_game_grid_frame->crtColumn);
}
}
});
settingsDialog->exec(); settingsDialog->exec();
}); });

View file

@ -173,6 +173,9 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
{ {
connect(ui->chooseHomeTabComboBox, &QComboBox::currentTextChanged, this, connect(ui->chooseHomeTabComboBox, &QComboBox::currentTextChanged, this,
[](const QString& hometab) { Config::setChooseHomeTab(hometab.toStdString()); }); [](const QString& hometab) { Config::setChooseHomeTab(hometab.toStdString()); });
connect(ui->showBackgroundImageCheckBox, &QCheckBox::stateChanged, this,
[](int state) { Config::setShowBackgroundImage(state == Qt::Checked); });
} }
// Input TAB // Input TAB
{ {
@ -251,6 +254,7 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
ui->updaterGroupBox->installEventFilter(this); ui->updaterGroupBox->installEventFilter(this);
#endif #endif
ui->GUIBackgroundImageGroupBox->installEventFilter(this);
ui->GUIMusicGroupBox->installEventFilter(this); ui->GUIMusicGroupBox->installEventFilter(this);
ui->disableTrophycheckBox->installEventFilter(this); ui->disableTrophycheckBox->installEventFilter(this);
ui->enableCompatibilityCheckBox->installEventFilter(this); ui->enableCompatibilityCheckBox->installEventFilter(this);
@ -410,6 +414,8 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty()); ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty());
ResetInstallFolders(); ResetInstallFolders();
ui->backgroundImageOpacitySlider->setValue(Config::getBackgroundImageOpacity());
ui->showBackgroundImageCheckBox->setChecked(Config::getShowBackgroundImage());
} }
void SettingsDialog::InitializeEmulatorLanguages() { void SettingsDialog::InitializeEmulatorLanguages() {
@ -504,6 +510,8 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
} else if (elementName == "updaterGroupBox") { } else if (elementName == "updaterGroupBox") {
text = tr("updaterGroupBox"); text = tr("updaterGroupBox");
#endif #endif
} else if (elementName == "GUIBackgroundImageGroupBox") {
text = tr("GUIBackgroundImageGroupBox");
} else if (elementName == "GUIMusicGroupBox") { } else if (elementName == "GUIMusicGroupBox") {
text = tr("GUIMusicGroupBox"); text = tr("GUIMusicGroupBox");
} else if (elementName == "disableTrophycheckBox") { } else if (elementName == "disableTrophycheckBox") {
@ -638,6 +646,9 @@ void SettingsDialog::UpdateSettings() {
Config::setChooseHomeTab(ui->chooseHomeTabComboBox->currentText().toStdString()); Config::setChooseHomeTab(ui->chooseHomeTabComboBox->currentText().toStdString());
Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked()); Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked());
Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked()); Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked());
Config::setBackgroundImageOpacity(ui->backgroundImageOpacitySlider->value());
emit BackgroundOpacityChanged(ui->backgroundImageOpacitySlider->value());
Config::setShowBackgroundImage(ui->showBackgroundImageCheckBox->isChecked());
#ifdef ENABLE_DISCORD_RPC #ifdef ENABLE_DISCORD_RPC
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance(); auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();

View file

@ -33,6 +33,7 @@ public:
signals: signals:
void LanguageChanged(const std::string& locale); void LanguageChanged(const std::string& locale);
void CompatibilityChanged(); void CompatibilityChanged();
void BackgroundOpacityChanged(int opacity);
private: private:
void LoadValuesFromConfig(); void LoadValuesFromConfig();

View file

@ -583,6 +583,76 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="GUIBackgroundImageGroupBox">
<property name="title">
<string>Background Image</string>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="backgroundImageVLayout">
<item>
<widget class="QCheckBox" name="showBackgroundImageCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show Background Image</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="opacityLayout">
<property name="spacing">
<number>9</number>
</property>
<item>
<widget class="QLabel" name="backgroundImageOpacityLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Opacity</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="backgroundImageOpacitySlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="GUIMusicGroupBox"> <widget class="QGroupBox" name="GUIMusicGroupBox">
<property name="sizePolicy"> <property name="sizePolicy">

View file

@ -757,6 +757,18 @@
<source>Disable Trophy Pop-ups</source> <source>Disable Trophy Pop-ups</source>
<translation>Disable Trophy Pop-ups</translation> <translation>Disable Trophy Pop-ups</translation>
</message> </message>
<message>
<source>Background Image</source>
<translation>Background Image</translation>
</message>
<message>
<source>Show Background Image</source>
<translation>Show Background Image</translation>
</message>
<message>
<source>Opacity</source>
<translation>Opacity</translation>
</message>
<message> <message>
<source>Play title music</source> <source>Play title music</source>
<translation>Play title music</translation> <translation>Play title music</translation>
@ -853,6 +865,10 @@
<source>updaterGroupBox</source> <source>updaterGroupBox</source>
<translation>Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable.</translation> <translation>Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable.</translation>
</message> </message>
<message>
<source>GUIBackgroundImageGroupBox</source>
<translation>Background Image:\nControl the opacity of the game background image.</translation>
</message>
<message> <message>
<source>GUIMusicGroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</translation> <translation>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</translation>

View file

@ -748,6 +748,18 @@
<source>Disable Trophy Pop-ups</source> <source>Disable Trophy Pop-ups</source>
<translation>Disable Trophy Pop-ups</translation> <translation>Disable Trophy Pop-ups</translation>
</message> </message>
<message>
<source>Background Image</source>
<translation>Imagen de fondo</translation>
</message>
<message>
<source>Show Background Image</source>
<translation>Mostrar Imagen de Fondo</translation>
</message>
<message>
<source>Opacity</source>
<translation>Opacidad</translation>
</message>
<message> <message>
<source>Play title music</source> <source>Play title music</source>
<translation>Reproducir la música de apertura</translation> <translation>Reproducir la música de apertura</translation>
@ -844,6 +856,10 @@
<source>updaterGroupBox</source> <source>updaterGroupBox</source>
<translation>Actualización:\nRelease: Versiones oficiales lanzadas cada mes que pueden estar muy desactualizadas, pero son más confiables y están probadas.\nNightly: Versiones de desarrollo que tienen todas las últimas funciones y correcciones, pero pueden contener errores y son menos estables.</translation> <translation>Actualización:\nRelease: Versiones oficiales lanzadas cada mes que pueden estar muy desactualizadas, pero son más confiables y están probadas.\nNightly: Versiones de desarrollo que tienen todas las últimas funciones y correcciones, pero pueden contener errores y son menos estables.</translation>
</message> </message>
<message>
<source>GUIBackgroundImageGroupBox</source>
<translation>Imagen de fondo:\nControle la opacidad de la imagen de fondo del juego.</translation>
</message>
<message> <message>
<source>GUIMusicGroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Reproducir Música del Título:\nSi un juego lo admite, habilita la reproducción de música especial al seleccionar el juego en la interfaz gráfica.</translation> <translation>Reproducir Música del Título:\nSi un juego lo admite, habilita la reproducción de música especial al seleccionar el juego en la interfaz gráfica.</translation>