1
/***************************************************************************
2
* Copyright © 2010-2011 Jonathan Thomas <echidnaman@kubuntu.org> *
4
* This program is free software; you can redistribute it and/or *
5
* modify it under the terms of the GNU General Public License as *
6
* published by the Free Software Foundation; either version 2 of *
7
* the License or (at your option) version 3 or any later version *
8
* accepted by the membership of KDE e.V. (or its successor approved *
9
* by the membership of KDE e.V.), which shall act as a proxy *
10
* defined in Section 14 of version 3 of the license. *
12
* This program is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU General Public License for more details. *
17
* You should have received a copy of the GNU General Public License *
18
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
19
***************************************************************************/
21
#include "Application.h"
24
#include <QtCore/QFile>
25
#include <QtCore/QVector>
26
#include <QtCore/QStringList>
29
#include <KIconLoader>
32
#include <KServiceGroup>
36
#include <LibQApt/Backend>
37
#include <LibQApt/Config>
39
Application::Application(const QString &fileName, QApt::Backend *backend)
40
: m_fileName(fileName)
44
, m_isTechnical(false)
46
m_data = desktopContents();
49
Application::Application(QApt::Package *package, QApt::Backend *backend)
57
Application::~Application()
61
QString Application::name()
63
return i18n(untranslatedName().toUtf8());
66
QString Application::untranslatedName()
68
QString name = QString::fromUtf8(getField("Name")).trimmed();
70
// extras.ubuntu.com packages can have this
71
name = package()->controlField(QLatin1String("Appname"));
73
if (!name.isEmpty()) {
74
// Graduate to non-technical, since it has Appname
75
m_isTechnical = false;
80
return package()->shortDescription();
82
return package()->latin1Name();
89
QString Application::comment()
91
QString comment = getField("Comment");
92
if (comment.isEmpty()) {
93
// Sometimes GenericName is used instead of Comment
94
comment = getField("GenericName");
95
if (comment.isEmpty()) {
97
return package()->name();
99
return package()->shortDescription();
104
return i18n(comment.toUtf8());
107
QApt::Package *Application::package()
110
QLatin1String packageName(getField("X-AppInstall-Package").data());
112
m_package = m_backend->package(packageName);
116
// Packages removed from archive will remain in app-install-data until the
117
// next refresh, so we can have valid .desktops with no package
120
// kDebug() << m_fileName;
126
QString Application::icon() const
128
QString icon = getField("Icon");
130
if (icon.isEmpty()) {
131
icon = QLatin1String("applications-other");
137
QString Application::mimetypes() const
139
return getField("MimeType");
142
QString Application::menuPath()
145
QString arrow(QString::fromUtf8(" ➜ "));
147
// Take the file name and remove the .desktop ending
148
QString desktopName = m_fileName.split('/').last().remove(QLatin1String(".desktop")).split(':').first();
149
KService::Ptr service = KService::serviceByDesktopName(desktopName);
150
QVector<QPair<QString, QString> > ret;
153
ret = locateApplication(QString(), service->menuId());
156
if (!ret.isEmpty()) {
157
path.append(QString("<img width=\"16\" heigh=\"16\"src=\"%1\"/>")
158
.arg(KIconLoader::global()->iconPath("kde", KIconLoader::Small)));
159
path.append(QString(" %1 <img width=\"16\" heigh=\"16\" src=\"%2\"/> %3")
161
.arg(KIconLoader::global()->iconPath("applications-other", KIconLoader::Small))
162
.arg(i18n("Applications")));
163
for (int i = 0; i < ret.size(); i++) {
164
path.append(QString(" %1 <img width=\"16\" heigh=\"16\" src=\"%2\"/> %3")
166
.arg(KIconLoader::global()->iconPath(ret.at(i).second, KIconLoader::Small))
167
.arg(ret.at(i).first));
174
QVector<QPair<QString, QString> > Application::locateApplication(const QString &_relPath, const QString &menuId) const
176
QVector<QPair<QString, QString> > ret;
177
KServiceGroup::Ptr root = KServiceGroup::group(_relPath);
179
if (!root || !root->isValid()) {
183
const KServiceGroup::List list = root->entries(false /* sorted */,
184
true /* exclude no display entries */,
185
false /* allow separators */);
187
for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) {
188
const KSycocaEntry::Ptr p = (*it);
190
if (p->isType(KST_KService)) {
191
const KService::Ptr service = KService::Ptr::staticCast(p);
193
if (service->noDisplay()) {
197
if (service->menuId() == menuId) {
198
QPair<QString, QString> pair;
199
pair.first = service->name();
200
pair.second = service->icon();
204
} else if (p->isType(KST_KServiceGroup)) {
205
const KServiceGroup::Ptr serviceGroup = KServiceGroup::Ptr::staticCast(p);
207
if (serviceGroup->noDisplay() || serviceGroup->childCount() == 0) {
211
QVector<QPair<QString, QString> > found;
212
found = locateApplication(serviceGroup->relPath(), menuId);
213
if (!found.isEmpty()) {
214
QPair<QString, QString> pair;
215
pair.first = serviceGroup->caption();
216
pair.second = serviceGroup->icon();
229
QString Application::categories()
231
QString categories = getField("Categories");
233
if (categories.isEmpty()) {
234
// extras.ubuntu.com packages can have this field
235
categories = package()->controlField(QLatin1String("Category"));
237
if (!categories.isEmpty()) {
238
// Graduate to non-technical, since it has Appname
239
m_isTechnical = false;
245
KUrl Application::screenshotUrl(QApt::ScreenshotType type)
249
case QApt::Thumbnail:
250
appUrl = package()->controlField(QLatin1String("Thumbnail-Url"));
252
case QApt::Screenshot:
253
appUrl = package()->controlField(QLatin1String("Screenshot-Url"));
260
if (appUrl.isEmpty()) {
261
url = package()->screenshotUrl(type);
269
QApt::PackageList Application::addons()
271
QApt::PackageList addons;
273
QApt::Package *pkg = package();
278
QStringList tempList;
279
// Only add recommends or suggests to the list if they aren't already going to be
281
if (!m_backend->config()->readEntry("APT::Install-Recommends", true)) {
282
tempList << m_package->recommendsList();
284
if (!m_backend->config()->readEntry("APT::Install-Suggests", false)) {
285
tempList << m_package->suggestsList();
287
tempList << m_package->enhancedByList();
289
QStringList languagePackages;
290
QFile l10nFilterFile("/usr/share/language-selector/data/pkg_depends");
292
if (l10nFilterFile.open(QFile::ReadOnly)) {
293
QString contents = l10nFilterFile.readAll();
295
foreach (const QString &line, contents.split('\n')) {
296
if (line.startsWith(QLatin1Char('#'))) {
299
languagePackages << line.split(':').last();
302
languagePackages.removeAll("");
305
foreach (const QString &addon, tempList) {
306
bool shouldShow = true;
307
QApt::Package *package = m_backend->package(addon);
309
if (!package || package->section().contains("lib") || addons.contains(package)) {
313
foreach (const QString &langpack, languagePackages) {
314
if (addon.contains(langpack)) {
328
bool Application::isValid() const
333
bool Application::isTechnical() const
335
return m_isTechnical;
338
QByteArray Application::getField(const QByteArray &field) const
340
return m_data.value(field);
343
QHash<QByteArray, QByteArray> Application::desktopContents()
345
QHash<QByteArray, QByteArray> contents;
347
QFile file(m_fileName);
348
if (!file.open(QFile::ReadOnly)) {
353
QByteArray buffer = file.readAll();
355
QList<QByteArray> lines = buffer.split('\n');
357
while (lineIndex < lines.size()) {
358
QByteArray line = lines.at(lineIndex);
359
if (line.isEmpty() || line.at(0) == '#') {
364
// Looking for a group heading.
365
if (!m_isValid && line.startsWith('[') && line.contains(']')) {
371
int eqpos = line.indexOf('=');
378
aKey = line.left(eqpos);
379
aValue = line.right(line.size() - eqpos -1);
381
if (!contents.contains(aKey)) {
382
contents[aKey] = aValue;