<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 "itemlibrarymodel.h"
#include "metainfo.h"

#include <QVariant>
#include <QMimeData>
#include <QPainter>
#include <QPen>
#include <qdebug.h>

namespace QmlDesigner {

namespace Internal {

template <class T>
ItemLibrarySortedModel<T>::ItemLibrarySortedModel(QObject *parent) :
    QDeclarativeListModel(parent)
{
}

template <class T>
ItemLibrarySortedModel<T>::~ItemLibrarySortedModel()
{
    clearElements();
}

template <class T>
void ItemLibrarySortedModel<T>::clearElements()
{
    while (m_elementOrder.count() > 0)
        removeElement(m_elementOrder.at(0).libId);
}

template <class T>
void ItemLibrarySortedModel<T>::addElement(T *element, int libId)
{
    struct order_struct orderEntry;
    orderEntry.libId = libId;
    orderEntry.visible = false;

    int pos = 0;
    while ((pos < m_elementOrder.count()) &&
           (*(m_elementModels.value(m_elementOrder.at(pos).libId)) < *element))
        ++pos;

    m_elementModels.insert(libId, element);
    m_elementOrder.insert(pos, orderEntry);

    setElementVisible(libId, true);
}

template <class T>
void ItemLibrarySortedModel<T>::removeElement(int libId)
{
    T *element = m_elementModels.value(libId);
    int pos = findElement(libId);

    setElementVisible(libId, false);

    m_elementModels.remove(libId);
    m_elementOrder.removeAt(pos);

    delete element;
}

template <class T>
bool ItemLibrarySortedModel<T>::elementVisible(int libId) const
{
    int pos = findElement(libId);
    return m_elementOrder.at(pos).visible;
}

template <class T>
bool ItemLibrarySortedModel<T>::setElementVisible(int libId, bool visible)
{
    int pos = findElement(libId);
    if (m_elementOrder.at(pos).visible == visible)
        return false;

    int visiblePos = visibleElementPosition(libId);
    if (visible)
        insert(visiblePos, *(m_elementModels.value(libId)));
    else
        remove(visiblePos);

    m_elementOrder[pos].visible = visible;
    return true;
}

template <class T>
const QMap<int, T *> &ItemLibrarySortedModel<T>::elements() const
{
    return m_elementModels;
}

template <class T>
T *ItemLibrarySortedModel<T>::elementModel(int libId)
{
    return m_elementModels.value(libId);
}

template <class T>
int ItemLibrarySortedModel<T>::findElement(int libId) const
{
    int i = 0;
    QListIterator<struct order_struct> it(m_elementOrder);

    while (it.hasNext()) {
        if (it.next().libId == libId)
            return i;
        ++i;
    }

    return -1;
}

template <class T>
int ItemLibrarySortedModel<T>::visibleElementPosition(int libId) const
{
    int i = 0;
    QListIterator<struct order_struct> it(m_elementOrder);

    while (it.hasNext()) {
        struct order_struct order = it.next();
        if (order.libId == libId)
            return i;
        if (order.visible)
            ++i;
    }

    return -1;
}

ItemLibraryItemModel::ItemLibraryItemModel(QScriptEngine *scriptEngine, int itemLibId, const QString &itemName)
    : QScriptValue(scriptEngine->newObject()),
      m_scriptEngine(scriptEngine),
      m_libId(itemLibId),
      m_name(itemName),
      m_icon(),
      m_iconSize(64, 64)
{
    QScriptValue pixmapScriptValue(m_scriptEngine->newVariant(QPixmap()));

    setProperty(QLatin1String("itemLibId"), itemLibId);
    setProperty(QLatin1String("itemName"), itemName);
    setProperty(QLatin1String("itemPixmap"), pixmapScriptValue);
}

ItemLibraryItemModel::~ItemLibraryItemModel()
{
    setProperty(QLatin1String("itemPixmap"), QVariant::Invalid);
}

int ItemLibraryItemModel::itemLibId() const
{
    return m_libId;
}

QString ItemLibraryItemModel::itemName() const
{
    return m_name;
}

void ItemLibraryItemModel::setItemIcon(const QIcon &itemIcon)
{
    m_icon = itemIcon;

    QScriptValue pixmapScriptValue(m_scriptEngine->newVariant(m_icon.pixmap(m_iconSize)));
    setProperty(QLatin1String("itemPixmap"), pixmapScriptValue);
}

void ItemLibraryItemModel::setItemIconSize(const QSize &itemIconSize)
{
    m_iconSize = itemIconSize;
//    qDebug() << "set icon size" << itemIconSize;
    setItemIcon(m_icon);
}

bool ItemLibraryItemModel::operator<(const ItemLibraryItemModel &other) const
{
    return itemName() < other.itemName();
}

ItemLibrarySectionModel::ItemLibrarySectionModel(QScriptEngine *scriptEngine, int sectionLibId, const QString &sectionName, QObject *parent)
    : QScriptValue(scriptEngine->newObject()),
      m_name(sectionName),
      m_sectionEntries(parent)
{
    QScriptValue::setProperty(QLatin1String("sectionLibId"), sectionLibId);
    QScriptValue::setProperty(QLatin1String("sectionName"), sectionName);
    QScriptValue::setProperty(QLatin1String("sectionEntries"),
        scriptEngine->newVariant(QVariant::fromValue(static_cast<QDeclarativeListModel *>(&m_sectionEntries))));
}

QString ItemLibrarySectionModel::sectionName() const
{
    return m_name;
}

void ItemLibrarySectionModel::addSectionEntry(ItemLibraryItemModel *sectionEntry)
{
    m_sectionEntries.addElement(sectionEntry, sectionEntry->itemLibId());
}

void ItemLibrarySectionModel::removeSectionEntry(int itemLibId)
{
    m_sectionEntries.removeElement(itemLibId);
}

int ItemLibrarySectionModel::visibleItemIndex(int itemLibId)
{
    return m_sectionEntries.visibleElementPosition(itemLibId);
}

bool ItemLibrarySectionModel::isItemVisible(int itemLibId)
{
    return m_sectionEntries.elementVisible(itemLibId);
}

bool ItemLibrarySectionModel::updateSectionVisibility(const QString &searchText, bool *changed)
{
    bool haveVisibleItems = false;

    *changed = false;

    QMap<int, ItemLibraryItemModel *>::const_iterator itemIt = m_sectionEntries.elements().constBegin();
    while (itemIt != m_sectionEntries.elements().constEnd()) {

        bool itemVisible = itemIt.value()->itemName().toLower().contains(searchText),
            itemChanged = false;
        itemChanged = m_sectionEntries.setElementVisible(itemIt.key(), itemVisible);

        *changed |= itemChanged;

        if (itemVisible)
            haveVisibleItems = true;

        ++itemIt;
    }

    return haveVisibleItems;
}

void ItemLibrarySectionModel::updateItemIconSize(const QSize &itemIconSize)
{
    foreach (ItemLibraryItemModel *item, m_sectionEntries.elements().values()) {
        item->setItemIconSize(itemIconSize);
    }
}

bool ItemLibrarySectionModel::operator<(const ItemLibrarySectionModel &other) const
{
    return sectionName() < other.sectionName();
}

ItemLibraryModel::ItemLibraryModel(QScriptEngine *scriptEngine, QObject *parent)
    : ItemLibrarySortedModel<ItemLibrarySectionModel>(parent),
      m_scriptEngine(scriptEngine),
      m_metaInfo(0),
      m_searchText(""),
      m_itemIconSize(64, 64),
      m_nextLibId(0)
{
}

ItemLibraryModel::~ItemLibraryModel()
{
    if (m_metaInfo)
        delete m_metaInfo;
}

QString ItemLibraryModel::searchText() const
{
    return m_searchText;
}

void ItemLibraryModel::setSearchText(const QString &searchText)
{
    QString lowerSearchText = searchText.toLower();

    if (m_searchText != lowerSearchText) {
        m_searchText = lowerSearchText;
        emit searchTextChanged();

        updateVisibility();
    }
}

void ItemLibraryModel::setItemIconSize(const QSize &itemIconSize)
{
    m_itemIconSize = itemIconSize;

    foreach (ItemLibrarySectionModel *section, elements().values())
        section->updateItemIconSize(itemIconSize);
}

int ItemLibraryModel::getItemSectionIndex(int itemLibId)
{
    if (m_sections.contains(itemLibId))
        return elementModel(m_sections.value(itemLibId))->visibleItemIndex(itemLibId);
    else
        return -1;
}

int ItemLibraryModel::getSectionLibId(int itemLibId)
{
    return m_sections.value(itemLibId);
}

bool ItemLibraryModel::isItemVisible(int itemLibId)
{
    if (!m_sections.contains(itemLibId))
        return false;

    int sectionLibId = m_sections.value(itemLibId);
    if (!elementVisible(sectionLibId))
        return false;

    return elementModel(sectionLibId)->isItemVisible(itemLibId);
}

void ItemLibraryModel::update(const MetaInfo &metaInfo)
{
    QMap<QString, int> sections;

    clearElements();
    m_itemInfos.clear();
    m_sections.clear();
    m_nextLibId = 0;

    if (!m_metaInfo) {
        m_metaInfo = new MetaInfo(metaInfo);
    } else {
        *m_metaInfo = metaInfo;
    }

    foreach (const QString &type, metaInfo.itemLibraryItems()) {
        foreach (const ItemLibraryInfo &itemLibraryRepresentation, itemLibraryRepresentations(type)) {

            QString itemSectionName = itemLibraryRepresentation.category();
            ItemLibrarySectionModel *sectionModel;
            ItemLibraryItemModel *itemModel;
            int itemId = m_nextLibId++, sectionId;

            if (sections.contains(itemSectionName)) {
                sectionId = sections.value(itemSectionName);
                sectionModel = elementModel(sectionId);
            } else {
                sectionId = m_nextLibId++;
                sectionModel = new ItemLibrarySectionModel(m_scriptEngine.data(), sectionId, itemSectionName, this);
                addElement(sectionModel, sectionId);
                sections.insert(itemSectionName, sectionId);
            }

            m_itemInfos.insert(itemId, itemLibraryRepresentation);

            itemModel = new ItemLibraryItemModel(m_scriptEngine.data(), itemId, itemLibraryRepresentation.name());
            itemModel->setItemIcon(itemLibraryRepresentation.icon());
            itemModel->setItemIconSize(m_itemIconSize);
            sectionModel->addSectionEntry(itemModel);
            m_sections.insert(itemId, sectionId);
        }
    }

    updateVisibility();
}

QString ItemLibraryModel::getTypeName(int libId)
{
    return m_itemInfos.value(libId).typeName();
}

QMimeData *ItemLibraryModel::getMimeData(int libId)
{
    QMimeData *mimeData = new QMimeData();

    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream << m_itemInfos.value(libId);
    mimeData->setData(QLatin1String("application/vnd.bauhaus.itemlibraryinfo"), data);

    const QIcon icon = m_itemInfos.value(libId).dragIcon();
    if (!icon.isNull()) {
        const QList<QSize> sizes = icon.availableSizes();
        if (!sizes.isEmpty())
            mimeData->setImageData(icon.pixmap(sizes.front()).toImage());
    }

    mimeData->removeFormat(QLatin1String("text/plain"));

    return mimeData;
}

QIcon ItemLibraryModel::getIcon(int libId)
{
    return m_itemInfos.value(libId).icon();
}

void ItemLibraryModel::updateVisibility()
{
    bool changed = false;

    QMap<int, ItemLibrarySectionModel *>::const_iterator sectionIt = elements().constBegin();
    while (sectionIt != elements().constEnd()) {

        ItemLibrarySectionModel *sectionModel = sectionIt.value();
        QString sectionSearchText = m_searchText;

        if (sectionModel->sectionName().toLower().contains(m_searchText))
            sectionSearchText = "";

        bool sectionChanged = false,
            sectionVisibility = sectionModel->updateSectionVisibility(sectionSearchText,
                                                                      &sectionChanged);
        if (sectionChanged) {
            changed = true;
            if (sectionVisibility)
                emit sectionVisibilityChanged(sectionIt.key());
        }

        changed |= setElementVisible(sectionIt.key(), sectionVisibility);
        ++sectionIt;
    }

    if (changed)
        emit visibilityChanged();
}

QList<ItemLibraryInfo> ItemLibraryModel::itemLibraryRepresentations(const QString &type)
{
    QList<ItemLibraryInfo> itemLibraryRepresentationList;
    NodeMetaInfo nodeInfo = m_metaInfo->nodeMetaInfo(type);

    if (nodeInfo.isQmlGraphicsItem()) {
        itemLibraryRepresentationList = m_metaInfo->itemLibraryRepresentations(nodeInfo);

        QImage dragImage(64, 64, QImage::Format_RGB32); // TODO: draw item drag icon
        dragImage.fill(0xffffffff);
        QPainter p(&dragImage);
        QPen pen(Qt::gray);
        pen.setWidth(2);
        p.setPen(pen);
        p.drawRect(1, 1, dragImage.width() - 2, dragImage.height() - 2);
        QPixmap dragPixmap(QPixmap::fromImage(dragImage));

        if (!m_metaInfo->hasNodeMetaInfo(type))
            qWarning() << "ItemLibrary: type not declared: " << type;

        static QIcon defaultIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));

