<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "buildsettingspropertiespage.h"
#include "buildstep.h"
#include "buildstepspage.h"
#include "project.h"
#include "buildconfiguration.h"

#include <coreplugin/coreconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>

#include <QtCore/QMargins>
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
#include <QtGui/QInputDialog>
#include <QtGui/QLabel>
#include <QtGui/QMenu>
#include <QtGui/QPushButton>
#include <QtGui/QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

///
// BuildSettingsPanelFactory
///

bool BuildSettingsPanelFactory::supports(Project *project)
{
    return project->hasBuildSettings();
}

IPropertiesPanel *BuildSettingsPanelFactory::createPanel(Project *project)
{
    return new BuildSettingsPanel(project);
}

///
// BuildSettingsPanel
///

BuildSettingsPanel::BuildSettingsPanel(Project *project) :
    m_widget(new BuildSettingsWidget(project)),
    m_icon(":/projectexplorer/images/rebuild.png")
{
}

BuildSettingsPanel::~BuildSettingsPanel()
{
    delete m_widget;
}

QString BuildSettingsPanel::name() const
{
    return QApplication::tr("Build Settings");
}

QWidget *BuildSettingsPanel::widget() const
{
    return m_widget;
}

QIcon BuildSettingsPanel::icon() const
{
    return m_icon;
}

///
// BuildSettingsWidget
///

BuildSettingsWidget::~BuildSettingsWidget()
{
    clear();
}

BuildSettingsWidget::BuildSettingsWidget(Project *project) :
    m_project(project),
    m_buildConfiguration(0),
    m_leftMargin(0)
{
    // Provide some time for our contentsmargins to get updated:
    QTimer::singleShot(0, this, SLOT(init()));
}

void BuildSettingsWidget::init()
{
    QMargins margins(contentsMargins());
    m_leftMargin = margins.left();
    margins.setLeft(0);
    setContentsMargins(margins);

    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setContentsMargins(0, 0, 0, 0);

    { // Edit Build Configuration row
        QHBoxLayout *hbox = new QHBoxLayout();
        hbox->setContentsMargins(m_leftMargin, 0, 0, 0);
        hbox->addWidget(new QLabel(tr("Edit Build Configuration:"), this));
        m_buildConfigurationComboBox = new QComboBox(this);
        m_buildConfigurationComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
        hbox->addWidget(m_buildConfigurationComboBox);

        m_addButton = new QPushButton(this);
        m_addButton->setText(tr("Add"));
        m_addButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_addButton);
        m_addButtonMenu = new QMenu(this);
        m_addButton->setMenu(m_addButtonMenu);

        m_removeButton = new QPushButton(this);
        m_removeButton->setText(tr("Remove"));
        m_removeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_removeButton);
        hbox->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
        vbox->addLayout(hbox);
    }

    m_makeActiveLabel = new QLabel(this);
    m_makeActiveLabel->setVisible(false);
    vbox->addWidget(m_makeActiveLabel);

    m_buildConfiguration = m_project->activeBuildConfiguration();

    connect(m_makeActiveLabel, SIGNAL(linkActivated(QString)),
            this, SLOT(makeActive()));

    connect(m_buildConfigurationComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(currentIndexChanged(int)));

    connect(m_removeButton, SIGNAL(clicked()),
            this, SLOT(deleteConfiguration()));

    // TODO update on displayNameChange
//    connect(m_project, SIGNAL(buildConfigurationDisplayNameChanged(const QString &)),
//            this, SLOT(buildConfigurationDisplayNameChanged(const QString &)));

    connect(m_project, SIGNAL(activeBuildConfigurationChanged()),
            this, SLOT(checkMakeActiveLabel()));

    if (m_project->buildConfigurationFactory())
        connect(m_project->buildConfigurationFactory(), SIGNAL(availableCreationTypesChanged()), SLOT(updateAddButtonMenu()));

    updateAddButtonMenu();
    updateBuildSettings();
}

void BuildSettingsWidget::addSubWidget(const QString &name, QWidget *widget)
{
    widget->setContentsMargins(m_leftMargin, 10, 0, 0);

    QLabel *label = new QLabel(this);
    label->setText(name);
    QFont f = label->font();
    f.setBold(true);
    f.setPointSizeF(f.pointSizeF() * 1.2);
    label->setFont(f);

    label->setContentsMargins(m_leftMargin, 10, 0, 0);

    layout()->addWidget(label);
    layout()->addWidget(widget);

    m_labels.append(label);
    m_subWidgets.append(widget);
}

void BuildSettingsWidget::clear()
{
    qDeleteAll(m_subWidgets);
    m_subWidgets.clear();
    qDeleteAll(m_labels);
    m_labels.clear();

}

QList<QWidget *> BuildSettingsWidget::subWidgets() const
{
    return m_subWidgets;
}

void BuildSettingsWidget::makeActive()
{
    m_project->setActiveBuildConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::updateAddButtonMenu()
{
    m_addButtonMenu->clear();
    m_addButtonMenu->addAction(tr("&Clone Selected"),
                               this, SLOT(cloneConfiguration()));
    IBuildConfigurationFactory *factory = m_project->buildConfigurationFactory();
    if (factory) {
        foreach (const QString &type, factory->availableCreationTypes()) {
            QAction *action = m_addButtonMenu->addAction(factory->displayNameForType(type), this, SLOT(createConfiguration()));
            action->setData(type);
        }
    }
}

void BuildSettingsWidget::updateBuildSettings()
{
    // TODO save position, entry from combbox

    // Delete old tree items
    bool blocked = m_buildConfigurationComboBox->blockSignals(true);
    m_buildConfigurationComboBox->clear();
    clear();

    // update buttons
    m_removeButton->setEnabled(m_project->buildConfigurations().size() > 1);

    // Add pages
    BuildConfigWidget *generalConfigWidget = m_project->createConfigWidget();
    addSubWidget(generalConfigWidget->displayName(), generalConfigWidget);

    addSubWidget(tr("Build Steps"), new BuildStepsPage(m_project, false));
    addSubWidget(tr("Clean Steps"), new BuildStepsPage(m_project, true));

    QList<BuildConfigWidget *> subConfigWidgets = m_project->subConfigWidgets();
    foreach (BuildConfigWidget *subConfigWidget, subConfigWidgets)
        addSubWidget(subConfigWidget->displayName(), subConfigWidget);

    // Add tree items
    foreach (BuildConfiguration *bc, m_project->buildConfigurations()) {
        m_buildConfigurationComboBox->addItem(bc->displayName(), QVariant::fromValue<BuildConfiguration *>(bc));
        if (bc == m_buildConfiguration)
            m_buildConfigurationComboBox->setCurrentIndex(m_buildConfigurationComboBox->count() - 1);
    }

    m_buildConfigurationComboBox->blockSignals(blocked);

    // TODO Restore position, entry from combbox
    // TODO? select entry from combobox ?

    activeBuildConfigurationChanged();
}

void BuildSettingsWidget::currentIndexChanged(int index)
{
    m_buildConfiguration = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
    activeBuildConfigurationChanged();
}

void BuildSettingsWidget::activeBuildConfigurationChanged()
{
    for (int i = 0; i < m_buildConfigurationComboBox->count(); ++i) {
        if (m_buildConfigurationComboBox->itemData(i).value<BuildConfiguration *>() == m_buildConfiguration) {
            m_buildConfigurationComboBox->setCurrentIndex(i);
            break;
        }
    }
    foreach (QWidget *widget, subWidgets()) {
        if (BuildConfigWidget *buildStepWidget = qobject_cast<BuildConfigWidget*>(widget)) {
            buildStepWidget->init(m_buildConfiguration);
        }
    }
    checkMakeActiveLabel();
}

void BuildSettingsWidget::checkMakeActiveLabel()
{
    m_makeActiveLabel->setVisible(false);
    if (!m_project->activeBuildConfiguration() || m_project->activeBuildConfiguration() != m_buildConfiguration) {
        m_makeActiveLabel->setText(tr("Make %1 active.").arg(m_buildConfiguration->displayName()));
        m_makeActiveLabel->setVisible(true);
    }
}

void BuildSettingsWidget::createConfiguration()
{
    QAction *action = qobject_cast<QAction *>(sender());
    const QString &type = action->data().toString();
    BuildConfiguration *bc = m_project->buildConfigurationFactory()->create(type);
    if (bc) {
        m_buildConfiguration = bc;
        updateBuildSettings();
    }
}

void BuildSettingsWidget::cloneConfiguration()
{
    const int index = m_buildConfigurationComboBox->currentIndex();
    BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
    cloneConfiguration(bc);
}

void BuildSettingsWidget::deleteConfiguration()
{
    const int index = m_buildConfigurationComboBox->currentIndex();
    BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
    deleteConfiguration(bc);
}

void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration)
{
    if (!sourceConfiguration)
        return;

    QString newDisplayName(QInputDialog::getText(this, tr("Clone configuration"), tr("New Configuration Name:")));
    if (newDisplayName.isEmpty())
        return;

    QStringList buildConfigurationDisplayNames;
    foreach(BuildConfiguration *bc, m_project->buildConfigurations())
        buildConfigurationDisplayNames << bc->displayName();
    newDisplayName = Project::makeUnique(newDisplayName, buildConfigurationDisplayNames);

    m_buildConfiguration = m_project->buildConfigurationFactory()->clone(sourceConfiguration);
    m_buildConfiguration->setDisplayName(newDisplayName);
    m_project->addBuildConfiguration(m_buildConfiguration);

    updateBuildSettings();
}

