Warning, file /utilities/kdebugsettings/src/kdebugsettingsutil.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2015-2023 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 0006 */ 0007 0008 #include "kdebugsettingsutil.h" 0009 #include "kdebugsettings_debug.h" 0010 #include <KLocalizedString> 0011 #include <QDir> 0012 #include <QFile> 0013 #include <QRegularExpression> 0014 #include <QStandardPaths> 0015 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0016 #include <QTextCodec> 0017 #endif 0018 0019 RenameCategory KDebugSettingsUtil::parseRenameCategory(QString line, const QString &filename) 0020 { 0021 RenameCategory category; 0022 int pos = line.indexOf(QLatin1Char('#')); 0023 if (pos != -1) { 0024 line.truncate(pos); 0025 line = line.simplified(); 0026 } 0027 0028 if (line.isEmpty()) { 0029 return category; 0030 } 0031 line = line.simplified(); 0032 const int space = line.indexOf(QLatin1Char(' ')); 0033 if (space == -1) { 0034 qCWarning(KDEBUGSETTINGS_LOG) << "Invalid categories file. Missing space. Syntax is logname<space>description + optional element. Line: " << line 0035 << " from file:" << filename << Qt::endl; 0036 return category; 0037 } 0038 0039 const QString originalName = line.left(space); 0040 0041 const QString newName = line.mid(space).simplified(); 0042 category.originalName = originalName; 0043 category.newName = newName; 0044 return category; 0045 } 0046 0047 RenameCategory::List KDebugSettingsUtil::readRenameCategories(const QString &filename) 0048 { 0049 RenameCategory::List insertCategories; 0050 0051 QFile file(filename); 0052 if (!file.open(QIODevice::ReadOnly)) { 0053 qCWarning(KDEBUGSETTINGS_LOG) << "Couldn't open" << filename; 0054 } else { 0055 QString data; 0056 QTextStream ts(&file); 0057 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0058 ts.setCodec(QTextCodec::codecForName("ISO-8859-1")); 0059 #else 0060 ts.setEncoding(QStringConverter::Encoding::Latin1); 0061 #endif 0062 while (!ts.atEnd()) { 0063 data = ts.readLine().simplified(); 0064 const RenameCategory category = parseRenameCategory(data, filename); 0065 if (category.isValid()) { 0066 insertCategories.append(category); 0067 } 0068 } 0069 } 0070 return insertCategories; 0071 } 0072 0073 KdeLoggingCategory KDebugSettingsUtil::parseLineKdeLoggingCategory(QString line, const QString &filename) 0074 { 0075 KdeLoggingCategory category; 0076 const int pos = line.indexOf(QLatin1Char('#')); 0077 if (pos != -1) { 0078 line.truncate(pos); 0079 line = line.simplified(); 0080 } 0081 0082 if (line.isEmpty()) { 0083 return category; 0084 } 0085 line = line.simplified(); 0086 const int space = line.indexOf(QLatin1Char(' ')); 0087 if (space == -1) { 0088 qCWarning(KDEBUGSETTINGS_LOG) << "Invalid categories file. Missing space. Syntax is logname<space>description + optional element. Line: " << line 0089 << " from file:" << filename << Qt::endl; 0090 return category; 0091 } 0092 QString logName; 0093 QString description; 0094 QString defaultSeverity; 0095 QString identifier; 0096 0097 // TODO create an unique regularexpression 0098 0099 static const QRegularExpression regularExpressionUser(QStringLiteral("^([\\w._-]+)\\s*(.*)$")); 0100 QRegularExpressionMatch match = regularExpressionUser.match(line); 0101 if (match.hasMatch()) { 0102 logName = match.captured(1); 0103 description = match.captured(2); 0104 } 0105 0106 bool newFormatFound = false; 0107 static const QRegularExpression regularExpressionDefaultSeverityNewFormat( 0108 QStringLiteral("^(.*)\\s+DEFAULT_SEVERITY\\s+\\[(DEBUG|INFO|WARNING|CRITICAL)\\](?:\\s+(.*))?")); 0109 QRegularExpressionMatch match3 = regularExpressionDefaultSeverityNewFormat.match(description); 0110 QString defaultSeverityCaptured; 0111 QString potentialIdentifier; 0112 if (match3.hasMatch()) { 0113 newFormatFound = true; 0114 const QString descriptionCaptured = match3.captured(1); 0115 defaultSeverityCaptured = match3.captured(2); 0116 potentialIdentifier = match3.captured(3); 0117 if (!descriptionCaptured.isEmpty() && !defaultSeverityCaptured.isEmpty()) { 0118 description = descriptionCaptured; 0119 defaultSeverity = defaultSeverityCaptured; 0120 // qDebug() << " match.captured(1);" << descriptionCaptured; 0121 // qDebug() << " match.captured(2);" << defaultCategoryCaptured; 0122 } 0123 } 0124 0125 if (potentialIdentifier.isEmpty()) { 0126 static const QRegularExpression regularExpressionDefaultIdentifierNewFormat(QStringLiteral("^(.*)\\s+IDENTIFIER\\s+\\[(.*)\\]")); 0127 QRegularExpressionMatch match4 = regularExpressionDefaultIdentifierNewFormat.match(description); 0128 if (match4.hasMatch()) { 0129 newFormatFound = true; 0130 const QString descriptionCaptured = match4.captured(1); 0131 const QString identifierCaptured = match4.captured(2); 0132 if (!descriptionCaptured.isEmpty() && !identifierCaptured.isEmpty()) { 0133 description = descriptionCaptured; 0134 identifier = identifierCaptured; 0135 // qDebug() << " match.captured(1);" << descriptionCaptured; 0136 // qDebug() << " match.captured(2);" << identifierCaptured; 0137 } 0138 } 0139 } else { 0140 static const QRegularExpression regularExpressionDefaultIdentifierNewFormat2(QStringLiteral("IDENTIFIER\\s+\\[(.*)\\]")); 0141 QRegularExpressionMatch match4 = regularExpressionDefaultIdentifierNewFormat2.match(potentialIdentifier); 0142 if (match4.hasMatch()) { 0143 newFormatFound = true; 0144 const QString identifierCaptured = match4.captured(1); 0145 if (!identifierCaptured.isEmpty()) { 0146 identifier = identifierCaptured; 0147 } 0148 } 0149 } 0150 0151 if (!newFormatFound) { 0152 // Old format. 0153 static const QRegularExpression regularExpressionDefaultSeverityOldFormat(QStringLiteral("^(.*)\\s+\\[(DEBUG|INFO|WARNING|CRITICAL)\\]")); 0154 QRegularExpressionMatch match2 = regularExpressionDefaultSeverityOldFormat.match(description); 0155 if (match2.hasMatch()) { 0156 const QString descriptionCaptured = match2.captured(1); 0157 defaultSeverityCaptured = match2.captured(2); 0158 if (!descriptionCaptured.isEmpty() && !defaultSeverityCaptured.isEmpty()) { 0159 description = descriptionCaptured; 0160 defaultSeverity = defaultSeverityCaptured; 0161 // qDebug() << " match.captured(1);" << descriptionCaptured; 0162 // qDebug() << " match.captured(2);" << defaultCategoryCaptured; 0163 qCWarning(KDEBUGSETTINGS_LOG) << "In this file: " << filename << " this line " << line << " still use old format. We need to port it"; 0164 } 0165 } else { 0166 qCWarning(KDEBUGSETTINGS_LOG) << "In this file: " << filename << " this line " << line << " still use old format. We need to port it"; 0167 } 0168 } 0169 category.categoryName = logName; 0170 category.description = description; 0171 category.defaultSeverity = defaultSeverity; 0172 category.identifierName = identifier; 0173 return category; 0174 } 0175 0176 KdeLoggingCategory::List KDebugSettingsUtil::readLoggingCategoriesForInserting(const QString &filename, KdeLoggingCategory::List &categoriesList) 0177 { 0178 KdeLoggingCategory::List insertCategories; 0179 0180 QFile file(filename); 0181 if (!file.open(QIODevice::ReadOnly)) { 0182 qCWarning(KDEBUGSETTINGS_LOG) << "Couldn't open" << filename; 0183 } else { 0184 QString data; 0185 QTextStream ts(&file); 0186 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0187 ts.setCodec(QTextCodec::codecForName("ISO-8859-1")); 0188 #else 0189 ts.setEncoding(QStringConverter::Encoding::Latin1); 0190 #endif 0191 while (!ts.atEnd()) { 0192 data = ts.readLine().simplified(); 0193 const KdeLoggingCategory category = parseLineKdeLoggingCategory(data, filename); 0194 if (category.isValid()) { 0195 bool needToAppend = true; 0196 for (const KdeLoggingCategory &cat : std::as_const(categoriesList)) { 0197 if (cat == category) { 0198 needToAppend = false; 0199 break; 0200 } else if (cat.categoryName == category.categoryName) { 0201 qCWarning(KDEBUGSETTINGS_LOG) << "Duplicate categories, it's a bug. Please verify: category:" << cat.categoryName 0202 << " filename : " << filename; 0203 needToAppend = false; 0204 } 0205 } 0206 if (needToAppend) { 0207 categoriesList.append(category); 0208 insertCategories.append(category); 0209 } 0210 } 0211 } 0212 } 0213 return insertCategories; 0214 } 0215 0216 void KDebugSettingsUtil::readLoggingCategories(const QString &filename, KdeLoggingCategory::List &categoriesList, bool checkCategoryList) 0217 { 0218 QFile file(filename); 0219 if (!file.open(QIODevice::ReadOnly)) { 0220 qCWarning(KDEBUGSETTINGS_LOG) << "Couldn't open" << filename; 0221 } else { 0222 QString data; 0223 QTextStream ts(&file); 0224 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0225 ts.setCodec(QTextCodec::codecForName("ISO-8859-1")); 0226 #else 0227 ts.setEncoding(QStringConverter::Encoding::Latin1); 0228 #endif 0229 while (!ts.atEnd()) { 0230 data = ts.readLine().simplified(); 0231 const KdeLoggingCategory category = parseLineKdeLoggingCategory(data, filename); 0232 if (category.isValid()) { 0233 if (checkCategoryList) { 0234 bool needToAppend = true; 0235 for (const KdeLoggingCategory &cat : std::as_const(categoriesList)) { 0236 if (cat == category) { 0237 needToAppend = false; 0238 break; 0239 } else if (cat.categoryName == category.categoryName) { 0240 qCWarning(KDEBUGSETTINGS_LOG) 0241 << "Duplicate categories, it's a bug. Please verify: category:" << cat.categoryName << " filename : " << filename; 0242 needToAppend = false; 0243 } 0244 } 0245 if (needToAppend) { 0246 categoriesList.append(category); 0247 } 0248 } else { 0249 categoriesList.append(category); 0250 } 0251 } 0252 } 0253 } 0254 } 0255 0256 KDebugSettingsUtil::LineLoggingQtCategory KDebugSettingsUtil::parseLineLoggingQtCategory(const QString &line) 0257 { 0258 LineLoggingQtCategory lineCategory; 0259 int equalPos = line.indexOf(QLatin1Char('=')); 0260 if ((equalPos != -1) && (line.lastIndexOf(QLatin1Char('=')) == equalPos)) { 0261 const QString pattern = line.left(equalPos); 0262 const QString valueStr = line.mid(equalPos + 1); 0263 if (valueStr == QLatin1String("true")) { 0264 lineCategory.enabled = true; 0265 } else { 0266 lineCategory.enabled = false; 0267 } 0268 QString p; 0269 if (pattern.endsWith(QLatin1String(".debug"))) { 0270 p = pattern.left(pattern.length() - 6); // strlen(".debug") 0271 lineCategory.logName = p; 0272 lineCategory.type = LineLoggingQtCategory::Debug; 0273 } else if (pattern.endsWith(QLatin1String(".warning"))) { 0274 p = pattern.left(pattern.length() - 8); // strlen(".warning") 0275 lineCategory.logName = p; 0276 lineCategory.type = LineLoggingQtCategory::Warning; 0277 } else if (pattern.endsWith(QLatin1String(".critical"))) { 0278 p = pattern.left(pattern.length() - 9); // strlen(".critical") 0279 lineCategory.logName = p; 0280 lineCategory.type = LineLoggingQtCategory::Critical; 0281 } else if (pattern.endsWith(QLatin1String(".info"))) { 0282 p = pattern.left(pattern.length() - 5); // strlen(".info") 0283 lineCategory.logName = p; 0284 lineCategory.type = LineLoggingQtCategory::Info; 0285 } else { 0286 p = pattern; 0287 lineCategory.logName = p; 0288 lineCategory.type = LineLoggingQtCategory::All; 0289 } 0290 } else { 0291 lineCategory.enabled = false; 0292 } 0293 return lineCategory; 0294 } 0295 0296 QList<KDebugSettingsUtil::LoadLoggingCategory> KDebugSettingsUtil::readLoggingQtCategories(const QString &filename) 0297 { 0298 if (filename.isEmpty()) { 0299 qCWarning(KDEBUGSETTINGS_LOG) << "Empty file name"; 0300 return {}; 0301 } 0302 // Code based on src/corelib/io/qloggingregistry.cpp 0303 QFile file(filename); 0304 QMap<QString, KDebugSettingsUtil::LoadLoggingCategory> hashLoadLoggingCategories; 0305 if (file.open(QIODevice::ReadOnly)) { 0306 QTextStream ts(&file); 0307 QString _section; 0308 bool rulesSections = false; 0309 while (!ts.atEnd()) { 0310 QString line = ts.readLine(); 0311 0312 // Remove all whitespace from line 0313 line = line.simplified(); 0314 line.remove(QLatin1Char(' ')); 0315 0316 // comment 0317 if (line.startsWith(QLatin1Char(';'))) { 0318 continue; 0319 } 0320 0321 if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) { 0322 // new section 0323 _section = line.mid(1, line.size() - 2); 0324 rulesSections = (_section == QLatin1String("Rules")); 0325 continue; 0326 } 0327 if (rulesSections) { 0328 KDebugSettingsUtil::LineLoggingQtCategory cat = parseLineLoggingQtCategory(line); 0329 // qDebug() << " line " << line; 0330 // qDebug() << "enable " << cat.enabled << " valid : " << cat.isValid(); 0331 if (cat.isValid()) { 0332 KDebugSettingsUtil::LoadLoggingCategory nextCat = hashLoadLoggingCategories.value(cat.logName); 0333 if (nextCat.isValid()) { 0334 LoadLoggingCategory::LogType type; 0335 switch (cat.type) { 0336 case LineLoggingQtCategory::Unknown: 0337 type = LoadLoggingCategory::Unknown; 0338 break; 0339 case LineLoggingQtCategory::Info: 0340 type = LoadLoggingCategory::Info; 0341 break; 0342 case LineLoggingQtCategory::Warning: 0343 type = LoadLoggingCategory::Warning; 0344 break; 0345 case LineLoggingQtCategory::Debug: 0346 type = LoadLoggingCategory::Debug; 0347 break; 0348 case LineLoggingQtCategory::Critical: 0349 type = LoadLoggingCategory::Critical; 0350 break; 0351 case LineLoggingQtCategory::All: 0352 type = LoadLoggingCategory::All; 0353 break; 0354 } 0355 0356 if (nextCat.loggingTypes.contains(type)) { 0357 nextCat.loggingTypes[type] = cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled; 0358 } else { 0359 nextCat.loggingTypes.insert(type, cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0360 } 0361 hashLoadLoggingCategories[cat.logName] = nextCat; 0362 } else { 0363 nextCat.logName = cat.logName; 0364 switch (cat.type) { 0365 case LineLoggingQtCategory::Unknown: 0366 nextCat.loggingTypes.insert(LoadLoggingCategory::Unknown, 0367 cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0368 break; 0369 case LineLoggingQtCategory::Info: 0370 nextCat.loggingTypes.insert(LoadLoggingCategory::Info, cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0371 break; 0372 case LineLoggingQtCategory::Warning: 0373 nextCat.loggingTypes.insert(LoadLoggingCategory::Warning, 0374 cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0375 break; 0376 case LineLoggingQtCategory::Debug: 0377 nextCat.loggingTypes.insert(LoadLoggingCategory::Debug, cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0378 break; 0379 case LineLoggingQtCategory::Critical: 0380 nextCat.loggingTypes.insert(LoadLoggingCategory::Critical, 0381 cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0382 break; 0383 case LineLoggingQtCategory::All: 0384 nextCat.loggingTypes.insert(LoadLoggingCategory::All, cat.enabled ? LoadLoggingCategory::Enabled : LoadLoggingCategory::Disabled); 0385 break; 0386 } 0387 hashLoadLoggingCategories.insert(cat.logName, nextCat); 0388 } 0389 } 0390 } 0391 } 0392 } else { 0393 qCWarning(KDEBUGSETTINGS_LOG) << "Impossible to open file: " << filename; 0394 } 0395 0396 return hashLoadLoggingCategories.values(); 0397 } 0398 0399 LoggingCategory::LoggingType KDebugSettingsUtil::convertCategoryTypeFromString(const QString &str) 0400 { 0401 if (str.isEmpty()) { 0402 return LoggingCategory::Info; // Default 0403 } else if (str == QLatin1String("DEBUG")) { 0404 return LoggingCategory::Debug; 0405 } else if (str == QLatin1String("INFO")) { 0406 return LoggingCategory::Info; 0407 } else if (str == QLatin1String("WARNING")) { 0408 return LoggingCategory::Warning; 0409 } else if (str == QLatin1String("CRITICAL")) { 0410 return LoggingCategory::Critical; 0411 } 0412 qCWarning(KDEBUGSETTINGS_LOG) << "Default category is unknown: " << str; 0413 return LoggingCategory::Info; 0414 } 0415 0416 QString KDebugSettingsUtil::convertCategoryTypeToString(LoggingCategory::LoggingType type) 0417 { 0418 QString str; 0419 switch (type) { 0420 case LoggingCategory::All: 0421 str = i18n("All Debug Messages"); 0422 break; 0423 case LoggingCategory::Info: 0424 str = i18n("Info Messages"); 0425 break; 0426 case LoggingCategory::Warning: 0427 str = i18n("Warning Messages"); 0428 break; 0429 case LoggingCategory::Debug: 0430 str = i18n("Debug Messages"); 0431 break; 0432 case LoggingCategory::Critical: 0433 str = i18n("Critical Messages"); 0434 break; 0435 case LoggingCategory::Off: 0436 str = i18n("No Debug Messages"); 0437 break; 0438 case LoggingCategory::Undefined: 0439 str = i18n("Undefined"); 0440 break; 0441 } 0442 return str; 0443 } 0444 0445 QString KDebugSettingsUtil::qtFileName() 0446 { 0447 const QString envPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/QtProject"); 0448 QDir().mkpath(envPath); 0449 const QString qtloggingFileName = envPath + QStringLiteral("/qtlogging.ini"); 0450 return qtloggingFileName; 0451 }