        if (itemLibraryRepresentationList.isEmpty() || !m_metaInfo->hasNodeMetaInfo(type)) {
            QIcon icon = nodeInfo.icon();
            if (icon.isNull())
                icon = defaultIcon;

            ItemLibraryInfo itemLibraryInfo;
            itemLibraryInfo.setName(type);
            itemLibraryInfo.setTypeName(nodeInfo.typeName());
            itemLibraryInfo.setCategory(nodeInfo.category());
            itemLibraryInfo.setIcon(icon);
            itemLibraryInfo.setDragIcon(dragPixmap);
            itemLibraryInfo.setMajorVersion(nodeInfo.majorVersion());
            itemLibraryInfo.setMinorVersion(nodeInfo.minorVersion());
            itemLibraryRepresentationList.append(itemLibraryInfo);
        }
        else {
            foreach (ItemLibraryInfo itemLibraryRepresentation, itemLibraryRepresentationList) {
                QIcon icon = itemLibraryRepresentation.icon();
                if (itemLibraryRepresentation.icon().isNull())
                    itemLibraryRepresentation.setIcon(defaultIcon);

                if (itemLibraryRepresentation.dragIcon().isNull())
                    itemLibraryRepresentation.setDragIcon(dragPixmap);

                if (itemLibraryRepresentation.category().isEmpty())
                    itemLibraryRepresentation.setCategory(nodeInfo.category());
            }
        }
    }

    return itemLibraryRepresentationList;
}

} // namespace Internal
} // namespace QmlDesigner

<commit_msg>QmlDesigner.itemLibrary: set correct size for dragItem<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 "itemlibrarymodel.h"
#include "metainfo.h"

#include <QVariant>
#include <QMimeData>
#include <QPainter>
#include <QPen>
#include <qdebug.h>

