| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // SPDX-License-Identifier: LGPL-3.0-or-later
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "desktopentry.h"
 | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | #include "global.h"
 | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | #include <QFileInfo>
 | 
					
						
							|  |  |  | #include <QDir>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <QRegularExpression>
 | 
					
						
							|  |  |  | #include <QDirIterator>
 | 
					
						
							|  |  |  | #include <QStringView>
 | 
					
						
							|  |  |  | #include <QVariant>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2023-08-20 18:25:59 +08:00
										 |  |  | #include <chrono>
 | 
					
						
							| 
									
										
										
										
											2023-08-23 17:20:47 +08:00
										 |  |  | #include <cstdio>
 | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 11:35:59 +08:00
										 |  |  | auto DesktopEntry::parseGroupHeader(const QString &str) noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-25 11:35:59 +08:00
										 |  |  |     // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#group-header
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     auto groupHeader = str.sliced(1, str.size() - 2).trimmed(); | 
					
						
							|  |  |  |     decltype(m_entryMap)::iterator it{m_entryMap.end()}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 11:35:59 +08:00
										 |  |  |     // NOTE:
 | 
					
						
							|  |  |  |     // This regex match '[', ']', control characters
 | 
					
						
							|  |  |  |     // and all non-ascii characters.
 | 
					
						
							|  |  |  |     // They are invalid in group header.
 | 
					
						
							|  |  |  |     // https://regex101.com/r/bZhHZo/1
 | 
					
						
							|  |  |  |     QRegularExpression re{R"([^\x20-\x5a\x5e-\x7e\x5c])"}; | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     auto matcher = re.match(groupHeader); | 
					
						
							|  |  |  |     if (matcher.hasMatch()) { | 
					
						
							| 
									
										
										
										
											2023-08-25 11:35:59 +08:00
										 |  |  |         qWarning() << "group header invalid:" << str; | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |         return it; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto tmp = m_entryMap.find(groupHeader); | 
					
						
							|  |  |  |     if (tmp == m_entryMap.end()) { | 
					
						
							|  |  |  |         it = m_entryMap.insert(groupHeader, {}); | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 11:35:59 +08:00
										 |  |  |     qWarning() << "group header already exists:" << str; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     return it; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  | QString DesktopFile::sourcePath() const noexcept | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     if (!m_fileSource) { | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  |     QFileInfo info(*m_fileSource); | 
					
						
							|  |  |  |     return info.absoluteFilePath(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-08-20 18:25:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  | bool DesktopEntry::isInvalidLocaleString(const QString &str) noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     constexpr auto Language = R"((?:[a-z]+))";        // language of locale postfix. eg.(en, zh)
 | 
					
						
							|  |  |  |     constexpr auto Country = R"((?:_[A-Z]+))";        // country of locale postfix. eg.(US, CN)
 | 
					
						
							|  |  |  |     constexpr auto Encoding = R"((?:\.[0-9A-Z-]+))";  // encoding of locale postfix. eg.(UFT-8)
 | 
					
						
							|  |  |  |     constexpr auto Modifier = R"((?:@[a-z=;]+))";     // modifier of locale postfix. eg.(euro;collation=traditional)
 | 
					
						
							|  |  |  |     const static auto validKey = QString(R"(^%1%2?%3?%4?$)").arg(Language, Country, Encoding, Modifier); | 
					
						
							|  |  |  |     // example: https://regex101.com/r/hylOay/2
 | 
					
						
							|  |  |  |     static QRegularExpression re = []() -> QRegularExpression { | 
					
						
							|  |  |  |         QRegularExpression tmp{validKey}; | 
					
						
							|  |  |  |         tmp.optimize(); | 
					
						
							|  |  |  |         return tmp; | 
					
						
							|  |  |  |     }(); | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     return re.match(str).hasMatch(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QPair<QString, QString> DesktopEntry::processEntry(const QString &str) noexcept | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     auto splitCharIndex = str.indexOf(']'); | 
					
						
							| 
									
										
										
										
											2023-07-21 14:47:40 +08:00
										 |  |  |     if (splitCharIndex != -1) { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         for (; splitCharIndex < str.size(); ++splitCharIndex) { | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |             if (str.at(splitCharIndex) == '=') { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         splitCharIndex = str.indexOf('='); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     auto keyStr = str.first(splitCharIndex).trimmed(); | 
					
						
							|  |  |  |     auto valueStr = str.sliced(splitCharIndex + 1).trimmed(); | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     return qMakePair(std::move(keyStr), std::move(valueStr)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::optional<QPair<QString, QString>> DesktopEntry::processEntryKey(const QString &keyStr) noexcept | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     QString key; | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     QString localeStr; | 
					
						
							| 
									
										
										
										
											2023-08-25 11:16:01 +08:00
										 |  |  |     // NOTE:
 | 
					
						
							|  |  |  |     // We are process "localized keys" here, for usage check:
 | 
					
						
							|  |  |  |     // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#localized-keys
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     if (auto index = keyStr.indexOf('['); index != -1) { | 
					
						
							|  |  |  |         key = keyStr.sliced(0, index); | 
					
						
							|  |  |  |         localeStr = keyStr.sliced(index + 1, keyStr.length() - 1 - index - 1);  // strip '[' and ']'
 | 
					
						
							| 
									
										
										
										
											2023-08-25 11:16:01 +08:00
										 |  |  |         if (!isInvalidLocaleString(localeStr)) { | 
					
						
							|  |  |  |             qWarning().noquote() << QString("invalid LOCALE (%2) for key \"%1\"").arg(key, localeStr); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         key = keyStr; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-21 18:38:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     QRegularExpression re{"R([^A-Za-z0-9-])"}; | 
					
						
							|  |  |  |     if (re.match(key).hasMatch()) { | 
					
						
							|  |  |  |         qWarning() << "keyName's format is invalid."; | 
					
						
							|  |  |  |         return std::nullopt; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     return qMakePair(std::move(key), std::move(localeStr)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DesktopErrorCode DesktopEntry::parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto [key, value] = processEntry(str); | 
					
						
							|  |  |  |     auto keyPair = processEntryKey(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!keyPair.has_value()) { | 
					
						
							|  |  |  |         return DesktopErrorCode::InvalidFormat; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     auto [keyName, localeStr] = std::move(keyPair).value(); | 
					
						
							|  |  |  |     if (localeStr.isEmpty()) { | 
					
						
							|  |  |  |         localeStr = defaultKeyStr; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     auto valueIt = currentGroup->find(keyName); | 
					
						
							|  |  |  |     if (valueIt == currentGroup->end()) { | 
					
						
							|  |  |  |         currentGroup->insert(keyName, {{localeStr, value}}); | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         return DesktopErrorCode::NoError; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     auto innerIt = valueIt->find(localeStr); | 
					
						
							|  |  |  |     if (innerIt == valueIt->end()) { | 
					
						
							|  |  |  |         valueIt->insert(localeStr, value); | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         return DesktopErrorCode::NoError; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qWarning() << "duplicated postfix and this line will be aborted, maybe format is invalid.\n" | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |                << "exist: " << innerIt.key() << "[" << innerIt.value() << "]" | 
					
						
							|  |  |  |                << "current: " << keyName << "[" << localeStr << "]"; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |     return DesktopErrorCode::NoError; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  | bool DesktopEntry::checkMainEntryValidation() const noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto it = m_entryMap.find(DesktopFileEntryKey); | 
					
						
							|  |  |  |     if (it == m_entryMap.end()) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (auto name = it->find("Name"); name == it->end()) { | 
					
						
							|  |  |  |         qWarning() << "No Name."; | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto type = it->find("Type"); | 
					
						
							|  |  |  |     if (type == it->end()) { | 
					
						
							|  |  |  |         qWarning() << "No Type."; | 
					
						
							|  |  |  |         for (const auto &[k, v] : it->asKeyValueRange()) { | 
					
						
							|  |  |  |             qInfo() << "keyName:" << k; | 
					
						
							|  |  |  |             for (const auto &[key, value] : v.asKeyValueRange()) { | 
					
						
							|  |  |  |                 qInfo() << key << value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto &typeStr = *type->find(defaultKeyStr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (typeStr == "Link") { | 
					
						
							|  |  |  |         if (it->find("URL") == it->end()) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  | std::optional<DesktopFile> DesktopFile::createTemporaryDesktopFile(std::unique_ptr<QFile> temporaryFile) noexcept | 
					
						
							| 
									
										
										
										
											2023-08-20 18:25:59 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  |     auto mtime = getFileModifiedTime(*temporaryFile); | 
					
						
							|  |  |  |     if (mtime == 0) { | 
					
						
							|  |  |  |         qWarning() << "create temporary file failed."; | 
					
						
							|  |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return DesktopFile{std::move(temporaryFile), "", mtime}; | 
					
						
							| 
									
										
										
										
											2023-08-20 18:25:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 17:20:47 +08:00
										 |  |  | std::optional<DesktopFile> DesktopFile::createTemporaryDesktopFile(const QString &temporaryFile) noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const static QString userTmp = QString{"/run/user/%1/"}.arg(getCurrentUID()); | 
					
						
							|  |  |  |     auto tempFile = std::make_unique<QFile>(QString{userTmp + QUuid::createUuid().toString(QUuid::Id128) + ".desktop"}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!tempFile->open(QFile::NewOnly | QFile::WriteOnly | QFile::Text)) { | 
					
						
							|  |  |  |         qWarning() << "failed to create temporary desktop file:" << QFileInfo{*tempFile}.absoluteFilePath() | 
					
						
							|  |  |  |                    << tempFile->errorString(); | 
					
						
							|  |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto content = temporaryFile.toLocal8Bit(); | 
					
						
							|  |  |  |     auto writeByte = tempFile->write(content); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (writeByte == -1 || writeByte != content.length()) { | 
					
						
							|  |  |  |         qWarning() << "write to temporary file failed:" << tempFile->errorString(); | 
					
						
							|  |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tempFile->close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return createTemporaryDesktopFile(std::move(tempFile)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  | std::optional<DesktopFile> DesktopFile::searchDesktopFileByPath(const QString &desktopFile, DesktopErrorCode &err) noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-23 17:20:47 +08:00
										 |  |  |     decltype(auto) desktopSuffix = ".desktop"; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 16:30:16 +08:00
										 |  |  |     if (!desktopFile.endsWith(desktopSuffix)) { | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         qWarning() << "file isn't a desktop file:" << desktopFile; | 
					
						
							|  |  |  |         err = DesktopErrorCode::MismatchedFile; | 
					
						
							|  |  |  |         return std::nullopt; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |     QFileInfo fileinfo{desktopFile}; | 
					
						
							|  |  |  |     if (!fileinfo.isAbsolute() or !fileinfo.exists()) { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         qWarning() << "desktop file not found."; | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         err = DesktopErrorCode::NotFound; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QString path{desktopFile}; | 
					
						
							|  |  |  |     QString id; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 17:20:47 +08:00
										 |  |  |     const auto &XDGDataDirs = getDesktopFileDirs(); | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |     auto idGen = std::any_of(XDGDataDirs.cbegin(), XDGDataDirs.cend(), [&desktopFile](const QString &suffixPath) { | 
					
						
							|  |  |  |         return desktopFile.startsWith(suffixPath); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (idGen) { | 
					
						
							| 
									
										
										
										
											2023-08-14 16:30:16 +08:00
										 |  |  |         auto tmp = path.chopped(sizeof(desktopSuffix) - 1); | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         auto components = tmp.split(QDir::separator()).toList(); | 
					
						
							|  |  |  |         auto it = std::find(components.cbegin(), components.cend(), "applications"); | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |         QString FileId; | 
					
						
							|  |  |  |         ++it; | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         while (it != components.cend()) { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             FileId += (*(it++) + "-"); | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |         id = FileId.chopped(1);  // remove extra "-""
 | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  |     auto filePtr = std::make_unique<QFile>(std::move(path)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto mtime = getFileModifiedTime(*filePtr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (mtime == 0) { | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         err = DesktopErrorCode::OpenFailed; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |     err = DesktopErrorCode::NoError; | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  |     return DesktopFile{std::move(filePtr), std::move(id), mtime}; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  | std::optional<DesktopFile> DesktopFile::searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-23 17:20:47 +08:00
										 |  |  |     auto XDGDataDirs = getDesktopFileDirs(); | 
					
						
							| 
									
										
										
										
											2023-08-14 16:30:16 +08:00
										 |  |  |     constexpr auto desktopSuffix = u8".desktop"; | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (const auto &dir : XDGDataDirs) { | 
					
						
							| 
									
										
										
										
											2023-08-14 16:30:16 +08:00
										 |  |  |         auto app = QFileInfo{dir + QDir::separator() + appId + desktopSuffix}; | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         while (!app.exists()) { | 
					
						
							|  |  |  |             auto filePath = app.absoluteFilePath(); | 
					
						
							|  |  |  |             auto hyphenIndex = filePath.indexOf('-'); | 
					
						
							|  |  |  |             if (hyphenIndex == -1) { | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             filePath.replace(hyphenIndex, 1, QDir::separator()); | 
					
						
							|  |  |  |             app.setFile(filePath); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (app.exists()) { | 
					
						
							|  |  |  |             return searchDesktopFileByPath(app.absoluteFilePath(), err); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-14 16:30:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     err = DesktopErrorCode::NotFound; | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |     return std::nullopt; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | bool DesktopFile::modified(std::size_t time) const noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return time != m_mtime; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  | DesktopErrorCode DesktopEntry::parse(DesktopFile &file) noexcept | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  |     DesktopFileGuard guard{file}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!guard.try_open()) { | 
					
						
							|  |  |  |         qWarning() << file.sourcePath() << "can't open."; | 
					
						
							|  |  |  |         return DesktopErrorCode::OpenFailed; | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 16:02:26 +08:00
										 |  |  |     QTextStream stream; | 
					
						
							|  |  |  |     stream.setDevice(file.sourceFile()); | 
					
						
							|  |  |  |     return parse(stream); | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  | bool DesktopEntry::skipCheck(const QString &line) noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return line.startsWith('#') or line.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  | DesktopErrorCode DesktopEntry::parse(QTextStream &stream) noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     if (stream.atEnd()) { | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |         if (m_context == EntryContext::Done) { | 
					
						
							|  |  |  |             return DesktopErrorCode::NoError; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         return DesktopErrorCode::OpenFailed; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     stream.setEncoding(QStringConverter::Utf8); | 
					
						
							|  |  |  |     decltype(m_entryMap)::iterator currentGroup; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |     DesktopErrorCode err{DesktopErrorCode::NoError}; | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     bool mainEntryParsed{false}; | 
					
						
							|  |  |  |     QString line; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     while (!stream.atEnd()) { | 
					
						
							|  |  |  |         switch (m_context) { | 
					
						
							|  |  |  |             case EntryContext::Unknown: { | 
					
						
							|  |  |  |                 qWarning() << "entry context is unknown,abort."; | 
					
						
							|  |  |  |                 err = DesktopErrorCode::InvalidFormat; | 
					
						
							|  |  |  |                 return err; | 
					
						
							|  |  |  |             } break; | 
					
						
							|  |  |  |             case EntryContext::EntryOuter: { | 
					
						
							|  |  |  |                 if (skipCheck(line)) { | 
					
						
							|  |  |  |                     line = stream.readLine().trimmed(); | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (line.startsWith('[')) { | 
					
						
							| 
									
										
										
										
											2023-08-25 11:35:59 +08:00
										 |  |  |                     auto group = parseGroupHeader(line); | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (group == m_entryMap.end()) { | 
					
						
							|  |  |  |                         return DesktopErrorCode::InvalidFormat; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     currentGroup = group; | 
					
						
							|  |  |  |                     bool isMainEntry = (currentGroup.key() == DesktopFileEntryKey); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if ((!mainEntryParsed and isMainEntry) or (mainEntryParsed and !isMainEntry)) { | 
					
						
							|  |  |  |                         m_context = EntryContext::Entry; | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 qWarning() << "groupName format error:" << line; | 
					
						
							|  |  |  |                 err = DesktopErrorCode::InvalidFormat; | 
					
						
							|  |  |  |                 return err; | 
					
						
							|  |  |  |             } break; | 
					
						
							|  |  |  |             case EntryContext::Entry: { | 
					
						
							|  |  |  |                 line = stream.readLine().trimmed(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (skipCheck(line)) { | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (line.startsWith('[')) { | 
					
						
							|  |  |  |                     m_context = EntryContext::EntryOuter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (currentGroup.key() == DesktopFileEntryKey) { | 
					
						
							|  |  |  |                         mainEntryParsed = true; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 err = parseEntry(line, currentGroup); | 
					
						
							|  |  |  |                 if (err != DesktopErrorCode::NoError) { | 
					
						
							|  |  |  |                     qWarning() << "Entry format error:" << line; | 
					
						
							|  |  |  |                     return err; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } break; | 
					
						
							|  |  |  |             case EntryContext::Done: | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |     m_context = EntryContext::Done; | 
					
						
							|  |  |  |     if (!checkMainEntryValidation()) { | 
					
						
							|  |  |  |         qWarning() << "invalid MainEntry, abort."; | 
					
						
							|  |  |  |         err = DesktopErrorCode::MissingInfo; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  | std::optional<QMap<QString, DesktopEntry::Value>> DesktopEntry::group(const QString &key) const noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     if (auto group = m_entryMap.find(key); group != m_entryMap.cend()) { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         return *group; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |     return std::nullopt; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::optional<DesktopEntry::Value> DesktopEntry::value(const QString &groupKey, const QString &valueKey) const noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const auto &destGroup = group(groupKey); | 
					
						
							|  |  |  |     if (!destGroup) { | 
					
						
							| 
									
										
										
										
											2023-08-16 17:44:56 +08:00
										 |  |  | #ifdef DEBUG_MODE
 | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |         qWarning() << "group " << groupKey << " can't be found."; | 
					
						
							| 
									
										
										
										
											2023-08-16 17:44:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto it = destGroup->find(valueKey); | 
					
						
							|  |  |  |     if (it == destGroup->cend()) { | 
					
						
							| 
									
										
										
										
											2023-08-16 17:44:56 +08:00
										 |  |  | #ifdef DEBUG_MODE
 | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |         qWarning() << "value " << valueKey << " can't be found."; | 
					
						
							| 
									
										
										
										
											2023-08-16 17:44:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-07-24 14:12:59 +08:00
										 |  |  |         return std::nullopt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return *it; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  | QString DesktopEntry::Value::unescape(const QString &str) noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     QString unescapedStr; | 
					
						
							|  |  |  |     for (qsizetype i = 0; i < str.size(); ++i) { | 
					
						
							|  |  |  |         auto c = str.at(i); | 
					
						
							|  |  |  |         if (c != '\\') { | 
					
						
							|  |  |  |             unescapedStr.append(c); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (str.at(i + 1).toLatin1()) { | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 unescapedStr.append(c); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'n': | 
					
						
							|  |  |  |                 unescapedStr.append('\n'); | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 't': | 
					
						
							|  |  |  |                 unescapedStr.append('\t'); | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'r': | 
					
						
							|  |  |  |                 unescapedStr.append('\r'); | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case '\\': | 
					
						
							|  |  |  |                 unescapedStr.append('\\'); | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case ';': | 
					
						
							|  |  |  |                 unescapedStr.append(';'); | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 's': | 
					
						
							|  |  |  |                 unescapedStr.append(' '); | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return unescapedStr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString DesktopEntry::Value::toString(bool &ok) const noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ok = false; | 
					
						
							|  |  |  |     auto str = this->find(defaultKeyStr); | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     if (str == this->end()) { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     auto unescapedStr = unescape(*str); | 
					
						
							|  |  |  |     constexpr auto controlChars = "\\p{Cc}"; | 
					
						
							|  |  |  |     constexpr auto asciiChars = "[^\x00-\x7f]"; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     if (unescapedStr.contains(QRegularExpression{controlChars}) and unescapedStr.contains(QRegularExpression{asciiChars})) { | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2023-08-10 14:32:09 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ok = true; | 
					
						
							|  |  |  |     return unescapedStr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 14:47:40 +08:00
										 |  |  | QString DesktopEntry::Value::toLocaleString(const QLocale &locale, bool &ok) const noexcept | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     ok = false; | 
					
						
							|  |  |  |     for (auto it = this->constKeyValueBegin(); it != this->constKeyValueEnd(); ++it) { | 
					
						
							|  |  |  |         auto [a, b] = *it; | 
					
						
							|  |  |  |         if (QLocale{a}.name() == locale.name()) { | 
					
						
							|  |  |  |             ok = true; | 
					
						
							|  |  |  |             return unescape(b); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return toString(ok); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString DesktopEntry::Value::toIconString(bool &ok) const noexcept | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return toString(ok); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DesktopEntry::Value::toBoolean(bool &ok) const noexcept | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |     ok = false; | 
					
						
							| 
									
										
										
										
											2023-07-21 14:47:40 +08:00
										 |  |  |     const auto &str = (*this)[defaultKeyStr]; | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |     if (str == "true") { | 
					
						
							|  |  |  |         ok = true; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (str == "false") { | 
					
						
							|  |  |  |         ok = true; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float DesktopEntry::Value::toNumeric(bool &ok) const noexcept | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-21 14:47:40 +08:00
										 |  |  |     const auto &str = (*this)[defaultKeyStr]; | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     QVariant v{str}; | 
					
						
							|  |  |  |     return v.toFloat(&ok); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDebug operator<<(QDebug debug, const DesktopEntry::Value &v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDebugStateSaver saver{debug}; | 
					
						
							| 
									
										
										
										
											2023-07-21 14:47:40 +08:00
										 |  |  |     debug << static_cast<const QMap<QString, QString> &>(v); | 
					
						
							| 
									
										
										
										
											2023-07-12 15:58:41 +08:00
										 |  |  |     return debug; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  | QDebug operator<<(QDebug debug, const DesktopErrorCode &v) | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     QDebugStateSaver saver{debug}; | 
					
						
							|  |  |  |     QString errMsg; | 
					
						
							|  |  |  |     switch (v) { | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         case DesktopErrorCode::NoError: { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             errMsg = "no error."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         case DesktopErrorCode::NotFound: { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             errMsg = "file not found."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         case DesktopErrorCode::MismatchedFile: { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             errMsg = "file type is mismatched."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         case DesktopErrorCode::InvalidLocation: { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             errMsg = "file location is invalid, please check $XDG_DATA_DIRS."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-11 17:46:46 +08:00
										 |  |  |         case DesktopErrorCode::OpenFailed: { | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             errMsg = "couldn't open the file."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |         case DesktopErrorCode::InvalidFormat: { | 
					
						
							|  |  |  |             errMsg = "the format of desktopEntry file is invalid."; | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-25 10:47:17 +08:00
										 |  |  |         case DesktopErrorCode::MissingInfo: { | 
					
						
							|  |  |  |             errMsg = "missing required infomation."; | 
					
						
							| 
									
										
										
										
											2023-07-19 17:56:45 +08:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     debug << errMsg; | 
					
						
							|  |  |  |     return debug; | 
					
						
							|  |  |  | } |