void BuildSettingsWidget::deleteConfiguration(BuildConfiguration *deleteConfiguration)
{
    if (!deleteConfiguration || m_project->buildConfigurations().size() <= 1)
        return;

    if (m_project->activeBuildConfiguration() == deleteConfiguration) {
        foreach (BuildConfiguration *bc, m_project->buildConfigurations()) {
            if (bc != deleteConfiguration) {
                m_project->setActiveBuildConfiguration(bc);
                break;
            }
        }
    }

    if (m_buildConfiguration == deleteConfiguration) {
        foreach (BuildConfiguration *bc, m_project->buildConfigurations()) {
            if (bc != deleteConfiguration) {
                m_buildConfiguration = bc;
                break;
            }
        }
    }

    m_project->removeBuildConfiguration(deleteConfiguration);

    updateBuildSettings();
}
<commit_msg>Move "make active" label to proper location.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "buildsettingspropertiespage.h"
#include "buildstep.h"
#include "buildstepspage.h"
#include "project.h"
#include "buildconfiguration.h"

#include <coreplugin/coreconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>

#include <QtCore/QMargins>
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
#include <QtGui/QInputDialog>
#include <QtGui/QLabel>
#include <QtGui/QMenu>
#include <QtGui/QPushButton>
#include <QtGui/QVBoxLayout>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

///
// BuildSettingsPanelFactory
///

bool BuildSettingsPanelFactory::supports(Project *project)
{
    return project->hasBuildSettings();
}

IPropertiesPanel *BuildSettingsPanelFactory::createPanel(Project *project)
{
    return new BuildSettingsPanel(project);
}

///
// BuildSettingsPanel
///

BuildSettingsPanel::BuildSettingsPanel(Project *project) :
    m_widget(new BuildSettingsWidget(project)),
    m_icon(":/projectexplorer/images/rebuild.png")
{
}

BuildSettingsPanel::~BuildSettingsPanel()
{
    delete m_widget;
}

QString BuildSettingsPanel::name() const
{
    return QApplication::tr("Build Settings");
}

QWidget *BuildSettingsPanel::widget() const
{
    return m_widget;
}

QIcon BuildSettingsPanel::icon() const
{
    return m_icon;
}

///
// BuildSettingsWidget
///

BuildSettingsWidget::~BuildSettingsWidget()
{
    clear();
}

BuildSettingsWidget::BuildSettingsWidget(Project *project) :
    m_project(project),
    m_buildConfiguration(0),
    m_leftMargin(0)
{
    // Provide some time for our contentsmargins to get updated:
    QTimer::singleShot(0, this, SLOT(init()));
}

void BuildSettingsWidget::init()
{
    QMargins margins(contentsMargins());
    m_leftMargin = margins.left();
    margins.setLeft(0);
    setContentsMargins(margins);

    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setContentsMargins(0, 0, 0, 0);

    { // Edit Build Configuration row
        QHBoxLayout *hbox = new QHBoxLayout();
        hbox->setContentsMargins(m_leftMargin, 0, 0, 0);
        hbox->addWidget(new QLabel(tr("Edit Build Configuration:"), this));
        m_buildConfigurationComboBox = new QComboBox(this);
        m_buildConfigurationComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
        hbox->addWidget(m_buildConfigurationComboBox);

        m_addButton = new QPushButton(this);
        m_addButton->setText(tr("Add"));
        m_addButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_addButton);
        m_addButtonMenu = new QMenu(this);
        m_addButton->setMenu(m_addButtonMenu);

        m_removeButton = new QPushButton(this);
        m_removeButton->setText(tr("Remove"));
        m_removeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        hbox->addWidget(m_removeButton);
        hbox->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
        vbox->addLayout(hbox);
    }

    m_makeActiveLabel = new QLabel(this);
    m_makeActiveLabel->setContentsMargins(m_leftMargin, 4, 0, 4);
    m_makeActiveLabel->setVisible(false);
    vbox->addWidget(m_makeActiveLabel);

    m_buildConfiguration = m_project->activeBuildConfiguration();

    connect(m_makeActiveLabel, SIGNAL(linkActivated(QString)),
            this, SLOT(makeActive()));

    connect(m_buildConfigurationComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(currentIndexChanged(int)));

    connect(m_removeButton, SIGNAL(clicked()),
            this, SLOT(deleteConfiguration()));

    // TODO update on displayNameChange
//    connect(m_project, SIGNAL(buildConfigurationDisplayNameChanged(const QString &)),
//            this, SLOT(buildConfigurationDisplayNameChanged(const QString &)));

    connect(m_project, SIGNAL(activeBuildConfigurationChanged()),
            this, SLOT(checkMakeActiveLabel()));

    if (m_project->buildConfigurationFactory())
        connect(m_project->buildConfigurationFactory(), SIGNAL(availableCreationTypesChanged()), SLOT(updateAddButtonMenu()));

    updateAddButtonMenu();
    updateBuildSettings();
}

void BuildSettingsWidget::addSubWidget(const QString &name, QWidget *widget)
{
    widget->setContentsMargins(m_leftMargin, 10, 0, 0);

    QLabel *label = new QLabel(this);
    label->setText(name);
    QFont f = label->font();
    f.setBold(true);
    f.setPointSizeF(f.pointSizeF() * 1.2);
    label->setFont(f);

    label->setContentsMargins(m_leftMargin, 10, 0, 0);

    layout()->addWidget(label);
    layout()->addWidget(widget);

    m_labels.append(label);
    m_subWidgets.append(widget);
}

void BuildSettingsWidget::clear()
{
    qDeleteAll(m_subWidgets);
    m_subWidgets.clear();
    qDeleteAll(m_labels);
    m_labels.clear();

}

QList<QWidget *> BuildSettingsWidget::subWidgets() const
{
    return m_subWidgets;
}

void BuildSettingsWidget::makeActive()
{
    m_project->setActiveBuildConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::updateAddButtonMenu()
{
    m_addButtonMenu->clear();
    m_addButtonMenu->addAction(tr("&Clone Selected"),
                               this, SLOT(cloneConfiguration()));
    IBuildConfigurationFactory *factory = m_project->buildConfigurationFactory();
    if (factory) {
        foreach (const QString &type, factory->availableCreationTypes()) {
            QAction *action = m_addButtonMenu->addAction(factory->displayNameForType(type), this, SLOT(createConfiguration()));
            action->setData(type);
        }
    }
}

void BuildSettingsWidget::updateBuildSettings()
{
    // TODO save position, entry from combbox

    // Delete old tree items
    bool blocked = m_buildConfigurationComboBox->blockSignals(true);
    m_buildConfigurationComboBox->clear();
    clear();

    // update buttons
    m_removeButton->setEnabled(m_project->buildConfigurations().size() > 1);

    // Add pages
    BuildConfigWidget *generalConfigWidget = m_project->createConfigWidget();
    addSubWidget(generalConfigWidget->displayName(), generalConfigWidget);

    addSubWidget(tr("Build Steps"), new BuildStepsPage(m_project, false));
    addSubWidget(tr("Clean Steps"), new BuildStepsPage(m_project, true));

    QList<BuildConfigWidget *> subConfigWidgets = m_project->subConfigWidgets();
    foreach (BuildConfigWidget *subConfigWidget, subConfigWidgets)
        addSubWidget(subConfigWidget->displayName(), subConfigWidget);

    // Add tree items
    foreach (BuildConfiguration *bc, m_project->buildConfigurations()) {
        m_buildConfigurationComboBox->addItem(bc->displayName(), QVariant::fromValue<BuildConfiguration *>(bc));
        if (bc == m_buildConfiguration)
            m_buildConfigurationComboBox->setCurrentIndex(m_buildConfigurationComboBox->count() - 1);
    }

    m_buildConfigurationComboBox->blockSignals(blocked);

    // TODO Restore position, entry from combbox
    // TODO? select entry from combobox ?

    activeBuildConfigurationChanged();
}

void BuildSettingsWidget::currentIndexChanged(int index)
{
    m_buildConfiguration = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
    activeBuildConfigurationChanged();
}

void BuildSettingsWidget::activeBuildConfigurationChanged()
{
    for (int i = 0; i < m_buildConfigurationComboBox->count(); ++i) {
        if (m_buildConfigurationComboBox->itemData(i).value<BuildConfiguration *>() == m_buildConfiguration) {
            m_buildConfigurationComboBox->setCurrentIndex(i);
            break;
        }
    }
    foreach (QWidget *widget, subWidgets()) {
        if (BuildConfigWidget *buildStepWidget = qobject_cast<BuildConfigWidget*>(widget)) {
            buildStepWidget->init(m_buildConfiguration);
        }
    }
    checkMakeActiveLabel();
}

void BuildSettingsWidget::checkMakeActiveLabel()
{
    m_makeActiveLabel->setVisible(false);
    if (!m_project->activeBuildConfiguration() || m_project->activeBuildConfiguration() != m_buildConfiguration) {
        m_makeActiveLabel->setText(tr("Make %1 active.").arg(m_buildConfiguration->displayName()));
        m_makeActiveLabel->setVisible(true);
    }
}

void BuildSettingsWidget::createConfiguration()
{
    QAction *action = qobject_cast<QAction *>(sender());
    const QString &type = action->data().toString();
    BuildConfiguration *bc = m_project->buildConfigurationFactory()->create(type);
    if (bc) {
        m_buildConfiguration = bc;
        updateBuildSettings();
    }
}

void BuildSettingsWidget::cloneConfiguration()
{
    const int index = m_buildConfigurationComboBox->currentIndex();
    BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
    cloneConfiguration(bc);
}

void BuildSettingsWidget::deleteConfiguration()
{
    const int index = m_buildConfigurationComboBox->currentIndex();
    BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(index).value<BuildConfiguration *>();
    deleteConfiguration(bc);
}

void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration)
{
    if (!sourceConfiguration)
        return;

    QString newDisplayName(QInputDialog::getText(this, tr("Clone configuration"), tr("New Configuration Name:")));
    if (newDisplayName.isEmpty())
        return;

    QStringList buildConfigurationDisplayNames;
    foreach(BuildConfiguration *bc, m_project->buildConfigurations())
        buildConfigurationDisplayNames << bc->displayName();
    newDisplayName = Project::makeUnique(newDisplayName, buildConfigurationDisplayNames);

    m_buildConfiguration = m_project->buildConfigurationFactory()->clone(sourceConfiguration);
    m_buildConfiguration->setDisplayName(newDisplayName);
    m_project->addBuildConfiguration(m_buildConfiguration);

    updateBuildSettings();
}

