<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 "pluginview.h"
#include "pluginview_p.h"
#include "pluginmanager.h"
#include "pluginspec.h"
#include "plugincollection.h"
#include "ui_pluginview.h"

#include <QtCore/QDir>
#include <QtGui/QHeaderView>
#include <QtGui/QTreeWidgetItem>
#include <QtGui/QPalette>

#include <QtDebug>

/*!
    \class ExtensionSystem::PluginView
    \brief Widget that shows a list of all plugins and their state.

    This can be embedded e.g. in a dialog in the application that
    uses the plugin manager.
    The class also provides notifications for interactions with the list.

    \sa ExtensionSystem::PluginDetailsView
    \sa ExtensionSystem::PluginErrorView
*/

/*!
    \fn void PluginView::currentPluginChanged(ExtensionSystem::PluginSpec *spec)
    The current selection in the plugin list has changed to the
    plugin corresponding to \a spec.
*/

/*!
    \fn void PluginView::pluginActivated(ExtensionSystem::PluginSpec *spec)
    The plugin list entry corresponding to \a spec has been activated,
    e.g. by a double-click.
*/

using namespace ExtensionSystem;

Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*);
Q_DECLARE_METATYPE(ExtensionSystem::PluginCollection*);

/*!
    \fn PluginView::PluginView(PluginManager *manager, QWidget *parent)
    Constructs a PluginView that gets the list of plugins from the
    given plugin \a manager with a given \a parent widget.
*/
PluginView::PluginView(PluginManager *manager, QWidget *parent)
    : QWidget(parent),
      m_ui(new Internal::Ui::PluginView),
      p(new Internal::PluginViewPrivate),
      m_allowCheckStateUpdate(true),
      C_LOAD(1)
{
    m_ui->setupUi(this);
    QHeaderView *header = m_ui->categoryWidget->header();
    header->setResizeMode(0, QHeaderView::ResizeToContents);
    header->setResizeMode(2, QHeaderView::ResizeToContents);

    m_okIcon = QIcon(QLatin1String(":/extensionsystem/images/ok.png"));
    m_errorIcon = QIcon(QLatin1String(":/extensionsystem/images/error.png"));
    m_notLoadedIcon = QIcon(QLatin1String(":/extensionsystem/images/notloaded.png"));

    m_ui->categoryWidget->setColumnWidth(C_LOAD, 40);

    // cannot disable these
    m_whitelist << QString("Core") << QString("Locator")
                << QString("Find") << QString("TextEditor");

    p->manager = manager;
    connect(p->manager, SIGNAL(pluginsChanged()), this, SLOT(updateList()));
    connect(m_ui->categoryWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
            this, SLOT(selectPlugin(QTreeWidgetItem*)));
    connect(m_ui->categoryWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
            this, SLOT(activatePlugin(QTreeWidgetItem*)));

    updateList();
}

/*!
    \fn PluginView::~PluginView()
    \internal
*/
PluginView::~PluginView()
{
    delete p;
    delete m_ui;
}

/*!
    \fn PluginSpec *PluginView::currentPlugin() const
    Returns the current selection in the list of plugins.
*/
PluginSpec *PluginView::currentPlugin() const
{
    if (!m_ui->categoryWidget->currentItem())
        return 0;
    if (!m_ui->categoryWidget->currentItem()->data(0, Qt::UserRole).isNull())
        return m_ui->categoryWidget->currentItem()->data(0, Qt::UserRole).value<PluginSpec *>();
    return 0;
}

void PluginView::updateList()
{
    connect(m_ui->categoryWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
            this, SLOT(updatePluginSettings(QTreeWidgetItem*, int)));

    PluginCollection *defaultCollection = 0;
    foreach(PluginCollection *collection, p->manager->pluginCollections()) {
        if (collection->name().isEmpty()) {
            defaultCollection = collection;
            continue;
        }
        // State, name, load, version, vendor.
        QTreeWidgetItem *collectionItem = new QTreeWidgetItem(QStringList()
            << collection->name()
            << QString()    // state
            << QString()    // load
            << QString()    // version
            << QString());  // vendor
        m_items.append(collectionItem);

        Qt::CheckState groupState = Qt::Unchecked;
        int state = parsePluginSpecs(collectionItem, groupState, collection->plugins());

        collectionItem->setIcon(0, iconForState(state));
        collectionItem->setData(C_LOAD, Qt::CheckStateRole, QVariant(groupState));
        collectionItem->setToolTip(C_LOAD, tr("Load on Startup"));
        collectionItem->setData(0, Qt::UserRole, qVariantFromValue(collection));
    }

    // add all non-categorized plugins into utilities. could also be added as root items
    // but that makes the tree ugly.
    QTreeWidgetItem *defaultCollectionItem = new QTreeWidgetItem(QStringList()
        << QString(tr("Utilities"))
        << QString()
        << QString()
        << QString()
        << QString());

    m_items.append(defaultCollectionItem);
    Qt::CheckState groupState = Qt::Unchecked;
    int state = parsePluginSpecs(defaultCollectionItem, groupState, defaultCollection->plugins());

    defaultCollectionItem->setIcon(0, iconForState(state));
    defaultCollectionItem->setData(C_LOAD, Qt::CheckStateRole, QVariant(groupState));
    defaultCollectionItem->setToolTip(C_LOAD, tr("Load on Startup"));
    defaultCollectionItem->setData(0, Qt::UserRole, qVariantFromValue(defaultCollection));

    updatePluginDependencies();

    m_ui->categoryWidget->clear();
    if (!m_items.isEmpty()) {
        m_ui->categoryWidget->addTopLevelItems(m_items);
        m_ui->categoryWidget->expandAll();
    }

    m_ui->categoryWidget->sortItems(0, Qt::AscendingOrder);
    if (m_ui->categoryWidget->topLevelItemCount())
        m_ui->categoryWidget->setCurrentItem(m_ui->categoryWidget->topLevelItem(0));
}

int PluginView::parsePluginSpecs(QTreeWidgetItem *parentItem, Qt::CheckState &groupState, QList<PluginSpec*> plugins)
{
    int ret = 0;
    int loadCount = 0;

    for (int i = 0; i < plugins.length(); ++i) {
        PluginSpec *spec = plugins[i];
        if (spec->hasError())
            ret |= ParsedWithErrors;

        QTreeWidgetItem *pluginItem = new QTreeWidgetItem(QStringList()
            << spec->name()
            << QString()    // load on startup
            << QString::fromLatin1("%1 (%2)").arg(spec->version(), spec->compatVersion())
            << spec->vendor());

        pluginItem->setToolTip(0, QDir::toNativeSeparators(spec->filePath()));
        bool ok = !spec->hasError();
        QIcon icon = ok ? m_okIcon : m_errorIcon;
        if (ok && (spec->state() != PluginSpec::Running))
            icon = m_notLoadedIcon;

        pluginItem->setIcon(0, icon);
        pluginItem->setData(0, Qt::UserRole, qVariantFromValue(spec));

        Qt::CheckState state = Qt::Unchecked;
        if (spec->isEnabled()) {
            state = Qt::Checked;
            ++loadCount;
        }

        if (!m_whitelist.contains(spec->name()))
            pluginItem->setData(C_LOAD, Qt::CheckStateRole, state);
        else {
            QColor disabledColor = palette().color(QPalette::Disabled,QPalette::WindowText).lighter(120);
            pluginItem->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
            pluginItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
            pluginItem->setSizeHint(C_LOAD, QSize(1,1));
            pluginItem->setForeground(C_LOAD, QBrush(disabledColor)); // QBrush(Qt::white, Qt::NoBrush));
            //pluginItem->setBackground(C_LOAD, QBrush(Qt::white, Qt::NoBrush));
        }
        pluginItem->setToolTip(C_LOAD, tr("Load on Startup"));

        m_specToItem.insert(spec, pluginItem);

        if (parentItem)
            parentItem->addChild(pluginItem);
        else
            m_items.append(pluginItem);

    }

    if (loadCount == plugins.length()) {
        groupState = Qt::Checked;
        ret |= ParsedAll;
    } else if (loadCount == 0) {
        groupState = Qt::Unchecked;
        ret |= ParsedNone;
    } else {
        groupState = Qt::PartiallyChecked;
        ret = ret | ParsedPartial;
    }
    return ret;
}

QIcon PluginView::iconForState(int state)
{
    if (state & ParsedWithErrors)
        return m_errorIcon;

    if (state & ParsedNone || state & ParsedPartial)
        return m_notLoadedIcon;

    return m_okIcon;
}

void PluginView::selectPlugin(QTreeWidgetItem *current)
{
    if (!current)
        emit currentPluginChanged(0);
    else if (current->data(0, Qt::UserRole).canConvert<PluginSpec*>())
        emit currentPluginChanged(current->data(0, Qt::UserRole).value<PluginSpec *>());
    else
        emit currentPluginChanged(0);

}

void PluginView::activatePlugin(QTreeWidgetItem *item)
{
    if (item->data(0, Qt::UserRole).canConvert<PluginSpec*>()) {
        emit pluginActivated(item->data(0, Qt::UserRole).value<PluginSpec *>());
    } else
        emit pluginActivated(0);
}

void PluginView::updatePluginSettings(QTreeWidgetItem *item, int column)
{
    if (!m_allowCheckStateUpdate)
        return;

    m_allowCheckStateUpdate = false;

    bool loadOnStartup = item->data(C_LOAD, Qt::CheckStateRole).toBool();

    if (item->data(0, Qt::UserRole).canConvert<PluginSpec*>()) {
        PluginSpec *spec = item->data(0, Qt::UserRole).value<PluginSpec *>();

        if (column == C_LOAD) {

            spec->setEnabled(loadOnStartup);
            updatePluginDependencies();

            if (item->parent()) {
                PluginCollection *collection = item->parent()->data(0, Qt::UserRole).value<PluginCollection *>();
                Qt::CheckState state = Qt::PartiallyChecked;
                int loadCount = 0;
                for (int i = 0; i < collection->plugins().length(); ++i) {
                    if (collection->plugins().at(i)->isEnabled())
                        ++loadCount;
                }
                if (loadCount == collection->plugins().length())
                    state = Qt::Checked;
                else if (loadCount == 0)
                    state = Qt::Unchecked;

                item->parent()->setData(C_LOAD, Qt::CheckStateRole, state);
            }

            emit pluginSettingsChanged(spec);
        }

    } else {
        PluginCollection *collection = item->data(0, Qt::UserRole).value<PluginCollection *>();
        for (int i = 0; i < collection->plugins().length(); ++i) {
            PluginSpec *spec = collection->plugins().at(i);
            QTreeWidgetItem *child = m_specToItem.value(spec);

            if (!m_whitelist.contains(spec->name())) {
                spec->setEnabled(loadOnStartup);
                Qt::CheckState state = (loadOnStartup ? Qt::Checked : Qt::Unchecked);
                child->setData(C_LOAD, Qt::CheckStateRole, state);
            } else {
                child->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
                child->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
            }
        }
        updatePluginDependencies();
        emit pluginSettingsChanged(collection->plugins().first());
    }

    m_allowCheckStateUpdate = true;
}

void PluginView::updatePluginDependencies()
{
    foreach (PluginSpec *spec, PluginManager::instance()->loadQueue()) {
        bool disableIndirectly = false;
        foreach(const PluginSpec *depSpec, spec->dependencySpecs()) {
            if (!depSpec->isEnabled() || depSpec->isDisabledIndirectly()) {
                disableIndirectly = true;
                break;
            }
        }
        QTreeWidgetItem *childItem = m_specToItem.value(spec);
        childItem->setDisabled(disableIndirectly);

        if (disableIndirectly == spec->isDisabledIndirectly())
            continue;
        spec->setDisabledIndirectly(disableIndirectly);

        if (childItem->parent() && !childItem->parent()->isExpanded())
            childItem->parent()->setExpanded(true);
    }
}
<commit_msg>Fixed disabled checkbox styles for plugin manager<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 "pluginview.h"
#include "pluginview_p.h"
#include "pluginmanager.h"
#include "pluginspec.h"
#include "plugincollection.h"
#include "ui_pluginview.h"

