<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum 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 Lesser General Public License version 3 for more details.
*/

#include "Context.h"

#include <string>
#include <unordered_map>
#include <Utility/Debug.h>
#include <Utility/String.h>

#include "AbstractShaderProgram.h"
#include "AbstractTexture.h"
#include "Buffer.h"
#include "BufferedTexture.h"
#include "Extensions.h"
#include "IndexedMesh.h"
#include "Mesh.h"
#include "Implementation/State.h"
#include "DebugMarker.h"

namespace Magnum {

#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, Version value) {
    switch(value) {
        #define _c(value, string) case Version::value: return debug << string;
        _c(None, "None")
        #ifndef MAGNUM_TARGET_GLES
        _c(GL210, "OpenGL 2.1")
        _c(GL300, "OpenGL 3.0")
        _c(GL310, "OpenGL 3.1")
        _c(GL320, "OpenGL 3.2")
        _c(GL330, "OpenGL 3.3")
        _c(GL400, "OpenGL 4.0")
        _c(GL410, "OpenGL 4.1")
        _c(GL420, "OpenGL 4.2")
        _c(GL430, "OpenGL 4.3")
        #else
        _c(GLES200, "OpenGL ES 2.0")
        _c(GLES300, "OpenGL ES 3.0")
        #endif
        #undef _c
    }

    return debug << "Invalid";
}
#endif

const std::vector<Extension>& Extension::extensions(Version version) {
    #define _extension(prefix, vendor, extension)                           \
        {Extensions::prefix::vendor::extension::Index, Extensions::prefix::vendor::extension::requiredVersion(), Extensions::prefix::vendor::extension::coreVersion(), Extensions::prefix::vendor::extension::string()}
    static const std::vector<Extension> empty;
    #ifndef MAGNUM_TARGET_GLES
    static const std::vector<Extension> extensions{
        _extension(GL,AMD,vertex_shader_layer),
        _extension(GL,AMD,shader_trinary_minmax),
        _extension(GL,EXT,texture_filter_anisotropic),
        _extension(GL,EXT,direct_state_access),
        _extension(GL,GREMEDY,string_marker)};
    static const std::vector<Extension> extensions300{
        _extension(GL,APPLE,flush_buffer_range),
        _extension(GL,APPLE,vertex_array_object),
        _extension(GL,ARB,color_buffer_float),
        _extension(GL,ARB,half_float_pixel),
        _extension(GL,ARB,texture_float),
        _extension(GL,ARB,depth_buffer_float),
        _extension(GL,ARB,texture_rg),
        _extension(GL,EXT,framebuffer_object),
        _extension(GL,EXT,packed_depth_stencil),
        _extension(GL,EXT,framebuffer_blit),
        _extension(GL,EXT,framebuffer_multisample),
        _extension(GL,EXT,gpu_shader4),
        _extension(GL,EXT,packed_float),
        _extension(GL,EXT,texture_array),
        _extension(GL,EXT,texture_compression_rgtc),
        _extension(GL,EXT,texture_shared_exponent),
        _extension(GL,EXT,framebuffer_sRGB),
        _extension(GL,EXT,draw_buffers2),
        _extension(GL,EXT,texture_integer),
        _extension(GL,EXT,transform_feedback),
        _extension(GL,NV,half_float),
        _extension(GL,NV,depth_buffer_float),
        _extension(GL,NV,conditional_render)};
    static const std::vector<Extension> extensions310{
        _extension(GL,ARB,texture_rectangle),
        _extension(GL,ARB,draw_instanced),
        _extension(GL,ARB,texture_buffer_object),
        _extension(GL,ARB,uniform_buffer_object),
        _extension(GL,ARB,copy_buffer),
        _extension(GL,EXT,texture_snorm),
        _extension(GL,NV,primitive_restart)};
    static const std::vector<Extension> extensions320{
        _extension(GL,ARB,geometry_shader4),
        _extension(GL,ARB,depth_clamp),
        _extension(GL,ARB,draw_elements_base_vertex),
        _extension(GL,ARB,fragment_coord_conventions),
        _extension(GL,ARB,provoking_vertex),
        _extension(GL,ARB,seamless_cube_map),
        _extension(GL,ARB,sync),
        _extension(GL,ARB,texture_multisample),
        _extension(GL,ARB,vertex_array_bgra)};
    static const std::vector<Extension> extensions330{
        _extension(GL,ARB,instanced_arrays),
        _extension(GL,ARB,blend_func_extended),
        _extension(GL,ARB,explicit_attrib_location),
        _extension(GL,ARB,occlusion_query2),
        _extension(GL,ARB,sampler_objects),
        _extension(GL,ARB,shader_bit_encoding),
        _extension(GL,ARB,texture_rgb10_a2ui),
        _extension(GL,ARB,texture_swizzle),
        _extension(GL,ARB,timer_query),
        _extension(GL,ARB,vertex_type_2_10_10_10_rev)};
    static const std::vector<Extension> extensions400{
        _extension(GL,ARB,draw_buffers_blend),
        _extension(GL,ARB,sample_shading),
        _extension(GL,ARB,texture_cube_map_array),
        _extension(GL,ARB,texture_gather),
        _extension(GL,ARB,texture_query_lod),
        _extension(GL,ARB,draw_indirect),
        _extension(GL,ARB,gpu_shader5),
        _extension(GL,ARB,gpu_shader_fp64),
        _extension(GL,ARB,shader_subroutine),
        _extension(GL,ARB,tessellation_shader),
        _extension(GL,ARB,texture_buffer_object_rgb32),
        _extension(GL,ARB,transform_feedback2),
        _extension(GL,ARB,transform_feedback3)};
    static const std::vector<Extension> extensions410{
        _extension(GL,ARB,ES2_compatibility),
        _extension(GL,ARB,get_program_binary),
        _extension(GL,ARB,separate_shader_objects),
        _extension(GL,ARB,shader_precision),
        _extension(GL,ARB,vertex_attrib_64bit),
        _extension(GL,ARB,viewport_array)};
    static const std::vector<Extension> extensions420{
        _extension(GL,ARB,texture_compression_bptc),
        _extension(GL,ARB,base_instance),
        _extension(GL,ARB,shading_language_420pack),
        _extension(GL,ARB,transform_feedback_instanced),
        _extension(GL,ARB,compressed_texture_pixel_storage),
        _extension(GL,ARB,conservative_depth),
        _extension(GL,ARB,internalformat_query),
        _extension(GL,ARB,map_buffer_alignment),
        _extension(GL,ARB,shader_atomic_counters),
        _extension(GL,ARB,shader_image_load_store),
        _extension(GL,ARB,texture_storage)};
    static const std::vector<Extension> extensions430{
        _extension(GL,ARB,arrays_of_arrays),
        _extension(GL,ARB,ES3_compatibility),
        _extension(GL,ARB,clear_buffer_object),
        _extension(GL,ARB,compute_shader),
        _extension(GL,ARB,copy_image),
        _extension(GL,KHR,debug),
        _extension(GL,ARB,explicit_uniform_location),
        _extension(GL,ARB,fragment_layer_viewport),
        _extension(GL,ARB,framebuffer_no_attachments),
        _extension(GL,ARB,internalformat_query2),
        _extension(GL,ARB,invalidate_subdata),
        _extension(GL,ARB,multi_draw_indirect),
        _extension(GL,ARB,program_interface_query),
        _extension(GL,ARB,robust_buffer_access_behavior),
        _extension(GL,ARB,shader_image_size),
        _extension(GL,ARB,shader_storage_buffer_object),
        _extension(GL,ARB,stencil_texturing),
        _extension(GL,ARB,texture_buffer_range),
        _extension(GL,ARB,texture_query_levels),
        _extension(GL,ARB,texture_storage_multisample),
        _extension(GL,ARB,texture_view),
        _extension(GL,ARB,vertex_attrib_binding)};
    #undef _extension
    #else
    static const std::vector<Extension> extensions;
    static const std::vector<Extension> extensionsES200;
    static const std::vector<Extension> extensionsES300;
    #endif

    switch(version) {
        case Version::None:  return extensions;
        #ifndef MAGNUM_TARGET_GLES
        case Version::GL210: return empty;
        case Version::GL300: return extensions300;
        case Version::GL310: return extensions310;
        case Version::GL320: return extensions320;
        case Version::GL330: return extensions330;
        case Version::GL400: return extensions400;
        /* case Version::GLES200: */
        case Version::GL410: return extensions410;
        case Version::GL420: return extensions420;
        /* case Version::GLES300: */
        case Version::GL430: return extensions430;
        #else
        case Version::GLES200: return extensionsES200;
        case Version::GLES300: return extensionsES300;
        #endif
    }

    return empty;
}

Context* Context::_current = nullptr;

