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"
23 #include <QStringList>
25 #include <KPluginInfo>
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)
40 m_rootConfigGroup
= KGlobal::config()->group("SourceFormatter");
43 SourceFormatterManager::~SourceFormatterManager()
47 SourceFormatterManager
* SourceFormatterManager::self()
50 m_instance
= new SourceFormatterManager();
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
))
70 kDebug() << "Loading plugin " << info
.name() << " for type " << s
71 << " and lang " << lang
<< endl
;
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
)
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
);
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
);
109 QString
SourceFormatterManager::languageNameForMimeType(const KMimeType::Ptr
&mime
)
111 if (m_languages
.contains(mime
->name()))
112 return m_languages
[mime
->name()];
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);
122 KPluginInfo info
= KDevelop::ICore::self()->pluginController()->pluginInfo(p
);
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
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();
173 m_currentPlugins
[language
] = p
->extension
<ISourceFormatter
>();
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
) {
185 ISourceFormatter
*f
= p
->extension
<ISourceFormatter
>();
186 if (f
&& (f
->name() == name
))
193 // void SourceFormatterManager::setFormatterForLanguage(const QString &lang, ISourceFormatter *formatter)
195 // m_currentPlugins[lang] = formatter;
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
)
204 ISourceFormatter
*f
= formatterForLanguage(lang
);
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()
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());
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
)
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","");
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();
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
;
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
325 QString s
= "User" + QString::number(idx
);
326 while (m_activeConfigGroup
.hasKey(s
)) {
328 s
= "User" + QString::number(idx
);
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"))
343 QString
SourceFormatterManager::addModelineForCurrentLang(QString input
, const KMimeType::Ptr
&mime
)
345 if (!m_currentPlugins
[m_currentLang
] || !m_modelinesEnabled
)
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("; ");
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
);
383 foreach(QString s
, optionList
) {
384 if (knownOptions
.indexIn(s
) < 0) { // unknown option, add it
386 kDebug() << "Found unknown option: " << s
<< endl
;
395 os
<< modeline
<< endl
;
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;