#include <QtCore/QDir>
#include <QtGui/QHeaderView>
#include <QtGui/QTreeWidgetItem>
#include <QtGui/QPalette>

#include <QtDebug>

/*!
    \class ExtensionSystem::PluginView
    \brief Widget that shows a list of all plugins and their state.

    This can be embedded e.g. in a dialog in the application that
    uses the plugin manager.
    The class also provides notifications for interactions with the list.

    \sa ExtensionSystem::PluginDetailsView
    \sa ExtensionSystem::PluginErrorView
*/

/*!
    \fn void PluginView::currentPluginChanged(ExtensionSystem::PluginSpec *spec)
    The current selection in the plugin list has changed to the
    plugin corresponding to \a spec.
*/

/*!
    \fn void PluginView::pluginActivated(ExtensionSystem::PluginSpec *spec)
    The plugin list entry corresponding to \a spec has been activated,
    e.g. by a double-click.
*/

using namespace ExtensionSystem;

Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*);
Q_DECLARE_METATYPE(ExtensionSystem::PluginCollection*);

/*!
    \fn PluginView::PluginView(PluginManager *manager, QWidget *parent)
    Constructs a PluginView that gets the list of plugins from the
    given plugin \a manager with a given \a parent widget.
*/
PluginView::PluginView(PluginManager *manager, QWidget *parent)
    : QWidget(parent),
      m_ui(new Internal::Ui::PluginView),
      p(new Internal::PluginViewPrivate),
      m_allowCheckStateUpdate(true),
      C_LOAD(1)
{
    m_ui->setupUi(this);
    QHeaderView *header = m_ui->categoryWidget->header();
    header->setResizeMode(0, QHeaderView::ResizeToContents);
    header->setResizeMode(2, QHeaderView::ResizeToContents);

    m_okIcon = QIcon(QLatin1String(":/extensionsystem/images/ok.png"));
    m_errorIcon = QIcon(QLatin1String(":/extensionsystem/images/error.png"));
    m_notLoadedIcon = QIcon(QLatin1String(":/extensionsystem/images/notloaded.png"));

    m_ui->categoryWidget->setColumnWidth(C_LOAD, 40);

    // cannot disable these
    m_whitelist << QString("Core") << QString("Locator")
                << QString("Find") << QString("TextEditor");

    p->manager = manager;
    connect(p->manager, SIGNAL(pluginsChanged()), this, SLOT(updateList()));
    connect(m_ui->categoryWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
            this, SLOT(selectPlugin(QTreeWidgetItem*)));
    connect(m_ui->categoryWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
            this, SLOT(activatePlugin(QTreeWidgetItem*)));

    updateList();
}

/*!
    \fn PluginView::~PluginView()
    \internal
*/
PluginView::~PluginView()
{
    delete p;
    delete m_ui;
}

/*!
    \fn PluginSpec *PluginView::currentPlugin() const
    Returns the current selection in the list of plugins.
*/
PluginSpec *PluginView::currentPlugin() const
{
    if (!m_ui->categoryWidget->currentItem())
        return 0;
    if (!m_ui->categoryWidget->currentItem()->data(0, Qt::UserRole).isNull())
        return m_ui->categoryWidget->currentItem()->data(0, Qt::UserRole).value<PluginSpec *>();
    return 0;
}

void PluginView::updateList()
{
    connect(m_ui->categoryWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
            this, SLOT(updatePluginSettings(QTreeWidgetItem*, int)));

    PluginCollection *defaultCollection = 0;
    foreach(PluginCollection *collection, p->manager->pluginCollections()) {
        if (collection->name().isEmpty()) {
            defaultCollection = collection;
            continue;
        }
        // State, name, load, version, vendor.
        QTreeWidgetItem *collectionItem = new QTreeWidgetItem(QStringList()
            << collection->name()
            << QString()    // state
            << QString()    // load
            << QString()    // version
            << QString());  // vendor
        m_items.append(collectionItem);

        Qt::CheckState groupState = Qt::Unchecked;
        int state = parsePluginSpecs(collectionItem, groupState, collection->plugins());

        collectionItem->setIcon(0, iconForState(state));
        collectionItem->setData(C_LOAD, Qt::CheckStateRole, QVariant(groupState));
        collectionItem->setToolTip(C_LOAD, tr("Load on Startup"));
        collectionItem->setData(0, Qt::UserRole, qVariantFromValue(collection));
    }

    // add all non-categorized plugins into utilities. could also be added as root items
    // but that makes the tree ugly.
    QTreeWidgetItem *defaultCollectionItem = new QTreeWidgetItem(QStringList()
        << QString(tr("Utilities"))
        << QString()
        << QString()
        << QString()
        << QString());

    m_items.append(defaultCollectionItem);
    Qt::CheckState groupState = Qt::Unchecked;
    int state = parsePluginSpecs(defaultCollectionItem, groupState, defaultCollection->plugins());

    defaultCollectionItem->setIcon(0, iconForState(state));
    defaultCollectionItem->setData(C_LOAD, Qt::CheckStateRole, QVariant(groupState));
    defaultCollectionItem->setToolTip(C_LOAD, tr("Load on Startup"));
    defaultCollectionItem->setData(0, Qt::UserRole, qVariantFromValue(defaultCollection));

    updatePluginDependencies();

    m_ui->categoryWidget->clear();
    if (!m_items.isEmpty()) {
        m_ui->categoryWidget->addTopLevelItems(m_items);
        m_ui->categoryWidget->expandAll();
    }

    m_ui->categoryWidget->sortItems(0, Qt::AscendingOrder);
    if (m_ui->categoryWidget->topLevelItemCount())
        m_ui->categoryWidget->setCurrentItem(m_ui->categoryWidget->topLevelItem(0));
}

int PluginView::parsePluginSpecs(QTreeWidgetItem *parentItem, Qt::CheckState &groupState, QList<PluginSpec*> plugins)
{
    int ret = 0;
    int loadCount = 0;

    for (int i = 0; i < plugins.length(); ++i) {
        PluginSpec *spec = plugins[i];
        if (spec->hasError())
            ret |= ParsedWithErrors;

        QTreeWidgetItem *pluginItem = new QTreeWidgetItem(QStringList()
            << spec->name()
            << QString()    // load on startup
            << QString::fromLatin1("%1 (%2)").arg(spec->version(), spec->compatVersion())
            << spec->vendor());

        pluginItem->setToolTip(0, QDir::toNativeSeparators(spec->filePath()));
        bool ok = !spec->hasError();
        QIcon icon = ok ? m_okIcon : m_errorIcon;
        if (ok && (spec->state() != PluginSpec::Running))
            icon = m_notLoadedIcon;

        pluginItem->setIcon(0, icon);
        pluginItem->setData(0, Qt::UserRole, qVariantFromValue(spec));

        Qt::CheckState state = Qt::Unchecked;
        if (spec->isEnabled()) {
            state = Qt::Checked;
            ++loadCount;
        }

        if (!m_whitelist.contains(spec->name())) {
            pluginItem->setData(C_LOAD, Qt::CheckStateRole, state);
        } else {
            pluginItem->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
            pluginItem->setFlags(Qt::ItemIsSelectable);
        }

        pluginItem->setToolTip(C_LOAD, tr("Load on Startup"));

        m_specToItem.insert(spec, pluginItem);

        if (parentItem)
            parentItem->addChild(pluginItem);
        else
            m_items.append(pluginItem);

    }

    if (loadCount == plugins.length()) {
        groupState = Qt::Checked;
        ret |= ParsedAll;
    } else if (loadCount == 0) {
        groupState = Qt::Unchecked;
        ret |= ParsedNone;
    } else {
        groupState = Qt::PartiallyChecked;
        ret = ret | ParsedPartial;
    }
    return ret;
}

QIcon PluginView::iconForState(int state)
{
    if (state & ParsedWithErrors)
        return m_errorIcon;

    if (state & ParsedNone || state & ParsedPartial)
        return m_notLoadedIcon;

    return m_okIcon;
}

void PluginView::selectPlugin(QTreeWidgetItem *current)
{
    if (!current)
        emit currentPluginChanged(0);
    else if (current->data(0, Qt::UserRole).canConvert<PluginSpec*>())
        emit currentPluginChanged(current->data(0, Qt::UserRole).value<PluginSpec *>());
    else
        emit currentPluginChanged(0);

}

void PluginView::activatePlugin(QTreeWidgetItem *item)
{
    if (item->data(0, Qt::UserRole).canConvert<PluginSpec*>()) {
        emit pluginActivated(item->data(0, Qt::UserRole).value<PluginSpec *>());
    } else
        emit pluginActivated(0);
}

void PluginView::updatePluginSettings(QTreeWidgetItem *item, int column)
{
    if (!m_allowCheckStateUpdate)
        return;

    m_allowCheckStateUpdate = false;

    bool loadOnStartup = item->data(C_LOAD, Qt::CheckStateRole).toBool();

    if (item->data(0, Qt::UserRole).canConvert<PluginSpec*>()) {
        PluginSpec *spec = item->data(0, Qt::UserRole).value<PluginSpec *>();

        if (column == C_LOAD) {

            spec->setEnabled(loadOnStartup);
            updatePluginDependencies();

            if (item->parent()) {
                PluginCollection *collection = item->parent()->data(0, Qt::UserRole).value<PluginCollection *>();
                Qt::CheckState state = Qt::PartiallyChecked;
                int loadCount = 0;
                for (int i = 0; i < collection->plugins().length(); ++i) {
                    if (collection->plugins().at(i)->isEnabled())
                        ++loadCount;
                }
                if (loadCount == collection->plugins().length())
                    state = Qt::Checked;
                else if (loadCount == 0)
                    state = Qt::Unchecked;

                item->parent()->setData(C_LOAD, Qt::CheckStateRole, state);
            }

            emit pluginSettingsChanged(spec);
        }

    } else {
        PluginCollection *collection = item->data(0, Qt::UserRole).value<PluginCollection *>();
        for (int i = 0; i < collection->plugins().length(); ++i) {
            PluginSpec *spec = collection->plugins().at(i);
            QTreeWidgetItem *child = m_specToItem.value(spec);

            if (!m_whitelist.contains(spec->name())) {
                spec->setEnabled(loadOnStartup);
                Qt::CheckState state = (loadOnStartup ? Qt::Checked : Qt::Unchecked);
                child->setData(C_LOAD, Qt::CheckStateRole, state);
            } else {
                child->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
                child->setFlags(Qt::ItemIsSelectable);
            }
        }
        updatePluginDependencies();
        emit pluginSettingsChanged(collection->plugins().first());
    }

    m_allowCheckStateUpdate = true;
}

