Fix no newlines warnings. Patch by Peter Oberndorfer
[kdevelopdvcssupport.git] / util / sourceformattermanager.cpp
blobf01ed2ebee6533ef9725c4373460305d78524f4b
1 /* This file is part of KDevelop
2 Copyright (C) 2008 Cédric Pasteur <cedric.pasteur@free.fr>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "sourceformattermanager.h"
22 #include <QVariant>
23 #include <QStringList>
24 #include <QRegExp>
25 #include <KPluginInfo>
26 #include <KDebug>
28 #include <interfaces/icore.h>
29 #include <interfaces/iplugincontroller.h>
30 #include <interfaces/ilanguagecontroller.h>
31 #include <language/interfaces/ilanguagesupport.h>
32 #include "interfaces/isourceformatter.h"
34 SourceFormatterManager* SourceFormatterManager::m_instance = 0;
36 SourceFormatterManager::SourceFormatterManager(QObject *parent)
37 : QObject(parent), m_modelinesEnabled(false)
39 loadPlugins();
40 m_rootConfigGroup = KGlobal::config()->group("SourceFormatter");
43 SourceFormatterManager::~SourceFormatterManager()
47 SourceFormatterManager* SourceFormatterManager::self()
49 if (!m_instance)
50 m_instance = new SourceFormatterManager();
51 return m_instance;
54 void SourceFormatterManager::loadPlugins()
56 KDevelop::IPluginController *controller = KDevelop::ICore::self()->pluginController();
58 foreach(KDevelop::IPlugin *p,
59 controller->allPluginsForExtension("org.kdevelop.ISourceFormatter")) {
60 KPluginInfo info = controller->pluginInfo(p);
61 QVariant mimes = info.property("X-KDevelop-SupportedMimeTypes");
62 kDebug() << "Found plugin " << info.name() << " for mimes " << mimes << endl;
64 QStringList mimeTypes = mimes.toStringList();
65 foreach(QString s, mimeTypes) {
66 QString lang = languageNameFromLanguageSupport(s);
67 QList<KDevelop::IPlugin*> &list = m_plugins[lang];
68 if (!list.contains(p))
69 list.append(p);
70 kDebug() << "Loading plugin " << info.name() << " for type " << s
71 << " and lang " << lang << endl;
76 KDevelop::IPlugin*
77 SourceFormatterManager::languageSupportForMimeType(const QString &name)
79 KDevelop::IPluginController *controller = KDevelop::ICore::self()->pluginController();
80 QStringList constraints;
81 constraints << QString("'%1' in [X-KDevelop-SupportedMimeTypes]").arg(name);
83 QList<KDevelop::IPlugin*> list = controller->allPluginsForExtension("ILanguageSupport", constraints);
84 foreach(KDevelop::IPlugin *p, list)
85 return p;
87 return 0;
90 QString SourceFormatterManager::languageNameFromLanguageSupport(const QString &name)
92 if (m_languages.contains(name))
93 return m_languages[name];
95 // we're loading the plugin, find the name from the language support plugin
96 KDevelop::IPlugin *p = languageSupportForMimeType(name);
97 if (p) {
98 KDevelop::ILanguageSupport *languageSupport = p->extension<KDevelop::ILanguageSupport>();
99 if (languageSupport) {
100 m_languages.insert(name, languageSupport->name());
101 return languageSupport->name();
104 // temp to support languages with no language support
105 m_languages.insert(name, name);
106 return name;
109 QString SourceFormatterManager::languageNameForMimeType(const KMimeType::Ptr &mime)
111 if (m_languages.contains(mime->name()))
112 return m_languages[mime->name()];
113 return QString();
116 QString SourceFormatterManager::iconForLanguage(const QString &lang)
118 // QString mime = mimeTypeForLanguage(lang);
119 KDevelop::IPlugin *p = KDevelop::ICore::self()
120 ->pluginController()->pluginForExtension("org.kdevelop.ILanguageSupport", lang);//languageForMimeType(mime);
121 if (p) {
122 KPluginInfo info = KDevelop::ICore::self()->pluginController()->pluginInfo(p);
123 return info.icon();
125 return lang;
128 QList<KDevelop::IPlugin*> SourceFormatterManager::pluginListForLanguage(const QString &lang)
130 if (m_plugins.contains(lang))
131 return m_plugins[lang];
132 return QList<KDevelop::IPlugin*>();
135 ISourceFormatter* SourceFormatterManager::activeFormatter()
137 return m_currentPlugins[m_currentLang];
140 ISourceFormatter* SourceFormatterManager::formatterForUrl(const KUrl &url)
142 KMimeType::Ptr mime = KMimeType::findByUrl(url);
143 return formatterForMimeType(mime);
146 ISourceFormatter* SourceFormatterManager::formatterForMimeType(const KMimeType::Ptr &mime)
148 if (!m_languages.contains(mime->name())) //unknown mime type
149 return 0;
151 setActiveLanguage(languageNameForMimeType(mime));
152 kDebug() << "About to format file " << mime->name() << m_currentLang << endl;
153 return formatterForLanguage(m_languages[mime->name()]);
156 bool SourceFormatterManager::isMimeTypeSupported(const KMimeType::Ptr &mime)
158 return m_languages.contains(mime->name());
161 ISourceFormatter* SourceFormatterManager::formatterForLanguage(const QString &language)
163 if (m_currentPlugins.contains(language))
164 return m_currentPlugins[language];
166 // else load the current plugin from config
167 KConfigGroup langGroup = m_rootConfigGroup.group(language);
168 QString formatterName = langGroup.readEntry("Plugin", "");
169 if (formatterName.isEmpty()) { // no formatters defined yet, load the first one
170 KDevelop::IPlugin *p = m_plugins[language].first();
171 if (!p)
172 return 0;
173 m_currentPlugins[language] = p->extension<ISourceFormatter>();
174 } else
175 m_currentPlugins[language] = formatterByName(language, formatterName);
177 return m_currentPlugins[language];
180 ISourceFormatter* SourceFormatterManager::formatterByName(const QString &language, const QString &name)
182 QList<KDevelop::IPlugin*> list = m_plugins[language];
183 foreach(KDevelop::IPlugin *p, list) {
184 if (p) {
185 ISourceFormatter *f = p->extension<ISourceFormatter>();
186 if (f && (f->name() == name))
187 return f;
190 return 0;
193 // void SourceFormatterManager::setFormatterForLanguage(const QString &lang, ISourceFormatter *formatter)
194 // {
195 // m_currentPlugins[lang] = formatter;
196 // }
198 void SourceFormatterManager::setActiveLanguage(const QString &lang, QString plugin)
200 // find the plugin for this language
201 if (plugin.isEmpty()) {
202 if (m_currentLang == lang)
203 return; // no change
204 ISourceFormatter *f = formatterForLanguage(lang);
205 if (f)
206 plugin = f->name();
207 } else
208 m_currentPlugins[lang] = formatterByName(lang, plugin);
209 kDebug() << "Activating language " << lang << " with plugin " << plugin << " == " << m_currentPlugins[lang] << endl;
211 if (plugin.isEmpty())
212 kDebug() << "Cannot find a suitable plugin for language " << lang << endl;
214 // update the plugin entry in config
215 // m_rootConfigGroup.group(lang).writeEntry("Plugin", plugin);
216 m_activeConfigGroup = m_rootConfigGroup.group(lang).group(plugin);
217 m_currentLang = lang;
219 // load the current style for this language
220 QString styleName = m_activeConfigGroup.readEntry("Style", "");
221 if (!styleName.isEmpty() && m_currentPlugins[lang])
222 setCurrentStyle(styleName);
225 QStringList SourceFormatterManager::languages()
227 QStringList list;
228 QHash<QString, QString>::const_iterator it = m_languages.constBegin();
229 for (; it != m_languages.constEnd(); ++it) {
230 if (!list.contains(it.value()))
231 list.append(it.value());
233 return list;
236 QString SourceFormatterManager::mimeTypeForLanguage(const QString &lang)
238 QHash<QString, QString>::const_iterator it = m_languages.constBegin();
239 for (; it != m_languages.constEnd(); ++it) {
240 if (it.value() == lang)
241 return it.key();
243 return QString();
246 void SourceFormatterManager::loadConfig()
248 // reload config that may have been modified by config dialog
249 m_currentPlugins.clear();
250 m_currentLang.clear();
252 m_modelinesEnabled = m_rootConfigGroup.readEntry("ModelinesEnabled",
253 QVariant(false)).toBool();
254 // // load current plugins and styles
255 // foreach(QString l, languages()) {
256 // KConfigGroup langGroup = m_configGroup.group(l);
257 // QString plugin = langGroup.readEntry("Plugin", "");
258 // if(!plugin.isEmpty()) {
259 // KConfigGroup pluginGroup = langGroup.group(plugin);
260 // m_currentPlugins[l] = formatterByName(l, plugin);
261 // // m_currentStyles[l] = pluginGroup.readEntry("Style","");
262 // }
263 // }
266 void SourceFormatterManager::saveConfig()
268 // save current plugins
269 QHash<QString, ISourceFormatter*>::const_iterator it = m_currentPlugins.constBegin();
270 for (; it != m_currentPlugins.constEnd(); ++it) {
271 ISourceFormatter *f = it.value();
272 if(f) {
273 QString pluginName = f->name();
274 m_rootConfigGroup.group(it.key()).writeEntry("Plugin", pluginName);
278 m_rootConfigGroup.writeEntry("ModelinesEnabled", m_modelinesEnabled);
279 m_rootConfigGroup.sync();
282 QString SourceFormatterManager::currentStyle() const
284 return m_currentStyle;
285 // return m_activeConfigGroup.readEntry("Style", "");
288 void SourceFormatterManager::setCurrentStyle(const QString &style)
290 if (!m_currentPlugins[m_currentLang]) {
291 kDebug() << "currrent plugin is null for style " << m_currentLang << style << endl;
292 return;
294 kDebug() << "style is " << style << endl;
296 if (m_activeConfigGroup.hasKey(style)) { // custom style
297 QString content = m_activeConfigGroup.readEntry(style);
298 m_currentPlugins[m_currentLang]->setStyle(QString(), content);
299 } else // predefined style
300 m_currentPlugins[m_currentLang]->setStyle(style);
302 m_currentStyle = style;
303 // m_activeConfigGroup.writeEntry("Style", style);
306 void SourceFormatterManager::saveStyle(const QString &name, const QString &content)
308 m_activeConfigGroup.writeEntry(name, content);
311 void SourceFormatterManager::renameStyle(const QString &name, const QString &caption)
313 m_activeConfigGroup.writeEntry("Caption" + name.mid(4), caption);
316 void SourceFormatterManager::deleteStyle(const QString &name)
318 m_activeConfigGroup.deleteEntry(name);
321 QString SourceFormatterManager::nameForNewStyle()
323 //find available number
324 int idx = 1;
325 QString s = "User" + QString::number(idx);
326 while (m_activeConfigGroup.hasKey(s)) {
327 ++idx;
328 s = "User" + QString::number(idx);
331 return s;
334 QString SourceFormatterManager::indentationMode(const KMimeType::Ptr &mime)
336 if (mime->is("text/x-c++src") || mime->is("text/x-chdr") ||
337 mime->is("text/x-c++hdr") || mime->is("text/x-csrc") ||
338 mime->is("text/x-java") || mime->is("text/x-csharp"))
339 return "cstyle";
340 return "none";
343 QString SourceFormatterManager::addModelineForCurrentLang(QString input, const KMimeType::Ptr &mime)
345 if (!m_currentPlugins[m_currentLang] || !m_modelinesEnabled)
346 return input;
348 QString output;
349 QTextStream os(&output, QIODevice::WriteOnly);
350 QTextStream is(&input, QIODevice::ReadOnly);
352 QString modeline("// kate: ");
353 QString length = QString::number(m_currentPlugins[m_currentLang]->indentationLength());
354 // add indentation style
355 modeline.append("indent-mode ").append(indentationMode(mime)).append("; ");
357 ISourceFormatter::IndentationType type = m_currentPlugins[m_currentLang]->indentationType();
358 if (type == ISourceFormatter::IndentWithTabs) {
359 modeline.append("replace-tabs off; ");
360 modeline.append("tab-width ").append(length).append("; ");
361 } else {
362 modeline.append("space-indent on; ");
363 modeline.append("indent-width ").append(length).append("; ");
364 if (type == ISourceFormatter::IndentWithSpacesAndConvertTabs)
365 modeline.append("replace-tabs on; ");
368 kDebug() << "created modeline: " << modeline << endl;
370 bool modelinefound = false;
371 QRegExp kateModeline("^\\s*//\\s*kate:(.*)$");
372 QRegExp knownOptions("\\s*(indent-width|space-indent|tab-width|indent-mode)");
373 while (!is.atEnd()) {
374 QString line = is.readLine();
375 // replace only the options we care about
376 if (kateModeline.indexIn(line) >= 0) { // match
377 kDebug() << "Found a kate modeline: " << line << endl;
378 modelinefound = true;
379 QString options = kateModeline.cap(1);
380 QStringList optionList = options.split(';', QString::SkipEmptyParts);
382 os << modeline;
383 foreach(QString s, optionList) {
384 if (knownOptions.indexIn(s) < 0) { // unknown option, add it
385 os << s << ";";
386 kDebug() << "Found unknown option: " << s << endl;
389 os << endl;
390 } else
391 os << line << endl;
394 if (!modelinefound)
395 os << modeline << endl;
396 return output;
399 void SourceFormatterManager::setModelinesEnabled(bool enable)
401 m_modelinesEnabled = enable;
404 #include "sourceformattermanager.moc"
406 // kate: indent-mode cstyle; space-indent off; tab-width 4;