<commit_before>/** This file is part of Contacts daemon
 **
 ** Copyright (c) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
 **
 ** Contact:  Nokia Corporation (info@qt.nokia.com)
 **
 ** 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.
 **
 ** 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.
 **/

#include "cdbirthdaycontroller.h"
#include "cdbirthdaycalendar.h"
#include "cdbirthdayplugin.h"
#include "debug.h"

#include <QDir>
#include <QFile>

#include <cubi.h>
#include <ontologies.h>

#include <QContactBirthday>
#include <QContactDetailFilter>
#include <QContactDisplayLabel>
#include <QContactFetchRequest>
#include <QContactLocalIdFilter>

QTM_USE_NAMESPACE

CUBI_USE_NAMESPACE
CUBI_USE_NAMESPACE_RESOURCES

using namespace Contactsd;

// The logic behind this class was strongly influenced by QctTrackerChangeListener in
// qtcontacts-tracker.
CDBirthdayController::CDBirthdayController(QSparqlConnection &connection,
                                           QObject *parent)
    : QObject(parent)
    , mSparqlConnection(connection)
    , mCalendar(0)
    , mManager(0)
{
    const QLatin1String trackerManagerName = QLatin1String("tracker");

    mManager = new QContactManager(trackerManagerName, QMap<QString, QString>(), this);

    if (mManager->managerName() != trackerManagerName) {
        debug() << Q_FUNC_INFO << "Tracker plugin not found";
        return;
    }

    fetchTrackerIds();

    if (not stampFileExists()) {
        // Delete the calendar database.
        mCalendar = new CDBirthdayCalendar(CDBirthdayCalendar::FullSync, this);

        updateAllBirthdays();
    } else {
        // Use the existing calendar database.
        mCalendar = new CDBirthdayCalendar(CDBirthdayCalendar::Incremental, this);
    }
}

CDBirthdayController::~CDBirthdayController()
{
}

void
CDBirthdayController::fetchTrackerIds()
{
    // keep in sync with the enum in the header and NTrackerIds
    const QList<ResourceValue> resources = QList<ResourceValue>()
                                           << nco::birthDate::resource()
                                           << rdf::type::resource()
                                           << nco::PersonContact::resource()
                                           << nco::ContactGroup::resource();

    Select select;

    foreach (const ResourceValue &value, resources) {
        select.addProjection(Functions::trackerId.apply(value));
    }

    if (not mSparqlConnection.isValid()) {
        debug() << Q_FUNC_INFO << "SPARQL connection is not valid";
        return;
    }

    QScopedPointer<QSparqlResult> result(mSparqlConnection.exec(QSparqlQuery(select.sparql())));

    if (result->hasError()) {
        debug() << Q_FUNC_INFO << "Could not fetch Tracker IDs:" << result->lastError().message();
        return;
    }

    connect(result.take(), SIGNAL(finished()), this, SLOT(onTrackerIdsFetched()));
}

bool CDBirthdayController::stampFileExists()
{
    const QFile cacheFile(stampFilePath(), this);

    return cacheFile.exists();
}

void CDBirthdayController::createStampFile()
{
    QFile cacheFile(stampFilePath(), this);

    if (not cacheFile.exists()) {
        if (not cacheFile.open(QIODevice::WriteOnly)) {
            warning() << Q_FUNC_INFO << "Unable to create birthday plugin stamp file "
                                     << cacheFile.fileName() << " with error " << cacheFile.errorString();
        } else {
            cacheFile.close();
        }
    }
}

QString CDBirthdayController::stampFilePath() const
{
    return BasePlugin::cacheFileName(QLatin1String("calendar.stamp"));
}

void
CDBirthdayController::updateAllBirthdays()
{
    QContactFetchHint fetchHint;
    static const QStringList detailDefinitions = QStringList() << QContactBirthday::DefinitionName
                                                               << QContactDisplayLabel::DefinitionName;
    fetchHint.setDetailDefinitionsHint(detailDefinitions);

    // Filter on any contact with a birthday.
    QContactDetailFilter fetchFilter;
    fetchFilter.setDetailDefinitionName(QContactBirthday::DefinitionName);

    QContactFetchRequest * const fetchRequest = new QContactFetchRequest(this);
    fetchRequest->setManager(mManager);
    fetchRequest->setFetchHint(fetchHint);
    fetchRequest->setFilter(fetchFilter);

    connect(fetchRequest,
            SIGNAL(stateChanged(QContactAbstractRequest::State)),
            SLOT(onFullSyncRequestStateChanged(QContactAbstractRequest::State)));

    if (not fetchRequest->start()) {
        warning() << Q_FUNC_INFO << "Unable to start contact birthdays fetch request";
        delete fetchRequest;
        return;
    }

    debug() << "Contact birthdays fetch request started";
}

void
CDBirthdayController::onTrackerIdsFetched()
{
    QSparqlResult *result = qobject_cast<QSparqlResult*>(sender());

    if (result == 0) {
        debug() << Q_FUNC_INFO << "Invalid result";
        return;
    }

    if (result->hasError()) {
        debug() << Q_FUNC_INFO << "Could not fetch Tracker IDs:" << result->lastError().message();
    } else if (not result->next()) {
        debug() << Q_FUNC_INFO << "No results returned";
        return;
    } else {
        const QSparqlResultRow row = result->current();

        for (int i = 0; i < NTrackerIds; ++i) {
            mTrackerIds[i] = row.value(i).toInt();
        }
    }

    // Provide hint we are done with this result.
    result->deleteLater();

    debug() << Q_FUNC_INFO << "Tracker IDs fetched, connecting the change notifier";

    connectChangeNotifier();
}

void
CDBirthdayController::connectChangeNotifier()
{
    const QStringList contactClassIris = QStringList()
                                      << nco::PersonContact::iri()
                                      << nco::ContactGroup::iri();

    foreach (const QString &iri, contactClassIris) {
        connect(new TrackerChangeNotifier(iri, this),
            SIGNAL(changed(QList<TrackerChangeNotifier::Quad>,
                           QList<TrackerChangeNotifier::Quad>)),
            SLOT(onGraphChanged(QList<TrackerChangeNotifier::Quad>,
                                QList<TrackerChangeNotifier::Quad>)));
    }
}

void CDBirthdayController::onGraphChanged(const QList<TrackerChangeNotifier::Quad>& deletions,
                                          const QList<TrackerChangeNotifier::Quad>& insertions)
{
    mDeleteNotifications += deletions;
    mInsertNotifications += insertions;

    if (isDebugEnabled()) {
        TrackerChangeNotifier const * const notifier = qobject_cast<TrackerChangeNotifier *>(sender());

        if (notifier == 0) {
            warning() << Q_FUNC_INFO << "Error casting birthday change notifier";
            return;
        }

        debug() << notifier->watchedClass() << "birthday: deletions:" << deletions;
        debug() << notifier->watchedClass() << "birthday: insertions:" << insertions;
    }

    processNotificationQueues();
}

void
CDBirthdayController::onFullSyncRequestStateChanged(QContactAbstractRequest::State newState)
{
    QContactFetchRequest * const fetchRequest = qobject_cast<QContactFetchRequest*>(sender());

    if (not processFetchRequest(fetchRequest, newState)) {
        return;
    }

    updateBirthdays(fetchRequest->contacts());

    // Create the stamp file only after a successful full sync.
    createStampFile();
}

void
CDBirthdayController::onFetchRequestStateChanged(QContactAbstractRequest::State newState)
{
    QContactFetchRequest * const fetchRequest = qobject_cast<QContactFetchRequest*>(sender());

    if (not processFetchRequest(fetchRequest, newState)) {
        return;
    }

    updateBirthdays(fetchRequest->contacts());
}

bool
CDBirthdayController::processFetchRequest(QContactFetchRequest * const fetchRequest,
                                          QContactAbstractRequest::State newState)
{
    if (fetchRequest == 0) {
        warning() << Q_FUNC_INFO << "Invalid fetch request";
        return false;
    }

    bool success = false;

    switch (newState) {
    case QContactAbstractRequest::FinishedState:
        debug() << "Birthday contacts fetch request finished";

        if (fetchRequest->error() != QContactManager::NoError) {
            warning() << Q_FUNC_INFO << "Error during birthday contact fetch request, code: "
                      << fetchRequest->error();
        } else {
            success = true;
        }

        break;

    case QContactAbstractRequest::CanceledState:
        break;

    default:
        return false;
    }

    // Provide hint we are done with this request.
    fetchRequest->deleteLater();

    return success;
}

void
CDBirthdayController::processNotificationQueues()
{
    QSet<QContactLocalId> insertedContacts;
    QSet<QContactLocalId> deletedContacts;
    QSet<QContactLocalId> birthdayChangedIds;

    // Process notification queues to determine contacts with changed birthdays.
    processNotifications(mDeleteNotifications, birthdayChangedIds, deletedContacts);
    processNotifications(mInsertNotifications, birthdayChangedIds, insertedContacts);

    if (isDebugEnabled()) {
        debug() << "changed birthdates: " << birthdayChangedIds.count() << birthdayChangedIds;
    }

    // Remove the birthdays for contacts that are not there anymore
    foreach (QContactLocalId id, deletedContacts) {
        mCalendar->deleteBirthday(id);
    }

    // Update the calendar with the birthday changes.
    if (not birthdayChangedIds.isEmpty()) {
        fetchContacts(birthdayChangedIds.toList());
    }
}

void
CDBirthdayController::processNotifications(QList<TrackerChangeNotifier::Quad> &notifications,
                                           QSet<QContactLocalId> &propertyChanges,
                                           QSet<QContactLocalId> &resourceChanges)
{
    foreach (const TrackerChangeNotifier::Quad &quad, notifications) {
        if (quad.predicate == mTrackerIds[NcoBirthDate]) {
            propertyChanges += quad.subject;
            continue;
        }

        if (quad.predicate == mTrackerIds[RdfType]) {
            if (quad.object == mTrackerIds[NcoPersonContact]
             || quad.object == mTrackerIds[NcoContactGroup]) {
                resourceChanges += quad.subject;
            }
        }
    }

    // Remove the processed notifications.
    notifications.clear();
}

