<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qnetworksession_p.h"
#include "qnetworksession.h"
#include "qnetworksessionengine_win_p.h"
#include "qnlaengine_win_p.h"

#ifndef Q_OS_WINCE
#include "qnativewifiengine_win_p.h"
#include "qioctlwifiengine_win_p.h"
#endif

#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>

#include <QtNetwork/qnetworkinterface.h>

QT_BEGIN_NAMESPACE

static QNetworkSessionEngine *getEngineFromId(const QString &id)
{
    QNlaEngine *nla = QNlaEngine::instance();
    if (nla && nla->hasIdentifier(id))
        return nla;

#ifndef Q_OS_WINCE
    QNativeWifiEngine *nativeWifi = QNativeWifiEngine::instance();
    if (nativeWifi && nativeWifi->hasIdentifier(id))
        return nativeWifi;

    QIoctlWifiEngine *ioctlWifi = QIoctlWifiEngine::instance();
    if (ioctlWifi && ioctlWifi->hasIdentifier(id))
        return ioctlWifi;
#endif

    return 0;
}

class QNetworkSessionManagerPrivate : public QObject
{
    Q_OBJECT

public:
    QNetworkSessionManagerPrivate(QObject *parent = 0);
    ~QNetworkSessionManagerPrivate();

    void forceSessionClose(const QNetworkConfiguration &config);

Q_SIGNALS:
    void forcedSessionClose(const QNetworkConfiguration &config);
};

#include "qnetworksession_win.moc"

Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager);

QNetworkSessionManagerPrivate::QNetworkSessionManagerPrivate(QObject *parent)
:   QObject(parent)
{
}

QNetworkSessionManagerPrivate::~QNetworkSessionManagerPrivate()
{
}

void QNetworkSessionManagerPrivate::forceSessionClose(const QNetworkConfiguration &config)
{
    emit forcedSessionClose(config);
}

void QNetworkSessionPrivate::syncStateWithInterface()
{
    connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
    connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)),
            this, SLOT(configurationChanged(QNetworkConfiguration)));
    connect(sessionManager(), SIGNAL(forcedSessionClose(QNetworkConfiguration)),
            this, SLOT(forcedSessionClose(QNetworkConfiguration)));

    opened = false;
    state = QNetworkSession::Invalid;
    lastError = QNetworkSession::UnknownSessionError;

    qRegisterMetaType<QNetworkSessionEngine::ConnectionError>
        ("QNetworkSessionEngine::ConnectionError");

    switch (publicConfig.type()) {
    case QNetworkConfiguration::InternetAccessPoint:
        activeConfig = publicConfig;
        engine = getEngineFromId(activeConfig.identifier());
        connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                Qt::QueuedConnection);
        break;
    case QNetworkConfiguration::ServiceNetwork:
        serviceConfig = publicConfig;
        // Defer setting engine and signals until open().
        // fall through
    case QNetworkConfiguration::UserChoice:
        // Defer setting serviceConfig and activeConfig until open().
        // fall through
    default:
        engine = 0;
    }

    networkConfigurationsChanged();
}

void QNetworkSessionPrivate::open()
{
    if (serviceConfig.isValid()) {
        lastError = QNetworkSession::OperationNotSupportedError;
        emit q->error(lastError);
    } else if (!isActive) {
        if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
            QNetworkConfiguration::Discovered) {
            lastError =QNetworkSession::InvalidConfigurationError;
            emit q->error(lastError);
            return;
        }
        opened = true;

        if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active &&
            (activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
            state = QNetworkSession::Connecting;
            emit q->stateChanged(state);

            engine->connectToId(activeConfig.identifier());
        }

        isActive = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
        if (isActive)
            emit quitPendingWaitsForOpened();
    }
}

void QNetworkSessionPrivate::close()
{
    if (serviceConfig.isValid()) {
        lastError = QNetworkSession::OperationNotSupportedError;
        emit q->error(lastError);
    } else if (isActive) {
        opened = false;
        isActive = false;
        emit q->sessionClosed();
    }
}

void QNetworkSessionPrivate::stop()
{
    if (serviceConfig.isValid()) {
        lastError = QNetworkSession::OperationNotSupportedError;
        emit q->error(lastError);
    } else {
        if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
            state = QNetworkSession::Closing;
            emit q->stateChanged(state);

            engine->disconnectFromId(activeConfig.identifier());

            sessionManager()->forceSessionClose(activeConfig);
        }

        opened = false;
        isActive = false;
        emit q->sessionClosed();
    }
}

void QNetworkSessionPrivate::migrate()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

void QNetworkSessionPrivate::accept()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

void QNetworkSessionPrivate::ignore()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

void QNetworkSessionPrivate::reject()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

QNetworkInterface QNetworkSessionPrivate::currentInterface() const
{
    if (!publicConfig.isValid() || !engine || state != QNetworkSession::Connected)
        return QNetworkInterface();

    QString interface = engine->getInterfaceFromId(activeConfig.identifier());

    if (interface.isEmpty())
        return QNetworkInterface();

    return QNetworkInterface::interfaceFromName(interface);
}

QVariant QNetworkSessionPrivate::property(const QString&)
{
    return QVariant();
}

QString QNetworkSessionPrivate::bearerName() const
{
    if (!publicConfig.isValid() || !engine)
        return QString();

    return engine->bearerName(activeConfig.identifier());
}

QString QNetworkSessionPrivate::errorString() const
{
    switch (lastError) {
    case QNetworkSession::UnknownSessionError:
        return tr("Unknown session error.");
    case QNetworkSession::SessionAbortedError:
        return tr("The session was aborted by the user or system.");
    case QNetworkSession::OperationNotSupportedError:
        return tr("The requested operation is not supported by the system.");
    case QNetworkSession::InvalidConfigurationError:
        return tr("The specified configuration cannot be used.");
    }

    return QString();
}

QNetworkSession::SessionError QNetworkSessionPrivate::error() const
{
    return lastError;
}

quint64 QNetworkSessionPrivate::sentData() const
{
    return tx_data;
}

quint64 QNetworkSessionPrivate::receivedData() const
{
    return rx_data;
}

quint64 QNetworkSessionPrivate::activeTime() const
{
    return m_activeTime;
}

void QNetworkSessionPrivate::updateStateFromServiceNetwork()
{
    QNetworkSession::State oldState = state;

    foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
        if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
            continue;

        if (activeConfig != config) {
            if (engine) {
                disconnect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                           this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)));
            }

            activeConfig = config;
            engine = getEngineFromId(activeConfig.identifier());
            connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                    this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                    Qt::QueuedConnection);
            emit q->newConfigurationActivated();
        }

        state = QNetworkSession::Connected;
        if (state != oldState)
            emit q->stateChanged(state);

        return;
    }

    // No active configurations found, must be disconnected.
    state = QNetworkSession::Disconnected;
    if (state != oldState)
        emit q->stateChanged(state);
}

void QNetworkSessionPrivate::updateStateFromActiveConfig()
{
    QNetworkSession::State oldState = state;

    bool newActive = false;

    if (!activeConfig.isValid()) {
        state = QNetworkSession::Invalid;
    } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
        state = QNetworkSession::Connected;
        newActive = opened;
    } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
        state = QNetworkSession::Disconnected;
    } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
        state = QNetworkSession::NotAvailable;
    } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
        state = QNetworkSession::NotAvailable;
    }

    bool oldActive = isActive;
    isActive = newActive;

    if (!oldActive && isActive)
        emit quitPendingWaitsForOpened();
    if (oldActive && !isActive)
        emit q->sessionClosed();

    if (oldState != state)
        emit q->stateChanged(state);
}

void QNetworkSessionPrivate::networkConfigurationsChanged()
{
    if (serviceConfig.isValid())
        updateStateFromServiceNetwork();
    else
        updateStateFromActiveConfig();
}

void QNetworkSessionPrivate::configurationChanged(const QNetworkConfiguration &config)
{
    if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
        updateStateFromServiceNetwork();
    else if (config == activeConfig)
        updateStateFromActiveConfig();
}

void QNetworkSessionPrivate::forcedSessionClose(const QNetworkConfiguration &config)
{
    if (activeConfig == config) {
        opened = false;
        isActive = false;

        emit q->sessionClosed();

        lastError = QNetworkSession::SessionAbortedError;
        emit q->error(lastError);
    }
}

void QNetworkSessionPrivate::connectionError(const QString &id, QNetworkSessionEngine::ConnectionError error)
{
    if (activeConfig.identifier() == id) {
        switch (error) {
        case QNetworkSessionEngine::OperationNotSupported:
            lastError = QNetworkSession::OperationNotSupportedError;
            opened = false;
            break;
        case QNetworkSessionEngine::InterfaceLookupError:
        case QNetworkSessionEngine::ConnectError:
        case QNetworkSessionEngine::DisconnectionError:
        default:
            lastError = QNetworkSession::UnknownSessionError;
        }

        emit q->error(lastError);
    }
}

QT_END_NAMESPACE

<commit_msg>Fix incorrect session state.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qnetworksession_p.h"
#include "qnetworksession.h"
#include "qnetworksessionengine_win_p.h"
#include "qnlaengine_win_p.h"

#ifndef Q_OS_WINCE
#include "qnativewifiengine_win_p.h"
#include "qioctlwifiengine_win_p.h"
#endif

#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>

#include <QtNetwork/qnetworkinterface.h>

QT_BEGIN_NAMESPACE

static QNetworkSessionEngine *getEngineFromId(const QString &id)
{
    QNlaEngine *nla = QNlaEngine::instance();
    if (nla && nla->hasIdentifier(id))
        return nla;

#ifndef Q_OS_WINCE
    QNativeWifiEngine *nativeWifi = QNativeWifiEngine::instance();
    if (nativeWifi && nativeWifi->hasIdentifier(id))
        return nativeWifi;

    QIoctlWifiEngine *ioctlWifi = QIoctlWifiEngine::instance();
    if (ioctlWifi && ioctlWifi->hasIdentifier(id))
        return ioctlWifi;
#endif

    return 0;
}

class QNetworkSessionManagerPrivate : public QObject
{
    Q_OBJECT

public:
    QNetworkSessionManagerPrivate(QObject *parent = 0);
    ~QNetworkSessionManagerPrivate();

    void forceSessionClose(const QNetworkConfiguration &config);

Q_SIGNALS:
    void forcedSessionClose(const QNetworkConfiguration &config);
};

#include "qnetworksession_win.moc"

Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager);

QNetworkSessionManagerPrivate::QNetworkSessionManagerPrivate(QObject *parent)
:   QObject(parent)
{
}

QNetworkSessionManagerPrivate::~QNetworkSessionManagerPrivate()
{
}