void PluginView::updatePluginDependencies()
{
    foreach (PluginSpec *spec, PluginManager::instance()->loadQueue()) {
        bool disableIndirectly = false;
        if (m_whitelist.contains(spec->name()))
            continue;

        foreach(const PluginSpec *depSpec, spec->dependencySpecs()) {
            if (!depSpec->isEnabled() || depSpec->isDisabledIndirectly()) {
                disableIndirectly = true;
                break;
            }
        }
        QTreeWidgetItem *childItem = m_specToItem.value(spec);
        childItem->setDisabled(disableIndirectly);

        if (disableIndirectly == spec->isDisabledIndirectly())
            continue;
        spec->setDisabledIndirectly(disableIndirectly);

        if (childItem->parent() && !childItem->parent()->isExpanded())
            childItem->parent()->setExpanded(true);
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Linguist of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*  TRANSLATOR PhraseBookBox

  Go to Phrase > Edit Phrase Book...  The dialog that pops up is a
  PhraseBookBox.
*/

#include "phrasebookbox.h"
#include "translationsettingsdialog.h"

#include <QtEvents>
#include <QLineEdit>
#include <QMessageBox>
#include <QHeaderView>
#include <QSortFilterProxyModel>

QT_BEGIN_NAMESPACE

PhraseBookBox::PhraseBookBox(PhraseBook *phraseBook, QWidget *parent)
    : QDialog(parent),
      m_phraseBook(phraseBook),
      m_translationSettingsDialog(0)
{

// This definition needs to be within class context for lupdate to find it
#define NewPhrase tr("(New Entry)")

    setupUi(this);
    setWindowTitle(tr("%1[*] - Qt Linguist").arg(m_phraseBook->friendlyPhraseBookName()));
    setWindowModified(m_phraseBook->isModified());

    phrMdl = new PhraseModel(this);

    m_sortedPhraseModel = new QSortFilterProxyModel(this);
    m_sortedPhraseModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    m_sortedPhraseModel->setSortLocaleAware(true);
    m_sortedPhraseModel->setDynamicSortFilter(true);
    m_sortedPhraseModel->setSourceModel(phrMdl);

    phraseList->setModel(m_sortedPhraseModel);
    phraseList->header()->setDefaultSectionSize(150);
    phraseList->header()->setResizeMode(QHeaderView::Interactive);

    connect(sourceLed, SIGNAL(textChanged(QString)),
            this, SLOT(sourceChanged(QString)));
    connect(targetLed, SIGNAL(textChanged(QString)),
            this, SLOT(targetChanged(QString)));
    connect(definitionLed, SIGNAL(textChanged(QString)),
            this, SLOT(definitionChanged(QString)));
    connect(phraseList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(selectionChanged()));
    connect(newBut, SIGNAL(clicked()), this, SLOT(newPhrase()));
    connect(removeBut, SIGNAL(clicked()), this, SLOT(removePhrase()));
    connect(settingsBut, SIGNAL(clicked()), this, SLOT(settings()));
    connect(saveBut, SIGNAL(clicked()), this, SLOT(save()));
    connect(m_phraseBook, SIGNAL(modifiedChanged(bool)), this, SLOT(setWindowModified(bool)));

    sourceLed->installEventFilter(this);
    targetLed->installEventFilter(this);
    definitionLed->installEventFilter(this);

    foreach (Phrase *p, phraseBook->phrases())
        phrMdl->addPhrase(p);

    phraseList->sortByColumn(0, Qt::AscendingOrder);

    enableDisable();
}

bool PhraseBookBox::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress &&
            (obj == sourceLed || obj == targetLed || obj == definitionLed))
    {
        const QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        const int key = keyEvent->key();

        switch (key) {
        case Qt::Key_Down:
        case Qt::Key_Up:
        case Qt::Key_PageDown:
        case Qt::Key_PageUp:
            return QApplication::sendEvent(phraseList, event);
        }
    }
    return QDialog::eventFilter(obj, event);
}

void PhraseBookBox::newPhrase()
{
    Phrase *p = new Phrase();
    p->setSource(NewPhrase);
    m_phraseBook->append(p);
    selectItem(phrMdl->addPhrase(p));
}

void PhraseBookBox::removePhrase()
{
    QModelIndex index = currentPhraseIndex();
    Phrase *phrase = phrMdl->phrase(index);
    m_phraseBook->remove(phrase);
    phrMdl->removePhrase(index);
    delete phrase;
}

void PhraseBookBox::settings()
{
    if (!m_translationSettingsDialog)
        m_translationSettingsDialog = new TranslationSettingsDialog(this);
    m_translationSettingsDialog->setPhraseBook(m_phraseBook);
    m_translationSettingsDialog->exec();
}

void PhraseBookBox::save()
{
    const QString &fileName = m_phraseBook->fileName();
    if (!m_phraseBook->save(fileName))
        QMessageBox::warning(this,
                             tr("Qt Linguist"),
                             tr("Cannot save phrase book '%1'.").arg(fileName));
}

void PhraseBookBox::sourceChanged(const QString& source)
{
    QModelIndex index = currentPhraseIndex();
    if (index.isValid())
        phrMdl->setData(phrMdl->index(index.row(), 0), source);
}

void PhraseBookBox::targetChanged(const QString& target)
{
    QModelIndex index = currentPhraseIndex();
    if (index.isValid())
        phrMdl->setData(phrMdl->index(index.row(), 1), target);
}

void PhraseBookBox::definitionChanged(const QString& definition)
{
    QModelIndex index = currentPhraseIndex();
    if (index.isValid())
        phrMdl->setData(phrMdl->index(index.row(), 2), definition);
}

void PhraseBookBox::selectionChanged()
{
    enableDisable();
}

void PhraseBookBox::selectItem(const QModelIndex &index)
{
    const QModelIndex &sortedIndex = m_sortedPhraseModel->mapFromSource(index);
    phraseList->scrollTo(sortedIndex);
    phraseList->setCurrentIndex(sortedIndex);
}

void PhraseBookBox::enableDisable()
{
    QModelIndex index = currentPhraseIndex();

    sourceLed->blockSignals(true);
    targetLed->blockSignals(true);
    definitionLed->blockSignals(true);

    bool indexValid = index.isValid();

    if (indexValid) {
        Phrase *p = phrMdl->phrase(index);
        sourceLed->setText(p->source().simplified());
        targetLed->setText(p->target().simplified());
        definitionLed->setText(p->definition());
    }
    else {
        sourceLed->setText(QString());
        targetLed->setText(QString());
        definitionLed->setText(QString());
    }

    sourceLed->setEnabled(indexValid);
    targetLed->setEnabled(indexValid);
    definitionLed->setEnabled(indexValid);
    removeBut->setEnabled(indexValid);

    sourceLed->blockSignals(false);
    targetLed->blockSignals(false);
    definitionLed->blockSignals(false);

    QWidget *f = QApplication::focusWidget();
    if (f != sourceLed && f != targetLed && f != definitionLed) {
        QLineEdit *led = (sourceLed->text() == NewPhrase ? sourceLed : targetLed);
        led->setFocus();
        led->selectAll();
    } else {
        static_cast<QLineEdit*>(f)->selectAll();
    }
}

QModelIndex PhraseBookBox::currentPhraseIndex() const
{
    return m_sortedPhraseModel->mapToSource(phraseList->currentIndex());
}

QT_END_NAMESPACE
<commit_msg>QHeaderView::setResizeMode is deprecated.<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Linguist of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*  TRANSLATOR PhraseBookBox

  Go to Phrase > Edit Phrase Book...  The dialog that pops up is a
  PhraseBookBox.
*/

#include "phrasebookbox.h"
#include "translationsettingsdialog.h"

#include <QtEvents>
#include <QLineEdit>
#include <QMessageBox>
#include <QHeaderView>
#include <QSortFilterProxyModel>

QT_BEGIN_NAMESPACE

PhraseBookBox::PhraseBookBox(PhraseBook *phraseBook, QWidget *parent)
    : QDialog(parent),
      m_phraseBook(phraseBook),
      m_translationSettingsDialog(0)
{

// This definition needs to be within class context for lupdate to find it
#define NewPhrase tr("(New Entry)")

    setupUi(this);
    setWindowTitle(tr("%1[*] - Qt Linguist").arg(m_phraseBook->friendlyPhraseBookName()));
    setWindowModified(m_phraseBook->isModified());

    phrMdl = new PhraseModel(this);

    m_sortedPhraseModel = new QSortFilterProxyModel(this);
    m_sortedPhraseModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    m_sortedPhraseModel->setSortLocaleAware(true);
    m_sortedPhraseModel->setDynamicSortFilter(true);
    m_sortedPhraseModel->setSourceModel(phrMdl);

    phraseList->setModel(m_sortedPhraseModel);
    phraseList->header()->setDefaultSectionSize(150);
    phraseList->header()->setSectionResizeMode(QHeaderView::Interactive);

    connect(sourceLed, SIGNAL(textChanged(QString)),
            this, SLOT(sourceChanged(QString)));
    connect(targetLed, SIGNAL(textChanged(QString)),
            this, SLOT(targetChanged(QString)));
    connect(definitionLed, SIGNAL(textChanged(QString)),
            this, SLOT(definitionChanged(QString)));
    connect(phraseList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(selectionChanged()));
    connect(newBut, SIGNAL(clicked()), this, SLOT(newPhrase()));
    connect(removeBut, SIGNAL(clicked()), this, SLOT(removePhrase()));
    connect(settingsBut, SIGNAL(clicked()), this, SLOT(settings()));
    connect(saveBut, SIGNAL(clicked()), this, SLOT(save()));
    connect(m_phraseBook, SIGNAL(modifiedChanged(bool)), this, SLOT(setWindowModified(bool)));

    sourceLed->installEventFilter(this);
    targetLed->installEventFilter(this);
    definitionLed->installEventFilter(this);

    foreach (Phrase *p, phraseBook->phrases())
        phrMdl->addPhrase(p);

    phraseList->sortByColumn(0, Qt::AscendingOrder);

    enableDisable();
}

bool PhraseBookBox::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress &&
            (obj == sourceLed || obj == targetLed || obj == definitionLed))
    {
        const QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        const int key = keyEvent->key();

        switch (key) {
        case Qt::Key_Down:
        case Qt::Key_Up:
        case Qt::Key_PageDown:
        case Qt::Key_PageUp:
            return QApplication::sendEvent(phraseList, event);
        }
    }
    return QDialog::eventFilter(obj, event);
}

void PhraseBookBox::newPhrase()
{
    Phrase *p = new Phrase();
    p->setSource(NewPhrase);
    m_phraseBook->append(p);
    selectItem(phrMdl->addPhrase(p));
}

void PhraseBookBox::removePhrase()
{
    QModelIndex index = currentPhraseIndex();
    Phrase *phrase = phrMdl->phrase(index);
    m_phraseBook->remove(phrase);
    phrMdl->removePhrase(index);
    delete phrase;
}

void PhraseBookBox::settings()
{
    if (!m_translationSettingsDialog)
        m_translationSettingsDialog = new TranslationSettingsDialog(this);
    m_translationSettingsDialog->setPhraseBook(m_phraseBook);
    m_translationSettingsDialog->exec();
}

void PhraseBookBox::save()
{
    const QString &fileName = m_phraseBook->fileName();
    if (!m_phraseBook->save(fileName))
        QMessageBox::warning(this,
                             tr("Qt Linguist"),
                             tr("Cannot save phrase book '%1'.").arg(fileName));
}

void PhraseBookBox::sourceChanged(const QString& source)
{
    QModelIndex index = currentPhraseIndex();
    if (index.isValid())
        phrMdl->setData(phrMdl->index(index.row(), 0), source);
}

void PhraseBookBox::targetChanged(const QString& target)
{
    QModelIndex index = currentPhraseIndex();
    if (index.isValid())
        phrMdl->setData(phrMdl->index(index.row(), 1), target);
}

void PhraseBookBox::definitionChanged(const QString& definition)
{
    QModelIndex index = currentPhraseIndex();
    if (index.isValid())
        phrMdl->setData(phrMdl->index(index.row(), 2), definition);
}