void
CDBirthdayController::fetchContacts(const QList<QContactLocalId> &contactIds)
{
    QContactFetchHint fetchHint;
    static const QStringList detailDefinitions = QStringList() << QContactBirthday::DefinitionName
                                                               << QContactDisplayLabel::DefinitionName;
    fetchHint.setDetailDefinitionsHint(detailDefinitions);

    QContactLocalIdFilter fetchFilter;
    fetchFilter.setIds(contactIds);

    QContactFetchRequest * const fetchRequest = new QContactFetchRequest(this);
    fetchRequest->setManager(mManager);
    fetchRequest->setFetchHint(fetchHint);
    fetchRequest->setFilter(fetchFilter);

    connect(fetchRequest,
            SIGNAL(stateChanged(QContactAbstractRequest::State)),
            SLOT(onFetchRequestStateChanged(QContactAbstractRequest::State)));

    if (not fetchRequest->start()) {
        warning() << Q_FUNC_INFO << "Unable to start birthday contact fetch request";
        delete fetchRequest;
        return;
    }

    debug() << "Birthday contacts fetch request started";
}

void
CDBirthdayController::updateBirthdays(const QList<QContact> &changedBirthdays)
{
    foreach (const QContact &contact, changedBirthdays) {
        const QContactBirthday contactBirthday = contact.detail<QContactBirthday>();
        const QContactDisplayLabel contactDisplayLabel = contact.detail<QContactDisplayLabel>();
        const QDate calendarBirthday = mCalendar->birthdayDate(contact.localId());
        const QString calendarSummary = mCalendar->summary(contact.localId());

        // Display label or birthdate was removed from the contact, so delete it from the calendar.
        if (contactDisplayLabel.label().isNull() || contactBirthday.date().isNull()) {
            if (isDebugEnabled()) {
                debug() << "Contact: " << contact << " removed birthday or displayLabel, so delete the calendar event";
            }

            mCalendar->deleteBirthday(contact.localId());
        // Display label or birthdate was changed on the contact, so update the calendar.
        } else if ((contactDisplayLabel.label() != calendarSummary) ||
                   (contactBirthday.date() != calendarBirthday)) {
            if (isDebugEnabled()) {
                debug() << "Contact with calendar birthday: " << contactBirthday.date()
                        << " and calendar displayLabel: " << calendarSummary
                        << " changed details to: " << contact << ", so update the calendar event";
            }

            mCalendar->updateBirthday(contact);
        }
    }
}
<commit_msg>Fixes: Reorder birthday controller methods to have a chance understanding it<commit_after>/** This file is part of Contacts daemon
 **
 ** Copyright (c) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
 **
 ** Contact:  Nokia Corporation (info@qt.nokia.com)
 **
 ** 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.
 **
 ** 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.
 **/

#include "cdbirthdaycontroller.h"
#include "cdbirthdaycalendar.h"
#include "cdbirthdayplugin.h"
#include "debug.h"

#include <QDir>
#include <QFile>

#include <cubi.h>
#include <ontologies.h>

#include <QContactBirthday>
#include <QContactDetailFilter>
#include <QContactDisplayLabel>
#include <QContactFetchRequest>
#include <QContactLocalIdFilter>

QTM_USE_NAMESPACE

CUBI_USE_NAMESPACE
CUBI_USE_NAMESPACE_RESOURCES

using namespace Contactsd;

// The logic behind this class was strongly influenced by QctTrackerChangeListener in
// qtcontacts-tracker.
CDBirthdayController::CDBirthdayController(QSparqlConnection &connection,
                                           QObject *parent)
    : QObject(parent)
    , mSparqlConnection(connection)
    , mCalendar(0)
    , mManager(0)
{
    const QLatin1String trackerManagerName = QLatin1String("tracker");

    mManager = new QContactManager(trackerManagerName, QMap<QString, QString>(), this);

    if (mManager->managerName() != trackerManagerName) {
        debug() << Q_FUNC_INFO << "Tracker plugin not found";
        return;
    }

    fetchTrackerIds();

    if (not stampFileExists()) {
        // Delete the calendar database.
        mCalendar = new CDBirthdayCalendar(CDBirthdayCalendar::FullSync, this);

        updateAllBirthdays();
    } else {
        // Use the existing calendar database.
        mCalendar = new CDBirthdayCalendar(CDBirthdayCalendar::Incremental, this);
    }
}