void QNetworkSessionManagerPrivate::forceSessionClose(const QNetworkConfiguration &config)
{
    emit forcedSessionClose(config);
}

void QNetworkSessionPrivate::syncStateWithInterface()
{
    connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
    connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)),
            this, SLOT(configurationChanged(QNetworkConfiguration)));
    connect(sessionManager(), SIGNAL(forcedSessionClose(QNetworkConfiguration)),
            this, SLOT(forcedSessionClose(QNetworkConfiguration)));

    opened = false;
    state = QNetworkSession::Invalid;
    lastError = QNetworkSession::UnknownSessionError;

    qRegisterMetaType<QNetworkSessionEngine::ConnectionError>
        ("QNetworkSessionEngine::ConnectionError");

    switch (publicConfig.type()) {
    case QNetworkConfiguration::InternetAccessPoint:
        activeConfig = publicConfig;
        engine = getEngineFromId(activeConfig.identifier());
        connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                Qt::QueuedConnection);
        break;
    case QNetworkConfiguration::ServiceNetwork:
        serviceConfig = publicConfig;
        // Defer setting engine and signals until open().
        // fall through
    case QNetworkConfiguration::UserChoice:
        // Defer setting serviceConfig and activeConfig until open().
        // fall through
    default:
        engine = 0;
    }

    networkConfigurationsChanged();
}

void QNetworkSessionPrivate::open()
{
    if (serviceConfig.isValid()) {
        lastError = QNetworkSession::OperationNotSupportedError;
        emit q->error(lastError);
    } else if (!isActive) {
        if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
            QNetworkConfiguration::Discovered) {
            lastError =QNetworkSession::InvalidConfigurationError;
            emit q->error(lastError);
            return;
        }
        opened = true;

        if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active &&
            (activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
            state = QNetworkSession::Connecting;
            emit q->stateChanged(state);

            engine->connectToId(activeConfig.identifier());
        }

        isActive = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
        if (isActive)
            emit quitPendingWaitsForOpened();
    }
}

void QNetworkSessionPrivate::close()
{
    if (serviceConfig.isValid()) {
        lastError = QNetworkSession::OperationNotSupportedError;
        emit q->error(lastError);
    } else if (isActive) {
        opened = false;
        isActive = false;
        emit q->sessionClosed();
    }
}

void QNetworkSessionPrivate::stop()
{
    if (serviceConfig.isValid()) {
        lastError = QNetworkSession::OperationNotSupportedError;
        emit q->error(lastError);
    } else {
        if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
            state = QNetworkSession::Closing;
            emit q->stateChanged(state);

            engine->disconnectFromId(activeConfig.identifier());

            sessionManager()->forceSessionClose(activeConfig);
        }

        opened = false;
        isActive = false;
        emit q->sessionClosed();
    }
}

void QNetworkSessionPrivate::migrate()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

void QNetworkSessionPrivate::accept()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

void QNetworkSessionPrivate::ignore()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

void QNetworkSessionPrivate::reject()
{
    qFatal("Function not implemented at %s.", __FUNCTION__);
}

QNetworkInterface QNetworkSessionPrivate::currentInterface() const
{
    if (!publicConfig.isValid() || !engine || state != QNetworkSession::Connected)
        return QNetworkInterface();

    QString interface = engine->getInterfaceFromId(activeConfig.identifier());

    if (interface.isEmpty())
        return QNetworkInterface();

    return QNetworkInterface::interfaceFromName(interface);
}

QVariant QNetworkSessionPrivate::property(const QString&)
{
    return QVariant();
}

QString QNetworkSessionPrivate::bearerName() const
{
    if (!publicConfig.isValid() || !engine)
        return QString();

    return engine->bearerName(activeConfig.identifier());
}

QString QNetworkSessionPrivate::errorString() const
{
    switch (lastError) {
    case QNetworkSession::UnknownSessionError:
        return tr("Unknown session error.");
    case QNetworkSession::SessionAbortedError:
        return tr("The session was aborted by the user or system.");
    case QNetworkSession::OperationNotSupportedError:
        return tr("The requested operation is not supported by the system.");
    case QNetworkSession::InvalidConfigurationError:
        return tr("The specified configuration cannot be used.");
    }

    return QString();
}

QNetworkSession::SessionError QNetworkSessionPrivate::error() const
{
    return lastError;
}

quint64 QNetworkSessionPrivate::sentData() const
{
    return tx_data;
}

quint64 QNetworkSessionPrivate::receivedData() const
{
    return rx_data;
}

quint64 QNetworkSessionPrivate::activeTime() const
{
    return m_activeTime;
}

void QNetworkSessionPrivate::updateStateFromServiceNetwork()
{
    QNetworkSession::State oldState = state;

    foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
        if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
            continue;

        if (activeConfig != config) {
            if (engine) {
                disconnect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                           this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)));
            }

            activeConfig = config;
            engine = getEngineFromId(activeConfig.identifier());
            connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                    this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)),
                    Qt::QueuedConnection);
            emit q->newConfigurationActivated();
        }

        state = QNetworkSession::Connected;
        if (state != oldState)
            emit q->stateChanged(state);

        return;
    }

    if (serviceConfig.children().isEmpty())
        state = QNetworkSession::NotAvailable;
    else
        state = QNetworkSession::Disconnected;

    if (state != oldState)
        emit q->stateChanged(state);
}

void QNetworkSessionPrivate::updateStateFromActiveConfig()
{
    QNetworkSession::State oldState = state;

    bool newActive = false;

    if (!activeConfig.isValid()) {
        state = QNetworkSession::Invalid;
    } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
        state = QNetworkSession::Connected;
        newActive = opened;
    } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
        state = QNetworkSession::Disconnected;
    } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
        state = QNetworkSession::NotAvailable;
    } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
        state = QNetworkSession::NotAvailable;
    }

    bool oldActive = isActive;
    isActive = newActive;

    if (!oldActive && isActive)
        emit quitPendingWaitsForOpened();
    if (oldActive && !isActive)
        emit q->sessionClosed();

    if (oldState != state)
        emit q->stateChanged(state);
}

void QNetworkSessionPrivate::networkConfigurationsChanged()
{
    if (serviceConfig.isValid())
        updateStateFromServiceNetwork();
    else
        updateStateFromActiveConfig();
}

void QNetworkSessionPrivate::configurationChanged(const QNetworkConfiguration &config)
{
    if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
        updateStateFromServiceNetwork();
    else if (config == activeConfig)
        updateStateFromActiveConfig();
}

void QNetworkSessionPrivate::forcedSessionClose(const QNetworkConfiguration &config)
{
    if (activeConfig == config) {
        opened = false;
        isActive = false;

        emit q->sessionClosed();

        lastError = QNetworkSession::SessionAbortedError;
        emit q->error(lastError);
    }
}

void QNetworkSessionPrivate::connectionError(const QString &id, QNetworkSessionEngine::ConnectionError error)
{
    if (activeConfig.identifier() == id) {
        switch (error) {
        case QNetworkSessionEngine::OperationNotSupported:
            lastError = QNetworkSession::OperationNotSupportedError;
            opened = false;
            break;
        case QNetworkSessionEngine::InterfaceLookupError:
        case QNetworkSessionEngine::ConnectError:
        case QNetworkSessionEngine::DisconnectionError:
        default:
            lastError = QNetworkSession::UnknownSessionError;
        }

        emit q->error(lastError);
    }
}

QT_END_NAMESPACE

<|endoftext|>