void BuildSettingsWidget::deleteConfiguration(BuildConfiguration *deleteConfiguration)
{
    if (!deleteConfiguration || m_project->buildConfigurations().size() <= 1)
        return;

    if (m_project->activeBuildConfiguration() == deleteConfiguration) {
        foreach (BuildConfiguration *bc, m_project->buildConfigurations()) {
            if (bc != deleteConfiguration) {
                m_project->setActiveBuildConfiguration(bc);
                break;
            }
        }
    }

    if (m_buildConfiguration == deleteConfiguration) {
        foreach (BuildConfiguration *bc, m_project->buildConfigurations()) {
            if (bc != deleteConfiguration) {
                m_buildConfiguration = bc;
                break;
            }
        }
    }

    m_project->removeBuildConfiguration(deleteConfiguration);

    updateBuildSettings();
}
<|endoftext|>


<commit_before>
#include "obj_to_vertex_array.h"

#include <limits>
#include <map>

#include <scm/core/utilities/foreach.h>

namespace {

struct obj_vert_index
{
    unsigned    _v;
    unsigned    _t;
    unsigned    _n;

    obj_vert_index(unsigned v, unsigned t, unsigned n) : _v(v), _t(t), _n(n) {}
    // lexicographic compare of the index vector
    bool operator<(const obj_vert_index& rhs) const {
        if (_v == rhs._v && _t == rhs._t) return (_n < rhs._n);
        if (_v == rhs._v) return (_t < rhs._t);
        return (_v < rhs._v);
    }

}; // struct obj_vert_index

} // namespace

namespace scm {
namespace data {

bool generate_vertex_buffer(const wavefront_model&               in_obj,
                            vertexbuffer_data&                   out_data,
                            bool                                 interleave_arrays)
{
    if (interleave_arrays) {
        return (false);
    }

    typedef std::map<obj_vert_index, unsigned>      index_mapping;
    typedef index_mapping::value_type               index_value;

    index_mapping       indices;

    wavefront_model::object_container::const_iterator     cur_obj_it;
    wavefront_object::group_container::const_iterator     cur_grp_it;
    unsigned index_buf_size = 0;

    // first pass
    // find out the size of our new arrays and reorder the indices

    out_data._index_arrays.reserve(in_obj._objects.size());
    out_data._index_array_counts.reserve(in_obj._objects.size());

    foreach (const wavefront_object& wf_obj, in_obj._objects) {
        foreach (const wavefront_object_group& wf_obj_grp, wf_obj._groups) {
            out_data._index_array_counts.push_back(3 * static_cast<unsigned>(wf_obj_grp._num_tri_faces));

            wavefront_model::material_container::const_iterator mat = in_obj._materials.find(wf_obj_grp._material_name);

            if (mat != in_obj._materials.end()) {
                out_data._materials.push_back(mat->second);
            }
            else {
                out_data._materials.push_back(wavefront_material());
            }
        }
    }

    vertexbuffer_data::index_counts_container::iterator     cur_index_count = out_data._index_array_counts.begin();

    unsigned new_index      = 0;
    unsigned iarray_index   = 0;

    foreach (const wavefront_object& wf_obj, in_obj._objects) {
        foreach (const wavefront_object_group& wf_obj_grp, wf_obj._groups) {

            iarray_index   = 0;

            // initialize index array
            out_data._index_arrays.push_back(boost::shared_array<core::uint32_t>());
            vertexbuffer_data::index_array_container::value_type& cur_index_array = out_data._index_arrays.back();
            cur_index_array.reset(new core::uint32_t[*cur_index_count]);

            // initialize bbox
            out_data._bboxes.push_back(aabbox());
            vertexbuffer_data::bbox_container::value_type& cur_bbox = out_data._bboxes.back();

            cur_bbox._min   = math::vec3f_t((std::numeric_limits<math::vec3f_t::component_type>::max)());
            cur_bbox._max   = math::vec3f_t((std::numeric_limits<math::vec3f_t::component_type>::min)());

            for (unsigned i = 0; i < wf_obj_grp._num_tri_faces; ++i) {
                const wavefront_object_triangle_face& cur_face = wf_obj_grp._tri_faces[i];

                for (unsigned k = 0; k < 3; ++k) {
                    obj_vert_index  cur_index(cur_face._vertices[k],
                                              in_obj._num_tex_coords != 0 ? cur_face._tex_coords[k] : 0,
                                              in_obj._num_normals    != 0 ? cur_face._normals[k] : 0);

                    // update bounding box
                    const math::vec3f_t& cur_vert = in_obj._vertices[cur_index._v];

                    for (unsigned c = 0; c < 3; ++c) {
                        cur_bbox._min.vec_array[c] = cur_vert.vec_array[c] < cur_bbox._min.vec_array[c] ? cur_vert.vec_array[c] : cur_bbox._min.vec_array[c];
                        cur_bbox._max.vec_array[c] = cur_vert.vec_array[c] > cur_bbox._max.vec_array[c] ? cur_vert.vec_array[c] : cur_bbox._max.vec_array[c];
                    }

                    // check index mapping
                    index_mapping::const_iterator prev_it = indices.find(cur_index);

                    if (prev_it == indices.end()) {
                        indices.insert(index_value(cur_index, new_index));
                        cur_index_array[iarray_index] = new_index;
                        ++new_index;
                    }
                    else {
                        cur_index_array[iarray_index] = prev_it->second;
                    }

                    ++iarray_index;
                }
            }

            ++cur_index_count;
        }
    }

    // second pass
    // copy vertex data according to new indices
    std::size_t     array_size = 3 * indices.size();
    if (in_obj._num_normals != 0) {
        array_size                 += 3 * indices.size();
        out_data._normals_offset    = 3 * indices.size();
    }
    else {
        out_data._normals_offset    = 0;
    }

    if (in_obj._num_tex_coords != 0) {
        array_size                 += 2 * indices.size();
        out_data._texcoords_offset  = out_data._normals_offset + 3 * indices.size();
    }
    else {
        out_data._texcoords_offset  = 0;
    }

    out_data._vert_array_count      = indices.size();
    out_data._vert_array.reset(new float[array_size]);

    unsigned varray_index = 0;

    for (index_mapping::const_iterator ind_it = indices.begin();
         ind_it != indices.end();
         ++ind_it) {

        const obj_vert_index&  cur_index = ind_it->first;

        varray_index =  ind_it->second;

        memcpy(out_data._vert_array.get() + varray_index * 3,
               in_obj._vertices[cur_index._v - 1].vec_array,
               3 * sizeof(float));

        if (out_data._normals_offset) {
            memcpy(out_data._vert_array.get() + varray_index * 3
                                              + out_data._normals_offset,
                   in_obj._normals[cur_index._n - 1].vec_array,
                   3 * sizeof(float));
        }
        if (out_data._texcoords_offset) {
            memcpy(out_data._vert_array.get() + varray_index * 2
                                              + out_data._texcoords_offset,
                   in_obj._tex_coords[cur_index._t - 1].vec_array,
                   2 * sizeof(float));
        }
    }

    return (true);
}

} // namespace data
} // namespace scm
<commit_msg>bugfix in obj vbo generator<commit_after>
#include "obj_to_vertex_array.h"

#include <limits>
#include <map>

#include <scm/core/utilities/foreach.h>

namespace {

struct obj_vert_index
{
    unsigned    _v;
    unsigned    _t;
    unsigned    _n;

    obj_vert_index(unsigned v, unsigned t, unsigned n) : _v(v), _t(t), _n(n) {}
    // lexicographic compare of the index vector
    bool operator<(const obj_vert_index& rhs) const {
        if (_v == rhs._v && _t == rhs._t) return (_n < rhs._n);
        if (_v == rhs._v) return (_t < rhs._t);
        return (_v < rhs._v);
    }

}; // struct obj_vert_index

} // namespace

