<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 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 "target.h"
#include "buildconfiguration.h"

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

#include <QtCore/QMargins>
#include <QtCore/QTimer>
#include <QtCore/QCoreApplication>
#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
///

QString BuildSettingsPanelFactory::id() const
{
    return QLatin1String(BUILDSETTINGS_PANEL_ID);
}

QString BuildSettingsPanelFactory::displayName() const
{
    return QCoreApplication::translate("BuildSettingsPanelFactory", "Build Settings");
}

bool BuildSettingsPanelFactory::supports(Target *target)
{
    return target->buildConfigurationFactory();
}

IPropertiesPanel *BuildSettingsPanelFactory::createPanel(Target *target)
{
    return new BuildSettingsPanel(target);
}

///
// BuildSettingsPanel
///

BuildSettingsPanel::BuildSettingsPanel(Target *target) :
    m_widget(new BuildSettingsWidget(target)),
    m_icon(":/projectexplorer/images/BuildSettings.png")
{
}

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

QString BuildSettingsPanel::displayName() const
{
    return QCoreApplication::translate("BuildSettingsPanel", "Build Settings");
}

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

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

///
// BuildSettingsWidget
///

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

BuildSettingsWidget::BuildSettingsWidget(Target *target) :
    m_target(target),
    m_buildConfiguration(0),
    m_leftMargin(0)
{
    Q_ASSERT(m_target);
    setupUi();
}

void BuildSettingsWidget::setupUi()
{
    m_leftMargin = Constants::PANEL_LEFT_MARGIN;
    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setContentsMargins(0, 0, 0, 0);

    if (!m_target->buildConfigurationFactory()) {
        QLabel * noSettingsLabel(new QLabel(this));
        noSettingsLabel->setText(tr("No Build Settings available"));
        {
            QFont f(noSettingsLabel->font());
            f.setPointSizeF(f.pointSizeF() * 1.2);
            noSettingsLabel->setFont(f);
        }
        vbox->addWidget(noSettingsLabel);
        return;
    }

    { // 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_buildConfiguration = m_target->activeBuildConfiguration();

    updateAddButtonMenu();
    updateBuildSettings();

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

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

    connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(updateActiveConfiguration()));

    connect(m_target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));

    connect(m_target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));

    foreach (BuildConfiguration *bc, m_target->buildConfigurations()) {
        connect(bc, SIGNAL(displayNameChanged()),
                this, SLOT(buildConfigurationDisplayNameChanged()));
    }

    if (m_target->buildConfigurationFactory())
        connect(m_target->buildConfigurationFactory(), SIGNAL(availableCreationIdsChanged()),
                SLOT(updateAddButtonMenu()));
}

void BuildSettingsWidget::addedBuildConfiguration(BuildConfiguration *bc)
{
    connect(bc, SIGNAL(displayNameChanged()),
            this, SLOT(buildConfigurationDisplayNameChanged()));
}

void BuildSettingsWidget::removedBuildConfiguration(BuildConfiguration *bc)
{
    disconnect(bc, SIGNAL(displayNameChanged()),
               this, SLOT(buildConfigurationDisplayNameChanged()));
}

void BuildSettingsWidget::buildConfigurationDisplayNameChanged()
{
    for (int i = 0; i < m_buildConfigurationComboBox->count(); ++i) {
        BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(i).value<BuildConfiguration *>();
        m_buildConfigurationComboBox->setItemText(i, bc->displayName());
    }
}

void BuildSettingsWidget::addSubWidget(const QString &name, BuildConfigWidget *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<BuildConfigWidget *> BuildSettingsWidget::subWidgets() const
{
    return m_subWidgets;
}

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

void BuildSettingsWidget::updateBuildSettings()
{
    // Delete old tree items
    bool blocked = m_buildConfigurationComboBox->blockSignals(true);
    m_buildConfigurationComboBox->clear();
    clear();

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

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

    addSubWidget(tr("Build Steps"), new BuildStepsPage(m_target, Build));
    addSubWidget(tr("Clean Steps"), new BuildStepsPage(m_target, Clean));

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

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

    foreach (BuildConfigWidget *widget, subWidgets())
        widget->init(m_buildConfiguration);

    m_buildConfigurationComboBox->blockSignals(blocked);
}

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

void BuildSettingsWidget::updateActiveConfiguration()
{
    if (!m_buildConfiguration || m_buildConfiguration == m_target->activeBuildConfiguration())
        return;

    m_buildConfiguration = m_target->activeBuildConfiguration();

    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);
        }
    }
}

void BuildSettingsWidget::createConfiguration()
{
    if (!m_target->buildConfigurationFactory())
        return;

    QAction *action = qobject_cast<QAction *>(sender());
    const QString &id = action->data().toString();
    BuildConfiguration *bc = m_target->buildConfigurationFactory()->create(m_target, id);
    if (bc) {
        m_buildConfiguration = bc;
        updateBuildSettings();
    }
}

void BuildSettingsWidget::cloneConfiguration()
{
    cloneConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::deleteConfiguration()
{
    deleteConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration)
{
    if (!sourceConfiguration ||
        !m_target->buildConfigurationFactory())
        return;

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

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

    BuildConfiguration * bc(m_target->buildConfigurationFactory()->clone(m_target, sourceConfiguration));
    if (!bc)
        return;

    m_buildConfiguration = bc;
    m_buildConfiguration->setDisplayName(newDisplayName);
    m_target->addBuildConfiguration(m_buildConfiguration);

    updateBuildSettings();
}

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

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

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

    m_target->removeBuildConfiguration(deleteConfiguration);

    updateBuildSettings();
}
<commit_msg>Fix deletion of buildconfigurations<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 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 "target.h"
#include "buildconfiguration.h"

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

#include <QtCore/QMargins>
#include <QtCore/QTimer>
#include <QtCore/QCoreApplication>
#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
///

QString BuildSettingsPanelFactory::id() const
{
    return QLatin1String(BUILDSETTINGS_PANEL_ID);
}

QString BuildSettingsPanelFactory::displayName() const
{
    return QCoreApplication::translate("BuildSettingsPanelFactory", "Build Settings");
}

bool BuildSettingsPanelFactory::supports(Target *target)
{
    return target->buildConfigurationFactory();
}

IPropertiesPanel *BuildSettingsPanelFactory::createPanel(Target *target)
{
    return new BuildSettingsPanel(target);
}

///
// BuildSettingsPanel
///

BuildSettingsPanel::BuildSettingsPanel(Target *target) :
    m_widget(new BuildSettingsWidget(target)),
    m_icon(":/projectexplorer/images/BuildSettings.png")
{
}

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

QString BuildSettingsPanel::displayName() const
{
    return QCoreApplication::translate("BuildSettingsPanel", "Build Settings");
}

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

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

///
// BuildSettingsWidget
///

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

BuildSettingsWidget::BuildSettingsWidget(Target *target) :
    m_target(target),
    m_buildConfiguration(0),
    m_leftMargin(0)
{
    Q_ASSERT(m_target);
    setupUi();
}

void BuildSettingsWidget::setupUi()
{
    m_leftMargin = Constants::PANEL_LEFT_MARGIN;
    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setContentsMargins(0, 0, 0, 0);

    if (!m_target->buildConfigurationFactory()) {
        QLabel * noSettingsLabel(new QLabel(this));
        noSettingsLabel->setText(tr("No Build Settings available"));
        {
            QFont f(noSettingsLabel->font());
            f.setPointSizeF(f.pointSizeF() * 1.2);
            noSettingsLabel->setFont(f);
        }
        vbox->addWidget(noSettingsLabel);
        return;
    }

    { // 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_buildConfiguration = m_target->activeBuildConfiguration();

    updateAddButtonMenu();
    updateBuildSettings();

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

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

    connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(updateActiveConfiguration()));

    connect(m_target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));

    connect(m_target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
            this, SLOT(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));

    foreach (BuildConfiguration *bc, m_target->buildConfigurations()) {
        connect(bc, SIGNAL(displayNameChanged()),
                this, SLOT(buildConfigurationDisplayNameChanged()));
    }

    if (m_target->buildConfigurationFactory())
        connect(m_target->buildConfigurationFactory(), SIGNAL(availableCreationIdsChanged()),
                SLOT(updateAddButtonMenu()));
}