<commit_before>/**
 *
 * main
 * ledger-core
 *
 * Created by Pierre Pollastri on 15/09/2016.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Ledger
 *
 * 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 <algorithm>
#include <gtest/gtest.h>
#include <iostream>
#include <memory>
#include <vector>

#include <api/OperationType.hpp>
#include <api/TimePeriod.hpp>
#include <utils/DateUtils.hpp>
#include <utils/Option.hpp>
#include <wallet/common/BalanceHistory.hpp>

using namespace ledger::core;
using namespace std;
using namespace std::chrono;

struct DummyOperation {
    int32_t amount;
    api::OperationType ty;
    system_clock::time_point date;

    DummyOperation(int32_t amount_, api::OperationType ty_, system_clock::time_point date_)
        : amount(amount_), ty(ty_), date(date_) {
    }

    ~DummyOperation() = default;
};

TEST(BalanceHistory, ZeroesOutOfRange) {
    // a basic collections of “operations” with nothing
    std::vector<DummyOperation> operations;
    auto start = DateUtils::fromJSON("2019-01-01T00:00:00Z");
    auto end = DateUtils::fromJSON("2019-02-01T00:00:00Z");

    auto balances = agnostic::getBalanceHistoryFor<int32_t, int32_t, int32_t>(
        start,
        end,
        api::TimePeriod::DAY,
        operations.cbegin(),
        operations.cend(),
        [](DummyOperation& op) { return op.date; },
        [](DummyOperation& op) { return op.ty; },
        [](DummyOperation& op) { return op.amount; },
        [](DummyOperation&)  { return Option<int32_t>(); },
        0
    );

    auto size = balances.size();
    EXPECT_EQ(size, 31);

    auto all_zero = all_of(balances.cbegin(), balances.cend(), [](shared_ptr<int32_t> const& balance) {
        return *balance == 0;
    });
    EXPECT_TRUE(all_zero);
}
<commit_msg>Add more getBalanceHistoryFor unit tests.<commit_after>/**
 *
 * main
 * ledger-core
 *
 * Created by Pierre Pollastri on 15/09/2016.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Ledger
 *
 * 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 <algorithm>
#include <gtest/gtest.h>
#include <iostream>
#include <memory>
#include <vector>

#include <api/OperationType.hpp>
#include <api/TimePeriod.hpp>
#include <utils/DateUtils.hpp>
#include <utils/Option.hpp>
#include <wallet/common/BalanceHistory.hpp>

using namespace ledger::core;
using namespace std;
using namespace std::chrono;

struct DummyOperation {
    int32_t amount;
    api::OperationType ty;
    system_clock::time_point date;

    DummyOperation(int32_t amount_, api::OperationType ty_, system_clock::time_point date_)
        : amount(amount_), ty(ty_), date(date_) {
    }

    ~DummyOperation() = default;
};

TEST(BalanceHistory, ZeroesOutOfRange) {
    // a basic collections of “operations” with nothing
    std::vector<DummyOperation> operations;
    auto start = DateUtils::fromJSON("2019-01-01T00:00:00Z");
    auto end = DateUtils::fromJSON("2019-02-01T00:00:00Z");

    auto balances = agnostic::getBalanceHistoryFor<int32_t, int32_t, int32_t>(
        start,
        end,
        api::TimePeriod::DAY,
        operations.cbegin(),
        operations.cend(),
        [](DummyOperation& op) { return op.date; },
        [](DummyOperation& op) { return op.ty; },
        [](DummyOperation& op) { return op.amount; },
        [](DummyOperation&)  { return Option<int32_t>(); },
        0
    );

    auto size = balances.size();
    EXPECT_EQ(size, 31);

    auto all_zero = all_of(balances.cbegin(), balances.cend(), [](shared_ptr<int32_t> const& balance) {
        return *balance == 0;
    });
    EXPECT_TRUE(all_zero);
}

TEST(BalanceHistory, CorrectBalances) {
    // a basic collections of “operations” with nothing
    std::vector<DummyOperation> operations = {
        DummyOperation(10, api::OperationType::RECEIVE, DateUtils::fromJSON("2019-01-01T00:00:00Z")),
        DummyOperation(12, api::OperationType::RECEIVE, DateUtils::fromJSON("2019-01-01T00:01:00Z")),
        DummyOperation(5, api::OperationType::SEND, DateUtils::fromJSON("2019-01-02T04:00:00Z")),
        DummyOperation(3, api::OperationType::SEND, DateUtils::fromJSON("2019-01-02T04:30:00Z"))
    };

    auto start = DateUtils::fromJSON("2019-01-01T00:00:00Z");
    auto end = DateUtils::fromJSON("2019-02-01T00:00:00Z");

    auto balances = agnostic::getBalanceHistoryFor<int32_t, int32_t, int32_t>(
        start,
        end,
        api::TimePeriod::DAY,
        operations.cbegin(),
        operations.cend(),
        [](DummyOperation& op) { return op.date; },
        [](DummyOperation& op) { return op.ty; },
        [](DummyOperation& op) { return op.amount; },
        [](DummyOperation&)  { return Option<int32_t>(); },
        0
    );

    auto size = balances.size();
    EXPECT_EQ(size, 31);

    EXPECT_EQ(*balances[0], 22);
    EXPECT_EQ(*balances[1], 14);
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <unsupported/Eigen/Polynomials>
#include <iostream>
#include <algorithm>

using namespace std;

namespace Eigen {
namespace internal {
template<int Size>
struct increment_if_fixed_size
{
  enum {
    ret = (Size == Dynamic) ? Dynamic : Size+1
  };
};
}
}

template<int Deg, typename POLYNOMIAL, typename SOLVER>
bool aux_evalSolver( const POLYNOMIAL& pols, SOLVER& psolve )
{
  typedef typename POLYNOMIAL::Index Index;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef typename SOLVER::RootsType    RootsType;
  typedef Matrix<Scalar,Deg,1>          EvalRootsType;

  const Index deg = pols.size()-1;

  psolve.compute( pols );
  const RootsType& roots( psolve.roots() );
  EvalRootsType evr( deg );
  for( int i=0; i<roots.size(); ++i ){
    evr[i] = std::abs( poly_eval( pols, roots[i] ) ); }

  bool evalToZero = evr.isZero( test_precision<Scalar>() );
  if( !evalToZero )
  {
    cerr << "WRONG root: " << endl;
    cerr << "Polynomial: " << pols.transpose() << endl;
    cerr << "Roots found: " << roots.transpose() << endl;
    cerr << "Abs value of the polynomial at the roots: " << evr.transpose() << endl;
    cerr << endl;
  }

  std::vector<Scalar> rootModuli( roots.size() );
  Map< EvalRootsType > aux( &rootModuli[0], roots.size() );
  aux = roots.array().abs();
  std::sort( rootModuli.begin(), rootModuli.end() );
  bool distinctModuli=true;
  for( size_t i=1; i<rootModuli.size() && distinctModuli; ++i )
  {
    if( internal::isApprox( rootModuli[i], rootModuli[i-1] ) ){
      distinctModuli = false; }
  }
  VERIFY( evalToZero || !distinctModuli );

  return distinctModuli;
}

template<int Deg, typename POLYNOMIAL>
void evalSolver( const POLYNOMIAL& pols )
{
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve );
}

template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
{
  using std::sqrt;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  if( aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve ) )
  {
    //It is supposed that
    // 1) the roots found are correct
    // 2) the roots have distinct moduli

    typedef typename POLYNOMIAL::Scalar                 Scalar;
    typedef typename REAL_ROOTS::Scalar                 Real;

    //Test realRoots
    std::vector< Real > calc_realRoots;
    psolve.realRoots( calc_realRoots );
    VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );

    const Scalar psPrec = sqrt( test_precision<Scalar>() );

    for( size_t i=0; i<calc_realRoots.size(); ++i )
    {
      bool found = false;
      for( size_t j=0; j<calc_realRoots.size()&& !found; ++j )
      {
        if( internal::isApprox( calc_realRoots[i], real_roots[j], psPrec ) ){
          found = true; }
      }
      VERIFY( found );
    }

    //Test greatestRoot
    VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
          abs( psolve.greatestRoot() ), psPrec ) );

    //Test smallestRoot
    VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
          abs( psolve.smallestRoot() ), psPrec ) );

    bool hasRealRoot;
    //Test absGreatestRealRoot
    Real r = psolve.absGreatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), abs(r), psPrec ) );  }

    //Test absSmallestRealRoot
    r = psolve.absSmallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), abs( r ), psPrec ) ); }

    //Test greatestRealRoot
    r = psolve.greatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().maxCoeff(), r, psPrec ) ); }

    //Test smallestRealRoot
    r = psolve.smallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
    VERIFY( internal::isApprox( real_roots.array().minCoeff(), r, psPrec ) ); }
  }
}

template<typename _Scalar, int _Deg>
void polynomialsolver(int deg)
{
  typedef internal::increment_if_fixed_size<_Deg>            Dim;
  typedef Matrix<_Scalar,Dim::ret,1>                  PolynomialType;
  typedef Matrix<_Scalar,_Deg,1>                      EvalRootsType;

  cout << "Standard cases" << endl;
  PolynomialType pols = PolynomialType::Random(deg+1);
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Hard cases" << endl;
  _Scalar multipleRoot = internal::random<_Scalar>();
  EvalRootsType allRoots = EvalRootsType::Constant(deg,multipleRoot);
  roots_to_monicPolynomial( allRoots, pols );
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Test sugar" << endl;
  EvalRootsType realRoots = EvalRootsType::Random(deg);
  roots_to_monicPolynomial( realRoots, pols );
  evalSolverSugarFunction<_Deg>(
      pols,
      realRoots.template cast <
                    std::complex<
                         typename NumTraits<_Scalar>::Real
                         >
                    >(),
      realRoots );
}

void test_polynomialsolver()
{
  for(int i = 0; i < g_repeat; i++)
  {
    CALL_SUBTEST_1( (polynomialsolver<float,1>(1)) );
    CALL_SUBTEST_2( (polynomialsolver<double,2>(2)) );
    CALL_SUBTEST_3( (polynomialsolver<double,3>(3)) );
    CALL_SUBTEST_4( (polynomialsolver<float,4>(4)) );
    CALL_SUBTEST_5( (polynomialsolver<double,5>(5)) );
    CALL_SUBTEST_6( (polynomialsolver<float,6>(6)) );
    CALL_SUBTEST_7( (polynomialsolver<float,7>(7)) );
    CALL_SUBTEST_8( (polynomialsolver<double,8>(8)) );

    CALL_SUBTEST_9( (polynomialsolver<float,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_10((polynomialsolver<double,Dynamic>(
            internal::random<int>(9,13)
            )) );
  }
}
<commit_msg>PolynomialSolver: add a test to reveal a bug.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <unsupported/Eigen/Polynomials>
#include <iostream>
#include <algorithm>

using namespace std;

namespace Eigen {
namespace internal {
template<int Size>
struct increment_if_fixed_size
{
  enum {
    ret = (Size == Dynamic) ? Dynamic : Size+1
  };
};
}
}

template<int Deg, typename POLYNOMIAL, typename SOLVER>
bool aux_evalSolver( const POLYNOMIAL& pols, SOLVER& psolve )
{
  typedef typename POLYNOMIAL::Index Index;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef typename SOLVER::RootsType    RootsType;
  typedef Matrix<Scalar,Deg,1>          EvalRootsType;

  const Index deg = pols.size()-1;

  psolve.compute( pols );
  const RootsType& roots( psolve.roots() );
  EvalRootsType evr( deg );
  for( int i=0; i<roots.size(); ++i ){
    evr[i] = std::abs( poly_eval( pols, roots[i] ) ); }

  bool evalToZero = evr.isZero( test_precision<Scalar>() );
  if( !evalToZero )
  {
    cerr << "WRONG root: " << endl;
    cerr << "Polynomial: " << pols.transpose() << endl;
    cerr << "Roots found: " << roots.transpose() << endl;
    cerr << "Abs value of the polynomial at the roots: " << evr.transpose() << endl;
    cerr << endl;
  }

  std::vector<Scalar> rootModuli( roots.size() );
  Map< EvalRootsType > aux( &rootModuli[0], roots.size() );
  aux = roots.array().abs();
  std::sort( rootModuli.begin(), rootModuli.end() );
  bool distinctModuli=true;
  for( size_t i=1; i<rootModuli.size() && distinctModuli; ++i )
  {
    if( internal::isApprox( rootModuli[i], rootModuli[i-1] ) ){
      distinctModuli = false; }
  }
  VERIFY( evalToZero || !distinctModuli );

  return distinctModuli;
}

template<int Deg, typename POLYNOMIAL>
void evalSolver( const POLYNOMIAL& pols )
{
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve );
}

template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
{
  using std::sqrt;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  if( aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve ) )
  {
    //It is supposed that
    // 1) the roots found are correct
    // 2) the roots have distinct moduli

    typedef typename POLYNOMIAL::Scalar                 Scalar;
    typedef typename REAL_ROOTS::Scalar                 Real;

    //Test realRoots
    std::vector< Real > calc_realRoots;
    psolve.realRoots( calc_realRoots );
    VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );

    const Scalar psPrec = sqrt( test_precision<Scalar>() );

    for( size_t i=0; i<calc_realRoots.size(); ++i )
    {
      bool found = false;
      for( size_t j=0; j<calc_realRoots.size()&& !found; ++j )
      {
        if( internal::isApprox( calc_realRoots[i], real_roots[j], psPrec ) ){
          found = true; }
      }
      VERIFY( found );
    }

    //Test greatestRoot
    VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
          abs( psolve.greatestRoot() ), psPrec ) );

    //Test smallestRoot
    VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
          abs( psolve.smallestRoot() ), psPrec ) );

    bool hasRealRoot;
    //Test absGreatestRealRoot
    Real r = psolve.absGreatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), abs(r), psPrec ) );  }

    //Test absSmallestRealRoot
    r = psolve.absSmallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), abs( r ), psPrec ) ); }

    //Test greatestRealRoot
    r = psolve.greatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().maxCoeff(), r, psPrec ) ); }

    //Test smallestRealRoot
    r = psolve.smallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
    VERIFY( internal::isApprox( real_roots.array().minCoeff(), r, psPrec ) ); }
  }
}

template<typename _Scalar, int _Deg>
void polynomialsolver(int deg)
{
  typedef internal::increment_if_fixed_size<_Deg>            Dim;
  typedef Matrix<_Scalar,Dim::ret,1>                  PolynomialType;
  typedef Matrix<_Scalar,_Deg,1>                      EvalRootsType;

  cout << "Standard cases" << endl;
  PolynomialType pols = PolynomialType::Random(deg+1);
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Hard cases" << endl;
  _Scalar multipleRoot = internal::random<_Scalar>();
  EvalRootsType allRoots = EvalRootsType::Constant(deg,multipleRoot);
  roots_to_monicPolynomial( allRoots, pols );
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Test sugar" << endl;
  EvalRootsType realRoots = EvalRootsType::Random(deg);
  roots_to_monicPolynomial( realRoots, pols );
  evalSolverSugarFunction<_Deg>(
      pols,
      realRoots.template cast <
                    std::complex<
                         typename NumTraits<_Scalar>::Real
                         >
                    >(),
      realRoots );
}

void test_polynomialsolver()
{
  for(int i = 0; i < g_repeat; i++)
  {
    CALL_SUBTEST_1( (polynomialsolver<float,1>(1)) );
    CALL_SUBTEST_2( (polynomialsolver<double,2>(2)) );
    CALL_SUBTEST_3( (polynomialsolver<double,3>(3)) );
    CALL_SUBTEST_4( (polynomialsolver<float,4>(4)) );
    CALL_SUBTEST_5( (polynomialsolver<double,5>(5)) );
    CALL_SUBTEST_6( (polynomialsolver<float,6>(6)) );
    CALL_SUBTEST_7( (polynomialsolver<float,7>(7)) );
    CALL_SUBTEST_8( (polynomialsolver<double,8>(8)) );

    CALL_SUBTEST_9( (polynomialsolver<float,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_10((polynomialsolver<double,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_11((polynomialsolver<float,Dynamic>(1)) );
  }
}
<|endoftext|>


<commit_before>#include "qgeomapreplygooglemaps.h"
#include <QNetworkAccessManager>
#include <QNetworkCacheMetaData>
#include <QDateTime>

QT_BEGIN_NAMESPACE

QGeoMapReplyGooglemaps::QGeoMapReplyGooglemaps(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent)
        : QGeoTiledMapReply(spec, parent),
        m_reply(reply)
{
    connect(m_reply,
            SIGNAL(finished()),
            this,
            SLOT(networkFinished()));

    connect(m_reply,
            SIGNAL(error(QNetworkReply::NetworkError)),
            this,
            SLOT(networkError(QNetworkReply::NetworkError)));
}

QGeoMapReplyGooglemaps::~QGeoMapReplyGooglemaps()
{
}

QNetworkReply *QGeoMapReplyGooglemaps::networkReply() const
{
    return m_reply;
}

void QGeoMapReplyGooglemaps::abort()
{
    if (!m_reply)
        return;

    m_reply->abort();
}

void QGeoMapReplyGooglemaps::networkFinished()
{
    if (!m_reply)
        return;

    if (m_reply->error() != QNetworkReply::NoError)
        return;

    setMapImageData(m_reply->readAll());
    setMapImageFormat("png");
    setFinished(true);

    m_reply->deleteLater();
    m_reply = 0;
}

void QGeoMapReplyGooglemaps::networkError(QNetworkReply::NetworkError error)
{
    if (!m_reply)
        return;

    if (error != QNetworkReply::OperationCanceledError)
        setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString());
    setFinished(true);
    m_reply->deleteLater();
    m_reply = 0;
}

QT_END_NAMESPACE
<commit_msg>Set correct file extentions<commit_after>#include "qgeomapreplygooglemaps.h"
#include <QNetworkAccessManager>
#include <QNetworkCacheMetaData>
#include <QDateTime>

QT_BEGIN_NAMESPACE

QGeoMapReplyGooglemaps::QGeoMapReplyGooglemaps(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent)
        : QGeoTiledMapReply(spec, parent),
        m_reply(reply)
{
    connect(m_reply,
            SIGNAL(finished()),
            this,
            SLOT(networkFinished()));

    connect(m_reply,
            SIGNAL(error(QNetworkReply::NetworkError)),
            this,
            SLOT(networkError(QNetworkReply::NetworkError)));
}

QGeoMapReplyGooglemaps::~QGeoMapReplyGooglemaps()
{
}

QNetworkReply *QGeoMapReplyGooglemaps::networkReply() const
{
    return m_reply;
}

void QGeoMapReplyGooglemaps::abort()
{
    if (!m_reply)
        return;

    m_reply->abort();
}

void QGeoMapReplyGooglemaps::networkFinished()
{
    if (!m_reply)
        return;

    if (m_reply->error() != QNetworkReply::NoError)
        return;

    setMapImageData(m_reply->readAll());
    const int _mid = tileSpec().mapId();
    if (_mid == 2)
        setMapImageFormat("jpeg");
    else
        setMapImageFormat("png");
    setFinished(true);

    m_reply->deleteLater();
    m_reply = 0;
}

void QGeoMapReplyGooglemaps::networkError(QNetworkReply::NetworkError error)
{
    if (!m_reply)
        return;

    if (error != QNetworkReply::OperationCanceledError)
        setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString());
    setFinished(true);
    m_reply->deleteLater();
    m_reply = 0;
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>AliAnalysisTaskNuclei* AddHighMultNucleiTask(TString name = "name", ULong64_t triggerMask = AliVEvent::kHighMultV0)
{
    // get the manager via the static access member. since it's static, you don't need
    // to create an instance of the class here to call the function
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
        return 0x0;
    }
    // get the input event handler, again via a static method.
    // this handler is part of the managing system and feeds events
    // to your task
    if (!mgr->GetInputEventHandler()) {
        return 0x0;
    }
    // by default, a file is open for writing. here, we get the filename
    TString fileName = AliAnalysisManager::GetCommonFileName();
    fileName += ":AntiHe3HM";      // create a subfolder in the file
    // now we create an instance of your task
    AliAnalysisTaskNuclei* task = new AliAnalysisTaskNuclei(name.Data());
    if(!task) return 0x0;
	//Add task settings here
	task->SelectCollisionCandidates(AliVEvent::kHighMultV0);
	task->SetFilterBit(16);
	task->SetLowPCut(0.1);
	task->SetHighPCut(1e30);
	task->SetEtaCut(0.8);
	task->SetMinNITSCl(1);
	task->SetMaxDCAxyPreCut(1.5);
	task->SetMaxDCAxyFinal(1.5);
	task->SetMaxDCAz(1.5);
	//set PID cuts #### Legacy code not used in analysis anymore ###
	task->SetMaxTPCnSigma(3.0);
	task->SetUseTOFPidCut(kFALSE);//kTRUE or kFALSE for use of TOF
	task->SetMaxTOFnSigma(3.0);
	// momentum p from which a hit/cut in TOF is required
	task->SetMomForTOFanaProt(0.7);
	task->SetMomForTOFanaDeut(1.4);
	task->SetAnalyseAllParticles(kTRUE);

	AliESDtrackCuts* trackCuts = new AliESDtrackCuts();
	trackCuts->SetPtRange(0.15, 1e30);
	trackCuts->SetEtaRange(-0.8, 0.8);
	/*
	//TPC
	trackCuts->SetRequireTPCRefit(kTRUE);
	trackCuts->SetMinNCrossedRowsTPC(110);
	trackCuts->SetMaxChi2PerClusterTPC(3.0);
	trackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.9);
	trackCuts->SetMaxFractionSharedTPCClusters(0.1);
	trackCuts->SetMaxChi2TPCConstrainedGlobal(25.);
	//ITS
	trackCuts->SetRequireITSRefit(kTRUE);
	trackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kFirst);
	trackCuts->SetMinNClustersITS(3);//This seems very high?

	//primary selection
	trackCuts->SetAcceptKinkDaughters(kFALSE);
	trackCuts->SetDCAToVertex2D(kFALSE);
	trackCuts->SetRequireSigmaToVertex(kFALSE);
	trackCuts->SetMaxDCAToVertexZ(10.0);
	trackCuts->SetMaxDCAToVertexXY(10.0);
	*/

	task->SetTrackCuts(trackCuts);

    // add your task to the manager
    mgr->AddTask(task);
    // your task needs input: here we connect the manager to your task
    mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());
    // same for the output
    mgr->ConnectOutput(task,1,mgr->CreateContainer("MyOutputContainerHighMult", TList::Class(), AliAnalysisManager::kOutputContainer, fileName.Data()));
    // in the end, this macro returns a pointer to your task. this will be convenient later on
    // when you will run your analysis in an analysis train on grid
    return task;
}
<commit_msg>Add suffix argument to AddTask<commit_after>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <Rtypes.h>
#include <TString.h>
#include "AliAnalysisTaskNuclei.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliPID.h"
#include "AliVEvent.h"
#include "AliESDtrackCuts.h"
#endif