CDBirthdayController::~CDBirthdayController()
{
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Tracker ID fetching
///////////////////////////////////////////////////////////////////////////////////////////////////

void
CDBirthdayController::fetchTrackerIds()
{
    // keep in sync with the enum in the header and NTrackerIds
    const QList<ResourceValue> resources = QList<ResourceValue>()
                                           << nco::birthDate::resource()
                                           << rdf::type::resource()
                                           << nco::PersonContact::resource()
                                           << nco::ContactGroup::resource();

    Select select;

    foreach (const ResourceValue &value, resources) {
        select.addProjection(Functions::trackerId.apply(value));
    }

    if (not mSparqlConnection.isValid()) {
        debug() << Q_FUNC_INFO << "SPARQL connection is not valid";
        return;
    }

    QScopedPointer<QSparqlResult> result(mSparqlConnection.exec(QSparqlQuery(select.sparql())));

    if (result->hasError()) {
        debug() << Q_FUNC_INFO << "Could not fetch Tracker IDs:" << result->lastError().message();
        return;
    }

    connect(result.take(), SIGNAL(finished()), this, SLOT(onTrackerIdsFetched()));
}

void
CDBirthdayController::onTrackerIdsFetched()
{
    QSparqlResult *result = qobject_cast<QSparqlResult*>(sender());

    if (result == 0) {
        debug() << Q_FUNC_INFO << "Invalid result";
        return;
    }

    if (result->hasError()) {
        debug() << Q_FUNC_INFO << "Could not fetch Tracker IDs:" << result->lastError().message();
    } else if (not result->next()) {
        debug() << Q_FUNC_INFO << "No results returned";
        return;
    } else {
        const QSparqlResultRow row = result->current();

        for (int i = 0; i < NTrackerIds; ++i) {
            mTrackerIds[i] = row.value(i).toInt();
        }
    }

    // Provide hint we are done with this result.
    result->deleteLater();

    debug() << Q_FUNC_INFO << "Tracker IDs fetched, connecting the change notifier";

    connectChangeNotifier();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Contact monitor
///////////////////////////////////////////////////////////////////////////////////////////////////

void
CDBirthdayController::connectChangeNotifier()
{
    const QStringList contactClassIris = QStringList()
                                      << nco::PersonContact::iri()
                                      << nco::ContactGroup::iri();

    foreach (const QString &iri, contactClassIris) {
        connect(new TrackerChangeNotifier(iri, this),
            SIGNAL(changed(QList<TrackerChangeNotifier::Quad>,
                           QList<TrackerChangeNotifier::Quad>)),
            SLOT(onGraphChanged(QList<TrackerChangeNotifier::Quad>,
                                QList<TrackerChangeNotifier::Quad>)));
    }
}

void
CDBirthdayController::onGraphChanged(const QList<TrackerChangeNotifier::Quad>& deletions,
                                     const QList<TrackerChangeNotifier::Quad>& insertions)
{
    mDeleteNotifications += deletions;
    mInsertNotifications += insertions;

    if (isDebugEnabled()) {
        TrackerChangeNotifier const * const notifier = qobject_cast<TrackerChangeNotifier *>(sender());

        if (notifier == 0) {
            warning() << Q_FUNC_INFO << "Error casting birthday change notifier";
            return;
        }

        debug() << notifier->watchedClass() << "birthday: deletions:" << deletions;
        debug() << notifier->watchedClass() << "birthday: insertions:" << insertions;
    }

    processNotificationQueues();
}

void
CDBirthdayController::processNotifications(QList<TrackerChangeNotifier::Quad> &notifications,
                                           QSet<QContactLocalId> &propertyChanges,
                                           QSet<QContactLocalId> &resourceChanges)
{
    foreach (const TrackerChangeNotifier::Quad &quad, notifications) {
        if (quad.predicate == mTrackerIds[NcoBirthDate]) {
            propertyChanges += quad.subject;
            continue;
        }

        if (quad.predicate == mTrackerIds[RdfType]) {
            if (quad.object == mTrackerIds[NcoPersonContact]
             || quad.object == mTrackerIds[NcoContactGroup]) {
                resourceChanges += quad.subject;
            }
        }
    }

    // Remove the processed notifications.
    notifications.clear();
}

void
CDBirthdayController::processNotificationQueues()
{
    QSet<QContactLocalId> insertedContacts;
    QSet<QContactLocalId> deletedContacts;
    QSet<QContactLocalId> birthdayChangedIds;

    // Process notification queues to determine contacts with changed birthdays.
    processNotifications(mDeleteNotifications, birthdayChangedIds, deletedContacts);
    processNotifications(mInsertNotifications, birthdayChangedIds, insertedContacts);

    if (isDebugEnabled()) {
        debug() << "changed birthdates: " << birthdayChangedIds.count() << birthdayChangedIds;
    }

    // Remove the birthdays for contacts that are not there anymore
    foreach (QContactLocalId id, deletedContacts) {
        mCalendar->deleteBirthday(id);
    }

    // Update the calendar with the birthday changes.
    if (not birthdayChangedIds.isEmpty()) {
        fetchContacts(birthdayChangedIds.toList());
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Full sync logic
///////////////////////////////////////////////////////////////////////////////////////////////////

bool
CDBirthdayController::stampFileExists()
{
    const QFile cacheFile(stampFilePath(), this);

    return cacheFile.exists();
}

void
CDBirthdayController::createStampFile()
{
    QFile cacheFile(stampFilePath(), this);

    if (not cacheFile.exists()) {
        if (not cacheFile.open(QIODevice::WriteOnly)) {
            warning() << Q_FUNC_INFO << "Unable to create birthday plugin stamp file "
                                     << cacheFile.fileName() << " with error " << cacheFile.errorString();
        } else {
            cacheFile.close();
        }
    }
}

QString
CDBirthdayController::stampFilePath() const
{
    return BasePlugin::cacheFileName(QLatin1String("calendar.stamp"));
}

void
CDBirthdayController::updateAllBirthdays()
{
    QContactFetchHint fetchHint;
    static const QStringList detailDefinitions = QStringList() << QContactBirthday::DefinitionName
                                                               << QContactDisplayLabel::DefinitionName;
    fetchHint.setDetailDefinitionsHint(detailDefinitions);

    // Filter on any contact with a birthday.
    QContactDetailFilter fetchFilter;
    fetchFilter.setDetailDefinitionName(QContactBirthday::DefinitionName);

    QContactFetchRequest * const fetchRequest = new QContactFetchRequest(this);
    fetchRequest->setManager(mManager);
    fetchRequest->setFetchHint(fetchHint);
    fetchRequest->setFilter(fetchFilter);

    connect(fetchRequest,
            SIGNAL(stateChanged(QContactAbstractRequest::State)),
            SLOT(onFullSyncRequestStateChanged(QContactAbstractRequest::State)));

    if (not fetchRequest->start()) {
        warning() << Q_FUNC_INFO << "Unable to start contact birthdays fetch request";
        delete fetchRequest;
        return;
    }

    debug() << "Contact birthdays fetch request started";
}

void
CDBirthdayController::onFullSyncRequestStateChanged(QContactAbstractRequest::State newState)
{
    QContactFetchRequest * const fetchRequest = qobject_cast<QContactFetchRequest*>(sender());

    if (not processFetchRequest(fetchRequest, newState)) {
        return;
    }

    updateBirthdays(fetchRequest->contacts());

    // Create the stamp file only after a successful full sync.
    createStampFile();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Incremental sync logic
///////////////////////////////////////////////////////////////////////////////////////////////////

void
CDBirthdayController::fetchContacts(const QList<QContactLocalId> &contactIds)
{
    QContactFetchHint fetchHint;
    static const QStringList detailDefinitions = QStringList() << QContactBirthday::DefinitionName
                                                               << QContactDisplayLabel::DefinitionName;
    fetchHint.setDetailDefinitionsHint(detailDefinitions);

    QContactLocalIdFilter fetchFilter;
    fetchFilter.setIds(contactIds);

    QContactFetchRequest * const fetchRequest = new QContactFetchRequest(this);
    fetchRequest->setManager(mManager);
    fetchRequest->setFetchHint(fetchHint);
    fetchRequest->setFilter(fetchFilter);

    connect(fetchRequest,
            SIGNAL(stateChanged(QContactAbstractRequest::State)),
            SLOT(onFetchRequestStateChanged(QContactAbstractRequest::State)));

    if (not fetchRequest->start()) {
        warning() << Q_FUNC_INFO << "Unable to start birthday contact fetch request";
        delete fetchRequest;
        return;
    }

    debug() << "Birthday contacts fetch request started";
}

void
CDBirthdayController::onFetchRequestStateChanged(QContactAbstractRequest::State newState)
{
    QContactFetchRequest * const fetchRequest = qobject_cast<QContactFetchRequest*>(sender());

    if (not processFetchRequest(fetchRequest, newState)) {
        return;
    }

    updateBirthdays(fetchRequest->contacts());
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Common sync logic
///////////////////////////////////////////////////////////////////////////////////////////////////

bool
CDBirthdayController::processFetchRequest(QContactFetchRequest * const fetchRequest,
                                          QContactAbstractRequest::State newState)
{
    if (fetchRequest == 0) {
        warning() << Q_FUNC_INFO << "Invalid fetch request";
        return false;
    }

    bool success = false;

    switch (newState) {
    case QContactAbstractRequest::FinishedState:
        debug() << "Birthday contacts fetch request finished";

        if (fetchRequest->error() != QContactManager::NoError) {
            warning() << Q_FUNC_INFO << "Error during birthday contact fetch request, code: "
                      << fetchRequest->error();
        } else {
            success = true;
        }

        break;

    case QContactAbstractRequest::CanceledState:
        break;

    default:
        return false;
    }

    // Provide hint we are done with this request.
    fetchRequest->deleteLater();

    return success;
}

void
CDBirthdayController::updateBirthdays(const QList<QContact> &changedBirthdays)
{
    foreach (const QContact &contact, changedBirthdays) {
        const QContactBirthday contactBirthday = contact.detail<QContactBirthday>();
        const QContactDisplayLabel contactDisplayLabel = contact.detail<QContactDisplayLabel>();
        const QDate calendarBirthday = mCalendar->birthdayDate(contact.localId());
        const QString calendarSummary = mCalendar->summary(contact.localId());

        // Display label or birthdate was removed from the contact, so delete it from the calendar.
        if (contactDisplayLabel.label().isNull() || contactBirthday.date().isNull()) {
            if (isDebugEnabled()) {
                debug() << "Contact: " << contact << " removed birthday or displayLabel, so delete the calendar event";
            }

            mCalendar->deleteBirthday(contact.localId());
        // Display label or birthdate was changed on the contact, so update the calendar.
        } else if ((contactDisplayLabel.label() != calendarSummary) ||
                   (contactBirthday.date() != calendarBirthday)) {
            if (isDebugEnabled()) {
                debug() << "Contact with calendar birthday: " << contactBirthday.date()
                        << " and calendar displayLabel: " << calendarSummary
                        << " changed details to: " << contact << ", so update the calendar event";
            }

            mCalendar->updateBirthday(contact);
        }
    }
}
<|endoftext|>


<commit_before>#include <iostream>

struct node
{
    int data;
    node* left;
    node* right;
};

void preOrder(node *root) {
    if (root == NULL) return;
    std::cout<<root->data<<" ";
    preOrder(root->left);
    preOrder(root->right);
}

void inOrder(node *root) {
	if (root == NULL) return;
	inOrder(root->left);
	std::cout<<root->data<<" ";
	inOrder(root->right);
}

void postOrder(node *root) {
    if (root == NULL) return;
    postOrder(root->left);
    postOrder(root->right);
    std::cout<<root->data<<" ";
}<commit_msg>added height in tree.cpp<commit_after>#include <iostream>

struct node
{
    int data;
    node* left;
    node* right;
};

void preOrder(node *root) {
    if (root == NULL) return;
    std::cout<<root->data<<" ";
    preOrder(root->left);
    preOrder(root->right);
}

void inOrder(node *root) {
	if (root == NULL) return;
	inOrder(root->left);
	std::cout<<root->data<<" ";
	inOrder(root->right);
}

void postOrder(node *root) {
    if (root == NULL) return;
    postOrder(root->left);
    postOrder(root->right);
    std::cout<<root->data<<" ";
}

int height(Node* root) {
        if (root == NULL) return 0;
        return max(height(root->left), height(root->right)) + 1;
    }<|endoftext|>


<commit_before>#ifndef RAPIDXML_PRINT_HPP_INCLUDED
#define RAPIDXML_PRINT_HPP_INCLUDED

// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_print.hpp This file contains rapidxml printer implementation

#include "rapidxml.hpp"

// Only include streams if not disabled
#ifndef RAPIDXML_NO_STREAMS
    #include <ostream>
    #include <iterator>
#endif

namespace rapidxml
{

    ///////////////////////////////////////////////////////////////////////
    // Printing flags

    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.

    ///////////////////////////////////////////////////////////////////////
    // Internal

    //! \cond internal
    namespace internal
    {

        ///////////////////////////////////////////////////////////////////////////
        // Internal character operations

        // Copy characters from given range to given output iterator
        template<class OutIt, class Ch>
        inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
        {
            while (begin != end)
                *out++ = *begin++;
            return out;
        }

        // Copy characters from given range to given output iterator and expand
        // characters into references (< > ' " &)
        template<class OutIt, class Ch>
        inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
        {
            while (begin != end)
            {
                if (*begin == noexpand)
                {
                    *out++ = *begin;    // No expansion, copy character
                }
                else
                {
                    switch (*begin)
                    {
                    case Ch('<'):
                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
                        break;
                    case Ch('>'):
                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
                        break;
                    case Ch('\''):
                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
                        break;
                    case Ch('"'):
                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
                        break;
                    case Ch('&'):
                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
                        break;
                    default:
                        *out++ = *begin;    // No expansion, copy character
                    }
                }
                ++begin;    // Step to next character
            }
            return out;
        }

        // Fill given output iterator with repetitions of the same character
        template<class OutIt, class Ch>
        inline OutIt fill_chars(OutIt out, int n, Ch ch)
        {
            for (int i = 0; i < n; ++i)
                *out++ = ch;
            return out;
        }

        // Find character
        template<class Ch, Ch ch>
        inline bool find_char(const Ch *begin, const Ch *end)
        {
            while (begin != end)
                if (*begin++ == ch)
                    return true;
            return false;
        }

        ///////////////////////////////////////////////////////////////////////////
        // Internal printing operations

        // Print node
        template<class OutIt, class Ch>
        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            // Print proper node type
            switch (node->type())
            {

            // Document
            case node_document:
                out = print_children(out, node, flags, indent);
                break;

            // Element
            case node_element:
                out = print_element_node(out, node, flags, indent);
                break;

            // Data
            case node_data:
                out = print_data_node(out, node, flags, indent);
                break;

            // CDATA
            case node_cdata:
                out = print_cdata_node(out, node, flags, indent);
                break;

            // Declaration
            case node_declaration:
                out = print_declaration_node(out, node, flags, indent);
                break;

            // Comment
            case node_comment:
                out = print_comment_node(out, node, flags, indent);
                break;

            // Doctype
            case node_doctype:
                out = print_doctype_node(out, node, flags, indent);
                break;

            // Pi
            case node_pi:
                out = print_pi_node(out, node, flags, indent);
                break;

                // Unknown
            default:
                assert(0);
                break;
            }

            // If indenting not disabled, add line break after node
            if (!(flags & print_no_indenting))
                *out = Ch('\n'), ++out;

            // Return modified iterator
            return out;
        }

        // Print children of the node
        template<class OutIt, class Ch>
        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
                out = print_node(out, child, flags, indent);
            return out;
        }

        // Print attributes of the node
        template<class OutIt, class Ch>
        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
        {
            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
            {
                if (attribute->name() && attribute->value())
                {
                    // Print attribute name
                    *out = Ch(' '), ++out;
                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
                    *out = Ch('='), ++out;
                    // Print attribute value using appropriate quote type
                    if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
                    {
                        *out = Ch('\''), ++out;
                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
                        *out = Ch('\''), ++out;
                    }
                    else
                    {
                        *out = Ch('"'), ++out;
                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
                        *out = Ch('"'), ++out;
                    }
                }
            }
            return out;
        }

        // Print data node
        template<class OutIt, class Ch>
        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_data);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
            return out;
        }

        // Print data node
        template<class OutIt, class Ch>
        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_cdata);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'); ++out;
            *out = Ch('!'); ++out;
            *out = Ch('['); ++out;
            *out = Ch('C'); ++out;
            *out = Ch('D'); ++out;
            *out = Ch('A'); ++out;
            *out = Ch('T'); ++out;
            *out = Ch('A'); ++out;
            *out = Ch('['); ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch(']'); ++out;
            *out = Ch(']'); ++out;
            *out = Ch('>'); ++out;
            return out;
        }

        // Print element node
        template<class OutIt, class Ch>
        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_element);

            // Print element name and attributes, if any
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            out = copy_chars(node->name(), node->name() + node->name_size(), out);
            out = print_attributes(out, node, flags);

            // If node is childless
            if (node->value_size() == 0 && !node->first_node())
            {
                // Print childless node tag ending
                *out = Ch('/'), ++out;
                *out = Ch('>'), ++out;
            }
            else
            {
                // Print normal node tag ending
                *out = Ch('>'), ++out;

                // Test if node contains a single data node only (and no other nodes)
                xml_node<Ch> *child = node->first_node();
                if (!child)
                {
                    // If node has no children, only print its value without indenting
                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
                }
                else if (child->next_sibling() == 0 && child->type() == node_data)
                {
                    // If node has a sole data child, only print its value without indenting
                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
                }
                else
                {
                    // Print all children with full indenting
                    if (!(flags & print_no_indenting))
                        *out = Ch('\n'), ++out;
                    out = print_children(out, node, flags, indent + 1);
                    if (!(flags & print_no_indenting))
                        out = fill_chars(out, indent, Ch('\t'));
                }

                // Print node end
                *out = Ch('<'), ++out;
                *out = Ch('/'), ++out;
                out = copy_chars(node->name(), node->name() + node->name_size(), out);
                *out = Ch('>'), ++out;
            }
            return out;
        }

        // Print declaration node
        template<class OutIt, class Ch>
        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            // Print declaration start
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('?'), ++out;
            *out = Ch('x'), ++out;
            *out = Ch('m'), ++out;
            *out = Ch('l'), ++out;

            // Print attributes
            out = print_attributes(out, node, flags);

            // Print declaration end
            *out = Ch('?'), ++out;
            *out = Ch('>'), ++out;

            return out;
        }

        // Print comment node
        template<class OutIt, class Ch>
        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_comment);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('!'), ++out;
            *out = Ch('-'), ++out;
            *out = Ch('-'), ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch('-'), ++out;
            *out = Ch('-'), ++out;
            *out = Ch('>'), ++out;
            return out;
        }

        // Print doctype node
        template<class OutIt, class Ch>
        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_doctype);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('!'), ++out;
            *out = Ch('D'), ++out;
            *out = Ch('O'), ++out;
            *out = Ch('C'), ++out;
            *out = Ch('T'), ++out;
            *out = Ch('Y'), ++out;
            *out = Ch('P'), ++out;
            *out = Ch('E'), ++out;
            *out = Ch(' '), ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch('>'), ++out;
            return out;
        }

        // Print pi node
        template<class OutIt, class Ch>
        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_pi);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('?'), ++out;
            out = copy_chars(node->name(), node->name() + node->name_size(), out);
            *out = Ch(' '), ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch('?'), ++out;
            *out = Ch('>'), ++out;
            return out;
        }

    }
    //! \endcond

    ///////////////////////////////////////////////////////////////////////////
    // Printing

    //! Prints XML to given output iterator.
    //! \param out Output iterator to print to.
    //! \param node Node to be printed. Pass xml_document to print entire document.
    //! \param flags Flags controlling how XML is printed.
    //! \return Output iterator pointing to position immediately after last character of printed text.
    template<class OutIt, class Ch>
    inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
    {
        return internal::print_node(out, &node, flags, 0);
    }

