mirror of
https://github.com/jellyfin/jellyfin-desktop.git
synced 2026-10-26 16:45:24 +00:00
Refactor ProfileManager to encapsulate profile IDs
- Make Profile::id private, expose only through ProfileManager - Add std::optional<Profile> returns for profileByName/defaultProfile - Add profiles(), createProfile(), deleteProfile(), setDefaultProfile() - Update setActiveProfile() to take Profile instead of id string - Move profile operations from main.cpp lambdas into ProfileManager - Remove profile-aware methods from Paths (dataDir, cacheDir, logDir) - All callers now use ProfileManager::activeProfile().dataDir() etc.
This commit is contained in:
1 parent
c563de40ac
commit
c8cd28e6ca
12 files changed
+264
-636
No files matched your search
@@ -16,7 +16,6 @@
|
||||
#ifdef LINUX_DBUS
|
||||
#include "mpris/MprisComponent.h"
|
||||
#endif
|
||||
#include "ProfileManager.h"
|
||||
|
||||
#ifdef KONVERGO_OPENELEC
|
||||
#include "system/openelec/OESystemComponent.h"
|
||||
@@ -53,9 +52,6 @@ void ComponentManager::registerComponent(ComponentBase* comp)
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ComponentManager::initialize()
|
||||
{
|
||||
// ProfileManager first - it sets up profile-aware paths before other components
|
||||
registerComponent(&ProfileManager::Get());
|
||||
|
||||
// then settings, since all other components
|
||||
// might have some settings
|
||||
//
|
||||
|
||||
+158
-324
@@ -1,360 +1,194 @@
|
||||
#include "ProfileManager.h"
|
||||
#include "Paths.h"
|
||||
#include "Names.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QUuid>
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
|
||||
static const QString PROFILES_FILE = "profiles.json";
|
||||
static const QString PROFILES_DIR = "profiles";
|
||||
|
||||
QVariantMap Profile::toVariantMap() const
|
||||
QString Profile::dataDir(const QString& subpath) const
|
||||
{
|
||||
QVariantMap map;
|
||||
map["id"] = id;
|
||||
map["name"] = name;
|
||||
map["url"] = url;
|
||||
map["created"] = created.toString(Qt::ISODate);
|
||||
return map;
|
||||
QString path = Paths::globalDataDir(PROFILES_DIR + "/" + id);
|
||||
if (!subpath.isEmpty())
|
||||
path += "/" + subpath;
|
||||
return path;
|
||||
}
|
||||
|
||||
Profile Profile::fromVariantMap(const QVariantMap& map)
|
||||
QString Profile::cacheDir(const QString& subpath) const
|
||||
{
|
||||
Profile p;
|
||||
p.id = map["id"].toString();
|
||||
p.name = map["name"].toString();
|
||||
p.url = map["url"].toString();
|
||||
p.created = QDateTime::fromString(map["created"].toString(), Qt::ISODate);
|
||||
return p;
|
||||
QString path = Paths::globalCacheDir(PROFILES_DIR + "/" + id);
|
||||
if (!subpath.isEmpty())
|
||||
path += "/" + subpath;
|
||||
return path;
|
||||
}
|
||||
|
||||
QString Profile::logDir() const
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
// macOS: ~/Library/Logs/<AppName>/profiles/<id>/
|
||||
QString home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
|
||||
return home + "/Library/Logs/" + Names::DataName() + "/profiles/" + id;
|
||||
#else
|
||||
// Other platforms: profiles/<id>/logs/
|
||||
return dataDir("logs");
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Profile::name() const
|
||||
{
|
||||
QFile meta(dataDir("profile.json"));
|
||||
if (meta.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(meta.readAll());
|
||||
meta.close();
|
||||
return doc.object()["name"].toString();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void Profile::ensureDirectories() const
|
||||
{
|
||||
QDir().mkpath(dataDir());
|
||||
QDir().mkpath(logDir());
|
||||
QDir().mkpath(cacheDir());
|
||||
}
|
||||
|
||||
ProfileManager::ProfileManager(QObject* parent)
|
||||
: ComponentBase(parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool ProfileManager::componentInitialize()
|
||||
void ProfileManager::setActiveProfile(const Profile& profile)
|
||||
{
|
||||
loadProfiles();
|
||||
ensureActiveProfile();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProfileManager::ensureActiveProfile()
|
||||
{
|
||||
// CLI --profile flag takes precedence (already set in Paths before ComponentManager)
|
||||
QString cliProfileId = Paths::activeProfileId();
|
||||
if (!cliProfileId.isEmpty())
|
||||
{
|
||||
m_activeProfileId = cliProfileId;
|
||||
// Ensure profile is in our list
|
||||
if (!m_profiles.contains(cliProfileId))
|
||||
{
|
||||
scanProfilesDirectory();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Already have valid active profile from profiles.json
|
||||
if (!m_activeProfileId.isEmpty() && m_profiles.contains(m_activeProfileId))
|
||||
{
|
||||
Paths::setActiveProfileId(m_activeProfileId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find first existing profile from profiles directory
|
||||
if (m_profiles.isEmpty())
|
||||
{
|
||||
scanProfilesDirectory();
|
||||
}
|
||||
|
||||
// Use first available profile
|
||||
if (!m_profiles.isEmpty())
|
||||
{
|
||||
QString firstId = m_profiles.keys().first();
|
||||
qInfo() << "Activating first available profile:" << firstId;
|
||||
m_activeProfileId = firstId;
|
||||
Paths::setActiveProfileId(firstId);
|
||||
saveProfiles();
|
||||
return;
|
||||
}
|
||||
|
||||
// No profiles exist - create one
|
||||
qInfo() << "No profiles found, creating new profile";
|
||||
QString id = generateProfileId();
|
||||
|
||||
Profile p;
|
||||
p.id = id;
|
||||
p.name = "Default";
|
||||
p.url = "";
|
||||
p.created = QDateTime::currentDateTime();
|
||||
|
||||
ensureProfileDirectories(id);
|
||||
m_profiles[id] = p;
|
||||
m_activeProfileId = id;
|
||||
Paths::setActiveProfileId(id);
|
||||
saveProfiles();
|
||||
}
|
||||
|
||||
void ProfileManager::scanProfilesDirectory()
|
||||
{
|
||||
QString profilesPath = Paths::globalDataDir(PROFILES_DIR);
|
||||
QDir profilesDir(profilesPath);
|
||||
|
||||
if (!profilesDir.exists())
|
||||
if (m_activeProfile.id == profile.id)
|
||||
return;
|
||||
|
||||
for (const QString& dirName : profilesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
|
||||
{
|
||||
// Check if it looks like a UUID
|
||||
if (dirName.length() == 32 && dirName.contains(QRegularExpression("^[0-9a-f]+$")))
|
||||
{
|
||||
Profile p;
|
||||
p.id = dirName;
|
||||
p.name = "Recovered Profile";
|
||||
p.url = "";
|
||||
p.created = QDateTime::currentDateTime();
|
||||
m_profiles[dirName] = p;
|
||||
qInfo() << "Found orphan profile directory:" << dirName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileManager::loadProfiles()
|
||||
{
|
||||
QString filePath = Paths::globalDataDir(PROFILES_FILE);
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
qInfo() << "No profiles.json found, starting fresh";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qWarning() << "Failed to open profiles.json for reading";
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||
file.close();
|
||||
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
qWarning() << "Failed to parse profiles.json:" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject root = doc.object();
|
||||
|
||||
// Load default profile ID
|
||||
m_activeProfileId = root["defaultProfile"].toString();
|
||||
|
||||
// Load profiles array
|
||||
QJsonArray profilesArray = root["profiles"].toArray();
|
||||
for (const QJsonValue& val : profilesArray)
|
||||
{
|
||||
QJsonObject obj = val.toObject();
|
||||
Profile p;
|
||||
p.id = obj["id"].toString();
|
||||
p.name = obj["name"].toString();
|
||||
p.url = obj["url"].toString();
|
||||
p.created = QDateTime::fromString(obj["created"].toString(), Qt::ISODate);
|
||||
|
||||
if (!p.id.isEmpty())
|
||||
{
|
||||
m_profiles[p.id] = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate active profile exists
|
||||
if (!m_activeProfileId.isEmpty() && !m_profiles.contains(m_activeProfileId))
|
||||
{
|
||||
qWarning() << "Active profile" << m_activeProfileId << "not found in profiles list";
|
||||
m_activeProfileId.clear();
|
||||
}
|
||||
|
||||
qInfo() << "Loaded" << m_profiles.size() << "profiles from profiles.json";
|
||||
}
|
||||
|
||||
void ProfileManager::saveProfiles()
|
||||
{
|
||||
QJsonObject root;
|
||||
root["defaultProfile"] = m_activeProfileId;
|
||||
|
||||
QJsonDocument doc(root);
|
||||
QByteArray data = doc.toJson(QJsonDocument::Indented);
|
||||
|
||||
QString filePath = Paths::globalDataDir(PROFILES_FILE);
|
||||
if (!Utils::safelyWriteFile(filePath, data))
|
||||
{
|
||||
qCritical() << "Failed to save profiles.json";
|
||||
}
|
||||
}
|
||||
|
||||
QString ProfileManager::generateProfileId()
|
||||
{
|
||||
return QUuid::createUuid().toString(QUuid::Id128);
|
||||
}
|
||||
|
||||
void ProfileManager::ensureProfileDirectories(const QString& id)
|
||||
{
|
||||
// Data directory (use global since profile may not be active yet)
|
||||
QString dataPath = Paths::globalDataDir(PROFILES_DIR + "/" + id);
|
||||
QDir dataDir(dataPath);
|
||||
if (!dataDir.exists())
|
||||
{
|
||||
dataDir.mkpath(dataPath);
|
||||
}
|
||||
|
||||
// Logs subdirectory
|
||||
QString logsPath = dataPath + "/logs";
|
||||
QDir logsDir(logsPath);
|
||||
if (!logsDir.exists())
|
||||
{
|
||||
logsDir.mkpath(logsPath);
|
||||
}
|
||||
|
||||
// Cache directory (use global since profile may not be active yet)
|
||||
QString cachePath = Paths::globalCacheDir(PROFILES_DIR + "/" + id);
|
||||
QDir cacheDir(cachePath);
|
||||
if (!cacheDir.exists())
|
||||
{
|
||||
cacheDir.mkpath(cachePath);
|
||||
}
|
||||
}
|
||||
|
||||
QString ProfileManager::createProfile(const QString& name, const QString& url)
|
||||
{
|
||||
QString id = generateProfileId();
|
||||
|
||||
Profile p;
|
||||
p.id = id;
|
||||
p.name = name;
|
||||
p.url = url;
|
||||
p.created = QDateTime::currentDateTime();
|
||||
|
||||
ensureProfileDirectories(id);
|
||||
|
||||
m_profiles[id] = p;
|
||||
saveProfiles();
|
||||
|
||||
emit profilesChanged();
|
||||
|
||||
qInfo() << "Created profile" << id << ":" << name << "for" << url;
|
||||
return id;
|
||||
}
|
||||
|
||||
bool ProfileManager::deleteProfile(const QString& id)
|
||||
{
|
||||
if (!m_profiles.contains(id))
|
||||
{
|
||||
qWarning() << "Cannot delete profile" << id << "- not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear active if deleting current
|
||||
if (m_activeProfileId == id)
|
||||
{
|
||||
m_activeProfileId.clear();
|
||||
emit activeProfileChanged();
|
||||
}
|
||||
|
||||
m_profiles.remove(id);
|
||||
saveProfiles();
|
||||
|
||||
// Optionally delete profile directories (leave for now, user can clean manually)
|
||||
// This avoids accidental data loss
|
||||
|
||||
emit profilesChanged();
|
||||
|
||||
qInfo() << "Deleted profile" << id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProfileManager::renameProfile(const QString& id, const QString& newName)
|
||||
{
|
||||
if (!m_profiles.contains(id))
|
||||
{
|
||||
qWarning() << "Cannot rename profile" << id << "- not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_profiles[id].name = newName;
|
||||
saveProfiles();
|
||||
|
||||
emit profilesChanged();
|
||||
|
||||
qInfo() << "Renamed profile" << id << "to" << newName;
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantList ProfileManager::listProfiles()
|
||||
{
|
||||
QVariantList list;
|
||||
for (const Profile& p : m_profiles)
|
||||
{
|
||||
list.append(p.toVariantMap());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
QVariantMap ProfileManager::getProfile(const QString& id)
|
||||
{
|
||||
if (m_profiles.contains(id))
|
||||
{
|
||||
return m_profiles[id].toVariantMap();
|
||||
}
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
bool ProfileManager::setActiveProfile(const QString& id)
|
||||
{
|
||||
if (id.isEmpty())
|
||||
{
|
||||
m_activeProfileId.clear();
|
||||
Paths::setActiveProfileId(QString());
|
||||
saveProfiles();
|
||||
emit activeProfileChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_profiles.contains(id))
|
||||
{
|
||||
qWarning() << "Cannot activate profile" << id << "- not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_activeProfileId = id;
|
||||
Paths::setActiveProfileId(id);
|
||||
ensureProfileDirectories(id);
|
||||
saveProfiles();
|
||||
m_activeProfile = profile;
|
||||
m_activeProfile.ensureDirectories();
|
||||
|
||||
qInfo() << "Activated profile:" << profile.name();
|
||||
emit activeProfileChanged();
|
||||
}
|
||||
|
||||
Profile ProfileManager::profileById(const QString& id)
|
||||
{
|
||||
Profile p;
|
||||
p.id = id;
|
||||
return p;
|
||||
}
|
||||
|
||||
std::optional<Profile> ProfileManager::profileByName(const QString& name)
|
||||
{
|
||||
QDir dir(profilesDir());
|
||||
if (!dir.exists())
|
||||
return std::nullopt;
|
||||
|
||||
for (const QString& id : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
|
||||
{
|
||||
if (id.length() != 32 || !id.contains(QRegularExpression("^[0-9a-f]+$")))
|
||||
continue;
|
||||
|
||||
Profile p = profileById(id);
|
||||
if (p.name() == name)
|
||||
return p;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QList<Profile> ProfileManager::profiles()
|
||||
{
|
||||
QList<Profile> result;
|
||||
QDir dir(profilesDir());
|
||||
if (!dir.exists())
|
||||
return result;
|
||||
|
||||
for (const QString& id : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
|
||||
{
|
||||
if (id.length() != 32 || !id.contains(QRegularExpression("^[0-9a-f]+$")))
|
||||
continue;
|
||||
|
||||
result.append(profileById(id));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Profile ProfileManager::createProfile(const QString& name)
|
||||
{
|
||||
QString id = QUuid::createUuid().toString(QUuid::Id128);
|
||||
Profile profile = profileById(id);
|
||||
profile.ensureDirectories();
|
||||
|
||||
// Write profile.json with name
|
||||
QFile meta(profile.dataDir("profile.json"));
|
||||
if (meta.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj["name"] = name;
|
||||
meta.write(QJsonDocument(obj).toJson());
|
||||
meta.close();
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
bool ProfileManager::deleteProfile(const Profile& profile)
|
||||
{
|
||||
QDir dir(profile.dataDir());
|
||||
if (!dir.removeRecursively())
|
||||
return false;
|
||||
|
||||
// Update default if we deleted it
|
||||
auto current = defaultProfile();
|
||||
if (current && current->id == profile.id)
|
||||
{
|
||||
auto remaining = profiles();
|
||||
if (!remaining.isEmpty())
|
||||
setDefaultProfile(remaining.first());
|
||||
}
|
||||
|
||||
qInfo() << "Activated profile" << id << ":" << m_profiles[id].name;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ProfileManager::profileDataDir() const
|
||||
std::optional<Profile> ProfileManager::defaultProfile()
|
||||
{
|
||||
if (m_activeProfileId.isEmpty())
|
||||
return QString();
|
||||
|
||||
return Paths::dataDir();
|
||||
QString profilesFile = Paths::globalDataDir("profiles.json");
|
||||
QFile file(profilesFile);
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
|
||||
file.close();
|
||||
QString id = doc.object()["defaultProfile"].toString();
|
||||
if (!id.isEmpty())
|
||||
{
|
||||
Profile p = profileById(id);
|
||||
if (QDir(p.dataDir()).exists())
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QString ProfileManager::profileCacheDir() const
|
||||
void ProfileManager::setDefaultProfile(const Profile& profile)
|
||||
{
|
||||
if (m_activeProfileId.isEmpty())
|
||||
return QString();
|
||||
|
||||
return Paths::cacheDir();
|
||||
QString profilesFile = Paths::globalDataDir("profiles.json");
|
||||
QJsonObject root;
|
||||
root["defaultProfile"] = profile.id;
|
||||
QFile out(profilesFile);
|
||||
if (out.open(QIODevice::WriteOnly))
|
||||
{
|
||||
out.write(QJsonDocument(root).toJson());
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
QString ProfileManager::profilesDir()
|
||||
{
|
||||
return Paths::globalDataDir(PROFILES_DIR);
|
||||
}
|
||||
+34
-39
@@ -2,70 +2,65 @@
|
||||
#define PROFILEMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantList>
|
||||
#include <QVariantMap>
|
||||
#include <QDateTime>
|
||||
#include "ComponentManager.h"
|
||||
#include <QList>
|
||||
#include <optional>
|
||||
#include "utils/Utils.h"
|
||||
|
||||
class ProfileManager;
|
||||
|
||||
struct Profile
|
||||
{
|
||||
QString id;
|
||||
QString name;
|
||||
QString url;
|
||||
QDateTime created;
|
||||
// Paths
|
||||
QString dataDir(const QString& subpath = QString()) const;
|
||||
QString cacheDir(const QString& subpath = QString()) const;
|
||||
QString logDir() const;
|
||||
|
||||
QVariantMap toVariantMap() const;
|
||||
static Profile fromVariantMap(const QVariantMap& map);
|
||||
// Metadata
|
||||
QString name() const;
|
||||
|
||||
// Directory management
|
||||
void ensureDirectories() const;
|
||||
|
||||
private:
|
||||
QString id;
|
||||
friend class ProfileManager;
|
||||
};
|
||||
|
||||
class ProfileManager : public ComponentBase
|
||||
class ProfileManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
DEFINE_SINGLETON(ProfileManager);
|
||||
|
||||
Q_PROPERTY(QString activeProfileId READ activeProfileId NOTIFY activeProfileChanged)
|
||||
Q_PROPERTY(QString profileDataDir READ profileDataDir NOTIFY activeProfileChanged)
|
||||
Q_PROPERTY(QString profileCacheDir READ profileCacheDir NOTIFY activeProfileChanged)
|
||||
Q_PROPERTY(bool hasActiveProfile READ hasActiveProfile NOTIFY activeProfileChanged)
|
||||
|
||||
public:
|
||||
bool componentExport() override { return true; }
|
||||
const char* componentName() override { return "profiles"; }
|
||||
bool componentInitialize() override;
|
||||
// Active profile
|
||||
static Profile& activeProfile() { return Get().m_activeProfile; }
|
||||
void setActiveProfile(const Profile& profile);
|
||||
bool hasActiveProfile() const { return !m_activeProfile.id.isEmpty(); }
|
||||
|
||||
// Profile lookup
|
||||
static std::optional<Profile> profileByName(const QString& name);
|
||||
static QList<Profile> profiles();
|
||||
|
||||
// Profile management
|
||||
Q_INVOKABLE QString createProfile(const QString& name, const QString& url);
|
||||
Q_INVOKABLE bool deleteProfile(const QString& id);
|
||||
Q_INVOKABLE bool renameProfile(const QString& id, const QString& newName);
|
||||
Q_INVOKABLE QVariantList listProfiles();
|
||||
Q_INVOKABLE QVariantMap getProfile(const QString& id);
|
||||
static Profile createProfile(const QString& name);
|
||||
static bool deleteProfile(const Profile& profile);
|
||||
|
||||
// Active profile
|
||||
Q_INVOKABLE bool setActiveProfile(const QString& id);
|
||||
QString activeProfileId() const { return m_activeProfileId; }
|
||||
bool hasActiveProfile() const { return !m_activeProfileId.isEmpty(); }
|
||||
|
||||
// Path accessors for QML
|
||||
QString profileDataDir() const;
|
||||
QString profileCacheDir() const;
|
||||
// Default profile
|
||||
static std::optional<Profile> defaultProfile();
|
||||
static void setDefaultProfile(const Profile& profile);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activeProfileChanged();
|
||||
void profilesChanged();
|
||||
|
||||
private:
|
||||
explicit ProfileManager(QObject* parent = nullptr);
|
||||
|
||||
void loadProfiles();
|
||||
void saveProfiles();
|
||||
void ensureActiveProfile();
|
||||
void scanProfilesDirectory();
|
||||
QString generateProfileId();
|
||||
void ensureProfileDirectories(const QString& id);
|
||||
static Profile profileById(const QString& id);
|
||||
static QString profilesDir();
|
||||
|
||||
QMap<QString, Profile> m_profiles;
|
||||
QString m_activeProfileId;
|
||||
Profile m_activeProfile;
|
||||
};
|
||||
|
||||
#endif // PROFILEMANAGER_H
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "Paths.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "utils/Utils.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -34,7 +35,7 @@ bool InputMapping::loadMappings()
|
||||
|
||||
// don't watch the path while we potentially copy files to the directory
|
||||
if (m_watcher->directories().size() > 0)
|
||||
m_watcher->removePath(Paths::dataDir("inputmaps"));
|
||||
m_watcher->removePath(ProfileManager::activeProfile().dataDir("inputmaps"));
|
||||
|
||||
// first we load the bundled mappings
|
||||
loadMappingDirectory(":/inputmaps", true);
|
||||
@@ -42,10 +43,10 @@ bool InputMapping::loadMappings()
|
||||
// now we load the user ones, if there are any
|
||||
// they will now overload the built-in ones.
|
||||
//
|
||||
loadMappingDirectory(Paths::dataDir("inputmaps"), false);
|
||||
loadMappingDirectory(ProfileManager::activeProfile().dataDir("inputmaps"), false);
|
||||
|
||||
// we want to watch this dir for new files and changed files
|
||||
m_watcher->addPath(Paths::dataDir("inputmaps"));
|
||||
m_watcher->addPath(ProfileManager::activeProfile().dataDir("inputmaps"));
|
||||
|
||||
emit mappingChanged();
|
||||
return true;
|
||||
@@ -120,7 +121,7 @@ bool InputMapping::loadMappingDirectory(const QString& path, bool copy)
|
||||
// make a copy of the original file to the example directory
|
||||
if (copy)
|
||||
{
|
||||
QDir userdir(Paths::dataDir());
|
||||
QDir userdir(ProfileManager::activeProfile().dataDir());
|
||||
userdir.mkpath("inputmaps/examples/");
|
||||
QString examplePath(userdir.filePath("inputmaps/examples/" + finfo.fileName()));
|
||||
|
||||
|
||||
+35
-149
@@ -3,11 +3,8 @@
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
#include <QIcon>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QUuid>
|
||||
#include <QtQml>
|
||||
#include <optional>
|
||||
#include <Qt>
|
||||
#include <QtWebEngineQuick>
|
||||
#include <qtwebenginecoreglobal.h>
|
||||
@@ -16,13 +13,13 @@
|
||||
#include <QtWebEngineCore/QWebEngineScript>
|
||||
#include <QCommandLineOption>
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
|
||||
#include "shared/Names.h"
|
||||
#include "system/SystemComponent.h"
|
||||
#include <QDebug>
|
||||
#include "Paths.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "player/CodecsComponent.h"
|
||||
#include "player/PlayerComponent.h"
|
||||
#include "player/OpenGLDetect.h"
|
||||
@@ -278,106 +275,21 @@ int main(int argc, char *argv[])
|
||||
QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, absPath);
|
||||
}
|
||||
|
||||
// Helper lambdas for profile operations
|
||||
auto profileExists = [](const QString& id) {
|
||||
return QDir(Paths::globalDataDir("profiles/" + id)).exists();
|
||||
};
|
||||
|
||||
auto getProfilesList = []() {
|
||||
QStringList profiles;
|
||||
QDir profilesDir(Paths::globalDataDir("profiles"));
|
||||
if (profilesDir.exists())
|
||||
{
|
||||
for (const QString& dir : profilesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
|
||||
{
|
||||
if (dir.length() == 32 && dir.contains(QRegularExpression("^[0-9a-f]+$")))
|
||||
profiles << dir;
|
||||
}
|
||||
}
|
||||
return profiles;
|
||||
};
|
||||
|
||||
auto getProfileName = [](const QString& id) {
|
||||
QFile meta(Paths::globalDataDir("profiles/" + id + "/profile.json"));
|
||||
if (meta.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(meta.readAll());
|
||||
meta.close();
|
||||
return doc.object()["name"].toString();
|
||||
}
|
||||
return QString();
|
||||
};
|
||||
|
||||
auto findProfileByName = [&getProfilesList, &getProfileName](const QString& name) {
|
||||
for (const QString& id : getProfilesList())
|
||||
{
|
||||
if (getProfileName(id) == name)
|
||||
return id;
|
||||
}
|
||||
return QString();
|
||||
};
|
||||
|
||||
auto readDefaultProfile = []() {
|
||||
QString profilesFile = Paths::globalDataDir("profiles.json");
|
||||
QFile file(profilesFile);
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
|
||||
file.close();
|
||||
return doc.object()["defaultProfile"].toString();
|
||||
}
|
||||
return QString();
|
||||
};
|
||||
|
||||
auto writeDefaultProfile = [](const QString& id) {
|
||||
QString profilesFile = Paths::globalDataDir("profiles.json");
|
||||
QJsonObject root;
|
||||
root["defaultProfile"] = id;
|
||||
QFile out(profilesFile);
|
||||
if (out.open(QIODevice::WriteOnly))
|
||||
{
|
||||
out.write(QJsonDocument(root).toJson());
|
||||
out.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto createNewProfile = [](const QString& name) {
|
||||
QString id = QUuid::createUuid().toString(QUuid::Id128);
|
||||
QDir().mkpath(Paths::globalDataDir("profiles/" + id));
|
||||
QDir().mkpath(Paths::globalDataDir("profiles/" + id + "/logs"));
|
||||
// Always write profile.json with name
|
||||
QFile meta(Paths::globalDataDir("profiles/" + id + "/profile.json"));
|
||||
if (meta.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj["name"] = name;
|
||||
meta.write(QJsonDocument(obj).toJson());
|
||||
meta.close();
|
||||
}
|
||||
return id;
|
||||
};
|
||||
|
||||
// Handle --list-profiles
|
||||
if (parser.isSet("list-profiles"))
|
||||
{
|
||||
QStringList profiles = getProfilesList();
|
||||
QString defaultId = readDefaultProfile();
|
||||
if (profiles.isEmpty())
|
||||
auto allProfiles = ProfileManager::profiles();
|
||||
auto defaultProf = ProfileManager::defaultProfile();
|
||||
if (allProfiles.isEmpty())
|
||||
{
|
||||
printf("No profiles found.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const QString& id : profiles)
|
||||
for (const Profile& p : allProfiles)
|
||||
{
|
||||
QString marker = (id == defaultId) ? " *" : "";
|
||||
QString name = getProfileName(id);
|
||||
if (name.isEmpty())
|
||||
printf("%s%s\n", qPrintable(id), qPrintable(marker));
|
||||
else
|
||||
printf("%s%s\n", qPrintable(name), qPrintable(marker));
|
||||
QString marker = (defaultProf && p.name() == defaultProf->name()) ? " *" : "";
|
||||
printf("%s%s\n", qPrintable(p.name()), qPrintable(marker));
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
@@ -392,12 +304,12 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr, "Profile name is required\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!findProfileByName(name).isEmpty())
|
||||
if (ProfileManager::profileByName(name))
|
||||
{
|
||||
fprintf(stderr, "Profile already exists: %s\n", qPrintable(name));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
createNewProfile(name);
|
||||
ProfileManager::createProfile(name);
|
||||
printf("Created profile: %s\n", qPrintable(name));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -406,25 +318,17 @@ int main(int argc, char *argv[])
|
||||
if (parser.isSet("delete-profile"))
|
||||
{
|
||||
QString name = parser.value("delete-profile");
|
||||
QString id = findProfileByName(name);
|
||||
if (id.isEmpty())
|
||||
auto profile = ProfileManager::profileByName(name);
|
||||
if (!profile)
|
||||
{
|
||||
fprintf(stderr, "Profile not found: %s\n", qPrintable(name));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
QString profilePath = Paths::globalDataDir("profiles/" + id);
|
||||
QDir dir(profilePath);
|
||||
if (!dir.removeRecursively())
|
||||
if (!ProfileManager::deleteProfile(*profile))
|
||||
{
|
||||
fprintf(stderr, "Failed to delete profile: %s\n", qPrintable(name));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Update default if we deleted it
|
||||
if (readDefaultProfile() == id)
|
||||
{
|
||||
QStringList remaining = getProfilesList();
|
||||
writeDefaultProfile(remaining.isEmpty() ? QString() : remaining.first());
|
||||
}
|
||||
printf("Deleted profile: %s\n", qPrintable(name));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -433,30 +337,26 @@ int main(int argc, char *argv[])
|
||||
if (parser.isSet("set-default-profile"))
|
||||
{
|
||||
QString name = parser.value("set-default-profile");
|
||||
QString id = findProfileByName(name);
|
||||
if (id.isEmpty())
|
||||
auto profile = ProfileManager::profileByName(name);
|
||||
if (!profile)
|
||||
{
|
||||
fprintf(stderr, "Profile not found: %s\n", qPrintable(name));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!writeDefaultProfile(id))
|
||||
{
|
||||
fprintf(stderr, "Failed to write profiles.json\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ProfileManager::setDefaultProfile(*profile);
|
||||
printf("Default profile set to: %s\n", qPrintable(name));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Determine which profile to use for this session
|
||||
QString profileId;
|
||||
std::optional<Profile> activeProfile;
|
||||
|
||||
// --profile overrides everything
|
||||
if (parser.isSet("profile"))
|
||||
{
|
||||
QString name = parser.value("profile");
|
||||
profileId = findProfileByName(name);
|
||||
if (profileId.isEmpty())
|
||||
activeProfile = ProfileManager::profileByName(name);
|
||||
if (!activeProfile)
|
||||
{
|
||||
fprintf(stderr, "Profile not found: %s\n", qPrintable(name));
|
||||
return EXIT_FAILURE;
|
||||
@@ -464,40 +364,26 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use default profile
|
||||
profileId = readDefaultProfile();
|
||||
bool needsWrite = false;
|
||||
// Try default profile
|
||||
activeProfile = ProfileManager::defaultProfile();
|
||||
|
||||
// Validate default exists
|
||||
if (!profileId.isEmpty() && !profileExists(profileId))
|
||||
// Try first available profile
|
||||
if (!activeProfile)
|
||||
{
|
||||
profileId.clear();
|
||||
needsWrite = true;
|
||||
auto allProfiles = ProfileManager::profiles();
|
||||
if (!allProfiles.isEmpty())
|
||||
activeProfile = allProfiles.first();
|
||||
}
|
||||
|
||||
// Find first profile
|
||||
if (profileId.isEmpty())
|
||||
{
|
||||
QStringList profiles = getProfilesList();
|
||||
if (!profiles.isEmpty())
|
||||
{
|
||||
profileId = profiles.first();
|
||||
needsWrite = true;
|
||||
}
|
||||
}
|
||||
// Create new profile if none exist
|
||||
if (!activeProfile)
|
||||
activeProfile = ProfileManager::createProfile("Default");
|
||||
|
||||
// Create new profile
|
||||
if (profileId.isEmpty())
|
||||
{
|
||||
profileId = createNewProfile("Default");
|
||||
needsWrite = true;
|
||||
}
|
||||
|
||||
if (needsWrite)
|
||||
writeDefaultProfile(profileId);
|
||||
// Update default
|
||||
ProfileManager::setDefaultProfile(*activeProfile);
|
||||
}
|
||||
|
||||
Paths::setActiveProfileId(profileId);
|
||||
ProfileManager::Get().setActiveProfile(*activeProfile);
|
||||
|
||||
// Now everything else - all paths are profile-specific from here on
|
||||
QString logLevel = parser.value("log-level");
|
||||
@@ -574,8 +460,8 @@ int main(int argc, char *argv[])
|
||||
// Configure default WebEngineProfile paths early (profile is already set)
|
||||
{
|
||||
QWebEngineProfile* defaultProfile = QWebEngineProfile::defaultProfile();
|
||||
defaultProfile->setCachePath(Paths::cacheDir("QtWebEngine"));
|
||||
defaultProfile->setPersistentStoragePath(Paths::dataDir("QtWebEngine"));
|
||||
defaultProfile->setCachePath(ProfileManager::activeProfile().cacheDir("QtWebEngine"));
|
||||
defaultProfile->setPersistentStoragePath(ProfileManager::activeProfile().dataDir("QtWebEngine"));
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MAC) && defined(NDEBUG)
|
||||
@@ -605,7 +491,7 @@ int main(int argc, char *argv[])
|
||||
// Rotate temp log to main log file and rotate old logs
|
||||
Log::RotateLog();
|
||||
|
||||
qInfo() << "Config directory:" << qPrintable(Paths::dataDir());
|
||||
qInfo() << "Config directory:" << qPrintable(ProfileManager::activeProfile().dataDir());
|
||||
|
||||
Codecs::preinitCodecs();
|
||||
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
#include "system/SystemComponent.h"
|
||||
#include "settings/SettingsComponent.h"
|
||||
#include "core/Globals.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "ui/WindowManager.h"
|
||||
#include "shared/Paths.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusError>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
@@ -70,8 +71,9 @@ bool MprisComponent::componentInitialize()
|
||||
return true;
|
||||
}
|
||||
|
||||
// Generate profile-specific service name
|
||||
m_serviceName = QString("org.mpris.MediaPlayer2.JellyfinDesktop.profile_%1").arg(Paths::activeProfileId());
|
||||
// Generate profile-specific service name using cache dir basename (profile ID)
|
||||
QString profileCacheDir = ProfileManager::activeProfile().cacheDir();
|
||||
m_serviceName = QString("org.mpris.MediaPlayer2.JellyfinDesktop.profile_%1").arg(QFileInfo(profileCacheDir).fileName());
|
||||
|
||||
qDebug() << "Attempting to register MPRIS service:" << m_serviceName;
|
||||
if (!QDBusConnection::sessionBus().registerService(m_serviceName))
|
||||
@@ -101,7 +103,7 @@ bool MprisComponent::componentInitialize()
|
||||
if (cacheSize > 0)
|
||||
{
|
||||
auto* cache = new QNetworkDiskCache(this);
|
||||
QString cacheDir = Paths::cacheDir("mpris-albumart");
|
||||
QString cacheDir = ProfileManager::activeProfile().cacheDir("mpris-albumart");
|
||||
cache->setCacheDirectory(cacheDir);
|
||||
cache->setMaximumCacheSize(cacheSize);
|
||||
m_albumArtManager->setCache(cache);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "system/SystemComponent.h"
|
||||
#include "settings/SettingsComponent.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "utils/Utils.h"
|
||||
#include "shared/Paths.h"
|
||||
#include "PlayerComponent.h"
|
||||
@@ -146,7 +147,7 @@ QString Codecs::plexNameFromFF(QString ffname)
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static QString codecsRootPath()
|
||||
{
|
||||
return Paths::dataDir("Codecs") + QDir::separator();
|
||||
return ProfileManager::activeProfile().dataDir("Codecs") + QDir::separator();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -504,7 +505,7 @@ static void updateCodecs()
|
||||
{
|
||||
QStringList candidates = {
|
||||
codecsRootPath(),
|
||||
Paths::dataDir() + "/codecs/",
|
||||
ProfileManager::activeProfile().dataDir("codecs"),
|
||||
};
|
||||
|
||||
QSet<QString> codecFiles;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "SettingsComponent.h"
|
||||
#include "SettingsSection.h"
|
||||
#include "Paths.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "utils/Utils.h"
|
||||
#include "AudioSettingsController.h"
|
||||
#include "Names.h"
|
||||
@@ -217,7 +218,7 @@ static void writeJson(const QString& filename, const QJsonObject& data, bool pre
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
QVariant SettingsComponent::readPreinitValue(const QString& sectionID, const QString& key)
|
||||
{
|
||||
QString path = Paths::dataDir("jellyfin-desktop.conf");
|
||||
QString path = ProfileManager::activeProfile().dataDir("jellyfin-desktop.conf");
|
||||
if (path.isEmpty())
|
||||
return QVariant();
|
||||
QJsonObject json = loadJson(path);
|
||||
@@ -227,15 +228,15 @@ QVariant SettingsComponent::readPreinitValue(const QString& sectionID, const QSt
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void SettingsComponent::load()
|
||||
{
|
||||
QString profileDir = Paths::dataDir();
|
||||
QString profileDir = ProfileManager::activeProfile().dataDir();
|
||||
if (profileDir.isEmpty())
|
||||
{
|
||||
qInfo() << "No active profile, skipping settings load (using defaults)";
|
||||
return;
|
||||
}
|
||||
|
||||
loadConf(Paths::dataDir("jellyfin-desktop.conf"), false);
|
||||
loadConf(Paths::dataDir("storage.json"), true);
|
||||
loadConf(ProfileManager::activeProfile().dataDir("jellyfin-desktop.conf"), false);
|
||||
loadConf(ProfileManager::activeProfile().dataDir("storage.json"), true);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -295,7 +296,7 @@ void SettingsComponent::loadConf(const QString& path, bool storage)
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void SettingsComponent::saveSettings()
|
||||
{
|
||||
QString path = Paths::dataDir("jellyfin-desktop.conf");
|
||||
QString path = ProfileManager::activeProfile().dataDir("jellyfin-desktop.conf");
|
||||
if (path.isEmpty())
|
||||
{
|
||||
qWarning() << "No active profile, cannot save settings";
|
||||
@@ -319,7 +320,7 @@ void SettingsComponent::saveSettings()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void SettingsComponent::saveStorage()
|
||||
{
|
||||
QString path = Paths::dataDir("storage.json");
|
||||
QString path = ProfileManager::activeProfile().dataDir("storage.json");
|
||||
if (path.isEmpty())
|
||||
{
|
||||
qWarning() << "No active profile, cannot save storage";
|
||||
@@ -716,11 +717,11 @@ bool SettingsComponent::componentInitialize()
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool SettingsComponent::resetAndSaveOldConfiguration()
|
||||
{
|
||||
QString path = Paths::dataDir("jellyfin-desktop.conf");
|
||||
QString path = ProfileManager::activeProfile().dataDir("jellyfin-desktop.conf");
|
||||
if (path.isEmpty())
|
||||
return false;
|
||||
QFile settingsFile(path);
|
||||
return settingsFile.rename(Paths::dataDir("jellyfin-desktop.conf.old"));
|
||||
return settingsFile.rename(ProfileManager::activeProfile().dataDir("jellyfin-desktop.conf.old"));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+6
-88
@@ -12,11 +12,11 @@
|
||||
#include <QDebug>
|
||||
#include "Names.h"
|
||||
#include "Version.h"
|
||||
#include "core/ProfileManager.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
static QString g_configDirOverride;
|
||||
static QString g_cacheDirOverride;
|
||||
static QString g_activeProfileId;
|
||||
static bool g_portableMode = false;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -152,83 +152,13 @@ QString Paths::globalCacheDir(const QString& file)
|
||||
return d.filePath(file);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
QString Paths::dataDir(const QString& file)
|
||||
{
|
||||
// Use profile-specific directory when profile is active
|
||||
if (!g_activeProfileId.isEmpty())
|
||||
{
|
||||
QDir d(globalDataDir("profiles/" + g_activeProfileId));
|
||||
if (!d.mkpath(d.absolutePath()))
|
||||
{
|
||||
qWarning() << "Failed to create profile data directory:" << d.absolutePath();
|
||||
return globalDataDir(file);
|
||||
}
|
||||
|
||||
if (file.isEmpty())
|
||||
return d.absolutePath();
|
||||
return d.filePath(file);
|
||||
}
|
||||
|
||||
// Fallback to global when no profile active
|
||||
return globalDataDir(file);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
QString Paths::cacheDir(const QString& file)
|
||||
{
|
||||
// Use profile-specific directory when profile is active
|
||||
if (!g_activeProfileId.isEmpty())
|
||||
{
|
||||
QDir d(globalCacheDir("profiles/" + g_activeProfileId));
|
||||
if (!d.mkpath(d.absolutePath()))
|
||||
{
|
||||
qWarning() << "Failed to create profile cache directory:" << d.absolutePath();
|
||||
return globalCacheDir(file);
|
||||
}
|
||||
|
||||
if (file.isEmpty())
|
||||
return d.absolutePath();
|
||||
return d.filePath(file);
|
||||
}
|
||||
|
||||
// Fallback to global when no profile active
|
||||
return globalCacheDir(file);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
QString Paths::logDir(const QString& file)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
// On macOS, logs go to ~/Library/Logs/
|
||||
QDir ldir = QDir(QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory));
|
||||
|
||||
if (!g_activeProfileId.isEmpty())
|
||||
{
|
||||
ldir.mkpath(ldir.absolutePath() + "/Library/Logs/" + Names::DataName() + "/" + g_activeProfileId);
|
||||
ldir.cd("Library/Logs/" + Names::DataName() + "/" + g_activeProfileId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ldir.mkpath(ldir.absolutePath() + "/Library/Logs/" + Names::DataName());
|
||||
ldir.cd("Library/Logs/" + Names::DataName());
|
||||
}
|
||||
|
||||
return ldir.filePath(file);
|
||||
#else
|
||||
// On other platforms, logs go to dataDir/logs/
|
||||
QDir ldir(dataDir());
|
||||
ldir.mkpath(ldir.absolutePath() + "/logs");
|
||||
ldir.cd("logs");
|
||||
return ldir.filePath(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
QString Paths::socketName(const QString& serverName)
|
||||
{
|
||||
QString profileId = g_activeProfileId.isEmpty() ? "default" : g_activeProfileId;
|
||||
QString socketFile = QString("jellyfin-desktop.%1.%2").arg(profileId, serverName);
|
||||
QString profileName = ProfileManager::activeProfile().name();
|
||||
if (profileName.isEmpty())
|
||||
profileName = "default";
|
||||
QString socketFile = QString("jellyfin-desktop.%1.%2").arg(profileName, serverName);
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
|
||||
@@ -244,7 +174,7 @@ QString Paths::socketName(const QString& serverName)
|
||||
QString Paths::soundsPath(const QString& sound)
|
||||
{
|
||||
// check local filesystem first
|
||||
auto localSound = dataDir("sounds/" + sound);
|
||||
auto localSound = ProfileManager::activeProfile().dataDir("sounds/" + sound);
|
||||
|
||||
QFileInfo f(localSound);
|
||||
if (f.exists())
|
||||
@@ -273,15 +203,3 @@ QString Paths::webExtensionPath(const QString& mode)
|
||||
QString webName = QString("web-client/%1").arg(mode);
|
||||
return resourceDir(webName + "/");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Paths::setActiveProfileId(const QString& id)
|
||||
{
|
||||
g_activeProfileId = id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
QString Paths::activeProfileId()
|
||||
{
|
||||
return g_activeProfileId;
|
||||
}
|
||||
@@ -24,13 +24,6 @@ namespace Paths
|
||||
// Global paths (always ~/.local/share/jellyfin-desktop or equivalent)
|
||||
QString globalDataDir(const QString& file = QString());
|
||||
QString globalCacheDir(const QString& file = QString());
|
||||
|
||||
// Profile-aware paths (profile-specific when active, fallback to global)
|
||||
void setActiveProfileId(const QString& id);
|
||||
QString activeProfileId();
|
||||
QString dataDir(const QString& file = QString());
|
||||
QString cacheDir(const QString& file = QString());
|
||||
QString logDir(const QString& file = QString());
|
||||
};
|
||||
|
||||
#endif //KONVERGO_PATHS_H
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "settings/SettingsComponent.h"
|
||||
#include "settings/SettingsSection.h"
|
||||
#include "Paths.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "Names.h"
|
||||
#include "utils/Utils.h"
|
||||
#include "utils/Log.h"
|
||||
@@ -102,8 +103,8 @@ SystemComponent::SystemComponent(QObject* parent) : ComponentBase(parent), m_pla
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool SystemComponent::componentInitialize()
|
||||
{
|
||||
QDir().mkpath(Paths::dataDir("scripts"));
|
||||
QDir().mkpath(Paths::dataDir("sounds"));
|
||||
QDir().mkpath(ProfileManager::activeProfile().dataDir("scripts"));
|
||||
QDir().mkpath(ProfileManager::activeProfile().dataDir("sounds"));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -457,8 +458,8 @@ QString SystemComponent::debugInformation()
|
||||
stream << "\n";
|
||||
|
||||
stream << "Files\n";
|
||||
stream << " Log file: " << Paths::logDir(Names::DataName() + ".log") << "\n";
|
||||
stream << " Config file: " << Paths::dataDir(Names::DataName() + ".conf") << "\n";
|
||||
stream << " Log file: " << ProfileManager::activeProfile().logDir() + "/" + Names::DataName() + ".log" << "\n";
|
||||
stream << " Config file: " << ProfileManager::activeProfile().dataDir(Names::DataName() + ".conf") << "\n";
|
||||
stream << "\n";
|
||||
|
||||
stream << "Network Addresses\n";
|
||||
@@ -506,7 +507,7 @@ void SystemComponent::runUserScript(QString script)
|
||||
// to be careful with their keymaps.
|
||||
//
|
||||
QFileInfo fi(script);
|
||||
QString scriptPath = Paths::dataDir("scripts/" + fi.fileName());
|
||||
QString scriptPath = ProfileManager::activeProfile().dataDir("scripts/" + fi.fileName());
|
||||
|
||||
QFile scriptFile(scriptPath);
|
||||
if (scriptFile.exists())
|
||||
|
||||
+2
-2
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "shared/Names.h"
|
||||
#include "shared/Paths.h"
|
||||
#include "core/ProfileManager.h"
|
||||
#include "settings/SettingsComponent.h"
|
||||
#include "Version.h"
|
||||
|
||||
@@ -87,8 +88,7 @@ void Log::CensorAuthTokens(QString& msg)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
static QString getLogDir()
|
||||
{
|
||||
// Paths::logDir() returns profile-specific path when profile is active
|
||||
return Paths::logDir("");
|
||||
return ProfileManager::activeProfile().logDir();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in new issue
Block a user