AliAnalysisTaskNuclei* AddHighMultNucleiTask(TString tskname = "name", ULong64_t triggerMask = AliVEvent::kHighMultV0, TString suffix = "")
{
    // get the manager via the static access member. since it's static, you don't need
    // to create an instance of the class here to call the function
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
        return 0x0;
    }
    // get the input event handler, again via a static method.
    // this handler is part of the managing system and feeds events
    // to your task
    if (!mgr->GetInputEventHandler()) {
        return 0x0;
    }
    // by default, a file is open for writing. here, we get the filename
    TString fileName = AliAnalysisManager::GetCommonFileName();
    fileName += ":AntiHe3HM";      // create a subfolder in the file
    // now we create an instance of your task
		tskname.Append(Form("%s",suffix.Data()));
    AliAnalysisTaskNuclei* task = new AliAnalysisTaskNuclei(tskname.Data());
    if(!task) return 0x0;
	//Add task settings here
	task->SelectCollisionCandidates(AliVEvent::kHighMultV0);
	task->SetFilterBit(16);
	task->SetLowPCut(0.1);
	task->SetHighPCut(1e30);
	task->SetEtaCut(0.8);
	task->SetMinNITSCl(1);
	task->SetMaxDCAxyPreCut(1.5);
	task->SetMaxDCAxyFinal(1.5);
	task->SetMaxDCAz(1.5);
	//set PID cuts #### Legacy code not used in analysis anymore ###
	task->SetMaxTPCnSigma(3.0);
	task->SetUseTOFPidCut(kFALSE);//kTRUE or kFALSE for use of TOF
	task->SetMaxTOFnSigma(3.0);
	// momentum p from which a hit/cut in TOF is required
	task->SetMomForTOFanaProt(0.7);
	task->SetMomForTOFanaDeut(1.4);
	task->SetAnalyseAllParticles(kTRUE);

	AliESDtrackCuts* trackCuts = new AliESDtrackCuts();
	trackCuts->SetPtRange(0.15, 1e30);
	trackCuts->SetEtaRange(-0.8, 0.8);
	/*
	//TPC
	trackCuts->SetRequireTPCRefit(kTRUE);
	trackCuts->SetMinNCrossedRowsTPC(110);
	trackCuts->SetMaxChi2PerClusterTPC(3.0);
	trackCuts->SetMinRatioCrossedRowsOverFindableClustersTPC(0.9);
	trackCuts->SetMaxFractionSharedTPCClusters(0.1);
	trackCuts->SetMaxChi2TPCConstrainedGlobal(25.);
	//ITS
	trackCuts->SetRequireITSRefit(kTRUE);
	trackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kFirst);
	trackCuts->SetMinNClustersITS(3);//This seems very high?

	//primary selection
	trackCuts->SetAcceptKinkDaughters(kFALSE);
	trackCuts->SetDCAToVertex2D(kFALSE);
	trackCuts->SetRequireSigmaToVertex(kFALSE);
	trackCuts->SetMaxDCAToVertexZ(10.0);
	trackCuts->SetMaxDCAToVertexXY(10.0);
	*/

	task->SetTrackCuts(trackCuts);

    // add your task to the manager
    mgr->AddTask(task);
    // your task needs input: here we connect the manager to your task
    mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());
    // same for the output
    mgr->ConnectOutput(task,1,mgr->CreateContainer(Form("AbsorptionRatio_%s",tskname.Data()), TList::Class(), AliAnalysisManager::kOutputContainer, fileName.Data()));
    // in the end, this macro returns a pointer to your task. this will be convenient later on
    // when you will run your analysis in an analysis train on grid
    return task;
}
<|endoftext|>


