kde-extraapps/kdevelop/languages/plugins/custom-definesandincludes/compilerprovider/settingsmanager.cpp
2015-07-26 14:23:17 +03:00

302 lines
9.3 KiB
C++

/*
* This file is part of KDevelop
*
* Copyright 2010 Andreas Pakulat <apaku@gmx.de>
* Copyright 2014 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "settingsmanager.h"
#include <KConfig>
#include <KConfigGroup>
#include <interfaces/iproject.h>
#include <interfaces/icore.h>
#include <interfaces/iplugincontroller.h>
#include "compilerprovider.h"
using namespace KDevelop;
namespace ConfigConstants
{
const QString configKey = QLatin1String( "CustomDefinesAndIncludes" );
const QString definesKey = QLatin1String( "Defines" );
const QString includesKey = QLatin1String( "Includes" );
const QString projectPathPrefix = QLatin1String( "ProjectPath" );
const QString projectPathKey = QLatin1String( "Path" );
const QString customBuildSystemGroup = QLatin1String( "CustomBuildSystem" );
const QString definesAndIncludesGroup = QLatin1String( "Defines And Includes" );
const QString compilersGroup = QLatin1String( "Compilers" );
const QString compilerNameKey = QLatin1String( "Name" );
const QString compilerPathKey = QLatin1String( "Path" );
const QString compilerTypeKey = QLatin1String( "Type" );
}
namespace
{
void doWriteSettings( KConfigGroup grp, const QList<ConfigEntry>& paths )
{
int pathIndex = 0;
for ( const auto& path : paths ) {
KConfigGroup pathgrp = grp.group( ConfigConstants::projectPathPrefix + QString::number( pathIndex++ ) );
pathgrp.writeEntry( ConfigConstants::projectPathKey, path.path );
{
QByteArray tmp;
QDataStream s( &tmp, QIODevice::WriteOnly );
s.setVersion( QDataStream::Qt_4_5 );
s << path.includes;
pathgrp.writeEntry( ConfigConstants::includesKey, tmp );
}
{
QByteArray tmp;
QDataStream s( &tmp, QIODevice::WriteOnly );
s.setVersion( QDataStream::Qt_4_5 );
// backwards compatible writing
QHash<QString, QVariant> defines;
defines.reserve(path.defines.size());
for (auto it = path.defines.begin(); it != path.defines.end(); ++it) {
defines[it.key()] = it.value();
}
s << defines;
pathgrp.writeEntry( ConfigConstants::definesKey, tmp );
}
}
}
/// @param remove if true all read entries will be removed from the config file
QList<ConfigEntry> doReadSettings( KConfigGroup grp, bool remove = false )
{
QList<ConfigEntry> paths;
for( const QString &grpName : grp.groupList() ) {
if ( grpName.startsWith( ConfigConstants::projectPathPrefix ) ) {
KConfigGroup pathgrp = grp.group( grpName );
ConfigEntry path;
path.path = pathgrp.readEntry( ConfigConstants::projectPathKey, "" );
{
QByteArray tmp = pathgrp.readEntry( ConfigConstants::definesKey, QByteArray() );
QDataStream s( tmp );
s.setVersion( QDataStream::Qt_4_5 );
// backwards compatible reading
QHash<QString, QVariant> defines;
s >> defines;
path.setDefines(defines);
}
{
QByteArray tmp = pathgrp.readEntry( ConfigConstants::includesKey, QByteArray() );
QDataStream s( tmp );
s.setVersion( QDataStream::Qt_4_5 );
s >> path.includes;
}
if ( remove ) {
pathgrp.deleteGroup();
}
paths << path;
}
}
return paths;
}
/**
* Reads and converts paths from old (Custom Build System's) format to the current one.
* @return all converted paths (if any)
*/
QList<ConfigEntry> convertedPaths( KConfig* cfg )
{
KConfigGroup group = cfg->group( ConfigConstants::customBuildSystemGroup );
if ( !group.isValid() )
return {};
QList<ConfigEntry> paths;
foreach( const QString &grpName, group.groupList() ) {
KConfigGroup subgroup = group.group( grpName );
if ( !subgroup.isValid() )
continue;
paths += doReadSettings( subgroup, true );
}
return paths;
}
}
void ConfigEntry::setDefines(const QHash<QString, QVariant>& newDefines)
{
defines.clear();
defines.reserve(newDefines.size());
for (auto it = newDefines.begin(); it != newDefines.end(); ++it) {
defines[it.key()] = it.value().toString();
}
}
SettingsManager* SettingsManager::s_globalInstance = nullptr;
SettingsManager::SettingsManager(bool globalInstance)
: m_provider(this)
{
if (globalInstance) {
Q_ASSERT(!s_globalInstance);
s_globalInstance = this;
}
}
SettingsManager::~SettingsManager()
{
if (s_globalInstance == this) {
s_globalInstance = nullptr;
}
}
SettingsManager* SettingsManager::globalInstance()
{
Q_ASSERT(s_globalInstance);
return s_globalInstance;
}
CompilerProvider* SettingsManager::provider()
{
return &m_provider;
}
const CompilerProvider* SettingsManager::provider() const
{
return &m_provider;
}
void SettingsManager::writePaths( KConfig* cfg, const QList< ConfigEntry >& paths )
{
KConfigGroup grp = cfg->group( ConfigConstants::configKey );
if ( !grp.isValid() )
return;
grp.deleteGroup();
doWriteSettings( grp, paths );
}
QList<ConfigEntry> SettingsManager::readPaths( KConfig* cfg ) const
{
auto converted = convertedPaths( cfg );
if ( !converted.isEmpty() ) {
const_cast<SettingsManager*>(this)->writePaths( cfg, converted );
return converted;
}
KConfigGroup grp = cfg->group( ConfigConstants::configKey );
if ( !grp.isValid() ) {
return {};
}
return doReadSettings( grp );
}
CompilerPointer SettingsManager::currentCompiler( KConfig* cfg, const CompilerPointer& defaultCompiler ) const
{
auto grp = cfg->group( ConfigConstants::definesAndIncludesGroup ).group("Compiler");
auto name = grp.readEntry( ConfigConstants::compilerNameKey, QString() );
if (name.isEmpty()) {
return {};
}
for (auto c : m_provider.compilers()) {
if (c->name() == name) {
return c;
}
}
auto path = grp.readEntry( ConfigConstants::compilerPathKey, QString() );
auto type = grp.readEntry( ConfigConstants::compilerTypeKey, QString() );
auto cf = m_provider.compilerFactories();
for (auto f : cf) {
if (f->name() == type) {
return f->createCompiler(name, path, true);
}
}
return defaultCompiler;
}
bool SettingsManager::needToReparseCurrentProject( KConfig* cfg ) const
{
auto grp = cfg->group( ConfigConstants::definesAndIncludesGroup );
return grp.readEntry( "reparse", true );
}
void SettingsManager::writeCurrentCompiler(KConfig* cfg, const CompilerPointer& compiler)
{
auto grp = cfg->group(ConfigConstants::definesAndIncludesGroup).group("Compiler");
grp.writeEntry(ConfigConstants::compilerNameKey, compiler->name());
grp.writeEntry(ConfigConstants::compilerPathKey, compiler->path());
grp.writeEntry(ConfigConstants::compilerTypeKey, compiler->factoryName());
}
void SettingsManager::writeUserDefinedCompilers(const QVector< CompilerPointer >& compilers)
{
QVector< CompilerPointer > editableCompilers;
for (const auto& compiler : compilers) {
if (!compiler->editable()) {
continue;
}
editableCompilers.append(compiler);
}
KConfigGroup config = KGlobal::config()->group(ConfigConstants::compilersGroup);
config.deleteGroup();
config.writeEntry("number", editableCompilers.count());
int i = 0;
for (const auto& compiler : editableCompilers) {
KConfigGroup grp = config.group(QString::number(i));
++i;
grp.writeEntry(ConfigConstants::compilerNameKey, compiler->name());
grp.writeEntry(ConfigConstants::compilerPathKey, compiler->path());
grp.writeEntry(ConfigConstants::compilerTypeKey, compiler->factoryName());
}
config.sync();
}
QVector< CompilerPointer > SettingsManager::userDefinedCompilers() const
{
QVector< CompilerPointer > compilers;
KConfigGroup config = KGlobal::config()->group(ConfigConstants::compilersGroup);
int count = config.readEntry("number", 0);
for (int i = 0; i < count; i++) {
KConfigGroup grp = config.group(QString::number(i));
auto name = grp.readEntry(ConfigConstants::compilerNameKey, QString());
auto path = grp.readEntry(ConfigConstants::compilerPathKey, QString());
auto type = grp.readEntry(ConfigConstants::compilerTypeKey, QString());
auto cf = m_provider.compilerFactories();
for (auto f : cf) {
if (f->name() == type) {
compilers.append(f->createCompiler(name, path));
}
}
}
return compilers;
}