void BuildSettingsWidget::addedBuildConfiguration(BuildConfiguration *bc)
{
    connect(bc, SIGNAL(displayNameChanged()),
            this, SLOT(buildConfigurationDisplayNameChanged()));
}

void BuildSettingsWidget::removedBuildConfiguration(BuildConfiguration *bc)
{
    disconnect(bc, SIGNAL(displayNameChanged()),
               this, SLOT(buildConfigurationDisplayNameChanged()));
}

void BuildSettingsWidget::buildConfigurationDisplayNameChanged()
{
    for (int i = 0; i < m_buildConfigurationComboBox->count(); ++i) {
        BuildConfiguration *bc = m_buildConfigurationComboBox->itemData(i).value<BuildConfiguration *>();
        m_buildConfigurationComboBox->setItemText(i, bc->displayName());
    }
}

void BuildSettingsWidget::addSubWidget(const QString &name, BuildConfigWidget *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<BuildConfigWidget *> BuildSettingsWidget::subWidgets() const
{
    return m_subWidgets;
}

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

void BuildSettingsWidget::updateBuildSettings()
{
    // Delete old tree items
    bool blocked = m_buildConfigurationComboBox->blockSignals(true);
    m_buildConfigurationComboBox->clear();
    clear();

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

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

    addSubWidget(tr("Build Steps"), new BuildStepsPage(m_target, Build));
    addSubWidget(tr("Clean Steps"), new BuildStepsPage(m_target, Clean));

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

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

    foreach (BuildConfigWidget *widget, subWidgets())
        widget->init(m_buildConfiguration);

    m_buildConfigurationComboBox->blockSignals(blocked);
}

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

void BuildSettingsWidget::updateActiveConfiguration()
{
    if (!m_buildConfiguration || m_buildConfiguration == m_target->activeBuildConfiguration())
        return;

    m_buildConfiguration = m_target->activeBuildConfiguration();

    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);
        }
    }
}

void BuildSettingsWidget::createConfiguration()
{
    if (!m_target->buildConfigurationFactory())
        return;

    QAction *action = qobject_cast<QAction *>(sender());
    const QString &id = action->data().toString();
    BuildConfiguration *bc = m_target->buildConfigurationFactory()->create(m_target, id);
    if (bc) {
        m_buildConfiguration = bc;
        updateBuildSettings();
    }
}

void BuildSettingsWidget::cloneConfiguration()
{
    cloneConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::deleteConfiguration()
{
    deleteConfiguration(m_buildConfiguration);
}

void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration)
{
    if (!sourceConfiguration ||
        !m_target->buildConfigurationFactory())
        return;

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

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

    BuildConfiguration * bc(m_target->buildConfigurationFactory()->clone(m_target, sourceConfiguration));
    if (!bc)
        return;

    m_buildConfiguration = bc;
    m_buildConfiguration->setDisplayName(newDisplayName);
    m_target->addBuildConfiguration(m_buildConfiguration);

    updateBuildSettings();
}

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

    m_target->removeBuildConfiguration(deleteConfiguration);

    updateBuildSettings();
}
<|endoftext|>


<commit_before>#pragma once
#ifndef OPENGM_STRUCT_PERCEPTRON_LEARNER_HXX
#define OPENGM_STRUCT_PERCEPTRON_LEARNER_HXX

#include <vector>
#include <opengm/inference/inference.hxx>
#include <opengm/graphicalmodel/weights.hxx>
#include <opengm/utilities/random.hxx>
#include <opengm/learning/gradient-accumulator.hxx>
#ifndef CI
#include <omp.h>
#endif CI

namespace opengm {
    namespace learning {

    template<class DATASET>
    class StructuredPerceptron
    {
    public:
        typedef DATASET DatasetType;
        typedef typename DATASET::GMType   GMType;
        typedef typename DATASET::LossType LossType;
        typedef typename GMType::ValueType ValueType;
        typedef typename GMType::IndexType IndexType;
        typedef typename GMType::LabelType LabelType;

        typedef typename std::vector<LabelType>::const_iterator LabelIterator;
        typedef FeatureAccumulator<GMType, LabelIterator> FeatureAcc;

        class Parameter{
        public:

            enum LearningMode{
                Online = 0,
                Batch = 2
            };

            Parameter(){
                eps_ = 0.00001;
                maxIterations_ = 10000;
                stopLoss_ = 0.0;
                decayExponent_ = 0.0;
                decayT0_ = 0.0;
                learningMode_ = Online;
            }

            double eps_;
            size_t maxIterations_;
            double stopLoss_;
            double decayExponent_;
            double decayT0_;
            LearningMode learningMode_;
        };

        StructuredPerceptron(DATASET&, const Parameter& );

        template<class INF>
        void learn(const typename INF::Parameter& para);
        //template<class INF, class VISITOR>
        //void learn(typename INF::Parameter para, VITITOR vis);

        const opengm::learning::Weights<double>& getWeights(){return weights_;}
        Parameter& getLerningParameters(){return para_;}

        double getLearningRate( )const{
            if(para_.decayExponent_<=0.000000001 && para_.decayExponent_>=-0.000000001 ){
                return 1.0;
            }
            else{
                return std::pow(para_.decayT0_ + static_cast<double>(iteration_+1),para_.decayExponent_);
            }
        }

    private:

        double updateWeights();

        DATASET& dataset_;
        opengm::learning::Weights<double> weights_;
        Parameter para_;
        size_t iteration_;
        FeatureAcc featureAcc_;
    };

    template<class DATASET>
    StructuredPerceptron<DATASET>::StructuredPerceptron(DATASET& ds, const Parameter& p )
    : dataset_(ds), para_(p),iteration_(0),featureAcc_(ds.getNumberOfWeights(),false)
    {
        featureAcc_.resetWeights();
        weights_ = opengm::learning::Weights<double>(ds.getNumberOfWeights());

    }

    template<class DATASET>
    template<class INF>
    void StructuredPerceptron<DATASET>::learn(const typename INF::Parameter& para){

        const size_t nModels = dataset_.getNumberOfModels();
        const size_t nWegihts = dataset_.getNumberOfWeights();

        if(para_.learningMode_ == Parameter::Online){
            RandomUniform<size_t> randModel(0, nModels);
            std::cout<<"online mode\n";
            for(iteration_=0 ; iteration_<para_.maxIterations_; ++iteration_){

                if(iteration_%nModels==0){
                    std::cout<<"loss :"<<dataset_. template getTotalLoss<INF>(para)<<"\n";
                }

                // get random model
                const size_t gmi = randModel();
                // lock the model
                dataset_.lockModel(gmi);
                const GMType & gm = dataset_.getModel(gmi);

                // do inference
                std::vector<LabelType> arg;
                opengm::infer<INF>(gm, para, arg);
                featureAcc_.resetWeights();
                featureAcc_.accumulateModelFeatures(gm, dataset_.getGT(gmi).begin(), arg.begin());
                dataset_.unlockModel(gmi);

                // update weights
                const double wChange =updateWeights();

            }
        }
        else if(para_.learningMode_ == Parameter::Batch){
            std::cout<<"batch mode\n";
            for(iteration_=0 ; iteration_<para_.maxIterations_; ++iteration_){
                // this
                if(iteration_%1==0){
                    std::cout<<"loss :"<<dataset_. template getTotalLoss<INF>(para)<<"\n";
                }

                // reset the weights
                featureAcc_.resetWeights();

                #ifndef CI
                omp_lock_t modelLockUnlock;
                omp_init_lock(&modelLockUnlock);

                omp_lock_t featureAccLock;
                omp_init_lock(&featureAccLock);
                #endif

                #pragma omp parallel for
                for(size_t gmi=0; gmi<nModels; ++gmi)
                {

                    // lock the model
                    omp_set_lock(&modelLockUnlock);
                    dataset_.lockModel(gmi);
                    omp_unset_lock(&modelLockUnlock);

                    const GMType & gm = dataset_.getModel(gmi);
                    //run inference
                    std::vector<LabelType> arg;
                    opengm::infer<INF>(gm, para, arg);

                    //
                    FeatureAcc featureAcc(nWegihts,false);
                    featureAcc.accumulateModelFeatures(gm, dataset_.getGT(gmi).begin(), arg.begin());

                    // acc features
                    #ifndef CI
                    omp_set_lock(&featureAccLock);
                    featureAcc_.accumulateFromOther(featureAcc);
                    omp_unset_lock(&featureAccLock);

                    // unlock the model
                    omp_set_lock(&modelLockUnlock);
                    dataset_.unlockModel(gmi);
                    omp_unset_lock(&modelLockUnlock);
                    #else
                    featureAcc_.accumulateFromOther(featureAcc);
                    dataset_.unlockModel(gmi);
                    #endif

                }

                // update the weights
                const double wChange =updateWeights();

            }
        }

        weights_ = dataset_.getWeights();
    }