Context::Context() {
    /* Version */
    #ifndef MAGNUM_TARGET_GLES2
    glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion);
    glGetIntegerv(GL_MINOR_VERSION, &_minorVersion);
    #else
    _majorVersion = 2;
    _minorVersion = 0;
    #endif
    _version = static_cast<Version>(_majorVersion*100+_minorVersion*10);

    /* Get first future (not supported) version */
    std::vector<Version> versions{
        #ifndef MAGNUM_TARGET_GLES
        Version::GL300,
        Version::GL310,
        Version::GL320,
        Version::GL330,
        Version::GL400,
        Version::GL410,
        Version::GL420,
        Version::GL430,
        #else
        Version::GLES200,
        Version::GLES300,
        #endif
        Version::None
    };
    std::size_t future = 0;
    while(versions[future] != Version::None && !isVersionSupported(_version))
        ++future;

    /* List of extensions from future versions (extensions from current and
       previous versions should be supported automatically, so we don't need
       to check for them) */
    std::unordered_map<std::string, Extension> futureExtensions;
    for(std::size_t i = future; i != versions.size(); ++i)
        for(const Extension& extension: Extension::extensions(versions[i]))
            futureExtensions.insert(std::make_pair(extension._string, extension));

    /* Check for presence of extensions in future versions */
    #ifndef MAGNUM_TARGET_GLES
    if(isVersionSupported(Version::GL300)) {
    #else
    if(isVersionSupported(Version::GLES300)) {
    #endif
        #ifndef MAGNUM_TARGET_GLES2
        GLuint index = 0;
        const char* extension;
        while((extension = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, index++)))) {
            auto found = futureExtensions.find(extension);
            if(found != futureExtensions.end()) {
                _supportedExtensions.push_back(found->second);
                extensionStatus.set(found->second._index);
            }
        }
        #endif

    /* OpenGL 2.1 / OpenGL ES 2.0 doesn't have glGetStringi() */
    } else {
        /* Don't crash when glGetString() returns nullptr */
        const char* e = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
        if(e) {
            std::vector<std::string> extensions = Corrade::Utility::String::split(e, ' ');
            for(const std::string& extension: extensions) {
                auto found = futureExtensions.find(extension);
                if(found != futureExtensions.end()) {
                    _supportedExtensions.push_back(found->second);
                    extensionStatus.set(found->second._index);
                }
            }
        }
    }

    /* Set this context as current */
    CORRADE_ASSERT(!_current, "Context: Another context currently active", );
    _current = this;

    /* Initialize state tracker */
    _state = new Implementation::State;

    /* Initialize functionality based on current OpenGL version and extensions */
    AbstractShaderProgram::initializeContextBasedFunctionality(this);
    AbstractTexture::initializeContextBasedFunctionality(this);
    Buffer::initializeContextBasedFunctionality(this);
    #ifndef MAGNUM_TARGET_GLES
    BufferedTexture::initializeContextBasedFunctionality(this);
    #endif
    DebugMarker::initializeContextBasedFunctionality(this);
    IndexedMesh::initializeContextBasedFunctionality(this);
    Mesh::initializeContextBasedFunctionality(this);
}

Context::~Context() {
    CORRADE_ASSERT(_current == this, "Context: Cannot destroy context which is not currently active", );
    delete _state;
    _current = nullptr;
}

Version Context::supportedVersion(std::initializer_list<Version> versions) const {
    for(auto version: versions)
        if(isVersionSupported(version)) return version;

    #ifndef MAGNUM_TARGET_GLES
    return Version::GL210;
    #else
    return Version::GLES200;
    #endif
}

}
<commit_msg>Context initialization was not skipping surely supported extensions.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum 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 Lesser General Public License version 3 for more details.
*/

#include "Context.h"

#include <string>
#include <unordered_map>
#include <Utility/Debug.h>
#include <Utility/String.h>

#include "AbstractShaderProgram.h"
#include "AbstractTexture.h"
#include "Buffer.h"
#include "BufferedTexture.h"
#include "Extensions.h"
#include "IndexedMesh.h"
#include "Mesh.h"
#include "Implementation/State.h"
#include "DebugMarker.h"

namespace Magnum {

#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, Version value) {
    switch(value) {
        #define _c(value, string) case Version::value: return debug << string;
        _c(None, "None")
        #ifndef MAGNUM_TARGET_GLES
        _c(GL210, "OpenGL 2.1")
        _c(GL300, "OpenGL 3.0")
        _c(GL310, "OpenGL 3.1")
        _c(GL320, "OpenGL 3.2")
        _c(GL330, "OpenGL 3.3")
        _c(GL400, "OpenGL 4.0")
        _c(GL410, "OpenGL 4.1")
        _c(GL420, "OpenGL 4.2")
        _c(GL430, "OpenGL 4.3")
        #else
        _c(GLES200, "OpenGL ES 2.0")
        _c(GLES300, "OpenGL ES 3.0")
        #endif
        #undef _c
    }

    return debug << "Invalid";
}
#endif

const std::vector<Extension>& Extension::extensions(Version version) {
    #define _extension(prefix, vendor, extension)                           \
        {Extensions::prefix::vendor::extension::Index, Extensions::prefix::vendor::extension::requiredVersion(), Extensions::prefix::vendor::extension::coreVersion(), Extensions::prefix::vendor::extension::string()}
    static const std::vector<Extension> empty;
    #ifndef MAGNUM_TARGET_GLES
    static const std::vector<Extension> extensions{
        _extension(GL,AMD,vertex_shader_layer),
        _extension(GL,AMD,shader_trinary_minmax),
        _extension(GL,EXT,texture_filter_anisotropic),
        _extension(GL,EXT,direct_state_access),
        _extension(GL,GREMEDY,string_marker)};
    static const std::vector<Extension> extensions300{
        _extension(GL,APPLE,flush_buffer_range),
        _extension(GL,APPLE,vertex_array_object),
        _extension(GL,ARB,color_buffer_float),
        _extension(GL,ARB,half_float_pixel),
        _extension(GL,ARB,texture_float),
        _extension(GL,ARB,depth_buffer_float),
        _extension(GL,ARB,texture_rg),
        _extension(GL,EXT,framebuffer_object),
        _extension(GL,EXT,packed_depth_stencil),
        _extension(GL,EXT,framebuffer_blit),
        _extension(GL,EXT,framebuffer_multisample),
        _extension(GL,EXT,gpu_shader4),
        _extension(GL,EXT,packed_float),
        _extension(GL,EXT,texture_array),
        _extension(GL,EXT,texture_compression_rgtc),
        _extension(GL,EXT,texture_shared_exponent),
        _extension(GL,EXT,framebuffer_sRGB),
        _extension(GL,EXT,draw_buffers2),
        _extension(GL,EXT,texture_integer),
        _extension(GL,EXT,transform_feedback),
        _extension(GL,NV,half_float),
        _extension(GL,NV,depth_buffer_float),
        _extension(GL,NV,conditional_render)};
    static const std::vector<Extension> extensions310{
        _extension(GL,ARB,texture_rectangle),
        _extension(GL,ARB,draw_instanced),
        _extension(GL,ARB,texture_buffer_object),
        _extension(GL,ARB,uniform_buffer_object),
        _extension(GL,ARB,copy_buffer),
        _extension(GL,EXT,texture_snorm),
        _extension(GL,NV,primitive_restart)};
    static const std::vector<Extension> extensions320{
        _extension(GL,ARB,geometry_shader4),
        _extension(GL,ARB,depth_clamp),
        _extension(GL,ARB,draw_elements_base_vertex),
        _extension(GL,ARB,fragment_coord_conventions),
        _extension(GL,ARB,provoking_vertex),
        _extension(GL,ARB,seamless_cube_map),
        _extension(GL,ARB,sync),
        _extension(GL,ARB,texture_multisample),
        _extension(GL,ARB,vertex_array_bgra)};
    static const std::vector<Extension> extensions330{
        _extension(GL,ARB,instanced_arrays),
        _extension(GL,ARB,blend_func_extended),
        _extension(GL,ARB,explicit_attrib_location),
        _extension(GL,ARB,occlusion_query2),
        _extension(GL,ARB,sampler_objects),
        _extension(GL,ARB,shader_bit_encoding),
        _extension(GL,ARB,texture_rgb10_a2ui),
        _extension(GL,ARB,texture_swizzle),
        _extension(GL,ARB,timer_query),
        _extension(GL,ARB,vertex_type_2_10_10_10_rev)};
    static const std::vector<Extension> extensions400{
        _extension(GL,ARB,draw_buffers_blend),
        _extension(GL,ARB,sample_shading),
        _extension(GL,ARB,texture_cube_map_array),
        _extension(GL,ARB,texture_gather),
        _extension(GL,ARB,texture_query_lod),
        _extension(GL,ARB,draw_indirect),
        _extension(GL,ARB,gpu_shader5),
        _extension(GL,ARB,gpu_shader_fp64),
        _extension(GL,ARB,shader_subroutine),
        _extension(GL,ARB,tessellation_shader),
        _extension(GL,ARB,texture_buffer_object_rgb32),
        _extension(GL,ARB,transform_feedback2),
        _extension(GL,ARB,transform_feedback3)};
    static const std::vector<Extension> extensions410{
        _extension(GL,ARB,ES2_compatibility),
        _extension(GL,ARB,get_program_binary),
        _extension(GL,ARB,separate_shader_objects),
        _extension(GL,ARB,shader_precision),
        _extension(GL,ARB,vertex_attrib_64bit),
        _extension(GL,ARB,viewport_array)};
    static const std::vector<Extension> extensions420{
        _extension(GL,ARB,texture_compression_bptc),
        _extension(GL,ARB,base_instance),
        _extension(GL,ARB,shading_language_420pack),
        _extension(GL,ARB,transform_feedback_instanced),
        _extension(GL,ARB,compressed_texture_pixel_storage),
        _extension(GL,ARB,conservative_depth),
        _extension(GL,ARB,internalformat_query),
        _extension(GL,ARB,map_buffer_alignment),
        _extension(GL,ARB,shader_atomic_counters),
        _extension(GL,ARB,shader_image_load_store),
        _extension(GL,ARB,texture_storage)};
    static const std::vector<Extension> extensions430{
        _extension(GL,ARB,arrays_of_arrays),
        _extension(GL,ARB,ES3_compatibility),
        _extension(GL,ARB,clear_buffer_object),
        _extension(GL,ARB,compute_shader),
        _extension(GL,ARB,copy_image),
        _extension(GL,KHR,debug),
        _extension(GL,ARB,explicit_uniform_location),
        _extension(GL,ARB,fragment_layer_viewport),
        _extension(GL,ARB,framebuffer_no_attachments),
        _extension(GL,ARB,internalformat_query2),
        _extension(GL,ARB,invalidate_subdata),
        _extension(GL,ARB,multi_draw_indirect),
        _extension(GL,ARB,program_interface_query),
        _extension(GL,ARB,robust_buffer_access_behavior),
        _extension(GL,ARB,shader_image_size),
        _extension(GL,ARB,shader_storage_buffer_object),
        _extension(GL,ARB,stencil_texturing),
        _extension(GL,ARB,texture_buffer_range),
        _extension(GL,ARB,texture_query_levels),
        _extension(GL,ARB,texture_storage_multisample),
        _extension(GL,ARB,texture_view),
        _extension(GL,ARB,vertex_attrib_binding)};
    #undef _extension
    #else
    static const std::vector<Extension> extensions;
    static const std::vector<Extension> extensionsES200;
    static const std::vector<Extension> extensionsES300;
    #endif

    switch(version) {
        case Version::None:  return extensions;
        #ifndef MAGNUM_TARGET_GLES
        case Version::GL210: return empty;
        case Version::GL300: return extensions300;
        case Version::GL310: return extensions310;
        case Version::GL320: return extensions320;
        case Version::GL330: return extensions330;
        case Version::GL400: return extensions400;
        /* case Version::GLES200: */
        case Version::GL410: return extensions410;
        case Version::GL420: return extensions420;
        /* case Version::GLES300: */
        case Version::GL430: return extensions430;
        #else
        case Version::GLES200: return extensionsES200;
        case Version::GLES300: return extensionsES300;
        #endif
    }

    return empty;
}