<commit_before>#include "../data_structures/dynamic_graph.hpp"
#include "../data_structures/import_edge.hpp"
#include "../data_structures/query_node.hpp"
#include "../data_structures/restriction.hpp"
#include "../data_structures/static_graph.hpp"
#include "../util/fingerprint.hpp"
#include "../util/graph_loader.hpp"
#include "../util/integer_range.hpp"
#include "../util/make_unique.hpp"
#include "../util/osrm_exception.hpp"
#include "../util/simple_logger.hpp"

#include "../typedefs.h"

#include <algorithm>
#include <fstream>

struct TarjanEdgeData
{
    TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
    TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {}
    unsigned distance;
    unsigned name_id;
};

using StaticTestGraph = StaticGraph<TarjanEdgeData>;
using DynamicTestGraph = StaticGraph<TarjanEdgeData>;
using StaticEdge = StaticTestGraph::InputEdge;
using DynamicEdge = DynamicTestGraph::InputEdge;

int main(int argc, char *argv[])
{
    std::vector<QueryNode> coordinate_list;
    std::vector<TurnRestriction> restriction_list;
    std::vector<NodeID> bollard_node_list;
    std::vector<NodeID> traffic_lights_list;

    LogPolicy::GetInstance().Unmute();
    try
    {
        // enable logging
        if (argc < 3)
        {
            SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
                                             << " <osrm> <osrm.restrictions>";
            return -1;
        }

        SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
        std::ifstream restriction_ifstream(argv[2], std::ios::binary);
        const FingerPrint fingerprint_orig;
        FingerPrint fingerprint_loaded;
        restriction_ifstream.read(reinterpret_cast<char *>(&fingerprint_loaded),
                                  sizeof(FingerPrint));

        // check fingerprint and warn if necessary
        if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
        {
            SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
                                                           "Reprocess to get rid of this warning.";
        }

        if (!restriction_ifstream.good())
        {
            throw osrm::exception("Could not access <osrm-restrictions> files");
        }
        uint32_t usable_restrictions = 0;
        restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
        restriction_list.resize(usable_restrictions);

        // load restrictions
        if (usable_restrictions > 0)
        {
            restriction_ifstream.read(reinterpret_cast<char *>(&restriction_list[0]),
                                      usable_restrictions * sizeof(TurnRestriction));
        }
        restriction_ifstream.close();

        std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary);
        if (!input_stream.is_open())
        {
            throw osrm::exception("Cannot open osrm file");
        }

        // load graph data
        std::vector<ImportEdge> edge_list;
        const NodeID number_of_nodes =
            readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list,
                                          traffic_lights_list, &coordinate_list, restriction_list);
        input_stream.close();

        BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
                         "size of restriction_list changed");

        SimpleLogger().Write() << restriction_list.size() << " restrictions, "
                               << bollard_node_list.size() << " bollard nodes, "
                               << traffic_lights_list.size() << " traffic lights";

        traffic_lights_list.clear();
        traffic_lights_list.shrink_to_fit();

        // Building an node-based graph
        std::vector<StaticEdge> static_graph_edge_list;
        std::vector<DynamicEdge> dynamic_graph_edge_list;
        for (const auto &input_edge : edge_list)
        {
            if (input_edge.source == input_edge.target)
            {
                continue;
            }

            if (input_edge.forward)
            {
                static_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
                                                    (std::max)(input_edge.weight, 1),
                                                    input_edge.name_id);
                dynamic_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
                                                     (std::max)(input_edge.weight, 1),
                                                     input_edge.name_id);
            }
            if (input_edge.backward)
            {
                dynamic_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
                                                     (std::max)(input_edge.weight, 1),
                                                     input_edge.name_id);
                static_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
                                                    (std::max)(input_edge.weight, 1),
                                                    input_edge.name_id);
            }
        }
        edge_list.clear();
        edge_list.shrink_to_fit();
        BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(),
                         "input edge vector not properly deallocated");

        tbb::parallel_sort(static_graph_edge_list.begin(), static_graph_edge_list.end());
        tbb::parallel_sort(dynamic_graph_edge_list.begin(), dynamic_graph_edge_list.end());

        auto static_graph =
            osrm::make_unique<StaticTestGraph>(number_of_nodes, static_graph_edge_list);
        auto dynamic_graph =
            osrm::make_unique<DynamicTestGraph>(number_of_nodes, dynamic_graph_edge_list);

        SimpleLogger().Write() << "Starting static/dynamic graph comparison";

        BOOST_ASSERT(static_graph->GetNumberOfNodes() == dynamic_graph->GetNumberOfNodes());
        BOOST_ASSERT(static_graph->GetNumberOfEdges() == dynamic_graph->GetNumberOfEdges());
        for (const auto node : osrm::irange(0u, static_graph->GetNumberOfNodes()))
        {
            const auto static_range = static_graph->GetAdjacentEdgeRange(node);
            const auto dynamic_range = dynamic_graph->GetAdjacentEdgeRange(node);
            SimpleLogger().Write() << "checking node " << node << "/"
                                   << static_graph->GetNumberOfNodes();

            BOOST_ASSERT(static_range.size() == dynamic_range.size());
            const auto static_begin = static_graph->BeginEdges(node);
            const auto dynamic_begin = dynamic_graph->BeginEdges(node);

            // check raw interface
            for (int i = 0; i < static_range.size(); ++i)
            {
                const auto static_target = static_graph->GetTarget(static_begin + i);
                const auto dynamic_target = dynamic_graph->GetTarget(dynamic_begin + i);
                BOOST_ASSERT(static_target == dynamic_target);

                const auto static_data = static_graph->GetEdgeData(static_begin + i);
                const auto dynamic_data = dynamic_graph->GetEdgeData(dynamic_begin + i);

                BOOST_ASSERT(static_data.distance == dynamic_data.distance);
                BOOST_ASSERT(static_data.name_id == dynamic_data.name_id);
            }

            // check range interface
            std::vector<EdgeID> static_target_ids, dynamic_target_ids;
            std::vector<TarjanEdgeData> static_edge_data, dynamic_edge_data;
            for (const auto static_id : static_range)
            {
                static_target_ids.push_back(static_graph->GetTarget(static_id));
                static_edge_data.push_back(static_graph->GetEdgeData(static_id));
            }
            for (const auto dynamic_id : dynamic_range)
            {
                dynamic_target_ids.push_back(dynamic_graph->GetTarget(dynamic_id));
                dynamic_edge_data.push_back(dynamic_graph->GetEdgeData(dynamic_id));
            }
            BOOST_ASSERT(static_target_ids.size() == dynamic_target_ids.size());
            BOOST_ASSERT(std::equal(std::begin(static_target_ids), std::end(static_target_ids),
                                    std::begin(dynamic_target_ids)));
        }

        SimpleLogger().Write() << "Graph comparison finished successfully";
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
    }

    return 0;
}
<commit_msg>fix unintended signed/unsigned comparison<commit_after>#include "../data_structures/dynamic_graph.hpp"
#include "../data_structures/import_edge.hpp"
#include "../data_structures/query_node.hpp"
#include "../data_structures/restriction.hpp"
#include "../data_structures/static_graph.hpp"
#include "../util/fingerprint.hpp"
#include "../util/graph_loader.hpp"
#include "../util/integer_range.hpp"
#include "../util/make_unique.hpp"
#include "../util/osrm_exception.hpp"
#include "../util/simple_logger.hpp"

#include "../typedefs.h"

#include <algorithm>
#include <fstream>

struct TarjanEdgeData
{
    TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
    TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {}
    unsigned distance;
    unsigned name_id;
};

using StaticTestGraph = StaticGraph<TarjanEdgeData>;
using DynamicTestGraph = StaticGraph<TarjanEdgeData>;
using StaticEdge = StaticTestGraph::InputEdge;
using DynamicEdge = DynamicTestGraph::InputEdge;