    template<class DATASET>
    double StructuredPerceptron<DATASET>::updateWeights(){
        double wChange = 0.0;
        const size_t nWegihts = dataset_.getNumberOfWeights();
        for(size_t wi=0; wi<nWegihts; ++wi){
            const double wOld = dataset_.getWeights().getWeight(wi);
            const double wNew = wOld + getLearningRate()*featureAcc_.getWeight(wi);
            wChange += std::pow(wOld-wNew,2);
            dataset_.getWeights().setWeight(wi, wNew);
        }
        weights_ = dataset_.getWeights();
        return wChange;
    }
}
}
#endif
<commit_msg>update struct. perceptron<commit_after>#pragma once
#ifndef OPENGM_STRUCT_PERCEPTRON_LEARNER_HXX
#define OPENGM_STRUCT_PERCEPTRON_LEARNER_HXX

#include <vector>
#include <opengm/inference/inference.hxx>
#include <opengm/graphicalmodel/weights.hxx>
#include <opengm/utilities/random.hxx>
#include <opengm/learning/gradient-accumulator.hxx>
#ifndef CI
#include <omp.h>
#endif

namespace opengm {
    namespace learning {

    template<class DATASET>
    class StructuredPerceptron
    {
    public:
        typedef DATASET DatasetType;
        typedef typename DATASET::GMType   GMType;
        typedef typename DATASET::LossType LossType;
        typedef typename GMType::ValueType ValueType;
        typedef typename GMType::IndexType IndexType;
        typedef typename GMType::LabelType LabelType;

        typedef typename std::vector<LabelType>::const_iterator LabelIterator;
        typedef FeatureAccumulator<GMType, LabelIterator> FeatureAcc;

        class Parameter{
        public:

            enum LearningMode{
                Online = 0,
                Batch = 2
            };

            Parameter(){
                eps_ = 0.00001;
                maxIterations_ = 10000;
                stopLoss_ = 0.0;
                decayExponent_ = 0.0;
                decayT0_ = 0.0;
                learningMode_ = Online;
            }

            double eps_;
            size_t maxIterations_;
            double stopLoss_;
            double decayExponent_;
            double decayT0_;
            LearningMode learningMode_;
        };

        StructuredPerceptron(DATASET&, const Parameter& );

        template<class INF>
        void learn(const typename INF::Parameter& para);
        //template<class INF, class VISITOR>
        //void learn(typename INF::Parameter para, VITITOR vis);

        const opengm::learning::Weights<double>& getWeights(){return weights_;}
        Parameter& getLerningParameters(){return para_;}

        double getLearningRate( )const{
            if(para_.decayExponent_<=0.000000001 && para_.decayExponent_>=-0.000000001 ){
                return 1.0;
            }
            else{
                return std::pow(para_.decayT0_ + static_cast<double>(iteration_+1),para_.decayExponent_);
            }
        }

    private:

        double updateWeights();

        DATASET& dataset_;
        opengm::learning::Weights<double> weights_;
        Parameter para_;
        size_t iteration_;
        FeatureAcc featureAcc_;
    };

    template<class DATASET>
    StructuredPerceptron<DATASET>::StructuredPerceptron(DATASET& ds, const Parameter& p )
    : dataset_(ds), para_(p),iteration_(0),featureAcc_(ds.getNumberOfWeights(),false)
    {
        featureAcc_.resetWeights();
        weights_ = opengm::learning::Weights<double>(ds.getNumberOfWeights());

    }

    template<class DATASET>
    template<class INF>
    void StructuredPerceptron<DATASET>::learn(const typename INF::Parameter& para){

        const size_t nModels = dataset_.getNumberOfModels();
        const size_t nWegihts = dataset_.getNumberOfWeights();

        if(para_.learningMode_ == Parameter::Online){
            RandomUniform<size_t> randModel(0, nModels);
            std::cout<<"online mode\n";
            for(iteration_=0 ; iteration_<para_.maxIterations_; ++iteration_){

                if(iteration_%nModels==0){
                    std::cout<<"loss :"<<dataset_. template getTotalLoss<INF>(para)<<"\n";
                }

                // get random model
                const size_t gmi = randModel();
                // lock the model
                dataset_.lockModel(gmi);
                const GMType & gm = dataset_.getModel(gmi);

                // do inference
                std::vector<LabelType> arg;
                opengm::infer<INF>(gm, para, arg);
                featureAcc_.resetWeights();
                featureAcc_.accumulateModelFeatures(gm, dataset_.getGT(gmi).begin(), arg.begin());
                dataset_.unlockModel(gmi);

                // update weights
                const double wChange =updateWeights();

            }
        }
        else if(para_.learningMode_ == Parameter::Batch){
            std::cout<<"batch mode\n";
            for(iteration_=0 ; iteration_<para_.maxIterations_; ++iteration_){
                // this
                if(iteration_%1==0){
                    std::cout<<"loss :"<<dataset_. template getTotalLoss<INF>(para)<<"\n";
                }

                // reset the weights
                featureAcc_.resetWeights();

                #ifndef CI
                omp_lock_t modelLockUnlock;
                omp_init_lock(&modelLockUnlock);

                omp_lock_t featureAccLock;
                omp_init_lock(&featureAccLock);
                #endif

                #pragma omp parallel for
                for(size_t gmi=0; gmi<nModels; ++gmi)
                {

                    // lock the model
                    omp_set_lock(&modelLockUnlock);
                    dataset_.lockModel(gmi);
                    omp_unset_lock(&modelLockUnlock);

                    const GMType & gm = dataset_.getModel(gmi);
                    //run inference
                    std::vector<LabelType> arg;
                    opengm::infer<INF>(gm, para, arg);

                    //
                    FeatureAcc featureAcc(nWegihts,false);
                    featureAcc.accumulateModelFeatures(gm, dataset_.getGT(gmi).begin(), arg.begin());

                    // acc features
                    #ifndef CI
                    omp_set_lock(&featureAccLock);
                    featureAcc_.accumulateFromOther(featureAcc);
                    omp_unset_lock(&featureAccLock);

                    // unlock the model
                    omp_set_lock(&modelLockUnlock);
                    dataset_.unlockModel(gmi);
                    omp_unset_lock(&modelLockUnlock);
                    #else
                    featureAcc_.accumulateFromOther(featureAcc);
                    dataset_.unlockModel(gmi);
                    #endif

                }

                // update the weights
                const double wChange =updateWeights();

            }
        }

        weights_ = dataset_.getWeights();
    }

    template<class DATASET>
    double StructuredPerceptron<DATASET>::updateWeights(){
        double wChange = 0.0;
        const size_t nWegihts = dataset_.getNumberOfWeights();
        for(size_t wi=0; wi<nWegihts; ++wi){
            const double wOld = dataset_.getWeights().getWeight(wi);
            const double wNew = wOld + getLearningRate()*featureAcc_.getWeight(wi);
            wChange += std::pow(wOld-wNew,2);
            dataset_.getWeights().setWeight(wi, wNew);
        }
        weights_ = dataset_.getWeights();
        return wChange;
    }
}
}
#endif
<|endoftext|>