namespace scm {
namespace data {

bool generate_vertex_buffer(const wavefront_model&               in_obj,
                            vertexbuffer_data&                   out_data,
                            bool                                 interleave_arrays)
{
    if (interleave_arrays) {
        return (false);
    }

    typedef std::map<obj_vert_index, unsigned>      index_mapping;
    typedef index_mapping::value_type               index_value;

    index_mapping       indices;

    wavefront_model::object_container::const_iterator     cur_obj_it;
    wavefront_object::group_container::const_iterator     cur_grp_it;
    unsigned index_buf_size = 0;

    // first pass
    // find out the size of our new arrays and reorder the indices

    out_data._index_arrays.reserve(in_obj._objects.size());
    out_data._index_array_counts.reserve(in_obj._objects.size());

    foreach (const wavefront_object& wf_obj, in_obj._objects) {
        foreach (const wavefront_object_group& wf_obj_grp, wf_obj._groups) {
            out_data._index_array_counts.push_back(3 * static_cast<unsigned>(wf_obj_grp._num_tri_faces));

            wavefront_model::material_container::const_iterator mat = in_obj._materials.find(wf_obj_grp._material_name);

            if (mat != in_obj._materials.end()) {
                out_data._materials.push_back(mat->second);
            }
            else {
                out_data._materials.push_back(wavefront_material());
            }
        }
    }

    vertexbuffer_data::index_counts_container::iterator     cur_index_count = out_data._index_array_counts.begin();

    unsigned new_index      = 0;
    unsigned iarray_index   = 0;

    foreach (const wavefront_object& wf_obj, in_obj._objects) {
        foreach (const wavefront_object_group& wf_obj_grp, wf_obj._groups) {

            iarray_index   = 0;

            // initialize index array
            out_data._index_arrays.push_back(boost::shared_array<core::uint32_t>());
            vertexbuffer_data::index_array_container::value_type& cur_index_array = out_data._index_arrays.back();
            cur_index_array.reset(new core::uint32_t[*cur_index_count]);

            // initialize bbox
            out_data._bboxes.push_back(aabbox());
            vertexbuffer_data::bbox_container::value_type& cur_bbox = out_data._bboxes.back();

            cur_bbox._min   = math::vec3f_t((std::numeric_limits<math::vec3f_t::component_type>::max)());
            cur_bbox._max   = math::vec3f_t((std::numeric_limits<math::vec3f_t::component_type>::min)());

            for (unsigned i = 0; i < wf_obj_grp._num_tri_faces; ++i) {
                const wavefront_object_triangle_face& cur_face = wf_obj_grp._tri_faces[i];

                for (unsigned k = 0; k < 3; ++k) {
                    obj_vert_index  cur_index(cur_face._vertices[k],
                                              in_obj._num_tex_coords != 0 ? cur_face._tex_coords[k] : 0,
                                              in_obj._num_normals    != 0 ? cur_face._normals[k] : 0);

                    // update bounding box
                    const math::vec3f_t& cur_vert = in_obj._vertices[cur_index._v - 1];

                    for (unsigned c = 0; c < 3; ++c) {
                        cur_bbox._min.vec_array[c] = cur_vert.vec_array[c] < cur_bbox._min.vec_array[c] ? cur_vert.vec_array[c] : cur_bbox._min.vec_array[c];
                        cur_bbox._max.vec_array[c] = cur_vert.vec_array[c] > cur_bbox._max.vec_array[c] ? cur_vert.vec_array[c] : cur_bbox._max.vec_array[c];
                    }

                    // check index mapping
                    index_mapping::const_iterator prev_it = indices.find(cur_index);

                    if (prev_it == indices.end()) {
                        indices.insert(index_value(cur_index, new_index));
                        cur_index_array[iarray_index] = new_index;
                        ++new_index;
                    }
                    else {
                        cur_index_array[iarray_index] = prev_it->second;
                    }

                    ++iarray_index;
                }
            }

            ++cur_index_count;
        }
    }

    // second pass
    // copy vertex data according to new indices
    std::size_t     array_size = 3 * indices.size();
    if (in_obj._num_normals != 0) {
        array_size                 += 3 * indices.size();
        out_data._normals_offset    = 3 * indices.size();
    }
    else {
        out_data._normals_offset    = 0;
    }

    if (in_obj._num_tex_coords != 0) {
        array_size                 += 2 * indices.size();
        out_data._texcoords_offset  = out_data._normals_offset + 3 * indices.size();
    }
    else {
        out_data._texcoords_offset  = 0;
    }

    out_data._vert_array_count      = indices.size();
    out_data._vert_array.reset(new float[array_size]);

    unsigned varray_index = 0;

    for (index_mapping::const_iterator ind_it = indices.begin();
         ind_it != indices.end();
         ++ind_it) {

        const obj_vert_index&  cur_index = ind_it->first;

        varray_index =  ind_it->second;

        memcpy(out_data._vert_array.get() + varray_index * 3,
               in_obj._vertices[cur_index._v - 1].vec_array,
               3 * sizeof(float));

        if (out_data._normals_offset) {
            memcpy(out_data._vert_array.get() + varray_index * 3
                                              + out_data._normals_offset,
                   in_obj._normals[cur_index._n - 1].vec_array,
                   3 * sizeof(float));
        }
        if (out_data._texcoords_offset) {
            memcpy(out_data._vert_array.get() + varray_index * 2
                                              + out_data._texcoords_offset,
                   in_obj._tex_coords[cur_index._t - 1].vec_array,
                   2 * sizeof(float));
        }
    }

    return (true);
}

} // namespace data
} // namespace scm
<|endoftext|>


<commit_before>//===--- XpcTracing.cpp ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "sourcekitd/XpcTracing.h"

#include "swift/Frontend/Frontend.h"

#include "llvm/Support/TimeValue.h"
#include "llvm/Support/YAMLTraits.h"

#include <xpc/xpc.h>

using namespace sourcekitd;
using namespace sourcekitd::trace;
using namespace llvm;

//===----------------------------------------------------------------------===//
// General
//===----------------------------------------------------------------------===//

static std::atomic<uint64_t> operation_id(0);
static uint64_t tracing_session = llvm::sys::TimeValue::now().msec();

uint64_t trace::getTracingSession() {
  return tracing_session;
}

static void append(xpc_object_t Contents, uint64_t Value) {
  xpc_array_set_uint64(Contents, XPC_ARRAY_APPEND, Value);
}

static void append(xpc_object_t Contents, ActionKind Value) {
  append(Contents, static_cast<uint64_t>(Value));
}

static void append(xpc_object_t Contents, OperationKind Value) {
  append(Contents, static_cast<uint64_t>(Value));
}

static void append(xpc_object_t Contents, llvm::StringRef Value) {
  xpc_array_set_string(Contents, XPC_ARRAY_APPEND, Value.data());
}

static void append(xpc_object_t Contents, const StringPairs &Files) {
  append(Contents, Files.size());
  std::for_each(Files.begin(), Files.end(),
                [&] (const std::pair<std::string, std::string> &File) {
                  append(Contents, File.first);
                  append(Contents, File.second);
                });
}

template <typename U>
struct llvm::yaml::SequenceTraits<std::vector<U>> {
  static size_t size(IO &Io, std::vector<U> &Vector) {
    return Vector.size();
  }
  static U &element(IO &Io, std::vector<U> &Vector, size_t Index) {
    return Vector[Index];
  }
};

template <>
struct llvm::yaml::MappingTraits<SwiftArguments> {
  static void mapping(IO &Io, SwiftArguments &Args) {

    Io.mapOptional("PrimaryFile", Args.PrimaryFile, std::string());
    Io.mapRequired("CompilerArgs", Args.Args);
  }
};

static std::string serializeCompilerArguments(const SwiftArguments &Args) {
  // Serialize compiler instance
  std::string OptionsAsYaml;
  llvm::raw_string_ostream OptionsStream(OptionsAsYaml);
  llvm::yaml::Output YamlOutput(OptionsStream);
  YamlOutput << const_cast<SwiftArguments &>(Args);
  OptionsStream.flush();
  return OptionsAsYaml;
}

//===----------------------------------------------------------------------===//
// Trace consumer
//===----------------------------------------------------------------------===//

class XpcTraceConsumer : public SourceKit::trace::TraceConsumer {
public:
  virtual ~XpcTraceConsumer() = default;

  // Operation previously started with startXXX has finished
  virtual void operationFinished(uint64_t OpId) override;

  // Trace start of SourceKit operation
  virtual void operationStarted(uint64_t OpId, OperationKind OpKind,
                                const SwiftInvocation &Inv,
                                const StringPairs &OpArgs) override;
};

// Trace start of SourceKit operation
void XpcTraceConsumer::operationStarted(uint64_t OpId,
                                        OperationKind OpKind,
                                        const SwiftInvocation &Inv,
                                        const StringPairs &OpArgs) {
  xpc_object_t Contents = xpc_array_create(nullptr, 0);
  append(Contents, ActionKind::OperationStarted);
  append(Contents, OpId);
  append(Contents, OpKind);
  append(Contents, serializeCompilerArguments(Inv.Args));
  append(Contents, Inv.Files);
  append(Contents, OpArgs);
  trace::sendTraceMessage(Contents);
}

// Operation previously started with startXXX has finished
void XpcTraceConsumer::operationFinished(uint64_t OpId) {
  xpc_object_t Contents = xpc_array_create(nullptr, 0);
  append(Contents, trace::ActionKind::OperationFinished);
  append(Contents, OpId);
  trace::sendTraceMessage(Contents);
}

static XpcTraceConsumer Instance;

void trace::initialize() {
  SourceKit::trace::registerConsumer(&Instance);
}

<commit_msg>[sourcekit] Remove unused variable to silence warning<commit_after>//===--- XpcTracing.cpp ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "sourcekitd/XpcTracing.h"

#include "swift/Frontend/Frontend.h"

#include "llvm/Support/TimeValue.h"
#include "llvm/Support/YAMLTraits.h"

#include <xpc/xpc.h>

using namespace sourcekitd;
using namespace sourcekitd::trace;
using namespace llvm;

//===----------------------------------------------------------------------===//
// General
//===----------------------------------------------------------------------===//

static uint64_t tracing_session = llvm::sys::TimeValue::now().msec();

uint64_t trace::getTracingSession() {
  return tracing_session;
}