int main(int argc, char *argv[])
{
    std::vector<QueryNode> coordinate_list;
    std::vector<TurnRestriction> restriction_list;
    std::vector<NodeID> bollard_node_list;
    std::vector<NodeID> traffic_lights_list;

    LogPolicy::GetInstance().Unmute();
    try
    {
        // enable logging
        if (argc < 3)
        {
            SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
                                             << " <osrm> <osrm.restrictions>";
            return -1;
        }

        SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
        std::ifstream restriction_ifstream(argv[2], std::ios::binary);
        const FingerPrint fingerprint_orig;
        FingerPrint fingerprint_loaded;
        restriction_ifstream.read(reinterpret_cast<char *>(&fingerprint_loaded),
                                  sizeof(FingerPrint));

        // check fingerprint and warn if necessary
        if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
        {
            SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
                                                           "Reprocess to get rid of this warning.";
        }

        if (!restriction_ifstream.good())
        {
            throw osrm::exception("Could not access <osrm-restrictions> files");
        }
        uint32_t usable_restrictions = 0;
        restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
        restriction_list.resize(usable_restrictions);

        // load restrictions
        if (usable_restrictions > 0)
        {
            restriction_ifstream.read(reinterpret_cast<char *>(&restriction_list[0]),
                                      usable_restrictions * sizeof(TurnRestriction));
        }
        restriction_ifstream.close();

        std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary);
        if (!input_stream.is_open())
        {
            throw osrm::exception("Cannot open osrm file");
        }

        // load graph data
        std::vector<ImportEdge> edge_list;
        const NodeID number_of_nodes =
            readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list,
                                          traffic_lights_list, &coordinate_list, restriction_list);
        input_stream.close();

        BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
                         "size of restriction_list changed");

        SimpleLogger().Write() << restriction_list.size() << " restrictions, "
                               << bollard_node_list.size() << " bollard nodes, "
                               << traffic_lights_list.size() << " traffic lights";

        traffic_lights_list.clear();
        traffic_lights_list.shrink_to_fit();

        // Building an node-based graph
        std::vector<StaticEdge> static_graph_edge_list;
        std::vector<DynamicEdge> dynamic_graph_edge_list;
        for (const auto &input_edge : edge_list)
        {
            if (input_edge.source == input_edge.target)
            {
                continue;
            }

            if (input_edge.forward)
            {
                static_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
                                                    (std::max)(input_edge.weight, 1),
                                                    input_edge.name_id);
                dynamic_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
                                                     (std::max)(input_edge.weight, 1),
                                                     input_edge.name_id);
            }
            if (input_edge.backward)
            {
                dynamic_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
                                                     (std::max)(input_edge.weight, 1),
                                                     input_edge.name_id);
                static_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
                                                    (std::max)(input_edge.weight, 1),
                                                    input_edge.name_id);
            }
        }
        edge_list.clear();
        edge_list.shrink_to_fit();
        BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(),
                         "input edge vector not properly deallocated");

        tbb::parallel_sort(static_graph_edge_list.begin(), static_graph_edge_list.end());
        tbb::parallel_sort(dynamic_graph_edge_list.begin(), dynamic_graph_edge_list.end());

        auto static_graph =
            osrm::make_unique<StaticTestGraph>(number_of_nodes, static_graph_edge_list);
        auto dynamic_graph =
            osrm::make_unique<DynamicTestGraph>(number_of_nodes, dynamic_graph_edge_list);

        SimpleLogger().Write() << "Starting static/dynamic graph comparison";

        BOOST_ASSERT(static_graph->GetNumberOfNodes() == dynamic_graph->GetNumberOfNodes());
        BOOST_ASSERT(static_graph->GetNumberOfEdges() == dynamic_graph->GetNumberOfEdges());
        for (const auto node : osrm::irange(0u, static_graph->GetNumberOfNodes()))
        {
            const auto static_range = static_graph->GetAdjacentEdgeRange(node);
            const auto dynamic_range = dynamic_graph->GetAdjacentEdgeRange(node);
            SimpleLogger().Write() << "checking node " << node << "/"
                                   << static_graph->GetNumberOfNodes();

            BOOST_ASSERT(static_range.size() == dynamic_range.size());
            const auto static_begin = static_graph->BeginEdges(node);
            const auto dynamic_begin = dynamic_graph->BeginEdges(node);

            // check raw interface
            for (const auto i : osrm::irange(0u, static_range.size()))
            {
                const auto static_target = static_graph->GetTarget(static_begin + i);
                const auto dynamic_target = dynamic_graph->GetTarget(dynamic_begin + i);
                BOOST_ASSERT(static_target == dynamic_target);

                const auto static_data = static_graph->GetEdgeData(static_begin + i);
                const auto dynamic_data = dynamic_graph->GetEdgeData(dynamic_begin + i);

                BOOST_ASSERT(static_data.distance == dynamic_data.distance);
                BOOST_ASSERT(static_data.name_id == dynamic_data.name_id);
            }

            // check range interface
            std::vector<EdgeID> static_target_ids, dynamic_target_ids;
            std::vector<TarjanEdgeData> static_edge_data, dynamic_edge_data;
            for (const auto static_id : static_range)
            {
                static_target_ids.push_back(static_graph->GetTarget(static_id));
                static_edge_data.push_back(static_graph->GetEdgeData(static_id));
            }
            for (const auto dynamic_id : dynamic_range)
            {
                dynamic_target_ids.push_back(dynamic_graph->GetTarget(dynamic_id));
                dynamic_edge_data.push_back(dynamic_graph->GetEdgeData(dynamic_id));
            }
            BOOST_ASSERT(static_target_ids.size() == dynamic_target_ids.size());
            BOOST_ASSERT(std::equal(std::begin(static_target_ids), std::end(static_target_ids),
                                    std::begin(dynamic_target_ids)));
        }

        SimpleLogger().Write() << "Graph comparison finished successfully";
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "QDataAnalysisView.h"
#include "QAction"
#include "QHeaderView"
#include <algorithm>
#include "simvis/color.h"
#include "xo/system/log.h"
#include "xo/utility/types.h"
#include "qtfx.h"
#include <array>
#include "xo/system/log.h"
#include "xo/container/sorted_vector.h"
#include "xo/numerical/constants.h"
#include "qt_convert.h"

QDataAnalysisView::QDataAnalysisView( QDataAnalysisModel* m, QWidget* parent ) :
	QWidget( parent ),
	model( m ),
	currentUpdateIdx( 0 )
{
	selectBox = new QCheckBox( this );
	connect( selectBox, &QCheckBox::stateChanged, this, &QDataAnalysisView::select );

	filter = new QLineEdit( this );
	connect( filter, &QLineEdit::textChanged, this, &QDataAnalysisView::filterChanged );

	auto* header = new QHGroup( this, 0, 4 );
	*header << new QLabel( "Filter", this ) << filter << selectBox;

	itemList = new QTreeWidget( this );
	itemList->setRootIsDecorated( false );
	itemList->setColumnCount( 2 );
	itemList->header()->close();
	itemList->resize( 100, 100 );
	QStringList headerLabels;
	headerLabels << "Variable" << "Value";
	itemList->setHeaderLabels( headerLabels );
	//itemList->setFrameStyle( QFrame::NoFrame );

	itemGroup = new QVGroup( this, 0, 4 );
	itemGroup->setContentsMargins( 0, 0, 0, 0 );
	*itemGroup << header << itemList;
	connect( itemList, &QTreeWidget::itemChanged, this, &QDataAnalysisView::itemChanged );

	splitter = new QSplitter( this );
	splitter->setContentsMargins( 0, 0, 0, 0 );
	splitter->setFrameShape( QFrame::NoFrame );
	splitter->setObjectName( "Analysis.Splitter" );
	splitter->addWidget( itemGroup );

	QVBoxLayout* layout = new QVBoxLayout( this );
	setLayout( layout );
	layout->setContentsMargins( 0, 0, 0, 0 );
	layout->setSpacing( 4 );
	layout->addWidget( splitter );

	for ( int i = 0; i < maxSeriesCount; ++i )
		freeColors.insert( i );

#if !defined QTFX_NO_QCUSTOMPLOT
	customPlot = new QCustomPlot();
	customPlot->setInteraction( QCP::iRangeZoom, true );
	customPlot->setInteraction( QCP::iRangeDrag, true );
	customPlot->axisRect()->setRangeDrag( Qt::Horizontal );
	customPlot->axisRect()->setRangeZoom( Qt::Horizontal );
	customPlot->legend->setVisible( true );
	customPlot->legend->setFont( itemList->font() );
	customPlot->legend->setRowSpacing( -6 );
	customPlotLine = new QCPItemLine( customPlot );
	customPlotLine->setHead( QCPLineEnding( QCPLineEnding::esDiamond, 9, 9, true ) );
	customPlotLine->setTail( QCPLineEnding( QCPLineEnding::esDiamond, 9, 9, true ) );
	customPlot->addItem( customPlotLine );
	splitter->addWidget( customPlot );
	connect( customPlot, &QCustomPlot::mousePress, this, &QDataAnalysisView::mouseEvent );
	connect( customPlot, &QCustomPlot::mouseMove, this, &QDataAnalysisView::mouseEvent );
	connect( customPlot->xAxis, SIGNAL( rangeChanged( const QCPRange&, const QCPRange& ) ), this, SLOT( rangeChanged( const QCPRange&, const QCPRange& ) ) );
#else
	chart = new QtCharts::QChart();
	chart->setBackgroundRoundness( 0 );
	chart->setMargins( QMargins( 4, 4, 4, 4 ) );
	chart->layout()->setContentsMargins( 0, 0, 0, 0 );
	chart->legend()->setAlignment( Qt::AlignRight );
	chart->createDefaultAxes();
	chartView = new QtCharts::QChartView( chart, this );
	chartView->setContentsMargins( 0, 0, 0, 0 );
	chartView->setRenderHint( QPainter::Antialiasing );
	chartView->setRubberBand( QtCharts::QChartView::RectangleRubberBand );
	chartView->setBackgroundBrush( QBrush( Qt::red ) );
	chartView->resize( 300, 100 );
	splitter->addWidget( chartView );
#endif

	splitter->setSizes( QList< int >{ 100, 300 } );
	reset();
}

int QDataAnalysisView::decimalPoints( double v )
{
	if ( v != 0 && xo::less_or_equal( abs( v ), 0.05 ) )
		return 6;
	else return 3;
}

void QDataAnalysisView::refresh( double time, bool refreshAll )
{
	if ( itemList->topLevelItemCount() != model->seriesCount() )
		return reset();

	if ( model->seriesCount() == 0 )
		return;

	// update state
	currentTime = time;

	// draw stuff if visible
	if ( isVisible() )
	{
		int itemCount = refreshAll ? model->seriesCount() : std::min<int>( smallRefreshItemCount, model->seriesCount() );
		itemList->setUpdatesEnabled( false );
		for ( size_t i = 0; i < itemCount; ++i )
		{
			auto y = model->value( currentUpdateIdx, time );
			itemList->topLevelItem( currentUpdateIdx )->setText( 1, QString().sprintf( "%.*f", decimalPoints( y ), y ) );
			++currentUpdateIdx %= model->seriesCount();
		}
		itemList->setUpdatesEnabled( true );

		// update graph
		updateIndicator();

#ifdef QTFX_USE_QCUSTOMPLOT
		customPlot->replot( QCustomPlot::rpQueued );
#endif
	}
}

