Commit 393a20b6 authored by Elvis Angelaccio's avatar Elvis Angelaccio
Browse files

Parse .desktop files using KDesktopFile

This replaces the parsing done by QSettings. Since KConfig supports localized
entries out of the box, there is no need anymore for custom code like the overloads
with a language string as argument.

CCBUG: 330010
CCBUG: 358658

Differential Revision: D994
parent 9eca06b5
......@@ -19,6 +19,7 @@ macro(add_unit_test _source)
akonadi_shared
KF5AkonadiPrivate
Qt5::Test
KF5::ConfigCore
${CMAKE_EXE_LINKER_FLAGS_ASAN}
)
endmacro()
......
......@@ -46,15 +46,10 @@ void AgentTypeTest::testLoad_data()
{QStringLiteral("KAccounts"), QStringList {QStringLiteral("google-contacts"), QStringLiteral("google-calendar")}}
};
googleContactsResource.launchMethod = AgentType::Process;
// We just test an UTF-8 entry
googleContactsResource.name = {{QStringLiteral("uk"), QStringLiteral("Контакти Google")}};
googleContactsResource.comment = {
{QStringLiteral("uk"), QStringLiteral("Доступ до ваших записів контактів Google з KDE")},
// Check for unquoted strings containing a comma. See bug #330010
{QStringLiteral("string_with_comma"), QStringLiteral("This is just a QString, not a QStringList")},
{QStringLiteral("quoted_string"), QStringLiteral("This is a QString")},
{QStringLiteral("escaped_quote_string"), QStringLiteral("\"This is a QString\"")}
};
// We test an UTF-8 name within quotes.
googleContactsResource.name = QStringLiteral("\"Контакти Google\"");
// We also check whether an unquoted string with a comma is not parsed as a QStringList. See bug #330010
googleContactsResource.comment = QStringLiteral("Доступ до ваших записів контактів, Google з KDE");
googleContactsResource.icon = QStringLiteral("im-google");
......@@ -70,6 +65,7 @@ void AgentTypeTest::testLoad()
QFETCH(AgentType, expectedAgentType);
AgentType agentType;
QLocale::setDefault(QLocale::Ukrainian);
QVERIFY(agentType.load(fileName, Q_NULLPTR));
QCOMPARE(agentType.exec, expectedAgentType.exec);
......@@ -79,11 +75,9 @@ void AgentTypeTest::testLoad()
QCOMPARE(agentType.identifier, expectedAgentType.identifier);
QCOMPARE(agentType.custom, expectedAgentType.custom);
QCOMPARE(agentType.launchMethod, expectedAgentType.launchMethod);
QCOMPARE(agentType.name.value(QLatin1String("uk")), expectedAgentType.name.value(QLatin1String("uk")));
QCOMPARE(agentType.comment.value(QLatin1String("uk")), expectedAgentType.comment.value(QLatin1String("uk")));
QCOMPARE(agentType.comment.value(QLatin1String("string_with_comma")), expectedAgentType.comment.value(QLatin1String("string_with_comma")));
QCOMPARE(agentType.comment.value(QLatin1String("quoted_string")), expectedAgentType.comment.value(QLatin1String("quoted_string")));
QCOMPARE(agentType.comment.value(QLatin1String("escaped_quote_string")), expectedAgentType.comment.value(QLatin1String("escaped_quote_string")));
QCOMPARE(agentType.name, expectedAgentType.name);
QCOMPARE(agentType.comment, expectedAgentType.comment);
QCOMPARE(agentType.icon, expectedAgentType.icon);
}
AKTEST_MAIN(AgentTypeTest)
......
......@@ -39,7 +39,7 @@ Name[sr@latin]=Googleovi kontakti
Name[sv]=Google kontakter
Name[tr]=Google Kişileri
Name[ug]=Google ئالاقەداشلىرى
Name[uk]=Контакти Google
Name[uk]="Контакти Google"
Name[x-test]=xxGoogle Contactsxx
Name[zh_CN]=Google 联系人
Name[zh_TW]=Google 聯絡人
......@@ -80,13 +80,10 @@ Comment[sr@ijekavianlatin]=Pristupite svojim kontaktima na Googleu iz KDE‑a
Comment[sr@latin]=Pristupite svojim kontaktima na Googleu iz KDE‑a
Comment[sv]=Kom åt Google kontakter från KDE
Comment[tr]=Google Kişilerinize KDE'den erişin
Comment[uk]=Доступ до ваших записів контактів Google з KDE
Comment[uk]=Доступ до ваших записів контактів, Google з KDE
Comment[x-test]=xxAccess your Google Contacts from KDExx
Comment[zh_CN]=在 KDE 中访问您的 Google 联系人
Comment[zh_TW]=用 KDE 存取您的 Google 聯絡人
Comment[string_with_comma]=This is just a QString, not a QStringList
Comment[quoted_string]="This is a QString"
Comment[escaped_quote_string]=\"This is a QString\"
Type=AkonadiResource
Exec=akonadi_googlecontacts_resource
X-Akonadi-MimeTypes=text/directory,
......
......@@ -39,6 +39,7 @@ endif()
target_link_libraries(akonadi_control
akonadi_shared
KF5AkonadiPrivate
KF5::ConfigCore
Qt5::Core
Qt5::DBus
Qt5::Gui
......
......@@ -175,24 +175,22 @@ QStringList AgentManager::agentTypes() const
return mAgents.keys();
}
QString AgentManager::agentName(const QString &identifier, const QString &language) const
QString AgentManager::agentName(const QString &identifier) const
{
if (!checkAgentExists(identifier)) {
return QString();
}
const QString name = mAgents.value(identifier).name.value(language);
return name.isEmpty() ? mAgents.value(identifier).name.value(QStringLiteral("en_US")) : name;
return mAgents.value(identifier).name;
}
QString AgentManager::agentComment(const QString &identifier, const QString &language) const
QString AgentManager::agentComment(const QString &identifier) const
{
if (!checkAgentExists(identifier)) {
return QString();
}
const QString comment = mAgents.value(identifier).comment.value(language);
return comment.isEmpty() ? mAgents.value(identifier).comment.value(QStringLiteral("en_US")) : comment;
return mAgents.value(identifier).comment;
}
QString AgentManager::agentIcon(const QString &identifier) const
......@@ -414,7 +412,7 @@ void AgentManager::setAgentInstanceName(const QString &identifier, const QString
mAgentInstances.value(identifier)->resourceInterface()->setName(name);
}
QString AgentManager::agentInstanceName(const QString &identifier, const QString &language) const
QString AgentManager::agentInstanceName(const QString &identifier) const
{
if (!checkInstance(identifier)) {
return QString();
......@@ -429,8 +427,7 @@ QString AgentManager::agentInstanceName(const QString &identifier, const QString
return QString();
}
const QString name = mAgents.value(instance->agentType()).name.value(language);
return name.isEmpty() ? mAgents.value(instance->agentType()).name.value(QStringLiteral("en_US")) : name;
return mAgents.value(instance->agentType()).name;
}
void AgentManager::agentInstanceSynchronize(const QString &identifier)
......
......@@ -75,15 +75,15 @@ public Q_SLOTS:
/**
* Returns the i18n'ed name of the agent type for
* the given @p identifier and the given @p language.
* the given @p identifier.
*/
QString agentName(const QString &identifier, const QString &language = QStringLiteral("en_US")) const;
QString agentName(const QString &identifier) const;
/**
* Returns the i18n'ed comment of the agent type for
* the given @p identifier and the given @p language.
* the given @p identifier..
*/
QString agentComment(const QString &identifier, const QString &language = QStringLiteral("en_US")) const;
QString agentComment(const QString &identifier) const;
/**
* Returns the icon name of the agent type for the
......@@ -166,10 +166,8 @@ public Q_SLOTS:
/**
* Returns the name of the agent instance with the given @p identifier.
* If there is no name, it returns the default name of the agent, you can tweak
* the language for that name with the @p language setting.
*/
QString agentInstanceName(const QString &identifier, const QString &language = QStringLiteral("en_US")) const;
QString agentInstanceName(const QString &identifier) const;
/**
* Triggers the agent instance with the given @p identifier to show
......
......@@ -25,7 +25,8 @@
#include <shared/akdebug.h>
#include <QSettings>
#include <KConfigGroup>
#include <KDesktopFile>
using namespace Akonadi;
......@@ -41,58 +42,34 @@ AgentType::AgentType()
{
}
QString AgentType::readString(const QSettings &file, const QString &key)
{
const QVariant value = file.value(key);
if (value.isNull()) {
return QString();
} else if (value.canConvert<QString>()) {
return value.toString();
} else if (value.canConvert<QStringList>()) {
// This is a workaround for QSettings interpreting value with a comma as
// a QStringList, which is not compatible with KConfig. KConfig reads everything
// as a QByteArray and splits it to a list when requested. See BKO#330010
// TODO KF5: If we end up in Tier 2 or above, depend on KConfig for parsing
// .desktop files
return value.toStringList().join(QStringLiteral(", "));
} else {
akError() << "Agent desktop file" << file.fileName() << "contains invalid value for key" << key;
return QString();
}
}
bool AgentType::load(const QString &fileName, AgentManager *manager)
{
Q_UNUSED(manager);
QSettings file(fileName, QSettings::IniFormat);
file.setIniCodec("UTF-8");
file.beginGroup(QStringLiteral("Desktop Entry"));
Q_FOREACH (const QString &key, file.allKeys()) {
if (key.startsWith(QLatin1String("Name["))) {
QString lang = key.mid(5, key.length() - 6);
name.insert(lang, readString(file, key));
} else if (key == QLatin1String("Name")) {
name.insert(QStringLiteral("en_US"), readString(file, key));
} else if (key.startsWith(QLatin1String("Comment["))) {
QString lang = key.mid(8, key.length() - 9);
comment.insert(lang, readString(file, key));
} else if (key == QLatin1String("Comment")) {
comment.insert(QStringLiteral("en_US"), readString(file, key));
} else if (key.startsWith(QLatin1String("X-Akonadi-Custom-"))) {
if (!KDesktopFile::isDesktopFile(fileName)) {
return false;
}
KDesktopFile desktopFile(fileName);
KConfigGroup group = desktopFile.desktopGroup();
Q_FOREACH (const QString &key, group.keyList()) {
if (key.startsWith(QLatin1String("X-Akonadi-Custom-"))) {
QString customKey = key.mid(17, key.length());
custom[customKey] = file.value(key);
custom[customKey] = group.readEntry(key, QStringList());
}
}
icon = file.value(QStringLiteral("Icon")).toString();
mimeTypes = file.value(QStringLiteral("X-Akonadi-MimeTypes")).toStringList();
capabilities = file.value(QStringLiteral("X-Akonadi-Capabilities")).toStringList();
exec = file.value(QStringLiteral("Exec")).toString();
identifier = file.value(QStringLiteral("X-Akonadi-Identifier")).toString();
name = desktopFile.readName();
comment = desktopFile.readComment();
icon = desktopFile.readIcon();
mimeTypes = group.readEntry(QStringLiteral("X-Akonadi-MimeTypes"), QStringList());
capabilities = group.readEntry(QStringLiteral("X-Akonadi-Capabilities"), QStringList());
exec = group.readEntry(QStringLiteral("Exec"));
identifier = group.readEntry(QStringLiteral("X-Akonadi-Identifier"));
launchMethod = Process; // Save default
const QString method = file.value(QStringLiteral("X-Akonadi-LaunchMethod")).toString();
const QString method = group.readEntry(QStringLiteral("X-Akonadi-LaunchMethod"));
if (method.compare(QLatin1String("AgentProcess"), Qt::CaseInsensitive) == 0) {
launchMethod = Process;
} else if (method.compare(QLatin1String("AgentServer"), Qt::CaseInsensitive) == 0) {
......@@ -103,8 +80,6 @@ bool AgentType::load(const QString &fileName, AgentManager *manager)
akError() << Q_FUNC_INFO << "Invalid exec method:" << method << "falling back to AgentProcess";
}
file.endGroup();
if (identifier.isEmpty()) {
akError() << Q_FUNC_INFO << "Agent desktop file" << fileName << "contains empty identifier";
return false;
......
......@@ -47,8 +47,8 @@ public:
void save(QSettings *config) const;
QString identifier;
QHash<QString, QString> name;
QHash<QString, QString> comment;
QString name;
QString comment;
QString icon;
QStringList mimeTypes;
QStringList capabilities;
......
......@@ -222,16 +222,10 @@ void AgentManagerPrivate::readAgentInstances()
AgentType AgentManagerPrivate::fillAgentType(const QString &identifier) const
{
const QStringList name = QLocale().name().split(QLatin1Char('_'));
QString lang;
if (name.size() == 2) {
lang = name[0];
}
AgentType type;
type.d->mIdentifier = identifier;
type.d->mName = mManager->agentName(identifier, lang);
type.d->mDescription = mManager->agentComment(identifier, lang);
type.d->mName = mManager->agentName(identifier);
type.d->mDescription = mManager->agentComment(identifier);
type.d->mIconName = mManager->agentIcon(identifier);
type.d->mMimeTypes = mManager->agentMimeTypes(identifier);
type.d->mCapabilities = mManager->agentCapabilities(identifier);
......
......@@ -52,19 +52,9 @@
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentName">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
<arg name="language" type="s" direction="in"/>
</method>
<method name="agentComment">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentComment">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
<arg name="language" type="s" direction="in"/>
</method>
<method name="agentIcon">
<arg type="s" direction="out"/>
......@@ -121,11 +111,6 @@
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceName">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
<arg name="language" type="s" direction="in"/>
</method>
<method name="agentInstanceConfigure">
<arg name="identifier" type="s" direction="in"/>
<arg name="windowId" type="x" direction="in"/>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment