1/* This file is part of the KDE project
2 Copyright (C) 2007, 2008 David Faure <faure@kde.org>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License or ( at
7 your option ) version 3 or, at the discretion of KDE e.V. ( which shall
8 act as a proxy as in section 14 of the GPLv3 ), any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "mimetypewriter.h"
22#include <kmimetype.h>
23
24#include <kdebug.h>
25#include <kdeversion.h>
26#include <kprocess.h>
27#include <kstandarddirs.h>
28
29#include <QXmlStreamWriter>
30#include <QFile>
31
32/// WARNING: this code is duplicated between apps/nsplugins and runtime/filetypes
33
34static bool sharedMimeInfoSupportsIcon()
35{
36 return KMimeType::sharedMimeInfoVersion() >= KDE_MAKE_VERSION(0, 40, 0);
37}
38
39class MimeTypeWriterPrivate
40{
41public:
42 QString localFilePath() const;
43
44 QString m_mimeType;
45 QString m_comment;
46 QString m_iconName;
47 QStringList m_patterns;
48 QString m_marker;
49};
50
51MimeTypeWriter::MimeTypeWriter(const QString& mimeType)
52 : d(new MimeTypeWriterPrivate)
53{
54 d->m_mimeType = mimeType;
55 Q_ASSERT(!mimeType.isEmpty());
56}
57
58MimeTypeWriter::~MimeTypeWriter()
59{
60 delete d;
61}
62
63void MimeTypeWriter::setComment(const QString& comment)
64{
65 d->m_comment = comment;
66}
67
68void MimeTypeWriter::setPatterns(const QStringList& patterns)
69{
70 d->m_patterns = patterns;
71}
72
73void MimeTypeWriter::setIconName(const QString& iconName)
74{
75 d->m_iconName = iconName;
76}
77
78void MimeTypeWriter::setMarker(const QString& marker)
79{
80 d->m_marker = marker;
81}
82
83bool MimeTypeWriter::write()
84{
85 const QString packageFileName = d->localFilePath();
86 kDebug() << "writing" << packageFileName;
87 QFile packageFile(packageFileName);
88 if (!packageFile.open(QIODevice::WriteOnly)) {
89 kError() << "Couldn't open" << packageFileName << "for writing";
90 return false;
91 }
92 QXmlStreamWriter writer(&packageFile);
93 writer.setAutoFormatting(true);
94 writer.writeStartDocument();
95 if (!d->m_marker.isEmpty()) {
96 writer.writeComment(d->m_marker);
97 }
98 const QString nsUri = "http://www.freedesktop.org/standards/shared-mime-info";
99 writer.writeDefaultNamespace(nsUri);
100 writer.writeStartElement("mime-info");
101 writer.writeStartElement(nsUri, "mime-type");
102 writer.writeAttribute("type", d->m_mimeType);
103
104 if (!d->m_comment.isEmpty()) {
105 writer.writeStartElement(nsUri, "comment");
106 writer.writeCharacters(d->m_comment);
107 writer.writeEndElement(); // comment
108 }
109
110 if (!d->m_iconName.isEmpty()) {
111 // User-specified icon name
112 if (sharedMimeInfoSupportsIcon()) {
113 writer.writeStartElement(nsUri, "icon");
114 writer.writeAttribute("name", d->m_iconName);
115 writer.writeEndElement(); // icon
116 }
117 }
118
119 // Allow this local definition to override the global definition
120 writer.writeStartElement(nsUri, "glob-deleteall");
121 writer.writeEndElement(); // glob-deleteall
122
123 foreach(const QString& pattern, d->m_patterns) {
124 writer.writeStartElement(nsUri, "glob");
125 writer.writeAttribute("pattern", pattern);
126 writer.writeEndElement(); // glob
127 }
128
129 writer.writeEndElement(); // mime-info
130 writer.writeEndElement(); // mime-type
131 writer.writeEndDocument();
132 return true;
133}
134
135void MimeTypeWriter::runUpdateMimeDatabase()
136{
137 const QString localPackageDir = KStandardDirs::locateLocal("xdgdata-mime", QString());
138 Q_ASSERT(!localPackageDir.isEmpty());
139 KProcess proc;
140 proc << "update-mime-database";
141 proc << localPackageDir;
142 const int exitCode = proc.execute();
143 if (exitCode) {
144 kWarning() << proc.program() << "exited with error code" << exitCode;
145 }
146}
147
148QString MimeTypeWriterPrivate::localFilePath() const
149{
150 // XDG shared mime: we must write into a <kdehome>/share/mime/packages/ file...
151 // To simplify our job, let's use one "input" file per mimetype, in the user's dir.
152 // (this writes into $HOME/.local/share/mime by default)
153 //
154 // We could also use Override.xml, says the spec, but then we'd need to merge with other mimetypes,
155 // and in ~/.local we don't really expect other packages to be installed anyway...
156 QString baseName = m_mimeType;
157 baseName.replace('/', '-');
158 return KStandardDirs::locateLocal( "xdgdata-mime", "packages/" + baseName + ".xml" );
159}
160
161static QString existingDefinitionFile(const QString& mimeType)
162{
163 QString baseName = mimeType;
164 baseName.replace('/', '-');
165 return KGlobal::dirs()->findResource( "xdgdata-mime", "packages/" + baseName + ".xml" );
166}
167
168bool MimeTypeWriter::hasDefinitionFile(const QString& mimeType)
169{
170 return !existingDefinitionFile(mimeType).isEmpty();
171}
172
173void MimeTypeWriter::removeOwnMimeType(const QString& mimeType)
174{
175 const QString file = existingDefinitionFile(mimeType);
176 Q_ASSERT(!file.isEmpty());
177 QFile::remove(file);
178 // We must also remove the generated XML file, update-mime-database doesn't do that, for unknown media types
179 QString xmlFile = KGlobal::dirs()->findResource( "xdgdata-mime", mimeType + ".xml" );
180 QFile::remove(xmlFile);
181}
182
183/// WARNING: this code is duplicated between apps/nsplugins and runtime/filetypes
184