#ifndef RAPIDXML_NO_STREAMS

    //! Prints XML to given output stream.
    //! \param out Output stream to print to.
    //! \param node Node to be printed. Pass xml_document to print entire document.
    //! \param flags Flags controlling how XML is printed.
    //! \return Output stream.
    template<class Ch>
    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
    {
        print(std::ostream_iterator<Ch>(out), node, flags);
        return out;
    }

    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
    //! \param out Output stream to print to.
    //! \param node Node to be printed.
    //! \return Output stream.
    template<class Ch>
    inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
    {
        return print(out, node);
    }

#endif

}

#endif
<commit_msg>Fixed compilation error with GCC >= 4.7<commit_after>#ifndef RAPIDXML_PRINT_HPP_INCLUDED
#define RAPIDXML_PRINT_HPP_INCLUDED

// Copyright (C) 2006, 2009 Marcin Kalicinski
// Version 1.13
// Revision $DateTime: 2009/05/13 01:46:17 $
//! \file rapidxml_print.hpp This file contains rapidxml printer implementation

#include "rapidxml.hpp"

// Only include streams if not disabled
#ifndef RAPIDXML_NO_STREAMS
    #include <ostream>
    #include <iterator>
#endif

namespace rapidxml
{

    ///////////////////////////////////////////////////////////////////////
    // Printing flags

    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.

    ///////////////////////////////////////////////////////////////////////
    // Internal

    //! \cond internal
    namespace internal
    {

        ///////////////////////////////////////////////////////////////////////////
        // Internal character operations

        // Copy characters from given range to given output iterator
        template<class OutIt, class Ch>
        inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
        {
            while (begin != end)
                *out++ = *begin++;
            return out;
        }

        // Copy characters from given range to given output iterator and expand
        // characters into references (< > ' " &)
        template<class OutIt, class Ch>
        inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
        {
            while (begin != end)
            {
                if (*begin == noexpand)
                {
                    *out++ = *begin;    // No expansion, copy character
                }
                else
                {
                    switch (*begin)
                    {
                    case Ch('<'):
                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
                        break;
                    case Ch('>'):
                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
                        break;
                    case Ch('\''):
                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
                        break;
                    case Ch('"'):
                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
                        break;
                    case Ch('&'):
                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
                        break;
                    default:
                        *out++ = *begin;    // No expansion, copy character
                    }
                }
                ++begin;    // Step to next character
            }
            return out;
        }

        // Fill given output iterator with repetitions of the same character
        template<class OutIt, class Ch>
        inline OutIt fill_chars(OutIt out, int n, Ch ch)
        {
            for (int i = 0; i < n; ++i)
                *out++ = ch;
            return out;
        }

        // Find character
        template<class Ch, Ch ch>
        inline bool find_char(const Ch *begin, const Ch *end)
        {
            while (begin != end)
                if (*begin++ == ch)
                    return true;
            return false;
        }

        ///////////////////////////////////////////////////////////////////////////
        // Internal printing operations

        template<class OutIt, class Ch>
        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags);