namespace QmlDesigner {

namespace Internal {

template <class T>
ItemLibrarySortedModel<T>::ItemLibrarySortedModel(QObject *parent) :
    QDeclarativeListModel(parent)
{
}

template <class T>
ItemLibrarySortedModel<T>::~ItemLibrarySortedModel()
{
    clearElements();
}

template <class T>
void ItemLibrarySortedModel<T>::clearElements()
{
    while (m_elementOrder.count() > 0)
        removeElement(m_elementOrder.at(0).libId);
}

template <class T>
void ItemLibrarySortedModel<T>::addElement(T *element, int libId)
{
    struct order_struct orderEntry;
    orderEntry.libId = libId;
    orderEntry.visible = false;

    int pos = 0;
    while ((pos < m_elementOrder.count()) &&
           (*(m_elementModels.value(m_elementOrder.at(pos).libId)) < *element))
        ++pos;

    m_elementModels.insert(libId, element);
    m_elementOrder.insert(pos, orderEntry);

    setElementVisible(libId, true);
}

template <class T>
void ItemLibrarySortedModel<T>::removeElement(int libId)
{
    T *element = m_elementModels.value(libId);
    int pos = findElement(libId);

    setElementVisible(libId, false);

    m_elementModels.remove(libId);
    m_elementOrder.removeAt(pos);

    delete element;
}

template <class T>
bool ItemLibrarySortedModel<T>::elementVisible(int libId) const
{
    int pos = findElement(libId);
    return m_elementOrder.at(pos).visible;
}

template <class T>
bool ItemLibrarySortedModel<T>::setElementVisible(int libId, bool visible)
{
    int pos = findElement(libId);
    if (m_elementOrder.at(pos).visible == visible)
        return false;

    int visiblePos = visibleElementPosition(libId);
    if (visible)
        insert(visiblePos, *(m_elementModels.value(libId)));
    else
        remove(visiblePos);

    m_elementOrder[pos].visible = visible;
    return true;
}

template <class T>
const QMap<int, T *> &ItemLibrarySortedModel<T>::elements() const
{
    return m_elementModels;
}

template <class T>
T *ItemLibrarySortedModel<T>::elementModel(int libId)
{
    return m_elementModels.value(libId);
}

template <class T>
int ItemLibrarySortedModel<T>::findElement(int libId) const
{
    int i = 0;
    QListIterator<struct order_struct> it(m_elementOrder);

    while (it.hasNext()) {
        if (it.next().libId == libId)
            return i;
        ++i;
    }

    return -1;
}

template <class T>
int ItemLibrarySortedModel<T>::visibleElementPosition(int libId) const
{
    int i = 0;
    QListIterator<struct order_struct> it(m_elementOrder);

    while (it.hasNext()) {
        struct order_struct order = it.next();
        if (order.libId == libId)
            return i;
        if (order.visible)
            ++i;
    }

    return -1;
}

ItemLibraryItemModel::ItemLibraryItemModel(QScriptEngine *scriptEngine, int itemLibId, const QString &itemName)
    : QScriptValue(scriptEngine->newObject()),
      m_scriptEngine(scriptEngine),
      m_libId(itemLibId),
      m_name(itemName),
      m_icon(),
      m_iconSize(64, 64)
{
    QScriptValue pixmapScriptValue(m_scriptEngine->newVariant(QPixmap()));

    setProperty(QLatin1String("itemLibId"), itemLibId);
    setProperty(QLatin1String("itemName"), itemName);
    setProperty(QLatin1String("itemPixmap"), pixmapScriptValue);
}

ItemLibraryItemModel::~ItemLibraryItemModel()
{
    setProperty(QLatin1String("itemPixmap"), QVariant::Invalid);
}

int ItemLibraryItemModel::itemLibId() const
{
    return m_libId;
}

QString ItemLibraryItemModel::itemName() const
{
    return m_name;
}

void ItemLibraryItemModel::setItemIcon(const QIcon &itemIcon)
{
    m_icon = itemIcon;

    QScriptValue pixmapScriptValue(m_scriptEngine->newVariant(m_icon.pixmap(m_iconSize)));
    setProperty(QLatin1String("itemPixmap"), pixmapScriptValue);
}

void ItemLibraryItemModel::setItemIconSize(const QSize &itemIconSize)
{
    m_iconSize = itemIconSize;
//    qDebug() << "set icon size" << itemIconSize;
    setItemIcon(m_icon);
}

bool ItemLibraryItemModel::operator<(const ItemLibraryItemModel &other) const
{
    return itemName() < other.itemName();
}

ItemLibrarySectionModel::ItemLibrarySectionModel(QScriptEngine *scriptEngine, int sectionLibId, const QString &sectionName, QObject *parent)
    : QScriptValue(scriptEngine->newObject()),
      m_name(sectionName),
      m_sectionEntries(parent)
{
    QScriptValue::setProperty(QLatin1String("sectionLibId"), sectionLibId);
    QScriptValue::setProperty(QLatin1String("sectionName"), sectionName);
    QScriptValue::setProperty(QLatin1String("sectionEntries"),
        scriptEngine->newVariant(QVariant::fromValue(static_cast<QDeclarativeListModel *>(&m_sectionEntries))));
}

QString ItemLibrarySectionModel::sectionName() const
{
    return m_name;
}

void ItemLibrarySectionModel::addSectionEntry(ItemLibraryItemModel *sectionEntry)
{
    m_sectionEntries.addElement(sectionEntry, sectionEntry->itemLibId());
}

void ItemLibrarySectionModel::removeSectionEntry(int itemLibId)
{
    m_sectionEntries.removeElement(itemLibId);
}

int ItemLibrarySectionModel::visibleItemIndex(int itemLibId)
{
    return m_sectionEntries.visibleElementPosition(itemLibId);
}

bool ItemLibrarySectionModel::isItemVisible(int itemLibId)
{
    return m_sectionEntries.elementVisible(itemLibId);
}

bool ItemLibrarySectionModel::updateSectionVisibility(const QString &searchText, bool *changed)
{
    bool haveVisibleItems = false;

    *changed = false;

    QMap<int, ItemLibraryItemModel *>::const_iterator itemIt = m_sectionEntries.elements().constBegin();
    while (itemIt != m_sectionEntries.elements().constEnd()) {

        bool itemVisible = itemIt.value()->itemName().toLower().contains(searchText),
            itemChanged = false;
        itemChanged = m_sectionEntries.setElementVisible(itemIt.key(), itemVisible);

        *changed |= itemChanged;

        if (itemVisible)
            haveVisibleItems = true;

        ++itemIt;
    }

    return haveVisibleItems;
}

void ItemLibrarySectionModel::updateItemIconSize(const QSize &itemIconSize)
{
    foreach (ItemLibraryItemModel *item, m_sectionEntries.elements().values()) {
        item->setItemIconSize(itemIconSize);
    }
}

bool ItemLibrarySectionModel::operator<(const ItemLibrarySectionModel &other) const
{
    return sectionName() < other.sectionName();
}

ItemLibraryModel::ItemLibraryModel(QScriptEngine *scriptEngine, QObject *parent)
    : ItemLibrarySortedModel<ItemLibrarySectionModel>(parent),
      m_scriptEngine(scriptEngine),
      m_metaInfo(0),
      m_searchText(""),
      m_itemIconSize(64, 64),
      m_nextLibId(0)
{
}

ItemLibraryModel::~ItemLibraryModel()
{
    if (m_metaInfo)
        delete m_metaInfo;
}

QString ItemLibraryModel::searchText() const
{
    return m_searchText;
}

void ItemLibraryModel::setSearchText(const QString &searchText)
{
    QString lowerSearchText = searchText.toLower();

    if (m_searchText != lowerSearchText) {
        m_searchText = lowerSearchText;
        emit searchTextChanged();

        updateVisibility();
    }
}

void ItemLibraryModel::setItemIconSize(const QSize &itemIconSize)
{
    m_itemIconSize = itemIconSize;

    foreach (ItemLibrarySectionModel *section, elements().values())
        section->updateItemIconSize(itemIconSize);
}

int ItemLibraryModel::getItemSectionIndex(int itemLibId)
{
    if (m_sections.contains(itemLibId))
        return elementModel(m_sections.value(itemLibId))->visibleItemIndex(itemLibId);
    else
        return -1;
}

int ItemLibraryModel::getSectionLibId(int itemLibId)
{
    return m_sections.value(itemLibId);
}

bool ItemLibraryModel::isItemVisible(int itemLibId)
{
    if (!m_sections.contains(itemLibId))
        return false;

    int sectionLibId = m_sections.value(itemLibId);
    if (!elementVisible(sectionLibId))
        return false;

    return elementModel(sectionLibId)->isItemVisible(itemLibId);
}

void ItemLibraryModel::update(const MetaInfo &metaInfo)
{
    QMap<QString, int> sections;

    clearElements();
    m_itemInfos.clear();
    m_sections.clear();
    m_nextLibId = 0;

    if (!m_metaInfo) {
        m_metaInfo = new MetaInfo(metaInfo);
    } else {
        *m_metaInfo = metaInfo;
    }

    foreach (const QString &type, metaInfo.itemLibraryItems()) {
        foreach (const ItemLibraryInfo &itemLibraryRepresentation, itemLibraryRepresentations(type)) {

            QString itemSectionName = itemLibraryRepresentation.category();
            ItemLibrarySectionModel *sectionModel;
            ItemLibraryItemModel *itemModel;
            int itemId = m_nextLibId++, sectionId;

            if (sections.contains(itemSectionName)) {
                sectionId = sections.value(itemSectionName);
                sectionModel = elementModel(sectionId);
            } else {
                sectionId = m_nextLibId++;
                sectionModel = new ItemLibrarySectionModel(m_scriptEngine.data(), sectionId, itemSectionName, this);
                addElement(sectionModel, sectionId);
                sections.insert(itemSectionName, sectionId);
            }

            m_itemInfos.insert(itemId, itemLibraryRepresentation);

            itemModel = new ItemLibraryItemModel(m_scriptEngine.data(), itemId, itemLibraryRepresentation.name());
            itemModel->setItemIcon(itemLibraryRepresentation.icon());
            itemModel->setItemIconSize(m_itemIconSize);
            sectionModel->addSectionEntry(itemModel);
            m_sections.insert(itemId, sectionId);
        }
    }

    updateVisibility();
}

QString ItemLibraryModel::getTypeName(int libId)
{
    return m_itemInfos.value(libId).typeName();
}

QMimeData *ItemLibraryModel::getMimeData(int libId)
{
    QMimeData *mimeData = new QMimeData();

    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream << m_itemInfos.value(libId);
    mimeData->setData(QLatin1String("application/vnd.bauhaus.itemlibraryinfo"), data);

    const QIcon icon = m_itemInfos.value(libId).dragIcon();
    if (!icon.isNull()) {
        const QList<QSize> sizes = icon.availableSizes();
        if (!sizes.isEmpty())
            mimeData->setImageData(icon.pixmap(sizes.front()).toImage());
    }

    mimeData->removeFormat(QLatin1String("text/plain"));

    return mimeData;
}

QIcon ItemLibraryModel::getIcon(int libId)
{
    return m_itemInfos.value(libId).icon();
}

void ItemLibraryModel::updateVisibility()
{
    bool changed = false;

    QMap<int, ItemLibrarySectionModel *>::const_iterator sectionIt = elements().constBegin();
    while (sectionIt != elements().constEnd()) {

        ItemLibrarySectionModel *sectionModel = sectionIt.value();
        QString sectionSearchText = m_searchText;

        if (sectionModel->sectionName().toLower().contains(m_searchText))
            sectionSearchText = "";

        bool sectionChanged = false,
            sectionVisibility = sectionModel->updateSectionVisibility(sectionSearchText,
                                                                      &sectionChanged);
        if (sectionChanged) {
            changed = true;
            if (sectionVisibility)
                emit sectionVisibilityChanged(sectionIt.key());
        }

        changed |= setElementVisible(sectionIt.key(), sectionVisibility);
        ++sectionIt;
    }

    if (changed)
        emit visibilityChanged();
}

static inline int getWidth(const ItemLibraryInfo &itemLibraryRepresentation)
{
    foreach (const ItemLibraryInfo::Property &property, itemLibraryRepresentation.properties())
    {
        if (property.name() == QLatin1String("width"))
            return property.value().toInt();
    }
    return 64;
}

static inline int getHeight(const ItemLibraryInfo &itemLibraryRepresentation)
{
    foreach (const ItemLibraryInfo::Property &property, itemLibraryRepresentation.properties())
    {
        if (property.name() == QLatin1String("height"))
            return property.value().toInt();
    }
    return 64;
}

static inline QPixmap createDragPixmap(int width, int height)
{
    QImage dragImage(width, height, QImage::Format_RGB32); // TODO: draw item drag icon
    dragImage.fill(0xffffffff);
    QPainter p(&dragImage);
    QPen pen(Qt::gray);
    pen.setWidth(2);
    p.setPen(pen);
    p.drawRect(1, 1, dragImage.width() - 2, dragImage.height() - 2);
    return QPixmap::fromImage(dragImage);
}

QList<ItemLibraryInfo> ItemLibraryModel::itemLibraryRepresentations(const QString &type)
{
    QList<ItemLibraryInfo> itemLibraryRepresentationList;
    NodeMetaInfo nodeInfo = m_metaInfo->nodeMetaInfo(type);

    if (nodeInfo.isQmlGraphicsItem()) {
        itemLibraryRepresentationList = m_metaInfo->itemLibraryRepresentations(nodeInfo);

        if (!m_metaInfo->hasNodeMetaInfo(type))
            qWarning() << "ItemLibrary: type not declared: " << type;

        static QIcon defaultIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));

        if (itemLibraryRepresentationList.isEmpty() || !m_metaInfo->hasNodeMetaInfo(type)) {
            QIcon icon = nodeInfo.icon();
            if (icon.isNull())
                icon = defaultIcon;

            ItemLibraryInfo itemLibraryInfo;
            itemLibraryInfo.setName(type);
            itemLibraryInfo.setTypeName(nodeInfo.typeName());
            itemLibraryInfo.setCategory(nodeInfo.category());
            itemLibraryInfo.setIcon(icon);
            itemLibraryInfo.setDragIcon(createDragPixmap(64, 64));
            itemLibraryInfo.setMajorVersion(nodeInfo.majorVersion());
            itemLibraryInfo.setMinorVersion(nodeInfo.minorVersion());
            itemLibraryRepresentationList.append(itemLibraryInfo);
        }
        else {
            foreach (ItemLibraryInfo itemLibraryRepresentation, itemLibraryRepresentationList) {

                QIcon icon = itemLibraryRepresentation.icon();
                if (itemLibraryRepresentation.icon().isNull())
                    itemLibraryRepresentation.setIcon(defaultIcon);

                if (itemLibraryRepresentation.dragIcon().isNull())
                    itemLibraryRepresentation.setDragIcon(createDragPixmap(getWidth(itemLibraryRepresentation), getHeight(itemLibraryRepresentation)));

                if (itemLibraryRepresentation.category().isEmpty())
                    itemLibraryRepresentation.setCategory(nodeInfo.category());
            }
        }
    }

    return itemLibraryRepresentationList;
}

} // namespace Internal
} // namespace QmlDesigner

<|endoftext|>


<commit_before>#include <stan/math/error_handling/matrix/check_spsd_matrix.hpp>
#include <gtest/gtest.h>

TEST(MathErrorHandlingMatrix, checkSpsdMatrixPosDef) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y;
  double result;

  y.resize(3,3);
  y << 2, -1, 0, -1, 2, -1, 0, -1, 2;
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)",
                                           y, "y", &result));

  y << 1, 2, 3, 2, 1, 2, 3, 2, 1;
  EXPECT_THROW(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result),
               std::domain_error);

  y.setZero();
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result));
}

TEST(MathErrorHandlingMatrix, checkSpsdMatrixZero) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y =
    Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>::Zero(3,3);
  double result;
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result));
}

TEST(MathErrorHandlingMatrix, checkSpsdNotSquare) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y =
    Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>::Zero(3,2);
  double result;
  EXPECT_THROW(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result),
               std::domain_error);
}
<commit_msg>added NaN test for check_spsd_matrix<commit_after>#include <stan/math/error_handling/matrix/check_spsd_matrix.hpp>
#include <gtest/gtest.h>

TEST(MathErrorHandlingMatrix, checkSpsdMatrixPosDef) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y;
  double result;

  y.resize(3,3);
  y << 2, -1, 0, -1, 2, -1, 0, -1, 2;
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)",
                                           y, "y", &result));

  y << 1, 2, 3, 2, 1, 2, 3, 2, 1;
  EXPECT_THROW(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result),
               std::domain_error);

  y.setZero();
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result));
}

