|
71 | 71 |
|
72 | 72 | #include <chrono> |
73 | 73 | #include <exception> |
| 74 | +#include <algorithm> |
74 | 75 | #include <fstream> |
75 | 76 | #include <string> |
76 | 77 | #include <vector> |
@@ -958,37 +959,51 @@ void loadStyleSheet(bool fForceUpdate) |
958 | 959 |
|
959 | 960 | QString strStyle = QLatin1String(qFile.readAll()); |
960 | 961 | // Process all <os=...></os> groups in the stylesheet first |
961 | | - QRegularExpressionMatch osStyleMatch; |
962 | 962 | QRegularExpression osStyleExp( |
963 | 963 | "^" |
964 | 964 | "(<os=(?:'|\").+(?:'|\")>)" // group 1 |
965 | 965 | "((?:.|\n)+?)" // group 2 |
966 | 966 | "(</os>?)" // group 3 |
967 | 967 | "$"); |
968 | 968 | osStyleExp.setPatternOptions(QRegularExpression::MultilineOption); |
969 | | - QRegularExpressionMatchIterator it = osStyleExp.globalMatch(strStyle); |
970 | 969 |
|
971 | | - // For all <os=...></os> sections |
972 | | - while (it.hasNext() && (osStyleMatch = it.next()).isValid()) { |
973 | | - QStringList listMatches = osStyleMatch.capturedTexts(); |
974 | | - |
975 | | - // Full match + 3 group matches |
976 | | - if (listMatches.size() % 4) { |
977 | | - throw std::runtime_error(strprintf("%s: Invalid <os=...></os> section in file %s", __func__, file.toStdString())); |
| 970 | + // Collect matches first to avoid modifying the string while iterating |
| 971 | + QList<QRegularExpressionMatch> matches; |
| 972 | + { |
| 973 | + QRegularExpressionMatchIterator it = osStyleExp.globalMatch(strStyle); |
| 974 | + while (it.hasNext()) { |
| 975 | + QRegularExpressionMatch m = it.next(); |
| 976 | + if (m.hasMatch()) { |
| 977 | + matches.append(m); |
| 978 | + } |
978 | 979 | } |
| 980 | + } |
979 | 981 |
|
980 | | - for (int i = 0; i < listMatches.size(); i += 4) { |
981 | | - if (!listMatches[i + 1].contains(QString::fromStdString(platformName))) { |
982 | | - // If os is not supported for this styles |
983 | | - // just remove the full match |
984 | | - strStyle.replace(listMatches[i], ""); |
985 | | - } else { |
986 | | - // If its supported remove the <os=...></os> tags |
987 | | - strStyle.replace(listMatches[i + 1], ""); |
988 | | - strStyle.replace(listMatches[i + 3], ""); |
989 | | - } |
| 982 | + // Build replacement operations using absolute positions |
| 983 | + struct Replacement { int start; int end; QString replacement; }; |
| 984 | + QVector<Replacement> replacements; |
| 985 | + for (const auto& m : matches) { |
| 986 | + const QString openTag = m.captured(1); |
| 987 | + const QString inner = m.captured(2); |
| 988 | + Q_UNUSED(inner); |
| 989 | + // Remove entire block if OS doesn't match, otherwise drop only the tags |
| 990 | + if (!openTag.contains(QString::fromStdString(platformName))) { |
| 991 | + replacements.push_back({m.capturedStart(0), m.capturedEnd(0), QString()}); |
| 992 | + } else { |
| 993 | + // Remove opening and closing tags, keep inner content |
| 994 | + replacements.push_back({m.capturedStart(1), m.capturedEnd(1), QString()}); |
| 995 | + replacements.push_back({m.capturedStart(3), m.capturedEnd(3), QString()}); |
990 | 996 | } |
991 | 997 | } |
| 998 | + |
| 999 | + // Apply replacements from end to start so offsets stay valid |
| 1000 | + std::sort(replacements.begin(), replacements.end(), [](const Replacement& a, const Replacement& b) { |
| 1001 | + return a.start > b.start; |
| 1002 | + }); |
| 1003 | + for (const auto& r : replacements) { |
| 1004 | + strStyle.replace(r.start, r.end - r.start, r.replacement); |
| 1005 | + } |
| 1006 | + |
992 | 1007 | stylesheet->append(strStyle); |
993 | 1008 | } |
994 | 1009 | return true; |
|
0 commit comments