        template<class OutIt, class Ch>
        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        template<class OutIt, class Ch>
        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);

        // Print node
        template<class OutIt, class Ch>
        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            // Print proper node type
            switch (node->type())
            {

            // Document
            case node_document:
                out = print_children(out, node, flags, indent);
                break;

            // Element
            case node_element:
                out = print_element_node(out, node, flags, indent);
                break;

            // Data
            case node_data:
                out = print_data_node(out, node, flags, indent);
                break;

            // CDATA
            case node_cdata:
                out = print_cdata_node(out, node, flags, indent);
                break;

            // Declaration
            case node_declaration:
                out = print_declaration_node(out, node, flags, indent);
                break;

            // Comment
            case node_comment:
                out = print_comment_node(out, node, flags, indent);
                break;

            // Doctype
            case node_doctype:
                out = print_doctype_node(out, node, flags, indent);
                break;

            // Pi
            case node_pi:
                out = print_pi_node(out, node, flags, indent);
                break;

                // Unknown
            default:
                assert(0);
                break;
            }

            // If indenting not disabled, add line break after node
            if (!(flags & print_no_indenting))
                *out = Ch('\n'), ++out;

            // Return modified iterator
            return out;
        }

        // Print children of the node
        template<class OutIt, class Ch>
        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
                out = print_node(out, child, flags, indent);
            return out;
        }

        // Print attributes of the node
        template<class OutIt, class Ch>
        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
        {
            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
            {
                if (attribute->name() && attribute->value())
                {
                    // Print attribute name
                    *out = Ch(' '), ++out;
                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
                    *out = Ch('='), ++out;
                    // Print attribute value using appropriate quote type
                    if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
                    {
                        *out = Ch('\''), ++out;
                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
                        *out = Ch('\''), ++out;
                    }
                    else
                    {
                        *out = Ch('"'), ++out;
                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
                        *out = Ch('"'), ++out;
                    }
                }
            }
            return out;
        }

        // Print data node
        template<class OutIt, class Ch>
        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_data);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
            return out;
        }

        // Print data node
        template<class OutIt, class Ch>
        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_cdata);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'); ++out;
            *out = Ch('!'); ++out;
            *out = Ch('['); ++out;
            *out = Ch('C'); ++out;
            *out = Ch('D'); ++out;
            *out = Ch('A'); ++out;
            *out = Ch('T'); ++out;
            *out = Ch('A'); ++out;
            *out = Ch('['); ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch(']'); ++out;
            *out = Ch(']'); ++out;
            *out = Ch('>'); ++out;
            return out;
        }

        // Print element node
        template<class OutIt, class Ch>
        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_element);

            // Print element name and attributes, if any
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            out = copy_chars(node->name(), node->name() + node->name_size(), out);
            out = print_attributes(out, node, flags);

            // If node is childless
            if (node->value_size() == 0 && !node->first_node())
            {
                // Print childless node tag ending
                *out = Ch('/'), ++out;
                *out = Ch('>'), ++out;
            }
            else
            {
                // Print normal node tag ending
                *out = Ch('>'), ++out;

                // Test if node contains a single data node only (and no other nodes)
                xml_node<Ch> *child = node->first_node();
                if (!child)
                {
                    // If node has no children, only print its value without indenting
                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
                }
                else if (child->next_sibling() == 0 && child->type() == node_data)
                {
                    // If node has a sole data child, only print its value without indenting
                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
                }
                else
                {
                    // Print all children with full indenting
                    if (!(flags & print_no_indenting))
                        *out = Ch('\n'), ++out;
                    out = print_children(out, node, flags, indent + 1);
                    if (!(flags & print_no_indenting))
                        out = fill_chars(out, indent, Ch('\t'));
                }

                // Print node end
                *out = Ch('<'), ++out;
                *out = Ch('/'), ++out;
                out = copy_chars(node->name(), node->name() + node->name_size(), out);
                *out = Ch('>'), ++out;
            }
            return out;
        }

        // Print declaration node
        template<class OutIt, class Ch>
        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            // Print declaration start
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('?'), ++out;
            *out = Ch('x'), ++out;
            *out = Ch('m'), ++out;
            *out = Ch('l'), ++out;

            // Print attributes
            out = print_attributes(out, node, flags);

            // Print declaration end
            *out = Ch('?'), ++out;
            *out = Ch('>'), ++out;

            return out;
        }

        // Print comment node
        template<class OutIt, class Ch>
        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_comment);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('!'), ++out;
            *out = Ch('-'), ++out;
            *out = Ch('-'), ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch('-'), ++out;
            *out = Ch('-'), ++out;
            *out = Ch('>'), ++out;
            return out;
        }

        // Print doctype node
        template<class OutIt, class Ch>
        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_doctype);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('!'), ++out;
            *out = Ch('D'), ++out;
            *out = Ch('O'), ++out;
            *out = Ch('C'), ++out;
            *out = Ch('T'), ++out;
            *out = Ch('Y'), ++out;
            *out = Ch('P'), ++out;
            *out = Ch('E'), ++out;
            *out = Ch(' '), ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch('>'), ++out;
            return out;
        }

        // Print pi node
        template<class OutIt, class Ch>
        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
        {
            assert(node->type() == node_pi);
            if (!(flags & print_no_indenting))
                out = fill_chars(out, indent, Ch('\t'));
            *out = Ch('<'), ++out;
            *out = Ch('?'), ++out;
            out = copy_chars(node->name(), node->name() + node->name_size(), out);
            *out = Ch(' '), ++out;
            out = copy_chars(node->value(), node->value() + node->value_size(), out);
            *out = Ch('?'), ++out;
            *out = Ch('>'), ++out;
            return out;
        }

    }
    //! \endcond

    ///////////////////////////////////////////////////////////////////////////
    // Printing

    //! Prints XML to given output iterator.
    //! \param out Output iterator to print to.
    //! \param node Node to be printed. Pass xml_document to print entire document.
    //! \param flags Flags controlling how XML is printed.
    //! \return Output iterator pointing to position immediately after last character of printed text.
    template<class OutIt, class Ch>
    inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
    {
        return internal::print_node(out, &node, flags, 0);
    }

#ifndef RAPIDXML_NO_STREAMS

    //! Prints XML to given output stream.
    //! \param out Output stream to print to.
    //! \param node Node to be printed. Pass xml_document to print entire document.
    //! \param flags Flags controlling how XML is printed.
    //! \return Output stream.
    template<class Ch>
    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
    {
        print(std::ostream_iterator<Ch>(out), node, flags);
        return out;
    }

    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
    //! \param out Output stream to print to.
    //! \param node Node to be printed.
    //! \return Output stream.
    template<class Ch>
    inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
    {
        return print(out, node);
    }

#endif

}

#endif
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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 <Interface/Modules/Base/WidgetSlotManagers.h>
#include <Interface/Modules/Base/ModuleDialogGeneric.h>

using namespace SCIRun::Gui;
using namespace SCIRun::Core::Algorithms;

WidgetSlotManager::WidgetSlotManager(SCIRun::Dataflow::Networks::ModuleStateHandle state, ModuleDialogGeneric& dialog, QWidget* widget, const AlgorithmParameterName& name)
  : state_(state), dialog_(dialog)
{
  if (widget)
    widget->setToolTip(QString::fromStdString(name.name_));
}

WidgetSlotManager::~WidgetSlotManager()
{
}

void WidgetSlotManager::push()
{
  //TODO: idea: tell state_ directly, i'm in a scoped region of pushing/editing, don't signal while i edit. signal when done editing!
  if (!dialog_.isPulling())
    pushImpl();
}<commit_msg>Closes #1255<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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 <Interface/Modules/Base/WidgetSlotManagers.h>
#include <Interface/Modules/Base/ModuleDialogGeneric.h>

using namespace SCIRun::Gui;
using namespace SCIRun::Core::Algorithms;

WidgetSlotManager::WidgetSlotManager(SCIRun::Dataflow::Networks::ModuleStateHandle state, ModuleDialogGeneric& dialog, QWidget* widget, const AlgorithmParameterName& name)
  : state_(state), dialog_(dialog)
{
  if (widget)
  {
    widget->setToolTip("State key: " + QString::fromStdString(name.name_));
    widget->setStyleSheet(widget->styleSheet() + " QToolTip { color: #ffffff; background - color: #2a82da; border: 1px solid white; }");
  }
}

WidgetSlotManager::~WidgetSlotManager()
{
}

void WidgetSlotManager::push()
{
  //TODO: idea: tell state_ directly, i'm in a scoped region of pushing/editing, don't signal while i edit. signal when done editing!
  if (!dialog_.isPulling())
    pushImpl();
}<|endoftext|>


<commit_before>#include "HelloWorld5Module.h"
#include "NFComm/NFCore/NFTimer.h"
#include <thread>
#include "NFComm/NFCore/NFIComponent.h"
#include "NFCTestComponent.h"

bool HelloWorld5Module::Init()
{
    //ʼ
    std::cout << "Hello, world5, Init" << std::endl;

    return true;
}

bool HelloWorld5Module::AfterInit()
{
    //ʼ
    std::cout << "Hello, world5, AfterInit, ThreadID: " << std::this_thread::get_id() << std::endl;

    m_pKernelModule = dynamic_cast<NFIKernelModule*>(pPluginManager->FindModule("NFCKernelModule"));
    m_pEventProcessModule = dynamic_cast<NFIEventProcessModule*>(pPluginManager->FindModule("NFCEventProcessModule"));
    m_pElementInfoModule = dynamic_cast<NFIElementInfoModule*>(pPluginManager->FindModule("NFCElementInfoModule"));

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

	//int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent, HelloWorld5Module>(this, &HelloWorld5Module::OnSyncEvent);
	int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent>(this, &HelloWorld5Module::OnSyncEvent);

    m_pEventProcessModule->SendActorMsg(nActorID, 555, NFIDENTID(), "Event Param");

    std::cout << "End Test Actor, ThreadID: " << std::this_thread::get_id() << std::endl;

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

    return true;
}

int HelloWorld5Module::OnSyncEvent(const NFIDENTID& self, const int event, const std::string& arg)
{
    //¼ص
    std::cout << "End OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

    return 0;
}

bool HelloWorld5Module::Execute( const float fLasFrametime, const float fStartedTime )
{
    //ÿִ֡
    //std::cout << "Hello, world5, Execute" << std::endl;

    return true;
}

bool HelloWorld5Module::BeforeShut()
{
    //ʼ֮ǰ
    std::cout << "Hello, world5, BeforeShut" << std::endl;

    m_pKernelModule->DestroyAll();

    return true;
}

bool HelloWorld5Module::Shut()
{
    //ʼ
    std::cout << "Hello, world5, Shut" << std::endl;

    return true;
}
<commit_msg>Tutorial<commit_after>#include "HelloWorld5Module.h"
#include "NFComm/NFCore/NFTimer.h"
#include <thread>
#include "NFComm/NFCore/NFIComponent.h"
#include "NFCTestComponent.h"

bool HelloWorld5Module::Init()
{
    //ʼ
    std::cout << "Hello, world5, Init" << std::endl;

    return true;
}

bool HelloWorld5Module::AfterInit()
{
    //ʼ
    std::cout << "Hello, world5, AfterInit, ThreadID: " << std::this_thread::get_id() << std::endl;

    m_pKernelModule = dynamic_cast<NFIKernelModule*>(pPluginManager->FindModule("NFCKernelModule"));
    m_pEventProcessModule = dynamic_cast<NFIEventProcessModule*>(pPluginManager->FindModule("NFCEventProcessModule"));
    m_pElementInfoModule = dynamic_cast<NFIElementInfoModule*>(pPluginManager->FindModule("NFCElementInfoModule"));

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

	//int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent, HelloWorld5Module>(this, &HelloWorld5Module::OnSyncEvent);
	int nActorID = m_pEventProcessModule->AddActorEventCallBack<NFCTestComponent>(this, &HelloWorld5Module::OnSyncEvent);

	for (int i = 0; i < 20; ++i)
	{
		m_pEventProcessModule->SendActorMsg(nActorID, 555, NFIDENTID(), boost::lexical_cast<std::string>(i));
	}

    std::cout << "End Test Actor, ThreadID: " << std::this_thread::get_id() << std::endl;

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

    return true;
}

int HelloWorld5Module::OnSyncEvent(const NFIDENTID& self, const int event, const std::string& arg)
{
    //¼ص
    std::cout << "End OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

    return 0;
}

bool HelloWorld5Module::Execute( const float fLasFrametime, const float fStartedTime )
{
    //ÿִ֡
    //std::cout << "Hello, world5, Execute" << std::endl;

    return true;
}

bool HelloWorld5Module::BeforeShut()
{
    //ʼ֮ǰ
    std::cout << "Hello, world5, BeforeShut" << std::endl;

    m_pKernelModule->DestroyAll();

    return true;
}

bool HelloWorld5Module::Shut()
{
    //ʼ
    std::cout << "Hello, world5, Shut" << std::endl;

    return true;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <utility>
#include <fstream>
#include <sstream>
#include "TGraph.h"
#include "TCanvas.h"
#include "TF1.h"
#include "TStyle.h"
#include "TGraphErrors.h"

std::vector< std::pair<int,double> > takeData(const std::string file, const char thresholdLabel);
std::pair<double,double> plotVelocity(std::vector<double> positions, std::vector<double> means, int strip, std::vector<double> errors, char thresholdLabel);

struct positionData{
	double positionValue;
	double deltaT;
	double deltaTError;
};

struct thresholdData{
	char thresholdLabel;
	std::vector<positionData> positions;
};

struct scintData{
	int ID;
	std::vector<thresholdData> thrData;
};

std::vector<scintData> takeData(const std::string file);
void velocityCalc(std::vector<scintData>& data, const char thrLabel, const std::string& outPath);
void parserTest(std::vector<scintData>& data, const char thrLabel);

int main(int argc, char** argv)
{
	gStyle->SetOptFit(1);

	std::vector<scintData> data;
	std::string outPath = "";
	if(argc == 1)
	{
	  data = takeData("results.txt");
	}
	else if (argc == 2)
	{
	  data = takeData(std::string(argv[1]));
	}
	else if (argc == 3)
	{
	  data = takeData(std::string(argv[1]));
	  outPath = argv[2];
	}

	if(data.size() == 0 )
	{
	  std::cout<<"Error while opening input file"<<std::endl;
	  return 1;
	}

	velocityCalc( data , 'a', outPath);
	velocityCalc( data , 'b', outPath);
	velocityCalc( data , 'c', outPath);
	velocityCalc( data , 'd', outPath);

	return 0;
}

void parserTest(std::vector<scintData>& data, const char thrLabel)
{
	for(auto scintillator : data)
	{
		std::cout << scintillator.ID;
		for(auto threshold : scintillator.thrData)
		{
			if( thrLabel == threshold.thresholdLabel )
			{
				std::cout << "\t" << threshold.thresholdLabel;
				for( auto position : threshold.positions )
				{
					std::cout << "\t" << position.positionValue << "\t" << position.deltaT << "\t" << position.deltaTError <<std::endl;
				}
			}
		}
	}

}

void velocityCalc(std::vector<scintData>& data, const char thrLabel, const std::string& outPath)
{

	std::ofstream results;
	std::string title = outPath+"resultsForThreshold";
	title+= thrLabel;
	title+= ".txt";
	results.open( title.c_str() );
	for(auto scintillator : data)
	{
		std::vector<double> positionsForFit;
		std::vector<double> timesForFit;
		std::vector<double> errorsForFit;
		for(auto threshold : scintillator.thrData)
		{

			if( thrLabel == threshold.thresholdLabel )
			{
				for( auto position : threshold.positions )
				{
					std::cout << "\t" << position.positionValue << "\t" << position.deltaT << "\t" << position.deltaTError <<std::endl;
					positionsForFit.push_back( position.positionValue );
					timesForFit.push_back( position.deltaT );
					errorsForFit.push_back( position.deltaTError);
					std::cout << positionsForFit.size() << std::endl;
					std::cout << timesForFit.size() << std::endl;
				}
			}
		}
		std::pair<double,double> velocity = plotVelocity( positionsForFit, timesForFit, scintillator.ID, errorsForFit, thrLabel);
		results << scintillator.ID << "\t" << velocity.first << "\t" << velocity.second << std::endl;
	}

	results.close();
}

std::pair<double,double> plotVelocity(std::vector<double> positions, std::vector<double> means, int strip, std::vector<double> errors, char thresholdLabel)
{
	TCanvas* c = new TCanvas();
	TGraphErrors* vGraph = new TGraphErrors(positions.size(), &means[0], &positions[0], 0, &errors[0] );
	vGraph->SetMarkerStyle(20);
	vGraph->SetMarkerSize(1);
	vGraph->Draw("AP");
	vGraph->Fit("pol1");
	TF1* fit = vGraph->GetFunction("pol1");
	std::stringstream buf;
	buf << strip << "_" << thresholdLabel;
	c->SaveAs( (buf.str() + ".png").c_str() );
	std::pair<double,double> resultOfFit = std::make_pair<double,double> ( (fit->GetParameter(1))*-0.2,  (fit->GetParError(1))*-0.2 );
	return resultOfFit;
}

bool ifScintillatorIsIn( std::vector<scintData>& data, int ID)
{
	for( auto scintillator : data )
	{
		if( ID == scintillator.ID )
			return true;
	}
	return false;
}

int findScintillatorIn( std::vector<scintData>& data, int ID)
{
	for( unsigned int i = 0; i < data.size(); i++ )
	{
		if( ID == data[i].ID )
			return i;
	}
	return -1;
}

std::vector<scintData> takeData(const std::string file){
	std::ifstream dataFile;
	dataFile.open(file.c_str());

	if( !dataFile.good() )
	{
		std::exit(1);
	}

	std::vector< scintData > allData;

	double position = 999;
	char thrLabel = 'z';
	double chi2 = 99;
	int degrees = 0;
	int ID = 0;
	double mean = 999;
	double meanError = 0;
		while( dataFile >> ID >> position >> thrLabel >>  mean >> meanError >> chi2 >> degrees )
		{
			//IF ID IS IN ALLDATA
			if ( ifScintillatorIsIn(allData, ID) )
			{
				//FILL THIS SCINTILLATOR WITH ADDITIONAL INFO
				int scintIndex = findScintillatorIn(allData, ID);

				positionData pos;
				pos.positionValue = position;
				pos.deltaT = mean;
				pos.deltaTError = meanError;

				thresholdData thr;
				thr.thresholdLabel = thrLabel;
				thr.positions.push_back(pos);

				allData[ scintIndex ].thrData.push_back(thr);
			}
			else{
				//ELSE MAKE NEW SCINTILLATOR AND FILL
				positionData pos;
				pos.positionValue = position;
				pos.deltaT = mean;
				pos.deltaTError = meanError;

				thresholdData thr;
				thr.thresholdLabel = thrLabel;
				thr.positions.push_back(pos);

				scintData scintillator;
				scintillator.ID = ID;
				scintillator.thrData.push_back(thr);

				// FILL THRESHOLD AND POSITION
				allData.push_back(scintillator);
			}
		}

	return allData;
}

<commit_msg>Make universal format output from velocity calib<commit_after>#include <iostream>
#include <vector>
#include <utility>
#include <fstream>
#include <sstream>
#include "TGraph.h"
#include "TCanvas.h"
#include "TF1.h"
#include "TStyle.h"
#include "TGraphErrors.h"
#include <map>

std::vector< std::pair<int,double> > takeData(const std::string file, const char thresholdLabel);
std::pair<double,double> plotVelocity(std::vector<double> positions, std::vector<double> means, int strip, std::vector<double> errors, char thresholdLabel);

struct positionData{
	double positionValue;
	double deltaT;
	double deltaTError;
};

struct thresholdData{
	char thresholdLabel;
	std::vector<positionData> positions;
};

struct scintData{
	int ID;
	std::vector<thresholdData> thrData;
};

std::vector<scintData> takeData(const std::string file);
void velocityCalc(std::vector<scintData>& data, const std::string& outPath);
void parserTest(std::vector<scintData>& data, const char thrLabel);

int main(int argc, char** argv)
{
	gStyle->SetOptFit(1);

	std::vector<scintData> data;
	std::string outPath = "";
	if(argc == 1)
	{
	  data = takeData("results.txt");
	}
	else if (argc == 2)
	{
	  data = takeData(std::string(argv[1]));
	}
	else if (argc == 3)
	{
	  data = takeData(std::string(argv[1]));
	  outPath = argv[2];
	}

	if(data.size() == 0 )
	{
	  std::cout<<"Error while opening input file"<<std::endl;
	  return 1;
	}

	velocityCalc( data , outPath);

	return 0;
}

void parserTest(std::vector<scintData>& data, const char thrLabel)
{
	for(auto scintillator : data)
	{
		std::cout << scintillator.ID;
		for(auto threshold : scintillator.thrData)
		{
			if( thrLabel == threshold.thresholdLabel )
			{
				std::cout << "\t" << threshold.thresholdLabel;
				for( auto position : threshold.positions )
				{
					std::cout << "\t" << position.positionValue << "\t" << position.deltaT << "\t" << position.deltaTError <<std::endl;
				}
			}
		}
	}

}

void velocityCalc(std::vector<scintData>& data, const std::string& outPath)
{
	std::map<char, int> thresholdLabelToInt = {{'a', 1}, {'b',2}, {'c',3}, {'d',4}};
	std::ofstream results;
	std::string title = outPath+"EffVelocities";
	title+= ".txt";
	results.open( title.c_str() );
	for(auto scintillator : data)
	{
		std::cout << scintillator.ID;
		for(auto threshold : scintillator.thrData)
		{
			std::cout << "\t" << threshold.thresholdLabel;
			std::vector<double> positionsForFit;
			std::vector<double> timesForFit;
			std::vector<double> errorsForFit;
			for( auto position : threshold.positions )
			{
				std::cout << "\t" << position.positionValue << "\t" << position.deltaT << "\t" << position.deltaTError <<std::endl;
				positionsForFit.push_back( position.positionValue );
				timesForFit.push_back( position.deltaT );
				errorsForFit.push_back( position.deltaTError);
			}
			std::pair<double,double> velocity = plotVelocity( positionsForFit, timesForFit, scintillator.ID, errorsForFit, threshold.thresholdLabel);
			int layer = 0, layerReset = 0;
			if( scintillator.ID < 49 )
			{
			  layer = 1;
			}
			else if( scintillator.ID > 48 && scintillator.ID < 97 )
			{
			  layer = 2;
			  layerReset = 48;
			}
			else
			{
			  layer = 3;
			  layerReset = 96;
			}

			results << layer << "\t" << scintillator.ID - layerReset << "\tA\t" << thresholdLabelToInt[threshold.thresholdLabel];
			results << "\t" << velocity.first << "\t" << velocity.second;
			results << "\t0\t0\t0\t0\t0\t0" << std::endl;
			results << layer << "\t" << scintillator.ID - layerReset << "\tB\t" << thresholdLabelToInt[threshold.thresholdLabel];
			results << "\t" << velocity.first << "\t" << velocity.second;
			results << "\t0\t0\t0\t0\t0\t0" << std::endl;
		}
	}

	results.close();
}

std::pair<double,double> plotVelocity(std::vector<double> positions, std::vector<double> means, int strip, std::vector<double> errors, char thresholdLabel)
{
	TCanvas* c = new TCanvas();
	TGraphErrors* vGraph = new TGraphErrors(positions.size(), &means[0], &positions[0], 0, &errors[0] );
	vGraph->SetMarkerStyle(20);
	vGraph->SetMarkerSize(1);
	vGraph->Draw("AP");
	vGraph->Fit("pol1");
	TF1* fit = vGraph->GetFunction("pol1");
	std::stringstream buf;
	buf << strip << "_" << thresholdLabel;
	c->SaveAs( (buf.str() + ".png").c_str() );
	std::pair<double,double> resultOfFit = std::make_pair<double,double> ( (fit->GetParameter(1))*-0.2,  (fit->GetParError(1))*-0.2 );
	return resultOfFit;
}

bool ifScintillatorIsIn( std::vector<scintData>& data, int ID)
{
	for( auto scintillator : data )
	{
		if( ID == scintillator.ID )
			return true;
	}
	return false;
}

int findScintillatorIn( std::vector<scintData>& data, int ID)
{
	for( unsigned int i = 0; i < data.size(); i++ )
	{
		if( ID == data[i].ID )
			return i;
	}
	return -1;
}

bool ifThresholdIsIn( scintData& data, char label)
{
	for( auto threshold : data.thrData )
	{
		if( label == threshold.thresholdLabel)
			return true;
	}
	return false;
}

int findThresholdIn( scintData& data, char label)
{
	for( unsigned int i = 0; i < data.thrData.size(); i++ )
	{
		if( label == data.thrData[i].thresholdLabel )
			return i;
	}
	return -1;
}

std::vector<scintData> takeData(const std::string file){
	std::ifstream dataFile;
	dataFile.open(file.c_str());

	if( !dataFile.good() )
	{
		std::exit(1);
	}

	std::vector< scintData > allData;

	double position = 999;
	char thrLabel = 'z';
	double chi2 = 99;
	int degrees = 0;
	int ID = 0;
	double mean = 999;
	double meanError = 0;
		while( dataFile >> ID >> position >> thrLabel >>  mean >> meanError >> chi2 >> degrees )
		{
			//IF ID IS IN ALLDATA
			if ( ifScintillatorIsIn(allData, ID) )
			{
				//FILL THIS SCINTILLATOR WITH ADDITIONAL INFO
				int scintIndex = findScintillatorIn(allData, ID);

				positionData pos;
				pos.positionValue = position;
				pos.deltaT = mean;
				pos.deltaTError = meanError;

				//IF THR IS IN SCINTILLATOR
				if( ifThresholdIsIn( allData[scintIndex], thrLabel ) )
				{
				  int thrIndex = findThresholdIn( allData[scintIndex], thrLabel );
				  allData[ scintIndex ].thrData[thrIndex].positions.push_back(pos);
				}
				else
				{
				//ELSE MAKE A NEW THRESHOLD AND FILL
				thresholdData thr;
				thr.thresholdLabel = thrLabel;
				thr.positions.push_back(pos);

				allData[ scintIndex ].thrData.push_back(thr);
				}
			}
			else{
				//ELSE MAKE NEW SCINTILLATOR AND FILL
				positionData pos;
				pos.positionValue = position;
				pos.deltaT = mean;
				pos.deltaTError = meanError;

				thresholdData thr;
				thr.thresholdLabel = thrLabel;
				thr.positions.push_back(pos);

				scintData scintillator;
				scintillator.ID = ID;
				scintillator.thrData.push_back(thr);

				// FILL THRESHOLD AND POSITION
				allData.push_back(scintillator);
			}
		}

	return allData;
}

<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/MayaCamUI.h"
#include "cinder/Perlin.h"
#include "cinder/gl/Fbo.h"

#include "VibrissaElement.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class VibrissaSketchApp : public AppNative {
  public:
	void setup();
	void update();
	void draw();
    void prepareSettings(Settings *settings);

    void mouseDown(MouseEvent event);
    void mouseDrag(MouseEvent event);
    void resize();

protected:
    MayaCamUI mMayaCam;
    VibrissaElement mElement;
    Perlin mPerlin;

    gl::Fbo mFboScene;
    gl::Fbo mFboBlur1;
    gl::Fbo mFboBlur2;
    gl::GlslProg mBlurShader;
    gl::GlslProg mPostShader;

    void drawScene();
    void drawElements();
    void drawGrid(float size=100.0f, float step=5.0f);
    void drawVibrissa(Vec3f origin);
};

