diff --git a/cockatrice/src/game_graphics/log/message_log_widget.cpp b/cockatrice/src/game_graphics/log/message_log_widget.cpp
index b998a3650..06b0301bd 100644
--- a/cockatrice/src/game_graphics/log/message_log_widget.cpp
+++ b/cockatrice/src/game_graphics/log/message_log_widget.cpp
@@ -6,7 +6,6 @@
#include "../../game/game_state.h"
#include "../../game/phase.h"
#include "../../game/player/player_logic.h"
-#include "../../interface/card_localization.h"
#include "../../interface/widgets/tabs/tab_game.h"
#include "../board/card_item.h"
#include "../board/translate_counter_name.h"
@@ -24,11 +23,7 @@ static QString sanitizeHtml(QString dirty)
static QString cardLink(const QString &cardName)
{
- // The href keeps the canonical name so the card popup can resolve it, while the label shows the name
- // in the configured card language.
- return QString("%2")
- .arg(sanitizeHtml(cardName))
- .arg(sanitizeHtml(CardLocalization::displayNameFor(cardName)));
+ return QString("%2").arg(cardName).arg(cardName);
}
QPair
@@ -808,9 +803,10 @@ void MessageLogWidget::logUndoDraw(PlayerLogic *player, QString cardName)
if (cardName.isEmpty()) {
appendHtmlServerMessage(tr("%1 undoes their last draw.").arg(sanitizeHtml(player->getPlayerInfo()->getName())));
} else {
- appendHtmlServerMessage(tr("%1 undoes their last draw (%2).")
- .arg(sanitizeHtml(player->getPlayerInfo()->getName()))
- .arg(cardLink(std::move(cardName))));
+ appendHtmlServerMessage(
+ tr("%1 undoes their last draw (%2).")
+ .arg(sanitizeHtml(player->getPlayerInfo()->getName()))
+ .arg(QString("%2").arg(sanitizeHtml(cardName)).arg(sanitizeHtml(cardName))));
}
}
diff --git a/cockatrice/src/interface/card_localization.h b/cockatrice/src/interface/card_localization.h
index 1a1e7be5d..0bfe4a764 100644
--- a/cockatrice/src/interface/card_localization.h
+++ b/cockatrice/src/interface/card_localization.h
@@ -5,7 +5,6 @@
#include
#include
-#include
#include
namespace CardLocalization
@@ -55,25 +54,6 @@ inline QString displayText(const CardInfo &card)
{
return card.getLocalizedText(displayLang());
}
-
-/**
- * @brief Looks a card up by its canonical name and returns its name in the configured display language.
- *
- * Use this where only the canonical name is known, such as the game log or [card] chat tags. Callers that
- * already hold a resolved card and need to keep the canonical name around (as a link target, say) should
- * use displayName() directly instead.
- *
- * @param cardName The canonical card name.
- * @return The localized name, or cardName unchanged when the card is unknown to the database.
- */
-inline QString displayNameFor(const QString &cardName)
-{
- if (cardName.isEmpty()) {
- return cardName;
- }
- const QString localizedName = displayName(CardDatabaseManager::query()->getCardInfo(cardName));
- return localizedName.isEmpty() ? cardName : localizedName;
-}
} // namespace CardLocalization
#endif // COCKATRICE_CARD_LOCALIZATION_H
\ No newline at end of file
diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp
index 08374c8fd..d93dfcf62 100644
--- a/cockatrice/src/interface/theme_manager.cpp
+++ b/cockatrice/src/interface/theme_manager.cpp
@@ -23,7 +23,6 @@
#include
#define SYSTEM_THEME_NAME "System"
-#define LEGACY_SYSTEM_THEME_NAME "Default"
#define FUSION_THEME_NAME "Fusion"
#define STYLE_CSS_NAME "style.css"
#define HANDZONE_BG_NAME "handzone"
@@ -123,84 +122,12 @@ ThemeManager::ThemeManager(QObject *parent) : QObject(parent)
themeChangedSlot();
}
-// Copy every file of sourceDir into targetDir without ever overwriting an
-// existing file, recursing into subdirectories (zones/, backgrounds/, ...).
-// Returns false as soon as an entry could not be copied, leaving the source
-// untouched so the caller can retry later.
-static bool mergeDirWithoutOverwrite(const QString &sourceDir, const QString &targetDir)
-{
- const QDir target(targetDir);
- bool merged = true;
-
- const QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden;
- for (const QFileInfo &entry : QDir(sourceDir).entryInfoList(filters)) {
- const QString targetEntry = target.absoluteFilePath(entry.fileName());
- if (entry.isDir()) {
- if (!QDir().mkpath(targetEntry) || !mergeDirWithoutOverwrite(entry.absoluteFilePath(), targetEntry)) {
- merged = false;
- }
- } else if (!target.exists(entry.fileName()) && !QFile::copy(entry.absoluteFilePath(), targetEntry)) {
- qCWarning(ThemeManagerLog) << "Could not migrate theme file:" << entry.absoluteFilePath();
- merged = false;
- }
- }
-
- return merged;
-}
-
-void ThemeManager::migrateLegacyThemeDir(const QString &themesPath, const QString ¤tThemeName)
-{
- const QString legacyPath = QDir(themesPath).absoluteFilePath(LEGACY_SYSTEM_THEME_NAME);
- if (!QDir(legacyPath).exists()) {
- return;
- }
-
- // Only the renamed theme's own directory is migrated. A user sitting on a
- // different theme may well have hand-made a "Default" folder of their own,
- // and silently folding it into "System" would be rude. The check accepts
- // both the pre-rename name and the post-rename one, since a user who
- // already ran the rename keeps their settings on "System" while their
- // customised directory is still called "Default".
- if (currentThemeName != LEGACY_SYSTEM_THEME_NAME && currentThemeName != SYSTEM_THEME_NAME) {
- return;
- }
-
- const QString targetPath = QDir(themesPath).absoluteFilePath(SYSTEM_THEME_NAME);
- if (!QDir(targetPath).exists() && QDir().rename(legacyPath, targetPath)) {
- qCInfo(ThemeManagerLog) << "Migrated customised theme directory" << LEGACY_SYSTEM_THEME_NAME << "to"
- << SYSTEM_THEME_NAME;
- return;
- }
-
- // The rename is only possible when the target does not exist yet. When it
- // does (a partial earlier upgrade, or a user who re-customised the theme
- // after the rename), fall back to merging so nothing is lost: existing
- // "System" files win, legacy files only fill gaps. Because every legacy
- // file either already exists at the target or is copied there, removing
- // the legacy directory afterwards cannot drop user data.
- if (!mergeDirWithoutOverwrite(legacyPath, targetPath)) {
- qCWarning(ThemeManagerLog) << "Could not fully migrate theme directory" << legacyPath << "; keeping it for a"
- << "later retry";
- return;
- }
- if (!QDir(legacyPath).removeRecursively()) {
- qCWarning(ThemeManagerLog) << "Migrated theme directory but could not remove the legacy one:" << legacyPath;
- return;
- }
- qCInfo(ThemeManagerLog) << "Merged customised theme directory" << LEGACY_SYSTEM_THEME_NAME << "into"
- << SYSTEM_THEME_NAME;
-}
-
void ThemeManager::ensureThemeDirectoryExists()
{
auto &settings = SettingsCache::instance();
- // Carry the user's theme customisations (zone graphics, stylesheets,
- // palettes, theme.cfg) across before the stored name is rewritten.
- migrateLegacyThemeDir(settings.paths().getThemesPath(), settings.getThemeName());
-
// Migrate the old "Default" theme name to "System"
- if (settings.getThemeName() == LEGACY_SYSTEM_THEME_NAME) {
+ if (settings.getThemeName() == "Default") {
settings.setThemeName(SYSTEM_THEME_NAME);
}
diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h
index 4c9d070dc..aadb38ee9 100644
--- a/cockatrice/src/interface/theme_manager.h
+++ b/cockatrice/src/interface/theme_manager.h
@@ -71,14 +71,6 @@ public:
// read-only system themes fall back to the user themes directory, creating
// it if needed, so customisations never get lost on upgrade.
static QString writableThemeDir(const QString &themeName);
- // Carries a user profile's customised "Default" theme directory over to the
- // "System" directory the theme was renamed to, so zone graphics,
- // stylesheets, palettes and theme.cfg survive the rename. Renames the
- // directory when "System" does not exist yet, otherwise merges file by
- // file without overwriting what "System" already has. No-op unless the
- // active theme is one of the two names, so a hand-made "Default" folder of
- // a user on another theme is left alone.
- static void migrateLegacyThemeDir(const QString &themesPath, const QString ¤tThemeName);
// Probe whether a directory is truly writable by trying to create and remove
// a temporary file. QFileInfo::isWritable() on a directory is unreliable
// (notably on Windows where UAC VirtualStore can make a system dir appear
diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp
index 91a7cb965..ae9b2deb4 100644
--- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp
+++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp
@@ -2,7 +2,6 @@
#include "../../../../client/settings/cache_settings.h"
#include "../../client/sound_engine.h"
-#include "../../interface/card_localization.h"
#include "../../interface/pixel_map_generator.h"
#include "../../interface/widgets/tabs/tab_account.h"
#include "../user/user_context_menu.h"
@@ -191,8 +190,7 @@ void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName)
QTextCharFormat cardFormat = oldFormat;
cardFormat.setFontItalic(true);
- const CardInfoPtr card = CardDatabaseManager::query()->lookupCardByName(cardName);
- if (card.isNull()) {
+ if (!CardDatabaseManager::query()->lookupCardByName(cardName)) {
cardFormat.setForeground(unresolvedCardTagColor);
cursor.setCharFormat(cardFormat);
cursor.insertText(cardName);
@@ -202,12 +200,10 @@ void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName)
cardFormat.setForeground(linkColor);
cardFormat.setAnchor(true);
- // The href keeps the canonical name so the card popup can resolve it, while the text shows the name
- // in the configured card language.
cardFormat.setAnchorHref("card://" + cardName);
cursor.setCharFormat(cardFormat);
- cursor.insertText(CardLocalization::displayName(card));
+ cursor.insertText(cardName);
cursor.setCharFormat(oldFormat);
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5c12957fb..1f9cdb9a3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -178,11 +178,6 @@ add_subdirectory(movecard_tests)
add_subdirectory(oracle)
add_subdirectory(settings)
-# theme_migration_test compiles client sources, whose headers are only reachable from a client build.
-if(WITH_CLIENT)
- add_subdirectory(theme_migration)
-endif()
-
# picture_loader_benchmark links libcockatrice_settings, which only exists when
# a client/UI-capable target is being built.
if(WITH_ORACLE OR WITH_CLIENT)
diff --git a/tests/settings/settings_migration_test.cpp b/tests/settings/settings_migration_test.cpp
index 4fa843abf..8a3d756a0 100644
--- a/tests/settings/settings_migration_test.cpp
+++ b/tests/settings/settings_migration_test.cpp
@@ -542,34 +542,6 @@ TEST_F(SettingsMigrationTest, PartialMigrationOnlyMigratesPresentKeys)
ASSERT_FALSE(fileExists("chat.ini"));
}
-TEST_F(SettingsMigrationTest, ThemeNameDefaultIsRewrittenToSystem)
-{
- {
- QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
- g.setValue("theme/name", "Default");
- g.sync();
- }
-
- ASSERT_TRUE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
-
- ASSERT_TRUE(fileExists("appearance.ini"));
- ASSERT_EQ(readFromIni("appearance.ini", "appearance/themeName"), QVariant("System"));
-}
-
-TEST_F(SettingsMigrationTest, OtherThemeNamesAreLeftAlone)
-{
- {
- QSettings g(settingsPath + "global.ini", QSettings::IniFormat);
- g.setValue("theme/name", "VelvetMarble");
- g.sync();
- }
-
- ASSERT_TRUE(SettingsMigration::migrateSettingsFromGlobalIni(settingsPath));
-
- ASSERT_TRUE(fileExists("appearance.ini"));
- ASSERT_EQ(readFromIni("appearance.ini", "appearance/themeName"), QVariant("VelvetMarble"));
-}
-
TEST_F(SettingsMigrationTest, KeyMapTranslationIsCorrect)
{
{
diff --git a/tests/theme_migration/CMakeLists.txt b/tests/theme_migration/CMakeLists.txt
deleted file mode 100644
index ac202210e..000000000
--- a/tests/theme_migration/CMakeLists.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-add_executable(
- theme_migration_test
- ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/theme_manager.cpp
- ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/theme_config.cpp
- ${CMAKE_SOURCE_DIR}/cockatrice/src/interface/pixel_map_generator.cpp
- ${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/cache_settings.cpp
- ${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/card_counter_settings.cpp
- ${CMAKE_SOURCE_DIR}/cockatrice/src/client/settings/shortcuts_settings.cpp
- ${CMAKE_SOURCE_DIR}/cockatrice/src/client/network/update/client/release_channel.cpp
- ${VERSION_STRING_CPP}
- theme_migration_test.cpp
-)
-target_include_directories(theme_migration_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src)
-
-target_link_libraries(
- theme_migration_test
- libcockatrice_settings
- libcockatrice_network
- libcockatrice_network_server_remote
- libcockatrice_protocol
- Threads::Threads
- ${GTEST_BOTH_LIBRARIES}
- ${TEST_QT_MODULES}
-)
-
-add_test(NAME theme_migration_test COMMAND theme_migration_test)
-
-if(NOT GTEST_FOUND)
- add_dependencies(theme_migration_test gtest)
-endif()
diff --git a/tests/theme_migration/theme_migration_test.cpp b/tests/theme_migration/theme_migration_test.cpp
deleted file mode 100644
index 147833630..000000000
--- a/tests/theme_migration/theme_migration_test.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-#include "interface/theme_manager.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-// Owned by main.cpp in the real application; pixel_map_generator.cpp references
-// it, so the test binary needs a definition even though it never renders.
-ThemeManager *themeManager = nullptr;
-
-namespace
-{
-const QString LEGACY = QStringLiteral("Default");
-const QString CURRENT = QStringLiteral("System");
-
-// Writes content at //, creating parents.
-void writeThemeFile(const QString &themesPath,
- const QString &theme,
- const QString &relativePath,
- const QByteArray &content)
-{
- const QString filePath = QDir(QDir(themesPath).absoluteFilePath(theme)).absoluteFilePath(relativePath);
- ASSERT_TRUE(QDir().mkpath(QFileInfo(filePath).absolutePath()));
- QFile file(filePath);
- ASSERT_TRUE(file.open(QIODevice::WriteOnly));
- file.write(content);
- file.close();
-}
-
-QByteArray readThemeFile(const QString &themesPath, const QString &theme, const QString &relativePath)
-{
- QFile file(QDir(QDir(themesPath).absoluteFilePath(theme)).absoluteFilePath(relativePath));
- if (!file.open(QIODevice::ReadOnly)) {
- return QByteArray();
- }
- return file.readAll();
-}
-
-class ThemeMigrationTest : public ::testing::Test
-{
-protected:
- QTemporaryDir tmp;
- QString themesPath;
-
- void SetUp() override
- {
- ASSERT_TRUE(tmp.isValid());
- themesPath = QDir(tmp.path()).absoluteFilePath("themes");
- ASSERT_TRUE(QDir().mkpath(themesPath));
- }
-};
-
-} // namespace
-
-TEST_F(ThemeMigrationTest, NoLegacyDirectoryIsANoOp)
-{
- writeThemeFile(themesPath, CURRENT, "theme.cfg", "[Appearance]\n");
-
- ThemeManager::migrateLegacyThemeDir(themesPath, CURRENT);
-
- EXPECT_TRUE(QDir(QDir(themesPath).absoluteFilePath(CURRENT)).exists());
- EXPECT_TRUE(QDir(QDir(themesPath).absoluteFilePath(LEGACY)).exists() == false);
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "theme.cfg").toStdString(), std::string("[Appearance]\n"));
-}
-
-TEST_F(ThemeMigrationTest, RenamesDirectoryWhenTargetIsFree)
-{
- // A customised "Default": stylesheet, zone graphics in a subdirectory and a
- // palette, i.e. everything a user is liable to have personalised.
- writeThemeFile(themesPath, LEGACY, "style.css", "QPushButton { color: red; }");
- writeThemeFile(themesPath, LEGACY, "zones/handzone.png", "handzone-bytes");
- writeThemeFile(themesPath, LEGACY, "zones/tablezone-dark.svg", "tablezone-bytes");
- writeThemeFile(themesPath, LEGACY, "palette-dark.toml", "palette");
-
- ThemeManager::migrateLegacyThemeDir(themesPath, LEGACY);
-
- EXPECT_FALSE(QDir(QDir(themesPath).absoluteFilePath(LEGACY)).exists());
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "style.css").toStdString(),
- std::string("QPushButton { color: red; }"));
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "zones/handzone.png").toStdString(), std::string("handzone-bytes"));
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "zones/tablezone-dark.svg").toStdString(),
- std::string("tablezone-bytes"));
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "palette-dark.toml").toStdString(), std::string("palette"));
-}
-
-TEST_F(ThemeMigrationTest, RenamesForAnAlreadyMigratedUserWhoseDirectoryWasLeftBehind)
-{
- // The settings value was rewritten to "System" on an earlier run, but the
- // customised directory is still called "Default". The customisations are
- // still reachable and must still be carried over.
- writeThemeFile(themesPath, LEGACY, "style.css", "legacy-css");
-
- ThemeManager::migrateLegacyThemeDir(themesPath, CURRENT);
-
- EXPECT_FALSE(QDir(QDir(themesPath).absoluteFilePath(LEGACY)).exists());
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "style.css").toStdString(), std::string("legacy-css"));
-}
-
-TEST_F(ThemeMigrationTest, MergesIntoAnExistingTargetWithoutOverwriting)
-{
- // Post-rename re-customisation: "System" already exists and holds newer
- // files. Those win; the legacy directory only fills the gaps.
- writeThemeFile(themesPath, CURRENT, "style.css", "newer-css");
- writeThemeFile(themesPath, CURRENT, "zones/handzone.png", "newer-handzone");
- writeThemeFile(themesPath, LEGACY, "style.css", "legacy-css");
- writeThemeFile(themesPath, LEGACY, "zones/handzone.png", "legacy-handzone");
- writeThemeFile(themesPath, LEGACY, "zones/stackzone.png", "legacy-stackzone");
- writeThemeFile(themesPath, LEGACY, "palette-light.toml", "legacy-palette");
-
- ThemeManager::migrateLegacyThemeDir(themesPath, CURRENT);
-
- EXPECT_FALSE(QDir(QDir(themesPath).absoluteFilePath(LEGACY)).exists());
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "style.css").toStdString(), std::string("newer-css"));
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "zones/handzone.png").toStdString(), std::string("newer-handzone"));
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "zones/stackzone.png").toStdString(), std::string("legacy-stackzone"));
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "palette-light.toml").toStdString(), std::string("legacy-palette"));
-}
-
-TEST_F(ThemeMigrationTest, LeavesAnotherThemesDefaultDirectoryAlone)
-{
- // A user on an unrelated theme may legitimately have made a "Default"
- // folder of their own; it must not be folded into "System".
- writeThemeFile(themesPath, LEGACY, "style.css", "unrelated");
-
- ThemeManager::migrateLegacyThemeDir(themesPath, QStringLiteral("Leather"));
-
- EXPECT_TRUE(QDir(QDir(themesPath).absoluteFilePath(LEGACY)).exists());
- EXPECT_EQ(readThemeFile(themesPath, LEGACY, "style.css").toStdString(), std::string("unrelated"));
- EXPECT_FALSE(QDir(QDir(themesPath).absoluteFilePath(CURRENT)).exists());
-}
-
-TEST_F(ThemeMigrationTest, IsIdempotent)
-{
- writeThemeFile(themesPath, LEGACY, "style.css", "css");
-
- ThemeManager::migrateLegacyThemeDir(themesPath, LEGACY);
- ASSERT_EQ(readThemeFile(themesPath, CURRENT, "style.css").toStdString(), std::string("css"));
-
- ThemeManager::migrateLegacyThemeDir(themesPath, CURRENT);
- ThemeManager::migrateLegacyThemeDir(themesPath, LEGACY);
-
- EXPECT_EQ(readThemeFile(themesPath, CURRENT, "style.css").toStdString(), std::string("css"));
-}
-
-// Every test brings its own main(): GTest is not guaranteed to be found on the build machines, and
-// the fallback then links the bare gtest library without gtest_main.
-int main(int argc, char **argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}