static void append(xpc_object_t Contents, uint64_t Value) {
  xpc_array_set_uint64(Contents, XPC_ARRAY_APPEND, Value);
}

static void append(xpc_object_t Contents, ActionKind Value) {
  append(Contents, static_cast<uint64_t>(Value));
}

static void append(xpc_object_t Contents, OperationKind Value) {
  append(Contents, static_cast<uint64_t>(Value));
}

static void append(xpc_object_t Contents, llvm::StringRef Value) {
  xpc_array_set_string(Contents, XPC_ARRAY_APPEND, Value.data());
}

static void append(xpc_object_t Contents, const StringPairs &Files) {
  append(Contents, Files.size());
  std::for_each(Files.begin(), Files.end(),
                [&] (const std::pair<std::string, std::string> &File) {
                  append(Contents, File.first);
                  append(Contents, File.second);
                });
}

template <typename U>
struct llvm::yaml::SequenceTraits<std::vector<U>> {
  static size_t size(IO &Io, std::vector<U> &Vector) {
    return Vector.size();
  }
  static U &element(IO &Io, std::vector<U> &Vector, size_t Index) {
    return Vector[Index];
  }
};

template <>
struct llvm::yaml::MappingTraits<SwiftArguments> {
  static void mapping(IO &Io, SwiftArguments &Args) {

    Io.mapOptional("PrimaryFile", Args.PrimaryFile, std::string());
    Io.mapRequired("CompilerArgs", Args.Args);
  }
};

static std::string serializeCompilerArguments(const SwiftArguments &Args) {
  // Serialize compiler instance
  std::string OptionsAsYaml;
  llvm::raw_string_ostream OptionsStream(OptionsAsYaml);
  llvm::yaml::Output YamlOutput(OptionsStream);
  YamlOutput << const_cast<SwiftArguments &>(Args);
  OptionsStream.flush();
  return OptionsAsYaml;
}

//===----------------------------------------------------------------------===//
// Trace consumer
//===----------------------------------------------------------------------===//

class XpcTraceConsumer : public SourceKit::trace::TraceConsumer {
public:
  virtual ~XpcTraceConsumer() = default;

  // Operation previously started with startXXX has finished
  virtual void operationFinished(uint64_t OpId) override;

  // Trace start of SourceKit operation
  virtual void operationStarted(uint64_t OpId, OperationKind OpKind,
                                const SwiftInvocation &Inv,
                                const StringPairs &OpArgs) override;
};

// Trace start of SourceKit operation
void XpcTraceConsumer::operationStarted(uint64_t OpId,
                                        OperationKind OpKind,
                                        const SwiftInvocation &Inv,
                                        const StringPairs &OpArgs) {
  xpc_object_t Contents = xpc_array_create(nullptr, 0);
  append(Contents, ActionKind::OperationStarted);
  append(Contents, OpId);
  append(Contents, OpKind);
  append(Contents, serializeCompilerArguments(Inv.Args));
  append(Contents, Inv.Files);
  append(Contents, OpArgs);
  trace::sendTraceMessage(Contents);
}

// Operation previously started with startXXX has finished
void XpcTraceConsumer::operationFinished(uint64_t OpId) {
  xpc_object_t Contents = xpc_array_create(nullptr, 0);
  append(Contents, trace::ActionKind::OperationFinished);
  append(Contents, OpId);
  trace::sendTraceMessage(Contents);
}

static XpcTraceConsumer Instance;

void trace::initialize() {
  SourceKit::trace::registerConsumer(&Instance);
}

<|endoftext|>


<commit_before>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_PIONHASHMAP_HEADER__
#define __PION_PIONHASHMAP_HEADER__

#include <boost/functional/hash.hpp>
#include <pion/PionConfig.hpp>

#if defined(PION_HAVE_UNORDERED_MAP)
	#include <unordered_map>
	#define PION_HASH_MAP std::tr1::unordered_map
	#define PION_HASH_MULTIMAP std::tr1::unordered_multimap
	#define PION_HASH_STRING boost::hash<std::string>
#elif defined(PION_HAVE_EXT_HASH_MAP)
	#if __GNUC__ >= 3
		#include <ext/hash_map>
		#define PION_HASH_MAP __gnu_cxx::hash_map
		#define PION_HASH_MULTIMAP __gnu_cxx::hash_multimap
	#else
		#include <ext/hash_map>
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
	#endif
	#define PION_HASH_STRING boost::hash<std::string>
#elif defined(PION_HAVE_HASH_MAP)
	#include <hash_map>
	#ifdef _MSC_VER
		#define PION_HASH_MAP stdext::hash_map
		#define PION_HASH_MULTIMAP stdext::hash_multimap
		#define PION_HASH_STRING stdext::hash_compare<std::string, std::less<std::string> >
	#else
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
		#define PION_HASH_STRING boost::hash<std::string>
	#endif
#endif

#endif
<commit_msg>Added new macro PION_HASH(TYPE), a generalization of PION_HASH_STRING.<commit_after>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_PIONHASHMAP_HEADER__
#define __PION_PIONHASHMAP_HEADER__

#include <boost/functional/hash.hpp>
#include <pion/PionConfig.hpp>

#if defined(PION_HAVE_UNORDERED_MAP)
	#include <unordered_map>
	#define PION_HASH_MAP std::tr1::unordered_map
	#define PION_HASH_MULTIMAP std::tr1::unordered_multimap
	#define PION_HASH_STRING boost::hash<std::string>
	#define PION_HASH(TYPE) boost::hash<TYPE>
#elif defined(PION_HAVE_EXT_HASH_MAP)
	#if __GNUC__ >= 3
		#include <ext/hash_map>
		#define PION_HASH_MAP __gnu_cxx::hash_map
		#define PION_HASH_MULTIMAP __gnu_cxx::hash_multimap
	#else
		#include <ext/hash_map>
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
	#endif
	#define PION_HASH_STRING boost::hash<std::string>
	#define PION_HASH(TYPE) boost::hash<TYPE>
#elif defined(PION_HAVE_HASH_MAP)
	#include <hash_map>
	#ifdef _MSC_VER
		#define PION_HASH_MAP stdext::hash_map
		#define PION_HASH_MULTIMAP stdext::hash_multimap
		#define PION_HASH_STRING stdext::hash_compare<std::string, std::less<std::string> >
		#define PION_HASH(TYPE) stdext::hash_compare<TYPE, std::less<TYPE> >
	#else
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
		#define PION_HASH_STRING boost::hash<std::string>
		#define PION_HASH(TYPE) boost::hash<TYPE>
	#endif
#endif

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "service/storage_proxy.hh"
#include "service/paxos/proposal.hh"
#include "service/paxos/paxos_state.hh"
#include "db/system_keyspace.hh"
#include "schema_registry.hh"
#include "database.hh"

#include "service/storage_service.hh"

#include <utils/error_injection.hh>