Context* Context::_current = nullptr;

Context::Context() {
    /* Version */
    #ifndef MAGNUM_TARGET_GLES2
    glGetIntegerv(GL_MAJOR_VERSION, &_majorVersion);
    glGetIntegerv(GL_MINOR_VERSION, &_minorVersion);
    #else
    _majorVersion = 2;
    _minorVersion = 0;
    #endif
    _version = static_cast<Version>(_majorVersion*100+_minorVersion*10);

    /* Get first future (not supported) version */
    std::vector<Version> versions{
        #ifndef MAGNUM_TARGET_GLES
        Version::GL300,
        Version::GL310,
        Version::GL320,
        Version::GL330,
        Version::GL400,
        Version::GL410,
        Version::GL420,
        Version::GL430,
        #else
        Version::GLES200,
        Version::GLES300,
        #endif
        Version::None
    };
    std::size_t future = 0;
    while(versions[future] != Version::None && isVersionSupported(versions[future]))
        ++future;

    /* List of extensions from future versions (extensions from current and
       previous versions should be supported automatically, so we don't need
       to check for them) */
    std::unordered_map<std::string, Extension> futureExtensions;
    for(std::size_t i = future; i != versions.size(); ++i)
        for(const Extension& extension: Extension::extensions(versions[i]))
            futureExtensions.insert(std::make_pair(extension._string, extension));

    /* Check for presence of extensions in future versions */
    #ifndef MAGNUM_TARGET_GLES
    if(isVersionSupported(Version::GL300)) {
    #else
    if(isVersionSupported(Version::GLES300)) {
    #endif
        #ifndef MAGNUM_TARGET_GLES2
        GLuint index = 0;
        const char* extension;
        while((extension = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, index++)))) {
            auto found = futureExtensions.find(extension);
            if(found != futureExtensions.end()) {
                _supportedExtensions.push_back(found->second);
                extensionStatus.set(found->second._index);
            }
        }
        #endif

    /* OpenGL 2.1 / OpenGL ES 2.0 doesn't have glGetStringi() */
    } else {
        /* Don't crash when glGetString() returns nullptr */
        const char* e = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
        if(e) {
            std::vector<std::string> extensions = Corrade::Utility::String::split(e, ' ');
            for(const std::string& extension: extensions) {
                auto found = futureExtensions.find(extension);
                if(found != futureExtensions.end()) {
                    _supportedExtensions.push_back(found->second);
                    extensionStatus.set(found->second._index);
                }
            }
        }
    }

    /* Set this context as current */
    CORRADE_ASSERT(!_current, "Context: Another context currently active", );
    _current = this;

    /* Initialize state tracker */
    _state = new Implementation::State;

    /* Initialize functionality based on current OpenGL version and extensions */
    AbstractShaderProgram::initializeContextBasedFunctionality(this);
    AbstractTexture::initializeContextBasedFunctionality(this);
    Buffer::initializeContextBasedFunctionality(this);
    #ifndef MAGNUM_TARGET_GLES
    BufferedTexture::initializeContextBasedFunctionality(this);
    #endif
    DebugMarker::initializeContextBasedFunctionality(this);
    IndexedMesh::initializeContextBasedFunctionality(this);
    Mesh::initializeContextBasedFunctionality(this);
}

Context::~Context() {
    CORRADE_ASSERT(_current == this, "Context: Cannot destroy context which is not currently active", );
    delete _state;
    _current = nullptr;
}

Version Context::supportedVersion(std::initializer_list<Version> versions) const {
    for(auto version: versions)
        if(isVersionSupported(version)) return version;

    #ifndef MAGNUM_TARGET_GLES
    return Version::GL210;
    #else
    return Version::GLES200;
    #endif
}

}
<|endoftext|>


<commit_before>#include <SmurffCpp/Utils/StepFile.h>

#include <iostream>

#include <SmurffCpp/Model.h>
#include <SmurffCpp/result.h>
#include <SmurffCpp/Priors/ILatentPrior.h>

#include <SmurffCpp/Utils/Error.h>
#include <SmurffCpp/IO/GenericIO.h>
#include <SmurffCpp/IO/MatrixIO.h>

#define STEP_SAMPLE_PREFIX "-sample-"
#define STEP_CHECKPOINT_PREFIX "-checkpoint-"
#define STEP_INI_SUFFIX "-step.ini"

#define MODEL_PREFIX "model_"
#define PRIOR_PREFIX "prior_"

#define MODELS_SEC_TAG "models"
#define PRED_SEC_TAG "predictions"
#define PRIORS_SEC_TAG "priors"

#define NUM_MODELS_TAG "num_models"
#define NUM_PRIORS_TAG "num_priors"
#define PRED_TAG "pred"
#define PRED_STATE_TAG "pred_state"

using namespace smurff;

StepFile::StepFile(std::int32_t isample, std::string prefix, std::string extension, bool create, bool checkpoint)
   : m_isample(isample), m_prefix(prefix), m_extension(extension), m_checkpoint(checkpoint)
{
   if (create)
   {
      m_iniReader = std::make_shared<INIFile>();
      m_iniReader->create(getStepFileName());
   }
   else
   {
      //load all entries in ini file to be able to go through step file internals
      m_iniReader = std::make_shared<INIFile>();
      m_iniReader->open(getStepFileName());
   }
}

StepFile::StepFile(const std::string& path, std::string prefix, std::string extension)
   : m_prefix(prefix), m_extension(extension)
{
   m_isample = tryGetIsampleFromPathInternal(path, STEP_CHECKPOINT_PREFIX, STEP_INI_SUFFIX);

   if (m_isample < 0)
   {
      m_isample = tryGetIsampleFromPathInternal(path, STEP_SAMPLE_PREFIX, STEP_INI_SUFFIX);

      if (m_isample < 0)
      {
         THROWERROR("Invalid step file name");
      }
      else
      {
         m_checkpoint = false;
      }
   }
   else
   {
      m_checkpoint = true;
   }

   //load all entries in ini file to be able to go through step file internals
   m_iniReader = std::make_shared<INIFile>();
   m_iniReader->open(path);
}

//name methods

std::string StepFile::getStepFileName() const
{
   std::string prefix = getStepPrefix();
   return prefix + STEP_INI_SUFFIX;
}

bool StepFile::isBinary() const
{
    if (m_extension == ".ddm")
    {
        return true;
    }
    else
    {
        THROWERROR_ASSERT_MSG(m_extension == ".csv", "Invalid save_extension: " + m_extension);
    }
    return false;
}

std::int32_t StepFile::tryGetIsampleFromPathInternal(const std::string& path, const std::string& prefix, const std::string& suffix) const
{
   std::size_t idx0 = path.find(prefix);
   if (idx0 == std::string::npos)
      return -1;

   std::size_t idx1 = path.find(suffix);
   THROWERROR_ASSERT_MSG(idx1 != std::string::npos, "Invalid step file name");

   std::size_t start = idx0 + prefix.length();
   std::string indexStr = path.substr(start, idx1 - start);

   std::int32_t index;
   std::stringstream ss;
   ss << indexStr;
   ss >> index;

   return index;
}

std::string StepFile::getStepPrefix() const
{
   std::string prefix = m_checkpoint ? STEP_CHECKPOINT_PREFIX : STEP_SAMPLE_PREFIX;
   return m_prefix + prefix + std::to_string(m_isample);
}

std::string StepFile::getModelFileName(std::uint64_t index) const
{
   auto modelIt = tryGetIniValueBase(MODELS_SEC_TAG, MODEL_PREFIX + std::to_string(index));
   if (modelIt.first)
      return modelIt.second;

   std::string prefix = getStepPrefix();
   return prefix + "-U" + std::to_string(index) + "-latents" + m_extension;
}

std::string StepFile::getLinkMatrixFileName(std::uint32_t mode) const
{
   auto linkMatrixIt = tryGetIniValueBase(PRIORS_SEC_TAG, PRIOR_PREFIX + std::to_string(mode));
   if (linkMatrixIt.first)
      return linkMatrixIt.second;

   std::string prefix = getStepPrefix();
   return prefix + "-F" + std::to_string(mode) + "-link" + m_extension;
}

std::string StepFile::getPredFileName() const
{
   auto predIt = tryGetIniValueBase(PRED_SEC_TAG, PRED_TAG);
   if (predIt.first)
      return predIt.second;

   std::string prefix = getStepPrefix();
   std::string extension = isBinary() ? ".bin" : ".csv";
   return prefix + "-predictions" + extension;
}

std::string StepFile::getPredStateFileName() const
{
   auto predStateIt = tryGetIniValueBase(PRED_SEC_TAG, PRED_STATE_TAG);
   if (predStateIt.first)
      return predStateIt.second;

   std::string prefix = getStepPrefix();
   return prefix + "-predictions-state.ini";
}

