From cc92f6cf887803a480cfda3e6e33987e31668784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 19 Jul 2024 09:49:53 +0200 Subject: [PATCH] Set default style to 'windowsvista' and allow stylesheet to modify base style (#2072) * Set 'windowsvista' as the default style. * Allow stylesheet to modify base style. --- src/moapplication.cpp | 89 ++++++++- src/organizer_en.ts | 453 ++++++++++++++++++++++++------------------ 2 files changed, 347 insertions(+), 195 deletions(-) diff --git a/src/moapplication.cpp b/src/moapplication.cpp index e131d3d96..bf6a40747 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -44,6 +44,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include // see addDllsToPath() below @@ -154,8 +155,8 @@ MOApplication::MOApplication(int& argc, char** argv) : QApplication(argc, argv) updateStyle(file); }); - m_defaultStyle = style()->objectName(); - setStyle(new ProxyStyle(style())); + m_defaultStyle = "windowsvista"; + updateStyle(m_defaultStyle); addDllsToPath(); } @@ -558,14 +559,94 @@ bool MOApplication::notify(QObject* receiver, QEvent* event) } } +namespace +{ +QStringList extractTopStyleSheetComments(QFile& stylesheet) +{ + if (!stylesheet.open(QFile::ReadOnly)) { + log::error("failed to open stylesheet file {}", stylesheet.fileName()); + return {}; + } + ON_BLOCK_EXIT([&stylesheet]() { + stylesheet.close(); + }); + + QStringList topComments; + + while (true) { + const auto byteLine = stylesheet.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(QFile& 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 {}: {}", stylesheet.fileName(), + 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, + stylesheet.fileName(), line); + continue; + } + + style = factoryStyles[index]; + log::info("found base style '{}' for style '{}'", style, stylesheet.fileName()); + break; + } + + return style; +} + +} // namespace + void MOApplication::updateStyle(const QString& fileName) { if (QStyleFactory::keys().contains(fileName)) { setStyleSheet(""); setStyle(new ProxyStyle(QStyleFactory::create(fileName))); } else { - setStyle(new ProxyStyle(QStyleFactory::create(m_defaultStyle))); - if (QFile::exists(fileName)) { + QFile stylesheet(fileName); + if (stylesheet.exists()) { + setStyle(new ProxyStyle(QStyleFactory::create( + extractBaseStyleFromStyleSheet(stylesheet, m_defaultStyle)))); setStyleSheet(QString("file:///%1").arg(fileName)); } else { log::warn("invalid stylesheet: {}", fileName); diff --git a/src/organizer_en.ts b/src/organizer_en.ts index 362ccd892..dc4bc55e2 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -1799,194 +1799,194 @@ Right now the only case I know of where this needs to be overwritten is for the 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 @@ -2398,11 +2398,17 @@ Right now the only case I know of where this needs to be overwritten is for the + None + Missing ESHs + + + + Missing ESLs @@ -2895,37 +2901,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 @@ -4662,22 +4668,22 @@ p, li { white-space: pre-wrap; } ModInfoForeign - + This pseudo mod represents content managed outside MO. It isn't modified by MO. - + DLC: - + Creation Club: - + Unmanaged: @@ -5884,207 +5890,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. @@ -6310,107 +6317,117 @@ Continue? - + Plugin not found: %1 - + Origin - + This plugin can't be disabled or moved (enforced by the game). - + This plugin can't be disabled (enforced by the game). - + Author - + Description - + Missing Masters - + Enabled Masters - + Loads Archives - + There are Archives connected to this plugin. Their assets will be added to your game, overwriting in case of conflicts following the plugin order. Loose files will always overwrite assets from Archives. (This flag only checks for Archives from the same mod as the plugin) - + Loads INI settings - + There is an ini file connected to this plugin. Its settings will be added to your game settings, overwriting in case of conflicts. - - This %1 is flagged as an ESL. It will adhere to the %1 load order but the records will be loaded in ESL space. + + This %1 is flagged as a light plugin (ESL). It will adhere to the %1 load order but the records will be loaded in ESL space (FE/FF). You can have up to 4096 light plugins in addition to other plugin types. + + + + + This ESM is flagged as a medium plugin (ESH). It adheres to the ESM load order but loads records in ESH space (FD). You can have 256 medium plugins in addition to other plugin types. + + + + + WARNING: This plugin is both light and medium flagged. This could indicate that the file was saved improperly and may have mismatched record references. Use it at your own risk. - + This is a dummy plugin. It contains no records and is typically used to load a paired archive file. - + Light plugins (ESL) are not supported by this game. - + This game does not currently permit custom plugin loading. There may be manual workarounds. - + Incompatible with %1 - + Depends on missing %1 - + Warning - + Error - + failed to restore load order for %1 @@ -6516,7 +6533,8 @@ Continue? PluginListView - <table cellspacing="6"><tr><th>Type</th><th>Active </th><th>Total</th></tr><tr><td>All plugins:</td><td align=right>%1 </td><td align=right>%2</td></tr><tr><td>ESMs:</td><td align=right>%3 </td><td align=right>%4</td></tr><tr><td>ESPs:</td><td align=right>%7 </td><td align=right>%8</td></tr><tr><td>ESMs+ESPs:</td><td align=right>%9 </td><td align=right>%10</td></tr><tr><td>ESLs:</td><td align=right>%5 </td><td align=right>%6</td></tr><tr><td>Overlay:</td><td align=right>%11 </td><td align=right>%12</td></tr></table> + <table cellspacing="6"><tr><th>Type</th><th>Active </th><th>Total</th></tr><tr><td>All plugins:</td><td align=right>%1 </td><td align=right>%2</td></tr><tr><td>ESMs:</td><td align=right>%3 </td><td align=right>%4</td></tr><tr><td>ESPs:</td><td align=right>%7 </td><td align=right>%8</td></tr><tr><td>ESMs+ESPs:</td><td align=right>%9 </td><td align=right>%10</td></tr><tr><td>ESHs:</td><td align=right>%11 </td><td align=right>%12</td></tr><tr><td>ESLs:</td><td align=right>%5 </td><td align=right>%6</td></tr></table> + <table cellspacing="6"><tr><th>Type</th><th>Active </th><th>Total</th></tr><tr><td>All plugins:</td><td align=right>%1 </td><td align=right>%2</td></tr><tr><td>ESMs:</td><td align=right>%3 </td><td align=right>%4</td></tr><tr><td>ESPs:</td><td align=right>%7 </td><td align=right>%8</td></tr><tr><td>ESMs+ESPs:</td><td align=right>%9 </td><td align=right>%10</td></tr><tr><td>ESLs:</td><td align=right>%5 </td><td align=right>%6</td></tr><tr><td>Overlay:</td><td align=right>%11 </td><td align=right>%12</td></tr></table> @@ -7230,7 +7248,7 @@ p, li { white-space: pre-wrap; } - + @@ -7449,22 +7467,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. @@ -7481,7 +7499,7 @@ Destination: - + @@ -7493,7 +7511,7 @@ Destination: - + Failed to create "%1". Your user account probably lacks permission. @@ -7621,12 +7639,12 @@ Destination: - + Instance at '%1' not found. Select another instance. - + Instance at '%1' not found. You must create a new instance @@ -7754,7 +7772,7 @@ 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. @@ -7764,12 +7782,12 @@ Destination: - + failed to access %1 - + failed to set file time %1 @@ -7822,19 +7840,19 @@ This program is known to cause issues with Mod Organizer, such as freezing or bl - - - + + + attempt to store setting for unknown plugin "%1" - + Failed - + Failed to start the helper application: %1 @@ -7989,12 +8007,12 @@ This program is known to cause issues with Mod Organizer, such as freezing or bl - + Executables Blacklist - + Enter one executable per line to be blacklisted from the virtual file system. Mods and other virtualized files will not be visible to these executables and any executables launched by them. @@ -8005,19 +8023,48 @@ Example: - - - + + Skip File Suffixes + + + + + Enter one file suffix per line to be skipped / ignored from the virtual file system. +Not to be confused with file extensions, file suffixes are simply how the filename ends. + +Example: + .txt - Would skip all files that end with .txt, <any text>.txt + some_file.txt - Would skip all files that end with some_file.txt, <any text>some_file.txt + + + + + Skip Directories + + + + + Enter one directory per line to be skipped / ignored from the virtual file system. + +Example: + .git + instructions + + + + + + Restart Mod Organizer - + Geometries will be reset to their default values. - + unexpected end of path @@ -8297,17 +8344,17 @@ You can restart Mod Organizer as administrator and try launching the program aga - + %1, #%2, Level %3, %4 - + failed to open %1 - + wrong file format - expected %1 got '%2' for %3 @@ -8408,11 +8455,6 @@ You can restart Mod Organizer as administrator and try launching the program aga Remember my choice for %1 - - - Failed to save '{}', could not create a temporary file: {} (error {}) - - removal of "%1" failed: %2 @@ -8452,55 +8494,60 @@ You can restart Mod Organizer as administrator and try launching the program aga - + %1 B - + %1 KB - + %1 MB - + %1 GB - + %1 TB - + %1 B/s - + %1 KB/s - + %1 MB/s - + %1 GB/s - + %1 TB/s + + + Failed to save '%1', could not create a temporary file: %2 (error %3) + + QueryOverwriteDialog @@ -9465,6 +9512,15 @@ p, li { white-space: pre-wrap; } + + + 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! + + + + + 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 @@ -9473,54 +9529,69 @@ 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 - - - 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! + + Back-date BSAs - - Back-date BSAs + + + 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. @@ -9528,17 +9599,17 @@ For the other games this is not a sufficient replacement for AI! - + 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. @@ -9549,17 +9620,17 @@ For the other games this is not a sufficient replacement for AI! - + 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. @@ -9567,22 +9638,22 @@ For the other games this is not a sufficient replacement for AI! - + 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. @@ -9839,7 +9910,7 @@ On Windows XP: UsvfsConnector - + Preparing vfs @@ -10458,19 +10529,19 @@ Please open the "Nexus" tab. uibase - + h Time remaining hours - + m Time remaining minutes - + s Time remaining seconds