void PhraseBookBox::selectionChanged()
{
    enableDisable();
}

void PhraseBookBox::selectItem(const QModelIndex &index)
{
    const QModelIndex &sortedIndex = m_sortedPhraseModel->mapFromSource(index);
    phraseList->scrollTo(sortedIndex);
    phraseList->setCurrentIndex(sortedIndex);
}

void PhraseBookBox::enableDisable()
{
    QModelIndex index = currentPhraseIndex();

    sourceLed->blockSignals(true);
    targetLed->blockSignals(true);
    definitionLed->blockSignals(true);

    bool indexValid = index.isValid();

    if (indexValid) {
        Phrase *p = phrMdl->phrase(index);
        sourceLed->setText(p->source().simplified());
        targetLed->setText(p->target().simplified());
        definitionLed->setText(p->definition());
    }
    else {
        sourceLed->setText(QString());
        targetLed->setText(QString());
        definitionLed->setText(QString());
    }

    sourceLed->setEnabled(indexValid);
    targetLed->setEnabled(indexValid);
    definitionLed->setEnabled(indexValid);
    removeBut->setEnabled(indexValid);

    sourceLed->blockSignals(false);
    targetLed->blockSignals(false);
    definitionLed->blockSignals(false);

    QWidget *f = QApplication::focusWidget();
    if (f != sourceLed && f != targetLed && f != definitionLed) {
        QLineEdit *led = (sourceLed->text() == NewPhrase ? sourceLed : targetLed);
        led->setFocus();
        led->selectAll();
    } else {
        static_cast<QLineEdit*>(f)->selectAll();
    }
}

QModelIndex PhraseBookBox::currentPhraseIndex() const
{
    return m_sortedPhraseModel->mapToSource(phraseList->currentIndex());
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s

// XFAIL: win32

int &src();
int *sink();
extern "C" __complex float complex_src();
extern "C" __complex float *complex_sink();

// CHECK-LABEL: define
void f1() {
#line 100
  * // The store for the assignment should be attributed to the start of the
      // assignment expression here, regardless of the location of subexpressions.
      sink() = src();
  // CHECK: store {{.*}}, !dbg [[DBG_F1:!.*]]
}

struct foo {
  int i;
  int &j;
  __complex float k;
  foo();
};

// CHECK-LABEL: define
foo::foo()
    :
#line 200
      i // CHECK: store i32 {{.*}} !dbg [[DBG_FOO_VALUE:!.*]]
      (src()),
      j // CHECK: store i32* {{.*}} !dbg [[DBG_FOO_REF:!.*]]
      (src()),
      k // CHECK: store float {{.*}} !dbg [[DBG_FOO_COMPLEX:!.*]]
      (complex_src()) {
}

// CHECK-LABEL: define {{.*}}f2{{.*}}
void f2() {
#line 300
  * // CHECK: store float {{.*}} !dbg [[DBG_F2:!.*]]
      complex_sink() = complex_src();
}

// CHECK-LABEL: define
void f3() {
#line 400
  * // CHECK: store float {{.*}} !dbg [[DBG_F3:!.*]]
      complex_sink() += complex_src();
}

// CHECK-LABEL: define
void f4() {
#line 500
  auto x // CHECK: store {{.*}} !dbg [[DBG_F4:!.*]]
      = src();
}

// CHECK-LABEL: define
void f5() {
#line 600
  auto x // CHECK: store float {{.*}} !dbg [[DBG_F5:!.*]]
      = complex_src();
}

struct agg { int i; };
agg agg_src();

// CHECK-LABEL: define
void f6() {
  agg x;
#line 700
  x // CHECK: call void @llvm.memcpy{{.*}} !dbg [[DBG_F6:!.*]]
      = agg_src();
}

// CHECK-LABEL: define
void f7() {
  int *src1();
  int src2();
#line 800
  int x = ( // CHECK: load {{.*}} !dbg [[DBG_F7:!.*]]
      src1())[src2()];
}

// CHECK-LABEL: define
void f8() {
  int src1[1];
  int src2();
#line 900
  int x = ( // CHECK: load {{.*}} !dbg [[DBG_F8:!.*]]
      src1)[src2()];
}

// CHECK-LABEL: define
void f9(int i) {
  int src1[1][i];
  int src2();
#line 1000
  auto x = ( // CHECK: getelementptr {{.*}} !dbg [[DBG_F9:!.*]]
      src1)[src2()];
}

inline void *operator new(decltype(sizeof(1)), void *p) noexcept { return p; }

// CHECK-LABEL: define
void f10() {
  void *void_src();
  ( // CHECK: icmp {{.*}} !dbg [[DBG_F10_ICMP:.*]]
    // CHECK: store {{.*}} !dbg [[DBG_F10_STORE:!.*]]
#line 1100
      new (void_src()) int(src()));
}

// noexcept just to simplify the codegen a bit
void fn() noexcept(true);

struct bar {
  bar();
  // noexcept(false) to convolute the global dtor
  ~bar() noexcept(false);
};
// global ctor cleanup
// CHECK-LABEL: define
// CHECK: invoke{{ }}
// CHECK: invoke{{ }}
// CHECK:   to label {{.*}}, !dbg [[DBG_GLBL_CTOR_B:!.*]]

// terminate caller
// CHECK-LABEL: define

// global dtor cleanup
// CHECK-LABEL: define
// CHECK: invoke{{ }}
// CHECK: invoke{{ }}
// CHECK:   to label {{.*}}, !dbg [[DBG_GLBL_DTOR_B:!.*]]
#line 1200
bar b[1] = { //
    (fn(),   //
     bar())};

// CHECK-LABEL: define
__complex double f11() {
  __complex double f;
// CHECK: store {{.*}} !dbg [[DBG_F11:!.*]]
#line 1300
  return f;
}

// CHECK-LABEL: define
void f12() {
  int f12_1();
  void f12_2(int = f12_1());
// CHECK: call {{(signext )?}}i32 {{.*}} !dbg [[DBG_F12:!.*]]
#line 1400
  f12_2();
}

// CHECK-LABEL: define
void f13() {
// CHECK: call {{.*}} !dbg [[DBG_F13:!.*]]
#define F13_IMPL 1, src()
  1,
#line 1500
  F13_IMPL;
}

struct f14 {
  f14(int);
};

// CHECK-LABEL: define
// CHECK-LABEL: define
// CHECK-LABEL: define
struct {
// CHECK: call {{.*}}, !dbg [[DBG_F14_CTOR_CALL:![0-9]*]]
#line 1600
  f14 v
      =
      1;
} f14_inst;

// CHECK-LABEL: define

// CHECK: [[DBG_F1]] = !MDLocation(line: 100,
// CHECK: [[DBG_FOO_VALUE]] = !MDLocation(line: 200,
// CHECK: [[DBG_FOO_REF]] = !MDLocation(line: 202,
// CHECK: [[DBG_FOO_COMPLEX]] = !MDLocation(line: 204,
// CHECK: [[DBG_F2]] = !MDLocation(line: 300,
// CHECK: [[DBG_F3]] = !MDLocation(line: 400,
// CHECK: [[DBG_F4]] = !MDLocation(line: 500,
// CHECK: [[DBG_F5]] = !MDLocation(line: 600,
// CHECK: [[DBG_F6]] = !MDLocation(line: 700,
// CHECK: [[DBG_F7]] = !MDLocation(line: 800,
// CHECK: [[DBG_F8]] = !MDLocation(line: 900,
// CHECK: [[DBG_F9]] = !MDLocation(line: 1000,
// CHECK: [[DBG_F10_ICMP]] = !MDLocation(line: 1100,
// CHECK: [[DBG_F10_STORE]] = !MDLocation(line: 1100,
// CHECK: [[DBG_GLBL_CTOR_B]] = !MDLocation(line: 1200,
// CHECK: [[DBG_GLBL_DTOR_B]] = !MDLocation(line: 1200,
// CHECK: [[DBG_F11]] = !MDLocation(line: 1300,
// CHECK: [[DBG_F12]] = !MDLocation(line: 1400,
// CHECK: [[DBG_F13]] = !MDLocation(line: 1500,
// CHECK: [[DBG_F14_CTOR_CALL]] = !MDLocation(line: 1600,
<commit_msg>Refactor test so it's not lazily emitted on a global, simplifying ordering when more test cases are added<commit_after>// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s

// XFAIL: win32

int &src();
int *sink();
extern "C" __complex float complex_src();
extern "C" __complex float *complex_sink();

// CHECK-LABEL: define
void f1() {
#line 100
  * // The store for the assignment should be attributed to the start of the
      // assignment expression here, regardless of the location of subexpressions.
      sink() = src();
  // CHECK: store {{.*}}, !dbg [[DBG_F1:!.*]]
}

struct foo {
  int i;
  int &j;
  __complex float k;
  foo();
};

// CHECK-LABEL: define
foo::foo()
    :
#line 200
      i // CHECK: store i32 {{.*}} !dbg [[DBG_FOO_VALUE:!.*]]
      (src()),
      j // CHECK: store i32* {{.*}} !dbg [[DBG_FOO_REF:!.*]]
      (src()),
      k // CHECK: store float {{.*}} !dbg [[DBG_FOO_COMPLEX:!.*]]
      (complex_src()) {
}

// CHECK-LABEL: define {{.*}}f2{{.*}}
void f2() {
#line 300
  * // CHECK: store float {{.*}} !dbg [[DBG_F2:!.*]]
      complex_sink() = complex_src();
}

// CHECK-LABEL: define
void f3() {
#line 400
  * // CHECK: store float {{.*}} !dbg [[DBG_F3:!.*]]
      complex_sink() += complex_src();
}

// CHECK-LABEL: define
void f4() {
#line 500
  auto x // CHECK: store {{.*}} !dbg [[DBG_F4:!.*]]
      = src();
}

// CHECK-LABEL: define
void f5() {
#line 600
  auto x // CHECK: store float {{.*}} !dbg [[DBG_F5:!.*]]
      = complex_src();
}

struct agg { int i; };
agg agg_src();

// CHECK-LABEL: define
void f6() {
  agg x;
#line 700
  x // CHECK: call void @llvm.memcpy{{.*}} !dbg [[DBG_F6:!.*]]
      = agg_src();
}

// CHECK-LABEL: define
void f7() {
  int *src1();
  int src2();
#line 800
  int x = ( // CHECK: load {{.*}} !dbg [[DBG_F7:!.*]]
      src1())[src2()];
}

// CHECK-LABEL: define
void f8() {
  int src1[1];
  int src2();
#line 900
  int x = ( // CHECK: load {{.*}} !dbg [[DBG_F8:!.*]]
      src1)[src2()];
}

// CHECK-LABEL: define
void f9(int i) {
  int src1[1][i];
  int src2();
#line 1000
  auto x = ( // CHECK: getelementptr {{.*}} !dbg [[DBG_F9:!.*]]
      src1)[src2()];
}

inline void *operator new(decltype(sizeof(1)), void *p) noexcept { return p; }

// CHECK-LABEL: define
void f10() {
  void *void_src();
  ( // CHECK: icmp {{.*}} !dbg [[DBG_F10_ICMP:.*]]
    // CHECK: store {{.*}} !dbg [[DBG_F10_STORE:!.*]]
#line 1100
      new (void_src()) int(src()));
}

// noexcept just to simplify the codegen a bit
void fn() noexcept(true);

struct bar {
  bar();
  // noexcept(false) to convolute the global dtor
  ~bar() noexcept(false);
};
// global ctor cleanup
// CHECK-LABEL: define
// CHECK: invoke{{ }}
// CHECK: invoke{{ }}
// CHECK:   to label {{.*}}, !dbg [[DBG_GLBL_CTOR_B:!.*]]

// terminate caller
// CHECK-LABEL: define

// global dtor cleanup
// CHECK-LABEL: define
// CHECK: invoke{{ }}
// CHECK: invoke{{ }}
// CHECK:   to label {{.*}}, !dbg [[DBG_GLBL_DTOR_B:!.*]]
#line 1200
bar b[1] = { //
    (fn(),   //
     bar())};

// CHECK-LABEL: define
__complex double f11() {
  __complex double f;
// CHECK: store {{.*}} !dbg [[DBG_F11:!.*]]
#line 1300
  return f;
}

// CHECK-LABEL: define
void f12() {
  int f12_1();
  void f12_2(int = f12_1());
// CHECK: call {{(signext )?}}i32 {{.*}} !dbg [[DBG_F12:!.*]]
#line 1400
  f12_2();
}

// CHECK-LABEL: define
void f13() {
// CHECK: call {{.*}} !dbg [[DBG_F13:!.*]]
#define F13_IMPL 1, src()
  1,
#line 1500
  F13_IMPL;
}

struct f14 {
  f14(int);
};

// CHECK-LABEL: define
struct f14_use {
// CHECK: call {{.*}}, !dbg [[DBG_F14_CTOR_CALL:![0-9]*]]
#line 1600
  f14 v
      =
      1;
  f14_use();
};

f14_use::f14_use() = default;

// CHECK-LABEL: define

// CHECK: [[DBG_F1]] = !MDLocation(line: 100,
// CHECK: [[DBG_FOO_VALUE]] = !MDLocation(line: 200,
// CHECK: [[DBG_FOO_REF]] = !MDLocation(line: 202,
// CHECK: [[DBG_FOO_COMPLEX]] = !MDLocation(line: 204,
// CHECK: [[DBG_F2]] = !MDLocation(line: 300,
// CHECK: [[DBG_F3]] = !MDLocation(line: 400,
// CHECK: [[DBG_F4]] = !MDLocation(line: 500,
// CHECK: [[DBG_F5]] = !MDLocation(line: 600,
// CHECK: [[DBG_F6]] = !MDLocation(line: 700,
// CHECK: [[DBG_F7]] = !MDLocation(line: 800,
// CHECK: [[DBG_F8]] = !MDLocation(line: 900,
// CHECK: [[DBG_F9]] = !MDLocation(line: 1000,
// CHECK: [[DBG_F10_ICMP]] = !MDLocation(line: 1100,
// CHECK: [[DBG_F10_STORE]] = !MDLocation(line: 1100,
// CHECK: [[DBG_GLBL_CTOR_B]] = !MDLocation(line: 1200,
// CHECK: [[DBG_GLBL_DTOR_B]] = !MDLocation(line: 1200,
// CHECK: [[DBG_F11]] = !MDLocation(line: 1300,
// CHECK: [[DBG_F12]] = !MDLocation(line: 1400,
// CHECK: [[DBG_F13]] = !MDLocation(line: 1500,
// CHECK: [[DBG_F14_CTOR_CALL]] = !MDLocation(line: 1600,
<|endoftext|>


<commit_before>namespace CountAndSay {
  class Solution {
  public:
      string countAndSay(int n) {
          if (n == 0) {
              return "";
          }

          if (n == 1) {
              return "1";
          }

          string s = countAndSay(n - 1);

          char curChar = s[0];
          int count = 1;
          int i = 1;
          string res = "";
          while (i < s.size()) {
              if (s[i] == curChar) {
                  count++;
              } else {
                  res += to_string(count);
                  res += curChar;

                  // reset
                  curChar = s[i];
                  count = 1;
              }
              i++;
          }
          res += to_string(count);
          res += curChar;
          return res;
      }
  };
}
<commit_msg>Update CountAndSay.cc<commit_after>/**
 * https://oj.leetcode.com/problems/count-and-say/
 */
namespace CountAndSay {
  class Solution {
  public:
      string countAndSay(int n) {
          if (n == 0) {
              return "";
          }

          if (n == 1) {
              return "1";
          }

          string s = countAndSay(n - 1);

          char curChar = s[0];
          int count = 1;
          int i = 1;
          string res = "";
          while (i < s.size()) {
              if (s[i] == curChar) {
                  count++;
              } else {
                  res += to_string(count);
                  res += curChar;

                  // reset
                  curChar = s[i];
                  count = 1;
              }
              i++;
          }
          res += to_string(count);
          res += curChar;
          return res;
      }
  };
}
<|endoftext|>


<commit_before>
const char* toConstChar(std:string strg)
{
return strg.c_str()
}
<commit_msg>Update stringopps.cpp<commit_after>/// Useful conversion in visual studio
const char* toConstChar(std:string strg)
{
return strg.c_str()
}
<|endoftext|>


<commit_before>/*
 * ThrottleDetector.cpp
 *
 * This class can detect up to two potentiometers and determine their min/max values,
 * whether they read low to high or high to low, and if the second potentiometer is
 * the inverse of the first.
 *
 Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin

 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
 without limitation the rights to use, copy, modify, merge, publish,
 distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to
 the following conditions:

 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 */

#include "ThrottleDetector.h"

/*
 * The constructor takes a pointer to a throttle
 */
ThrottleDetector::ThrottleDetector(Throttle *throttle) {
	this->throttle = throttle;
	config = (PotThrottleConfiguration *) throttle->getConfiguration();
	state = DoNothing;
	maxThrottleReadingDeviationPercent = 50; // 5% in 0-1000 scale
	Logger::debug("ThrottleDetector constructed with throttle %d", throttle);
	resetValues();
}

/*
 * Nothing to do in the destructor right now but good to have as a general rule
 */
ThrottleDetector::~ThrottleDetector() {
}

/*
 * Operations run asynchronously in small increments each time this
 * method is called so we track the state and resume the operation each call
 */
void ThrottleDetector::handleTick() {
	switch (state) {
	case DetectMinWait:
		detectMinWait();
		break;
	case DetectMinCalibrate:
		detectMinCalibrate();
		break;
	case DetectMaxWait:
		detectMaxWait();
		break;
	case DetectMaxCalibrate:
		detectMaxCalibrate();
		break;

	case DoNothing:
		break;
	}
}

/*
 * Run the complete throttle detection.
 * Step 1. Kick it off
 */
void ThrottleDetector::detect() {
	SerialUSB.println("Throttle detection starting. Do NOT press the pedal until instructed.");

	resetValues();

	// reset stats
	sampleCount = 0;
	linearCount = 0;
	inverseCount = 0;
	for (int i=0; i<200; i++) {
		throttle1Values[i]=0;
		throttle2Values[i]=0;
	}

	// we wait for 2 seconds so kick this off
	startTime = millis();
	state = DetectMinWait;

	TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_POT_THROTTLE);
}