//save methods

void StepFile::saveModel(std::shared_ptr<const Model> model) const
{
   model->save(shared_from_this());

   //save models
   appendToStepFile(MODELS_SEC_TAG, NUM_MODELS_TAG, std::to_string(model->nmodes()));

   for (std::uint64_t mIndex = 0; mIndex < model->nmodes(); mIndex++)
   {
      std::string path = getModelFileName(mIndex);
      appendToStepFile(MODELS_SEC_TAG, MODEL_PREFIX + std::to_string(mIndex), path);
   }
}

void StepFile::savePred(std::shared_ptr<const Result> m_pred) const
{
   if (m_pred->isEmpty())
      return;

   m_pred->save(shared_from_this());

   //save predictions

   appendToStepFile(PRED_SEC_TAG, PRED_TAG, getPredFileName());
   appendToStepFile(PRED_SEC_TAG, PRED_STATE_TAG, getPredStateFileName());
}

void StepFile::savePriors(const std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   for (auto &p : priors)
   {
      p->save(shared_from_this());
   }

   //save priors

   appendToStepFile(PRIORS_SEC_TAG, NUM_PRIORS_TAG, std::to_string(priors.size()));

   for (std::uint64_t pIndex = 0; pIndex < priors.size(); pIndex++)
   {
      std::string priorPath = getLinkMatrixFileName(priors.at(pIndex)->getMode());
      appendToStepFile(PRIORS_SEC_TAG, PRIOR_PREFIX + std::to_string(pIndex), priorPath);
   }
}

void StepFile::save(std::shared_ptr<const Model> model, std::shared_ptr<const Result> pred, const std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   saveModel(model);
   savePred(pred);
   savePriors(priors);
}

//restore methods

void StepFile::restoreModel(std::shared_ptr<Model> model) const
{
   //it is enough to check presence of num tag
   if (!hasIniValueBase(MODELS_SEC_TAG, NUM_MODELS_TAG))
      return;

   model->restore(shared_from_this());
}

  //-- used in PredictSession
std::shared_ptr<Model> StepFile::restoreModel() const
{
    auto model = std::make_shared<Model>();
    model->restore(shared_from_this());
    return model;
}

void StepFile::restorePred(std::shared_ptr<Result> m_pred) const
{
   if (!hasIniValueBase(PRED_SEC_TAG, PRED_TAG))
      return;

   if (!hasIniValueBase(PRED_SEC_TAG, PRED_STATE_TAG))
      return;

   m_pred->restore(shared_from_this());
}

void StepFile::restorePriors(std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   //it is enough to check presence of num tag
   if (!hasIniValueBase(PRIORS_SEC_TAG,NUM_PRIORS_TAG))
      return;

   for (auto &p : priors)
   {
      p->restore(shared_from_this());
   }
}

std::vector<std::shared_ptr<MatrixConfig>> StepFile::restoreLinkMatrices() const
{
   std::vector<std::shared_ptr<MatrixConfig>> betas;

   //it is enough to check presence of num tag
   auto npriors = tryGetIniValueBase(PRIORS_SEC_TAG, NUM_PRIORS_TAG);
   if (!npriors.first) return betas;
   int nmodes = atoi(npriors.second.c_str());

   for(int i=0; i<nmodes; ++i)
   {
      std::string path = getLinkMatrixFileName(i);
      THROWERROR_FILE_NOT_EXIST(path);
      betas.push_back(smurff::matrix_io::read_matrix(path, false));
   }

   return betas;
}

void StepFile::restore(std::shared_ptr<Model> model, std::shared_ptr<Result> pred, std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   restoreModel(model);
   restorePred(pred);
   restorePriors(priors);
}

//remove methods

void StepFile::removeModel() const
{
   std::uint64_t index = 0;
   while (true)
   {
      std::string path = getModelFileName(index++);
      if (!generic_io::file_exists(path))
         break;

      std::remove(path.c_str());
   }

   std::int32_t nModels = getNSamples();
   for(std::int32_t i = 0; i < nModels; i++)
      removeFromStepFile(MODEL_PREFIX + std::to_string(i));

   removeFromStepFile(NUM_MODELS_TAG);
}

void StepFile::removePred() const
{
   std::remove(getPredFileName().c_str());
   removeFromStepFile(PRED_TAG);

   std::remove(getPredStateFileName().c_str());
   removeFromStepFile(PRED_STATE_TAG);
}

void StepFile::removePriors() const
{
   std::uint32_t mode = 0;
   while (true)
   {
      std::string path = getLinkMatrixFileName(mode++);
      if (!generic_io::file_exists(path))
         break;

      std::remove(path.c_str());
   }

   std::int32_t nPriors = getNPriors();
   for (std::int32_t i = 0; i < nPriors; i++)
      removeFromStepFile(PRIOR_PREFIX + std::to_string(i));

   removeFromStepFile(NUM_PRIORS_TAG);
}

void StepFile::remove(bool model, bool pred, bool priors) const
{
   if (m_iniReader->empty())
       return;

   //remove all model files
   if(model)
      removeModel();

   //remove all pred files
   if(pred)
      removePred();

   //remove all prior files
   if(priors)
      removePriors();

   //remove step file itself
   std::remove(getStepFileName().c_str());

   THROWERROR_ASSERT_MSG(m_iniReader->empty(), "Unexpected data in step file");

   //nullify reader
   m_iniReader = std::shared_ptr<INIFile>();
}

//getters

std::int32_t StepFile::getIsample() const
{
   return m_isample;
}

bool StepFile::getCheckpoint() const
{
   return m_checkpoint;
}

std::int32_t StepFile::getNSamples() const
{
   return std::stoi(getIniValueBase(PRIORS_SEC_TAG, NUM_MODELS_TAG));
}

std::int32_t StepFile::getNPriors() const
{
   return std::stoi(getIniValueBase(PRIORS_SEC_TAG, NUM_PRIORS_TAG));
}

//ini methods

std::string StepFile::getIniValueBase(const std::string& section, const std::string& tag) const
{
   THROWERROR_ASSERT_MSG(m_iniReader, "Step ini file is not loaded");

   return m_iniReader->get(section, tag);
}

bool StepFile::hasIniValueBase(const std::string& section, const std::string& tag) const
{
   return tryGetIniValueBase(section, tag).first;
}

std::pair<bool, std::string> StepFile::tryGetIniValueBase(const std::string& section, const std::string& tag) const
{
   if (m_iniReader)
      return m_iniReader->tryGet(section, tag);

   return std::make_pair(false, std::string());
}

void StepFile::appendToStepFile(std::string section, std::string tag, std::string value) const
{
   if (m_cur_section != section) {
      m_iniReader->startSection(section);
      m_cur_section = section;
   }

   m_iniReader->appendItem(section, tag, value);

   flushLast();
}

void StepFile::appendCommentToStepFile(std::string comment) const
{
   m_iniReader->appendComment(comment);
}

void StepFile::removeFromStepFile(std::string tag) const
{
   m_iniReader->removeItem(std::string(), tag);
}

void StepFile::flushLast() const
{
   m_iniReader->flush();
}
<commit_msg>Wrong tag in ini-file<commit_after>#include <SmurffCpp/Utils/StepFile.h>

#include <iostream>

#include <SmurffCpp/Model.h>
#include <SmurffCpp/result.h>
#include <SmurffCpp/Priors/ILatentPrior.h>

#include <SmurffCpp/Utils/Error.h>
#include <SmurffCpp/IO/GenericIO.h>
#include <SmurffCpp/IO/MatrixIO.h>

#define STEP_SAMPLE_PREFIX "-sample-"
#define STEP_CHECKPOINT_PREFIX "-checkpoint-"
#define STEP_INI_SUFFIX "-step.ini"

#define MODEL_PREFIX "model_"
#define PRIOR_PREFIX "prior_"

#define MODELS_SEC_TAG "models"
#define PRED_SEC_TAG "predictions"
#define PRIORS_SEC_TAG "priors"

#define NUM_MODELS_TAG "num_models"
#define NUM_PRIORS_TAG "num_priors"
#define PRED_TAG "pred"
#define PRED_STATE_TAG "pred_state"

using namespace smurff;

StepFile::StepFile(std::int32_t isample, std::string prefix, std::string extension, bool create, bool checkpoint)
   : m_isample(isample), m_prefix(prefix), m_extension(extension), m_checkpoint(checkpoint)
{
   if (create)
   {
      m_iniReader = std::make_shared<INIFile>();
      m_iniReader->create(getStepFileName());
   }
   else
   {
      //load all entries in ini file to be able to go through step file internals
      m_iniReader = std::make_shared<INIFile>();
      m_iniReader->open(getStepFileName());
   }
}

StepFile::StepFile(const std::string& path, std::string prefix, std::string extension)
   : m_prefix(prefix), m_extension(extension)
{
   m_isample = tryGetIsampleFromPathInternal(path, STEP_CHECKPOINT_PREFIX, STEP_INI_SUFFIX);

   if (m_isample < 0)
   {
      m_isample = tryGetIsampleFromPathInternal(path, STEP_SAMPLE_PREFIX, STEP_INI_SUFFIX);

      if (m_isample < 0)
      {
         THROWERROR("Invalid step file name");
      }
      else
      {
         m_checkpoint = false;
      }
   }
   else
   {
      m_checkpoint = true;
   }

   //load all entries in ini file to be able to go through step file internals
   m_iniReader = std::make_shared<INIFile>();
   m_iniReader->open(path);
}

//name methods

std::string StepFile::getStepFileName() const
{
   std::string prefix = getStepPrefix();
   return prefix + STEP_INI_SUFFIX;
}

bool StepFile::isBinary() const
{
    if (m_extension == ".ddm")
    {
        return true;
    }
    else
    {
        THROWERROR_ASSERT_MSG(m_extension == ".csv", "Invalid save_extension: " + m_extension);
    }
    return false;
}