<commit_before>#include "framework/framework.h"
#include "framework/logger.h"
#include "framework/sound_interface.h"
#include "framework/trace.h"
#include "library/sp.h"
#include "library/vec.h"
#include <SDL.h>
#include <SDL_audio.h>
#include <list>
#include <mutex>
#include <queue>

namespace
{

using namespace OpenApoc;

struct SampleData
{
	sp<Sample> sample;
	float gain;
	int sample_position; // in bytes
	SampleData(sp<Sample> sample, float gain) : sample(sample), gain(gain), sample_position(0) {}
};

struct MusicData
{
	MusicData() : sample_position(0) {}
	std::vector<unsigned char> samples;
	int sample_position; // in bytes
};

// 'samples' must already be large enough to contain the full output size
static bool ConvertAudio(AudioFormat input_format, SDL_AudioSpec &output_spec, int input_size_bytes,
                         std::vector<unsigned char> &samples)
{
	SDL_AudioCVT cvt;
	SDL_AudioFormat sdl_input_format;
	switch (input_format.format)
	{
		case AudioFormat::SampleFormat::PCM_SINT16:
			sdl_input_format = AUDIO_S16LSB;
			break;
		case AudioFormat::SampleFormat::PCM_UINT8:
			sdl_input_format = AUDIO_U8;
			break;
		default:
			LogWarning("Unknown input sample format");
			return false;
	}

	int ret =
	    SDL_BuildAudioCVT(&cvt, sdl_input_format, input_format.channels, input_format.frequency,
	                      output_spec.format, output_spec.channels, output_spec.freq);
	if (ret < 0)
	{
		LogWarning("Failed to build AudioCVT");
		return false;
	}
	else if (ret == 0)
	{
		// No conversion needed
		return true;
	}
	else
	{
		cvt.len = input_size_bytes;
		cvt.buf = (Uint8 *)samples.data();
		SDL_ConvertAudio(&cvt);
		return true;
	}
}

class SDLSampleData : public BackendSampleData
{
  public:
	SDLSampleData(sp<Sample> sample, SDL_AudioSpec &output_spec)
	{
		unsigned int input_size =
		    sample->format.getSampleSize() * sample->format.channels * sample->sampleCount;
		unsigned int output_size = (SDL_AUDIO_BITSIZE(output_spec.format) / 8) *
		                           output_spec.channels * sample->sampleCount;
		this->samples.resize(std::max(input_size, output_size));
		memcpy(this->samples.data(), sample->data.get(), input_size);
		if (!ConvertAudio(sample->format, output_spec, input_size, this->samples))
		{
			LogWarning("Failed to convert sample data");
		}
		this->samples.resize(output_size);
	}
	~SDLSampleData() override = default;
	std::vector<unsigned char> samples;
};

static void unwrap_callback(void *userdata, Uint8 *stream, int len);

class SDLRawBackend : public SoundBackend
{
	std::recursive_mutex audio_lock;

	float overall_volume;
	float music_volume;
	float sound_volume;

	sp<MusicTrack> track;
	bool music_playing;

	std::function<void(void *)> music_finished_callback;
	void *music_callback_data;

	std::list<SampleData> live_samples;

	SDL_AudioDeviceID devID;
	SDL_AudioSpec output_spec;
	AudioFormat preferred_format;

	sp<MusicData> current_music_data;
	std::queue<sp<MusicData>> music_queue;

	std::future<void> get_music_future;

	int music_queue_size;

	void get_more_music()
	{
		TRACE_FN;
		std::lock_guard<std::recursive_mutex> lock(this->audio_lock);
		if (!this->music_playing)
		{
			// Music probably disabled in the time it took us to be scheduled?
			return;
		}
		if (!this->track)
		{
			LogWarning("Music playing but no track?");
			return;
		}
		while (this->music_queue.size() < this->music_queue_size)
		{
			auto data = mksp<MusicData>();

			unsigned int input_size = this->track->format.getSampleSize() *
			                          this->track->format.channels *
			                          this->track->requestedSampleBufferSize;
			unsigned int output_size = (SDL_AUDIO_BITSIZE(this->output_spec.format) / 8) *
			                           this->output_spec.channels *
			                           this->track->requestedSampleBufferSize;

			data->samples.resize(std::max(input_size, output_size));

			unsigned int returned_samples;

			auto ret = this->track->callback(this->track, this->track->requestedSampleBufferSize,
			                                 (void *)data->samples.data(), &returned_samples);

			// Reset the sizes, as we may have fewer returned_samples than asked for
			input_size = this->track->format.getSampleSize() * this->track->format.channels *
			             returned_samples;
			output_size = (SDL_AUDIO_BITSIZE(this->output_spec.format) / 8) *
			              this->output_spec.channels * returned_samples;

			bool convert_ret =
			    ConvertAudio(this->track->format, this->output_spec, input_size, data->samples);
			if (!convert_ret)
			{
				LogWarning("Failed to convert music data");
			}

			data->samples.resize(output_size);

			if (ret == MusicTrack::MusicCallbackReturn::End)
			{
				this->track = nullptr;
				if (this->music_finished_callback)
				{
					this->music_finished_callback(music_callback_data);
				}
			}
			this->music_queue.push(data);
		}
	}

  public:
	void mixingCallback(Uint8 *stream, int len)
	{
		TRACE_FN;
		// initialize stream buffer
		memset(stream, 0, len);
		std::lock_guard<std::recursive_mutex> lock(this->audio_lock);

		if (this->current_music_data || !this->music_queue.empty())
		{
			int int_music_volume =
			    clamp((int)lrint(this->overall_volume * this->music_volume * 128.0f), 0, 128);
			int music_bytes = 0;
			while (music_bytes < len)
			{
				if (!this->current_music_data)
				{
					this->get_music_future =
					    fw().threadPool->enqueue(std::mem_fn(&SDLRawBackend::get_more_music), this);
					if (this->music_queue.empty())
					{
						LogWarning("Music underrun!");
						break;
					}
					this->current_music_data = this->music_queue.front();
					this->music_queue.pop();
				}
				int bytes_from_this_chunk =
				    std::min(len - music_bytes, (int)(this->current_music_data->samples.size() -
				                                      this->current_music_data->sample_position));
				SDL_MixAudioFormat(
				    stream + music_bytes, this->current_music_data->samples.data() +
				                              this->current_music_data->sample_position,
				    this->output_spec.format, bytes_from_this_chunk, int_music_volume);
				music_bytes += bytes_from_this_chunk;
				this->current_music_data->sample_position += bytes_from_this_chunk;
				assert(this->current_music_data->sample_position <=
				       this->current_music_data->samples.size());
				if (this->current_music_data->sample_position ==
				    this->current_music_data->samples.size())
				{
					this->current_music_data = nullptr;
				}
			}
		}

		auto sampleIt = this->live_samples.begin();
		while (sampleIt != this->live_samples.end())
		{
			int int_sample_volume = clamp(
			    (int)lrint(this->overall_volume * this->sound_volume * sampleIt->gain * 128.0f), 0,
			    128);
			auto sampleData =
			    std::dynamic_pointer_cast<SDLSampleData>(sampleIt->sample->backendData);
			if (!sampleData)
			{
				LogWarning("Sample with invalid sample data");
				// Clear it in case we've changed drivers or something
				sampleIt->sample->backendData = nullptr;
				sampleIt = this->live_samples.erase(sampleIt);
				continue;
			}
			if (sampleIt->sample_position == sampleData->samples.size())
			{
				// Reached the end of the sample
				sampleIt = this->live_samples.erase(sampleIt);
				continue;
			}

			unsigned bytes_to_mix =
			    std::min(len, (int)(sampleData->samples.size() - sampleIt->sample_position));
			SDL_MixAudioFormat(stream, sampleData->samples.data() + sampleIt->sample_position,
			                   this->output_spec.format, bytes_to_mix, int_sample_volume);
			sampleIt->sample_position += bytes_to_mix;
			assert(sampleIt->sample_position <= sampleData->samples.size());

			sampleIt++;
		}
	}

