From c976d47bda6b83968c3b75b87529c31644387684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 5 Aug 2024 21:51:12 +0200 Subject: [PATCH] Fix after rebase. --- src/extensionlistproxy.h | 2 +- src/extensionmanager.h | 2 +- src/extensionwatcher.h | 2 +- src/organizer_en.ts | 809 +++++++++++++------------------ src/organizercore.cpp | 2 +- src/pluginmanager.h | 20 +- src/previewgenerator.cpp | 4 +- src/proxyqt.h | 2 +- src/settingsdialogextensionrow.h | 2 +- src/thememanager.cpp | 122 ++++- src/thememanager.h | 8 +- src/translationmanager.h | 2 +- 12 files changed, 470 insertions(+), 507 deletions(-) diff --git a/src/extensionlistproxy.h b/src/extensionlistproxy.h index 47a394f69..84245cdc2 100644 --- a/src/extensionlistproxy.h +++ b/src/extensionlistproxy.h @@ -1,7 +1,7 @@ #ifndef EXTENSIONLISTPROXY_H #define EXTENSIONLISTPROXY_H -#include +#include #include "extensionmanager.h" diff --git a/src/extensionmanager.h b/src/extensionmanager.h index 5ecc05595..3cef8d689 100644 --- a/src/extensionmanager.h +++ b/src/extensionmanager.h @@ -7,7 +7,7 @@ #include #include -#include +#include #include "extensionwatcher.h" diff --git a/src/extensionwatcher.h b/src/extensionwatcher.h index 5dd47259b..2d476e1b2 100644 --- a/src/extensionwatcher.h +++ b/src/extensionwatcher.h @@ -1,7 +1,7 @@ #ifndef EXTENSIONWATCHER_H #define EXTENSIONWATCHER_H -#include +#include // an extension watcher is a class that watches extensions get loaded/unloaded, // typically to extract information from theme that are needed by MO2 diff --git a/src/organizer_en.ts b/src/organizer_en.ts index 5715889bd..b25ece0a5 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -836,44 +836,6 @@ p, li { white-space: pre-wrap; } - - DisableProxyPluginDialog - - - Really disable plugin? - - - - - Disabling the '%1' plugin will prevent the following plugins from working: - - - - - Plugin - - - - - Description - - - - - Do you want to continue? You will need to restart Mod Organizer for the change to take effect. - - - - - Yes - - - - - No - - - DownloadList @@ -1796,197 +1758,213 @@ Right now the only case I know of where this needs to be overwritten is for the + + ExtensionListItemWidget + + + Form + + + + + + + + TextLabel + + + FileTree - + Enter Name - + Enter a name for the executable - + Not an executable - + This is not a recognized executable. - - + + File '%1' does not exist, you may need to refresh. - + (only has %1 file(s)) - + %1 file(s) selected - + &Add as Executable - + Add this file to the executables list - + This file is not executable - + Reveal in E&xplorer - + Opens the file in Explorer - - - - - - - + + + + + + + This file is in an archive - + Open &Mod Info - + Opens the Mod Info Window - + This file is not in a managed mod - + &Un-Hide - + Un-hides the file - + &Hide - + Hides the file - + &Execute - + Launches this program - + Execute with &VFS - + Launches this program hooked to the VFS - + &Open - + Opens this file with its default handler - + Open with &VFS - + Opens this file with its default handler hooked to the VFS - + &Preview - + Previews this file within Mod Organizer - + This file is in an archive or has no preview handler associated with it - + &Save Tree to Text File... - + Writes the list of files to a text file - + &Refresh - + Refreshes the list - + Ex&pand All - + &Collapse All @@ -2501,96 +2479,96 @@ This is likely due to a corrupted or incompatible download or unrecognized archi - + Switching instances - + Mod Organizer must restart to manage the instance '%1'. - + This confirmation can be disabled in the settings. - + Restart Mod Organizer - - + + Cancel - - + + Rename instance - + The active instance cannot be renamed. - + Instance name - + Error - + Failed to rename "%1" to "%2": %3 - - - + + + Deleting instance - + The active instance cannot be deleted. - + These files and folders will be deleted - + All checked items will be deleted. - + Move to the recycle bin - + Delete permanently - + Nothing to delete. - + A portable instance already exists. @@ -2731,37 +2709,37 @@ This is likely due to a corrupted or incompatible download or unrecognized archi MOApplication - + Failed to create log folder. - + Failed to set up data paths. - + Download started - + This shortcut or command line is for instance '%1', but the current instance is '%2'. - + This shortcut or command line is for profile '%1', but the current profile is '%2'. - + an error occurred: %1 - + an error occurred @@ -3003,7 +2981,7 @@ This is likely due to a corrupted or incompatible download or unrecognized archi - + Sort the plugins using LOOT. @@ -3137,7 +3115,7 @@ This is likely due to a corrupted or incompatible download or unrecognized archi - + Name @@ -3395,7 +3373,7 @@ This is likely due to a corrupted or incompatible download or unrecognized archi - + Endorse Mod Organizer @@ -3479,169 +3457,169 @@ This is likely due to a corrupted or incompatible download or unrecognized archi - + Toolbar and Menu - + Desktop - + Start Menu - + Crash on exit - + MO crashed while exiting. Some settings may not be saved. Error: %1 - + There are notifications to read - + There are no notifications - + Endorse - + Won't Endorse - + First Steps Translation strings for tutorial names - + Conflict Resolution - + Overview - + Help on UI - + Documentation - - + + Game Support Wiki - + Chat on Discord - + Report Issue - + Tutorials - + About - + About Qt - + Please enter a name for the new profile - + failed to create profile: %1 - + Show tutorial? - + You are starting Mod Organizer for the first time. Do you want to show a tutorial of its basic features? If you choose no you can always start the tutorial from the "Help" menu. - + Never ask to show tutorials - + Do you know how to mod this game? Do you need to learn? There's a game support wiki available! Click OK to open the wiki. In the future, you can access this link from the "Help" menu. - + Category Setup - + Please choose how to handle the default category setup. If you've already connected to Nexus, you can automatically import Nexus categories for this game (if applicable). Otherwise, use the old Mod Organizer default category structure, or leave the categories blank (for manual setup). - - + + &Import Nexus Categories - + Use &Old Category Defaults - + Do &Nothing - + This is your first time running version 2.5 or higher with an old MO2 instance. The category system now relies on an updated system to map Nexus categories. In order to assign Nexus categories automatically, you will need to import the Nexus categories for the currently managed game and map them to your preferred category structure. @@ -3652,321 +3630,321 @@ As a final option, you can disable Nexus category mapping altogether, which can - + &Open Categories Dialog - + &Disable Nexus Mappings - + &Close - + &Don't show this again - + Downloads in progress - + There are still downloads in progress, do you really want to quit? - + Plugin "%1" failed: %2 - + Plugin "%1" failed - + <Edit...> - + (no executables) - + This bsa is enabled in the ini file so it may be required! - + Activating Network Proxy - + Notice: Your current MO version (%1) is lower than the previously used one (%2). The GUI may not downgrade gracefully, so you may experience oddities. However, there should be no serious issues. - + failed to change origin name: %1 - + failed to move "%1" from mod "%2" to "%3": %4 - + Open Game folder - + Open MyGames folder - + Open INIs folder - + Open Instance folder - + Open Mods folder - + Open Profile folder - + Open Downloads folder - + Open MO2 Install folder - + Open MO2 Plugins folder - + Open MO2 Stylesheets folder - + Open MO2 Logs folder - + Restart Mod Organizer - + Mod Organizer must restart to finish configuration changes - + Restart - + Continue - + Some things might be weird. - + Can't change download directory while downloads are in progress! - + Update available - + Do you want to endorse Mod Organizer on %1 now? - + Abstain from Endorsing Mod Organizer - + Are you sure you want to abstain from endorsing Mod Organizer 2? You will have to visit the mod page on the %1 Nexus site to change your mind. - + Thank you for endorsing MO2! :) - + Please reconsider endorsing MO2 on Nexus! - + There is no supported sort mechanism for this game. You will probably have to use a third-party tool. - + None of your %1 mods appear to have had recent file updates. - + All of your mods have been checked recently. We restrict update checks to help preserve your available API requests. - + Thank you! - + Thank you for your endorsement! - + Mod ID %1 no longer seems to be available on Nexus. - + Error %1: Request to Nexus failed: %2 - - + + failed to read %1: %2 - + Error - + failed to extract %1 (errorcode %2) - + Extract BSA - + This archive contains invalid hashes. Some files may be broken. - + Extract... - + Remove '%1' from the toolbar - + Backup of load order created - + Choose backup to restore - + No Backups - + There are no backups to restore - - + + Restore failed - - + + Failed to restore the backup. Errorcode: %1 - + Backup of mod list created - + A file with the same name has already been downloaded. What would you like to do? - + Overwrite - + Rename new file - + Ignore file @@ -4435,12 +4413,12 @@ p, li { white-space: pre-wrap; } ModInfoRegular - + %1 contains no esp/esm/esl and no asset (textures, meshes, interface, ...) directory - + Categories: <br> @@ -5626,208 +5604,208 @@ Please enter a name: OrganizerCore - + File is write protected - + Invalid file format (probably a bug) - + Unknown error %1 - + Failed to write settings - + An error occurred trying to write back MO settings to %1: %2 - + Download started - + Download failed - + The selected profile '%1' does not exist. The profile '%2' will be used instead - + Installation cancelled - + Another installation is currently in progress. - + Installation successful - + Configure Mod - + This mod contains ini tweaks. Do you want to configure them now? - + mod not found: %1 - + Extraction cancelled - + The installation was cancelled while extracting files. If this was prior to a FOMOD setup, this warning may be ignored. However, if this was during installation, the mod will likely be missing files. - + file not found: %1 - - + + failed to generate preview for %1 - + Sorry - + Sorry, can't preview anything. This function currently does not support extracting from bsas. - + File '%1' not found. - + Failed to generate preview for %1 - + Failed to refresh list of esps: %1 - + Multiple esps/esls activated, please check that they don't conflict. - + You need to be logged in with Nexus - + Download? - + A download has been started but no installed page plugin recognizes it. If you download anyway no information (i.e. version) will be associated with the download. Continue? - - + + failed to update mod list: %1 - - + + login successful - + Login failed - + Login failed, try again? - + login failed: %1. Download will not be associated with an account - + login failed: %1 - + login failed: %1. You need to log-in with Nexus to update MO. - + MO1 "Script Extender" load mechanism has left hook.dll in your game folder - - + + Description missing - + <a href="%1">hook.dll</a> has been found in your game folder (right click to copy the full path). This is most likely a leftover of setting the ModOrganizer 1 load mechanism to "Script Extender", in which case you must remove this file either by changing the load mechanism in ModOrganizer 1 or manually removing the file, otherwise the game is likely to crash and burn. - + failed to save load order: %1 - + Error - + The designated write target "%1" is not enabled. @@ -5950,55 +5928,6 @@ Continue? - - PluginContainer - - - Plugin error - - - - - Mod Organizer failed to load the plugin '%1' last time it was started. - - - - - The plugin can be skipped for this session, blacklisted, or loaded normally, in which case it might fail again. Blacklisted plugins can be re-enabled later in the settings. - - - - - Skip this plugin - - - - - Blacklist this plugin - - - - - Load this plugin - - - - - Some plugins could not be loaded - - - - - - Description missing - - - - - The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: - - - PluginList @@ -6302,44 +6231,44 @@ Continue? - PluginTypeName + PluginManager + + + Plugin + + - + Diagnose - + Game - + Installer - + Mod Page - + Preview - + Tool - - Proxy - - - - + File Mapper @@ -6869,12 +6798,12 @@ p, li { white-space: pre-wrap; } - + Download URL must start with https:// - + Download started @@ -6890,7 +6819,7 @@ p, li { white-space: pre-wrap; } - + Portable @@ -7137,14 +7066,6 @@ p, li { white-space: pre-wrap; } empty field name - - - Disabling the '%1' plugin will prevent the following %2 plugin(s) from working: - - - - - No menu available @@ -7193,7 +7114,7 @@ Destination: - + Disabled because @@ -7203,22 +7124,22 @@ Destination: - + Cannot open instance '%1', failed to read INI file %2. - + Cannot open instance '%1', the managed game was not found in the INI file %2. Select the game managed by this instance. - + Cannot open instance '%1', the game plugin '%2' doesn't exist. It may have been deleted by an antivirus. Select another instance. - + Cannot open instance '%1', the game directory '%2' doesn't exist or the game plugin '%3' doesn't recognize it. Select the game managed by this instance. @@ -7235,7 +7156,7 @@ Destination: - + @@ -7245,7 +7166,7 @@ Destination: - + Failed to create "%1". Your user account probably lacks permission. @@ -7352,33 +7273,33 @@ Destination: - + Please use "Help" from the toolbar to get usage instructions to all elements - + Visit %1 on Nexus - - + + <Manage...> - + failed to parse profile %1: %2 - + Instance at '%1' not found. Select another instance. - + Instance at '%1' not found. You must create a new instance @@ -7506,15 +7427,10 @@ Destination: - + One of the configured MO2 directories (profiles, mods, or overwrite) is on a path containing a symbolic (or other) link. This is likely to be incompatible with MO2's virtual filesystem. - - - failed to initialize plugin %1: %2 - - failed to access %1 @@ -7623,12 +7539,12 @@ This program is known to cause issues with Mod Organizer, such as freezing or bl - + Confirm? - + This will reset all the choices you made to dialogs and make them all visible again. Continue? @@ -7715,31 +7631,6 @@ This program is known to cause issues with Mod Organizer, such as freezing or bl The given path was not recognized as a valid game installation. The current game plugin requires the executable to be in a "%1" subfolder of the game directory. - - - Cannot disable plugin - - - - - The '%1' plugin is used by the current game plugin and cannot disabled. - - - - - <p>Disabling the '%1' plugin will also disable the following plugins:</p><ul>%1</ul><p>Do you want to continue?</p> - - - - - Really disable plugin? - - - - - This plugin is required for Mod Organizer to work properly and cannot be disabled. - - Executables Blacklist @@ -8629,7 +8520,7 @@ If you disable this feature, MO will only display official DLCs this way. Please - + ... @@ -8766,7 +8657,7 @@ If you disable this feature, MO will only display official DLCs this way. Please - + Options @@ -8827,124 +8718,119 @@ If you disable this feature, MO will only display official DLCs this way. Please - - Plugins - - - - + Author: - + Version: - + Description: - + Enabled - + Key - + Value - + No plugin found. - + Blacklisted Plugins (use <del> to remove): - + Workarounds - + If checked, files (i.e. esps, esms and bsas) belonging to the core game can not be disabled in the UI. (default: on) - + If checked, files (i.e. esps, esms and bsas) belonging to the core game can not be disabled in the UI. (default: on) Uncheck this if you want to use Mod Organizer with total conversions (like Nehrim) but be aware that the game will crash if required files are not enabled. - + Force-enable game files - + Enable parsing of Archives. This is an Experimental Feature. Has negative effects on performance and known incorrectness. - + <html><head/><body><p>By default, MO will parse archive files (BSA, BA2) to calculate conflicts between the contents of the archive files and other loose files. This process has a noticeable cost in performance.</p><p>This feature should not be confused with the archive management feature offered by MO1. MO2 will only show conflicts with archives and will NOT load them into the game or program.</p><p>If you disable this feature, MO will only display conflicts between loose files.</p></body></html> - + Enable archives parsing (experimental) - - + + Disable this to prevent the GUI from being locked when running an executable. This may result in abnormal behavior. - + Lock GUI when running executable - + Steam - + Password - + Username - + Steam App ID - + The Steam AppID for your game - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } @@ -8960,69 +8846,69 @@ p, li { white-space: pre-wrap; } - + Network - + Disable automatic internet features - + Disable automatic internet features. This does not affect features that are explicitly invoked by the user (like checking mods for updates, endorsing, opening the web browser) - + Offline Mode - + Use a proxy for network connections. - + Use a proxy for network connections. This uses the system-wide settings which can be configured in Internet Explorer. Please note that MO will start up a few seconds slower on some systems when using a proxy. - + Use System HTTP Proxy + + - - + + - - Use "%1" as a placeholder for the URL. - + Custom browser - - + + Resets the window geometries for all windows. This can be useful if a window becomes too small or too large, if a column becomes too thin or too wide, and in similar situations. - + Reset Window Geometries + - For Skyrim, this can be used instead of Archive Invalidation. It should make AI redundant for all Profiles. For the other games this is not a sufficient replacement for AI! @@ -9030,7 +8916,7 @@ p, li { white-space: pre-wrap; } - + Add executables to the blacklist to prevent them from accessing the virtual file system. This is useful to prevent unintended programs from being hooked. Hooking unintended @@ -9039,69 +8925,74 @@ programs you are intentionally running. - + Add executables to the blacklist to prevent them from accessing the virtual file system. This is useful to prevent unintended programs from being hooked. Hooking unintended programs may affect the execution of these programs or the programs you are intentionally running. - + Executables Blacklist - + Back-date BSAs - - + + Extensions + + + + + Files to skip or ignore from the virtual file system. - + Skip File Suffixes - - + + Directories to skip or ignore from the virtual file system. - + Skip Directories - + These are workarounds for problems with Mod Organizer. Please make sure you read the help text before changing anything here. - + Diagnostics - + Logs and Crashes - + Log Level - + Decides the amount of data printed to "ModOrganizer.log" - + Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regular use. On the "Error" level the log file usually remains empty. @@ -9109,17 +9000,17 @@ programs you are intentionally running. - + Crash Dumps - + Decides which type of crash dumps are collected when injected processes crash. - + Decides which type of crash dumps are collected when injected processes crash. "None" Disables the generation of crash dumps by MO. @@ -9130,17 +9021,17 @@ programs you are intentionally running. - + Max Dumps To Keep - + Maximum number of crash dumps to keep on disk. Use 0 for unlimited. - + Maximum number of crash dumps to keep on disk. Use 0 for unlimited. Set "Crash Dumps" above to None to disable crash dump collection. @@ -9148,22 +9039,22 @@ programs you are intentionally running. - + Integrated LOOT - + LOOT Log Level - + Click a link to open the location - + Logs and crash dumps are stored under your current instance in the <a href="LOGS_FULL_PATH">LOGS_DIR</a> and <a href="DUMPS_FULL_PATH">DUMPS_DIR</a> folders. @@ -9173,12 +9064,12 @@ programs you are intentionally running. - + Confirm - + Changing the mod directory affects all your profiles! Mods not present (or named differently) in the new location will be disabled in all profiles. There is no way to undo this unless you backed up your profiles manually. Proceed? @@ -9224,14 +9115,6 @@ programs you are intentionally running. - - T - - - Plugin - - - TransferSavesDialog diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 76083a2cb..0cbbf1199 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1081,7 +1081,7 @@ bool OrganizerCore::previewFileWithAlternatives(QWidget* parent, QString fileNam libbsarch::memory_blob fileData = archiveLoader.extract_to_memory(fileName.toStdWString()); QByteArray convertedFileData((char*)(fileData.data), fileData.size); - QWidget* wid = m_PluginContainer->previewGenerator().genArchivePreview( + QWidget* wid = m_PluginManager->previewGenerator().genArchivePreview( convertedFileData, filePath); if (wid == nullptr) { reportError(tr("failed to generate preview for %1").arg(filePath)); diff --git a/src/pluginmanager.h b/src/pluginmanager.h index 9ffa6c2e8..11c56f170 100644 --- a/src/pluginmanager.h +++ b/src/pluginmanager.h @@ -11,16 +11,16 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "game_features.h" #include "previewgenerator.h" diff --git a/src/previewgenerator.cpp b/src/previewgenerator.cpp index ed2eb7c8a..cd5376cfe 100644 --- a/src/previewgenerator.cpp +++ b/src/previewgenerator.cpp @@ -67,9 +67,9 @@ QWidget* PreviewGenerator::genArchivePreview(const QByteArray& fileData, const QString& fileName) const { const QString ext = QFileInfo(fileName).suffix().toLower(); - auto& previews = m_PluginContainer.plugins(); + auto& previews = m_PluginManager.plugins(); for (auto* preview : previews) { - if (m_PluginContainer.isEnabled(preview) && + if (m_PluginManager.isEnabled(preview) && preview->supportedExtensions().contains(ext) && preview->supportsArchives()) { return preview->genDataPreview(fileData, fileName, m_MaxSize); } diff --git a/src/proxyqt.h b/src/proxyqt.h index 80c7fb95b..a234fab1e 100644 --- a/src/proxyqt.h +++ b/src/proxyqt.h @@ -3,7 +3,7 @@ #include -#include +#include class ProxyQtLoader : public MOBase::IPluginLoader { diff --git a/src/settingsdialogextensionrow.h b/src/settingsdialogextensionrow.h index e2aa52806..80a489f75 100644 --- a/src/settingsdialogextensionrow.h +++ b/src/settingsdialogextensionrow.h @@ -3,7 +3,7 @@ #include -#include "extension.h" +#include namespace Ui { diff --git a/src/thememanager.cpp b/src/thememanager.cpp index cc9dfa008..765f736ae 100644 --- a/src/thememanager.cpp +++ b/src/thememanager.cpp @@ -3,9 +3,10 @@ #include #include #include +#include -#include -#include +#include +#include #include "shared/appconfig.h" @@ -60,6 +61,87 @@ class ProxyStyle : public QProxyStyle } }; +namespace +{ +QString readWholeFile(std::filesystem::path const& path) +{ + QFile file(path); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + return {}; + } + + return QTextStream(&file).readAll(); +} + +QStringList extractTopStyleSheetComments(QString const& stylesheet) +{ + QTextStream stream(stylesheet.toUtf8()); + QStringList topComments; + + while (true) { + const auto byteLine = stream.readLine(); + if (byteLine.isNull()) { + break; + } + + const auto line = QString(byteLine).trimmed(); + + // skip empty lines + if (line.isEmpty()) { + continue; + } + + // only handle single line comments + if (!line.startsWith("/*")) { + break; + } + + topComments.push_back(line.mid(2, line.size() - 4).trimmed()); + } + + return topComments; +} + +QString extractBaseStyleFromStyleSheet(std::filesystem::path const& path, + QString const& stylesheet, + const QString& defaultStyle) +{ + // read the first line of the files that are either empty or comments + // + const auto topLines = extractTopStyleSheetComments(stylesheet); + + const auto factoryStyles = QStyleFactory::keys(); + + QString style = defaultStyle; + + for (const auto& line : topLines) { + if (!line.startsWith("mo2-base-style")) { + continue; + } + + const auto parts = line.split(":"); + if (parts.size() != 2) { + log::warn("found invalid top-comment for mo2 in {}: {}", path, line); + continue; + } + + const auto tmpStyle = parts[1].trimmed(); + const auto index = factoryStyles.indexOf(tmpStyle, 0, Qt::CaseInsensitive); + if (index == -1) { + log::warn("base style '{}' from style '{}' not found", tmpStyle, path, line); + continue; + } + + style = factoryStyles[index]; + log::info("found base style '{}' for style '{}'", style, path); + break; + } + + return style; +} + +} // namespace + ThemeManager::ThemeManager(QApplication* application) : m_app{application} { // add built-in themes @@ -67,8 +149,7 @@ ThemeManager::ThemeManager(QApplication* application) : m_app{application} // find the default theme - this might be a built-in Qt theme, or null, in which case // we just create a default theme - if (auto it = - m_baseThemesByIdentifier.find(m_app->style()->objectName().toStdString()); + if (auto it = m_baseThemesByIdentifier.find("windowsvista"); it != m_baseThemesByIdentifier.end()) { m_defaultTheme = it->second; } else { @@ -148,12 +229,14 @@ void ThemeManager::loadQtTheme(std::string_view themeIdentifier) void ThemeManager::loadExtensionTheme(std::shared_ptr const& theme) { + auto baseTheme = ToQString(m_defaultTheme->identifier()); + const auto stylesheet = buildStyleSheet(theme, baseTheme); + // load the default theme - m_app->setStyle( - new ProxyStyle(QStyleFactory::create(ToQString(m_defaultTheme->identifier())))); + m_app->setStyle(new ProxyStyle(QStyleFactory::create(baseTheme))); // build the stylesheet and set it - m_app->setStyleSheet(buildStyleSheet(theme)); + m_app->setStyleSheet(stylesheet); } void ThemeManager::unload() @@ -198,24 +281,19 @@ void ThemeManager::addQtThemes() } } -namespace +QString ThemeManager::buildStyleSheet(std::shared_ptr const& theme, + QString& baseTheme) const { -QString readWholeFile(std::filesystem::path const& path) -{ - QFile file(path); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - return {}; - } + // read the file + const auto stylesheetContent = readWholeFile(theme->stylesheet()); - return QTextStream(&file).readAll(); -} -} // namespace + // check for base theme override + baseTheme = + extractBaseStyleFromStyleSheet(theme->stylesheet(), stylesheetContent, baseTheme); -QString ThemeManager::buildStyleSheet(std::shared_ptr const& theme) const -{ - // create the base stylesheet - QString stylesheet = patchStyleSheet(readWholeFile(theme->stylesheet()), - theme->stylesheet().parent_path()); + // patch the file + QString stylesheet = + patchStyleSheet(stylesheetContent, theme->stylesheet().parent_path()); for (auto&& themeAddition : m_additions) { if (themeAddition->isAdditionFor(*theme)) { diff --git a/src/thememanager.h b/src/thememanager.h index a5211ba2c..099755cc2 100644 --- a/src/thememanager.h +++ b/src/thememanager.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include "extensionwatcher.h" @@ -70,9 +70,11 @@ class ThemeManager : public ExtensionWatcher, // void loadExtensionTheme(std::shared_ptr const& theme); - // build a stylesheet for a theme + // build a stylesheet for a theme, extracting the base theme if needed (if no base + // theme is found, the baseTheme variable is kept untouched) // - QString buildStyleSheet(std::shared_ptr const& theme) const; + QString buildStyleSheet(std::shared_ptr const& theme, + QString& baseTheme) const; // patch the given stylesheet by replacing url() to be relative to the given folder // diff --git a/src/translationmanager.h b/src/translationmanager.h index 0afab7a82..691a2af0f 100644 --- a/src/translationmanager.h +++ b/src/translationmanager.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include "extensionwatcher.h"