2026-01-18 12:13:07 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
// SPDX-FileCopyrightText: 2024 A-La-Karte Contributors
|
|
|
|
|
|
|
|
|
|
#include "game.h"
|
|
|
|
|
|
|
|
|
|
#include <KLocalizedString>
|
2026-01-25 13:19:57 +00:00
|
|
|
#include <QCryptographicHash>
|
|
|
|
|
#include <QJsonValue>
|
2026-01-18 12:13:07 +00:00
|
|
|
#include <QLocale>
|
|
|
|
|
#include <QUuid>
|
|
|
|
|
|
|
|
|
|
Game::Game(QObject *parent)
|
|
|
|
|
: QObject(parent)
|
|
|
|
|
, m_id(QUuid::createUuid().toString(QUuid::WithoutBraces))
|
|
|
|
|
, m_dateAdded(QDateTime::currentDateTime())
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Game::Game(const QString &id, const QString &name, QObject *parent)
|
|
|
|
|
: QObject(parent)
|
|
|
|
|
, m_id(id.isEmpty() ? QUuid::createUuid().toString(QUuid::WithoutBraces) : id)
|
|
|
|
|
, m_name(name)
|
|
|
|
|
, m_dateAdded(QDateTime::currentDateTime())
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::id() const
|
|
|
|
|
{
|
|
|
|
|
return m_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::name() const
|
|
|
|
|
{
|
|
|
|
|
return m_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setName(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
if (m_name != name) {
|
|
|
|
|
m_name = name;
|
|
|
|
|
Q_EMIT nameChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::description() const
|
|
|
|
|
{
|
|
|
|
|
return m_description;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setDescription(const QString &description)
|
|
|
|
|
{
|
|
|
|
|
if (m_description != description) {
|
|
|
|
|
m_description = description;
|
|
|
|
|
Q_EMIT descriptionChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::developer() const
|
|
|
|
|
{
|
|
|
|
|
return m_developer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setDeveloper(const QString &developer)
|
|
|
|
|
{
|
|
|
|
|
if (m_developer != developer) {
|
|
|
|
|
m_developer = developer;
|
|
|
|
|
Q_EMIT developerChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::publisher() const
|
|
|
|
|
{
|
|
|
|
|
return m_publisher;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setPublisher(const QString &publisher)
|
|
|
|
|
{
|
|
|
|
|
if (m_publisher != publisher) {
|
|
|
|
|
m_publisher = publisher;
|
|
|
|
|
Q_EMIT publisherChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QUrl Game::coverUrl() const
|
|
|
|
|
{
|
|
|
|
|
return m_coverUrl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setCoverUrl(const QUrl &url)
|
|
|
|
|
{
|
|
|
|
|
if (m_coverUrl != url) {
|
|
|
|
|
m_coverUrl = url;
|
|
|
|
|
Q_EMIT coverUrlChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QUrl Game::iconUrl() const
|
|
|
|
|
{
|
|
|
|
|
return m_iconUrl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setIconUrl(const QUrl &url)
|
|
|
|
|
{
|
|
|
|
|
if (m_iconUrl != url) {
|
|
|
|
|
m_iconUrl = url;
|
|
|
|
|
Q_EMIT iconUrlChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::launchCommand() const
|
|
|
|
|
{
|
|
|
|
|
return m_launchCommand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setLaunchCommand(const QString &command)
|
|
|
|
|
{
|
|
|
|
|
if (m_launchCommand != command) {
|
|
|
|
|
m_launchCommand = command;
|
|
|
|
|
Q_EMIT launchCommandChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::workingDirectory() const
|
|
|
|
|
{
|
|
|
|
|
return m_workingDirectory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setWorkingDirectory(const QString &dir)
|
|
|
|
|
{
|
|
|
|
|
if (m_workingDirectory != dir) {
|
|
|
|
|
m_workingDirectory = dir;
|
|
|
|
|
Q_EMIT workingDirectoryChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 13:19:57 +00:00
|
|
|
QVariantMap Game::launchEnv() const
|
|
|
|
|
{
|
|
|
|
|
return m_launchEnv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setLaunchEnv(const QVariantMap &env)
|
|
|
|
|
{
|
|
|
|
|
if (m_launchEnv != env) {
|
|
|
|
|
m_launchEnv = env;
|
|
|
|
|
Q_EMIT launchEnvChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::launchRunner() const
|
|
|
|
|
{
|
|
|
|
|
return m_launchRunner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setLaunchRunner(const QString &runner)
|
|
|
|
|
{
|
|
|
|
|
if (m_launchRunner != runner) {
|
|
|
|
|
m_launchRunner = runner;
|
|
|
|
|
Q_EMIT launchRunnerChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::launchRunnerPath() const
|
|
|
|
|
{
|
|
|
|
|
return m_launchRunnerPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setLaunchRunnerPath(const QString &path)
|
|
|
|
|
{
|
|
|
|
|
if (m_launchRunnerPath != path) {
|
|
|
|
|
m_launchRunnerPath = path;
|
|
|
|
|
Q_EMIT launchRunnerPathChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::launchPrefixPath() const
|
|
|
|
|
{
|
|
|
|
|
return m_launchPrefixPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setLaunchPrefixPath(const QString &path)
|
|
|
|
|
{
|
|
|
|
|
if (m_launchPrefixPath != path) {
|
|
|
|
|
m_launchPrefixPath = path;
|
|
|
|
|
Q_EMIT launchPrefixPathChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 12:13:07 +00:00
|
|
|
QString Game::platform() const
|
|
|
|
|
{
|
|
|
|
|
return m_platform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setPlatform(const QString &platform)
|
|
|
|
|
{
|
|
|
|
|
if (m_platform != platform) {
|
|
|
|
|
m_platform = platform;
|
|
|
|
|
Q_EMIT platformChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::platformId() const
|
|
|
|
|
{
|
|
|
|
|
return m_platformId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setPlatformId(const QString &id)
|
|
|
|
|
{
|
|
|
|
|
if (m_platformId != id) {
|
|
|
|
|
m_platformId = id;
|
|
|
|
|
Q_EMIT platformIdChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QDateTime Game::dateAdded() const
|
|
|
|
|
{
|
|
|
|
|
return m_dateAdded;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setDateAdded(const QDateTime &dateTime)
|
|
|
|
|
{
|
|
|
|
|
if (m_dateAdded != dateTime) {
|
|
|
|
|
m_dateAdded = dateTime;
|
|
|
|
|
Q_EMIT dateAddedChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QDateTime Game::lastPlayed() const
|
|
|
|
|
{
|
|
|
|
|
return m_lastPlayed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setLastPlayed(const QDateTime &dateTime)
|
|
|
|
|
{
|
|
|
|
|
if (m_lastPlayed != dateTime) {
|
|
|
|
|
m_lastPlayed = dateTime;
|
|
|
|
|
Q_EMIT lastPlayedChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qint64 Game::playTime() const
|
|
|
|
|
{
|
|
|
|
|
return m_playTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setPlayTime(qint64 seconds)
|
|
|
|
|
{
|
|
|
|
|
if (m_playTime != seconds) {
|
|
|
|
|
m_playTime = seconds;
|
|
|
|
|
Q_EMIT playTimeChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Game::favorite() const
|
|
|
|
|
{
|
|
|
|
|
return m_favorite;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setFavorite(bool favorite)
|
|
|
|
|
{
|
|
|
|
|
if (m_favorite != favorite) {
|
|
|
|
|
m_favorite = favorite;
|
|
|
|
|
Q_EMIT favoriteChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Game::hidden() const
|
|
|
|
|
{
|
|
|
|
|
return m_hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setHidden(bool hidden)
|
|
|
|
|
{
|
|
|
|
|
if (m_hidden != hidden) {
|
|
|
|
|
m_hidden = hidden;
|
|
|
|
|
Q_EMIT hiddenChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Game::installed() const
|
|
|
|
|
{
|
|
|
|
|
return m_installed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setInstalled(bool installed)
|
|
|
|
|
{
|
|
|
|
|
if (m_installed != installed) {
|
|
|
|
|
m_installed = installed;
|
|
|
|
|
Q_EMIT installedChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Game::running() const
|
|
|
|
|
{
|
|
|
|
|
return m_running;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Game::setRunning(bool running)
|
|
|
|
|
{
|
|
|
|
|
if (m_running != running) {
|
|
|
|
|
m_running = running;
|
|
|
|
|
Q_EMIT runningChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QJsonObject Game::toJson() const
|
|
|
|
|
{
|
|
|
|
|
QJsonObject obj;
|
|
|
|
|
obj[QStringLiteral("id")] = m_id;
|
|
|
|
|
obj[QStringLiteral("name")] = m_name;
|
|
|
|
|
obj[QStringLiteral("description")] = m_description;
|
|
|
|
|
obj[QStringLiteral("developer")] = m_developer;
|
|
|
|
|
obj[QStringLiteral("publisher")] = m_publisher;
|
|
|
|
|
obj[QStringLiteral("coverUrl")] = m_coverUrl.toString();
|
|
|
|
|
obj[QStringLiteral("iconUrl")] = m_iconUrl.toString();
|
|
|
|
|
obj[QStringLiteral("launchCommand")] = m_launchCommand;
|
|
|
|
|
obj[QStringLiteral("workingDirectory")] = m_workingDirectory;
|
|
|
|
|
obj[QStringLiteral("platform")] = m_platform;
|
|
|
|
|
obj[QStringLiteral("platformId")] = m_platformId;
|
|
|
|
|
obj[QStringLiteral("dateAdded")] = m_dateAdded.toString(Qt::ISODate);
|
|
|
|
|
obj[QStringLiteral("lastPlayed")] = m_lastPlayed.toString(Qt::ISODate);
|
|
|
|
|
obj[QStringLiteral("playTime")] = m_playTime;
|
|
|
|
|
obj[QStringLiteral("favorite")] = m_favorite;
|
|
|
|
|
obj[QStringLiteral("hidden")] = m_hidden;
|
|
|
|
|
obj[QStringLiteral("installed")] = m_installed;
|
2026-01-25 13:19:57 +00:00
|
|
|
|
|
|
|
|
const bool hasLaunchConfig = !m_launchEnv.isEmpty() || !m_launchRunner.isEmpty() || !m_launchRunnerPath.isEmpty() || !m_launchPrefixPath.isEmpty();
|
|
|
|
|
if (hasLaunchConfig) {
|
|
|
|
|
QJsonObject launchObj;
|
|
|
|
|
|
|
|
|
|
if (!m_launchEnv.isEmpty()) {
|
|
|
|
|
QJsonObject envObj;
|
|
|
|
|
for (auto it = m_launchEnv.constBegin(); it != m_launchEnv.constEnd(); ++it) {
|
|
|
|
|
envObj.insert(it.key(), QJsonValue::fromVariant(it.value()));
|
|
|
|
|
}
|
|
|
|
|
launchObj.insert(QStringLiteral("env"), envObj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!m_launchRunner.isEmpty()) {
|
|
|
|
|
launchObj.insert(QStringLiteral("runner"), m_launchRunner);
|
|
|
|
|
}
|
|
|
|
|
if (!m_launchRunnerPath.isEmpty()) {
|
|
|
|
|
launchObj.insert(QStringLiteral("runnerPath"), m_launchRunnerPath);
|
|
|
|
|
}
|
|
|
|
|
if (!m_launchPrefixPath.isEmpty()) {
|
|
|
|
|
launchObj.insert(QStringLiteral("prefixPath"), m_launchPrefixPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj.insert(QStringLiteral("launch"), launchObj);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 12:13:07 +00:00
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Game *Game::fromJson(const QJsonObject &json, QObject *parent)
|
|
|
|
|
{
|
|
|
|
|
QString id = json[QStringLiteral("id")].toString();
|
|
|
|
|
QString name = json[QStringLiteral("name")].toString();
|
|
|
|
|
|
2026-01-25 13:19:57 +00:00
|
|
|
if (name.isEmpty()) {
|
2026-01-18 12:13:07 +00:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 13:19:57 +00:00
|
|
|
const QString platformId = json[QStringLiteral("platformId")].toString();
|
|
|
|
|
const QString platform = json[QStringLiteral("platform")].toString();
|
|
|
|
|
const QString launchCommand = json[QStringLiteral("launchCommand")].toString();
|
|
|
|
|
const QString workingDirectory = json[QStringLiteral("workingDirectory")].toString();
|
|
|
|
|
if (id.isEmpty()) {
|
|
|
|
|
const QByteArray fingerprint =
|
|
|
|
|
(platformId + QLatin1Char('|') + platform + QLatin1Char('|') + name + QLatin1Char('|') + launchCommand + QLatin1Char('|') + workingDirectory)
|
|
|
|
|
.toUtf8();
|
|
|
|
|
const QByteArray hash = QCryptographicHash::hash(fingerprint, QCryptographicHash::Sha1).toHex();
|
|
|
|
|
id = QStringLiteral("legacy-") + QString::fromLatin1(hash);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 12:13:07 +00:00
|
|
|
Game *game = new Game(id, name, parent);
|
|
|
|
|
game->setDescription(json[QStringLiteral("description")].toString());
|
|
|
|
|
game->setDeveloper(json[QStringLiteral("developer")].toString());
|
|
|
|
|
game->setPublisher(json[QStringLiteral("publisher")].toString());
|
|
|
|
|
game->setCoverUrl(QUrl(json[QStringLiteral("coverUrl")].toString()));
|
|
|
|
|
game->setIconUrl(QUrl(json[QStringLiteral("iconUrl")].toString()));
|
2026-01-25 13:19:57 +00:00
|
|
|
game->setLaunchCommand(launchCommand);
|
|
|
|
|
game->setWorkingDirectory(workingDirectory);
|
|
|
|
|
game->setPlatform(platform);
|
|
|
|
|
game->setPlatformId(platformId);
|
2026-01-18 12:13:07 +00:00
|
|
|
game->setDateAdded(QDateTime::fromString(json[QStringLiteral("dateAdded")].toString(), Qt::ISODate));
|
|
|
|
|
game->setLastPlayed(QDateTime::fromString(json[QStringLiteral("lastPlayed")].toString(), Qt::ISODate));
|
|
|
|
|
game->setPlayTime(json[QStringLiteral("playTime")].toInteger());
|
|
|
|
|
game->setFavorite(json[QStringLiteral("favorite")].toBool());
|
|
|
|
|
game->setHidden(json[QStringLiteral("hidden")].toBool());
|
|
|
|
|
game->setInstalled(json[QStringLiteral("installed")].toBool(true));
|
2026-01-25 13:19:57 +00:00
|
|
|
|
|
|
|
|
QVariantMap env;
|
|
|
|
|
QString runner;
|
|
|
|
|
QString runnerPath;
|
|
|
|
|
QString prefixPath;
|
|
|
|
|
const QJsonValue launchValue = json.value(QStringLiteral("launch"));
|
|
|
|
|
if (launchValue.isObject()) {
|
|
|
|
|
const QJsonObject launchObj = launchValue.toObject();
|
|
|
|
|
const QJsonValue envValue = launchObj.value(QStringLiteral("env"));
|
|
|
|
|
if (envValue.isObject()) {
|
|
|
|
|
env = envValue.toObject().toVariantMap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
runner = launchObj.value(QStringLiteral("runner")).toString();
|
|
|
|
|
runnerPath = launchObj.value(QStringLiteral("runnerPath")).toString();
|
|
|
|
|
prefixPath = launchObj.value(QStringLiteral("prefixPath")).toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QJsonValue legacyEnvValue = json.value(QStringLiteral("launchEnv"));
|
|
|
|
|
if (env.isEmpty() && legacyEnvValue.isObject()) {
|
|
|
|
|
env = legacyEnvValue.toObject().toVariantMap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (runner.isEmpty()) {
|
|
|
|
|
runner = json.value(QStringLiteral("launchRunner")).toString();
|
|
|
|
|
}
|
|
|
|
|
if (runnerPath.isEmpty()) {
|
|
|
|
|
runnerPath = json.value(QStringLiteral("launchRunnerPath")).toString();
|
|
|
|
|
}
|
|
|
|
|
if (prefixPath.isEmpty()) {
|
|
|
|
|
prefixPath = json.value(QStringLiteral("launchPrefixPath")).toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!env.isEmpty()) {
|
|
|
|
|
game->setLaunchEnv(env);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!runner.isEmpty()) {
|
|
|
|
|
game->setLaunchRunner(runner);
|
|
|
|
|
}
|
|
|
|
|
if (!runnerPath.isEmpty()) {
|
|
|
|
|
game->setLaunchRunnerPath(runnerPath);
|
|
|
|
|
}
|
|
|
|
|
if (!prefixPath.isEmpty()) {
|
|
|
|
|
game->setLaunchPrefixPath(prefixPath);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 12:13:07 +00:00
|
|
|
return game;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::playTimeFormatted() const
|
|
|
|
|
{
|
|
|
|
|
if (m_playTime == 0) {
|
|
|
|
|
return i18n("Never played");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qint64 hours = m_playTime / 3600;
|
|
|
|
|
qint64 minutes = (m_playTime % 3600) / 60;
|
|
|
|
|
|
|
|
|
|
if (hours > 0) {
|
|
|
|
|
return i18np("%1 hour", "%1 hours", hours) + QStringLiteral(" ") + i18np("%1 minute", "%1 minutes", minutes);
|
|
|
|
|
}
|
|
|
|
|
return i18np("%1 minute", "%1 minutes", minutes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::lastPlayedFormatted() const
|
|
|
|
|
{
|
|
|
|
|
if (!m_lastPlayed.isValid()) {
|
|
|
|
|
return i18n("Never");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QDateTime now = QDateTime::currentDateTime();
|
|
|
|
|
qint64 days = m_lastPlayed.daysTo(now);
|
|
|
|
|
|
|
|
|
|
if (days == 0) {
|
|
|
|
|
return i18n("Today");
|
|
|
|
|
} else if (days == 1) {
|
|
|
|
|
return i18n("Yesterday");
|
|
|
|
|
} else if (days < 7) {
|
|
|
|
|
return i18np("%1 day ago", "%1 days ago", days);
|
|
|
|
|
} else if (days < 30) {
|
|
|
|
|
return i18np("%1 week ago", "%1 weeks ago", days / 7);
|
|
|
|
|
} else if (days < 365) {
|
|
|
|
|
return i18np("%1 month ago", "%1 months ago", days / 30);
|
|
|
|
|
}
|
|
|
|
|
return QLocale().toString(m_lastPlayed, QLocale::ShortFormat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Game::dateAddedFormatted() const
|
|
|
|
|
{
|
|
|
|
|
if (!m_dateAdded.isValid()) {
|
|
|
|
|
return i18n("Unknown");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QDateTime now = QDateTime::currentDateTime();
|
|
|
|
|
qint64 days = m_dateAdded.daysTo(now);
|
|
|
|
|
|
|
|
|
|
if (days == 0) {
|
|
|
|
|
return i18n("Today");
|
|
|
|
|
} else if (days == 1) {
|
|
|
|
|
return i18n("Yesterday");
|
|
|
|
|
} else if (days < 7) {
|
|
|
|
|
return i18np("%1 day ago", "%1 days ago", days);
|
|
|
|
|
} else if (days < 30) {
|
|
|
|
|
return i18np("%1 week ago", "%1 weeks ago", days / 7);
|
|
|
|
|
} else if (days < 365) {
|
|
|
|
|
return i18np("%1 month ago", "%1 months ago", days / 30);
|
|
|
|
|
}
|
|
|
|
|
return QLocale().toString(m_dateAdded, QLocale::ShortFormat);
|
|
|
|
|
}
|