	SDLRawBackend()
	    : overall_volume(1.0f), music_volume(1.0f), sound_volume(1.0f),
	      music_callback_data(nullptr), music_playing(false), music_queue_size(2)
	{
		SDL_Init(SDL_INIT_AUDIO);
		preferred_format.channels = 2;
		preferred_format.format = AudioFormat::SampleFormat::PCM_SINT16;
		preferred_format.frequency = 22050;
		LogInfo("Current audio driver: %s", SDL_GetCurrentAudioDriver());
		LogWarning("Changing audio drivers is not currently implemented!");
		int numDevices = SDL_GetNumAudioDevices(0); // Request playback devices only
		LogInfo("Number of audio devices: %d", numDevices);
		for (int i = 0; i < numDevices; ++i)
		{
			LogInfo("Device %d: %s", i, SDL_GetAudioDeviceName(i, 0));
		}
		LogWarning(
		    "Selecting audio devices not currently implemented! Selecting first available device.");
		const char *deviceName = SDL_GetAudioDeviceName(0, 0);
		SDL_AudioSpec wantFormat;
		wantFormat.channels = 2;
		wantFormat.format = AUDIO_S16LSB;
		wantFormat.freq = 22050;
		wantFormat.samples = 512;
		wantFormat.callback = unwrap_callback;
		wantFormat.userdata = this;
		devID = SDL_OpenAudioDevice(
		    nullptr, // "NULL" here is a 'reasonable default', which uses the platform default when
		             // available
		    0,       // capturing is not supported
		    &wantFormat, &output_spec,
		    SDL_AUDIO_ALLOW_ANY_CHANGE); // hopefully we'll get a sane output format
		SDL_PauseAudioDevice(devID, 0);  // Run at once?
		LogInfo("Audio output format: Channels %d, format %d, freq %d, samples %d",
		        (int)output_spec.channels, (int)output_spec.format, (int)output_spec.freq,
		        (int)output_spec.samples);
	}
	void playSample(sp<Sample> sample, float gain) override
	{
		// Clamp to 0..1
		gain = std::min(1.0f, std::max(0.0f, gain));
		if (!sample->backendData)
		{
			sample->backendData.reset(new SDLSampleData(sample, this->output_spec));
		}
		{
			std::lock_guard<std::recursive_mutex> l(this->audio_lock);
			this->live_samples.emplace_back(sample, gain);
		}
		LogInfo("Placed sound %p on queue", sample.get());
	}

	void playMusic(std::function<void(void *)> finishedCallback, void *callbackData) override
	{
		std::lock_guard<std::recursive_mutex> l(this->audio_lock);
		while (!music_queue.empty())
			music_queue.pop();
		music_finished_callback = finishedCallback;
		music_callback_data = callbackData;
		music_playing = true;
		this->get_music_future =
		    fw().threadPool->enqueue(std::mem_fn(&SDLRawBackend::get_more_music), this);
		LogInfo("Playing music on SDL backend");
	}

	void setTrack(sp<MusicTrack> track) override
	{
		std::lock_guard<std::recursive_mutex> l(this->audio_lock);
		LogInfo("Setting track to %p", track.get());
		this->track = track;
		while (!music_queue.empty())
			music_queue.pop();
	}

	void stopMusic() override
	{
		std::future<void> outstanding_get_music;
		{
			std::lock_guard<std::recursive_mutex> l(this->audio_lock);
			this->music_playing = false;
			this->track = nullptr;
			if (this->get_music_future.valid())
				outstanding_get_music = std::move(this->get_music_future);
			while (!music_queue.empty())
				music_queue.pop();
		}
		if (outstanding_get_music.valid())
			outstanding_get_music.wait();
	}

	virtual ~SDLRawBackend()
	{
		// Lock the device and stop any outstanding music threads to ensure everything is dead
		// before destroying the device
		SDL_LockAudioDevice(devID);
		SDL_PauseAudioDevice(devID, 1);
		this->stopMusic();
		SDL_UnlockAudioDevice(devID);
		SDL_CloseAudioDevice(devID);
		SDL_QuitSubSystem(SDL_INIT_AUDIO);
	}

	virtual const AudioFormat &getPreferredFormat() { return preferred_format; }

	float getGain(Gain g) override
	{
		float reqGain = 0;
		switch (g)
		{
			case Gain::Global:
				reqGain = overall_volume;
				break;
			case Gain::Sample:
				reqGain = sound_volume;
				break;
			case Gain::Music:
				reqGain = music_volume;
				break;
		}
		return reqGain;
	}
	void setGain(Gain g, float f) override
	{
		// Clamp to 0..1
		f = std::min(1.0f, std::max(0.0f, f));
		switch (g)
		{
			case Gain::Global:
				overall_volume = f;
				break;
			case Gain::Sample:
				sound_volume = f;
				break;
			case Gain::Music:
				music_volume = f;
				break;
		}
	}
};

void unwrap_callback(void *userdata, Uint8 *stream, int len)
{
	auto backend = reinterpret_cast<SDLRawBackend *>(userdata);
	backend->mixingCallback(stream, len);
}

class SDLRawBackendFactory : public SoundBackendFactory
{
  public:
	SoundBackend *create() override
	{
		LogWarning("Creating SDLRaw sound backend (Might have issues!)");
		int ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
		if (ret < 0)
		{
			LogWarning("Failed to init SDL_AUDIO (%d) - %s", ret, SDL_GetError());
			return nullptr;
		}
		return new SDLRawBackend();
	}

	virtual ~SDLRawBackendFactory() {}
};

}; // anonymous namespace

namespace OpenApoc
{
SoundBackendFactory *getSDLSoundBackend() { return new SDLRawBackendFactory(); }
} // namespace OpenApoc
<commit_msg>SDLraw audio: print device name to info<commit_after>#include "framework/framework.h"
#include "framework/logger.h"
#include "framework/sound_interface.h"
#include "framework/trace.h"
#include "library/sp.h"
#include "library/vec.h"
#include <SDL.h>
#include <SDL_audio.h>
#include <list>
#include <mutex>
#include <queue>

namespace
{

using namespace OpenApoc;

struct SampleData
{
	sp<Sample> sample;
	float gain;
	int sample_position; // in bytes
	SampleData(sp<Sample> sample, float gain) : sample(sample), gain(gain), sample_position(0) {}
};

struct MusicData
{
	MusicData() : sample_position(0) {}
	std::vector<unsigned char> samples;
	int sample_position; // in bytes
};

// 'samples' must already be large enough to contain the full output size
static bool ConvertAudio(AudioFormat input_format, SDL_AudioSpec &output_spec, int input_size_bytes,
                         std::vector<unsigned char> &samples)
{
	SDL_AudioCVT cvt;
	SDL_AudioFormat sdl_input_format;
	switch (input_format.format)
	{
		case AudioFormat::SampleFormat::PCM_SINT16:
			sdl_input_format = AUDIO_S16LSB;
			break;
		case AudioFormat::SampleFormat::PCM_UINT8:
			sdl_input_format = AUDIO_U8;
			break;
		default:
			LogWarning("Unknown input sample format");
			return false;
	}

	int ret =
	    SDL_BuildAudioCVT(&cvt, sdl_input_format, input_format.channels, input_format.frequency,
	                      output_spec.format, output_spec.channels, output_spec.freq);
	if (ret < 0)
	{
		LogWarning("Failed to build AudioCVT");
		return false;
	}
	else if (ret == 0)
	{
		// No conversion needed
		return true;
	}
	else
	{
		cvt.len = input_size_bytes;
		cvt.buf = (Uint8 *)samples.data();
		SDL_ConvertAudio(&cvt);
		return true;
	}
}

class SDLSampleData : public BackendSampleData
{
  public:
	SDLSampleData(sp<Sample> sample, SDL_AudioSpec &output_spec)
	{
		unsigned int input_size =
		    sample->format.getSampleSize() * sample->format.channels * sample->sampleCount;
		unsigned int output_size = (SDL_AUDIO_BITSIZE(output_spec.format) / 8) *
		                           output_spec.channels * sample->sampleCount;
		this->samples.resize(std::max(input_size, output_size));
		memcpy(this->samples.data(), sample->data.get(), input_size);
		if (!ConvertAudio(sample->format, output_spec, input_size, this->samples))
		{
			LogWarning("Failed to convert sample data");
		}
		this->samples.resize(output_size);
	}
	~SDLSampleData() override = default;
	std::vector<unsigned char> samples;
};

static void unwrap_callback(void *userdata, Uint8 *stream, int len);

class SDLRawBackend : public SoundBackend
{
	std::recursive_mutex audio_lock;