std::int32_t StepFile::tryGetIsampleFromPathInternal(const std::string& path, const std::string& prefix, const std::string& suffix) const
{
   std::size_t idx0 = path.find(prefix);
   if (idx0 == std::string::npos)
      return -1;

   std::size_t idx1 = path.find(suffix);
   THROWERROR_ASSERT_MSG(idx1 != std::string::npos, "Invalid step file name");

   std::size_t start = idx0 + prefix.length();
   std::string indexStr = path.substr(start, idx1 - start);

   std::int32_t index;
   std::stringstream ss;
   ss << indexStr;
   ss >> index;

   return index;
}

std::string StepFile::getStepPrefix() const
{
   std::string prefix = m_checkpoint ? STEP_CHECKPOINT_PREFIX : STEP_SAMPLE_PREFIX;
   return m_prefix + prefix + std::to_string(m_isample);
}

std::string StepFile::getModelFileName(std::uint64_t index) const
{
   auto modelIt = tryGetIniValueBase(MODELS_SEC_TAG, MODEL_PREFIX + std::to_string(index));
   if (modelIt.first)
      return modelIt.second;

   std::string prefix = getStepPrefix();
   return prefix + "-U" + std::to_string(index) + "-latents" + m_extension;
}

std::string StepFile::getLinkMatrixFileName(std::uint32_t mode) const
{
   auto linkMatrixIt = tryGetIniValueBase(PRIORS_SEC_TAG, PRIOR_PREFIX + std::to_string(mode));
   if (linkMatrixIt.first)
      return linkMatrixIt.second;

   std::string prefix = getStepPrefix();
   return prefix + "-F" + std::to_string(mode) + "-link" + m_extension;
}

std::string StepFile::getPredFileName() const
{
   auto predIt = tryGetIniValueBase(PRED_SEC_TAG, PRED_TAG);
   if (predIt.first)
      return predIt.second;

   std::string prefix = getStepPrefix();
   std::string extension = isBinary() ? ".bin" : ".csv";
   return prefix + "-predictions" + extension;
}

std::string StepFile::getPredStateFileName() const
{
   auto predStateIt = tryGetIniValueBase(PRED_SEC_TAG, PRED_STATE_TAG);
   if (predStateIt.first)
      return predStateIt.second;

   std::string prefix = getStepPrefix();
   return prefix + "-predictions-state.ini";
}

//save methods

void StepFile::saveModel(std::shared_ptr<const Model> model) const
{
   model->save(shared_from_this());

   //save models
   appendToStepFile(MODELS_SEC_TAG, NUM_MODELS_TAG, std::to_string(model->nmodes()));

   for (std::uint64_t mIndex = 0; mIndex < model->nmodes(); mIndex++)
   {
      std::string path = getModelFileName(mIndex);
      appendToStepFile(MODELS_SEC_TAG, MODEL_PREFIX + std::to_string(mIndex), path);
   }
}

void StepFile::savePred(std::shared_ptr<const Result> m_pred) const
{
   if (m_pred->isEmpty())
      return;

   m_pred->save(shared_from_this());

   //save predictions

   appendToStepFile(PRED_SEC_TAG, PRED_TAG, getPredFileName());
   appendToStepFile(PRED_SEC_TAG, PRED_STATE_TAG, getPredStateFileName());
}

void StepFile::savePriors(const std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   for (auto &p : priors)
   {
      p->save(shared_from_this());
   }

   //save priors

   appendToStepFile(PRIORS_SEC_TAG, NUM_PRIORS_TAG, std::to_string(priors.size()));

   for (std::uint64_t pIndex = 0; pIndex < priors.size(); pIndex++)
   {
      std::string priorPath = getLinkMatrixFileName(priors.at(pIndex)->getMode());
      appendToStepFile(PRIORS_SEC_TAG, PRIOR_PREFIX + std::to_string(pIndex), priorPath);
   }
}

void StepFile::save(std::shared_ptr<const Model> model, std::shared_ptr<const Result> pred, const std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   saveModel(model);
   savePred(pred);
   savePriors(priors);
}

//restore methods

void StepFile::restoreModel(std::shared_ptr<Model> model) const
{
   //it is enough to check presence of num tag
   if (!hasIniValueBase(MODELS_SEC_TAG, NUM_MODELS_TAG))
      return;

   model->restore(shared_from_this());
}

  //-- used in PredictSession
std::shared_ptr<Model> StepFile::restoreModel() const
{
    auto model = std::make_shared<Model>();
    model->restore(shared_from_this());
    return model;
}

void StepFile::restorePred(std::shared_ptr<Result> m_pred) const
{
   if (!hasIniValueBase(PRED_SEC_TAG, PRED_TAG))
      return;

   if (!hasIniValueBase(PRED_SEC_TAG, PRED_STATE_TAG))
      return;

   m_pred->restore(shared_from_this());
}

void StepFile::restorePriors(std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   //it is enough to check presence of num tag
   if (!hasIniValueBase(PRIORS_SEC_TAG,NUM_PRIORS_TAG))
      return;

   for (auto &p : priors)
   {
      p->restore(shared_from_this());
   }
}

std::vector<std::shared_ptr<MatrixConfig>> StepFile::restoreLinkMatrices() const
{
   std::vector<std::shared_ptr<MatrixConfig>> betas;

   //it is enough to check presence of num tag
   auto npriors = tryGetIniValueBase(PRIORS_SEC_TAG, NUM_PRIORS_TAG);
   if (!npriors.first) return betas;
   int nmodes = atoi(npriors.second.c_str());

   for(int i=0; i<nmodes; ++i)
   {
      std::string path = getLinkMatrixFileName(i);
      THROWERROR_FILE_NOT_EXIST(path);
      betas.push_back(smurff::matrix_io::read_matrix(path, false));
   }

   return betas;
}

void StepFile::restore(std::shared_ptr<Model> model, std::shared_ptr<Result> pred, std::vector<std::shared_ptr<ILatentPrior> >& priors) const
{
   restoreModel(model);
   restorePred(pred);
   restorePriors(priors);
}

//remove methods

void StepFile::removeModel() const
{
   std::uint64_t index = 0;
   while (true)
   {
      std::string path = getModelFileName(index++);
      if (!generic_io::file_exists(path))
         break;

      std::remove(path.c_str());
   }

   std::int32_t nModels = getNSamples();
   for(std::int32_t i = 0; i < nModels; i++)
      removeFromStepFile(MODEL_PREFIX + std::to_string(i));

   removeFromStepFile(NUM_MODELS_TAG);
}

void StepFile::removePred() const
{
   std::remove(getPredFileName().c_str());
   removeFromStepFile(PRED_TAG);

   std::remove(getPredStateFileName().c_str());
   removeFromStepFile(PRED_STATE_TAG);
}

void StepFile::removePriors() const
{
   std::uint32_t mode = 0;
   while (true)
   {
      std::string path = getLinkMatrixFileName(mode++);
      if (!generic_io::file_exists(path))
         break;

      std::remove(path.c_str());
   }

   std::int32_t nPriors = getNPriors();
   for (std::int32_t i = 0; i < nPriors; i++)
      removeFromStepFile(PRIOR_PREFIX + std::to_string(i));

   removeFromStepFile(NUM_PRIORS_TAG);
}

void StepFile::remove(bool model, bool pred, bool priors) const
{
   if (m_iniReader->empty())
       return;

   //remove all model files
   if(model)
      removeModel();

   //remove all pred files
   if(pred)
      removePred();

   //remove all prior files
   if(priors)
      removePriors();

   //remove step file itself
   std::remove(getStepFileName().c_str());

   THROWERROR_ASSERT_MSG(m_iniReader->empty(), "Unexpected data in step file");

   //nullify reader
   m_iniReader = std::shared_ptr<INIFile>();
}

//getters

std::int32_t StepFile::getIsample() const
{
   return m_isample;
}

bool StepFile::getCheckpoint() const
{
   return m_checkpoint;
}

std::int32_t StepFile::getNSamples() const
{
   return std::stoi(getIniValueBase(MODELS_SEC_TAG, NUM_MODELS_TAG));
}

std::int32_t StepFile::getNPriors() const
{
   return std::stoi(getIniValueBase(PRIORS_SEC_TAG, NUM_PRIORS_TAG));
}

//ini methods

std::string StepFile::getIniValueBase(const std::string& section, const std::string& tag) const
{
   THROWERROR_ASSERT_MSG(m_iniReader, "Step ini file is not loaded");

   return m_iniReader->get(section, tag);
}

bool StepFile::hasIniValueBase(const std::string& section, const std::string& tag) const
{
   return tryGetIniValueBase(section, tag).first;
}

std::pair<bool, std::string> StepFile::tryGetIniValueBase(const std::string& section, const std::string& tag) const
{
   if (m_iniReader)
      return m_iniReader->tryGet(section, tag);

   return std::make_pair(false, std::string());
}

void StepFile::appendToStepFile(std::string section, std::string tag, std::string value) const
{
   if (m_cur_section != section) {
      m_iniReader->startSection(section);
      m_cur_section = section;
   }

   m_iniReader->appendItem(section, tag, value);

   flushLast();
}

void StepFile::appendCommentToStepFile(std::string comment) const
{
   m_iniReader->appendComment(comment);
}

void StepFile::removeFromStepFile(std::string tag) const
{
   m_iniReader->removeItem(std::string(), tag);
}