TEST(MathErrorHandlingMatrix, checkSpsdMatrixZero) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y =
    Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>::Zero(3,3);
  double result;
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result));
}

TEST(MathErrorHandlingMatrix, checkSpsdNotSquare) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y =
    Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>::Zero(3,2);
  double result;
  EXPECT_THROW(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result),
               std::domain_error);
}

TEST(MathErrorHandlingMatrix, checkSpsdMatrixPosDef_nan) {
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y;
  double result;
  double nan = std::numeric_limits<double>::quiet_NaN();

  y.resize(3,3);
  y << 2, -1, 0, -1, 2, -1, 0, -1, 2;
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)",
                                           y, "y", &result));

  y.setZero();
  EXPECT_TRUE(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)", y, "y", &result));

  for (int i = 0; i < y.size(); i++) {
    y << 2, -1, 0, -1, 2, -1, 0, -1, 2;
    y(i) = nan;
    EXPECT_THROW(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)",
                                               y, "y", &result),
                 std::domain_error);

    y.setZero();
    y(i) = nan;
    EXPECT_THROW(stan::math::check_spsd_matrix("checkSpsdMatrix(%1%)",
                                               y, "y", &result),
                 std::domain_error);
  }
}
<|endoftext|>


<commit_before>#include <stan/math/error_handling/matrix/check_unit_vector.hpp>
#include <gtest/gtest.h>

TEST(MathErrorHandlingMatrix, checkUnitVector) {
  Eigen::Matrix<double,Eigen::Dynamic,1> y(2);
  double result;
  y << sqrt(0.5), sqrt(0.5);

  EXPECT_TRUE(stan::math::check_unit_vector("checkUnitVector(%1%)",
                                        y, "y", &result));

  y[1] = 0.55;
  EXPECT_THROW(stan::math::check_unit_vector("checkUnitVector(%1%)", y, "y", &result),
               std::domain_error);
}
<commit_msg>added failing nan test for check_unit_vector<commit_after>#include <stan/math/error_handling/matrix/check_unit_vector.hpp>
#include <gtest/gtest.h>

TEST(MathErrorHandlingMatrix, checkUnitVector) {
  Eigen::Matrix<double,Eigen::Dynamic,1> y(2);
  double result;
  y << sqrt(0.5), sqrt(0.5);

  EXPECT_TRUE(stan::math::check_unit_vector("checkUnitVector(%1%)",
                                        y, "y", &result));

  y[1] = 0.55;
  EXPECT_THROW(stan::math::check_unit_vector("checkUnitVector(%1%)", y, "y", &result),
               std::domain_error);
}

TEST(MathErrorHandlingMatrix, checkUnitVector_nan) {
  Eigen::Matrix<double,Eigen::Dynamic,1> y(2);
  double result;
  double nan = std::numeric_limits<double>::quiet_NaN();

  y << nan, sqrt(0.5);
  EXPECT_THROW(stan::math::check_unit_vector("checkUnitVector(%1%)", y, "y", &result),
               std::domain_error);
  y << sqrt(0.5), nan;
  EXPECT_THROW(stan::math::check_unit_vector("checkUnitVector(%1%)", y, "y", &result),
               std::domain_error);
  y << nan, nan;
  EXPECT_THROW(stan::math::check_unit_vector("checkUnitVector(%1%)", y, "y", &result),
               std::domain_error);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>

#include "qnfctestcommon.h"
#include "qnfctestutil.h"

#include <qnearfieldmanager.h>
#include <qnearfieldtarget.h>
#include <qndefnfctextrecord.h>
#include <qndefnfcurirecord.h>
#include <qndefmessage.h>
#include <qndefrecord.h>

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QNearFieldTarget*)
Q_DECLARE_METATYPE(QNearFieldTarget::Type)
Q_DECLARE_METATYPE(QNdefFilter)

class tst_QNearFieldManager : public QObject
{
    Q_OBJECT

public:
    tst_QNearFieldManager();

private Q_SLOTS:
    void initTestCase();
    void cleanupTestCase();
    void targetDetected();
    void targetDetected_data();
    void unregisterTargetDetectedHandler();
    void registerTargetDetectedHandler();
    void registerTargetDetectedHandler_filter_data();
    void registerTargetDetectedHandler_filter();
    void registerTargetDetectedHandler_filter_negtive();
    void registerTargetDetectedHandler_filter_negtive_data();
};

tst_QNearFieldManager::tst_QNearFieldManager()
{
    qRegisterMetaType<QNdefMessage>("QNdefMessage");
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*");
}

void tst_QNearFieldManager::initTestCase()
{
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget *");
}

void tst_QNearFieldManager::cleanupTestCase()
{
}

/*!
 Description: Unit test for NFC target detected and lost

 TestScenario: 1. Touch and remove llcp device/Type1/Type2/Type3/Type4 tag one by one

 TestExpectedResults: 1. llcp device/Type1/Type2/Type3/Type4 tag detected/lost signal can be received
*/

void tst_QNearFieldManager::targetDetected()
{
    QFETCH(QNearFieldTarget::Type, type);
    QFETCH(QString, hint);

    QNearFieldManager nfcManager;

    QSignalSpy targetDetectedSpy(&nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)));
    QSignalSpy targetLostSpy(&nfcManager, SIGNAL(targetLost(QNearFieldTarget*)));

    nfcManager.startTargetDetection(type);
    QNfcTestUtil::ShowMessage(hint);
    QTRY_VERIFY(!targetDetectedSpy.isEmpty());

    QNearFieldTarget *target = targetDetectedSpy.at(targetDetectedSpy.count()-1).at(0).value<QNearFieldTarget *>();

    QSignalSpy disconnectedSpy(target, SIGNAL(disconnected()));
    QVERIFY(target);

    if (type != QNearFieldTarget::AnyTarget)
    {
        QVERIFY(!target->uid().isEmpty());
        QCOMPARE(target->type(), type);
    }

    QNfcTestUtil::ShowMessage("please remove the target");

    QTRY_VERIFY(!targetLostSpy.isEmpty());

    QNearFieldTarget *lostTarget = targetLostSpy.first().at(0).value<QNearFieldTarget *>();

    QCOMPARE(target, lostTarget);

    QVERIFY(!disconnectedSpy.isEmpty());

    nfcManager.stopTargetDetection();
}

void tst_QNearFieldManager::targetDetected_data()
{
    QTest::addColumn<QNearFieldTarget::Type>("type");
    QTest::addColumn<QString>("hint");
    QTest::newRow("llcp device") << QNearFieldTarget::AnyTarget << "Please touch llcp device";
    QTest::newRow("NfcTagType1") << QNearFieldTarget::NfcTagType1 << "Please touch tag type1";
    QTest::newRow("NfcTagType2") << QNearFieldTarget::NfcTagType2 << "Please touch tag type2";
    QTest::newRow("NfcTagType3") << QNearFieldTarget::NfcTagType3 << "Please touch tag type3";
    QTest::newRow("NfcTagType4") << QNearFieldTarget::NfcTagType4 << "Please touch tag type4";
}

/*!
 Description: Unit test for NFC unregisterTargetDetectedHandler function

 TestScenario: 1.

 TestExpectedResults: 1. return false
*/

void tst_QNearFieldManager::unregisterTargetDetectedHandler()
{
    QNearFieldManager manager;

    QVERIFY(!manager.unregisterTargetDetectedHandler(-1));
    QVERIFY(!manager.unregisterTargetDetectedHandler(0));
}

class MessageListener : public QObject
{
    Q_OBJECT

signals:
    void matchedNdefMessage(const QNdefMessage &message, QNearFieldTarget *target);
};