void VibrissaSketchApp::setup()
{
    setFullScreen(true);
    hideCursor();

    gl::Fbo::Format fmt;
    fmt.setColorInternalFormat(GL_RGB32F_ARB);

    mFboScene = gl::Fbo(getWindowWidth() * 2, getWindowHeight() * 2, fmt);
    mFboBlur1 = gl::Fbo(getWindowWidth() / 4, getWindowHeight() / 4, fmt);
    mFboBlur2 = gl::Fbo(getWindowWidth() / 4, getWindowHeight() / 4, fmt);

    mBlurShader = gl::GlslProg(loadResource("blur.glslv"), loadResource("blur.glslf"));
    mPostShader = gl::GlslProg(loadResource("post.glslv"), loadResource("post.glslf"));

    mElement.setup(*this);

    CameraPersp cam;
    cam.setEyePoint( Vec3f(5.0f, 1.5f, -5.0f) );
    cam.setCenterOfInterestPoint( Vec3f(20.f, 5.f, 4.f) );
    cam.setPerspective( 60.0f, getWindowAspectRatio(), 1.0f, 1000.0f );
    mMayaCam.setCurrentCam( cam );
}

void VibrissaSketchApp::prepareSettings( Settings *settings )
{
    settings->setWindowSize( 1920, 1080 );
    settings->setFrameRate( 60.0f );
}

void VibrissaSketchApp::mouseDown( MouseEvent event )
{
    mMayaCam.mouseDown( event.getPos() );
}

void VibrissaSketchApp::mouseDrag( MouseEvent event )
{
    mMayaCam.mouseDrag(event.getPos(),
                       event.isLeftDown() && !event.isShiftDown(),
                       event.isMiddleDown() || event.isShiftDown(),
                       event.isRightDown() );
}

void VibrissaSketchApp::resize()
{
    CameraPersp cam = mMayaCam.getCamera();
    cam.setAspectRatio( getWindowAspectRatio() );
    mMayaCam.setCurrentCam( cam );
}

void VibrissaSketchApp::update()
{
    mElement.update();
}

void VibrissaSketchApp::drawGrid(float size, float step)
{
    float gray = 0.12f;
    gl::color( Colorf(gray, gray, gray) );

    for (float i=-size;i<=size;i+=step) {
        gl::drawLine( Vec3f(i, 0.0f, -size), Vec3f(i, 0.0f, size) );
        gl::drawLine( Vec3f(-size, 0.0f, i), Vec3f(size, 0.0f, i) );
    }
}

void VibrissaSketchApp::draw()
{
    mFboScene.bindFramebuffer();
    gl::setViewport(mFboScene.getBounds());
    gl::enableDepthRead();
    gl::enableDepthWrite();

    drawScene();

    mFboScene.unbindFramebuffer();
    gl::disableDepthRead();
    gl::disableDepthWrite();
    gl::color(1.f, 1.f, 1.f);

    const float atten = 2.5f;
    for (unsigned step = 0; step < 10; step++) {

        // Horizontal blur
        mFboBlur1.bindFramebuffer();
        gl::setViewport(mFboBlur1.getBounds());
        gl::setMatricesWindow(mFboBlur1.getSize());
        mBlurShader.bind();
        mBlurShader.uniform("tex0", 0);
        mBlurShader.uniform("sample_offset", Vec2f(1.f / mFboBlur1.getWidth(), 0.f));
        mBlurShader.uniform("attenuation", step ? 1.f : atten);
        gl::draw(step ? mFboBlur2.getTexture() : mFboScene.getTexture(),
                 Rectf(Vec2f(0,0), mFboBlur1.getSize()));
        mBlurShader.unbind();
        mFboBlur1.unbindFramebuffer();

        // Vertical blur
        mFboBlur2.bindFramebuffer();
        gl::setViewport(mFboBlur2.getBounds());
        gl::setMatricesWindow(mFboBlur2.getSize());
        mBlurShader.bind();
        mBlurShader.uniform("tex0", 0);
        mBlurShader.uniform("sample_offset", Vec2f(0.f, 1.f / mFboBlur2.getWidth()));
        mBlurShader.uniform("attenuation", 1.f);
        gl::draw(mFboBlur1.getTexture(), Rectf(Vec2f(0,0), mFboBlur2.getSize()));
        mBlurShader.unbind();
        mFboBlur2.unbindFramebuffer();
    }

    // Final scene, combine blurred and unblurred
    gl::setViewport(getWindowBounds());
    gl::setMatricesWindow(getWindowSize(), false);
    mPostShader.bind();
    mPostShader.uniform("scene", 0);
    mPostShader.uniform("blurred", 1);
    mFboBlur2.getTexture().bind(1);
    gl::draw(mFboScene.getTexture(), Rectf(Vec2f(0,0), getWindowSize()));
    mPostShader.unbind();
}