/*
 * Step 2. Wait for 2 seconds then start taking MIN readings
 */
void ThrottleDetector::detectMinWait() {
	if ((millis() - startTime) >= 2000) {
		// drop initial readings as they seem to be invalid
		readThrottleValues();
		resetValues();

		// take MIN readings for 2 seconds
		startTime = millis();
		readThrottleValues();
		state = DetectMinCalibrate;
	}
}

/*
 * Step 3. Take MIN readings for 2 seconds then start waiting again
 */
void ThrottleDetector::detectMinCalibrate() {
	if ((millis() - startTime) < 2000 || sampleCount < maxSamples/3 ) {
		readThrottleValues();
	} else {
		displayCalibratedValues(true);

		// save rest minimums
		throttle1MinRest = throttle1Min;  // minimum sensor value at rest
		throttle2MinRest = throttle2Min;  // minimum sensor value at rest
		throttle2MaxRest = throttle2Max;  // maximum sensor value at rest

		SerialUSB.println("");
		SerialUSB.println("Smoothly depress the pedal to full acceleration");
		SerialUSB.println("and hold the pedal until complete");

		// wait for 5 seconds so they can react and then still get some readings
		startTime = millis();
		state = DetectMaxWait;
	}
}

/*
 * Step 4. Wait for 5 seconds then start taking MAX readings
 */
void ThrottleDetector::detectMaxWait() {
	if ((millis() - startTime) >= 5000 || sampleCount >= maxSamples*2/3) {
		// drop initial readings as they seem to be invalid
		readThrottleValues();
		resetValues();

		// take MAX readings for 2 seconds
		startTime = millis();
		readThrottleValues();
		state = DetectMaxCalibrate;
	} else {
		readThrottleValues();
	}
}

/*
 * Step 5. Take MAX readings for 3 seconds then show results
 */
void ThrottleDetector::detectMaxCalibrate() {
	if ((millis() - startTime) < 2000 && sampleCount < maxSamples) {
		readThrottleValues();
	} else {
		displayCalibratedValues(false);

		// Determine throttle type based off min/max
		if (throttle1MinRest > throttle1Min) { // high to low pot
			throttle1HighLow = true;
		}

		if (throttle2MinRest > throttle2Min) { // high to low pot
			throttle2HighLow = true;
		}

		// restore the true min
		throttle1Min = throttle1MinRest;

		if ((throttle1HighLow && !throttle2HighLow)
				|| (throttle2HighLow && !throttle1HighLow)) {
			throttle2Inverse = true;
		}

		// Detect grounded pin (always zero) or floating values which indicate no potentiometer provided
		// If the values deviate by more than 15% we assume floating
		int restDiff = abs(throttle2MaxRest-throttle2MinRest) * 100 / throttle2MaxRest;
		int maxDiff = abs(throttle2Max-throttle2Min) * 100 / throttle2Max;
		if ((throttle2MinRest == 0 && throttle2MaxRest == 0
				&& throttle2Min == INT16_MAX && throttle2Max == 0)
				|| (restDiff > maxThrottleReadingDeviationPercent
					&& maxDiff > maxThrottleReadingDeviationPercent)) {
			potentiometerCount = 1;
		} else {
			potentiometerCount = 2;
		}

		// restore the true min
		throttle2Min = throttle2MinRest;

		// Determine throttle subtype by examining the data sampled
		for (int i=0; i<sampleCount; i++) {
			// normalize the values to a 0-1000 scale using the found min/max
			uint16_t value1 = normalize(throttle1Values[i], throttle1Min, throttle1Max, 0, 1000);
			uint16_t value2 = normalize(throttle2Values[i],
									throttle2Inverse ? throttle2Max : throttle2Min,
									throttle2Inverse ? throttle2Min : throttle2Max,
									0,1000);

			// see if they match known subtypes
			linearCount += checkLinear(value1, value2);
			inverseCount += checkInverse(value1, value2);

			//SerialUSB.println("NT1: " + String(value1) + ", NT2: " + String(value2) + ", L: " + String(linearCount) + ", I: " + String(inverseCount));
		}

		throttleSubType = 0;
		if (potentiometerCount > 1) {
			// For dual pots, we trust the detection of >75%
			if ( linearCount/sampleCount*100 > 75 ) {
				throttleSubType = 1;
			} else if ( inverseCount/sampleCount*100 > 75 ) {
				throttleSubType =  2;
			}
		} else {
			// For single pots we use the high/low
			if (throttle1HighLow) {
				throttleSubType =  2;
			} else {
				throttleSubType = 1;
			}
		}

		SerialUSB.println("");
		SerialUSB.println("=======================================");
		SerialUSB.println("Detection complete");
		SerialUSB.print("Num samples taken: ");
		SerialUSB.println(sampleCount);
		SerialUSB.print("Num potentiometers found: ");
		SerialUSB.println(potentiometerCount);
		SerialUSB.print("T1: ");
		SerialUSB.print(throttle1Min, DEC);
		SerialUSB.print(" to ");
		SerialUSB.print(throttle1Max, DEC);
		SerialUSB.println(throttle1HighLow ? " HIGH-LOW" : " LOW-HIGH");

		if (potentiometerCount > 1) {
			SerialUSB.print("T2: ");
			SerialUSB.print(throttle2Inverse ? throttle2Max : throttle2Min, DEC);
			SerialUSB.print(" to ");
			SerialUSB.print(throttle2Inverse ? throttle2Min : throttle2Max, DEC);
			SerialUSB.print(throttle2HighLow ? " HIGH-LOW" : " LOW-HIGH");
			SerialUSB.println(throttle2Inverse ? " (Inverse of T1)" : "");
			SerialUSB.print("Num linear throttle matches: ");
			SerialUSB.println(linearCount);
			SerialUSB.print("Num inverse throttle matches: ");
			SerialUSB.println(inverseCount);
		}

		SerialUSB.print("Throttle type: ");
		if (throttleSubType == 0) {
			SerialUSB.println("UNKNOWN");
		} else if (throttleSubType == 1) {
			SerialUSB.println("Linear");
		} else if (throttleSubType == 2) {
			SerialUSB.println("Inverse");
		}

		/*
		SerialUSB.println();
		SerialUSB.println("----- RAW values ----");
		for (int i=0; i<sampleCount; i++) {
			SerialUSB.println("T1: " + String(throttle1Values[i]) + ", T2: " + String(throttle2Values[i]));
		}
		*/

		SerialUSB.println("========================================");

		// update the throttle's configuration (without storing it yet)
		config->minimumLevel1 = throttle1Min;
		config->maximumLevel1 = throttle1Max;
		config->numberPotMeters = potentiometerCount;
		if (config->numberPotMeters > 1) {
			config->minimumLevel2 = throttle2Min;
			config->maximumLevel2 = throttle2Max;
		} else {
			config->minimumLevel2 = 0;
			config->maximumLevel2 = 0;
		}
		config->throttleSubType = throttleSubType;

		// Done!
		state = DoNothing;
		TickHandler::getInstance()->detach(this);

		// send updates to ichip wifi
		DeviceManager::getInstance()->sendMessage(DEVICE_WIFI, ICHIP2128, MSG_CONFIG_CHANGE, NULL);
	}
}