void QDataAnalysisView::itemChanged( QTreeWidgetItem* item, int column )
{
	if ( column == 0 )
		updateSeries( itemList->indexOfTopLevelItem( item ) );
}

void QDataAnalysisView::clearSeries()
{
	while ( !series.empty() )
		removeSeries( series.rbegin()->channel );
}

void QDataAnalysisView::mouseEvent( QMouseEvent* event )
{
#if !defined QTFX_NO_QCUSTOMPLOT
	if ( event->buttons() & Qt::LeftButton )
	{
		double x = customPlot->xAxis->pixelToCoord( event->pos().x() );
		double t = model->timeValue( model->timeIndex( x ) );
		emit timeChanged( t );
	}
#endif
}

void QDataAnalysisView::rangeChanged( const QCPRange &newRange, const QCPRange &oldRange )
{
	QCPRange fixedRange = QCPRange( xo::max( newRange.lower, model->timeStart() ), xo::min( newRange.upper, model->timeFinish() ) );
	if ( fixedRange != newRange )
	{
		customPlot->xAxis->blockSignals( true );
		customPlot->xAxis->setRange( fixedRange );
		customPlot->xAxis->blockSignals( false );
	}

	updateSeriesStyle();
}

void QDataAnalysisView::filterChanged( const QString& filter )
{
	updateFilter();
}

void QDataAnalysisView::setSelectionState( int state )
{
	if ( state != Qt::PartiallyChecked )
	{
		for ( size_t i = 0; i < itemList->topLevelItemCount(); ++i )
		{
			auto* item = itemList->topLevelItem( i );
			if ( !item->isHidden() && item->checkState( 0 ) != state )
				item->setCheckState( 0, Qt::CheckState( state ) );
		}
	}
}

QColor QDataAnalysisView::getStandardColor( int idx )
{
	return to_qt( vis::make_unique_color( size_t( idx ) ) );
}

void QDataAnalysisView::reset()
{
	itemList->clear();
	clearSeries();

	for ( size_t i = 0; i < model->seriesCount(); ++i )
	{
		auto* wdg = new QTreeWidgetItem( itemList, QStringList( model->label( i ) ) );
		wdg->setTextAlignment( 1, Qt::AlignRight );
		wdg->setFlags( wdg->flags() | Qt::ItemIsUserCheckable );
		wdg->setCheckState( 0, persistentSerieNames.find( model->label( i ) ) != persistentSerieNames.end() ? Qt::Checked : Qt::Unchecked );
	}
	itemList->resizeColumnToContents( 0 );

	currentUpdateIdx = 0;
	currentTime = 0.0;
	updateIndicator();
	updateFilter();
}

void QDataAnalysisView::updateIndicator()
{
#if !defined QTFX_NO_QCUSTOMPLOT
	customPlotLine->start->setCoords( currentTime, customPlot->yAxis->range().lower );
	customPlotLine->end->setCoords( currentTime, customPlot->yAxis->range().upper );
	customPlot->replot();
#else
	auto pos = chart->mapToPosition( QPointF( currentTime, 0 ) );
#endif
}

void QDataAnalysisView::updateFilter()
{
	//selectAllButton->setDisabled( filter->text().isEmpty() );
	for ( size_t i = 0; i < itemList->topLevelItemCount(); ++i )
	{
		auto* item = itemList->topLevelItem( i );
		item->setHidden( !item->text( 0 ).contains( filter->text() ) );
	}

	updateSelectBox();
}

void QDataAnalysisView::updateSelectBox()
{
	size_t checked_count = 0;
	size_t shown_count = 0;

	for ( size_t i = 0; i < itemList->topLevelItemCount(); ++i )
	{
		auto* item = itemList->topLevelItem( i );
		if ( !item->isHidden() )
		{
			shown_count++;
			checked_count += item->checkState( 0 ) == Qt::Checked;
		}
	}

	selectBox->blockSignals( true );
	selectBox->setCheckState( checked_count > 0 ? ( shown_count == checked_count ? Qt::Checked : Qt::Checked ) : Qt::Unchecked );
	selectBox->blockSignals( false );
}

void QDataAnalysisView::updateSeriesStyle()
{
	auto zoom = currentSeriesInterval * customPlot->xAxis->axisRect()->width() / customPlot->xAxis->range().size();
	SeriesStyle newstyle = zoom > 8 ? discStyle : lineStyle;

	if ( newstyle != seriesStyle )
	{
		seriesStyle = newstyle;
		QCPScatterStyle ss = QCPScatterStyle( seriesStyle == discStyle ? QCPScatterStyle::ssDisc : QCPScatterStyle::ssNone, 4 );
		for ( auto& s : series )
		{
			s.graph->setScatterStyle( ss );
			s.graph->setLineStyle( QCPGraph::lsLine );
		}
	}
}

void QDataAnalysisView::updateSeries( int idx )
{
	auto item = itemList->topLevelItem( idx );
	auto series_it = xo::find_if( series, [&]( auto& p ) { return idx == p.channel; } );
	if ( item->checkState( 0 ) == Qt::Checked && series_it == series.end() )
	{
		if ( series.size() < maxSeriesCount )
		{
			addSeries( idx );
			persistentSerieNames.insert( model->label( idx ) );
		}
		else item->setCheckState( 0, Qt::Unchecked );
	}
	else if ( series_it != series.end() && item->checkState( 0 ) == Qt::Unchecked )
	{
		removeSeries( idx );
		persistentSerieNames.remove( model->label( idx ) );
	}
	updateSelectBox();
}

void QDataAnalysisView::addSeries( int idx )
{
#if !defined QTFX_NO_QCUSTOMPLOT
	QCPGraph* graph = customPlot->addGraph();
	QString name = model->label( idx );
	graph->setName( name );

	xo_assert( !freeColors.empty() );

	graph->setScatterStyle( QCPScatterStyle( seriesStyle == discStyle ? QCPScatterStyle::ssDisc : QCPScatterStyle::ssNone, 4 ) );
	graph->setPen( QPen( getStandardColor( freeColors.front() ), lineWidth ) );

	auto data = model->getSeries( idx, minSeriesInterval );
	for ( auto& e : data )
		graph->addData( e.first, e.second );

	series.emplace_back( Series{ idx, freeColors.front(), graph } );
	freeColors.erase( freeColors.begin() );

	currentSeriesInterval = ( data.back().first - data.front().first ) / data.size();

	updateSeriesStyle();

	auto range = customPlot->xAxis->range();
	customPlot->rescaleAxes();
	customPlot->xAxis->setRange( range );
	updateIndicator();
	customPlot->replot();

#else
	QtCharts::QLineSeries* ls = new QtCharts::QLineSeries;
	ls->setName( model->label( idx ) );
	auto data = model->getSeries( idx, minSeriesInterval );
	for ( auto& e : data )
		ls->append( e.first, e.second );
	chart->addSeries( ls );
	chart->createDefaultAxes();
	chart->zoomReset();
	series[ idx ] = ls;
#endif
}

void QDataAnalysisView::removeSeries( int idx )
{
#if !defined QTFX_NO_QCUSTOMPLOT
	auto range = customPlot->xAxis->range();
	auto it = xo::find_if( series, [&]( auto& p ) { return idx == p.channel; } );
	auto name = it->graph->name();

	freeColors.insert( it->color );

	customPlot->removeGraph( it->graph );
	series.erase( it );

	customPlot->rescaleAxes();
	customPlot->xAxis->setRange( range );
	updateIndicator();
	customPlot->replot();
#else
	auto it = series.find( idx );
	chart->removeSeries( it->second );
	chart->zoomReset();
	chart->createDefaultAxes();
	series.erase( it );
#endif
}
<commit_msg>U: const -> numconst<commit_after>#include "QDataAnalysisView.h"
#include "QAction"
#include "QHeaderView"
#include <algorithm>
#include "simvis/color.h"
#include "xo/system/log.h"
#include "xo/utility/types.h"
#include "qtfx.h"
#include <array>
#include "xo/system/log.h"
#include "xo/container/sorted_vector.h"
#include "xo/numerical/numconst.h"
#include "qt_convert.h"

QDataAnalysisView::QDataAnalysisView( QDataAnalysisModel* m, QWidget* parent ) :
	QWidget( parent ),
	model( m ),
	currentUpdateIdx( 0 )
{
	selectBox = new QCheckBox( this );
	connect( selectBox, &QCheckBox::stateChanged, this, &QDataAnalysisView::select );

	filter = new QLineEdit( this );
	connect( filter, &QLineEdit::textChanged, this, &QDataAnalysisView::filterChanged );

	auto* header = new QHGroup( this, 0, 4 );
	*header << new QLabel( "Filter", this ) << filter << selectBox;

	itemList = new QTreeWidget( this );
	itemList->setRootIsDecorated( false );
	itemList->setColumnCount( 2 );
	itemList->header()->close();
	itemList->resize( 100, 100 );
	QStringList headerLabels;
	headerLabels << "Variable" << "Value";
	itemList->setHeaderLabels( headerLabels );
	//itemList->setFrameStyle( QFrame::NoFrame );

	itemGroup = new QVGroup( this, 0, 4 );
	itemGroup->setContentsMargins( 0, 0, 0, 0 );
	*itemGroup << header << itemList;
	connect( itemList, &QTreeWidget::itemChanged, this, &QDataAnalysisView::itemChanged );

	splitter = new QSplitter( this );
	splitter->setContentsMargins( 0, 0, 0, 0 );
	splitter->setFrameShape( QFrame::NoFrame );
	splitter->setObjectName( "Analysis.Splitter" );
	splitter->addWidget( itemGroup );

	QVBoxLayout* layout = new QVBoxLayout( this );
	setLayout( layout );
	layout->setContentsMargins( 0, 0, 0, 0 );
	layout->setSpacing( 4 );
	layout->addWidget( splitter );

	for ( int i = 0; i < maxSeriesCount; ++i )
		freeColors.insert( i );

#if !defined QTFX_NO_QCUSTOMPLOT
	customPlot = new QCustomPlot();
	customPlot->setInteraction( QCP::iRangeZoom, true );
	customPlot->setInteraction( QCP::iRangeDrag, true );
	customPlot->axisRect()->setRangeDrag( Qt::Horizontal );
	customPlot->axisRect()->setRangeZoom( Qt::Horizontal );
	customPlot->legend->setVisible( true );
	customPlot->legend->setFont( itemList->font() );
	customPlot->legend->setRowSpacing( -6 );
	customPlotLine = new QCPItemLine( customPlot );
	customPlotLine->setHead( QCPLineEnding( QCPLineEnding::esDiamond, 9, 9, true ) );
	customPlotLine->setTail( QCPLineEnding( QCPLineEnding::esDiamond, 9, 9, true ) );
	customPlot->addItem( customPlotLine );
	splitter->addWidget( customPlot );
	connect( customPlot, &QCustomPlot::mousePress, this, &QDataAnalysisView::mouseEvent );
	connect( customPlot, &QCustomPlot::mouseMove, this, &QDataAnalysisView::mouseEvent );
	connect( customPlot->xAxis, SIGNAL( rangeChanged( const QCPRange&, const QCPRange& ) ), this, SLOT( rangeChanged( const QCPRange&, const QCPRange& ) ) );
#else
	chart = new QtCharts::QChart();
	chart->setBackgroundRoundness( 0 );
	chart->setMargins( QMargins( 4, 4, 4, 4 ) );
	chart->layout()->setContentsMargins( 0, 0, 0, 0 );
	chart->legend()->setAlignment( Qt::AlignRight );
	chart->createDefaultAxes();
	chartView = new QtCharts::QChartView( chart, this );
	chartView->setContentsMargins( 0, 0, 0, 0 );
	chartView->setRenderHint( QPainter::Antialiasing );
	chartView->setRubberBand( QtCharts::QChartView::RectangleRubberBand );
	chartView->setBackgroundBrush( QBrush( Qt::red ) );
	chartView->resize( 300, 100 );
	splitter->addWidget( chartView );
#endif

	splitter->setSizes( QList< int >{ 100, 300 } );
	reset();
}

