2023-07-12 15:58:41 +08:00
|
|
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
#ifndef DESKTOPENTRY_H
|
|
|
|
#define DESKTOPENTRY_H
|
|
|
|
|
2023-07-12 15:58:41 +08:00
|
|
|
#include <QString>
|
|
|
|
#include <QMap>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QLocale>
|
|
|
|
#include <QTextStream>
|
|
|
|
#include <optional>
|
2023-08-21 16:02:26 +08:00
|
|
|
#include <QFile>
|
2023-07-12 15:58:41 +08:00
|
|
|
|
|
|
|
constexpr static auto defaultKeyStr = "default";
|
|
|
|
|
2023-08-11 17:46:46 +08:00
|
|
|
enum class DesktopErrorCode {
|
|
|
|
NoError,
|
|
|
|
NotFound,
|
|
|
|
MismatchedFile,
|
|
|
|
InvalidLocation,
|
|
|
|
OpenFailed,
|
|
|
|
GroupHeaderInvalid,
|
|
|
|
EntryKeyInvalid
|
|
|
|
};
|
2023-07-12 15:58:41 +08:00
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
struct DesktopFileGuard;
|
|
|
|
|
2023-07-24 14:12:59 +08:00
|
|
|
struct DesktopFile
|
|
|
|
{
|
2023-08-21 16:02:26 +08:00
|
|
|
friend struct DesktopFileGuard;
|
|
|
|
DesktopFile(const DesktopFile &) = delete;
|
2023-07-24 14:12:59 +08:00
|
|
|
DesktopFile(DesktopFile &&) = default;
|
2023-08-21 16:02:26 +08:00
|
|
|
DesktopFile &operator=(const DesktopFile &) = delete;
|
2023-07-24 14:12:59 +08:00
|
|
|
DesktopFile &operator=(DesktopFile &&) = default;
|
|
|
|
~DesktopFile() = default;
|
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
[[nodiscard]] QString sourcePath() const noexcept;
|
|
|
|
// WARNING: This raw pointer's ownership belong to DesktopFile, DO NOT MODIFY!
|
|
|
|
[[nodiscard]] QFile *sourceFile() const noexcept { return &sourceFileRef(); };
|
|
|
|
[[nodiscard]] QFile &sourceFileRef() const noexcept { return *m_fileSource; };
|
2023-08-20 18:25:59 +08:00
|
|
|
[[nodiscard]] const QString &desktopId() const noexcept { return m_desktopId; }
|
|
|
|
[[nodiscard]] bool modified(std::size_t time) const noexcept;
|
2023-07-24 14:12:59 +08:00
|
|
|
|
2023-08-11 17:46:46 +08:00
|
|
|
static std::optional<DesktopFile> searchDesktopFileById(const QString &appId, DesktopErrorCode &err) noexcept;
|
|
|
|
static std::optional<DesktopFile> searchDesktopFileByPath(const QString &desktopFilePath, DesktopErrorCode &err) noexcept;
|
2023-08-21 16:02:26 +08:00
|
|
|
static std::optional<DesktopFile> createTemporaryDesktopFile(std::unique_ptr<QFile> temporaryFile) noexcept;
|
2023-07-24 14:12:59 +08:00
|
|
|
|
|
|
|
private:
|
2023-08-21 16:02:26 +08:00
|
|
|
DesktopFile(std::unique_ptr<QFile> source, QString fileId, std::size_t mtime)
|
|
|
|
: m_mtime(mtime)
|
2023-08-20 18:25:59 +08:00
|
|
|
, m_fileSource(std::move(source))
|
2023-07-24 14:12:59 +08:00
|
|
|
, m_desktopId(std::move(fileId))
|
|
|
|
{
|
|
|
|
}
|
2023-08-10 14:32:09 +08:00
|
|
|
|
|
|
|
std::size_t m_mtime;
|
2023-08-21 16:02:26 +08:00
|
|
|
std::unique_ptr<QFile> m_fileSource{nullptr};
|
2023-07-24 14:12:59 +08:00
|
|
|
QString m_desktopId{""};
|
|
|
|
};
|
|
|
|
|
2023-08-21 16:02:26 +08:00
|
|
|
struct DesktopFileGuard
|
|
|
|
{
|
|
|
|
DesktopFileGuard(const DesktopFileGuard &) = delete;
|
|
|
|
DesktopFileGuard(DesktopFileGuard &&other) noexcept
|
|
|
|
: fileRef(other.fileRef)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
DesktopFileGuard &operator=(const DesktopFileGuard &) = delete;
|
|
|
|
DesktopFileGuard &operator=(DesktopFileGuard &&) = delete;
|
|
|
|
|
|
|
|
explicit DesktopFileGuard(DesktopFile &file)
|
|
|
|
: fileRef(file)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool try_open() { return fileRef.m_fileSource->open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text); }
|
|
|
|
~DesktopFileGuard()
|
|
|
|
{
|
|
|
|
if (fileRef.m_fileSource->isOpen()) {
|
|
|
|
fileRef.m_fileSource->close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
DesktopFile &fileRef;
|
|
|
|
};
|
|
|
|
|
2023-07-12 15:58:41 +08:00
|
|
|
class DesktopEntry
|
|
|
|
{
|
|
|
|
public:
|
2023-08-20 18:25:59 +08:00
|
|
|
class Value final : private QMap<QString, QString>
|
2023-07-12 15:58:41 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
using QMap<QString, QString>::QMap;
|
2023-08-20 18:25:59 +08:00
|
|
|
using QMap<QString, QString>::find;
|
|
|
|
using QMap<QString, QString>::insert;
|
|
|
|
using QMap<QString, QString>::cbegin;
|
|
|
|
using QMap<QString, QString>::cend;
|
|
|
|
using QMap<QString, QString>::begin;
|
|
|
|
using QMap<QString, QString>::end;
|
|
|
|
|
2023-07-12 15:58:41 +08:00
|
|
|
QString toString(bool &ok) const noexcept;
|
|
|
|
bool toBoolean(bool &ok) const noexcept;
|
|
|
|
QString toIconString(bool &ok) const noexcept;
|
|
|
|
float toNumeric(bool &ok) const noexcept;
|
|
|
|
QString toLocaleString(const QLocale &locale, bool &ok) const noexcept;
|
|
|
|
friend QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
|
|
|
|
|
|
|
|
private:
|
2023-08-10 14:32:09 +08:00
|
|
|
[[nodiscard]] static QString unescape(const QString &str) noexcept;
|
2023-07-12 15:58:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
DesktopEntry() = default;
|
2023-08-10 14:32:09 +08:00
|
|
|
DesktopEntry(const DesktopEntry &) = default;
|
|
|
|
DesktopEntry(DesktopEntry &&) = default;
|
|
|
|
DesktopEntry &operator=(const DesktopEntry &) = default;
|
|
|
|
DesktopEntry &operator=(DesktopEntry &&) = default;
|
|
|
|
|
2023-07-12 15:58:41 +08:00
|
|
|
~DesktopEntry() = default;
|
2023-08-21 16:02:26 +08:00
|
|
|
[[nodiscard]] DesktopErrorCode parse(DesktopFile &file) noexcept;
|
2023-08-11 17:46:46 +08:00
|
|
|
[[nodiscard]] DesktopErrorCode parse(QTextStream &stream) noexcept;
|
2023-07-24 14:12:59 +08:00
|
|
|
[[nodiscard]] std::optional<QMap<QString, Value>> group(const QString &key) const noexcept;
|
|
|
|
[[nodiscard]] std::optional<Value> value(const QString &key, const QString &valueKey) const noexcept;
|
2023-07-12 15:58:41 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
QMap<QString, QMap<QString, Value>> m_entryMap;
|
|
|
|
auto parserGroupHeader(const QString &str) noexcept;
|
2023-08-11 17:46:46 +08:00
|
|
|
static DesktopErrorCode parseEntry(const QString &str, decltype(m_entryMap)::iterator ¤tGroup) noexcept;
|
2023-07-12 15:58:41 +08:00
|
|
|
};
|
|
|
|
|
2023-07-21 14:47:40 +08:00
|
|
|
QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
|
2023-07-19 17:56:45 +08:00
|
|
|
|
2023-08-11 17:46:46 +08:00
|
|
|
QDebug operator<<(QDebug debug, const DesktopErrorCode &v);
|
2023-08-21 16:02:26 +08:00
|
|
|
|
|
|
|
#endif
|