void VibrissaSketchApp::drawScene()
{
    float gray = 0.02f;
    gl::clear(Colorf(gray, gray, gray));

    gl::setMatrices(mMayaCam.getCamera());
    drawGrid();
    drawElements();
}

void VibrissaSketchApp::drawElements()
{
    const float kMetersPerInch = 0.0254f;
    const float kMetersPerFoot = kMetersPerInch * 12;

    float extent = 540 * kMetersPerFoot;
    float spacing = 20 * kMetersPerFoot;

    // Line of elements along the front
    for (float t = 0.f; t <= 1.f; t += spacing / extent) {
        mElement.draw(Vec3f((t - 0.5f) * extent, 0.f, 0.f), t);
    }

    float loop_center = (225 + 150) * kMetersPerFoot / 2;
    float loop_r = 80 * kMetersPerFoot / 2;
    float path_r = 6 * kMetersPerFoot;

    // Loops along path
    for (int side = -1; side <= 1; side += 2) {

        for (float t = 0.f; t < 1.f; t += 0.1f) {
            float a = t * M_PI * 2.f;
            float r = loop_r * (0.5f + 6.f * mPerlin.noise(sin(a) * 0.4f));

            for (int pair = 0; pair < 2; pair++) {
                mElement.draw(Vec3f(cos(a) * r * 2.f + loop_center * side, 0.f,
                                    sin(a) * r + loop_r * 1.5f), t);
                r += path_r;
            }
        }
    }
}

CINDER_APP_NATIVE( VibrissaSketchApp, RendererGl )
<commit_msg>Fullscreen on "f" key<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/MayaCamUI.h"
#include "cinder/Perlin.h"
#include "cinder/gl/Fbo.h"

#include "VibrissaElement.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class VibrissaSketchApp : public AppNative {
  public:
	void setup();
	void update();
	void draw();
    void prepareSettings(Settings *settings);

    void mouseDown(MouseEvent event);
    void mouseDrag(MouseEvent event);
    void resize();
    void keyDown(KeyEvent event);

protected:
    MayaCamUI mMayaCam;
    VibrissaElement mElement;
    Perlin mPerlin;

    gl::Fbo mFboScene;
    gl::Fbo mFboBlur1;
    gl::Fbo mFboBlur2;
    gl::GlslProg mBlurShader;
    gl::GlslProg mPostShader;

    void drawScene();
    void drawElements();
    void drawGrid(float size=100.0f, float step=5.0f);
    void drawVibrissa(Vec3f origin);
};

void VibrissaSketchApp::keyDown(KeyEvent event)
{
    if (event.getCode() == KeyEvent::KEY_f) {
        bool fs = !isFullScreen();
        setFullScreen(fs);
        if (fs) {
            hideCursor();
        } else {
            showCursor();
        }
    }
}

void VibrissaSketchApp::setup()
{
    gl::Fbo::Format fmt;
    fmt.setColorInternalFormat(GL_RGB32F_ARB);

    mFboScene = gl::Fbo(getWindowWidth() * 2, getWindowHeight() * 2, fmt);
    mFboBlur1 = gl::Fbo(getWindowWidth() / 4, getWindowHeight() / 4, fmt);
    mFboBlur2 = gl::Fbo(getWindowWidth() / 4, getWindowHeight() / 4, fmt);

    mBlurShader = gl::GlslProg(loadResource("blur.glslv"), loadResource("blur.glslf"));
    mPostShader = gl::GlslProg(loadResource("post.glslv"), loadResource("post.glslf"));

    mElement.setup(*this);

    CameraPersp cam;
    cam.setEyePoint( Vec3f(5.0f, 1.5f, -5.0f) );
    cam.setCenterOfInterestPoint( Vec3f(20.f, 5.f, 4.f) );
    cam.setPerspective( 60.0f, getWindowAspectRatio(), 1.0f, 1000.0f );
    mMayaCam.setCurrentCam( cam );
}

void VibrissaSketchApp::prepareSettings( Settings *settings )
{
    settings->setWindowSize( 1920, 1080 );
    settings->setFrameRate( 60.0f );
}

void VibrissaSketchApp::mouseDown( MouseEvent event )
{
    mMayaCam.mouseDown( event.getPos() );
}

void VibrissaSketchApp::mouseDrag( MouseEvent event )
{
    mMayaCam.mouseDrag(event.getPos(),
                       event.isLeftDown() && !event.isShiftDown(),
                       event.isMiddleDown() || event.isShiftDown(),
                       event.isRightDown() );
}

void VibrissaSketchApp::resize()
{
    CameraPersp cam = mMayaCam.getCamera();
    cam.setAspectRatio( getWindowAspectRatio() );
    mMayaCam.setCurrentCam( cam );
}

void VibrissaSketchApp::update()
{
    mElement.update();
}

void VibrissaSketchApp::drawGrid(float size, float step)
{
    float gray = 0.12f;
    gl::color( Colorf(gray, gray, gray) );

    for (float i=-size;i<=size;i+=step) {
        gl::drawLine( Vec3f(i, 0.0f, -size), Vec3f(i, 0.0f, size) );
        gl::drawLine( Vec3f(-size, 0.0f, i), Vec3f(size, 0.0f, i) );
    }
}

void VibrissaSketchApp::draw()
{
    mFboScene.bindFramebuffer();
    gl::setViewport(mFboScene.getBounds());
    gl::enableDepthRead();
    gl::enableDepthWrite();

    drawScene();

    mFboScene.unbindFramebuffer();
    gl::disableDepthRead();
    gl::disableDepthWrite();
    gl::color(1.f, 1.f, 1.f);

    const float atten = 2.5f;
    for (unsigned step = 0; step < 10; step++) {

        // Horizontal blur
        mFboBlur1.bindFramebuffer();
        gl::setViewport(mFboBlur1.getBounds());
        gl::setMatricesWindow(mFboBlur1.getSize());
        mBlurShader.bind();
        mBlurShader.uniform("tex0", 0);
        mBlurShader.uniform("sample_offset", Vec2f(1.f / mFboBlur1.getWidth(), 0.f));
        mBlurShader.uniform("attenuation", step ? 1.f : atten);
        gl::draw(step ? mFboBlur2.getTexture() : mFboScene.getTexture(),
                 Rectf(Vec2f(0,0), mFboBlur1.getSize()));
        mBlurShader.unbind();
        mFboBlur1.unbindFramebuffer();

        // Vertical blur
        mFboBlur2.bindFramebuffer();
        gl::setViewport(mFboBlur2.getBounds());
        gl::setMatricesWindow(mFboBlur2.getSize());
        mBlurShader.bind();
        mBlurShader.uniform("tex0", 0);
        mBlurShader.uniform("sample_offset", Vec2f(0.f, 1.f / mFboBlur2.getWidth()));
        mBlurShader.uniform("attenuation", 1.f);
        gl::draw(mFboBlur1.getTexture(), Rectf(Vec2f(0,0), mFboBlur2.getSize()));
        mBlurShader.unbind();
        mFboBlur2.unbindFramebuffer();
    }

    // Final scene, combine blurred and unblurred
    gl::setViewport(getWindowBounds());
    gl::setMatricesWindow(getWindowSize(), false);
    mPostShader.bind();
    mPostShader.uniform("scene", 0);
    mPostShader.uniform("blurred", 1);
    mFboBlur2.getTexture().bind(1);
    gl::draw(mFboScene.getTexture(), Rectf(Vec2f(0,0), getWindowSize()));
    mPostShader.unbind();
}

void VibrissaSketchApp::drawScene()
{
    float gray = 0.02f;
    gl::clear(Colorf(gray, gray, gray));

    gl::setMatrices(mMayaCam.getCamera());
    drawGrid();
    drawElements();
}

void VibrissaSketchApp::drawElements()
{
    const float kMetersPerInch = 0.0254f;
    const float kMetersPerFoot = kMetersPerInch * 12;

    float extent = 540 * kMetersPerFoot;
    float spacing = 20 * kMetersPerFoot;

    // Line of elements along the front
    for (float t = 0.f; t <= 1.f; t += spacing / extent) {
        mElement.draw(Vec3f((t - 0.5f) * extent, 0.f, 0.f), t);
    }

    float loop_center = (225 + 150) * kMetersPerFoot / 2;
    float loop_r = 80 * kMetersPerFoot / 2;
    float path_r = 6 * kMetersPerFoot;

    // Loops along path
    for (int side = -1; side <= 1; side += 2) {

        for (float t = 0.f; t < 1.f; t += 0.1f) {
            float a = t * M_PI * 2.f;
            float r = loop_r * (0.5f + 6.f * mPerlin.noise(sin(a) * 0.4f));

            for (int pair = 0; pair < 2; pair++) {
                mElement.draw(Vec3f(cos(a) * r * 2.f + loop_center * side, 0.f,
                                    sin(a) * r + loop_r * 1.5f), t);
                r += path_r;
            }
        }
    }
}

CINDER_APP_NATIVE( VibrissaSketchApp, RendererGl )
<|endoftext|>