int QDataAnalysisView::decimalPoints( double v )
{
	if ( v != 0 && xo::less_or_equal( abs( v ), 0.05 ) )
		return 6;
	else return 3;
}

void QDataAnalysisView::refresh( double time, bool refreshAll )
{
	if ( itemList->topLevelItemCount() != model->seriesCount() )
		return reset();

	if ( model->seriesCount() == 0 )
		return;

	// update state
	currentTime = time;

	// draw stuff if visible
	if ( isVisible() )
	{
		int itemCount = refreshAll ? model->seriesCount() : std::min<int>( smallRefreshItemCount, model->seriesCount() );
		itemList->setUpdatesEnabled( false );
		for ( size_t i = 0; i < itemCount; ++i )
		{
			auto y = model->value( currentUpdateIdx, time );
			itemList->topLevelItem( currentUpdateIdx )->setText( 1, QString().sprintf( "%.*f", decimalPoints( y ), y ) );
			++currentUpdateIdx %= model->seriesCount();
		}
		itemList->setUpdatesEnabled( true );

		// update graph
		updateIndicator();

#ifdef QTFX_USE_QCUSTOMPLOT
		customPlot->replot( QCustomPlot::rpQueued );
#endif
	}
}

void QDataAnalysisView::itemChanged( QTreeWidgetItem* item, int column )
{
	if ( column == 0 )
		updateSeries( itemList->indexOfTopLevelItem( item ) );
}

void QDataAnalysisView::clearSeries()
{
	while ( !series.empty() )
		removeSeries( series.rbegin()->channel );
}

void QDataAnalysisView::mouseEvent( QMouseEvent* event )
{
#if !defined QTFX_NO_QCUSTOMPLOT
	if ( event->buttons() & Qt::LeftButton )
	{
		double x = customPlot->xAxis->pixelToCoord( event->pos().x() );
		double t = model->timeValue( model->timeIndex( x ) );
		emit timeChanged( t );
	}
#endif
}

void QDataAnalysisView::rangeChanged( const QCPRange &newRange, const QCPRange &oldRange )
{
	QCPRange fixedRange = QCPRange( xo::max( newRange.lower, model->timeStart() ), xo::min( newRange.upper, model->timeFinish() ) );
	if ( fixedRange != newRange )
	{
		customPlot->xAxis->blockSignals( true );
		customPlot->xAxis->setRange( fixedRange );
		customPlot->xAxis->blockSignals( false );
	}

	updateSeriesStyle();
}

void QDataAnalysisView::filterChanged( const QString& filter )
{
	updateFilter();
}

void QDataAnalysisView::setSelectionState( int state )
{
	if ( state != Qt::PartiallyChecked )
	{
		for ( size_t i = 0; i < itemList->topLevelItemCount(); ++i )
		{
			auto* item = itemList->topLevelItem( i );
			if ( !item->isHidden() && item->checkState( 0 ) != state )
				item->setCheckState( 0, Qt::CheckState( state ) );
		}
	}
}

QColor QDataAnalysisView::getStandardColor( int idx )
{
	return to_qt( vis::make_unique_color( size_t( idx ) ) );
}

void QDataAnalysisView::reset()
{
	itemList->clear();
	clearSeries();

	for ( size_t i = 0; i < model->seriesCount(); ++i )
	{
		auto* wdg = new QTreeWidgetItem( itemList, QStringList( model->label( i ) ) );
		wdg->setTextAlignment( 1, Qt::AlignRight );
		wdg->setFlags( wdg->flags() | Qt::ItemIsUserCheckable );
		wdg->setCheckState( 0, persistentSerieNames.find( model->label( i ) ) != persistentSerieNames.end() ? Qt::Checked : Qt::Unchecked );
	}
	itemList->resizeColumnToContents( 0 );

	currentUpdateIdx = 0;
	currentTime = 0.0;
	updateIndicator();
	updateFilter();
}

void QDataAnalysisView::updateIndicator()
{
#if !defined QTFX_NO_QCUSTOMPLOT
	customPlotLine->start->setCoords( currentTime, customPlot->yAxis->range().lower );
	customPlotLine->end->setCoords( currentTime, customPlot->yAxis->range().upper );
	customPlot->replot();
#else
	auto pos = chart->mapToPosition( QPointF( currentTime, 0 ) );
#endif
}

void QDataAnalysisView::updateFilter()
{
	//selectAllButton->setDisabled( filter->text().isEmpty() );
	for ( size_t i = 0; i < itemList->topLevelItemCount(); ++i )
	{
		auto* item = itemList->topLevelItem( i );
		item->setHidden( !item->text( 0 ).contains( filter->text() ) );
	}

	updateSelectBox();
}

void QDataAnalysisView::updateSelectBox()
{
	size_t checked_count = 0;
	size_t shown_count = 0;

	for ( size_t i = 0; i < itemList->topLevelItemCount(); ++i )
	{
		auto* item = itemList->topLevelItem( i );
		if ( !item->isHidden() )
		{
			shown_count++;
			checked_count += item->checkState( 0 ) == Qt::Checked;
		}
	}

	selectBox->blockSignals( true );
	selectBox->setCheckState( checked_count > 0 ? ( shown_count == checked_count ? Qt::Checked : Qt::Checked ) : Qt::Unchecked );
	selectBox->blockSignals( false );
}

void QDataAnalysisView::updateSeriesStyle()
{
	auto zoom = currentSeriesInterval * customPlot->xAxis->axisRect()->width() / customPlot->xAxis->range().size();
	SeriesStyle newstyle = zoom > 8 ? discStyle : lineStyle;

	if ( newstyle != seriesStyle )
	{
		seriesStyle = newstyle;
		QCPScatterStyle ss = QCPScatterStyle( seriesStyle == discStyle ? QCPScatterStyle::ssDisc : QCPScatterStyle::ssNone, 4 );
		for ( auto& s : series )
		{
			s.graph->setScatterStyle( ss );
			s.graph->setLineStyle( QCPGraph::lsLine );
		}
	}
}

void QDataAnalysisView::updateSeries( int idx )
{
	auto item = itemList->topLevelItem( idx );
	auto series_it = xo::find_if( series, [&]( auto& p ) { return idx == p.channel; } );
	if ( item->checkState( 0 ) == Qt::Checked && series_it == series.end() )
	{
		if ( series.size() < maxSeriesCount )
		{
			addSeries( idx );
			persistentSerieNames.insert( model->label( idx ) );
		}
		else item->setCheckState( 0, Qt::Unchecked );
	}
	else if ( series_it != series.end() && item->checkState( 0 ) == Qt::Unchecked )
	{
		removeSeries( idx );
		persistentSerieNames.remove( model->label( idx ) );
	}
	updateSelectBox();
}

void QDataAnalysisView::addSeries( int idx )
{
#if !defined QTFX_NO_QCUSTOMPLOT
	QCPGraph* graph = customPlot->addGraph();
	QString name = model->label( idx );
	graph->setName( name );

	xo_assert( !freeColors.empty() );

	graph->setScatterStyle( QCPScatterStyle( seriesStyle == discStyle ? QCPScatterStyle::ssDisc : QCPScatterStyle::ssNone, 4 ) );
	graph->setPen( QPen( getStandardColor( freeColors.front() ), lineWidth ) );

	auto data = model->getSeries( idx, minSeriesInterval );
	for ( auto& e : data )
		graph->addData( e.first, e.second );

	series.emplace_back( Series{ idx, freeColors.front(), graph } );
	freeColors.erase( freeColors.begin() );

	currentSeriesInterval = ( data.back().first - data.front().first ) / data.size();

	updateSeriesStyle();

	auto range = customPlot->xAxis->range();
	customPlot->rescaleAxes();
	customPlot->xAxis->setRange( range );
	updateIndicator();
	customPlot->replot();

#else
	QtCharts::QLineSeries* ls = new QtCharts::QLineSeries;
	ls->setName( model->label( idx ) );
	auto data = model->getSeries( idx, minSeriesInterval );
	for ( auto& e : data )
		ls->append( e.first, e.second );
	chart->addSeries( ls );
	chart->createDefaultAxes();
	chart->zoomReset();
	series[ idx ] = ls;
#endif
}

void QDataAnalysisView::removeSeries( int idx )
{
#if !defined QTFX_NO_QCUSTOMPLOT
	auto range = customPlot->xAxis->range();
	auto it = xo::find_if( series, [&]( auto& p ) { return idx == p.channel; } );
	auto name = it->graph->name();

	freeColors.insert( it->color );

	customPlot->removeGraph( it->graph );
	series.erase( it );

	customPlot->rescaleAxes();
	customPlot->xAxis->setRange( range );
	updateIndicator();
	customPlot->replot();
#else
	auto it = series.find( idx );
	chart->removeSeries( it->second );
	chart->zoomReset();
	chart->createDefaultAxes();
	series.erase( it );
#endif
}
<|endoftext|>