void StepFile::flushLast() const
{
   m_iniReader->flush();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "kitmanager.h"

#include "kit.h"
#include "kitconfigwidget.h"
#include "kitinformation.h"
#include "kitmanagerconfigwidget.h"
#include "project.h"

#include <coreplugin/icore.h>

#include <extensionsystem/pluginmanager.h>

#include <utils/persistentsettings.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>

#include <QCoreApplication>
#include <QDir>
#include <QSettings>

#include <QFormLayout>
#include <QLabel>

static const char KIT_DATA_KEY[] = "Profile.";
static const char KIT_COUNT_KEY[] = "Profile.Count";
static const char KIT_FILE_VERSION_KEY[] = "Version";
static const char KIT_DEFAULT_KEY[] = "Profile.Default";
static const char KIT_FILENAME[] = "/qtcreator/profiles.xml";

using Utils::PersistentSettingsWriter;
using Utils::PersistentSettingsReader;

static Utils::FileName settingsFileName()
{
    QFileInfo settingsLocation(ExtensionSystem::PluginManager::settings()->fileName());
    return Utils::FileName::fromString(settingsLocation.absolutePath() + QLatin1String(KIT_FILENAME));
}

namespace ProjectExplorer {

KitManager *KitManager::m_instance = 0;

namespace Internal {

// --------------------------------------------------------------------------
// KitManagerPrivate:
// --------------------------------------------------------------------------

class KitManagerPrivate
{
public:
    KitManagerPrivate();
    ~KitManagerPrivate();
    QList<Task> validateKit(Kit *k) const;

    Kit *m_defaultKit;
    bool m_initialized;
    QList<KitInformation *> m_informationList;
    QList<Kit *> m_kitList;
    Utils::PersistentSettingsWriter *m_writer;
};

KitManagerPrivate::KitManagerPrivate()
    : m_defaultKit(0), m_initialized(false),
      m_writer(0)
{ }

KitManagerPrivate::~KitManagerPrivate()
{
    qDeleteAll(m_informationList);
    qDeleteAll(m_kitList);
    delete m_writer;
}

QList<Task> KitManagerPrivate::validateKit(Kit *k) const
{
    Q_ASSERT(k);
    QList<Task> result;
    bool hasError = false;
    foreach (KitInformation *ki, m_informationList) {
        QList<Task> tmp = ki->validate(k);
        foreach (const Task &t, tmp)
            if (t.type == Task::Error)
                hasError = true;
        result << tmp;
    }
    k->setValid(!hasError);
    return result;
}

} // namespace Internal

// --------------------------------------------------------------------------
// KitManager:
// --------------------------------------------------------------------------

KitManager *KitManager::instance()
{
    return m_instance;
}

KitManager::KitManager(QObject *parent) :
    QObject(parent),
    d(new Internal::KitManagerPrivate())
{
    Q_ASSERT(!m_instance);
    m_instance = this;

    connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
            this, SLOT(saveKits()));

    connect(this, SIGNAL(kitAdded(ProjectExplorer::Kit*)),
            this, SIGNAL(kitsChanged()));
    connect(this, SIGNAL(kitRemoved(ProjectExplorer::Kit*)),
            this, SIGNAL(kitsChanged()));
    connect(this, SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
            this, SIGNAL(kitsChanged()));
}

void KitManager::restoreKits()
{
    QTC_ASSERT(!d->m_writer, return);
    QList<Kit *> kitsToRegister;
    QList<Kit *> kitsToCheck;

    // read all kits from SDK
    QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
    KitList system = restoreKits(Utils::FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(KIT_FILENAME)));
    QList<Kit *> readKits = system.kits;
    // make sure we mark these as autodetected!
    foreach (Kit *k, readKits)
        k->setAutoDetected(true);

    kitsToRegister = readKits; // SDK kits are always considered to be up-to-date, so no need to
                             // recheck them.

    // read all kit chains from user file
    KitList userKits = restoreKits(settingsFileName());
    readKits = userKits.kits;

    foreach (Kit *k, readKits) {
        if (k->isAutoDetected())
            kitsToCheck.append(k);
        else
            kitsToRegister.append(k);
    }
    readKits.clear();

    // Then auto create kits:
    QList<Kit *> detectedKits;

    // Find/update autodetected kits:
    Kit *toStore = 0;
    foreach (Kit *currentDetected, detectedKits) {
        toStore = currentDetected;

        // Check whether we had this kit stored and prefer the old one with the old id:
        for (int i = 0; i < kitsToCheck.count(); ++i) {
            if (*(kitsToCheck.at(i)) == *currentDetected) {
                toStore = kitsToCheck.at(i);
                kitsToCheck.removeAt(i);
                delete currentDetected;
                break;
            }
        }
        addKit(toStore);
    }

    // Delete all loaded autodetected kits that were not rediscovered:
    qDeleteAll(kitsToCheck);

    // Store manual kits
    foreach (Kit *k, kitsToRegister)
        addKit(k);

    if (kits().isEmpty()) {
        Kit *defaultKit = new Kit; // One kit using default values
        defaultKit->setDisplayName(tr("Desktop"));
        defaultKit->setAutoDetected(false);
        defaultKit->setIconPath(QLatin1String(":///DESKTOP///"));

        addKit(defaultKit);
    }

    Kit *k = find(userKits.defaultKit);
    if (k)
        setDefaultKit(k);

    d->m_writer = new Utils::PersistentSettingsWriter(settingsFileName(), QLatin1String("QtCreatorProfiles"));
}

KitManager::~KitManager()
{
    saveKits(); // Make sure we save the current state on exit!
    // Clean out kit information to avoid calling them during deregistration:
    delete d;
    m_instance = 0;
}

void KitManager::saveKits()
{
    if (!d->m_writer) // ignore save requests while we are not initialized.
        return;

    QVariantMap data;
    data.insert(QLatin1String(KIT_FILE_VERSION_KEY), 1);

    int count = 0;
    foreach (Kit *k, kits()) {
        QVariantMap tmp = k->toMap();
        if (tmp.isEmpty())
            continue;
        data.insert(QString::fromLatin1(KIT_DATA_KEY) + QString::number(count), tmp);
        ++count;
    }
    data.insert(QLatin1String(KIT_COUNT_KEY), count);
    data.insert(QLatin1String(KIT_DEFAULT_KEY),
                d->m_defaultKit ? QString::fromLatin1(d->m_defaultKit->id().name()) : QString());
    d->m_writer->save(data, Core::ICore::mainWindow());
}

bool greaterPriority(KitInformation *a, KitInformation *b)
{
    return a->priority() > b->priority();
}

void KitManager::registerKitInformation(KitInformation *ki)
{
    QList<KitInformation *>::iterator it
            = qLowerBound(d->m_informationList.begin(), d->m_informationList.end(), ki, greaterPriority);
    d->m_informationList.insert(it, ki);

    connect(ki, SIGNAL(validationNeeded()), this, SLOT(validateKits()));

    if (!d->m_initialized)
        return;

    foreach (Kit *k, kits()) {
        if (!k->hasValue(ki->dataId()))
            k->setValue(ki->dataId(), ki->defaultValue(k));
    }

    return;
}

void KitManager::deregisterKitInformation(KitInformation *ki)
{
    Q_ASSERT(d->m_informationList.contains(ki));
    d->m_informationList.removeAll(ki);
    delete ki;
}

KitManager::KitList KitManager::restoreKits(const Utils::FileName &fileName)
{
    KitList result;

    PersistentSettingsReader reader;
    if (!reader.load(fileName)) {
        qWarning("Warning: Failed to read \"%s\", cannot restore kits!", qPrintable(fileName.toUserOutput()));
        return result;
    }
    QVariantMap data = reader.restoreValues();

    // Check version:
    int version = data.value(QLatin1String(KIT_FILE_VERSION_KEY), 0).toInt();
    if (version < 1) {
        qWarning("Warning: Kit file version %d not supported, cannot restore kits!", version);
        return result;
    }

    const int count = data.value(QLatin1String(KIT_COUNT_KEY), 0).toInt();
    for (int i = 0; i < count; ++i) {
        const QString key = QString::fromLatin1(KIT_DATA_KEY) + QString::number(i);
        if (!data.contains(key))
            break;

        const QVariantMap stMap = data.value(key).toMap();

        Kit *k = new Kit;
        if (k->fromMap(stMap)) {
            result.kits.append(k);
        } else {
            delete k;
            qWarning("Warning: Unable to restore kits stored in %s at position %d.",
                     qPrintable(fileName.toUserOutput()), i);
        }
    }
    const QString defaultId = data.value(QLatin1String(KIT_DEFAULT_KEY)).toString();
    if (defaultId.isEmpty())
        return result;

    const Core::Id id = Core::Id(defaultId);
    foreach (Kit *k, result.kits) {
        if (k->id() == id) {
            result.defaultKit = id;
            break;
        }
    }
    return result;
}

QList<Kit *> KitManager::kits(const KitMatcher *m) const
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        const_cast<KitManager *>(this)->restoreKits();
    }

    QList<Kit *> result;
    foreach (Kit *k, d->m_kitList) {
        if (!m || m->matches(k))
            result.append(k);
    }
    return result;
}

Kit *KitManager::find(const Core::Id &id) const
{
    if (!id.isValid())
        return 0;

    foreach (Kit *k, kits()) {
        if (k->id() == id)
            return k;
    }
    return 0;
}

Kit *KitManager::find(const KitMatcher *m) const
{
    QList<Kit *> matched = kits(m);
    return matched.isEmpty() ? 0 : matched.first();
}

Kit *KitManager::defaultKit()
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        restoreKits();
    }
    return d->m_defaultKit;
}

QList<KitInformation *> KitManager::kitInformation() const
{
    return d->m_informationList;
}

Internal::KitManagerConfigWidget *KitManager::createConfigWidget(Kit *k) const
{
    if (!k)
        return 0;

    Internal::KitManagerConfigWidget *result = new Internal::KitManagerConfigWidget(k);
    foreach (KitInformation *ki, d->m_informationList)
        result->addConfigWidget(ki->createConfigWidget(k));

    return result;
}

void KitManager::notifyAboutUpdate(ProjectExplorer::Kit *k)
{
    if (!k || !kits().contains(k))
        return;
    d->validateKit(k);
    emit kitUpdated(k);
}