/*
 * Reset/initialize some values
 */
void ThrottleDetector::resetValues() {
	throttle1Min = INT16_MAX;
	throttle1Max = 0;
	throttle2Min = INT16_MAX;
	throttle2Max = 0;

	potentiometerCount = 1;
	throttle1HighLow = false;
	throttle2HighLow = false;
	throttle2Inverse = false;
}

/*
 * Reads values from the throttles.
 */
void ThrottleDetector::readThrottleValues() {
	RawSignalData *rawSignal = throttle->acquireRawSignal();
	throttle1Values[sampleCount] = rawSignal->input1;
	throttle2Values[sampleCount] = rawSignal->input2;
	sampleCount++;

	// record the minimum sensor value
	if (rawSignal->input1 < throttle1Min) {
		throttle1Min = rawSignal->input1;
	}

	// record the maximum sensor value
	if (rawSignal->input1 > throttle1Max) {
		throttle1Max = rawSignal->input1;
	}

	if (throttle2Provided()) {
		// record the minimum sensor value
		if (rawSignal->input2 < throttle2Min) {
			throttle2Min = rawSignal->input2;
		}

		// record the maximum sensor value
		if (rawSignal->input2 > throttle2Max) {
			throttle2Max = rawSignal->input2;
		}
	}
}

/*
 * Compares two throttle readings and returns 1 if they are a mirror
 * of each other (within a tolerance) otherwise returns 0
 * Assumes the values are already mapped to a 0-1000 scale
 */
int ThrottleDetector::checkLinear(uint16_t throttle1Value, uint16_t throttle2Value) {
	int match = 0;

	if ( abs(throttle1Value-throttle2Value) < maxThrottleReadingDeviationPercent) {
		match = 1;
	}
	return match;
}

/*
 * Compares two throttle readings and returns 1 if they are the inverse
 * of each other (within a tolerance) otherwise returns 0
 * Assumes the values are already mapped to a 0-1000 scale
 */
int ThrottleDetector::checkInverse(uint16_t throttle1Value, uint16_t throttle2Value) {
	int match = 0;

	if (abs(1000 - (throttle1Value+throttle2Value)) <  maxThrottleReadingDeviationPercent) {
		match = 1;
	}

	return match;
}

void ThrottleDetector::displayCalibratedValues(bool minPedal) {
	SerialUSB.println("");
	SerialUSB.print("At ");
	if (minPedal) {
		SerialUSB.print("MIN");
	} else {
		SerialUSB.print("MAX");
	}
	SerialUSB.print(" T1: ");
	SerialUSB.print(throttle1Min, DEC);
	SerialUSB.print(" to ");
	SerialUSB.print(throttle1Max, DEC);
	if (throttle2Provided()) {
		SerialUSB.print(" T2: ");
		SerialUSB.print(throttle2Min, DEC);
		SerialUSB.print(" to ");
		SerialUSB.print(throttle2Max, DEC);
	}
	SerialUSB.println("");
}

/**
 * Map and constrain the value to the given range
 */
uint16_t ThrottleDetector::normalize(uint16_t sensorValue, uint16_t sensorMin, uint16_t sensorMax, uint16_t constrainMin, uint16_t constrainMax) {
  int value = map(sensorValue, sensorMin, sensorMax, constrainMin, constrainMax);
  return constrain(value, constrainMin, constrainMax);
}
<commit_msg>small fix<commit_after>/*
 * ThrottleDetector.cpp
 *
 * This class can detect up to two potentiometers and determine their min/max values,
 * whether they read low to high or high to low, and if the second potentiometer is
 * the inverse of the first.
 *
 Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin

 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
 without limitation the rights to use, copy, modify, merge, publish,
 distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to
 the following conditions:

 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 */

#include "ThrottleDetector.h"

/*
 * The constructor takes a pointer to a throttle
 */
ThrottleDetector::ThrottleDetector(Throttle *throttle) {
	this->throttle = throttle;
	config = (PotThrottleConfiguration *) throttle->getConfiguration();
	state = DoNothing;
	maxThrottleReadingDeviationPercent = 50; // 5% in 0-1000 scale
	Logger::debug("ThrottleDetector constructed with throttle %d", throttle);
	resetValues();
}

/*
 * Nothing to do in the destructor right now but good to have as a general rule
 */
ThrottleDetector::~ThrottleDetector() {
}

/*
 * Operations run asynchronously in small increments each time this
 * method is called so we track the state and resume the operation each call
 */
void ThrottleDetector::handleTick() {
	switch (state) {
	case DetectMinWait:
		detectMinWait();
		break;
	case DetectMinCalibrate:
		detectMinCalibrate();
		break;
	case DetectMaxWait:
		detectMaxWait();
		break;
	case DetectMaxCalibrate:
		detectMaxCalibrate();
		break;

	case DoNothing:
		break;
	}
}

/*
 * Run the complete throttle detection.
 * Step 1. Kick it off
 */
void ThrottleDetector::detect() {
	SerialUSB.println("Throttle detection starting. Do NOT press the pedal until instructed.");

	resetValues();

	// reset stats
	sampleCount = 0;
	linearCount = 0;
	inverseCount = 0;
	for (int i=0; i<200; i++) {
		throttle1Values[i]=0;
		throttle2Values[i]=0;
	}

	// we wait for 2 seconds so kick this off
	startTime = millis();
	state = DetectMinWait;

	TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_POT_THROTTLE);
}

/*
 * Step 2. Wait for 2 seconds then start taking MIN readings
 */
void ThrottleDetector::detectMinWait() {
	if ((millis() - startTime) >= 2000) {
		// drop initial readings as they seem to be invalid
		readThrottleValues();
		resetValues();

		// take MIN readings for 2 seconds
		startTime = millis();
		readThrottleValues();
		state = DetectMinCalibrate;
	}
}

/*
 * Step 3. Take MIN readings for 2 seconds then start waiting again
 */
void ThrottleDetector::detectMinCalibrate() {
	if ((millis() - startTime) < 2000 || sampleCount < maxSamples/3 ) {
		readThrottleValues();
	} else {
		displayCalibratedValues(true);

		// save rest minimums
		throttle1MinRest = throttle1Min;  // minimum sensor value at rest
		throttle2MinRest = throttle2Min;  // minimum sensor value at rest
		throttle2MaxRest = throttle2Max;  // maximum sensor value at rest

		SerialUSB.println("");
		SerialUSB.println("Smoothly depress the pedal to full acceleration");
		SerialUSB.println("and hold the pedal until complete");

		// wait for 5 seconds so they can react and then still get some readings
		startTime = millis();
		state = DetectMaxWait;
	}
}

/*
 * Step 4. Wait for 5 seconds then start taking MAX readings
 */
void ThrottleDetector::detectMaxWait() {
	if ((millis() - startTime) >= 5000 || sampleCount >= maxSamples*2/3) {
		// drop initial readings as they seem to be invalid
		readThrottleValues();
		resetValues();

		// take MAX readings for 2 seconds
		startTime = millis();
		readThrottleValues();
		state = DetectMaxCalibrate;
	} else {
		readThrottleValues();
	}
}

/*
 * Step 5. Take MAX readings for 3 seconds then show results
 */