	float overall_volume;
	float music_volume;
	float sound_volume;

	sp<MusicTrack> track;
	bool music_playing;

	std::function<void(void *)> music_finished_callback;
	void *music_callback_data;

	std::list<SampleData> live_samples;

	SDL_AudioDeviceID devID;
	SDL_AudioSpec output_spec;
	AudioFormat preferred_format;

	sp<MusicData> current_music_data;
	std::queue<sp<MusicData>> music_queue;

	std::future<void> get_music_future;

	int music_queue_size;

	void get_more_music()
	{
		TRACE_FN;
		std::lock_guard<std::recursive_mutex> lock(this->audio_lock);
		if (!this->music_playing)
		{
			// Music probably disabled in the time it took us to be scheduled?
			return;
		}
		if (!this->track)
		{
			LogWarning("Music playing but no track?");
			return;
		}
		while (this->music_queue.size() < this->music_queue_size)
		{
			auto data = mksp<MusicData>();

			unsigned int input_size = this->track->format.getSampleSize() *
			                          this->track->format.channels *
			                          this->track->requestedSampleBufferSize;
			unsigned int output_size = (SDL_AUDIO_BITSIZE(this->output_spec.format) / 8) *
			                           this->output_spec.channels *
			                           this->track->requestedSampleBufferSize;

			data->samples.resize(std::max(input_size, output_size));

			unsigned int returned_samples;

			auto ret = this->track->callback(this->track, this->track->requestedSampleBufferSize,
			                                 (void *)data->samples.data(), &returned_samples);

			// Reset the sizes, as we may have fewer returned_samples than asked for
			input_size = this->track->format.getSampleSize() * this->track->format.channels *
			             returned_samples;
			output_size = (SDL_AUDIO_BITSIZE(this->output_spec.format) / 8) *
			              this->output_spec.channels * returned_samples;

			bool convert_ret =
			    ConvertAudio(this->track->format, this->output_spec, input_size, data->samples);
			if (!convert_ret)
			{
				LogWarning("Failed to convert music data");
			}

			data->samples.resize(output_size);

			if (ret == MusicTrack::MusicCallbackReturn::End)
			{
				this->track = nullptr;
				if (this->music_finished_callback)
				{
					this->music_finished_callback(music_callback_data);
				}
			}
			this->music_queue.push(data);
		}
	}

  public:
	void mixingCallback(Uint8 *stream, int len)
	{
		TRACE_FN;
		// initialize stream buffer
		memset(stream, 0, len);
		std::lock_guard<std::recursive_mutex> lock(this->audio_lock);

		if (this->current_music_data || !this->music_queue.empty())
		{
			int int_music_volume =
			    clamp((int)lrint(this->overall_volume * this->music_volume * 128.0f), 0, 128);
			int music_bytes = 0;
			while (music_bytes < len)
			{
				if (!this->current_music_data)
				{
					this->get_music_future =
					    fw().threadPool->enqueue(std::mem_fn(&SDLRawBackend::get_more_music), this);
					if (this->music_queue.empty())
					{
						LogWarning("Music underrun!");
						break;
					}
					this->current_music_data = this->music_queue.front();
					this->music_queue.pop();
				}
				int bytes_from_this_chunk =
				    std::min(len - music_bytes, (int)(this->current_music_data->samples.size() -
				                                      this->current_music_data->sample_position));
				SDL_MixAudioFormat(
				    stream + music_bytes, this->current_music_data->samples.data() +
				                              this->current_music_data->sample_position,
				    this->output_spec.format, bytes_from_this_chunk, int_music_volume);
				music_bytes += bytes_from_this_chunk;
				this->current_music_data->sample_position += bytes_from_this_chunk;
				assert(this->current_music_data->sample_position <=
				       this->current_music_data->samples.size());
				if (this->current_music_data->sample_position ==
				    this->current_music_data->samples.size())
				{
					this->current_music_data = nullptr;
				}
			}
		}

		auto sampleIt = this->live_samples.begin();
		while (sampleIt != this->live_samples.end())
		{
			int int_sample_volume = clamp(
			    (int)lrint(this->overall_volume * this->sound_volume * sampleIt->gain * 128.0f), 0,
			    128);
			auto sampleData =
			    std::dynamic_pointer_cast<SDLSampleData>(sampleIt->sample->backendData);
			if (!sampleData)
			{
				LogWarning("Sample with invalid sample data");
				// Clear it in case we've changed drivers or something
				sampleIt->sample->backendData = nullptr;
				sampleIt = this->live_samples.erase(sampleIt);
				continue;
			}
			if (sampleIt->sample_position == sampleData->samples.size())
			{
				// Reached the end of the sample
				sampleIt = this->live_samples.erase(sampleIt);
				continue;
			}

			unsigned bytes_to_mix =
			    std::min(len, (int)(sampleData->samples.size() - sampleIt->sample_position));
			SDL_MixAudioFormat(stream, sampleData->samples.data() + sampleIt->sample_position,
			                   this->output_spec.format, bytes_to_mix, int_sample_volume);
			sampleIt->sample_position += bytes_to_mix;
			assert(sampleIt->sample_position <= sampleData->samples.size());

			sampleIt++;
		}
	}

	SDLRawBackend()
	    : overall_volume(1.0f), music_volume(1.0f), sound_volume(1.0f),
	      music_callback_data(nullptr), music_playing(false), music_queue_size(2)
	{
		SDL_Init(SDL_INIT_AUDIO);
		preferred_format.channels = 2;
		preferred_format.format = AudioFormat::SampleFormat::PCM_SINT16;
		preferred_format.frequency = 22050;
		LogInfo("Current audio driver: %s", SDL_GetCurrentAudioDriver());
		LogWarning("Changing audio drivers is not currently implemented!");
		int numDevices = SDL_GetNumAudioDevices(0); // Request playback devices only
		LogInfo("Number of audio devices: %d", numDevices);
		for (int i = 0; i < numDevices; ++i)
		{
			LogInfo("Device %d: %s", i, SDL_GetAudioDeviceName(i, 0));
		}
		LogWarning(
		    "Selecting audio devices not currently implemented! Selecting first available device.");
		const char *deviceName = SDL_GetAudioDeviceName(0, 0);
		LogInfo("Using audio device: %s", deviceName);
		SDL_AudioSpec wantFormat;
		wantFormat.channels = 2;
		wantFormat.format = AUDIO_S16LSB;
		wantFormat.freq = 22050;
		wantFormat.samples = 512;
		wantFormat.callback = unwrap_callback;
		wantFormat.userdata = this;
		devID = SDL_OpenAudioDevice(
		    nullptr, // "NULL" here is a 'reasonable default', which uses the platform default when
		             // available
		    0,       // capturing is not supported
		    &wantFormat, &output_spec,
		    SDL_AUDIO_ALLOW_ANY_CHANGE); // hopefully we'll get a sane output format
		SDL_PauseAudioDevice(devID, 0);  // Run at once?
		LogInfo("Audio output format: Channels %d, format %d, freq %d, samples %d",
		        (int)output_spec.channels, (int)output_spec.format, (int)output_spec.freq,
		        (int)output_spec.samples);
	}
	void playSample(sp<Sample> sample, float gain) override
	{
		// Clamp to 0..1
		gain = std::min(1.0f, std::max(0.0f, gain));
		if (!sample->backendData)
		{
			sample->backendData.reset(new SDLSampleData(sample, this->output_spec));
		}
		{
			std::lock_guard<std::recursive_mutex> l(this->audio_lock);
			this->live_samples.emplace_back(sample, gain);
		}
		LogInfo("Placed sound %p on queue", sample.get());
	}