namespace service::paxos {

logging::logger paxos_state::logger("paxos");
thread_local paxos_state::key_lock_map paxos_state::_paxos_table_lock;
thread_local paxos_state::key_lock_map paxos_state::_coordinator_lock;

paxos_state::key_lock_map::semaphore& paxos_state::key_lock_map::get_semaphore_for_key(const dht::token& key) {
    return _locks.try_emplace(key, 1).first->second;
}

void paxos_state::key_lock_map::release_semaphore_for_key(const dht::token& key) {
    auto it = _locks.find(key);
    if (it != _locks.end() && (*it).second.current() == 1) {
        _locks.erase(it);
    }
}

future<prepare_response> paxos_state::prepare(tracing::trace_state_ptr tr_state, schema_ptr schema,
        const query::read_command& cmd, const partition_key& key, utils::UUID ballot,
        bool only_digest, query::digest_algorithm da, clock_type::time_point timeout) {
    dht::token token = dht::get_token(*schema, key);
    utils::latency_counter lc;
    lc.start();
    return with_locked_key(token, timeout, [&cmd, token, &key, ballot, tr_state, schema, only_digest, da, timeout] () mutable {
        // When preparing, we need to use the same time as "now" (that's the time we use to decide if something
        // is expired or not) across nodes, otherwise we may have a window where a Most Recent Decision shows up
        // on some replica and not others during a new proposal (in storage_proxy::begin_and_repair_paxos()), and no
        // amount of re-submit will fix this (because the node on which the commit has expired will have a
        // tombstone that hides any re-submit). See CASSANDRA-12043 for details.
        auto now_in_sec = utils::UUID_gen::unix_timestamp_in_sec(ballot);

        return utils::get_local_injector().inject("paxos_state_prepare_timeout", timeout).then([&key, schema, now_in_sec, timeout] {
            return db::system_keyspace::load_paxos_state(key, schema, gc_clock::time_point(now_in_sec), timeout);
        }).then([&cmd, token = std::move(token), &key, ballot, tr_state, schema, only_digest, da, timeout] (paxos_state state) {
            // If received ballot is newer that the one we already accepted it has to be accepted as well,
            // but we will return the previously accepted proposal so that the new coordinator will use it instead of
            // its own.
            if (ballot.timestamp() > state._promised_ballot.timestamp()) {
                logger.debug("Promising ballot {}", ballot);
                tracing::trace(tr_state, "Promising ballot {}", ballot);
                auto f1 = futurize_invoke(db::system_keyspace::save_paxos_promise, *schema, std::ref(key), ballot, timeout);
                auto f2 = futurize_invoke([&] {
                    return do_with(dht::partition_range_vector({dht::partition_range::make_singular({token, key})}),
                            [tr_state, schema, &cmd, only_digest, da, timeout] (const dht::partition_range_vector& prv) {
                        return get_local_storage_proxy().get_db().local().query(schema, cmd,
                                {only_digest ? query::result_request::only_digest : query::result_request::result_and_digest, da},
                                prv, tr_state, query::result_memory_limiter::maximum_result_size, timeout);
                    });
                });
                return when_all(std::move(f1), std::move(f2)).then([state = std::move(state), only_digest] (auto t) {
                    auto&& f1 = std::get<0>(t);
                    auto&& f2 = std::get<1>(t);
                    if (f1.failed()) {
                        // Failed to save promise. Nothing we can do but throw.
                        return make_exception_future<prepare_response>(f1.get_exception());
                    }
                    std::optional<std::variant<foreign_ptr<lw_shared_ptr<query::result>>, query::result_digest>> data_or_digest;
                    // Silently ignore any errors querying the current value as the caller is prepared to fall back
                    // on querying it by itself in case it's missing in the response.
                    if (!f2.failed()) {
                        auto&& [result, hit_rate] = f2.get();
                        if (only_digest) {
                            data_or_digest = *result->digest();
                        } else {
                            data_or_digest = std::move(make_foreign(std::move(result)));
                        }
                    }
                    return make_ready_future<prepare_response>(prepare_response(promise(std::move(state._accepted_proposal),
                                    std::move(state._most_recent_commit), std::move(data_or_digest))));
                });
            } else {
                logger.debug("Promise rejected; {} is not sufficiently newer than {}", ballot, state._promised_ballot);
                tracing::trace(tr_state, "Promise rejected; {} is not sufficiently newer than {}", ballot, state._promised_ballot);
                // Return the currently promised ballot (rather than, e.g., the ballot of the last
                // accepted proposal) so the coordinator can make sure it uses a newer ballot next
                // time (#5667).
                return make_ready_future<prepare_response>(prepare_response(std::move(state._promised_ballot)));
            }
        });
    }).finally([schema, lc] () mutable {
        auto& stats = get_local_storage_proxy().get_db().local().find_column_family(schema).get_stats();
        stats.cas_prepare.mark(lc.stop().latency());
        if (lc.is_start()) {
            stats.estimated_cas_prepare.add(lc.latency(), stats.cas_prepare.hist.count);
        }
    });
}

future<bool> paxos_state::accept(tracing::trace_state_ptr tr_state, schema_ptr schema, dht::token token, const proposal& proposal,
        clock_type::time_point timeout) {
    utils::latency_counter lc;
    lc.start();

    return with_locked_key(token, timeout, [proposal = std::move(proposal), schema, tr_state, timeout] () mutable {
        auto now_in_sec = utils::UUID_gen::unix_timestamp_in_sec(proposal.ballot);
        auto f = db::system_keyspace::load_paxos_state(proposal.update.decorated_key(*schema).key(), schema,
                gc_clock::time_point(now_in_sec), timeout);
        return f.then([proposal = std::move(proposal), tr_state, schema, timeout] (paxos_state state) {
            return utils::get_local_injector().inject("paxos_state_accept_timeout", timeout).then(
                    [proposal = std::move(proposal), state = std::move(state), tr_state, schema, timeout] {
                // Accept the proposal if we promised to accept it or the proposal is newer than the one we promised.
                // Otherwise the proposal was cutoff by another Paxos proposer and has to be rejected.
                if (proposal.ballot == state._promised_ballot || proposal.ballot.timestamp() > state._promised_ballot.timestamp()) {
                    logger.debug("Accepting proposal {}", proposal);
                    tracing::trace(tr_state, "Accepting proposal {}", proposal);
                    return db::system_keyspace::save_paxos_proposal(*schema, proposal, timeout).then([] {
                            return true;
                    });
                } else {
                    logger.debug("Rejecting proposal for {} because in_progress is now {}", proposal, state._promised_ballot);
                    tracing::trace(tr_state, "Rejecting proposal for {} because in_progress is now {}", proposal, state._promised_ballot);
                    return make_ready_future<bool>(false);
                }
            });
        });
    }).finally([schema, lc] () mutable {
        auto& stats = get_local_storage_proxy().get_db().local().find_column_family(schema).get_stats();
        stats.cas_accept.mark(lc.stop().latency());
        if (lc.is_start()) {
            stats.estimated_cas_accept.add(lc.latency(), stats.cas_accept.hist.count);
        }
    });
}

future<> paxos_state::learn(schema_ptr schema, proposal decision, clock_type::time_point timeout,
        tracing::trace_state_ptr tr_state) {
    utils::latency_counter lc;
    lc.start();

    return do_with(std::move(decision), [tr_state = std::move(tr_state), schema, timeout] (proposal& decision) {
        auto f = utils::get_local_injector().inject("paxos_state_learn_timeout", timeout);

        table& cf = get_local_storage_proxy().get_db().local().find_column_family(schema);
        db_clock::time_point t = cf.get_truncation_record();
        auto truncated_at = std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch()).count();
        // When saving a decision, also delete the last accepted proposal. This is just an
        // optimization to save space.
        // Even though there is no guarantee we will see decisions in the right order,
        // because messages can get delayed, so this decision can be older than our current most
        // recent accepted proposal/committed decision, saving it is always safe due to column timestamps.
        // Since the mutation uses the decision ballot timestamp, if cell timestmap of any current cell
        // is strictly greater than the decision one, saving the decision will not erase it.
        //
        // The table may have been truncated since the proposal was initiated. In that case, we
        // don't want to perform the mutation and potentially resurrect truncated data.
        if (utils::UUID_gen::unix_timestamp(decision.ballot) >= truncated_at) {
            f = f.then([schema, &decision, timeout, tr_state] {
                logger.debug("Committing decision {}", decision);
                tracing::trace(tr_state, "Committing decision {}", decision);
                return get_local_storage_proxy().mutate_locally(schema, decision.update, db::commitlog::force_sync::yes, timeout);
            });
        } else {
            logger.debug("Not committing decision {} as ballot timestamp predates last truncation time", decision);
            tracing::trace(tr_state, "Not committing decision {} as ballot timestamp predates last truncation time", decision);
        }
        return f.then([&decision, schema, timeout] {
            // We don't need to lock the partition key if there is no gap between loading paxos
            // state and saving it, and here we're just blindly updating.
            return db::system_keyspace::save_paxos_decision(*schema, decision, timeout);
        });
    }).finally([schema, lc] () mutable {
        auto& stats = get_local_storage_proxy().get_db().local().find_column_family(schema).get_stats();
        stats.cas_learn.mark(lc.stop().latency());
        if (lc.is_start()) {
            stats.estimated_cas_learn.add(lc.latency(), stats.cas_learn.hist.count);
        }
    });
}