/*!
 Description: Unit test for NFC registerTargetDetectedHandler function

 TestScenario: 1. Symbian backend does not support registerTargetDetectedHandler without a QNdefFilter

 TestExpectedResults: 1. return -1
*/
void tst_QNearFieldManager::registerTargetDetectedHandler()
{
    QNearFieldManager manager;

    MessageListener listener;
    QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    int id = manager.registerTargetDetectedHandler(&listener,
                                                   SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    QVERIFY(id == -1);//symbian backend does not support registerTargetDetectedHandler without QNdefFilter
}

void tst_QNearFieldManager::registerTargetDetectedHandler_filter_data()
{
    QTest::addColumn<QNdefFilter>("filter");
    QTest::addColumn<QString>("hint");

    QNdefFilter filter;

    filter.appendRecord(QNdefRecord::NfcRtd, "Sp");
    QTest::newRow("SP") << filter << "Please touch a tag with 'SP' NDef message";

    filter.clear();
    filter.setOrderMatch(true);
    filter.appendRecord(QNdefRecord::Mime, "image/gif");
    filter.appendRecord<QNdefNfcTextRecord>(2, 10);
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("Image + Multiple Text + URI") << filter << "Please touch a tag with 'Image + Multiple Text + URI' NDef message";

    filter.clear();
    filter.setOrderMatch(true);
    filter.appendRecord<QNdefNfcTextRecord>(1, 1);
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("Text + URI") << filter << "Please touch a tag with 'Text + URI' NDef message";

    //negtive test
    filter.clear();
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("URI") << filter << "Please touch a tag without 'URI' NDef message";

}

/*!
 Description: Unit test for NFC registerTargetDetectedHandler with a NDef filter

 TestScenario: 1. Touch a tag with random NDef message/with 'Image + Multiple Text + URI' NDef message/with 'Text + URI' NDef message

 TestExpectedResults: 1. matchedNdefMessage signal will be emitted
*/
void tst_QNearFieldManager::registerTargetDetectedHandler_filter()
{
    QFETCH(QNdefFilter, filter);
    QFETCH(QString, hint);

    QNearFieldManager manager;

    MessageListener listener;
    QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    int id = manager.registerTargetDetectedHandler(filter, &listener,
                                                   SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    QVERIFY(id != -1);

    QNfcTestUtil::ShowMessage(hint);

    QTRY_VERIFY(!messageSpy.isEmpty());

    const QNdefMessage message = messageSpy.first().at(0).value<QNdefMessage>();

    QNearFieldTarget *target = messageSpy.first().at(1).value<QNearFieldTarget *>();

    QVERIFY(target == NULL);//symbain backend always return NULL target

    QVERIFY(manager.unregisterTargetDetectedHandler(id));
}

void tst_QNearFieldManager::registerTargetDetectedHandler_filter_negtive_data()
{
    QTest::addColumn<QNdefFilter>("filter");
    QTest::addColumn<QString>("hint");
    //negtive test
    QNdefFilter filter;

    QTest::newRow("Empty") << filter << "Please touch a tag without NDef message";

    filter.clear();
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("URI") << filter << "Please touch a tag without 'URI' NDef message";

}

/*!
 Description: Unit test for NFC registerTargetDetectedHandler with a NDef filter

 TestScenario: 1. Touch a tag without filter expected NDef message

 TestExpectedResults: 1. matchedNdefMessage signal will NOT be emitted
*/
void tst_QNearFieldManager::registerTargetDetectedHandler_filter_negtive()
{
    QFETCH(QNdefFilter, filter);
    QFETCH(QString, hint);

    QNearFieldManager manager;

    MessageListener listener;
    QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    int id = manager.registerTargetDetectedHandler(filter, &listener,
                                                   SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    QVERIFY(id != -1);

    QNfcTestUtil::ShowMessage(hint);

    QTRY_VERIFY(messageSpy.isEmpty());
    QVERIFY(manager.unregisterTargetDetectedHandler(id));
}

QTEST_MAIN(tst_QNearFieldManager);

#include "tst_qnearfieldmanager.moc"
<commit_msg>remove unused case<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>

#include "qnfctestcommon.h"
#include "qnfctestutil.h"

#include <qnearfieldmanager.h>
#include <qnearfieldtarget.h>
#include <qndefnfctextrecord.h>
#include <qndefnfcurirecord.h>
#include <qndefmessage.h>
#include <qndefrecord.h>

QTM_USE_NAMESPACE

Q_DECLARE_METATYPE(QNearFieldTarget*)
Q_DECLARE_METATYPE(QNearFieldTarget::Type)
Q_DECLARE_METATYPE(QNdefFilter)

class tst_QNearFieldManager : public QObject
{
    Q_OBJECT

public:
    tst_QNearFieldManager();

private Q_SLOTS:
    void initTestCase();
    void cleanupTestCase();
    void targetDetected();
    void targetDetected_data();
    void unregisterTargetDetectedHandler();
    void registerTargetDetectedHandler();
    void registerTargetDetectedHandler_filter_data();
    void registerTargetDetectedHandler_filter();
    void registerTargetDetectedHandler_filter_negtive();
    void registerTargetDetectedHandler_filter_negtive_data();
};

tst_QNearFieldManager::tst_QNearFieldManager()
{
    qRegisterMetaType<QNdefMessage>("QNdefMessage");
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*");
}

void tst_QNearFieldManager::initTestCase()
{
    qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget *");
}

void tst_QNearFieldManager::cleanupTestCase()
{
}

/*!
 Description: Unit test for NFC target detected and lost

 TestScenario: 1. Touch and remove llcp device/Type1/Type2/Type3/Type4 tag one by one

 TestExpectedResults: 1. llcp device/Type1/Type2/Type3/Type4 tag detected/lost signal can be received
*/

void tst_QNearFieldManager::targetDetected()
{
    QFETCH(QNearFieldTarget::Type, type);
    QFETCH(QString, hint);

    QNearFieldManager nfcManager;

    QSignalSpy targetDetectedSpy(&nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)));
    QSignalSpy targetLostSpy(&nfcManager, SIGNAL(targetLost(QNearFieldTarget*)));

    nfcManager.startTargetDetection(type);
    QNfcTestUtil::ShowMessage(hint);
    QTRY_VERIFY(!targetDetectedSpy.isEmpty());

    QNearFieldTarget *target = targetDetectedSpy.at(targetDetectedSpy.count()-1).at(0).value<QNearFieldTarget *>();

    QSignalSpy disconnectedSpy(target, SIGNAL(disconnected()));
    QVERIFY(target);

    if (type != QNearFieldTarget::AnyTarget)
    {
        QVERIFY(!target->uid().isEmpty());
        QCOMPARE(target->type(), type);
    }

    QNfcTestUtil::ShowMessage("please remove the target");

    QTRY_VERIFY(!targetLostSpy.isEmpty());

    QNearFieldTarget *lostTarget = targetLostSpy.first().at(0).value<QNearFieldTarget *>();

    QCOMPARE(target, lostTarget);

    QVERIFY(!disconnectedSpy.isEmpty());

    nfcManager.stopTargetDetection();
}

void tst_QNearFieldManager::targetDetected_data()
{
    QTest::addColumn<QNearFieldTarget::Type>("type");
    QTest::addColumn<QString>("hint");
    QTest::newRow("llcp device") << QNearFieldTarget::AnyTarget << "Please touch llcp device";
    QTest::newRow("NfcTagType1") << QNearFieldTarget::NfcTagType1 << "Please touch tag type1";
    QTest::newRow("NfcTagType2") << QNearFieldTarget::NfcTagType2 << "Please touch tag type2";
    QTest::newRow("NfcTagType3") << QNearFieldTarget::NfcTagType3 << "Please touch tag type3";
    QTest::newRow("NfcTagType4") << QNearFieldTarget::NfcTagType4 << "Please touch tag type4";
}

/*!
 Description: Unit test for NFC unregisterTargetDetectedHandler function

 TestScenario: 1.

 TestExpectedResults: 1. return false
*/

void tst_QNearFieldManager::unregisterTargetDetectedHandler()
{
    QNearFieldManager manager;

    QVERIFY(!manager.unregisterTargetDetectedHandler(-1));
    QVERIFY(!manager.unregisterTargetDetectedHandler(0));
}

class MessageListener : public QObject
{
    Q_OBJECT

signals:
    void matchedNdefMessage(const QNdefMessage &message, QNearFieldTarget *target);
};

/*!
 Description: Unit test for NFC registerTargetDetectedHandler function

 TestScenario: 1. Symbian backend does not support registerTargetDetectedHandler without a QNdefFilter

 TestExpectedResults: 1. return -1
*/
void tst_QNearFieldManager::registerTargetDetectedHandler()
{
    QNearFieldManager manager;

    MessageListener listener;
    QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    int id = manager.registerTargetDetectedHandler(&listener,
                                                   SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    QVERIFY(id == -1);//symbian backend does not support registerTargetDetectedHandler without QNdefFilter
}

void tst_QNearFieldManager::registerTargetDetectedHandler_filter_data()
{
    QTest::addColumn<QNdefFilter>("filter");
    QTest::addColumn<QString>("hint");

    QNdefFilter filter;

    filter.appendRecord(QNdefRecord::NfcRtd, "Sp");
    QTest::newRow("SP") << filter << "Please touch a tag with 'SP' NDef message";

    filter.clear();
    filter.setOrderMatch(true);
    filter.appendRecord<QNdefNfcTextRecord>(1, 1);
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("Text + URI") << filter << "Please touch a tag with 'Text + URI' NDef message";

    filter.clear();
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("URI") << filter << "Please touch a tag with 'URI' NDef message";

}

/*!
 Description: Unit test for NFC registerTargetDetectedHandler with a NDef filter

 TestScenario: 1. Touch a tag with random NDef message/with 'Image + Multiple Text + URI' NDef message/with 'Text + URI' NDef message

 TestExpectedResults: 1. matchedNdefMessage signal will be emitted
*/
void tst_QNearFieldManager::registerTargetDetectedHandler_filter()
{
    QFETCH(QNdefFilter, filter);
    QFETCH(QString, hint);

    QNearFieldManager manager;

    MessageListener listener;
    QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    int id = manager.registerTargetDetectedHandler(filter, &listener,
                                                   SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    QVERIFY(id != -1);

    QNfcTestUtil::ShowMessage(hint);

    QTRY_VERIFY(!messageSpy.isEmpty());

    const QNdefMessage message = messageSpy.first().at(0).value<QNdefMessage>();

    QNearFieldTarget *target = messageSpy.first().at(1).value<QNearFieldTarget *>();

    QVERIFY(target == NULL);//symbain backend always return NULL target

    QVERIFY(manager.unregisterTargetDetectedHandler(id));
}

void tst_QNearFieldManager::registerTargetDetectedHandler_filter_negtive_data()
{
    QTest::addColumn<QNdefFilter>("filter");
    QTest::addColumn<QString>("hint");
    //negtive test
    QNdefFilter filter;

    QTest::newRow("Empty") << filter << "Please touch a tag without NDef message";

    filter.clear();
    filter.appendRecord<QNdefNfcUriRecord>(1, 1);
    QTest::newRow("URI") << filter << "Please touch a tag without 'URI' NDef message";

}

/*!
 Description: Unit test for NFC registerTargetDetectedHandler with a NDef filter

 TestScenario: 1. Touch a tag without filter expected NDef message

 TestExpectedResults: 1. matchedNdefMessage signal will NOT be emitted
*/
void tst_QNearFieldManager::registerTargetDetectedHandler_filter_negtive()
{
    QFETCH(QNdefFilter, filter);
    QFETCH(QString, hint);

    QNearFieldManager manager;

    MessageListener listener;
    QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    int id = manager.registerTargetDetectedHandler(filter, &listener,
                                                   SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*)));

    QVERIFY(id != -1);

    QNfcTestUtil::ShowMessage(hint);

    QTRY_VERIFY(messageSpy.isEmpty());
    QVERIFY(manager.unregisterTargetDetectedHandler(id));
}

QTEST_MAIN(tst_QNearFieldManager);

#include "tst_qnearfieldmanager.moc"
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "tracer.h"

#include <pthread.h>

#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

#include "atomic.h"
#include "util/posix.h"
#include "util/string.h"

using namespace std;  // NOLINT

void Tracer::Activate(
  const int buffer_size,
  const int flush_threshold,
  const string &trace_file)
{
  trace_file_ = trace_file;
  buffer_size_ = buffer_size;
  flush_threshold_ = flush_threshold;
  assert(buffer_size_ > 1 && flush_threshold_>= 0
    && flush_threshold_ < buffer_size_);

  ring_buffer_ = new BufferEntry[buffer_size_];
  commit_buffer_ = new atomic_int32[buffer_size_];
  for (int i = 0; i < buffer_size_; i++)
    atomic_init32(&commit_buffer_[i]);

  int retval;
  retval = pthread_cond_init(&sig_continue_trace_, NULL);
  retval |= pthread_mutex_init(&sig_continue_trace_mutex_, NULL);
  retval |= pthread_cond_init(&sig_flush_, NULL);
  retval |= pthread_mutex_init(&sig_flush_mutex_, NULL);
  assert(retval == 0);

  active_ = true;
}

/**
 * Trace a message.  This is usually a lock-free procedure that just
 * requires two fetch_and_add operations and a gettimeofday syscall.
 * There are two exceptions:
 *   -# If the ring buffer is full, the function blocks until the flush
 *      thread made some space.  Avoid that by carefully choosing size
 *      and threshold.
 *   -# If this message reaches the threshold, the flush thread gets
 *      signaled.
 *
 * \param[in] event Arbitrary code, for consistency applications should use one
 *            of the TraceEvents constants. Negative codes are reserved
 *            for internal use.
 * \param[in] id Arbitrary id, for example file name or module name which is
 *            doing the trace.
 * \return The sequence number which was used to trace the record
 */
int32_t Tracer::DoTrace(
  const int event,
  const PathString &path,
  const string &msg)
{
  int32_t my_seq_no = atomic_xadd32(&seq_no_, 1);
  timeval now;
  gettimeofday(&now, NULL);
  int pos = my_seq_no % buffer_size_;

  while (my_seq_no - atomic_read32(&flushed_) >= buffer_size_) {
    timespec timeout;
    int retval;
    GetTimespecRel(25, &timeout);
    retval = pthread_mutex_lock(&sig_continue_trace_mutex_);
    retval |= pthread_cond_timedwait(&sig_continue_trace_,
                                     &sig_continue_trace_mutex_, &timeout);
    retval |= pthread_mutex_unlock(&sig_continue_trace_mutex_);
    assert(retval == ETIMEDOUT || retval == 0);
  }

  ring_buffer_[pos].time_stamp = now;
  ring_buffer_[pos].code = event;
  ring_buffer_[pos].path = path;
  ring_buffer_[pos].msg = msg;
  atomic_inc32(&commit_buffer_[pos]);

  if (my_seq_no - atomic_read32(&flushed_) == flush_threshold_) {
    LockMutex(&sig_flush_mutex_);
    int err_code __attribute__((unused)) = pthread_cond_signal(&sig_flush_);
    assert(err_code == 0 && "Could not signal flush thread");
    UnlockMutex(&sig_flush_mutex_);
  }

  return my_seq_no;
}

void Tracer::Flush() {
  if (!active_) return;

  int32_t save_seq_no = DoTrace(kEventFlush, PathString("Tracer", 6),
                                "flushed ring buffer");
  while (atomic_read32(&flushed_) <= save_seq_no) {
    timespec timeout;
    int retval;

    atomic_cas32(&flush_immediately_, 0, 1);
    LockMutex(&sig_flush_mutex_);
    retval = pthread_cond_signal(&sig_flush_);
    assert(retval == 0);
    UnlockMutex(&sig_flush_mutex_);

    GetTimespecRel(250, &timeout);
    retval = pthread_mutex_lock(&sig_continue_trace_mutex_);
    retval |= pthread_cond_timedwait(&sig_continue_trace_,
                                     &sig_continue_trace_mutex_,
                                     &timeout);
    retval |= pthread_mutex_unlock(&sig_continue_trace_mutex_);
    assert(retval == ETIMEDOUT || retval == 0);
  }
}

void Tracer::GetTimespecRel(const int64_t ms, timespec *ts) {
  timeval now;
  gettimeofday(&now, NULL);
  int64_t nsecs = now.tv_usec * 1000 + (ms % 1000)*1000*1000;
  int carry = 0;
  if (nsecs >= 1000*1000*1000) {
    carry = 1;
    nsecs -= 1000*1000*1000;
  }
  ts->tv_sec = now.tv_sec + ms/1000 + carry;
  ts->tv_nsec = nsecs;
}

void *Tracer::MainFlush(void *data) {
  Tracer *tracer = reinterpret_cast<Tracer *>(data);
  int retval;
  LockMutex(&tracer->sig_flush_mutex_);
  FILE *f = fopen(tracer->trace_file_.c_str(), "a");
  assert(f != NULL && "Could not open trace file");
  struct timespec timeout;

  do {
    while ((atomic_read32(&tracer->terminate_flush_thread_) == 0) &&
           (atomic_read32(&tracer->flush_immediately_) == 0) &&
           (atomic_read32(&tracer->seq_no_) -
              atomic_read32(&tracer->flushed_)
              <= tracer->flush_threshold_))
    {
      tracer->GetTimespecRel(2000, &timeout);
      retval = pthread_cond_timedwait(&tracer->sig_flush_,
                                      &tracer->sig_flush_mutex_,
                                      &timeout);
      assert(retval != EINVAL);
    }

    int base = atomic_read32(&tracer->flushed_) % tracer->buffer_size_;
    int pos, i = 0;
    while ((i <= tracer->flush_threshold_) &&
           (atomic_read32(&tracer->commit_buffer_[
             pos = ((base + i) % tracer->buffer_size_)]) == 1))
    {
      string tmp;
      tmp = StringifyTimeval(tracer->ring_buffer_[pos].time_stamp);
      retval = tracer->WriteCsvFile(f, tmp);
      retval |= fputc(',', f) - ',';
      tmp = StringifyInt(tracer->ring_buffer_[pos].code);
      retval = tracer->WriteCsvFile(f, tmp);
      retval |= fputc(',', f) - ',';
      retval |= tracer->WriteCsvFile(
        f, tracer->ring_buffer_[pos].path.ToString());
      retval |= fputc(',', f) - ',';
      retval |= tracer->WriteCsvFile(f, tracer->ring_buffer_[pos].msg);
      retval |= (fputc(13, f) - 13) | (fputc(10, f) - 10);
      assert(retval == 0);

      atomic_dec32(&tracer->commit_buffer_[pos]);
      ++i;
    }
    retval = fflush(f);
    assert(retval == 0);
    atomic_xadd32(&tracer->flushed_, i);
    atomic_cas32(&tracer->flush_immediately_, 1, 0);

    LockMutex(&tracer->sig_continue_trace_mutex_);
    retval = pthread_cond_broadcast(&tracer->sig_continue_trace_);
    assert(retval == 0);
    UnlockMutex(&tracer->sig_continue_trace_mutex_);
  } while ((atomic_read32(&tracer->terminate_flush_thread_) == 0) ||
           (atomic_read32(&tracer->flushed_) <
             atomic_read32(&tracer->seq_no_)));

  UnlockMutex(&tracer->sig_flush_mutex_);
  retval = fclose(f);
  assert(retval == 0);
  return NULL;
}

void Tracer::Spawn() {
  if (active_) {
    int retval = pthread_create(&thread_flush_, NULL, MainFlush, this);
    assert(retval == 0);

    spawned_ = true;
    DoTrace(kEventStart, PathString("Tracer", 6), "Trace buffer created");
  }
}

Tracer::Tracer()
  : active_(false)
  , spawned_(false)
  , buffer_size_(0)
  , flush_threshold_(0)
  , ring_buffer_(NULL)
  , commit_buffer_(NULL)
{
  memset(&thread_flush_, 0, sizeof(thread_flush_));
  atomic_init32(&seq_no_);
  atomic_init32(&flushed_);
  atomic_init32(&terminate_flush_thread_);
  atomic_init32(&flush_immediately_);
}

Tracer::~Tracer() {
  if (!active_)
    return;
  int retval;

  if (spawned_) {
    DoTrace(kEventStop, PathString("Tracer", 6), "Destroying trace buffer...");

    // Trigger flushing and wait for it
    atomic_inc32(&terminate_flush_thread_);
    LockMutex(&sig_flush_mutex_);
    retval = pthread_cond_signal(&sig_flush_);
    assert(retval == 0);
    UnlockMutex(&sig_flush_mutex_);
    retval = pthread_join(thread_flush_, NULL);
    assert(retval == 0);
  }

  retval = pthread_cond_destroy(&sig_continue_trace_);
  retval |= pthread_mutex_destroy(&sig_continue_trace_mutex_);
  retval |= pthread_cond_destroy(&sig_flush_);
  retval |= pthread_mutex_destroy(&sig_flush_mutex_);
  assert(retval == 0);

  delete[] ring_buffer_;
  delete[] commit_buffer_;
}

int Tracer::WriteCsvFile(FILE *fp, const string &field) {
  if (fp == NULL)
    return 0;

  int retval;

  if ((retval = fputc('"', fp)) != '"')
    return retval;

  for (unsigned i = 0, l = field.length(); i < l; ++i) {
    if (field[i] == '"') {
      if ((retval = fputc('"', fp)) != '"')
        return retval;
    }
    if ((retval = fputc(field[i], fp)) != field[i])
      return retval;
  }

  if ((retval = fputc('"', fp)) != '"')
    return retval;

  return 0;
}
<commit_msg>remove raw mutex from tracer.cc<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "tracer.h"

#include <pthread.h>

#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

#include "atomic.h"
#include "util/posix.h"
#include "util/string.h"
#include "util_concurrency.h"

using namespace std;  // NOLINT

void Tracer::Activate(
  const int buffer_size,
  const int flush_threshold,
  const string &trace_file)
{
  trace_file_ = trace_file;
  buffer_size_ = buffer_size;
  flush_threshold_ = flush_threshold;
  assert(buffer_size_ > 1 && flush_threshold_>= 0
    && flush_threshold_ < buffer_size_);

  ring_buffer_ = new BufferEntry[buffer_size_];
  commit_buffer_ = new atomic_int32[buffer_size_];
  for (int i = 0; i < buffer_size_; i++)
    atomic_init32(&commit_buffer_[i]);

  int retval;
  retval = pthread_cond_init(&sig_continue_trace_, NULL);
  retval |= pthread_mutex_init(&sig_continue_trace_mutex_, NULL);
  retval |= pthread_cond_init(&sig_flush_, NULL);
  retval |= pthread_mutex_init(&sig_flush_mutex_, NULL);
  assert(retval == 0);

  active_ = true;
}

/**
 * Trace a message.  This is usually a lock-free procedure that just
 * requires two fetch_and_add operations and a gettimeofday syscall.
 * There are two exceptions:
 *   -# If the ring buffer is full, the function blocks until the flush
 *      thread made some space.  Avoid that by carefully choosing size
 *      and threshold.
 *   -# If this message reaches the threshold, the flush thread gets
 *      signaled.
 *
 * \param[in] event Arbitrary code, for consistency applications should use one
 *            of the TraceEvents constants. Negative codes are reserved
 *            for internal use.
 * \param[in] id Arbitrary id, for example file name or module name which is
 *            doing the trace.
 * \return The sequence number which was used to trace the record
 */
int32_t Tracer::DoTrace(
  const int event,
  const PathString &path,
  const string &msg)
{
  int32_t my_seq_no = atomic_xadd32(&seq_no_, 1);
  timeval now;
  gettimeofday(&now, NULL);
  int pos = my_seq_no % buffer_size_;

  while (my_seq_no - atomic_read32(&flushed_) >= buffer_size_) {
    timespec timeout;
    int retval;
    GetTimespecRel(25, &timeout);
    retval = pthread_mutex_lock(&sig_continue_trace_mutex_);
    retval |= pthread_cond_timedwait(&sig_continue_trace_,
                                     &sig_continue_trace_mutex_, &timeout);
    retval |= pthread_mutex_unlock(&sig_continue_trace_mutex_);
    assert(retval == ETIMEDOUT || retval == 0);
  }

  ring_buffer_[pos].time_stamp = now;
  ring_buffer_[pos].code = event;
  ring_buffer_[pos].path = path;
  ring_buffer_[pos].msg = msg;
  atomic_inc32(&commit_buffer_[pos]);

  if (my_seq_no - atomic_read32(&flushed_) == flush_threshold_) {
    MutexLockGuard m(&sig_flush_mutex_);
    int err_code __attribute__((unused)) = pthread_cond_signal(&sig_flush_);
    assert(err_code == 0 && "Could not signal flush thread");
  }

  return my_seq_no;
}

void Tracer::Flush() {
  if (!active_) return;

  int32_t save_seq_no = DoTrace(kEventFlush, PathString("Tracer", 6),
                                "flushed ring buffer");
  while (atomic_read32(&flushed_) <= save_seq_no) {
    timespec timeout;
    int retval;

    atomic_cas32(&flush_immediately_, 0, 1);
    {
      MutexLockGuard m(&sig_flush_mutex_);
      retval = pthread_cond_signal(&sig_flush_);
      assert(retval == 0);
    }

    GetTimespecRel(250, &timeout);
    retval = pthread_mutex_lock(&sig_continue_trace_mutex_);
    retval |= pthread_cond_timedwait(&sig_continue_trace_,
                                     &sig_continue_trace_mutex_,
                                     &timeout);
    retval |= pthread_mutex_unlock(&sig_continue_trace_mutex_);
    assert(retval == ETIMEDOUT || retval == 0);
  }
}

void Tracer::GetTimespecRel(const int64_t ms, timespec *ts) {
  timeval now;
  gettimeofday(&now, NULL);
  int64_t nsecs = now.tv_usec * 1000 + (ms % 1000)*1000*1000;
  int carry = 0;
  if (nsecs >= 1000*1000*1000) {
    carry = 1;
    nsecs -= 1000*1000*1000;
  }
  ts->tv_sec = now.tv_sec + ms/1000 + carry;
  ts->tv_nsec = nsecs;
}

void *Tracer::MainFlush(void *data) {
  Tracer *tracer = reinterpret_cast<Tracer *>(data);
  int retval;
  MutexLockGuard m(&tracer->sig_flush_mutex_);
  FILE *f = fopen(tracer->trace_file_.c_str(), "a");
  assert(f != NULL && "Could not open trace file");
  struct timespec timeout;

  do {
    while ((atomic_read32(&tracer->terminate_flush_thread_) == 0) &&
           (atomic_read32(&tracer->flush_immediately_) == 0) &&
           (atomic_read32(&tracer->seq_no_) -
              atomic_read32(&tracer->flushed_)
              <= tracer->flush_threshold_))
    {
      tracer->GetTimespecRel(2000, &timeout);
      retval = pthread_cond_timedwait(&tracer->sig_flush_,
                                      &tracer->sig_flush_mutex_,
                                      &timeout);
      assert(retval != EINVAL);
    }

    int base = atomic_read32(&tracer->flushed_) % tracer->buffer_size_;
    int pos, i = 0;
    while ((i <= tracer->flush_threshold_) &&
           (atomic_read32(&tracer->commit_buffer_[
             pos = ((base + i) % tracer->buffer_size_)]) == 1))
    {
      string tmp;
      tmp = StringifyTimeval(tracer->ring_buffer_[pos].time_stamp);
      retval = tracer->WriteCsvFile(f, tmp);
      retval |= fputc(',', f) - ',';
      tmp = StringifyInt(tracer->ring_buffer_[pos].code);
      retval = tracer->WriteCsvFile(f, tmp);
      retval |= fputc(',', f) - ',';
      retval |= tracer->WriteCsvFile(
        f, tracer->ring_buffer_[pos].path.ToString());
      retval |= fputc(',', f) - ',';
      retval |= tracer->WriteCsvFile(f, tracer->ring_buffer_[pos].msg);
      retval |= (fputc(13, f) - 13) | (fputc(10, f) - 10);
      assert(retval == 0);

      atomic_dec32(&tracer->commit_buffer_[pos]);
      ++i;
    }
    retval = fflush(f);
    assert(retval == 0);
    atomic_xadd32(&tracer->flushed_, i);
    atomic_cas32(&tracer->flush_immediately_, 1, 0);

    {
      MutexLockGuard l(&tracer->sig_continue_trace_mutex_);
      retval = pthread_cond_broadcast(&tracer->sig_continue_trace_);
      assert(retval == 0);
    }
  } while ((atomic_read32(&tracer->terminate_flush_thread_) == 0) ||
           (atomic_read32(&tracer->flushed_) <
             atomic_read32(&tracer->seq_no_)));

  retval = fclose(f);
  assert(retval == 0);
  return NULL;
}

void Tracer::Spawn() {
  if (active_) {
    int retval = pthread_create(&thread_flush_, NULL, MainFlush, this);
    assert(retval == 0);

    spawned_ = true;
    DoTrace(kEventStart, PathString("Tracer", 6), "Trace buffer created");
  }
}

Tracer::Tracer()
  : active_(false)
  , spawned_(false)
  , buffer_size_(0)
  , flush_threshold_(0)
  , ring_buffer_(NULL)
  , commit_buffer_(NULL)
{
  memset(&thread_flush_, 0, sizeof(thread_flush_));
  atomic_init32(&seq_no_);
  atomic_init32(&flushed_);
  atomic_init32(&terminate_flush_thread_);
  atomic_init32(&flush_immediately_);
}

Tracer::~Tracer() {
  if (!active_)
    return;
  int retval;

  if (spawned_) {
    DoTrace(kEventStop, PathString("Tracer", 6), "Destroying trace buffer...");

    // Trigger flushing and wait for it
    atomic_inc32(&terminate_flush_thread_);
    {
      MutexLockGuard m(&sig_flush_mutex_);
      retval = pthread_cond_signal(&sig_flush_);
      assert(retval == 0);
    }
    retval = pthread_join(thread_flush_, NULL);
    assert(retval == 0);
  }

  retval = pthread_cond_destroy(&sig_continue_trace_);
  retval |= pthread_mutex_destroy(&sig_continue_trace_mutex_);
  retval |= pthread_cond_destroy(&sig_flush_);
  retval |= pthread_mutex_destroy(&sig_flush_mutex_);
  assert(retval == 0);

  delete[] ring_buffer_;
  delete[] commit_buffer_;
}

int Tracer::WriteCsvFile(FILE *fp, const string &field) {
  if (fp == NULL)
    return 0;

  int retval;

  if ((retval = fputc('"', fp)) != '"')
    return retval;

  for (unsigned i = 0, l = field.length(); i < l; ++i) {
    if (field[i] == '"') {
      if ((retval = fputc('"', fp)) != '"')
        return retval;
    }
    if ((retval = fputc(field[i], fp)) != field[i])
      return retval;
  }

  if ((retval = fputc('"', fp)) != '"')
    return retval;

  return 0;
}
<|endoftext|>


<commit_before>// Query binary phrase tables.
// Christian Hardmeier, 16 May 2010

#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

#include "util.h"
#include "OnDiskWrapper.h"
#include "SourcePhrase.h"

using namespace std;
using namespace OnDiskPt;

void usage();

typedef unsigned int uint;

void Tokenize(OnDiskPt::Phrase &phrase
              , const std::string &token, bool addSourceNonTerm, bool addTargetNonTerm
              , OnDiskPt::OnDiskWrapper &onDiskWrapper)
{

  bool nonTerm = false;
  size_t tokSize = token.size();
  int comStr =token.compare(0, 1, "[");

  if (comStr == 0) {
    comStr = token.compare(tokSize - 1, 1, "]");
    nonTerm = comStr == 0;
  }

  if (nonTerm) {
    // non-term
    size_t splitPos		= token.find_first_of("[", 2);
    string wordStr	= token.substr(0, splitPos);

    if (splitPos == string::npos) {
      // lhs - only 1 word
      Word *word = new Word();
      word->CreateFromString(wordStr, onDiskWrapper.GetVocab());
      phrase.AddWord(word);
    } else {
      // source & target non-terms
      if (addSourceNonTerm) {
        Word *word = new Word();
        word->CreateFromString(wordStr, onDiskWrapper.GetVocab());
        phrase.AddWord(word);
      }

      wordStr = token.substr(splitPos, tokSize - splitPos);
      if (addTargetNonTerm) {
        Word *word = new Word();
        word->CreateFromString(wordStr, onDiskWrapper.GetVocab());
        phrase.AddWord(word);
      }

    }
  } else {
    // term
    Word *word = new Word();
    word->CreateFromString(token, onDiskWrapper.GetVocab());
    phrase.AddWord(word);
  }
}

int main(int argc, char **argv)
{
  int tableLimit = 20;
  std::string ttable = "";
  bool useAlignments = false;

  for(int i = 1; i < argc; i++) {
    if(!strcmp(argv[i], "-tlimit")) {
      if(i + 1 == argc)
        usage();
      tableLimit = atoi(argv[++i]);
    } else if(!strcmp(argv[i], "-t")) {
      if(i + 1 == argc)
        usage();
      ttable = argv[++i];
    }
    else
      usage();
  }

  if(ttable == "")
    usage();

	OnDiskWrapper onDiskWrapper;
  bool retDb = onDiskWrapper.BeginLoad(ttable);
	CHECK(retDb);

	cerr << "Ready..." << endl;

  std::string line;
  while(getline(std::cin, line)) {
    std::vector<std::string> tokens;
    tokens = Moses::Tokenize(line, " ");

		cerr << "line: " << line << endl;

		// create source phrase
    SourcePhrase sourcePhrase;

		for (size_t pos = 0; pos < tokens.size(); ++pos)
		{
		  const string &tok = tokens[pos];

		  if (pos == tokens.size() - 1)
		  { // last position. LHS non-term
			  Tokenize(sourcePhrase, tok, false, true, onDiskWrapper);
			}
			else
			{
			  Tokenize(sourcePhrase, tok, true, true, onDiskWrapper);
			}
		}

    const PhraseNode *node = &onDiskWrapper.GetRootSourceNode();
		cerr << "node=" << node << endl;
    assert(node);

    for (size_t pos = 0; pos < sourcePhrase.GetSize(); ++pos)
		{
		  const Word &word = sourcePhrase.GetWord(pos);
		  cerr << word << " ";
		  node = node->GetChild(word, onDiskWrapper);
  		cerr << "node=" << node << endl;

		  if (node == NULL)
		  {
		    break;
		  }
		}

    if (node)
    { // source phrase points to a bunch of rules
      const TargetPhraseCollection *coll = node->GetTargetPhraseCollection(tableLimit, onDiskWrapper);
      string str = coll->GetDebugStr();
      cout << "Found " << coll->GetSize() << endl;

      for (size_t ind = 0; ind < coll->GetSize(); ++ind)
      {
        const TargetPhrase &targetPhrase = coll->GetTargetPhrase(ind);
        cerr << "  ";
        targetPhrase.DebugPrint(cerr, onDiskWrapper.GetVocab());
        cerr << endl;

      }
    }
    else
    {
      cout << "Not found" << endl;
    }

    std::cout << '\n';
    std::cout.flush();
  }

  cerr << "Finished." << endl;

}

void usage()
{
  std::cerr << 	"Usage: queryOnDiskPt [-n <nscores>] [-a] -t <ttable>\n"
            "-tlimit <table limit>      max number of rules per source phrase (default: 20)\n"
            "-t <ttable>       phrase table\n";
  exit(1);
}
<commit_msg>Fix compile error.<commit_after>// Query binary phrase tables.
// Christian Hardmeier, 16 May 2010

#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

#include "Util.h"
#include "OnDiskWrapper.h"
#include "SourcePhrase.h"

using namespace std;
using namespace OnDiskPt;

void usage();

typedef unsigned int uint;

void Tokenize(OnDiskPt::Phrase &phrase
              , const std::string &token, bool addSourceNonTerm, bool addTargetNonTerm
              , OnDiskPt::OnDiskWrapper &onDiskWrapper)
{

  bool nonTerm = false;
  size_t tokSize = token.size();
  int comStr =token.compare(0, 1, "[");

  if (comStr == 0) {
    comStr = token.compare(tokSize - 1, 1, "]");
    nonTerm = comStr == 0;
  }

  if (nonTerm) {
    // non-term
    size_t splitPos		= token.find_first_of("[", 2);
    string wordStr	= token.substr(0, splitPos);

    if (splitPos == string::npos) {
      // lhs - only 1 word
      Word *word = new Word();
      word->CreateFromString(wordStr, onDiskWrapper.GetVocab());
      phrase.AddWord(word);
    } else {
      // source & target non-terms
      if (addSourceNonTerm) {
        Word *word = new Word();
        word->CreateFromString(wordStr, onDiskWrapper.GetVocab());
        phrase.AddWord(word);
      }

      wordStr = token.substr(splitPos, tokSize - splitPos);
      if (addTargetNonTerm) {
        Word *word = new Word();
        word->CreateFromString(wordStr, onDiskWrapper.GetVocab());
        phrase.AddWord(word);
      }

    }
  } else {
    // term
    Word *word = new Word();
    word->CreateFromString(token, onDiskWrapper.GetVocab());
    phrase.AddWord(word);
  }
}

int main(int argc, char **argv)
{
  int tableLimit = 20;
  std::string ttable = "";
  bool useAlignments = false;

  for(int i = 1; i < argc; i++) {
    if(!strcmp(argv[i], "-tlimit")) {
      if(i + 1 == argc)
        usage();
      tableLimit = atoi(argv[++i]);
    } else if(!strcmp(argv[i], "-t")) {
      if(i + 1 == argc)
        usage();
      ttable = argv[++i];
    }
    else
      usage();
  }

  if(ttable == "")
    usage();

	OnDiskWrapper onDiskWrapper;
  bool retDb = onDiskWrapper.BeginLoad(ttable);
	CHECK(retDb);

	cerr << "Ready..." << endl;

  std::string line;
  while(getline(std::cin, line)) {
    std::vector<std::string> tokens;
    tokens = Moses::Tokenize(line, " ");

		cerr << "line: " << line << endl;

		// create source phrase
    SourcePhrase sourcePhrase;

		for (size_t pos = 0; pos < tokens.size(); ++pos)
		{
		  const string &tok = tokens[pos];

		  if (pos == tokens.size() - 1)
		  { // last position. LHS non-term
			  Tokenize(sourcePhrase, tok, false, true, onDiskWrapper);
			}
			else
			{
			  Tokenize(sourcePhrase, tok, true, true, onDiskWrapper);
			}
		}

    const PhraseNode *node = &onDiskWrapper.GetRootSourceNode();
		cerr << "node=" << node << endl;
    assert(node);

    for (size_t pos = 0; pos < sourcePhrase.GetSize(); ++pos)
		{
		  const Word &word = sourcePhrase.GetWord(pos);
		  cerr << word << " ";
		  node = node->GetChild(word, onDiskWrapper);
  		cerr << "node=" << node << endl;

		  if (node == NULL)
		  {
		    break;
		  }
		}

    if (node)
    { // source phrase points to a bunch of rules
      const TargetPhraseCollection *coll = node->GetTargetPhraseCollection(tableLimit, onDiskWrapper);
      string str = coll->GetDebugStr();
      cout << "Found " << coll->GetSize() << endl;

      for (size_t ind = 0; ind < coll->GetSize(); ++ind)
      {
        const TargetPhrase &targetPhrase = coll->GetTargetPhrase(ind);
        cerr << "  ";
        targetPhrase.DebugPrint(cerr, onDiskWrapper.GetVocab());
        cerr << endl;

      }
    }
    else
    {
      cout << "Not found" << endl;
    }

    std::cout << '\n';
    std::cout.flush();
  }

  cerr << "Finished." << endl;

}

void usage()
{
  std::cerr << 	"Usage: queryOnDiskPt [-n <nscores>] [-a] -t <ttable>\n"
            "-tlimit <table limit>      max number of rules per source phrase (default: 20)\n"
            "-t <ttable>       phrase table\n";
  exit(1);
}
<|endoftext|>


<commit_before>/*
 * server_test.cpp
 *
 *  Created on: Jan 16, 2013
 *      Author: mfleder
 */

#include <stdio.h>
#include <boost/shared_ptr.hpp>
#include "affordance/AffordanceState.h"
//#include "affordance/OpenGL_Affordance.h"
#include <iostream>

using namespace boost;
using namespace std;
using namespace affordance;

int main(int argc, char ** argv)
{
   //create affordance cylinder objects
   AffPtr c(new AffordanceState());
   c->setToCylinder(4, 0.18,
                    0,0, //uid/map id.
                    KDL::Frame(KDL::Vector(0,0,1)),
                    Eigen::Vector3f(0,1,0));
   cout << "\nOriginal Cylinder:\n" << *c << endl;

   //convert to LCM message
   drc::affordance_t msg;
   c->toMsg(&msg);

   //get the raw bytes of the message
   void* buffer = malloc(msg.getEncodedSize());
   msg.encode(buffer, 0, msg.getEncodedSize());

   //convert to lcm::LogEvent
   lcm::LogEvent logEvent;
   logEvent.eventnum = 0;
   logEvent.timestamp = 0;
   logEvent.channel = "test_channel";
   logEvent.datalen = msg.getEncodedSize();
   logEvent.data = buffer;

   //write to disk
   //'w' for write
   lcm::LogFile *lFileWriter = new lcm::LogFile("lcm_io_test_save.bin", "w");
   lFileWriter->writeEvent(&logEvent);
   delete lFileWriter;

   //read from disk
   //'r' for read
   lcm::LogFile *lFileReader = new lcm::LogFile("lcm_io_test_save.bin", "r");
   const lcm::LogEvent* eventFromFile = lFileReader->readNextEvent();

   //construct message from raw bytes
   drc::affordance_t msgFromFile;
   msgFromFile.decode(eventFromFile->data, 0, eventFromFile->datalen);

   //now convert back to an AffordanceStateObject
   AffPtr cylinderFromFile(new AffordanceState());
   cylinderFromFile->fromMsg(&msgFromFile);

   cout << "\n\n=====Read from file:\n" << *cylinderFromFile << endl;

   return 0;
}
<commit_msg>updated test<commit_after>/*
 * server_test.cpp
 *
 *  Created on: Jan 16, 2013
 *      Author: mfleder
 */

#include <stdio.h>
#include <boost/shared_ptr.hpp>
#include "affordance/AffordanceState.h"
//#include "affordance/OpenGL_Affordance.h"
#include <iostream>

using namespace boost;
using namespace std;
using namespace affordance;

int main(int argc, char ** argv)
{
   //create affordance cylinder objects
   AffPtr c(new AffordanceState());
   c->setToCylinder(4, 0.18,
                    0,0, //uid/map id.
                    KDL::Frame(KDL::Vector(0,0,1)),
                    Eigen::Vector3f(0,1,0));
   cout << "\nOriginal Cylinder:\n" << *c << endl;

   //convert to LCM message
   drc::affordance_t msg;
   c->toMsg(&msg);

   //get the raw bytes of the message
   void* buffer = malloc(msg.getEncodedSize());
   msg.encode(buffer, 0, msg.getEncodedSize());

   //convert to lcm::LogEvent
   lcm::LogEvent logEvent;
   logEvent.eventnum = 0;
   logEvent.timestamp = 0;
   logEvent.channel = "test_channel";
   logEvent.datalen = msg.getEncodedSize();
   logEvent.data = buffer;

   //write to disk
   //'w' for write
   lcm::LogFile *lFileWriter = new lcm::LogFile("lcm_io_test_save.bin", "w");
   lFileWriter->writeEvent(&logEvent);
   delete lFileWriter;

   //read from disk
   //'r' for read
   lcm::LogFile *lFileReader = new lcm::LogFile("lcm_io_test_save.bin", "r");
   const lcm::LogEvent* eventFromFile = lFileReader->readNextEvent();

   //construct message from raw bytes
   drc::affordance_t msgFromFile;
   msgFromFile.decode(eventFromFile->data, 0, eventFromFile->datalen);

   //NOW we can delete the lFileReader.  we couldn't delete it before
   //b/c we had a pointer to the log event it read and seems to store internally
   delete lFileReader;

   //now convert back to an AffordanceStateObject
   AffPtr cylinderFromFile(new AffordanceState());
   cylinderFromFile->fromMsg(&msgFromFile);

   cout << "\n\n=====Read from file:\n" << *cylinderFromFile << endl;

   return 0;
}
<|endoftext|>