	void playMusic(std::function<void(void *)> finishedCallback, void *callbackData) override
	{
		std::lock_guard<std::recursive_mutex> l(this->audio_lock);
		while (!music_queue.empty())
			music_queue.pop();
		music_finished_callback = finishedCallback;
		music_callback_data = callbackData;
		music_playing = true;
		this->get_music_future =
		    fw().threadPool->enqueue(std::mem_fn(&SDLRawBackend::get_more_music), this);
		LogInfo("Playing music on SDL backend");
	}

	void setTrack(sp<MusicTrack> track) override
	{
		std::lock_guard<std::recursive_mutex> l(this->audio_lock);
		LogInfo("Setting track to %p", track.get());
		this->track = track;
		while (!music_queue.empty())
			music_queue.pop();
	}

	void stopMusic() override
	{
		std::future<void> outstanding_get_music;
		{
			std::lock_guard<std::recursive_mutex> l(this->audio_lock);
			this->music_playing = false;
			this->track = nullptr;
			if (this->get_music_future.valid())
				outstanding_get_music = std::move(this->get_music_future);
			while (!music_queue.empty())
				music_queue.pop();
		}
		if (outstanding_get_music.valid())
			outstanding_get_music.wait();
	}

	virtual ~SDLRawBackend()
	{
		// Lock the device and stop any outstanding music threads to ensure everything is dead
		// before destroying the device
		SDL_LockAudioDevice(devID);
		SDL_PauseAudioDevice(devID, 1);
		this->stopMusic();
		SDL_UnlockAudioDevice(devID);
		SDL_CloseAudioDevice(devID);
		SDL_QuitSubSystem(SDL_INIT_AUDIO);
	}

	virtual const AudioFormat &getPreferredFormat() { return preferred_format; }

	float getGain(Gain g) override
	{
		float reqGain = 0;
		switch (g)
		{
			case Gain::Global:
				reqGain = overall_volume;
				break;
			case Gain::Sample:
				reqGain = sound_volume;
				break;
			case Gain::Music:
				reqGain = music_volume;
				break;
		}
		return reqGain;
	}
	void setGain(Gain g, float f) override
	{
		// Clamp to 0..1
		f = std::min(1.0f, std::max(0.0f, f));
		switch (g)
		{
			case Gain::Global:
				overall_volume = f;
				break;
			case Gain::Sample:
				sound_volume = f;
				break;
			case Gain::Music:
				music_volume = f;
				break;
		}
	}
};

void unwrap_callback(void *userdata, Uint8 *stream, int len)
{
	auto backend = reinterpret_cast<SDLRawBackend *>(userdata);
	backend->mixingCallback(stream, len);
}

class SDLRawBackendFactory : public SoundBackendFactory
{
  public:
	SoundBackend *create() override
	{
		LogWarning("Creating SDLRaw sound backend (Might have issues!)");
		int ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
		if (ret < 0)
		{
			LogWarning("Failed to init SDL_AUDIO (%d) - %s", ret, SDL_GetError());
			return nullptr;
		}
		return new SDLRawBackend();
	}

	virtual ~SDLRawBackendFactory() {}
};

}; // anonymous namespace

namespace OpenApoc
{
SoundBackendFactory *getSDLSoundBackend() { return new SDLRawBackendFactory(); }
} // namespace OpenApoc
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: objshimp.hxx,v $
 * $Revision: 1.45 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org 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.
 *
 * OpenOffice.org 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
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SFX_OBJSHIMP_HXX
#define _SFX_OBJSHIMP_HXX

//#include <hash_map>

#include <com/sun/star/frame/XModel.hpp>
#include <tools/datetime.hxx>

#include <svtools/securityoptions.hxx>
#include <sfx2/objsh.hxx>
#include "sfx2/docmacromode.hxx"
#include "bitset.hxx"

namespace svtools { class AsynchronLink; }

//====================================================================

DBG_NAMEEX(SfxObjectShell)

class SfxViewFrame;
struct MarkData_Impl
{
    String aMark;
    String aUserData;
    SfxViewFrame* pFrame;
};

class SfxFrame;
class SfxToolBoxConfig;
class SfxAcceleratorManager;
class SfxBasicManagerHolder;

struct SfxObjectShell_Impl : public ::sfx2::IMacroDocumentAccess
{
    ::comphelper::EmbeddedObjectContainer* mpObjectContainer;
    SfxAcceleratorManager*  pAccMgr;
    SfxConfigManager*   pCfgMgr;
    SfxBasicManagerHolder*
                        pBasicManager;
    SfxObjectShell&     rDocShell;
    ::com::sun::star::uno::Reference< ::com::sun::star::script::XLibraryContainer >
                        xBasicLibraries;
    ::com::sun::star::uno::Reference< ::com::sun::star::script::XLibraryContainer >
                        xDialogLibraries;
    ::sfx2::DocumentMacroMode
                        aMacroMode;
    SfxProgress*        pProgress;
    String              aTitle;
    String              aTempName;
    DateTime            nTime;
    sal_uInt16          nVisualDocumentNumber;
    sal_Int16           nDocumentSignatureState;
    sal_Int16           nScriptingSignatureState;
    sal_Bool            bTemplateConfig:1,
                        bInList:1,          // ob per First/Next erreichbar
                        bClosing:1,         // sal_True w"aehrend Close(), um Benachrichtigungs-Rekursionen zu verhindern
                        bSetInPlaceObj:1,   // sal_True, falls bereits versucht wurde pInPlaceObject zu casten
                        bIsSaving:1,
                        bPasswd:1,
                        bIsTmp:1,
                        bIsNamedVisible:1,
                        bIsTemplate:1,
                        bIsAbortingImport:1,  // Importvorgang soll abgebrochen werden.
                        bImportDone : 1, //Import schon fertig? Fuer AutoReload von Docs.
                        bInPrepareClose : 1,
                        bPreparedForClose : 1,
                        bWaitingForPicklist : 1,// Muss noch in die Pickliste
                        bModuleSearched : 1,
                        bIsHelpObjSh : 1,
                        bForbidCaching : 1,
                        bForbidReload : 1,
                        bSupportsEventMacros: 1,
                        bLoadingWindows: 1,
                        bBasicInitialized :1,
                        //bHidden :1, // indicates a hidden view shell
                        bIsPrintJobCancelable :1, // Stampit disable/enable cancel button for print jobs ... default = true = enable!
                        bOwnsStorage:1,
                        bNoBaseURL:1,
                        bInitialized:1,
                        bSignatureErrorIsShown:1,
                        bModelInitialized:1, // whether the related model is initialized
                        bPreserveVersions:1,
                        m_bMacroSignBroken:1, // whether the macro signature was explicitly broken
                        m_bNoBasicCapabilities:1,
                        bQueryLoadTemplate:1,
                        bLoadReadonly:1,
                        bUseUserData:1,
                        bSaveVersionOnClose:1,
                        m_bSharedXMLFlag:1, // whether the flag should be stored in xml file
                        m_bAllowShareControlFileClean:1; // whether the flag should be stored in xml file

    String              aNewName;  // Der Name, unter dem das Doc gespeichert
                                   // werden soll
    IndexBitSet         aBitSet;
    sal_uInt32               lErr;
    sal_uInt16              nEventId;           // falls vor Activate noch ein
                                            // Open/Create gesendet werden mu/s
    sal_Bool                bDoNotTouchDocInfo;

    AutoReloadTimer_Impl *pReloadTimer;
    MarkData_Impl*      pMarkData;
    sal_uInt16              nLoadedFlags;
    sal_uInt16              nFlagsInProgress;
    String              aMark;
    Size                aViewSize;          // wird leider vom Writer beim
    sal_Bool                bInFrame;           // HTML-Import gebraucht
    sal_Bool                bModalMode;
    sal_Bool                bRunningMacro;
    sal_Bool                bReloadAvailable;
    sal_uInt16              nAutoLoadLocks;
    SfxModule*              pModule;
    SfxFrame*               pFrame;
    SfxToolBoxConfig*       pTbxConfig;
    SfxEventConfigItem_Impl* pEventConfig;
    SfxObjectShellFlags     eFlags;
    svtools::AsynchronLink* pCloser;
    String                  aBaseURL;
    sal_Bool                bReadOnlyUI;
    SvRefBaseRef            xHeaderAttributes;
    sal_Bool                bHiddenLockedByAPI;
    sal_Bool                bInCloseEvent;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > xModel;
    sal_uInt16              nStyleFilter;
    sal_Bool                bDisposing;