future<> paxos_state::prune(schema_ptr schema, const partition_key& key, utils::UUID ballot, clock_type::time_point timeout,
        tracing::trace_state_ptr tr_state) {
    logger.debug("Delete paxos state for ballot {}", ballot);
    tracing::trace(tr_state, "Delete paxos state for ballot {}", ballot);
    return db::system_keyspace::delete_paxos_decision(*schema, key, ballot, timeout);
}

} // end of namespace "service::paxos"
<commit_msg>lwt: do not copy proposal in paxos_state::accept<commit_after>/*
 * Copyright (C) 2019 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "service/storage_proxy.hh"
#include "service/paxos/proposal.hh"
#include "service/paxos/paxos_state.hh"
#include "db/system_keyspace.hh"
#include "schema_registry.hh"
#include "database.hh"

#include "service/storage_service.hh"

#include <utils/error_injection.hh>

namespace service::paxos {

logging::logger paxos_state::logger("paxos");
thread_local paxos_state::key_lock_map paxos_state::_paxos_table_lock;
thread_local paxos_state::key_lock_map paxos_state::_coordinator_lock;

paxos_state::key_lock_map::semaphore& paxos_state::key_lock_map::get_semaphore_for_key(const dht::token& key) {
    return _locks.try_emplace(key, 1).first->second;
}

void paxos_state::key_lock_map::release_semaphore_for_key(const dht::token& key) {
    auto it = _locks.find(key);
    if (it != _locks.end() && (*it).second.current() == 1) {
        _locks.erase(it);
    }
}

future<prepare_response> paxos_state::prepare(tracing::trace_state_ptr tr_state, schema_ptr schema,
        const query::read_command& cmd, const partition_key& key, utils::UUID ballot,
        bool only_digest, query::digest_algorithm da, clock_type::time_point timeout) {
    dht::token token = dht::get_token(*schema, key);
    utils::latency_counter lc;
    lc.start();
    return with_locked_key(token, timeout, [&cmd, token, &key, ballot, tr_state, schema, only_digest, da, timeout] () mutable {
        // When preparing, we need to use the same time as "now" (that's the time we use to decide if something
        // is expired or not) across nodes, otherwise we may have a window where a Most Recent Decision shows up
        // on some replica and not others during a new proposal (in storage_proxy::begin_and_repair_paxos()), and no
        // amount of re-submit will fix this (because the node on which the commit has expired will have a
        // tombstone that hides any re-submit). See CASSANDRA-12043 for details.
        auto now_in_sec = utils::UUID_gen::unix_timestamp_in_sec(ballot);

        return utils::get_local_injector().inject("paxos_state_prepare_timeout", timeout).then([&key, schema, now_in_sec, timeout] {
            return db::system_keyspace::load_paxos_state(key, schema, gc_clock::time_point(now_in_sec), timeout);
        }).then([&cmd, token = std::move(token), &key, ballot, tr_state, schema, only_digest, da, timeout] (paxos_state state) {
            // If received ballot is newer that the one we already accepted it has to be accepted as well,
            // but we will return the previously accepted proposal so that the new coordinator will use it instead of
            // its own.
            if (ballot.timestamp() > state._promised_ballot.timestamp()) {
                logger.debug("Promising ballot {}", ballot);
                tracing::trace(tr_state, "Promising ballot {}", ballot);
                auto f1 = futurize_invoke(db::system_keyspace::save_paxos_promise, *schema, std::ref(key), ballot, timeout);
                auto f2 = futurize_invoke([&] {
                    return do_with(dht::partition_range_vector({dht::partition_range::make_singular({token, key})}),
                            [tr_state, schema, &cmd, only_digest, da, timeout] (const dht::partition_range_vector& prv) {
                        return get_local_storage_proxy().get_db().local().query(schema, cmd,
                                {only_digest ? query::result_request::only_digest : query::result_request::result_and_digest, da},
                                prv, tr_state, query::result_memory_limiter::maximum_result_size, timeout);
                    });
                });
                return when_all(std::move(f1), std::move(f2)).then([state = std::move(state), only_digest] (auto t) {
                    auto&& f1 = std::get<0>(t);
                    auto&& f2 = std::get<1>(t);
                    if (f1.failed()) {
                        // Failed to save promise. Nothing we can do but throw.
                        return make_exception_future<prepare_response>(f1.get_exception());
                    }
                    std::optional<std::variant<foreign_ptr<lw_shared_ptr<query::result>>, query::result_digest>> data_or_digest;
                    // Silently ignore any errors querying the current value as the caller is prepared to fall back
                    // on querying it by itself in case it's missing in the response.
                    if (!f2.failed()) {
                        auto&& [result, hit_rate] = f2.get();
                        if (only_digest) {
                            data_or_digest = *result->digest();
                        } else {
                            data_or_digest = std::move(make_foreign(std::move(result)));
                        }
                    }
                    return make_ready_future<prepare_response>(prepare_response(promise(std::move(state._accepted_proposal),
                                    std::move(state._most_recent_commit), std::move(data_or_digest))));
                });
            } else {
                logger.debug("Promise rejected; {} is not sufficiently newer than {}", ballot, state._promised_ballot);
                tracing::trace(tr_state, "Promise rejected; {} is not sufficiently newer than {}", ballot, state._promised_ballot);
                // Return the currently promised ballot (rather than, e.g., the ballot of the last
                // accepted proposal) so the coordinator can make sure it uses a newer ballot next
                // time (#5667).
                return make_ready_future<prepare_response>(prepare_response(std::move(state._promised_ballot)));
            }
        });
    }).finally([schema, lc] () mutable {
        auto& stats = get_local_storage_proxy().get_db().local().find_column_family(schema).get_stats();
        stats.cas_prepare.mark(lc.stop().latency());
        if (lc.is_start()) {
            stats.estimated_cas_prepare.add(lc.latency(), stats.cas_prepare.hist.count);
        }
    });
}

future<bool> paxos_state::accept(tracing::trace_state_ptr tr_state, schema_ptr schema, dht::token token, const proposal& proposal,
        clock_type::time_point timeout) {
    utils::latency_counter lc;
    lc.start();

    return with_locked_key(token, timeout, [&proposal, schema, tr_state, timeout] () mutable {
        auto now_in_sec = utils::UUID_gen::unix_timestamp_in_sec(proposal.ballot);
        auto f = db::system_keyspace::load_paxos_state(proposal.update.decorated_key(*schema).key(), schema,
                gc_clock::time_point(now_in_sec), timeout);
        return f.then([&proposal, tr_state, schema, timeout] (paxos_state state) {
            return utils::get_local_injector().inject("paxos_state_accept_timeout", timeout).then(
                    [&proposal, state = std::move(state), tr_state, schema, timeout] {
                // Accept the proposal if we promised to accept it or the proposal is newer than the one we promised.
                // Otherwise the proposal was cutoff by another Paxos proposer and has to be rejected.
                if (proposal.ballot == state._promised_ballot || proposal.ballot.timestamp() > state._promised_ballot.timestamp()) {
                    logger.debug("Accepting proposal {}", proposal);
                    tracing::trace(tr_state, "Accepting proposal {}", proposal);
                    return db::system_keyspace::save_paxos_proposal(*schema, proposal, timeout).then([] {
                            return true;
                    });
                } else {
                    logger.debug("Rejecting proposal for {} because in_progress is now {}", proposal, state._promised_ballot);
                    tracing::trace(tr_state, "Rejecting proposal for {} because in_progress is now {}", proposal, state._promised_ballot);
                    return make_ready_future<bool>(false);
                }
            });
        });
    }).finally([schema, lc] () mutable {
        auto& stats = get_local_storage_proxy().get_db().local().find_column_family(schema).get_stats();
        stats.cas_accept.mark(lc.stop().latency());
        if (lc.is_start()) {
            stats.estimated_cas_accept.add(lc.latency(), stats.cas_accept.hist.count);
        }
    });
}

future<> paxos_state::learn(schema_ptr schema, proposal decision, clock_type::time_point timeout,
        tracing::trace_state_ptr tr_state) {
    utils::latency_counter lc;
    lc.start();

    return do_with(std::move(decision), [tr_state = std::move(tr_state), schema, timeout] (proposal& decision) {
        auto f = utils::get_local_injector().inject("paxos_state_learn_timeout", timeout);

        table& cf = get_local_storage_proxy().get_db().local().find_column_family(schema);
        db_clock::time_point t = cf.get_truncation_record();
        auto truncated_at = std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch()).count();
        // When saving a decision, also delete the last accepted proposal. This is just an
        // optimization to save space.
        // Even though there is no guarantee we will see decisions in the right order,
        // because messages can get delayed, so this decision can be older than our current most
        // recent accepted proposal/committed decision, saving it is always safe due to column timestamps.
        // Since the mutation uses the decision ballot timestamp, if cell timestmap of any current cell
        // is strictly greater than the decision one, saving the decision will not erase it.
        //
        // The table may have been truncated since the proposal was initiated. In that case, we
        // don't want to perform the mutation and potentially resurrect truncated data.
        if (utils::UUID_gen::unix_timestamp(decision.ballot) >= truncated_at) {
            f = f.then([schema, &decision, timeout, tr_state] {
                logger.debug("Committing decision {}", decision);
                tracing::trace(tr_state, "Committing decision {}", decision);
                return get_local_storage_proxy().mutate_locally(schema, decision.update, db::commitlog::force_sync::yes, timeout);
            });
        } else {
            logger.debug("Not committing decision {} as ballot timestamp predates last truncation time", decision);
            tracing::trace(tr_state, "Not committing decision {} as ballot timestamp predates last truncation time", decision);
        }
        return f.then([&decision, schema, timeout] {
            // We don't need to lock the partition key if there is no gap between loading paxos
            // state and saving it, and here we're just blindly updating.
            return db::system_keyspace::save_paxos_decision(*schema, decision, timeout);
        });
    }).finally([schema, lc] () mutable {
        auto& stats = get_local_storage_proxy().get_db().local().find_column_family(schema).get_stats();
        stats.cas_learn.mark(lc.stop().latency());
        if (lc.is_start()) {
            stats.estimated_cas_learn.add(lc.latency(), stats.cas_learn.hist.count);
        }
    });
}

future<> paxos_state::prune(schema_ptr schema, const partition_key& key, utils::UUID ballot, clock_type::time_point timeout,
        tracing::trace_state_ptr tr_state) {
    logger.debug("Delete paxos state for ballot {}", ballot);
    tracing::trace(tr_state, "Delete paxos state for ballot {}", ballot);
    return db::system_keyspace::delete_paxos_decision(*schema, key, ballot, timeout);
}

} // end of namespace "service::paxos"
<|endoftext|>


<commit_before>void k_print_line(const char* string);
void k_print(const char* string);

extern "C"
void  __attribute__ ((section ("main_section"))) kernel_main(){
    k_print_line("hello, world!");

    return;
}

typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));

enum vga_color {
    BLACK = 0,
    BLUE = 1,
    GREEN = 2,
    CYAN = 3,
    RED = 4,
    MAGENTA = 5,
    BROWN = 6,
    LIGHT_GREY = 7,
    DARK_GREY = 8,
    LIGHT_BLUE = 9,
    LIGHT_GREEN = 10,
    LIGHT_CYAN = 11,
    LIGHT_RED = 12,
    LIGHT_MAGENTA = 13,
    LIGHT_BROWN = 14,
    WHITE = 15,
};

long current_line = 0;
long current_column = 0;

uint8_t make_color(vga_color fg, vga_color bg){
    return fg | bg << 4;
}

uint16_t make_vga_entry(char c, uint8_t color){
    uint16_t c16 = c;
    uint16_t color16 = color;
    return c16 | color16 << 8;
}

void k_print_line(const char* string){
    k_print(string);

    current_column = 0;
    ++current_line;
}

void k_print(const char* string){
    uint16_t* vga_buffer = (uint16_t*) 0x0B8000;

    for(int i = 0; string[i] != 0; ++i){
        vga_buffer[current_line * 80 + current_column] = make_vga_entry(string[i], make_color(WHITE, BLACK));

        ++current_column;
    }

    return;
}
<commit_msg>Output more lines<commit_after>void k_print_line(const char* string);
void k_print(const char* string);

extern "C"
void  __attribute__ ((section ("main_section"))) kernel_main(){
    k_print_line("hello, ");
    k_print_line(" world!");

    return;
}

typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));

enum vga_color {
    BLACK = 0,
    BLUE = 1,
    GREEN = 2,
    CYAN = 3,
    RED = 4,
    MAGENTA = 5,
    BROWN = 6,
    LIGHT_GREY = 7,
    DARK_GREY = 8,
    LIGHT_BLUE = 9,
    LIGHT_GREEN = 10,
    LIGHT_CYAN = 11,
    LIGHT_RED = 12,
    LIGHT_MAGENTA = 13,
    LIGHT_BROWN = 14,
    WHITE = 15,
};

long current_line = 0;
long current_column = 0;

uint8_t make_color(vga_color fg, vga_color bg){
    return fg | bg << 4;
}

uint16_t make_vga_entry(char c, uint8_t color){
    uint16_t c16 = c;
    uint16_t color16 = color;
    return c16 | color16 << 8;
}

void k_print_line(const char* string){
    k_print(string);

    current_column = 0;
    ++current_line;
}

void k_print(const char* string){
    uint16_t* vga_buffer = (uint16_t*) 0x0B8000;

    for(int i = 0; string[i] != 0; ++i){
        vga_buffer[current_line * 80 + current_column] = make_vga_entry(string[i], make_color(WHITE, BLACK));

        ++current_column;
    }

    return;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Library:   CTK

  Copyright (c) Isomics Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// Qt includes
#include <QApplication>
#include <QTreeView>
#include <QSettings>
#include <QDir>

// CTK Core
#include <ctkDICOMDatabase.h>

// CTK widget includes
#include <ctkDICOMQueryRetrieveWidget.h>

// Logger
#include "ctkLogger.h"

// STD includes
#include <iostream>

int main(int argc, char** argv)
{
  ctkLogger::configure();
  QApplication app(argc, argv);

  app.setOrganizationName("commontk");
  app.setOrganizationDomain("commontk.org");
  app.setApplicationName("ctkDICOMQueryRetrieve");

  QSettings settings;
  QString databaseDirectory;

  // set up the database
  if (argc > 1)
  {
    QString directory(argv[1]);
    settings.setValue("DatabaseDirectory", directory);
    settings.sync();
  }

  if ( settings.value("DatabaseDirectory", "") == "" )
  {
    databaseDirectory = QString("./ctkDICOM-Database");
    std::cerr << "No DatabaseDirectory on command line or in settings.  Using \"" << databaseDirectory.toLatin1().data() << "\".\n";
  } else
  {
    databaseDirectory = settings.value("DatabaseDirectory", "").toString();
  }

  QDir qdir(databaseDirectory);
  if ( !qdir.exists(databaseDirectory) )
  {
    if ( !qdir.mkpath(databaseDirectory) )
    {
      std::cerr << "Could not create database directory \"" << databaseDirectory.toLatin1().data() << "\".\n";
      return EXIT_FAILURE;
    }
  }

  QString databaseFileName = databaseDirectory + QString("/ctkDICOM.sql");

  QSharedPointer<ctkDICOMDatabase> dicomDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);
  dicomDatabase->openDatabase(databaseFileName);

  ctkDICOMQueryRetrieveWidget queryRetrieve;

  queryRetrieve.setRetrieveDatabase(dicomDatabase);

  queryRetrieve.show();
  queryRetrieve.raise();
  return app.exec();
}
<commit_msg>Enabled DCMTK debug logging to better debug DICOM networking.<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Isomics Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// Qt includes
#include <QApplication>
#include <QTreeView>
#include <QSettings>
#include <QDir>

// CTK Core
#include <ctkDICOMDatabase.h>

// CTK widget includes
#include <ctkDICOMQueryRetrieveWidget.h>

// Logger
#include "ctkLogger.h"
#include "dcmtk/oflog/oflog.h"

// STD includes
#include <iostream>

int main(int argc, char** argv)
{
  ctkLogger::configure();
  // Set the DCMTK log level to debug
  dcmtk::log4cplus::Logger rootLogger = dcmtk::log4cplus::Logger::getRoot();
  rootLogger.setLogLevel(dcmtk::log4cplus::DEBUG_LOG_LEVEL);

  QApplication app(argc, argv);

  app.setOrganizationName("commontk");
  app.setOrganizationDomain("commontk.org");
  app.setApplicationName("ctkDICOMQueryRetrieve");

  QSettings settings;
  QString databaseDirectory;

  // set up the database
  if (argc > 1)
  {
    QString directory(argv[1]);
    settings.setValue("DatabaseDirectory", directory);
    settings.sync();
  }

  if ( settings.value("DatabaseDirectory", "") == "" )
  {
    databaseDirectory = QString("./ctkDICOM-Database");
    std::cerr << "No DatabaseDirectory on command line or in settings.  Using \"" << databaseDirectory.toLatin1().data() << "\".\n";
  } else
  {
    databaseDirectory = settings.value("DatabaseDirectory", "").toString();
  }

  QDir qdir(databaseDirectory);
  if ( !qdir.exists(databaseDirectory) )
  {
    if ( !qdir.mkpath(databaseDirectory) )
    {
      std::cerr << "Could not create database directory \"" << databaseDirectory.toLatin1().data() << "\".\n";
      return EXIT_FAILURE;
    }
  }

  QString databaseFileName = databaseDirectory + QString("/ctkDICOM.sql");

  QSharedPointer<ctkDICOMDatabase> dicomDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);
  dicomDatabase->openDatabase(databaseFileName);

  ctkDICOMQueryRetrieveWidget queryRetrieve;

  queryRetrieve.setRetrieveDatabase(dicomDatabase);

  queryRetrieve.show();
  queryRetrieve.raise();
  return app.exec();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: viewobjectcontactofsdrmediaobj.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 20:02:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
#define _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX

#ifndef _SDR_CONTACT_VIEWOBJECTCONTACT_HXX
#include <svx/sdr/contact/viewobjectcontact.hxx>
#endif

namespace avmedia { class MediaItem; }

namespace sdr
{
    namespace contact
    {
        class SdrMediaWindow;

        class ViewObjectContactOfSdrMediaObj : public ViewObjectContact
        {
        public:

            ViewObjectContactOfSdrMediaObj( ObjectContact& rObjectContact,
                                            ViewContact& rViewContact,
                                            const ::avmedia::MediaItem& rMediaItem );

            // The destructor. When PrepareDelete() was not called before (see there)
            // warnings will be generated in debug version if there are still contacts
            // existing.
            virtual ~ViewObjectContactOfSdrMediaObj();

        public:

            Window* getWindow() const;

            bool    hasPreferredSize() const;
            Size    getPreferredSize() const;

            void    updateMediaItem( ::avmedia::MediaItem& rItem ) const;
            void    executeMediaItem( const ::avmedia::MediaItem& rItem );

        protected:

            // Prepare deletion of this object. This needs to be called always
            // before really deleting this objects. This is necessary since in a c++
            // destructor no virtual function calls are allowed. To avoid this problem,
            // it is required to first call PrepareDelete().
            virtual void PrepareDelete();

            // Paint this object. This is before evtl. SubObjects get painted. This method
            // needs to set the flag mbIsPainted and mbIsInvalidated and to set the
            // maPaintedRectangle member. This information is later used for invalidates
            // and repaints.
            virtual void PaintObject(DisplayInfo& rDisplayInfo);

        private:

            ::sdr::contact::SdrMediaWindow* mpMediaWindow;
        };
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif // _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
<commit_msg>INTEGRATION: CWS aw024 (1.3.76); FILE MERGED 2005/09/18 01:39:50 aw 1.3.76.2: RESYNC: (1.3-1.4); FILE MERGED 2005/05/19 12:30:05 aw 1.3.76.1: #i39529#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: viewobjectcontactofsdrmediaobj.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: ihi $ $Date: 2006-11-14 13:05:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
#define _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX

#ifndef _SDR_CONTACT_VIEWOBJECTCONTACT_HXX
#include <svx/sdr/contact/viewobjectcontact.hxx>
#endif

namespace avmedia { class MediaItem; }
class Window;

namespace sdr
{
    namespace contact
    {
        class SdrMediaWindow;

        class ViewObjectContactOfSdrMediaObj : public ViewObjectContact
        {
        public:

            ViewObjectContactOfSdrMediaObj( ObjectContact& rObjectContact,
                                            ViewContact& rViewContact,
                                            const ::avmedia::MediaItem& rMediaItem );

            // The destructor. When PrepareDelete() was not called before (see there)
            // warnings will be generated in debug version if there are still contacts
            // existing.
            virtual ~ViewObjectContactOfSdrMediaObj();

        public:

            Window* getWindow() const;

            bool    hasPreferredSize() const;
            Size    getPreferredSize() const;

            void    updateMediaItem( ::avmedia::MediaItem& rItem ) const;
            void    executeMediaItem( const ::avmedia::MediaItem& rItem );

        protected:

            // Prepare deletion of this object. This needs to be called always
            // before really deleting this objects. This is necessary since in a c++
            // destructor no virtual function calls are allowed. To avoid this problem,
            // it is required to first call PrepareDelete().
            virtual void PrepareDelete();

            // Paint this object. This is before evtl. SubObjects get painted. This method
            // needs to set the flag mbIsPainted and mbIsInvalidated and to set the
            // maPaintedRectangle member. This information is later used for invalidates
            // and repaints.
            virtual void PaintObject(DisplayInfo& rDisplayInfo);

        private:

            ::sdr::contact::SdrMediaWindow* mpMediaWindow;
        };
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif // _SDR_CONTACT_VIEWOBJECTCONTACTOFSDRMEDIAOBJ_HXX
<|endoftext|>