bool KitManager::registerKit(ProjectExplorer::Kit *k)
{
    if (!k)
        return true;
    foreach (Kit *current, kits()) {
        if (k == current)
            return false;
    }

    // make sure we have all the information in our kits:
    foreach (KitInformation *ki, d->m_informationList) {
        if (!k->hasValue(ki->dataId()))
            k->setValue(ki->dataId(), ki->defaultValue(k));
    }

    addKit(k);
    emit kitAdded(k);
    return true;
}

void KitManager::deregisterKit(Kit *k)
{
    if (!k || !kits().contains(k))
        return;
    d->m_kitList.removeOne(k);
    if (d->m_defaultKit == k) {
        QList<Kit *> stList = kits();
        Kit *newDefault = 0;
        foreach (Kit *cur, stList) {
            if (cur->isValid()) {
                newDefault = cur;
                break;
            }
        }
        setDefaultKit(newDefault);
    }
    emit kitRemoved(k);
    delete k;
}

QList<Task> KitManager::validateKit(Kit *k)
{
    QList<Task> result = d->validateKit(k);
    qSort(result);
    return result;
}

void KitManager::setDefaultKit(Kit *k)
{
    if (d->m_defaultKit == k)
        return;
    if (k && !kits().contains(k))
        return;
    d->m_defaultKit = k;
    emit defaultkitChanged();
}

void KitManager::validateKits()
{
    foreach (Kit *k, kits())
        d->validateKit(k);
}

void KitManager::addKit(Kit *k)
{
    if (!k)
        return;
    k->setDisplayName(k->displayName()); // make name unique
    d->validateKit(k);
    d->m_kitList.append(k);
    if (!d->m_defaultKit ||
            (!d->m_defaultKit->isValid() && k->isValid()))
        setDefaultKit(k);
}

void KitInformation::addToEnvironment(const Kit *k, Utils::Environment &env) const
{
    Q_UNUSED(k);
    Q_UNUSED(env);
}

QString KitInformation::displayNamePostfix(const Kit *k) const
{
    Q_UNUSED(k);
    return QString();
}

} // namespace ProjectExplorer
<commit_msg>Restore system kits only if the kit file exist<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "kitmanager.h"

#include "kit.h"
#include "kitconfigwidget.h"
#include "kitinformation.h"
#include "kitmanagerconfigwidget.h"
#include "project.h"

#include <coreplugin/icore.h>

#include <extensionsystem/pluginmanager.h>

#include <utils/persistentsettings.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>

#include <QCoreApplication>
#include <QDir>
#include <QSettings>

#include <QFormLayout>
#include <QLabel>

static const char KIT_DATA_KEY[] = "Profile.";
static const char KIT_COUNT_KEY[] = "Profile.Count";
static const char KIT_FILE_VERSION_KEY[] = "Version";
static const char KIT_DEFAULT_KEY[] = "Profile.Default";
static const char KIT_FILENAME[] = "/qtcreator/profiles.xml";

using Utils::PersistentSettingsWriter;
using Utils::PersistentSettingsReader;

static Utils::FileName settingsFileName()
{
    QFileInfo settingsLocation(ExtensionSystem::PluginManager::settings()->fileName());
    return Utils::FileName::fromString(settingsLocation.absolutePath() + QLatin1String(KIT_FILENAME));
}

namespace ProjectExplorer {

KitManager *KitManager::m_instance = 0;

namespace Internal {

// --------------------------------------------------------------------------
// KitManagerPrivate:
// --------------------------------------------------------------------------

class KitManagerPrivate
{
public:
    KitManagerPrivate();
    ~KitManagerPrivate();
    QList<Task> validateKit(Kit *k) const;

    Kit *m_defaultKit;
    bool m_initialized;
    QList<KitInformation *> m_informationList;
    QList<Kit *> m_kitList;
    Utils::PersistentSettingsWriter *m_writer;
};

KitManagerPrivate::KitManagerPrivate()
    : m_defaultKit(0), m_initialized(false),
      m_writer(0)
{ }

KitManagerPrivate::~KitManagerPrivate()
{
    qDeleteAll(m_informationList);
    qDeleteAll(m_kitList);
    delete m_writer;
}

QList<Task> KitManagerPrivate::validateKit(Kit *k) const
{
    Q_ASSERT(k);
    QList<Task> result;
    bool hasError = false;
    foreach (KitInformation *ki, m_informationList) {
        QList<Task> tmp = ki->validate(k);
        foreach (const Task &t, tmp)
            if (t.type == Task::Error)
                hasError = true;
        result << tmp;
    }
    k->setValid(!hasError);
    return result;
}

} // namespace Internal

// --------------------------------------------------------------------------
// KitManager:
// --------------------------------------------------------------------------

KitManager *KitManager::instance()
{
    return m_instance;
}

KitManager::KitManager(QObject *parent) :
    QObject(parent),
    d(new Internal::KitManagerPrivate())
{
    Q_ASSERT(!m_instance);
    m_instance = this;

    connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
            this, SLOT(saveKits()));

    connect(this, SIGNAL(kitAdded(ProjectExplorer::Kit*)),
            this, SIGNAL(kitsChanged()));
    connect(this, SIGNAL(kitRemoved(ProjectExplorer::Kit*)),
            this, SIGNAL(kitsChanged()));
    connect(this, SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
            this, SIGNAL(kitsChanged()));
}

void KitManager::restoreKits()
{
    QTC_ASSERT(!d->m_writer, return);
    QList<Kit *> kitsToRegister;
    QList<Kit *> kitsToCheck;

    // read all kits from SDK
    QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName());
    QFileInfo kitFile(systemSettingsFile.absolutePath(), QLatin1String(KIT_FILENAME));
    if (kitFile.exists()) {
        KitList system = restoreKits(Utils::FileName(kitFile));
        // make sure we mark these as autodetected!
        foreach (Kit *k, system.kits)
            k->setAutoDetected(true);

        // SDK kits are always considered to be up-to-date, so no need to recheck them.
        kitsToRegister = system.kits;
    }

    // read all kit chains from user file
    KitList userKits = restoreKits(settingsFileName());
    foreach (Kit *k, userKits.kits) {
        if (k->isAutoDetected())
            kitsToCheck.append(k);
        else
            kitsToRegister.append(k);
    }

    // Then auto create kits:
    QList<Kit *> detectedKits;

    // Find/update autodetected kits:
    Kit *toStore = 0;
    foreach (Kit *currentDetected, detectedKits) {
        toStore = currentDetected;

        // Check whether we had this kit stored and prefer the old one with the old id:
        for (int i = 0; i < kitsToCheck.count(); ++i) {
            if (*(kitsToCheck.at(i)) == *currentDetected) {
                toStore = kitsToCheck.at(i);
                kitsToCheck.removeAt(i);
                delete currentDetected;
                break;
            }
        }
        addKit(toStore);
    }

    // Delete all loaded autodetected kits that were not rediscovered:
    qDeleteAll(kitsToCheck);

    // Store manual kits
    foreach (Kit *k, kitsToRegister)
        addKit(k);

    if (kits().isEmpty()) {
        Kit *defaultKit = new Kit; // One kit using default values
        defaultKit->setDisplayName(tr("Desktop"));
        defaultKit->setAutoDetected(false);
        defaultKit->setIconPath(QLatin1String(":///DESKTOP///"));

        addKit(defaultKit);
    }

    Kit *k = find(userKits.defaultKit);
    if (k)
        setDefaultKit(k);

    d->m_writer = new Utils::PersistentSettingsWriter(settingsFileName(), QLatin1String("QtCreatorProfiles"));
}

KitManager::~KitManager()
{
    saveKits(); // Make sure we save the current state on exit!
    // Clean out kit information to avoid calling them during deregistration:
    delete d;
    m_instance = 0;
}

void KitManager::saveKits()
{
    if (!d->m_writer) // ignore save requests while we are not initialized.
        return;

    QVariantMap data;
    data.insert(QLatin1String(KIT_FILE_VERSION_KEY), 1);

    int count = 0;
    foreach (Kit *k, kits()) {
        QVariantMap tmp = k->toMap();
        if (tmp.isEmpty())
            continue;
        data.insert(QString::fromLatin1(KIT_DATA_KEY) + QString::number(count), tmp);
        ++count;
    }
    data.insert(QLatin1String(KIT_COUNT_KEY), count);
    data.insert(QLatin1String(KIT_DEFAULT_KEY),
                d->m_defaultKit ? QString::fromLatin1(d->m_defaultKit->id().name()) : QString());
    d->m_writer->save(data, Core::ICore::mainWindow());
}

bool greaterPriority(KitInformation *a, KitInformation *b)
{
    return a->priority() > b->priority();
}

void KitManager::registerKitInformation(KitInformation *ki)
{
    QList<KitInformation *>::iterator it
            = qLowerBound(d->m_informationList.begin(), d->m_informationList.end(), ki, greaterPriority);
    d->m_informationList.insert(it, ki);

    connect(ki, SIGNAL(validationNeeded()), this, SLOT(validateKits()));

    if (!d->m_initialized)
        return;

    foreach (Kit *k, kits()) {
        if (!k->hasValue(ki->dataId()))
            k->setValue(ki->dataId(), ki->defaultValue(k));
    }

    return;
}

void KitManager::deregisterKitInformation(KitInformation *ki)
{
    Q_ASSERT(d->m_informationList.contains(ki));
    d->m_informationList.removeAll(ki);
    delete ki;
}