    sal_Bool                m_bEnableSetModified;
    sal_Bool                m_bIsModified;

    Rectangle               m_aVisArea;
    MapUnit                 m_nMapUnit;

    sal_Bool                m_bCreateTempStor;
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > m_xDocStorage;

    ::com::sun::star::uno::Reference<
        ::com::sun::star::util::XModifyListener > m_xDocInfoListener;

    sal_Bool                m_bIsInit;

    ::rtl::OUString         m_aSharedFileURL;

    SfxObjectShell_Impl( SfxObjectShell& _rDocShell );
    virtual ~SfxObjectShell_Impl();

    // IMacroDocumentAccess overridables
    virtual sal_Int16 getImposedMacroExecMode() const;
    virtual sal_Bool setImposedMacroExecMode( sal_uInt16 nMacroMode );
    virtual ::rtl::OUString getDocumentLocation() const;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > getLastCommitDocumentStorage();
    virtual sal_Bool documentStorageHasMacros() const;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const;
    virtual sal_Int16 getScriptingSignatureState() const;
    virtual void showBrokenSignatureWarning( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxInteraction ) const;
};

#endif

<commit_msg>INTEGRATION: CWS dba30b (1.43.6); FILE MERGED 2008/04/15 22:18:31 fs 1.43.6.2: RESYNC: (1.43-1.44); FILE MERGED 2008/03/17 09:13:49 fs 1.43.6.1: during #152837#: IMacroDocumentAccess::(s|g)etImposedMacroExecMode renamed to (s|g)etCurrentMacroExecMode, to better fit its changed semantics<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: objshimp.hxx,v $
 * $Revision: 1.46 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org 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.
 *
 * OpenOffice.org 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
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SFX_OBJSHIMP_HXX
#define _SFX_OBJSHIMP_HXX

//#include <hash_map>

#include <com/sun/star/frame/XModel.hpp>
#include <tools/datetime.hxx>

#include <svtools/securityoptions.hxx>
#include <sfx2/objsh.hxx>
#include "sfx2/docmacromode.hxx"
#include "bitset.hxx"

namespace svtools { class AsynchronLink; }

//====================================================================

DBG_NAMEEX(SfxObjectShell)

class SfxViewFrame;
struct MarkData_Impl
{
    String aMark;
    String aUserData;
    SfxViewFrame* pFrame;
};

class SfxFrame;
class SfxToolBoxConfig;
class SfxAcceleratorManager;
class SfxBasicManagerHolder;

struct SfxObjectShell_Impl : public ::sfx2::IMacroDocumentAccess
{
    ::comphelper::EmbeddedObjectContainer* mpObjectContainer;
    SfxAcceleratorManager*  pAccMgr;
    SfxConfigManager*   pCfgMgr;
    SfxBasicManagerHolder*
                        pBasicManager;
    SfxObjectShell&     rDocShell;
    ::com::sun::star::uno::Reference< ::com::sun::star::script::XLibraryContainer >
                        xBasicLibraries;
    ::com::sun::star::uno::Reference< ::com::sun::star::script::XLibraryContainer >
                        xDialogLibraries;
    ::sfx2::DocumentMacroMode
                        aMacroMode;
    SfxProgress*        pProgress;
    String              aTitle;
    String              aTempName;
    DateTime            nTime;
    sal_uInt16          nVisualDocumentNumber;
    sal_Int16           nDocumentSignatureState;
    sal_Int16           nScriptingSignatureState;
    sal_Bool            bTemplateConfig:1,
                        bInList:1,          // ob per First/Next erreichbar
                        bClosing:1,         // sal_True w"aehrend Close(), um Benachrichtigungs-Rekursionen zu verhindern
                        bSetInPlaceObj:1,   // sal_True, falls bereits versucht wurde pInPlaceObject zu casten
                        bIsSaving:1,
                        bPasswd:1,
                        bIsTmp:1,
                        bIsNamedVisible:1,
                        bIsTemplate:1,
                        bIsAbortingImport:1,  // Importvorgang soll abgebrochen werden.
                        bImportDone : 1, //Import schon fertig? Fuer AutoReload von Docs.
                        bInPrepareClose : 1,
                        bPreparedForClose : 1,
                        bWaitingForPicklist : 1,// Muss noch in die Pickliste
                        bModuleSearched : 1,
                        bIsHelpObjSh : 1,
                        bForbidCaching : 1,
                        bForbidReload : 1,
                        bSupportsEventMacros: 1,
                        bLoadingWindows: 1,
                        bBasicInitialized :1,
                        //bHidden :1, // indicates a hidden view shell
                        bIsPrintJobCancelable :1, // Stampit disable/enable cancel button for print jobs ... default = true = enable!
                        bOwnsStorage:1,
                        bNoBaseURL:1,
                        bInitialized:1,
                        bSignatureErrorIsShown:1,
                        bModelInitialized:1, // whether the related model is initialized
                        bPreserveVersions:1,
                        m_bMacroSignBroken:1, // whether the macro signature was explicitly broken
                        m_bNoBasicCapabilities:1,
                        bQueryLoadTemplate:1,
                        bLoadReadonly:1,
                        bUseUserData:1,
                        bSaveVersionOnClose:1,
                        m_bSharedXMLFlag:1, // whether the flag should be stored in xml file
                        m_bAllowShareControlFileClean:1; // whether the flag should be stored in xml file

    String              aNewName;  // Der Name, unter dem das Doc gespeichert
                                   // werden soll
    IndexBitSet         aBitSet;
    sal_uInt32               lErr;
    sal_uInt16              nEventId;           // falls vor Activate noch ein
                                            // Open/Create gesendet werden mu/s
    sal_Bool                bDoNotTouchDocInfo;

    AutoReloadTimer_Impl *pReloadTimer;
    MarkData_Impl*      pMarkData;
    sal_uInt16              nLoadedFlags;
    sal_uInt16              nFlagsInProgress;
    String              aMark;
    Size                aViewSize;          // wird leider vom Writer beim
    sal_Bool                bInFrame;           // HTML-Import gebraucht
    sal_Bool                bModalMode;
    sal_Bool                bRunningMacro;
    sal_Bool                bReloadAvailable;
    sal_uInt16              nAutoLoadLocks;
    SfxModule*              pModule;
    SfxFrame*               pFrame;
    SfxToolBoxConfig*       pTbxConfig;
    SfxEventConfigItem_Impl* pEventConfig;
    SfxObjectShellFlags     eFlags;
    svtools::AsynchronLink* pCloser;
    String                  aBaseURL;
    sal_Bool                bReadOnlyUI;
    SvRefBaseRef            xHeaderAttributes;
    sal_Bool                bHiddenLockedByAPI;
    sal_Bool                bInCloseEvent;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > xModel;
    sal_uInt16              nStyleFilter;
    sal_Bool                bDisposing;

    sal_Bool                m_bEnableSetModified;
    sal_Bool                m_bIsModified;

    Rectangle               m_aVisArea;
    MapUnit                 m_nMapUnit;

    sal_Bool                m_bCreateTempStor;
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > m_xDocStorage;

    ::com::sun::star::uno::Reference<
        ::com::sun::star::util::XModifyListener > m_xDocInfoListener;

    sal_Bool                m_bIsInit;

    ::rtl::OUString         m_aSharedFileURL;

    SfxObjectShell_Impl( SfxObjectShell& _rDocShell );
    virtual ~SfxObjectShell_Impl();

    // IMacroDocumentAccess overridables
    virtual sal_Int16 getCurrentMacroExecMode() const;
    virtual sal_Bool setCurrentMacroExecMode( sal_uInt16 nMacroMode );
    virtual ::rtl::OUString getDocumentLocation() const;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > getLastCommitDocumentStorage();
    virtual sal_Bool documentStorageHasMacros() const;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const;
    virtual sal_Int16 getScriptingSignatureState() const;
    virtual void showBrokenSignatureWarning( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxInteraction ) const;
};

#endif

<|endoftext|>