Files
iDescriptor/src/settingsmanager.cpp
T
2026-01-04 22:30:44 +00:00

417 lines
11 KiB
C++

/*
* iDescriptor: A free and open-source idevice management tool.
*
* Copyright (C) 2025 Uncore <https://github.com/uncor3>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "settingsmanager.h"
#include "settingswidget.h"
#include <QDebug>
#include <QDir>
#include <QSettings>
#include <QStandardPaths>
SettingsManager *SettingsManager::sharedInstance()
{
static SettingsManager instance;
return &instance;
}
void SettingsManager::showSettingsDialog()
{
if (m_dialog) {
m_dialog->raise();
m_dialog->activateWindow();
return;
}
m_dialog = new SettingsWidget();
m_dialog->setWindowTitle("Settings - iDescriptor");
m_dialog->setModal(true);
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(m_dialog, &QObject::destroyed, [this]() { m_dialog = nullptr; });
m_dialog->show();
}
SettingsManager::SettingsManager(QObject *parent) : QObject{parent}
{
m_settings = new QSettings(this);
}
void SettingsManager::clear()
{
m_settings->clear();
m_settings->sync();
}
QString SettingsManager::devdiskimgpath() const
{
return m_settings
->value("devdiskimgpath",
SettingsManager::homePath() + "/devdiskimages")
.toString();
}
void SettingsManager::setDevDiskImgPath(const QString &path)
{
m_settings->setValue("devdiskimgpath", path);
m_settings->sync();
}
QString SettingsManager::mkDevDiskImgPath() const
{
QString path = devdiskimgpath();
QDir dir(path);
if (!dir.exists()) {
dir.mkpath(path);
return path;
}
return path;
}
QString SettingsManager::homePath()
{
return QStandardPaths::writableLocation(QStandardPaths::HomeLocation) +
"/.idescriptor";
}
bool SettingsManager::autoCheckUpdates() const
{
return m_settings->value("autoCheckUpdates", true).toBool();
}
void SettingsManager::setAutoCheckUpdates(bool enabled)
{
m_settings->setValue("autoCheckUpdates", enabled);
m_settings->sync();
}
bool SettingsManager::autoRaiseWindow() const
{
return m_settings->value("autoRaiseWindow", true).toBool();
}
void SettingsManager::setAutoRaiseWindow(bool enabled)
{
m_settings->setValue("autoRaiseWindow", enabled);
m_settings->sync();
}
bool SettingsManager::switchToNewDevice() const
{
return m_settings->value("switchToNewDevice", true).toBool();
}
void SettingsManager::setSwitchToNewDevice(bool enabled)
{
m_settings->setValue("switchToNewDevice", enabled);
m_settings->sync();
}
#ifndef __APPLE__
bool SettingsManager::unmountiFuseOnExit() const
{
return m_settings->value("unmountiFuseOnExit", false).toBool();
}
void SettingsManager::setUnmountiFuseOnExit(bool enabled)
{
m_settings->setValue("unmountiFuseOnExit", enabled);
m_settings->sync();
}
#endif
bool SettingsManager::useUnsecureBackend() const
{
return m_settings->value("useUnsecureBackend-ipatool", false).toBool();
}
void SettingsManager::setUseUnsecureBackend(bool enabled)
{
m_settings->setValue("useUnsecureBackend-ipatool", enabled);
m_settings->sync();
}
QString SettingsManager::theme() const
{
return m_settings->value("theme", "System Default").toString();
}
void SettingsManager::setTheme(const QString &theme)
{
m_settings->setValue("theme", theme);
m_settings->sync();
}
int SettingsManager::connectionTimeout() const
{
return m_settings->value("connectionTimeout", 30).toInt();
}
void SettingsManager::setConnectionTimeout(int seconds)
{
m_settings->setValue("connectionTimeout", seconds);
m_settings->sync();
}
bool SettingsManager::showKeychainDialog() const
{
return m_settings->value("showKeychainDialog", true).toBool();
}
void SettingsManager::setShowKeychainDialog(bool show)
{
m_settings->setValue("showKeychainDialog", show);
m_settings->sync();
}
QString SettingsManager::defaultJailbrokenRootPassword() const
{
return m_settings->value("defaultJailbrokenRootPassword", "alpine")
.toString();
}
void SettingsManager::setDefaultJailbrokenRootPassword(const QString &password)
{
m_settings->setValue("defaultJailbrokenRootPassword", password);
m_settings->sync();
}
void SettingsManager::doIfEnabled(Setting setting, std::function<void()> action)
{
bool shouldExecute = false;
switch (setting) {
case Setting::AutoRaiseWindow:
shouldExecute = autoRaiseWindow();
break;
case Setting::SwitchToNewDevice:
shouldExecute = switchToNewDevice();
break;
case Setting::AutoCheckUpdates:
shouldExecute = autoCheckUpdates();
break;
#ifndef __APPLE__
case Setting::UnmountiFuseOnExit:
shouldExecute = unmountiFuseOnExit();
break;
#endif
default:
qWarning() << "Unhandled setting in doIfEnabled";
return;
}
qDebug() << "enabled" << switchToNewDevice();
if (shouldExecute && action) {
action();
}
}
void SettingsManager::resetToDefaults()
{
setDevDiskImgPath(SettingsManager::homePath() + "/devdiskimages");
setAutoCheckUpdates(true);
setAutoRaiseWindow(true);
setSwitchToNewDevice(true);
#ifndef __APPLE__
setUnmountiFuseOnExit(false);
#endif
setUseUnsecureBackend(false);
setTheme("System Default");
setConnectionTimeout(30);
setShowKeychainDialog(true);
setDefaultJailbrokenRootPassword("alpine");
}
void SettingsManager::saveFavoritePlace(const QString &path,
const QString &alias,
const QString &keyPrefix)
{
if (path.isEmpty() || alias.isEmpty()) {
qWarning() << "Cannot save favorite place with empty path or alias";
return;
}
// Use a key that encodes the path properly
QString key = keyPrefix + QString::fromLatin1(path.toUtf8().toBase64());
m_settings->setValue(key, QStringList() << path << alias);
m_settings->sync();
qDebug() << "Saved favorite place (AFC2):" << alias << "(" << path << ")";
emit favoritePlacesChanged();
}
void SettingsManager::removeFavoritePlace(const QString &keyPrefix,
const QString &path)
{
// Use the same encoding as in saveFavoritePlace
QString key = keyPrefix + QString::fromLatin1(path.toUtf8().toBase64());
qDebug() << "Attempting to remove favorite place with key:" << key;
if (m_settings->contains(key)) {
m_settings->remove(key);
m_settings->sync();
qDebug() << "Removed favorite place:" << path;
emit favoritePlacesChanged();
}
}
QList<QPair<QString, QString>>
SettingsManager::getFavoritePlaces(const QString &keyPrefix) const
{
QList<QPair<QString, QString>> favorites;
// Get all keys that start with the specified prefix
QStringList allKeys = m_settings->allKeys();
QStringList favoriteKeys = allKeys.filter(keyPrefix);
qDebug() << "Found favorite keys:" << favoriteKeys;
for (const QString &key : favoriteKeys) {
QStringList value = m_settings->value(key).toStringList();
if (value.size() >= 2) {
QString path = value[0];
QString alias = value[1];
if (!path.isEmpty() && !alias.isEmpty()) {
favorites.append(qMakePair(path, alias));
qDebug() << "Loaded favorite:" << alias << "->" << path;
}
}
}
// Sort by alias for consistent ordering
std::sort(
favorites.begin(), favorites.end(),
[](const QPair<QString, QString> &a, const QPair<QString, QString> &b) {
return a.second.toLower() < b.second.toLower();
});
return favorites;
}
void SettingsManager::clearKeys(const QString &keyPrefix)
{
QStringList allKeys = m_settings->allKeys();
QStringList favoriteKeys = allKeys.filter(keyPrefix);
for (const QString &key : favoriteKeys) {
m_settings->remove(key);
}
m_settings->sync();
emit favoritePlacesChanged();
}
void SettingsManager::saveRecentLocation(double latitude, double longitude,
const QString &name)
{
// Get existing recent locations
QList<QVariantMap> recentLocations = getRecentLocations();
// Create new location entry
QVariantMap newLocation;
newLocation["latitude"] = latitude;
newLocation["longitude"] = longitude;
// Add to front of list
recentLocations.prepend(newLocation);
// Keep only last 10 locations
while (recentLocations.size() > 10) {
recentLocations.removeLast();
}
// Save to settings
QVariantList variantList;
for (const QVariantMap &loc : recentLocations) {
variantList.append(loc);
}
m_settings->setValue("recentLocations", variantList);
m_settings->sync();
qDebug() << "Saved recent location:" << latitude << "," << longitude;
emit recentLocationsChanged();
}
QList<QVariantMap> SettingsManager::getRecentLocations() const
{
QList<QVariantMap> recentLocations;
QVariantList variantList = m_settings->value("recentLocations").toList();
for (const QVariant &item : variantList) {
if (item.canConvert<QVariantMap>()) {
recentLocations.append(item.toMap());
}
}
return recentLocations;
}
void SettingsManager::clearRecentLocations()
{
m_settings->remove("recentLocations");
m_settings->sync();
}
QString SettingsManager::appVersion()
{
return m_settings->value("__APP_VERSION__", "").toString();
}
void SettingsManager::setAppVersion(const QString &version)
{
m_settings->setValue("__APP_VERSION__", version);
m_settings->sync();
}
double SettingsManager::iconSizeBaseMultiplier() const
{
return m_settings->value("iconSizeBaseMultiplier", 1.0).toDouble();
}
void SettingsManager::setIconSizeBaseMultiplier(double multiplier)
{
m_settings->setValue("iconSizeBaseMultiplier", multiplier);
m_settings->sync();
}
int SettingsManager::airplayFps() const
{
return m_settings->value("airplayFps", 60).toInt();
}
void SettingsManager::setAirplayFps(int fps)
{
m_settings->setValue("airplayFps", fps);
m_settings->sync();
}
#ifdef __linux__
bool SettingsManager::showV4L2() const
{
return m_settings->value("showV4L2", false).toBool();
}
void SettingsManager::setShowV4L2(bool show)
{
m_settings->setValue("showV4L2", show);
m_settings->sync();
}
#endif