Katja Marttila 0f8d11ca8e Enable usage of categorized repositories
This change allows to categorize repositories in component selection
page. Using categorized repositories will by default show only
uncagetorized repository items in tree. Selecting one or several categories
using checkbox will update the treeview to show all selected categorized repository
content. Repository's metadata is fetched only after the category is selected.
Categorized repositories can be defined in config.xml:
<RepositoryCategories>
    <RemoteRepositories>
    <Displayname>category 1</Displayname>
    <Repository> <Url>(url)</Url></Repository>
    </RemoteReposiories>
    ...
<RepositoryCategories

Change-Id: I6eae9daee70b1afa322144d52c11f25d0b655ebf
Reviewed-by: Jani Heikkinen <jani.heikkinen@qt.io>
Reviewed-by: Iikka Eklund <iikka.eklund@qt.io>
2018-09-26 04:46:21 +00:00

822 lines
28 KiB
C++

/**************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
**************************************************************************/
#include "settings.h"
#include "errors.h"
#include "qinstallerglobal.h"
#include "repository.h"
#include "repositorycategory.h"
#include <QtCore/QFileInfo>
#include <QtCore/QStringList>
#include <QtGui/QFontMetrics>
#include <QtWidgets/QApplication>
#include <QRegularExpression>
#include <QXmlStreamReader>
using namespace QInstaller;
static const QLatin1String scInstallerApplicationIcon("InstallerApplicationIcon");
static const QLatin1String scInstallerWindowIcon("InstallerWindowIcon");
static const QLatin1String scLogo("Logo");
static const QLatin1String scPrefix("Prefix");
static const QLatin1String scWatermark("Watermark");
static const QLatin1String scBanner("Banner");
static const QLatin1String scProductUrl("ProductUrl");
static const QLatin1String scBackground("Background");
static const QLatin1String scAdminTargetDir("AdminTargetDir");
static const QLatin1String scMaintenanceToolName("MaintenanceToolName");
static const QLatin1String scUserRepositories("UserRepositories");
static const QLatin1String scTmpRepositories("TemporaryRepositories");
static const QLatin1String scMaintenanceToolIniFile("MaintenanceToolIniFile");
static const QLatin1String scRemoteRepositories("RemoteRepositories");
static const QLatin1String scRepositoryCategories("RepositoryCategories");
static const QLatin1String scDependsOnLocalInstallerBinary("DependsOnLocalInstallerBinary");
static const QLatin1String scTranslations("Translations");
static const QLatin1String scCreateLocalRepository("CreateLocalRepository");
static const QLatin1String scInstallActionColumnVisible("InstallActionColumnVisible");
static const QLatin1String scFtpProxy("FtpProxy");
static const QLatin1String scHttpProxy("HttpProxy");
static const QLatin1String scProxyType("ProxyType");
const char scControlScript[] = "ControlScript";
template <typename T>
static QSet<T> variantListToSet(const QVariantList &list)
{
QSet<T> set;
foreach (const QVariant &variant, list)
set.insert(variant.value<T>());
return set;
}
static void raiseError(QXmlStreamReader &reader, const QString &error, Settings::ParseMode parseMode)
{
if (parseMode == Settings::StrictParseMode) {
reader.raiseError(error);
} else {
QFile *xmlFile = qobject_cast<QFile*>(reader.device());
if (xmlFile) {
qWarning().noquote().nospace()
<< "Ignoring following settings reader error in " << xmlFile->fileName()
<< ", line " << reader.lineNumber() << ", column " << reader.columnNumber()
<< ": " << error;
} else {
qWarning("Ignoring following settings reader error: %s", qPrintable(error));
}
}
}
static QStringList readArgumentAttributes(QXmlStreamReader &reader, Settings::ParseMode parseMode,
const QString &tagName, bool lc = false)
{
QStringList arguments;
while (QXmlStreamReader::TokenType token = reader.readNext()) {
switch (token) {
case QXmlStreamReader::StartElement: {
if (!reader.attributes().isEmpty()) {
raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".")
.arg(reader.name().toString()), parseMode);
return arguments;
} else {
if (reader.name().toString() == tagName) {
(lc) ? arguments.append(reader.readElementText().toLower()) :
arguments.append(reader.readElementText());
} else {
raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(reader.name()
.toString()), parseMode);
return arguments;
}
}
}
break;
case QXmlStreamReader::Characters: {
if (reader.isWhitespace())
continue;
arguments.append(reader.text().toString().split(QRegularExpression(QLatin1String("\\s+")),
QString::SkipEmptyParts));
}
break;
case QXmlStreamReader::EndElement: {
return arguments;
}
default:
break;
}
}
return arguments;
}
static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefault, Settings::ParseMode parseMode, QString *displayName = 0)
{
qDebug()<<__FUNCTION__;
QSet<Repository> set;
while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("DisplayName")) {
//remote repository can have also displayname. Needed when creating archive repositories
*displayName = reader.readElementText();
} else if (reader.name() == QLatin1String("Repository")) {
Repository repo(QString(), isDefault);
while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("Url")) {
repo.setUrl(reader.readElementText());
} else if (reader.name() == QLatin1String("Username")) {
repo.setUsername(reader.readElementText());
} else if (reader.name() == QLatin1String("Password")) {
repo.setPassword(reader.readElementText());
} else if (reader.name() == QLatin1String("DisplayName")) {
repo.setDisplayName(reader.readElementText());
} else if (reader.name() == QLatin1String("Enabled")) {
repo.setEnabled(bool(reader.readElementText().toInt()));
} else {
raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(reader.name()
.toString()), parseMode);
}
if (!reader.attributes().isEmpty()) {
raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".")
.arg(reader.name().toString()), parseMode);
}
}
if (displayName && !displayName->isEmpty())
repo.setArchiveName(*displayName);
set.insert(repo);
} else {
raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(reader.name().toString()),
parseMode);
}
if (!reader.attributes().isEmpty()) {
raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".").arg(reader
.name().toString()), parseMode);
}
}
return set;
}
static QSet<RepositoryCategory> readRepositoryCategories(QXmlStreamReader &reader, bool isDefault, Settings::ParseMode parseMode,
QString *repositoryCategoryName)
{
QSet<RepositoryCategory> archiveSet;
while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("RemoteRepositories")) {
RepositoryCategory archiveRepo;
QString displayName;
archiveRepo.setRepositories(readRepositories(reader, isDefault, parseMode, &displayName));
archiveRepo.setDisplayName(displayName);
archiveSet.insert(archiveRepo);
} else if (reader.name() == QLatin1String("RepositoryCategoryDisplayname")) {
*repositoryCategoryName = reader.readElementText();
}
}
return archiveSet;
}
// -- Settings::Private
class Settings::Private : public QSharedData
{
public:
Private()
: m_replacementRepos(false)
{}
QVariantHash m_data;
bool m_replacementRepos;
QString absolutePathFromKey(const QString &key, const QString &suffix = QString()) const
{
const QString value = m_data.value(key).toString();
if (value.isEmpty())
return QString();
const QString path = value + suffix;
if (QFileInfo(path).isAbsolute())
return path;
return m_data.value(scPrefix).toString() + QLatin1String("/") + path;
}
};
// -- Settings
Settings::Settings()
: d(new Private)
{
}
Settings::~Settings()
{
}
Settings::Settings(const Settings &other)
: d(other.d)
{
}
Settings& Settings::operator=(const Settings &other)
{
Settings copy(other);
std::swap(d, copy.d);
return *this;
}
/* static */
Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix, ParseMode parseMode)
{
QFile file(path);
QFile overrideConfig(QLatin1String(":/overrideconfig.xml"));
if (overrideConfig.exists())
file.setFileName(overrideConfig.fileName());
if (!file.open(QIODevice::ReadOnly))
throw Error(tr("Cannot open settings file %1 for reading: %2").arg(path, file.errorString()));
QXmlStreamReader reader(&file);
if (reader.readNextStartElement()) {
if (reader.name() != QLatin1String("Installer")) {
reader.raiseError(QString::fromLatin1("Unexpected element \"%1\" as root element.").arg(reader
.name().toString()));
}
}
QStringList elementList;
elementList << scName << scVersion << scTitle << scPublisher << scProductUrl
<< scTargetDir << scAdminTargetDir
<< scInstallerApplicationIcon << scInstallerWindowIcon
<< scLogo << scWatermark << scBanner << scBackground
<< scStartMenuDir << scMaintenanceToolName << scMaintenanceToolIniFile << scRemoveTargetDir
<< scRunProgram << scRunProgramArguments << scRunProgramDescription
<< scDependsOnLocalInstallerBinary
<< scAllowSpaceInPath << scAllowNonAsciiCharacters << scDisableAuthorizationFallback
<< scWizardStyle << scStyleSheet << scTitleColor
<< scWizardDefaultWidth << scWizardDefaultHeight
<< scRepositorySettingsPageVisible << scTargetConfigurationFile
<< scRemoteRepositories << scTranslations << scUrlQueryString << QLatin1String(scControlScript)
<< scCreateLocalRepository << scInstallActionColumnVisible << scSupportsModify << scAllowUnstableComponents
<< scSaveDefaultRepositories << scRepositoryCategories;
Settings s;
s.d->m_data.insert(scPrefix, prefix);
while (reader.readNextStartElement()) {
const QString name = reader.name().toString();
if (!elementList.contains(name))
raiseError(reader, QString::fromLatin1("Unexpected element \"%1\".").arg(name), parseMode);
if (!reader.attributes().isEmpty()) {
raiseError(reader, QString::fromLatin1("Unexpected attribute for element \"%1\".").arg(name),
parseMode);
}
if (s.d->m_data.contains(name))
reader.raiseError(QString::fromLatin1("Element \"%1\" has been defined before.").arg(name));
if (name == scTranslations) {
s.setTranslations(readArgumentAttributes(reader, parseMode, QLatin1String("Translation"), true));
} else if (name == scRunProgramArguments) {
s.setRunProgramArguments(readArgumentAttributes(reader, parseMode, QLatin1String("Argument")));
} else if (name == scRemoteRepositories) {
s.addDefaultRepositories(readRepositories(reader, true, parseMode));
} else if (name == scRepositoryCategories) {
QString repositoryCategoryName;
s.addRepositoryCategories(readRepositoryCategories(reader, true, parseMode, &repositoryCategoryName));
if (!repositoryCategoryName.isEmpty()) {
s.setRepositoryCategoryDisplayName(repositoryCategoryName);
}
} else {
s.d->m_data.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements));
}
}
if (reader.error() != QXmlStreamReader::NoError) {
throw Error(QString::fromLatin1("Error in %1, line %2, column %3: %4").arg(path).arg(reader
.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()));
}
if (s.d->m_data.value(scName).isNull())
throw Error(QString::fromLatin1("Missing or empty <Name> tag in %1.").arg(file.fileName()));
if (s.d->m_data.value(scVersion).isNull())
throw Error(QString::fromLatin1("Missing or empty <Version> tag in %1.").arg(file.fileName()));
// Add some possible missing values
if (!s.d->m_data.contains(scInstallerApplicationIcon))
s.d->m_data.insert(scInstallerApplicationIcon, QLatin1String(":/installer"));
if (!s.d->m_data.contains(scInstallerWindowIcon)) {
s.d->m_data.insert(scInstallerWindowIcon,
QString(QLatin1String(":/installer") + s.systemIconSuffix()));
}
if (!s.d->m_data.contains(scRemoveTargetDir))
s.d->m_data.insert(scRemoveTargetDir, scTrue);
if (s.d->m_data.value(scMaintenanceToolName).toString().isEmpty()) {
s.d->m_data.insert(scMaintenanceToolName,
// TODO: Remove deprecated 'UninstallerName'.
s.d->m_data.value(QLatin1String("UninstallerName"), QLatin1String("maintenancetool"))
.toString());
}
if (s.d->m_data.value(scTargetConfigurationFile).toString().isEmpty())
s.d->m_data.insert(scTargetConfigurationFile, QLatin1String("components.xml"));
if (s.d->m_data.value(scMaintenanceToolIniFile).toString().isEmpty()) {
s.d->m_data.insert(scMaintenanceToolIniFile,
// TODO: Remove deprecated 'UninstallerIniFile'.
s.d->m_data.value(QLatin1String("UninstallerIniFile"), QString(s.maintenanceToolName()
+ QLatin1String(".ini"))).toString());
}
if (!s.d->m_data.contains(scDependsOnLocalInstallerBinary))
s.d->m_data.insert(scDependsOnLocalInstallerBinary, false);
if (!s.d->m_data.contains(scRepositorySettingsPageVisible))
s.d->m_data.insert(scRepositorySettingsPageVisible, true);
if (!s.d->m_data.contains(scCreateLocalRepository))
s.d->m_data.insert(scCreateLocalRepository, false);
if (!s.d->m_data.contains(scInstallActionColumnVisible))
s.d->m_data.insert(scInstallActionColumnVisible, false);
if (!s.d->m_data.contains(scAllowUnstableComponents))
s.d->m_data.insert(scAllowUnstableComponents, false);
if (!s.d->m_data.contains(scSaveDefaultRepositories))
s.d->m_data.insert(scSaveDefaultRepositories, true);
return s;
}
QString Settings::logo() const
{
return d->absolutePathFromKey(scLogo);
}
QString Settings::title() const
{
return d->m_data.value(scTitle).toString();
}
QString Settings::applicationName() const
{
return d->m_data.value(scName).toString();
}
QString Settings::version() const
{
return d->m_data.value(scVersion).toString();
}
QString Settings::publisher() const
{
return d->m_data.value(scPublisher).toString();
}
QString Settings::url() const
{
return d->m_data.value(scProductUrl).toString();
}
QString Settings::watermark() const
{
return d->absolutePathFromKey(scWatermark);
}
QString Settings::banner() const
{
return d->absolutePathFromKey(scBanner);
}
QString Settings::background() const
{
return d->absolutePathFromKey(scBackground);
}
QString Settings::wizardStyle() const
{
return d->m_data.value(scWizardStyle).toString();
}
QString Settings::styleSheet() const
{
return d->absolutePathFromKey(scStyleSheet);
}
QString Settings::titleColor() const
{
return d->m_data.value(scTitleColor).toString();
}
static int lengthToInt(const QVariant &variant)
{
QString length = variant.toString().trimmed();
if (length.endsWith(QLatin1String("em"), Qt::CaseInsensitive)) {
length.chop(2);
return qRound(length.toDouble() * QApplication::fontMetrics().height());
}
if (length.endsWith(QLatin1String("ex"), Qt::CaseInsensitive)) {
length.chop(2);
return qRound(length.toDouble() * QApplication::fontMetrics().xHeight());
}
if (length.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
length.chop(2);
}
return length.toInt();
}
int Settings::wizardDefaultWidth() const
{
return lengthToInt(d->m_data.value(scWizardDefaultWidth));
}
int Settings::wizardDefaultHeight() const
{
return lengthToInt(d->m_data.value(scWizardDefaultHeight));
}
QString Settings::installerApplicationIcon() const
{
return d->absolutePathFromKey(scInstallerApplicationIcon, systemIconSuffix());
}
QString Settings::installerWindowIcon() const
{
return d->absolutePathFromKey(scInstallerWindowIcon);
}
QString Settings::systemIconSuffix() const
{
#if defined(Q_OS_OSX)
return QLatin1String(".icns");
#elif defined(Q_OS_WIN)
return QLatin1String(".ico");
#endif
return QLatin1String(".png");
}
QString Settings::removeTargetDir() const
{
return d->m_data.value(scRemoveTargetDir).toString();
}
QString Settings::maintenanceToolName() const
{
return d->m_data.value(scMaintenanceToolName).toString();
}
QString Settings::maintenanceToolIniFile() const
{
return d->m_data.value(scMaintenanceToolIniFile).toString();
}
QString Settings::runProgram() const
{
return d->m_data.value(scRunProgram).toString();
}
QStringList Settings::runProgramArguments() const
{
const QVariant variant = d->m_data.values(scRunProgramArguments);
if (variant.canConvert<QStringList>())
return variant.value<QStringList>();
return QStringList();
}
void Settings::setRunProgramArguments(const QStringList &arguments)
{
d->m_data.insert(scRunProgramArguments, arguments);
}
QString Settings::runProgramDescription() const
{
return d->m_data.value(scRunProgramDescription).toString();
}
QString Settings::startMenuDir() const
{
return d->m_data.value(scStartMenuDir).toString();
}
QString Settings::targetDir() const
{
return d->m_data.value(scTargetDir).toString();
}
QString Settings::adminTargetDir() const
{
return d->m_data.value(scAdminTargetDir).toString();
}
QString Settings::configurationFileName() const
{
return d->m_data.value(scTargetConfigurationFile).toString();
}
bool Settings::createLocalRepository() const
{
return d->m_data.value(scCreateLocalRepository).toBool();
}
bool Settings::installActionColumnVisible() const
{
return d->m_data.value(scInstallActionColumnVisible, false).toBool();
}
bool Settings::allowSpaceInPath() const
{
return d->m_data.value(scAllowSpaceInPath, true).toBool();
}
bool Settings::allowNonAsciiCharacters() const
{
return d->m_data.value(scAllowNonAsciiCharacters, false).toBool();
}
bool Settings::disableAuthorizationFallback() const
{
return d->m_data.value(scDisableAuthorizationFallback, false).toBool();
}
bool Settings::dependsOnLocalInstallerBinary() const
{
return d->m_data.value(scDependsOnLocalInstallerBinary).toBool();
}
bool Settings::hasReplacementRepos() const
{
return d->m_replacementRepos;
}
QSet<Repository> Settings::repositories() const
{
if (d->m_replacementRepos)
return variantListToSet<Repository>(d->m_data.values(scTmpRepositories));
return variantListToSet<Repository>(d->m_data.values(scRepositories)
+ d->m_data.values(scUserRepositories) + d->m_data.values(scTmpRepositories));
}
QSet<Repository> Settings::defaultRepositories() const
{
return variantListToSet<Repository>(d->m_data.values(scRepositories));
}
QSet<RepositoryCategory> Settings::repositoryCategories() const
{
return variantListToSet<RepositoryCategory>(d->m_data.values(scRepositoryCategories));
}
void Settings::setDefaultRepositories(const QSet<Repository> &repositories)
{
d->m_data.remove(scRepositories);
addDefaultRepositories(repositories);
}
void Settings::addDefaultRepositories(const QSet<Repository> &repositories)
{
foreach (const Repository &repository, repositories)
d->m_data.insertMulti(scRepositories, QVariant().fromValue(repository));
}
void Settings::addRepositoryCategories(const QSet<RepositoryCategory> &repositories)
{
foreach (const RepositoryCategory &repository, repositories)
d->m_data.insertMulti(scRepositoryCategories, QVariant().fromValue(repository));
}
static bool apply(const RepoHash &updates, QHash<QUrl, Repository> *reposToUpdate)
{
bool update = false;
QList<QPair<Repository, Repository> > values = updates.values(QLatin1String("replace"));
for (int a = 0; a < values.count(); ++a) {
const QPair<Repository, Repository> data = values.at(a);
if (reposToUpdate->contains(data.first.url())) {
update = true;
reposToUpdate->remove(data.first.url());
reposToUpdate->insert(data.second.url(), data.second);
}
}
values = updates.values(QLatin1String("remove"));
for (int a = 0; a < values.count(); ++a) {
const QPair<Repository, Repository> data = values.at(a);
if (reposToUpdate->contains(data.first.url())) {
update = true;
reposToUpdate->remove(data.first.url());
}
}
values = updates.values(QLatin1String("add"));
for (int a = 0; a < values.count(); ++a) {
const QPair<Repository, Repository> data = values.at(a);
if (!reposToUpdate->contains(data.first.url())) {
update = true;
reposToUpdate->insert(data.first.url(), data.first);
}
}
return update;
}
Settings::Update Settings::updateDefaultRepositories(const RepoHash &updates)
{
if (updates.isEmpty())
return Settings::NoUpdatesApplied;
QHash <QUrl, Repository> defaultRepos;
foreach (const QVariant &variant, d->m_data.values(scRepositories)) {
const Repository repository = variant.value<Repository>();
defaultRepos.insert(repository.url(), repository);
}
const bool updated = apply(updates, &defaultRepos);
if (updated)
setDefaultRepositories(defaultRepos.values().toSet());
return updated ? Settings::UpdatesApplied : Settings::NoUpdatesApplied;
}
QSet<Repository> Settings::temporaryRepositories() const
{
return variantListToSet<Repository>(d->m_data.values(scTmpRepositories));
}
void Settings::setTemporaryRepositories(const QSet<Repository> &repositories, bool replace)
{
d->m_data.remove(scTmpRepositories);
addTemporaryRepositories(repositories, replace);
}
void Settings::addTemporaryRepositories(const QSet<Repository> &repositories, bool replace)
{
d->m_replacementRepos = replace;
foreach (const Repository &repository, repositories)
d->m_data.insertMulti(scTmpRepositories, QVariant().fromValue(repository));
}
QSet<Repository> Settings::userRepositories() const
{
return variantListToSet<Repository>(d->m_data.values(scUserRepositories));
}
void Settings::setUserRepositories(const QSet<Repository> &repositories)
{
d->m_data.remove(scUserRepositories);
addUserRepositories(repositories);
}
void Settings::addUserRepositories(const QSet<Repository> &repositories)
{
foreach (const Repository &repository, repositories)
d->m_data.insertMulti(scUserRepositories, QVariant().fromValue(repository));
}
Settings::Update Settings::updateUserRepositories(const RepoHash &updates)
{
if (updates.isEmpty())
return Settings::NoUpdatesApplied;
QHash <QUrl, Repository> reposToUpdate;
foreach (const QVariant &variant, d->m_data.values(scUserRepositories)) {
const Repository repository = variant.value<Repository>();
reposToUpdate.insert(repository.url(), repository);
}
const bool updated = apply(updates, &reposToUpdate);
if (updated)
setUserRepositories(reposToUpdate.values().toSet());
return updated ? Settings::UpdatesApplied : Settings::NoUpdatesApplied;
}
bool Settings::containsValue(const QString &key) const
{
return d->m_data.contains(key);
}
QVariant Settings::value(const QString &key, const QVariant &defaultValue) const
{
return d->m_data.value(key, defaultValue);
}
QVariantList Settings::values(const QString &key, const QVariantList &defaultValue) const
{
QVariantList list = d->m_data.values(key);
return list.isEmpty() ? defaultValue : list;
}
bool Settings::repositorySettingsPageVisible() const
{
return d->m_data.value(scRepositorySettingsPageVisible, true).toBool();
}
void Settings::setRepositorySettingsPageVisible(bool visible)
{
d->m_data.insert(scRepositorySettingsPageVisible, visible);
}
Settings::ProxyType Settings::proxyType() const
{
return Settings::ProxyType(d->m_data.value(scProxyType, Settings::NoProxy).toInt());
}
void Settings::setProxyType(Settings::ProxyType type)
{
d->m_data.insert(scProxyType, type);
}
QNetworkProxy Settings::ftpProxy() const
{
const QVariant variant = d->m_data.value(scFtpProxy);
if (variant.canConvert<QNetworkProxy>())
return variant.value<QNetworkProxy>();
return QNetworkProxy();
}
void Settings::setFtpProxy(const QNetworkProxy &proxy)
{
d->m_data.insert(scFtpProxy, QVariant::fromValue(proxy));
}
QNetworkProxy Settings::httpProxy() const
{
const QVariant variant = d->m_data.value(scHttpProxy);
if (variant.canConvert<QNetworkProxy>())
return variant.value<QNetworkProxy>();
return QNetworkProxy();
}
void Settings::setHttpProxy(const QNetworkProxy &proxy)
{
d->m_data.insert(scHttpProxy, QVariant::fromValue(proxy));
}
QStringList Settings::translations() const
{
const QVariant variant = d->m_data.values(scTranslations);
if (variant.canConvert<QStringList>())
return variant.value<QStringList>();
return QStringList();
}
void Settings::setTranslations(const QStringList &translations)
{
d->m_data.insert(scTranslations, translations);
}
QString Settings::controlScript() const
{
return d->m_data.value(QLatin1String(scControlScript)).toString();
}
bool Settings::supportsModify() const
{
return d->m_data.value(scSupportsModify, true).toBool();
}
bool Settings::allowUnstableComponents() const
{
return d->m_data.value(scAllowUnstableComponents, true).toBool();
}
void Settings::setAllowUnstableComponents(bool allow)
{
d->m_data.insert(scAllowUnstableComponents, allow);
}
bool Settings::saveDefaultRepositories() const
{
return d->m_data.value(scSaveDefaultRepositories, true).toBool();
}
void Settings::setSaveDefaultRepositories(bool save)
{
d->m_data.insert(scSaveDefaultRepositories, save);
}
QString Settings::repositoryCategoryDisplayName() const
{
QString displayName = d->m_data.value(QLatin1String(scRepositoryCategoryDisplayName)).toString();
return displayName.isEmpty() ? tr("Package categories") : displayName;
}
void Settings::setRepositoryCategoryDisplayName(const QString& name)
{
d->m_data.insert(scRepositoryCategoryDisplayName, name);
}