void ThrottleDetector::detectMaxCalibrate() {
	if ((millis() - startTime) < 2000 && sampleCount < maxSamples) {
		readThrottleValues();
	} else {
		displayCalibratedValues(false);

		// Determine throttle type based off min/max
		if (throttle1MinRest > throttle1Min) { // high to low pot
			throttle1HighLow = true;
		}

		if (throttle2MinRest > throttle2Min) { // high to low pot
			throttle2HighLow = true;
		}

		// restore the true min
		throttle1Min = throttle1MinRest;

		if ((throttle1HighLow && !throttle2HighLow)
				|| (throttle2HighLow && !throttle1HighLow)) {
			throttle2Inverse = true;
		}

		// Detect grounded pin (always zero) or floating values which indicate no potentiometer provided
		// If the values deviate by more than 15% we assume floating
		int restDiff = abs(throttle2MaxRest-throttle2MinRest) * 100 / throttle2MaxRest;
		int maxDiff = abs(throttle2Max-throttle2Min) * 100 / throttle2Max;
		if ((throttle2MinRest == 0 && throttle2MaxRest == 0
				&& throttle2Min == INT16_MAX && throttle2Max == 0)
				|| (restDiff > maxThrottleReadingDeviationPercent
					&& maxDiff > maxThrottleReadingDeviationPercent)) {
			potentiometerCount = 1;
		} else {
			potentiometerCount = 2;
		}

		// restore the true min
		throttle2Min = throttle2MinRest;

		// Determine throttle subtype by examining the data sampled
		for (int i=0; i<sampleCount; i++) {
			// normalize the values to a 0-1000 scale using the found min/max
			uint16_t value1 = normalize(throttle1Values[i], throttle1Min, throttle1Max, 0, 1000);
			uint16_t value2 = normalize(throttle2Values[i],
									throttle2Inverse ? throttle2Max : throttle2Min,
									throttle2Inverse ? throttle2Min : throttle2Max,
									0,1000);

			// see if they match known subtypes
			linearCount += checkLinear(value1, value2);
			inverseCount += checkInverse(value1, value2);

			//Logger::debug("NT1: %d, NT2: %d, L: %d, I: %d", value1, value2, linearCount, inverseCount);
		}

		throttleSubType = 0;
		if (potentiometerCount > 1) {
			// For dual pots, we trust the detection of >75%
			if ( linearCount/sampleCount*100 > 75 ) {
				throttleSubType = 1;
			} else if ( inverseCount/sampleCount*100 > 75 ) {
				throttleSubType =  2;
			}
		} else {
			// For single pots we use the high/low
			if (throttle1HighLow) {
				throttleSubType =  2;
			} else {
				throttleSubType = 1;
			}
		}

		SerialUSB.println("");
		SerialUSB.println("=======================================");
		SerialUSB.println("Detection complete");
		SerialUSB.print("Num samples taken: ");
		SerialUSB.println(sampleCount);
		SerialUSB.print("Num potentiometers found: ");
		SerialUSB.println(potentiometerCount);
		SerialUSB.print("T1: ");
		SerialUSB.print(throttle1Min, DEC);
		SerialUSB.print(" to ");
		SerialUSB.print(throttle1Max, DEC);
		SerialUSB.println(throttle1HighLow ? " HIGH-LOW" : " LOW-HIGH");

		if (potentiometerCount > 1) {
			SerialUSB.print("T2: ");
			SerialUSB.print(throttle2Inverse ? throttle2Max : throttle2Min, DEC);
			SerialUSB.print(" to ");
			SerialUSB.print(throttle2Inverse ? throttle2Min : throttle2Max, DEC);
			SerialUSB.print(throttle2HighLow ? " HIGH-LOW" : " LOW-HIGH");
			SerialUSB.println(throttle2Inverse ? " (Inverse of T1)" : "");
			SerialUSB.print("Num linear throttle matches: ");
			SerialUSB.println(linearCount);
			SerialUSB.print("Num inverse throttle matches: ");
			SerialUSB.println(inverseCount);
		}

		SerialUSB.print("Throttle type: ");
		if (throttleSubType == 0) {
			SerialUSB.println("UNKNOWN");
		} else if (throttleSubType == 1) {
			SerialUSB.println("Linear");
		} else if (throttleSubType == 2) {
			SerialUSB.println("Inverse");
		}

		/*
		SerialUSB.println();
		SerialUSB.println("----- RAW values ----");
		for (int i=0; i<sampleCount; i++) {
			SerialUSB.println("T1: " + String(throttle1Values[i]) + ", T2: " + String(throttle2Values[i]));
		}
		*/

		SerialUSB.println("========================================");

		// update the throttle's configuration (without storing it yet)
		config->minimumLevel1 = throttle1Min;
		config->maximumLevel1 = throttle1Max;
		config->numberPotMeters = potentiometerCount;
		if (config->numberPotMeters > 1) {
			config->minimumLevel2 = throttle2Min;
			config->maximumLevel2 = throttle2Max;
		} else {
			config->minimumLevel2 = 0;
			config->maximumLevel2 = 0;
		}
		config->throttleSubType = throttleSubType;

		// Done!
		state = DoNothing;
		TickHandler::getInstance()->detach(this);

		// send updates to ichip wifi
		DeviceManager::getInstance()->sendMessage(DEVICE_WIFI, ICHIP2128, MSG_CONFIG_CHANGE, NULL);
	}
}

/*
 * Reset/initialize some values
 */
void ThrottleDetector::resetValues() {
	throttle1Min = INT16_MAX;
	throttle1Max = 0;
	throttle2Min = INT16_MAX;
	throttle2Max = 0;

	potentiometerCount = 1;
	throttle1HighLow = false;
	throttle2HighLow = false;
	throttle2Inverse = false;
}

/*
 * Reads values from the throttles.
 */
void ThrottleDetector::readThrottleValues() {
	RawSignalData *rawSignal = throttle->acquireRawSignal();
	throttle1Values[sampleCount] = rawSignal->input1;
	throttle2Values[sampleCount] = rawSignal->input2;
	sampleCount++;

	// record the minimum sensor value
	if (rawSignal->input1 < throttle1Min) {
		throttle1Min = rawSignal->input1;
	}

	// record the maximum sensor value
	if (rawSignal->input1 > throttle1Max) {
		throttle1Max = rawSignal->input1;
	}

	if (throttle2Provided()) {
		// record the minimum sensor value
		if (rawSignal->input2 < throttle2Min) {
			throttle2Min = rawSignal->input2;
		}

		// record the maximum sensor value
		if (rawSignal->input2 > throttle2Max) {
			throttle2Max = rawSignal->input2;
		}
	}
}

/*
 * Compares two throttle readings and returns 1 if they are a mirror
 * of each other (within a tolerance) otherwise returns 0
 * Assumes the values are already mapped to a 0-1000 scale
 */
int ThrottleDetector::checkLinear(uint16_t throttle1Value, uint16_t throttle2Value) {
	int match = 0;

	if ( abs(throttle1Value-throttle2Value) < maxThrottleReadingDeviationPercent) {
		match = 1;
	}
	return match;
}

/*
 * Compares two throttle readings and returns 1 if they are the inverse
 * of each other (within a tolerance) otherwise returns 0
 * Assumes the values are already mapped to a 0-1000 scale
 */
int ThrottleDetector::checkInverse(uint16_t throttle1Value, uint16_t throttle2Value) {
	int match = 0;

	if (abs(1000 - (throttle1Value+throttle2Value)) <  maxThrottleReadingDeviationPercent) {
		match = 1;
	}

	return match;
}

void ThrottleDetector::displayCalibratedValues(bool minPedal) {
	SerialUSB.println("");
	SerialUSB.print("At ");
	if (minPedal) {
		SerialUSB.print("MIN");
	} else {
		SerialUSB.print("MAX");
	}
	SerialUSB.print(" T1: ");
	SerialUSB.print(throttle1Min, DEC);
	SerialUSB.print(" to ");
	SerialUSB.print(throttle1Max, DEC);
	if (throttle2Provided) {
		SerialUSB.print(" T2: ");
		SerialUSB.print(throttle2Min, DEC);
		SerialUSB.print(" to ");
		SerialUSB.print(throttle2Max, DEC);
	}
	SerialUSB.println("");
}

/**
 * Map and constrain the value to the given range
 */
uint16_t ThrottleDetector::normalize(uint16_t sensorValue, uint16_t sensorMin, uint16_t sensorMax, uint16_t constrainMin, uint16_t constrainMax) {
  int value = map(sensorValue, sensorMin, sensorMax, constrainMin, constrainMax);
  return constrain(value, constrainMin, constrainMax);
}
<|endoftext|>


<commit_before>/*
 * Licensed to Green Energy Corp (www.greenenergycorp.com) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership.  Green Enery
 * Corp licenses this file to you 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
 *
 * 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.
 */

#include <APL/Logger.h>

#include "APDU.h"
#include "VtoTransmitTask.h"

using namespace apl;
using namespace apl::dnp;

namespace apl {
	namespace dnp {

		void VtoTransmitTask::ConfigureRequest(APDU& arAPDU)
		{
			/*
			 * For now, VTO packets are only sent as a single fragment.  We
			 * also will require the receiver to confirm receipt, because I
			 * don't want to have to code reliable delivery into the higher
			 * level protocol.
			 */
			arAPDU.Set(FC_WRITE, true, true, true, false);

			/*
			 * Only grab from the buffer that which will fit into a single APDU
			 * message.  VTO is considered a 'low-priority' traffic flow, so we
			 * don't want to hog the bandwidth with multiple fragments.
			 */
			size_t numObjects = this->mBuffer.Select(
					PC_ALL_EVENTS,
					(arAPDU.Size() - 2) / 300
			);

			/*
			 * If there are no objects to write, skip the remainder.
			 */
			if (numObjects < 0)
				return;

			/*
			 * Loop through the selected data and add corresponding objects to
			 * the arAPDU instance.
			 */
			VtoDataEventIter itr = this->mBuffer.Begin();
			for (size_t i = 0; i < numObjects; ++i, ++itr)
			{
				/* Insert a new object into the APDU message. */
				IndexedWriteIterator obj = arAPDU.WriteIndexed(
						Group112Var0::Inst(),
						itr->mValue.GetSize(),
						itr->mIndex
				);

				/* Set the object index */
				obj.SetIndex(itr->mIndex);

				/* Write the data to the APDU message */
				Group112Var0::Inst()->Write(
						*obj,
						itr->mValue.GetSize(),
						itr->mValue.GetData()
				);
			}
		}

		TaskResult VtoTransmitTask::_OnPartialResponse(const APDU& arAPDU)
		{
			LOG_BLOCK(LEV_ERROR,
					"Non fin responses not allowed for task: "
					<< this->Name());

			return TR_CONTINUE;
		}

		TaskResult VtoTransmitTask::_OnFinalResponse(const APDU& arAPDU)
		{
			/* Remove the written data from the buffer */
			this->mBuffer.ClearWrittenEvents();

			return TR_SUCCESS;
		}

		TaskResult VtoTransmitTask::OnFailure()
		{
			/* Put the written data back onto the buffer */
			this->mBuffer.Deselect();
		}

	}
}

/* vim: set ts=4 sw=4: */
<commit_msg>Fixed OnFailure() declaration.<commit_after>/*
 * Licensed to Green Energy Corp (www.greenenergycorp.com) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership.  Green Enery
 * Corp licenses this file to you 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
 *
 * 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.
 */

#include <APL/Logger.h>

#include "APDU.h"
#include "VtoTransmitTask.h"

using namespace apl;
using namespace apl::dnp;

namespace apl {
	namespace dnp {

		void VtoTransmitTask::ConfigureRequest(APDU& arAPDU)
		{
			/*
			 * For now, VTO packets are only sent as a single fragment.  We
			 * also will require the receiver to confirm receipt, because I
			 * don't want to have to code reliable delivery into the higher
			 * level protocol.
			 */
			arAPDU.Set(FC_WRITE, true, true, true, false);

			/*
			 * Only grab from the buffer that which will fit into a single APDU
			 * message.  VTO is considered a 'low-priority' traffic flow, so we
			 * don't want to hog the bandwidth with multiple fragments.
			 */
			size_t numObjects = this->mBuffer.Select(
					PC_ALL_EVENTS,
					(arAPDU.Size() - 2) / 300
			);

			/*
			 * If there are no objects to write, skip the remainder.
			 */
			if (numObjects < 0)
				return;

			/*
			 * Loop through the selected data and add corresponding objects to
			 * the arAPDU instance.
			 */
			VtoDataEventIter itr = this->mBuffer.Begin();
			for (size_t i = 0; i < numObjects; ++i, ++itr)
			{
				/* Insert a new object into the APDU message. */
				IndexedWriteIterator obj = arAPDU.WriteIndexed(
						Group112Var0::Inst(),
						itr->mValue.GetSize(),
						itr->mIndex
				);

				/* Set the object index */
				obj.SetIndex(itr->mIndex);

				/* Write the data to the APDU message */
				Group112Var0::Inst()->Write(
						*obj,
						itr->mValue.GetSize(),
						itr->mValue.GetData()
				);
			}
		}

		TaskResult VtoTransmitTask::_OnPartialResponse(const APDU& arAPDU)
		{
			LOG_BLOCK(LEV_ERROR,
					"Non fin responses not allowed for task: "
					<< this->Name());

			return TR_CONTINUE;
		}

		TaskResult VtoTransmitTask::_OnFinalResponse(const APDU& arAPDU)
		{
			/* Remove the written data from the buffer */
			this->mBuffer.ClearWrittenEvents();

			return TR_SUCCESS;
		}

		void VtoTransmitTask::OnFailure()
		{
			/* Put the written data back onto the buffer */
			this->mBuffer.Deselect();
		}

	}
}

/* vim: set ts=4 sw=4: */
<|endoftext|>