KitManager::KitList KitManager::restoreKits(const Utils::FileName &fileName)
{
    KitList result;

    PersistentSettingsReader reader;
    if (!reader.load(fileName)) {
        qWarning("Warning: Failed to read \"%s\", cannot restore kits!", qPrintable(fileName.toUserOutput()));
        return result;
    }
    QVariantMap data = reader.restoreValues();

    // Check version:
    int version = data.value(QLatin1String(KIT_FILE_VERSION_KEY), 0).toInt();
    if (version < 1) {
        qWarning("Warning: Kit file version %d not supported, cannot restore kits!", version);
        return result;
    }

    const int count = data.value(QLatin1String(KIT_COUNT_KEY), 0).toInt();
    for (int i = 0; i < count; ++i) {
        const QString key = QString::fromLatin1(KIT_DATA_KEY) + QString::number(i);
        if (!data.contains(key))
            break;

        const QVariantMap stMap = data.value(key).toMap();

        Kit *k = new Kit;
        if (k->fromMap(stMap)) {
            result.kits.append(k);
        } else {
            delete k;
            qWarning("Warning: Unable to restore kits stored in %s at position %d.",
                     qPrintable(fileName.toUserOutput()), i);
        }
    }
    const QString defaultId = data.value(QLatin1String(KIT_DEFAULT_KEY)).toString();
    if (defaultId.isEmpty())
        return result;

    const Core::Id id = Core::Id(defaultId);
    foreach (Kit *k, result.kits) {
        if (k->id() == id) {
            result.defaultKit = id;
            break;
        }
    }
    return result;
}

QList<Kit *> KitManager::kits(const KitMatcher *m) const
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        const_cast<KitManager *>(this)->restoreKits();
    }

    QList<Kit *> result;
    foreach (Kit *k, d->m_kitList) {
        if (!m || m->matches(k))
            result.append(k);
    }
    return result;
}

Kit *KitManager::find(const Core::Id &id) const
{
    if (!id.isValid())
        return 0;

    foreach (Kit *k, kits()) {
        if (k->id() == id)
            return k;
    }
    return 0;
}

Kit *KitManager::find(const KitMatcher *m) const
{
    QList<Kit *> matched = kits(m);
    return matched.isEmpty() ? 0 : matched.first();
}

Kit *KitManager::defaultKit()
{
    if (!d->m_initialized) {
        d->m_initialized = true;
        restoreKits();
    }
    return d->m_defaultKit;
}

QList<KitInformation *> KitManager::kitInformation() const
{
    return d->m_informationList;
}

Internal::KitManagerConfigWidget *KitManager::createConfigWidget(Kit *k) const
{
    if (!k)
        return 0;

    Internal::KitManagerConfigWidget *result = new Internal::KitManagerConfigWidget(k);
    foreach (KitInformation *ki, d->m_informationList)
        result->addConfigWidget(ki->createConfigWidget(k));

    return result;
}

void KitManager::notifyAboutUpdate(ProjectExplorer::Kit *k)
{
    if (!k || !kits().contains(k))
        return;
    d->validateKit(k);
    emit kitUpdated(k);
}

bool KitManager::registerKit(ProjectExplorer::Kit *k)
{
    if (!k)
        return true;
    foreach (Kit *current, kits()) {
        if (k == current)
            return false;
    }

    // make sure we have all the information in our kits:
    foreach (KitInformation *ki, d->m_informationList) {
        if (!k->hasValue(ki->dataId()))
            k->setValue(ki->dataId(), ki->defaultValue(k));
    }

    addKit(k);
    emit kitAdded(k);
    return true;
}

void KitManager::deregisterKit(Kit *k)
{
    if (!k || !kits().contains(k))
        return;
    d->m_kitList.removeOne(k);
    if (d->m_defaultKit == k) {
        QList<Kit *> stList = kits();
        Kit *newDefault = 0;
        foreach (Kit *cur, stList) {
            if (cur->isValid()) {
                newDefault = cur;
                break;
            }
        }
        setDefaultKit(newDefault);
    }
    emit kitRemoved(k);
    delete k;
}

QList<Task> KitManager::validateKit(Kit *k)
{
    QList<Task> result = d->validateKit(k);
    qSort(result);
    return result;
}

void KitManager::setDefaultKit(Kit *k)
{
    if (d->m_defaultKit == k)
        return;
    if (k && !kits().contains(k))
        return;
    d->m_defaultKit = k;
    emit defaultkitChanged();
}

void KitManager::validateKits()
{
    foreach (Kit *k, kits())
        d->validateKit(k);
}

void KitManager::addKit(Kit *k)
{
    if (!k)
        return;
    k->setDisplayName(k->displayName()); // make name unique
    d->validateKit(k);
    d->m_kitList.append(k);
    if (!d->m_defaultKit ||
            (!d->m_defaultKit->isValid() && k->isValid()))
        setDefaultKit(k);
}

void KitInformation::addToEnvironment(const Kit *k, Utils::Environment &env) const
{
    Q_UNUSED(k);
    Q_UNUSED(env);
}

QString KitInformation::displayNamePostfix(const Kit *k) const
{
    Q_UNUSED(k);
    return QString();
}

} // namespace ProjectExplorer
<|endoftext|>


<commit_before>/**************************************************************************
**
** Copyright (C) 2012, 2013 BlackBerry Limited. All rights reserved.
**
** Contact: BlackBerry (qt@blackberry.com)
** Contact: KDAB (info@kdab.com)
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "blackberrydebugsupport.h"
#include "blackberryapplicationrunner.h"

#include <debugger/debuggerrunner.h>
#include <debugger/debuggerengine.h>
#include <debugger/debuggerstartparameters.h>

using namespace Qnx;
using namespace Qnx::Internal;

BlackBerryDebugSupport::BlackBerryDebugSupport(BlackBerryRunConfiguration *runConfig,
                                 Debugger::DebuggerRunControl *runControl)
    : QObject(runControl->engine())
    , m_engine(runControl->engine())
{
    m_runner = new BlackBerryApplicationRunner(true, runConfig, this);

    connect(m_engine, SIGNAL(requestRemoteSetup()), this, SLOT(launchRemoteApplication()));
    connect(m_engine, SIGNAL(stateChanged(Debugger::DebuggerState)),
            this, SLOT(handleDebuggerStateChanged(Debugger::DebuggerState)));

    connect(m_runner, SIGNAL(started()), this, SLOT(handleStarted()));
    connect(m_runner, SIGNAL(startFailed(QString)), this, SLOT(handleStartFailed(QString)));
    connect(m_runner, SIGNAL(started()), m_runner, SLOT(checkSlog2Info()));
    connect(m_runner, SIGNAL(output(QString,Utils::OutputFormat)),
            this, SLOT(handleApplicationOutput(QString,Utils::OutputFormat)));

    connect(this, SIGNAL(output(QString,Utils::OutputFormat)),
            runControl, SLOT(appendMessage(QString,Utils::OutputFormat)));
}

void BlackBerryDebugSupport::launchRemoteApplication()
{
    m_runner->start();
}

void BlackBerryDebugSupport::handleStarted()
{
    m_engine->startParameters().attachPID = m_runner->pid();
    m_engine->notifyEngineRemoteSetupDone(8000, -1);
}

void BlackBerryDebugSupport::handleStartFailed(const QString &message)
{
    m_engine->notifyEngineRemoteSetupFailed(message);
}

void BlackBerryDebugSupport::handleDebuggerStateChanged(Debugger::DebuggerState state)
{
    if (state == Debugger::EngineShutdownOk || state == Debugger::DebuggerFinished) {
        if (m_runner->isRunning())
            m_runner->stop();
    }
}

void BlackBerryDebugSupport::handleApplicationOutput(const QString &msg, Utils::OutputFormat format)
{
    Q_UNUSED(format)
    m_engine->showMessage(msg, Debugger::AppOutput);
}
<commit_msg>QNX: Remove dead code<commit_after>/**************************************************************************
**
** Copyright (C) 2012, 2013 BlackBerry Limited. All rights reserved.
**
** Contact: BlackBerry (qt@blackberry.com)
** Contact: KDAB (info@kdab.com)
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "blackberrydebugsupport.h"
#include "blackberryapplicationrunner.h"

#include <debugger/debuggerrunner.h>
#include <debugger/debuggerengine.h>
#include <debugger/debuggerstartparameters.h>

using namespace Qnx;
using namespace Qnx::Internal;

BlackBerryDebugSupport::BlackBerryDebugSupport(BlackBerryRunConfiguration *runConfig,
                                 Debugger::DebuggerRunControl *runControl)
    : QObject(runControl->engine())
    , m_engine(runControl->engine())
{
    m_runner = new BlackBerryApplicationRunner(true, runConfig, this);

    connect(m_engine, SIGNAL(requestRemoteSetup()), this, SLOT(launchRemoteApplication()));
    connect(m_engine, SIGNAL(stateChanged(Debugger::DebuggerState)),
            this, SLOT(handleDebuggerStateChanged(Debugger::DebuggerState)));

    connect(m_runner, SIGNAL(started()), this, SLOT(handleStarted()));
    connect(m_runner, SIGNAL(startFailed(QString)), this, SLOT(handleStartFailed(QString)));
    connect(m_runner, SIGNAL(output(QString,Utils::OutputFormat)),
            this, SLOT(handleApplicationOutput(QString,Utils::OutputFormat)));

    connect(this, SIGNAL(output(QString,Utils::OutputFormat)),
            runControl, SLOT(appendMessage(QString,Utils::OutputFormat)));
}

void BlackBerryDebugSupport::launchRemoteApplication()
{
    m_runner->start();
}

void BlackBerryDebugSupport::handleStarted()
{
    m_engine->startParameters().attachPID = m_runner->pid();
    m_engine->notifyEngineRemoteSetupDone(8000, -1);
}

void BlackBerryDebugSupport::handleStartFailed(const QString &message)
{
    m_engine->notifyEngineRemoteSetupFailed(message);
}

void BlackBerryDebugSupport::handleDebuggerStateChanged(Debugger::DebuggerState state)
{
    if (state == Debugger::EngineShutdownOk || state == Debugger::DebuggerFinished) {
        if (m_runner->isRunning())
            m_runner->stop();
    }
}

void BlackBerryDebugSupport::handleApplicationOutput(const QString &msg, Utils::OutputFormat format)
{
    Q_UNUSED(format)
    m_engine->showMessage(msg, Debugger::AppOutput);
}
<|endoftext|>