<commit_before>/**
 * CMassAction
 *
 * Created for Copasi by Stefan Hoops
 * (C) Stefan Hoops 2001
 */

#include "copasi.h"
#include "CMassAction.h"
#include "utilities/utility.h"

#define COPASI_TRACE_CONSTRUCTION
CMassAction::CMassAction(const std::string & name,
                         const CCopasiContainer * pParent):
    CFunction(name, pParent)
{
  CONSTRUCTOR_TRACE;
  setType(CFunction::MassAction);
}

CMassAction::CMassAction(const CFunction & src,
                         const CCopasiContainer * pParent):
    CFunction(src, pParent)
{CONSTRUCTOR_TRACE;}

CMassAction::CMassAction(const TriLogic & reversible,
                         const CCopasiContainer * pParent):
    CFunction((reversible == TriTrue) ?
              "Mass action (reversible)" :
              "Mass action (irreversible)",
              pParent)
{
  CONSTRUCTOR_TRACE;
  if (reversible != TriFalse && reversible != TriTrue)
    CCopasiMessage(CCopasiMessage::ERROR, MCMassAction + 1);

  setType(CFunction::MassAction);
  setReversible(reversible);

  getParameters().add("k1",
                      CFunctionParameter::FLOAT64,
                      "PARAMETER");
  getParameters().add("substrate",
                      CFunctionParameter::VFLOAT64,
                      "SUBSTRATE");
  addUsage("SUBSTRATES", 0, CRange::Infinity);

  if (isReversible() == TriTrue)
    {
      // setName("Mass action (reversible)");
      setDescription("k1 * PRODUCT <substrate_i> "
                     "- k2 * PRODUCT <product_j>");
      getParameters().add("k2",
                          CFunctionParameter::FLOAT64,
                          "PARAMETER");
      getParameters().add("product",
                          CFunctionParameter::VFLOAT64,
                          "PRODUCT");
      addUsage("PRODUCTS", 0, CRange::Infinity);
    }
  else
    {
      // setName("Mass action (irreversible)");
      setDescription("k1 * PRODUCT <substrate_i>");
    }
}
CMassAction::~CMassAction(){DESTRUCTOR_TRACE;}

/*unsigned C_INT32 CMassAction::getParameterPosition(const std::string & name) const
{
  if (isReversible() != TriFalse && isReversible() != TriTrue)
    CCopasiMessage(CCopasiMessage::ERROR, MCMassAction + 1);

  if (name == "k1")
    return 0;
  if (name.substr(0, strlen("substrate")) == "substrate")
    return 1;
  if (name == "k2" &&
      isReversible() == TriTrue)
    return 2;
  if (name.substr(0, strlen("product")) == "product" &&
      isReversible() == TriTrue)
    return 3;

  return (unsigned C_INT32) - 1;
}*/

std::string CMassAction::getSBMLString(const std::vector< std::vector< std::string > > & callParameterNames,
                                       const std::string &r) const
  {
    std::string sf, tmpstr;
    unsigned C_INT32 i, imax;
    const std::vector<std::string> * pFactors;

    pFactors = &(callParameterNames[1]);   // first substr.
    imax = pFactors->size();   // NoSubstrates
    if (imax)
      {
        sf = callParameterNames[0][0] + r;           // k1
        for (i = 0; i < imax; i++)
          {
            FixSName((*pFactors)[i], tmpstr);
            sf += "*" + tmpstr;
          }
      }

    if (isReversible() == TriFalse)
      return sf;

    pFactors = &(callParameterNames[3]);
    imax = pFactors->size();
    if (imax)
      {
        sf += "-" + callParameterNames[2][0] + r;
        for (i = 0; i < imax; i++)
          {
            FixSName((*pFactors)[i], tmpstr);
            sf += "*" + tmpstr;
          }
      }

    return sf;
  }

C_FLOAT64 CMassAction::calcValue(const CCallParameterPointers & callParameters) const
  {
    unsigned C_INT32 i, imax;
    C_FLOAT64 **Factor;
    C_FLOAT64 Substrates = 0.0, Products = 0.0;

    imax = ((std::vector< C_FLOAT64 *> *)callParameters[1])->size();   // NoSubstrates
    if (imax)
      {
        Substrates = *(C_FLOAT64 *) callParameters[0];           // k1
        Factor =
          &*((std::vector< C_FLOAT64*>*)callParameters[1])->begin();   // first substr.

        for (i = 0; i < imax; i++)
          Substrates *= **(Factor++);
      }

    if (isReversible() == TriFalse)
      return Substrates;

    imax = ((std::vector< C_FLOAT64 *> *)callParameters[3])->size();   // NoProducts
    if (imax)
      {
        Products = *(C_FLOAT64 *) callParameters[2];             // k2
        Factor =
          &*((std::vector< C_FLOAT64*>*)callParameters[3])->begin();   // first product

        for (i = 0; i < imax; i++)
          Products *= **(Factor++);
      }

    return Substrates - Products;
  }

bool CMassAction::dependsOn(const void * parameter,
                            const CCallParameterPointers & callParameters) const
  {
    if (parameter == callParameters[0]) return true;

    std::vector< C_FLOAT64 * >::const_iterator it;
    std::vector< C_FLOAT64 * >::const_iterator end;

    it = ((std::vector< C_FLOAT64 * > *) callParameters[1])->begin();
    end = ((std::vector< C_FLOAT64 * > *) callParameters[1])->end();

    for (; it != end; it++) if (parameter == *it) return true;

    if (isReversible() == TriFalse) return false;

    if (parameter == callParameters[2]) return true;

    it = ((std::vector< C_FLOAT64 * > *) callParameters[3])->begin();
    end = ((std::vector< C_FLOAT64 * > *) callParameters[3])->end();

    for (; it != end; it++) if (parameter == *it) return true;

    return false;
  }
<commit_msg>Fixed error in UsageRange for substrate and product. The minimal number hast to be 1 and not 0.<commit_after>/**
 * CMassAction
 *
 * Created for Copasi by Stefan Hoops
 * (C) Stefan Hoops 2001
 */

#include "copasi.h"
#include "CMassAction.h"
#include "utilities/utility.h"

#define COPASI_TRACE_CONSTRUCTION
CMassAction::CMassAction(const std::string & name,
                         const CCopasiContainer * pParent):
    CFunction(name, pParent)
{
  CONSTRUCTOR_TRACE;
  setType(CFunction::MassAction);
}

CMassAction::CMassAction(const CFunction & src,
                         const CCopasiContainer * pParent):
    CFunction(src, pParent)
{CONSTRUCTOR_TRACE;}

CMassAction::CMassAction(const TriLogic & reversible,
                         const CCopasiContainer * pParent):
    CFunction((reversible == TriTrue) ?
              "Mass action (reversible)" :
              "Mass action (irreversible)",
              pParent)
{
  CONSTRUCTOR_TRACE;
  if (reversible != TriFalse && reversible != TriTrue)
    CCopasiMessage(CCopasiMessage::ERROR, MCMassAction + 1);

  setType(CFunction::MassAction);
  setReversible(reversible);

  getParameters().add("k1",
                      CFunctionParameter::FLOAT64,
                      "PARAMETER");
  getParameters().add("substrate",
                      CFunctionParameter::VFLOAT64,
                      "SUBSTRATE");
  addUsage("SUBSTRATES", 1, CRange::Infinity);

  if (isReversible() == TriTrue)
    {
      // setName("Mass action (reversible)");
      setDescription("k1 * PRODUCT <substrate_i> "
                     "- k2 * PRODUCT <product_j>");
      getParameters().add("k2",
                          CFunctionParameter::FLOAT64,
                          "PARAMETER");
      getParameters().add("product",
                          CFunctionParameter::VFLOAT64,
                          "PRODUCT");
      addUsage("PRODUCTS", 1, CRange::Infinity);
    }
  else
    {
      // setName("Mass action (irreversible)");
      setDescription("k1 * PRODUCT <substrate_i>");
    }
}
CMassAction::~CMassAction(){DESTRUCTOR_TRACE;}

/*unsigned C_INT32 CMassAction::getParameterPosition(const std::string & name) const
{
  if (isReversible() != TriFalse && isReversible() != TriTrue)
    CCopasiMessage(CCopasiMessage::ERROR, MCMassAction + 1);

  if (name == "k1")
    return 0;
  if (name.substr(0, strlen("substrate")) == "substrate")
    return 1;
  if (name == "k2" &&
      isReversible() == TriTrue)
    return 2;
  if (name.substr(0, strlen("product")) == "product" &&
      isReversible() == TriTrue)
    return 3;

  return (unsigned C_INT32) - 1;
}*/

std::string CMassAction::getSBMLString(const std::vector< std::vector< std::string > > & callParameterNames,
                                       const std::string &r) const
  {
    std::string sf, tmpstr;
    unsigned C_INT32 i, imax;
    const std::vector<std::string> * pFactors;

    pFactors = &(callParameterNames[1]);   // first substr.
    imax = pFactors->size();   // NoSubstrates
    if (imax)
      {
        sf = callParameterNames[0][0] + r;           // k1
        for (i = 0; i < imax; i++)
          {
            FixSName((*pFactors)[i], tmpstr);
            sf += "*" + tmpstr;
          }
      }

    if (isReversible() == TriFalse)
      return sf;

    pFactors = &(callParameterNames[3]);
    imax = pFactors->size();
    if (imax)
      {
        sf += "-" + callParameterNames[2][0] + r;
        for (i = 0; i < imax; i++)
          {
            FixSName((*pFactors)[i], tmpstr);
            sf += "*" + tmpstr;
          }
      }

    return sf;
  }

C_FLOAT64 CMassAction::calcValue(const CCallParameterPointers & callParameters) const
  {
    unsigned C_INT32 i, imax;
    C_FLOAT64 **Factor;
    C_FLOAT64 Substrates = 0.0, Products = 0.0;

    imax = ((std::vector< C_FLOAT64 *> *)callParameters[1])->size();   // NoSubstrates
    if (imax)
      {
        Substrates = *(C_FLOAT64 *) callParameters[0];           // k1
        Factor =
          &*((std::vector< C_FLOAT64*>*)callParameters[1])->begin();   // first substr.

        for (i = 0; i < imax; i++)
          Substrates *= **(Factor++);
      }

    if (isReversible() == TriFalse)
      return Substrates;

    imax = ((std::vector< C_FLOAT64 *> *)callParameters[3])->size();   // NoProducts
    if (imax)
      {
        Products = *(C_FLOAT64 *) callParameters[2];             // k2
        Factor =
          &*((std::vector< C_FLOAT64*>*)callParameters[3])->begin();   // first product

        for (i = 0; i < imax; i++)
          Products *= **(Factor++);
      }

    return Substrates - Products;
  }

bool CMassAction::dependsOn(const void * parameter,
                            const CCallParameterPointers & callParameters) const
  {
    if (parameter == callParameters[0]) return true;

    std::vector< C_FLOAT64 * >::const_iterator it;
    std::vector< C_FLOAT64 * >::const_iterator end;

    it = ((std::vector< C_FLOAT64 * > *) callParameters[1])->begin();
    end = ((std::vector< C_FLOAT64 * > *) callParameters[1])->end();

    for (; it != end; it++) if (parameter == *it) return true;

    if (isReversible() == TriFalse) return false;

    if (parameter == callParameters[2]) return true;

    it = ((std::vector< C_FLOAT64 * > *) callParameters[3])->begin();
    end = ((std::vector< C_FLOAT64 * > *) callParameters[3])->end();

    for (; it != end; it++) if (parameter == *it) return true;

    return false;
  }
<|endoftext|>