<commit_before>/*
 * Convert any file descriptor to a pipe by splicing.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifdef __linux

#include "istream_pipe.hxx"
#include "istream_internal.hxx"
#include "fd_util.h"
#include "direct.hxx"
#include "pipe_stock.hxx"
#include "stock.hxx"
#include "gerrno.h"
#include "util/Cast.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

struct istream_pipe {
    struct istream output;
    struct istream *input;
    Stock *stock;
    StockItem *stock_item;
    int fds[2];
    size_t piped;
};

static void
pipe_close(struct istream_pipe *p)
{
    if (p->stock != nullptr) {
        if (p->stock_item != nullptr)
            /* reuse the pipe only if it's empty */
            stock_put(*p->stock_item, p->piped > 0);
    } else {
        if (p->fds[0] >= 0) {
            close(p->fds[0]);
            p->fds[0] = -1;
        }

        if (p->fds[1] >= 0) {
            close(p->fds[1]);
            p->fds[1] = -1;
        }
    }
}

static void
pipe_abort(struct istream_pipe *p, GError *error)
{
    pipe_close(p);

    if (p->input != nullptr)
        istream_close_handler(p->input);

    istream_deinit_abort(&p->output, error);
}

static ssize_t
pipe_consume(struct istream_pipe *p)
{
    ssize_t nbytes;

    assert(p->fds[0] >= 0);
    assert(p->piped > 0);
    assert(p->stock_item != nullptr || p->stock == nullptr);

    nbytes = istream_invoke_direct(&p->output, FdType::FD_PIPE, p->fds[0], p->piped);
    if (unlikely(nbytes == ISTREAM_RESULT_BLOCKING ||
                 nbytes == ISTREAM_RESULT_CLOSED))
        /* handler blocks (-2) or pipe was closed (-3) */
        return nbytes;

    if (unlikely(nbytes == ISTREAM_RESULT_ERRNO && errno != EAGAIN)) {
        GError *error = new_error_errno_msg("read from pipe failed");
        pipe_abort(p, error);
        return ISTREAM_RESULT_CLOSED;
    }

    if (nbytes > 0) {
        assert((size_t)nbytes <= p->piped);
        p->piped -= (size_t)nbytes;

        if (p->piped == 0 && p->stock != nullptr) {
            /* if the pipe was drained, return it to the stock, to
               make it available to other streams */

            stock_put(*p->stock_item, false);
            p->stock_item = nullptr;
            p->fds[0] = -1;
            p->fds[1] = -1;
        }

        if (p->piped == 0 && p->input == nullptr) {
            /* p->input has already reported EOF, and we have been
               waiting for the pipe buffer to become empty */
            pipe_close(p);
            istream_deinit_eof(&p->output);
            return ISTREAM_RESULT_CLOSED;
        }
    }

    return nbytes;
}

/*
 * istream handler
 *
 */

static size_t
pipe_input_data(const void *data, size_t length, void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    assert(p->output.handler != nullptr);

    if (p->piped > 0) {
        ssize_t nbytes = pipe_consume(p);
        if (nbytes == ISTREAM_RESULT_CLOSED)
            return 0;

        if (p->piped > 0 || p->output.handler == nullptr)
            return 0;
    }

    assert(p->piped == 0);

    return istream_invoke_data(&p->output, data, length);
}

static bool
pipe_create(struct istream_pipe *p)
{
    int ret;

    assert(p->fds[0] < 0);
    assert(p->fds[1] < 0);

    if (p->stock != nullptr) {
        assert(p->stock_item == nullptr);

        GError *error = nullptr;
        p->stock_item = stock_get_now(*p->stock, *p->output.pool, nullptr,
                                      &error);
        if (p->stock_item == nullptr) {
            daemon_log(1, "%s\n", error->message);
            g_error_free(error);
            return false;
        }

        pipe_stock_item_get(p->stock_item, p->fds);
    } else {
        ret = pipe_cloexec_nonblock(p->fds);
        if (ret < 0) {
            daemon_log(1, "pipe() failed: %s\n", strerror(errno));
            return false;
        }
    }

    return true;
}

static ssize_t
pipe_input_direct(FdType type, int fd, size_t max_length, void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;
    ssize_t nbytes;

    assert(p->output.handler != nullptr);
    assert(p->output.handler->direct != nullptr);
    assert(istream_check_direct(&p->output, FdType::FD_PIPE));

    if (p->piped > 0) {
        nbytes = pipe_consume(p);
        if (nbytes <= 0)
            return nbytes;

        if (p->piped > 0)
            /* if the pipe still isn't empty, we can't start reading
               new input */
            return ISTREAM_RESULT_BLOCKING;
    }

    if (istream_check_direct(&p->output, type))
        /* already supported by handler (maybe already a pipe) - no
           need for wrapping it into a pipe */
        return istream_invoke_direct(&p->output, type, fd, max_length);

    assert((type & ISTREAM_TO_PIPE) == type);

    if (p->fds[1] < 0 && !pipe_create(p))
        return ISTREAM_RESULT_CLOSED;

    nbytes = splice(fd, nullptr, p->fds[1], nullptr, max_length,
                    SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
    /* don't check EAGAIN here (and don't return -2).  We assume that
       splicing to the pipe cannot possibly block, since we flushed
       the pipe; assume that it can only be the source file which is
       blocking */
    if (nbytes <= 0)
        return nbytes;

    assert(p->piped == 0);
    p->piped = (size_t)nbytes;

    if (pipe_consume(p) == ISTREAM_RESULT_CLOSED)
        return ISTREAM_RESULT_CLOSED;

    return nbytes;
}

static void
pipe_input_eof(void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    p->input = nullptr;

    if (p->stock == nullptr && p->fds[1] >= 0) {
        close(p->fds[1]);
        p->fds[1] = -1;
    }

    if (p->piped == 0) {
        pipe_close(p);
        istream_deinit_eof(&p->output);
    }
}

static void
pipe_input_abort(GError *error, void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    pipe_close(p);

    p->input = nullptr;
    istream_deinit_abort(&p->output, error);
}

static const struct istream_handler pipe_input_handler = {
    .data = pipe_input_data,
    .direct = pipe_input_direct,
    .eof = pipe_input_eof,
    .abort = pipe_input_abort,
};

/*
 * istream implementation
 *
 */

static inline struct istream_pipe *
istream_to_pipe(struct istream *istream)
{
    return &ContainerCast2(*istream, &istream_pipe::output);
}

static off_t
istream_pipe_available(struct istream *istream, bool partial)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    if (likely(p->input != nullptr)) {
        off_t available = istream_available(p->input, partial);
        if (p->piped > 0) {
            if (available != -1)
                available += p->piped;
            else if (partial)
                available = p->piped;
        }

        return available;
    } else {
        assert(p->piped > 0);

        return p->piped;
    }
}

static void
istream_pipe_read(struct istream *istream)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    if (p->piped > 0 && (pipe_consume(p) <= 0 || p->piped > 0))
        return;

    /* at this point, the pipe must be flushed - if the pipe is
       flushed, this stream is either closed or there must be an input
       stream */
    assert(p->input != nullptr);

    auto mask = p->output.handler_direct;
    if (mask & FdType::FD_PIPE)
        /* if the handler supports the pipe, we offer our services */
        mask |= ISTREAM_TO_PIPE;

    istream_handler_set_direct(p->input, mask);
    istream_read(p->input);
}

static int
istream_pipe_as_fd(struct istream *istream)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    if (p->piped > 0)
        /* need to flush the pipe buffer first */
        return -1;

    int fd = istream_as_fd(p->input);
    if (fd >= 0) {
        pipe_close(p);
        istream_deinit(&p->output);
    }

    return fd;
}

static void
istream_pipe_close(struct istream *istream)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    pipe_close(p);

    if (p->input != nullptr)
        istream_close_handler(p->input);

    istream_deinit(&p->output);
}

static const struct istream_class istream_pipe = {
    .available = istream_pipe_available,
    .read = istream_pipe_read,
    .as_fd = istream_pipe_as_fd,
    .close = istream_pipe_close,
};

/*
 * constructor
 *
 */

struct istream *
istream_pipe_new(struct pool *pool, struct istream *input,
                 Stock *pipe_stock)
{
    struct istream_pipe *p = istream_new_macro(pool, pipe);

    assert(input != nullptr);
    assert(!istream_has_handler(input));

    p->stock = pipe_stock;
    p->stock_item = nullptr;
    p->fds[0] = -1;
    p->fds[1] = -1;
    p->piped = 0;

    istream_assign_handler(&p->input, input,
                           &pipe_input_handler, p,
                           0);

    return &p->output;
}

#endif
<commit_msg>istream/pipe: make variables more local<commit_after>/*
 * Convert any file descriptor to a pipe by splicing.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifdef __linux

#include "istream_pipe.hxx"
#include "istream_internal.hxx"
#include "fd_util.h"
#include "direct.hxx"
#include "pipe_stock.hxx"
#include "stock.hxx"
#include "gerrno.h"
#include "util/Cast.hxx"

#include <daemon/log.h>

#include <assert.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

struct istream_pipe {
    struct istream output;
    struct istream *input;
    Stock *stock;
    StockItem *stock_item;
    int fds[2];
    size_t piped;
};

static void
pipe_close(struct istream_pipe *p)
{
    if (p->stock != nullptr) {
        if (p->stock_item != nullptr)
            /* reuse the pipe only if it's empty */
            stock_put(*p->stock_item, p->piped > 0);
    } else {
        if (p->fds[0] >= 0) {
            close(p->fds[0]);
            p->fds[0] = -1;
        }

        if (p->fds[1] >= 0) {
            close(p->fds[1]);
            p->fds[1] = -1;
        }
    }
}

static void
pipe_abort(struct istream_pipe *p, GError *error)
{
    pipe_close(p);

    if (p->input != nullptr)
        istream_close_handler(p->input);

    istream_deinit_abort(&p->output, error);
}

static ssize_t
pipe_consume(struct istream_pipe *p)
{
    assert(p->fds[0] >= 0);
    assert(p->piped > 0);
    assert(p->stock_item != nullptr || p->stock == nullptr);

    ssize_t nbytes = istream_invoke_direct(&p->output, FdType::FD_PIPE,
                                           p->fds[0], p->piped);
    if (unlikely(nbytes == ISTREAM_RESULT_BLOCKING ||
                 nbytes == ISTREAM_RESULT_CLOSED))
        /* handler blocks (-2) or pipe was closed (-3) */
        return nbytes;

    if (unlikely(nbytes == ISTREAM_RESULT_ERRNO && errno != EAGAIN)) {
        GError *error = new_error_errno_msg("read from pipe failed");
        pipe_abort(p, error);
        return ISTREAM_RESULT_CLOSED;
    }

    if (nbytes > 0) {
        assert((size_t)nbytes <= p->piped);
        p->piped -= (size_t)nbytes;

        if (p->piped == 0 && p->stock != nullptr) {
            /* if the pipe was drained, return it to the stock, to
               make it available to other streams */

            stock_put(*p->stock_item, false);
            p->stock_item = nullptr;
            p->fds[0] = -1;
            p->fds[1] = -1;
        }

        if (p->piped == 0 && p->input == nullptr) {
            /* p->input has already reported EOF, and we have been
               waiting for the pipe buffer to become empty */
            pipe_close(p);
            istream_deinit_eof(&p->output);
            return ISTREAM_RESULT_CLOSED;
        }
    }

    return nbytes;
}

/*
 * istream handler
 *
 */

static size_t
pipe_input_data(const void *data, size_t length, void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    assert(p->output.handler != nullptr);

    if (p->piped > 0) {
        ssize_t nbytes = pipe_consume(p);
        if (nbytes == ISTREAM_RESULT_CLOSED)
            return 0;

        if (p->piped > 0 || p->output.handler == nullptr)
            return 0;
    }

    assert(p->piped == 0);

    return istream_invoke_data(&p->output, data, length);
}

static bool
pipe_create(struct istream_pipe *p)
{
    assert(p->fds[0] < 0);
    assert(p->fds[1] < 0);

    if (p->stock != nullptr) {
        assert(p->stock_item == nullptr);

        GError *error = nullptr;
        p->stock_item = stock_get_now(*p->stock, *p->output.pool, nullptr,
                                      &error);
        if (p->stock_item == nullptr) {
            daemon_log(1, "%s\n", error->message);
            g_error_free(error);
            return false;
        }

        pipe_stock_item_get(p->stock_item, p->fds);
    } else {
        if (pipe_cloexec_nonblock(p->fds) < 0) {
            daemon_log(1, "pipe() failed: %s\n", strerror(errno));
            return false;
        }
    }

    return true;
}

static ssize_t
pipe_input_direct(FdType type, int fd, size_t max_length, void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    assert(p->output.handler != nullptr);
    assert(p->output.handler->direct != nullptr);
    assert(istream_check_direct(&p->output, FdType::FD_PIPE));

    if (p->piped > 0) {
        ssize_t nbytes = pipe_consume(p);
        if (nbytes <= 0)
            return nbytes;

        if (p->piped > 0)
            /* if the pipe still isn't empty, we can't start reading
               new input */
            return ISTREAM_RESULT_BLOCKING;
    }

    if (istream_check_direct(&p->output, type))
        /* already supported by handler (maybe already a pipe) - no
           need for wrapping it into a pipe */
        return istream_invoke_direct(&p->output, type, fd, max_length);

    assert((type & ISTREAM_TO_PIPE) == type);

    if (p->fds[1] < 0 && !pipe_create(p))
        return ISTREAM_RESULT_CLOSED;

    ssize_t nbytes = splice(fd, nullptr, p->fds[1], nullptr, max_length,
                            SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
    /* don't check EAGAIN here (and don't return -2).  We assume that
       splicing to the pipe cannot possibly block, since we flushed
       the pipe; assume that it can only be the source file which is
       blocking */
    if (nbytes <= 0)
        return nbytes;

    assert(p->piped == 0);
    p->piped = (size_t)nbytes;

    if (pipe_consume(p) == ISTREAM_RESULT_CLOSED)
        return ISTREAM_RESULT_CLOSED;

    return nbytes;
}

static void
pipe_input_eof(void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    p->input = nullptr;

    if (p->stock == nullptr && p->fds[1] >= 0) {
        close(p->fds[1]);
        p->fds[1] = -1;
    }

    if (p->piped == 0) {
        pipe_close(p);
        istream_deinit_eof(&p->output);
    }
}

static void
pipe_input_abort(GError *error, void *ctx)
{
    struct istream_pipe *p = (struct istream_pipe *)ctx;

    pipe_close(p);

    p->input = nullptr;
    istream_deinit_abort(&p->output, error);
}

static const struct istream_handler pipe_input_handler = {
    .data = pipe_input_data,
    .direct = pipe_input_direct,
    .eof = pipe_input_eof,
    .abort = pipe_input_abort,
};

/*
 * istream implementation
 *
 */

static inline struct istream_pipe *
istream_to_pipe(struct istream *istream)
{
    return &ContainerCast2(*istream, &istream_pipe::output);
}

static off_t
istream_pipe_available(struct istream *istream, bool partial)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    if (likely(p->input != nullptr)) {
        off_t available = istream_available(p->input, partial);
        if (p->piped > 0) {
            if (available != -1)
                available += p->piped;
            else if (partial)
                available = p->piped;
        }

        return available;
    } else {
        assert(p->piped > 0);

        return p->piped;
    }
}

static void
istream_pipe_read(struct istream *istream)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    if (p->piped > 0 && (pipe_consume(p) <= 0 || p->piped > 0))
        return;

    /* at this point, the pipe must be flushed - if the pipe is
       flushed, this stream is either closed or there must be an input
       stream */
    assert(p->input != nullptr);

    auto mask = p->output.handler_direct;
    if (mask & FdType::FD_PIPE)
        /* if the handler supports the pipe, we offer our services */
        mask |= ISTREAM_TO_PIPE;

    istream_handler_set_direct(p->input, mask);
    istream_read(p->input);
}

static int
istream_pipe_as_fd(struct istream *istream)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    if (p->piped > 0)
        /* need to flush the pipe buffer first */
        return -1;

    int fd = istream_as_fd(p->input);
    if (fd >= 0) {
        pipe_close(p);
        istream_deinit(&p->output);
    }

    return fd;
}

static void
istream_pipe_close(struct istream *istream)
{
    struct istream_pipe *p = istream_to_pipe(istream);

    pipe_close(p);

    if (p->input != nullptr)
        istream_close_handler(p->input);

    istream_deinit(&p->output);
}

static const struct istream_class istream_pipe = {
    .available = istream_pipe_available,
    .read = istream_pipe_read,
    .as_fd = istream_pipe_as_fd,
    .close = istream_pipe_close,
};

/*
 * constructor
 *
 */

struct istream *
istream_pipe_new(struct pool *pool, struct istream *input,
                 Stock *pipe_stock)
{
    struct istream_pipe *p = istream_new_macro(pool, pipe);

    assert(input != nullptr);
    assert(!istream_has_handler(input));

    p->stock = pipe_stock;
    p->stock_item = nullptr;
    p->fds[0] = -1;
    p->fds[1] = -1;
    p->piped = 0;

    istream_assign_handler(&p->input, input,
                           &pipe_input_handler, p,
                           0);

    return &p->output;
}

#endif
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007   Andrew Manson   <g.real.ate@gmail.com>
// Copyright 2009   Eckhart Wörner  <ewoerner@kde.org>
// Copyright 2010   Thibaut Gridel  <tgridel@free.fr>
//

#include "PositionTracking.h"

#include "GeoDataDocument.h"
#include "GeoDataPlacemark.h"
#include "GeoDataStyle.h"
#include "GeoDataStyleMap.h"
#include "AbstractProjection.h"
#include "FileManager.h"
#include "MarbleMath.h"
#include "MarbleDebug.h"
#include "PositionProviderPlugin.h"

#include "PositionTracking_p.h"

using namespace Marble;

void PositionTrackingPrivate::setPosition( GeoDataCoordinates position,
                                           GeoDataAccuracy accuracy )
{
    Q_UNUSED( accuracy );
    if ( m_positionProvider && m_positionProvider->status() ==
        PositionProviderStatusAvailable )
    {
        GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(m_document->child(m_document->size()-1));
        //GeoDataMultiGeometry *geometry = static_cast<GeoDataMultiGeometry*>(placemark->geometry());
        m_currentLineString->append(position);

        //if the position has moved then update the current position
        if ( !( m_gpsCurrentPosition ==
                position ) )
        {
            placemark = static_cast<GeoDataPlacemark*>(m_document->child(0));
            placemark->setCoordinate(position);
            m_gpsCurrentPosition = position;
            qreal speed = m_positionProvider->speed();
            emit gpsLocation( position, speed );
        }
    }
}

void PositionTrackingPrivate::setStatus( PositionProviderStatus status )
{
    if (status == PositionProviderStatusAvailable) {
        Q_ASSERT(m_document);
        GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(m_document->child(m_document->size()-1));
        GeoDataMultiGeometry *multiGeometry = static_cast<GeoDataMultiGeometry*>(placemark->geometry());
        m_currentLineString = new GeoDataLineString;
        multiGeometry->append(m_currentLineString);
    }

    emit statusChanged( status );
}

PositionTracking::PositionTracking( FileManager *fileManager,
                          QObject *parent )
     : QObject( parent ), d (new PositionTrackingPrivate(fileManager, parent))
{

    connect( d, SIGNAL( gpsLocation(GeoDataCoordinates,qreal) ),
             this, SIGNAL( gpsLocation(GeoDataCoordinates,qreal) ));
    connect( d, SIGNAL( statusChanged(PositionProviderStatus)),
             this, SIGNAL( statusChanged(PositionProviderStatus) ) );

    d->m_document     = new GeoDataDocument();
    d->m_document->setName("Position Tracking");

    // First point is current position
    GeoDataPlacemark *placemark = new GeoDataPlacemark;
    placemark->setName("Current Position");
    placemark->setVisible(false);
    d->m_document->append(placemark);

    // Second point is position track
    placemark = new GeoDataPlacemark;
    GeoDataMultiGeometry *multiGeometry = new GeoDataMultiGeometry;
    d->m_currentLineString = new GeoDataLineString;

    multiGeometry->append(d->m_currentLineString);
    placemark->setGeometry(multiGeometry);
    placemark->setName("Current Track");

    GeoDataStyle style;
    GeoDataLineStyle lineStyle;
    lineStyle.setColor( oxygenBrickRed4 );
    lineStyle.setWidth(2);
    style.setLineStyle(lineStyle);
    style.setStyleId("track");

    GeoDataStyleMap styleMap;
    styleMap.setStyleId("map-track");
    styleMap.insert("normal", QString("#").append(style.styleId()));
    d->m_document->addStyleMap(styleMap);
    d->m_document->addStyle(style);

    placemark->setStyleUrl(QString("#").append(styleMap.styleId()));
    d->m_document->append(placemark);

    d->m_fileManager->addGeoDataDocument(d->m_document);
}

PositionTracking::~PositionTracking()
{
    delete d;
}

void PositionTracking::setPositionProviderPlugin( PositionProviderPlugin* plugin )
{
    if ( d->m_positionProvider ) {
        d->m_positionProvider->deleteLater();
    }

    d->m_positionProvider = plugin;

    if ( d->m_positionProvider ) {
        d->m_positionProvider->setParent( this );
        mDebug() << "Initializing position provider:" << d->m_positionProvider->name();
        connect( d->m_positionProvider, SIGNAL( statusChanged( PositionProviderStatus ) ),
                d, SLOT( setStatus(PositionProviderStatus) ) );
        connect( d->m_positionProvider, SIGNAL( positionChanged( GeoDataCoordinates,GeoDataAccuracy ) ),
                 d, SLOT( setPosition( GeoDataCoordinates,GeoDataAccuracy ) ) );

        d->m_positionProvider->initialize();
    }
    emit positionProviderPluginChanged( plugin );
}

QString PositionTracking::error() const
{
    return d->m_positionProvider ? d->m_positionProvider->error() : QString();
}

//get speed from provider
qreal PositionTracking::speed() const
{
    return d->m_positionProvider ? d->m_positionProvider->speed() : 0 ;
}

//get direction from provider
qreal PositionTracking::direction() const
{
    return d->m_positionProvider ? d->m_positionProvider->direction() : 0 ;
}

bool PositionTracking::trackVisible() const
{
    return d->m_document->isVisible();
}

void PositionTracking::setTrackVisible( bool visible )
{
    d->m_document->setVisible( visible );
}

void PositionTracking::clearTrack()
{
    GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(d->m_document->child(d->m_document->size()-1));
    GeoDataMultiGeometry *multiGeometry = static_cast<GeoDataMultiGeometry*>(placemark->geometry());
    d->m_currentLineString = new GeoDataLineString;
    multiGeometry->clear();
    multiGeometry->append(d->m_currentLineString);

}

#include "PositionTracking.moc"
#include "PositionTracking_p.moc"
<commit_msg>Use an alpha value and a width of the track that match the parameters of the route.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007   Andrew Manson   <g.real.ate@gmail.com>
// Copyright 2009   Eckhart Wörner  <ewoerner@kde.org>
// Copyright 2010   Thibaut Gridel  <tgridel@free.fr>
//

#include "PositionTracking.h"

#include "GeoDataDocument.h"
#include "GeoDataPlacemark.h"
#include "GeoDataStyle.h"
#include "GeoDataStyleMap.h"
#include "AbstractProjection.h"
#include "FileManager.h"
#include "MarbleMath.h"
#include "MarbleDebug.h"
#include "PositionProviderPlugin.h"

#include "PositionTracking_p.h"

using namespace Marble;

void PositionTrackingPrivate::setPosition( GeoDataCoordinates position,
                                           GeoDataAccuracy accuracy )
{
    Q_UNUSED( accuracy );
    if ( m_positionProvider && m_positionProvider->status() ==
        PositionProviderStatusAvailable )
    {
        GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(m_document->child(m_document->size()-1));
        //GeoDataMultiGeometry *geometry = static_cast<GeoDataMultiGeometry*>(placemark->geometry());
        m_currentLineString->append(position);

        //if the position has moved then update the current position
        if ( !( m_gpsCurrentPosition ==
                position ) )
        {
            placemark = static_cast<GeoDataPlacemark*>(m_document->child(0));
            placemark->setCoordinate(position);
            m_gpsCurrentPosition = position;
            qreal speed = m_positionProvider->speed();
            emit gpsLocation( position, speed );
        }
    }
}

void PositionTrackingPrivate::setStatus( PositionProviderStatus status )
{
    if (status == PositionProviderStatusAvailable) {
        Q_ASSERT(m_document);
        GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(m_document->child(m_document->size()-1));
        GeoDataMultiGeometry *multiGeometry = static_cast<GeoDataMultiGeometry*>(placemark->geometry());
        m_currentLineString = new GeoDataLineString;
        multiGeometry->append(m_currentLineString);
    }

    emit statusChanged( status );
}

PositionTracking::PositionTracking( FileManager *fileManager,
                          QObject *parent )
     : QObject( parent ), d (new PositionTrackingPrivate(fileManager, parent))
{

    connect( d, SIGNAL( gpsLocation(GeoDataCoordinates,qreal) ),
             this, SIGNAL( gpsLocation(GeoDataCoordinates,qreal) ));
    connect( d, SIGNAL( statusChanged(PositionProviderStatus)),
             this, SIGNAL( statusChanged(PositionProviderStatus) ) );

    d->m_document     = new GeoDataDocument();
    d->m_document->setName("Position Tracking");

    // First point is current position
    GeoDataPlacemark *placemark = new GeoDataPlacemark;
    placemark->setName("Current Position");
    placemark->setVisible(false);
    d->m_document->append(placemark);

    // Second point is position track
    placemark = new GeoDataPlacemark;
    GeoDataMultiGeometry *multiGeometry = new GeoDataMultiGeometry;
    d->m_currentLineString = new GeoDataLineString;

    multiGeometry->append(d->m_currentLineString);
    placemark->setGeometry(multiGeometry);
    placemark->setName("Current Track");

    GeoDataStyle style;
    GeoDataLineStyle lineStyle;
    QColor transparentRed = oxygenBrickRed4;
    transparentRed.setAlpha( 200 );
    lineStyle.setColor( transparentRed );
    lineStyle.setWidth( 4 );
    style.setLineStyle(lineStyle);
    style.setStyleId("track");

    GeoDataStyleMap styleMap;
    styleMap.setStyleId("map-track");
    styleMap.insert("normal", QString("#").append(style.styleId()));
    d->m_document->addStyleMap(styleMap);
    d->m_document->addStyle(style);

    placemark->setStyleUrl(QString("#").append(styleMap.styleId()));
    d->m_document->append(placemark);

    d->m_fileManager->addGeoDataDocument(d->m_document);
}

PositionTracking::~PositionTracking()
{
    delete d;
}

void PositionTracking::setPositionProviderPlugin( PositionProviderPlugin* plugin )
{
    if ( d->m_positionProvider ) {
        d->m_positionProvider->deleteLater();
    }

    d->m_positionProvider = plugin;

    if ( d->m_positionProvider ) {
        d->m_positionProvider->setParent( this );
        mDebug() << "Initializing position provider:" << d->m_positionProvider->name();
        connect( d->m_positionProvider, SIGNAL( statusChanged( PositionProviderStatus ) ),
                d, SLOT( setStatus(PositionProviderStatus) ) );
        connect( d->m_positionProvider, SIGNAL( positionChanged( GeoDataCoordinates,GeoDataAccuracy ) ),
                 d, SLOT( setPosition( GeoDataCoordinates,GeoDataAccuracy ) ) );

        d->m_positionProvider->initialize();
    }
    emit positionProviderPluginChanged( plugin );
}

QString PositionTracking::error() const
{
    return d->m_positionProvider ? d->m_positionProvider->error() : QString();
}

//get speed from provider
qreal PositionTracking::speed() const
{
    return d->m_positionProvider ? d->m_positionProvider->speed() : 0 ;
}

//get direction from provider
qreal PositionTracking::direction() const
{
    return d->m_positionProvider ? d->m_positionProvider->direction() : 0 ;
}

bool PositionTracking::trackVisible() const
{
    return d->m_document->isVisible();
}

void PositionTracking::setTrackVisible( bool visible )
{
    d->m_document->setVisible( visible );
}

void PositionTracking::clearTrack()
{
    GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(d->m_document->child(d->m_document->size()-1));
    GeoDataMultiGeometry *multiGeometry = static_cast<GeoDataMultiGeometry*>(placemark->geometry());
    d->m_currentLineString = new GeoDataLineString;
    multiGeometry->clear();
    multiGeometry->append(d->m_currentLineString);

}

#include "PositionTracking.moc"
#include "PositionTracking_p.moc"
<|endoftext|>


<commit_before>/**
 * This file is part of the Marble Desktop Globe.
 *
 * Copyright 2005-2007 Torsten Rahn <tackat@kde.org>"
 * Copyright 2007      Inge Wallin  <ingwa@kde.org>"
 * Copyright 2008       Patrick Spendrin <ps_ml@gmx.de>"
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "TileLoaderHelper.h"

#include <cmath>

#include <QtCore/QDebug>

#include "GeoSceneTexture.h"
#include "global.h"

int TileLoaderHelper::levelToRow( int level )
{
    if ( level < 0 ) {
        qDebug() << QString( "TileLoaderHelper::levelToRow(): Invalid level: %1" )
            .arg( level );
        return 0;
    }
    return (int)std::pow( 2.0, (double)( level ) );
}

int TileLoaderHelper::levelToColumn( int level )
{
    if ( level < 0 ) {
        qDebug() << QString( "TileLoaderHelper::levelToColumn(): Invalid level: %1" )
            .arg( level );
        return 0;
    }
    return (int)std::pow( 2.0, (double)( level + 1 ) );
}

int TileLoaderHelper::rowToLevel( int row )
{
    if ( row < 1 )    {
        qDebug() << QString( "TileLoaderHelper::rowToLevel(): Invalid number of rows: %1" )
            .arg( row );
        return 0;
    }
    return (int)( std::log( (double)row ) / std::log( (double)2.0 ) );
}

int TileLoaderHelper::columnToLevel( int column )
{
    if ( column < 2 ) {
        qDebug() << QString( "TileLoaderHelper::columnToLevel(): Invalid number of columns: %1" )
        .arg( column );
        return 0;
    }
    return (int)( std::log( (double)(column / 2) ) / std::log( (double)2.0 ) );
}

QString TileLoaderHelper::relativeTileFileName( GeoSceneTexture *textureLayer, int level, int x,
                                                int y )
{
    QString relFileName;
    if ( textureLayer ) {
        const QString suffix = textureLayer->fileFormat().toLower();
        switch ( textureLayer->storageLayoutMode() ) {
        case GeoSceneTexture::Marble:
            // FIXME: use format information from GeoSceneTexturex
            relFileName = QString( "%1/%2/%3/%3_%4.%5" )
                .arg( themeStr( textureLayer ) )
                .arg( level )
                .arg( y, tileDigits, 10, QChar('0') )
                .arg( x, tileDigits, 10, QChar('0') )
                .arg( suffix );
            break;
        case GeoSceneTexture::OpenStreetMap:
            // FIXME: use format information from GeoSceneTexturex
            relFileName = QString( "%1/%2/%3/%4.%5" )
                .arg( themeStr( textureLayer ) )
                .arg( level )
                .arg( x )
                .arg( y )
                .arg( suffix );
            break;
        }
    }
    return relFileName;
}

QString TileLoaderHelper::themeStr( GeoSceneTexture *textureLayer )
{
    QString oldThemeStr;

    if ( textureLayer ) {
         oldThemeStr = "maps/" + textureLayer->sourceDir();
    }

    return oldThemeStr;
}
<commit_msg>Remove FIXME comments.<commit_after>/**
 * This file is part of the Marble Desktop Globe.
 *
 * Copyright 2005-2007 Torsten Rahn <tackat@kde.org>"
 * Copyright 2007      Inge Wallin  <ingwa@kde.org>"
 * Copyright 2008       Patrick Spendrin <ps_ml@gmx.de>"
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "TileLoaderHelper.h"

#include <cmath>

#include <QtCore/QDebug>

#include "GeoSceneTexture.h"
#include "global.h"

int TileLoaderHelper::levelToRow( int level )
{
    if ( level < 0 ) {
        qDebug() << QString( "TileLoaderHelper::levelToRow(): Invalid level: %1" )
            .arg( level );
        return 0;
    }
    return (int)std::pow( 2.0, (double)( level ) );
}

int TileLoaderHelper::levelToColumn( int level )
{
    if ( level < 0 ) {
        qDebug() << QString( "TileLoaderHelper::levelToColumn(): Invalid level: %1" )
            .arg( level );
        return 0;
    }
    return (int)std::pow( 2.0, (double)( level + 1 ) );
}

int TileLoaderHelper::rowToLevel( int row )
{
    if ( row < 1 )    {
        qDebug() << QString( "TileLoaderHelper::rowToLevel(): Invalid number of rows: %1" )
            .arg( row );
        return 0;
    }
    return (int)( std::log( (double)row ) / std::log( (double)2.0 ) );
}

int TileLoaderHelper::columnToLevel( int column )
{
    if ( column < 2 ) {
        qDebug() << QString( "TileLoaderHelper::columnToLevel(): Invalid number of columns: %1" )
        .arg( column );
        return 0;
    }
    return (int)( std::log( (double)(column / 2) ) / std::log( (double)2.0 ) );
}

QString TileLoaderHelper::relativeTileFileName( GeoSceneTexture *textureLayer, int level, int x,
                                                int y )
{
    QString relFileName;
    if ( textureLayer ) {
        const QString suffix = textureLayer->fileFormat().toLower();
        switch ( textureLayer->storageLayoutMode() ) {
        case GeoSceneTexture::Marble:
            relFileName = QString( "%1/%2/%3/%3_%4.%5" )
                .arg( themeStr( textureLayer ) )
                .arg( level )
                .arg( y, tileDigits, 10, QChar('0') )
                .arg( x, tileDigits, 10, QChar('0') )
                .arg( suffix );
            break;
        case GeoSceneTexture::OpenStreetMap:
            relFileName = QString( "%1/%2/%3/%4.%5" )
                .arg( themeStr( textureLayer ) )
                .arg( level )
                .arg( x )
                .arg( y )
                .arg( suffix );
            break;
        }
    }
    return relFileName;
}

QString TileLoaderHelper::themeStr( GeoSceneTexture *textureLayer )
{
    QString oldThemeStr;

    if ( textureLayer ) {
         oldThemeStr = "maps/" + textureLayer->sourceDir();
    }

    return oldThemeStr;
}
<|endoftext|>


<commit_before>#include "nar-accessor.hh"
#include "archive.hh"

#include <map>

namespace nix {

struct NarMember
{
    FSAccessor::Type type;

    bool isExecutable;

    /* If this is a regular file, position of the contents of this
       file in the NAR. */
    size_t start, size;

    std::string target;
};

struct NarIndexer : ParseSink, StringSource
{
    // FIXME: should store this as a tree. Now we're vulnerable to
    // O(nm) memory consumption (e.g. for x_0/.../x_n/{y_0..y_m}).
    typedef std::map<Path, NarMember> Members;
    Members members;

    Path currentPath;
    std::string currentStart;
    bool isExec;

    NarIndexer(const std::string & nar) : StringSource(nar)
    {
    }

    void createDirectory(const Path & path) override
    {
        members.emplace(path,
            NarMember{FSAccessor::Type::tDirectory, false, 0, 0});
    }

    void createRegularFile(const Path & path) override
    {
        currentPath = path;
    }

    void isExecutable() override
    {
        isExec = true;
    }

    void preallocateContents(unsigned long long size) override
    {
        currentStart = string(s, pos, 16);
        members.emplace(currentPath,
            NarMember{FSAccessor::Type::tRegular, isExec, pos, size});
    }

    void receiveContents(unsigned char * data, unsigned int len) override
    {
        // Sanity check
        if (!currentStart.empty()) {
            assert(len < 16 || currentStart == string((char *) data, 16));
            currentStart.clear();
        }
    }

    void createSymlink(const Path & path, const string & target) override
    {
        members.emplace(path,
            NarMember{FSAccessor::Type::tSymlink, false, 0, 0, target});
    }

    Members::iterator find(const Path & path)
    {
        auto i = members.find(path);
        if (i == members.end())
            throw Error(format("NAR file does not contain path ‘%1%’") % path);
        return i;
    }
};

struct NarAccessor : public FSAccessor
{
    ref<const std::string> nar;
    NarIndexer indexer;

    NarAccessor(ref<const std::string> nar) : nar(nar), indexer(*nar)
    {
        parseDump(indexer, indexer);
    }

    Stat stat(const Path & path) override
    {
        auto i = indexer.members.find(path);
        if (i == indexer.members.end())
            return {FSAccessor::Type::tMissing, 0, false};
        return {i->second.type, i->second.size, i->second.isExecutable};
    }

    StringSet readDirectory(const Path & path) override
    {
        auto i = indexer.find(path);

        if (i->second.type != FSAccessor::Type::tDirectory)
            throw Error(format("path ‘%1%’ inside NAR file is not a directory") % path);

        ++i;
        StringSet res;
        while (i != indexer.members.end() && isInDir(i->first, path)) {
            // FIXME: really bad performance.
            if (i->first.find('/', path.size() + 1) == std::string::npos)
                res.insert(std::string(i->first, path.size() + 1));
            ++i;
        }
        return res;
    }

    std::string readFile(const Path & path) override
    {
        auto i = indexer.find(path);
        if (i->second.type != FSAccessor::Type::tRegular)
            throw Error(format("path ‘%1%’ inside NAR file is not a regular file") % path);
        return std::string(*nar, i->second.start, i->second.size);
    }

    std::string readLink(const Path & path) override
    {
        auto i = indexer.find(path);
        if (i->second.type != FSAccessor::Type::tSymlink)
            throw Error(format("path ‘%1%’ inside NAR file is not a symlink") % path);
        return i->second.target;
    }
};

ref<FSAccessor> makeNarAccessor(ref<const std::string> nar)
{
    return make_ref<NarAccessor>(nar);
}

}
<commit_msg>NarAccessor: Fix handling of non-executable files<commit_after>#include "nar-accessor.hh"
#include "archive.hh"

#include <map>

namespace nix {

struct NarMember
{
    FSAccessor::Type type;

    bool isExecutable;

    /* If this is a regular file, position of the contents of this
       file in the NAR. */
    size_t start, size;

    std::string target;
};

struct NarIndexer : ParseSink, StringSource
{
    // FIXME: should store this as a tree. Now we're vulnerable to
    // O(nm) memory consumption (e.g. for x_0/.../x_n/{y_0..y_m}).
    typedef std::map<Path, NarMember> Members;
    Members members;

    Path currentPath;
    std::string currentStart;
    bool isExec = false;

    NarIndexer(const std::string & nar) : StringSource(nar)
    {
    }

    void createDirectory(const Path & path) override
    {
        members.emplace(path,
            NarMember{FSAccessor::Type::tDirectory, false, 0, 0});
    }

    void createRegularFile(const Path & path) override
    {
        currentPath = path;
    }

    void isExecutable() override
    {
        isExec = true;
    }

    void preallocateContents(unsigned long long size) override
    {
        currentStart = string(s, pos, 16);
        members.emplace(currentPath,
            NarMember{FSAccessor::Type::tRegular, isExec, pos, size});
    }

    void receiveContents(unsigned char * data, unsigned int len) override
    {
        // Sanity check
        if (!currentStart.empty()) {
            assert(len < 16 || currentStart == string((char *) data, 16));
            currentStart.clear();
        }
    }

    void createSymlink(const Path & path, const string & target) override
    {
        members.emplace(path,
            NarMember{FSAccessor::Type::tSymlink, false, 0, 0, target});
    }

    Members::iterator find(const Path & path)
    {
        auto i = members.find(path);
        if (i == members.end())
            throw Error(format("NAR file does not contain path ‘%1%’") % path);
        return i;
    }
};

struct NarAccessor : public FSAccessor
{
    ref<const std::string> nar;
    NarIndexer indexer;

    NarAccessor(ref<const std::string> nar) : nar(nar), indexer(*nar)
    {
        parseDump(indexer, indexer);
    }

    Stat stat(const Path & path) override
    {
        auto i = indexer.members.find(path);
        if (i == indexer.members.end())
            return {FSAccessor::Type::tMissing, 0, false};
        return {i->second.type, i->second.size, i->second.isExecutable};
    }

    StringSet readDirectory(const Path & path) override
    {
        auto i = indexer.find(path);

        if (i->second.type != FSAccessor::Type::tDirectory)
            throw Error(format("path ‘%1%’ inside NAR file is not a directory") % path);

        ++i;
        StringSet res;
        while (i != indexer.members.end() && isInDir(i->first, path)) {
            // FIXME: really bad performance.
            if (i->first.find('/', path.size() + 1) == std::string::npos)
                res.insert(std::string(i->first, path.size() + 1));
            ++i;
        }
        return res;
    }

    std::string readFile(const Path & path) override
    {
        auto i = indexer.find(path);
        if (i->second.type != FSAccessor::Type::tRegular)
            throw Error(format("path ‘%1%’ inside NAR file is not a regular file") % path);
        return std::string(*nar, i->second.start, i->second.size);
    }

    std::string readLink(const Path & path) override
    {
        auto i = indexer.find(path);
        if (i->second.type != FSAccessor::Type::tSymlink)
            throw Error(format("path ‘%1%’ inside NAR file is not a symlink") % path);
        return i->second.target;
    }
};

ref<FSAccessor> makeNarAccessor(ref<const std::string> nar)
{
    return make_ref<NarAccessor>(nar);
}

}
<|endoftext|>


<commit_before>#include "linear_interpolate_d.hpp"

#include <cmath>

#include <algorithm>
#include <map>
#include <numeric>
#include <limits>
#include <string>
#include <tuple>
#include <vector>

std::vector<double> find_barycentric_coords(std::size_t size,
                                            Point const & point,
                                            std::vector<Point> const & simplex)
{
  std::vector<double> a(size * size);
  for (size_t i = 0; i < size; ++i)
  {
    for (size_t j = 0; j < size; ++j)
    {
      a[i*size+j] = *(simplex[i].cartesian_begin()+j) - *(simplex[size].cartesian_begin()+j);
    }
  }

  std::vector<double> b(size + 1);
  for (size_t i = 0; i < size; ++i)
  {
    b[i] = *(point.cartesian_begin()+i) - *(simplex[size].cartesian_begin()+i);
  }

  // additional variables needed for LAPACK
  std::vector<int> ipiv(size);
  int info;
  int size_int = size;
  int b_size = 1;

  // solve a*x = b
  // result will be in b
  F77_NAME(dgesv)(&size_int, &b_size, &a[0], &size_int, &ipiv[0],
    &b[0], &size_int, &info);

  if (info != 0)
  {
    error("Bad matrix");
  }

  // calculate last coordinate
  b[size] = 1 - std::accumulate(b.begin(), b.end() - 1, 0.);

  return b;
}

// returns beta_1, ..., beta_d+1, beta_0
std::vector<double> linear_coef(size_t d,
                                const std::vector<Point> &points,
                                const std::vector<double> &values) {
  std::vector<double> a((d+1) * (d+1));
  for (size_t i = 0; i <= d; ++i) {
    for (size_t j = 0; j < d; ++j) {
      a[i + j*(d+1)] = *(points[i].cartesian_begin() + j);
    }

    a[i + d*(d+1)] = 1;
  }

  std::vector<double> b(values);

  for (auto el : b) {
    if (ISNAN(el)) {
      return b;
    }
  }

  // additional variables needed for LAPACK
  std::vector<int> ipiv(d + 1);
  int info;
  int size_int = d + 1;
  int b_size = 1;

  // solve a*x = b
  // result will be in b
  F77_NAME(dgesv)(&size_int, &b_size, &a[0], &size_int, &ipiv[0],
    &b[0], &size_int, &info);

  if (info != 0)
  {
    // error("Bad matrix");
  }

  return b;
}

class LinearInterpolator_d {
public:
  LinearInterpolator_d(int d,
                       const double *points,
                       const double *values,
                       size_t npoints) : d{d}, triangulation{d}, npoints{npoints} {
    for (size_t i{0}; i < npoints; ++i) {
      Point point(d, points + i*d, points + (i + 1)*d);
      Vertex_handle vertex_handle = triangulation.insert(point);
      vertices_to_values[vertex_handle] = values[i];
    }

    for (const auto &simplex : triangulation.all_simplices()) {
      if (simplex == Delaunay::Simplex_handle()) continue;

      std::vector<Point>  vertices;
      std::vector<double> vertex_values;
      bool flag = true;
      for (size_t i{0}; i <= d; ++i) {
        auto vertex = triangulation.vertex_of_simplex(simplex, i);
        double vertex_val = vertices_to_values[vertex];
        if (vertex == Delaunay::Vertex_handle()) {
          flag = false;
          break;
        }
        vertices.push_back(vertex->point());
        vertex_values.push_back(vertex_val);
      }
      if (!flag) continue;
      m[simplex] = linear_coef(d, vertices, vertex_values);
    }
  }

  double get(const double *x) {
    const double double_fill_value = NA_REAL;

    Point point(d, x, x + d);
    auto simplex = triangulation.locate(point);
    if (!m.count(simplex)) {
      return double_fill_value;
    }

    auto beta = m[simplex];
    return std::inner_product(x, x + d, beta.begin(), beta[d]);
  }

  double operator()(const double *x) {
    const double double_fill_value = NA_REAL;

    Point point(d, x, x + d);
    auto simplex = triangulation.locate(point);
    if (simplex == Delaunay::Simplex_handle()) {
      return double_fill_value;
    }
    std::vector<Point>  vertices(d + 1);
    std::vector<double> vertex_values(d + 1);
    for (size_t i{0}; i <= triangulation.current_dimension(); ++i) {
      auto vertex = triangulation.vertex_of_simplex(simplex, i);
      double vertex_val = vertices_to_values[vertex];
      if (ISNAN(vertex_val)) {
        return double_fill_value;
      }
      vertices[i] = triangulation.associated_point(vertex);
      vertex_values[i] = vertex_val;
    }
    auto barycentric = find_barycentric_coords(triangulation.current_dimension(), point, vertices);
    return std::inner_product(vertex_values.begin(), vertex_values.end(), barycentric.begin(), 0.);
  }

private:
  const int d;
  size_t npoints;
  Delaunay triangulation;
  std::map<Vertex_handle, double> vertices_to_values;
  std::map<Delaunay::Simplex_handle, std::vector<double>> m;
};

SEXP linear_interpolate_d(SEXP dimentions,
                          SEXP points,
                          SEXP values,
                          SEXP xi) {
  int d = INTEGER(dimentions)[0];

  LinearInterpolator_d li(d, REAL(points), REAL(values), length(values));

  int result_length = length(xi) / d;
  SEXP results = PROTECT(allocVector(REALSXP, result_length));

  for (size_t i{0}; i < result_length; ++i) {
    // REAL(results)[i] = li(REAL(xi) + i*d);
    REAL(results)[i] = li.get(REAL(xi) + i*d);
  }

  UNPROTECT(1);
  return results;
}
<commit_msg>Make function local<commit_after>#include "linear_interpolate_d.hpp"

#include <cmath>

#include <algorithm>
#include <map>
#include <numeric>
#include <limits>
#include <string>
#include <tuple>
#include <vector>

static std::vector<double> find_barycentric_coords(std::size_t size,
                                            Point const & point,
                                            std::vector<Point> const & simplex)
{
  std::vector<double> a(size * size);
  for (size_t i = 0; i < size; ++i)
  {
    for (size_t j = 0; j < size; ++j)
    {
      a[i*size+j] = *(simplex[i].cartesian_begin()+j) - *(simplex[size].cartesian_begin()+j);
    }
  }

  std::vector<double> b(size + 1);
  for (size_t i = 0; i < size; ++i)
  {
    b[i] = *(point.cartesian_begin()+i) - *(simplex[size].cartesian_begin()+i);
  }

  // additional variables needed for LAPACK
  std::vector<int> ipiv(size);
  int info;
  int size_int = size;
  int b_size = 1;

  // solve a*x = b
  // result will be in b
  F77_NAME(dgesv)(&size_int, &b_size, &a[0], &size_int, &ipiv[0],
    &b[0], &size_int, &info);

  if (info != 0)
  {
    error("Bad matrix");
  }

  // calculate last coordinate
  b[size] = 1 - std::accumulate(b.begin(), b.end() - 1, 0.);

  return b;
}

// returns beta_1, ..., beta_d+1, beta_0
std::vector<double> linear_coef(size_t d,
                                const std::vector<Point> &points,
                                const std::vector<double> &values) {
  std::vector<double> a((d+1) * (d+1));
  for (size_t i = 0; i <= d; ++i) {
    for (size_t j = 0; j < d; ++j) {
      a[i + j*(d+1)] = *(points[i].cartesian_begin() + j);
    }

    a[i + d*(d+1)] = 1;
  }

  std::vector<double> b(values);

  for (auto el : b) {
    if (ISNAN(el)) {
      return b;
    }
  }

  // additional variables needed for LAPACK
  std::vector<int> ipiv(d + 1);
  int info;
  int size_int = d + 1;
  int b_size = 1;

  // solve a*x = b
  // result will be in b
  F77_NAME(dgesv)(&size_int, &b_size, &a[0], &size_int, &ipiv[0],
    &b[0], &size_int, &info);

  if (info != 0)
  {
    // error("Bad matrix");
  }

  return b;
}

class LinearInterpolator_d {
public:
  LinearInterpolator_d(int d,
                       const double *points,
                       const double *values,
                       size_t npoints) : d{d}, triangulation{d}, npoints{npoints} {
    for (size_t i{0}; i < npoints; ++i) {
      Point point(d, points + i*d, points + (i + 1)*d);
      Vertex_handle vertex_handle = triangulation.insert(point);
      vertices_to_values[vertex_handle] = values[i];
    }

    for (const auto &simplex : triangulation.all_simplices()) {
      if (simplex == Delaunay::Simplex_handle()) continue;

      std::vector<Point>  vertices;
      std::vector<double> vertex_values;
      bool flag = true;
      for (size_t i{0}; i <= d; ++i) {
        auto vertex = triangulation.vertex_of_simplex(simplex, i);
        double vertex_val = vertices_to_values[vertex];
        if (vertex == Delaunay::Vertex_handle()) {
          flag = false;
          break;
        }
        vertices.push_back(vertex->point());
        vertex_values.push_back(vertex_val);
      }
      if (!flag) continue;
      m[simplex] = linear_coef(d, vertices, vertex_values);
    }
  }

  double get(const double *x) {
    const double double_fill_value = NA_REAL;

    Point point(d, x, x + d);
    auto simplex = triangulation.locate(point);
    if (!m.count(simplex)) {
      return double_fill_value;
    }

    auto beta = m[simplex];
    return std::inner_product(x, x + d, beta.begin(), beta[d]);
  }

  double operator()(const double *x) {
    const double double_fill_value = NA_REAL;

    Point point(d, x, x + d);
    auto simplex = triangulation.locate(point);
    if (simplex == Delaunay::Simplex_handle()) {
      return double_fill_value;
    }
    std::vector<Point>  vertices(d + 1);
    std::vector<double> vertex_values(d + 1);
    for (size_t i{0}; i <= triangulation.current_dimension(); ++i) {
      auto vertex = triangulation.vertex_of_simplex(simplex, i);
      double vertex_val = vertices_to_values[vertex];
      if (ISNAN(vertex_val)) {
        return double_fill_value;
      }
      vertices[i] = triangulation.associated_point(vertex);
      vertex_values[i] = vertex_val;
    }
    auto barycentric = find_barycentric_coords(triangulation.current_dimension(), point, vertices);
    return std::inner_product(vertex_values.begin(), vertex_values.end(), barycentric.begin(), 0.);
  }

private:
  const int d;
  size_t npoints;
  Delaunay triangulation;
  std::map<Vertex_handle, double> vertices_to_values;
  std::map<Delaunay::Simplex_handle, std::vector<double>> m;
};

SEXP linear_interpolate_d(SEXP dimentions,
                          SEXP points,
                          SEXP values,
                          SEXP xi) {
  int d = INTEGER(dimentions)[0];

  LinearInterpolator_d li(d, REAL(points), REAL(values), length(values));

  int result_length = length(xi) / d;
  SEXP results = PROTECT(allocVector(REALSXP, result_length));

  for (size_t i{0}; i < result_length; ++i) {
    // REAL(results)[i] = li(REAL(xi) + i*d);
    REAL(results)[i] = li.get(REAL(xi) + i*d);
  }

  UNPROTECT(1);
  return results;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
 * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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 "ir.h"
#include "glsl_types.h"
#include "ir_visitor.h"
#include "../glsl/program.h"
#include "ir_uniform.h"

#include "main/mtypes.h"
#include "program/hash_table.h"
#include "program/prog_parameter.h"
#include "program/program.h"

class get_sampler_name : public ir_hierarchical_visitor
{
public:
   get_sampler_name(ir_dereference *last,
		    struct gl_shader_program *shader_program)
   {
      this->mem_ctx = ralloc_context(NULL);
      this->shader_program = shader_program;
      this->name = NULL;
      this->offset = 0;
      this->last = last;
   }

   ~get_sampler_name()
   {
      ralloc_free(this->mem_ctx);
   }

   virtual ir_visitor_status visit(ir_dereference_variable *ir)
   {
      this->name = ir->var->name;
      return visit_continue;
   }

   virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
   {
      this->name = ralloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
      return visit_continue;
   }

   virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
   {
      ir_constant *index = ir->array_index->as_constant();
      int i;

      if (index) {
	 i = index->value.i[0];
      } else {
	 /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
	  * while GLSL 1.30 requires that the array indices be
	  * constant integer expressions.  We don't expect any driver
	  * to actually work with a really variable array index, so
	  * all that would work would be an unrolled loop counter that ends
	  * up being constant above.
	  */
	 ralloc_strcat(&shader_program->InfoLog,
		       "warning: Variable sampler array index unsupported.\n"
		       "This feature of the language was removed in GLSL 1.20 "
		       "and is unlikely to be supported for 1.10 in Mesa.\n");
	 i = 0;
      }
      if (ir != last) {
	 this->name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);
      } else {
	 offset = i;
      }
      return visit_continue;
   }

   struct gl_shader_program *shader_program;
   const char *name;
   void *mem_ctx;
   int offset;
   ir_dereference *last;
};

int
_mesa_get_sampler_uniform_value(class ir_dereference *sampler,
				struct gl_shader_program *shader_program,
				const struct gl_program *prog)
{
   get_sampler_name getname(sampler, shader_program);

   GLuint shader = _mesa_program_enum_to_shader_stage(prog->Target);

   sampler->accept(&getname);

   unsigned location;
   if (!shader_program->UniformHash->get(location, getname.name)) {
      linker_error(shader_program,
		   "failed to find sampler named %s.\n", getname.name);
      return 0;
   }

   if (!shader_program->UniformStorage[location].sampler[shader].active) {
      assert(0 && "cannot return a sampler");
      linker_error(shader_program,
		   "cannot return a sampler named %s, because it is not "
                   "used in this shader stage. This is a driver bug.\n",
                   getname.name);
      return 0;
   }

   return shader_program->UniformStorage[location].sampler[shader].index +
          getname.offset;
}

class ir_rvalue *
_mesa_get_sampler_array_nonconst_index(class ir_dereference *sampler)
{
   ir_dereference_array *deref_arr = sampler->as_dereference_array();
   if (!deref_arr || deref_arr->array_index->as_constant())
      return NULL;

   return deref_arr->array_index;
}
<commit_msg>mesa: clean up #includes in sampler.cpp<commit_after>/*
 * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
 * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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 "main/mtypes.h"
#include "glsl/glsl_types.h"
#include "glsl/ir.h"
#include "glsl/ir_uniform.h"
#include "glsl/ir_visitor.h"
#include "glsl/program.h"
#include "program/hash_table.h"
#include "program/prog_parameter.h"
#include "program/program.h"

class get_sampler_name : public ir_hierarchical_visitor
{
public:
   get_sampler_name(ir_dereference *last,
		    struct gl_shader_program *shader_program)
   {
      this->mem_ctx = ralloc_context(NULL);
      this->shader_program = shader_program;
      this->name = NULL;
      this->offset = 0;
      this->last = last;
   }

   ~get_sampler_name()
   {
      ralloc_free(this->mem_ctx);
   }

   virtual ir_visitor_status visit(ir_dereference_variable *ir)
   {
      this->name = ir->var->name;
      return visit_continue;
   }

   virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
   {
      this->name = ralloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
      return visit_continue;
   }

   virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
   {
      ir_constant *index = ir->array_index->as_constant();
      int i;

      if (index) {
	 i = index->value.i[0];
      } else {
	 /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
	  * while GLSL 1.30 requires that the array indices be
	  * constant integer expressions.  We don't expect any driver
	  * to actually work with a really variable array index, so
	  * all that would work would be an unrolled loop counter that ends
	  * up being constant above.
	  */
	 ralloc_strcat(&shader_program->InfoLog,
		       "warning: Variable sampler array index unsupported.\n"
		       "This feature of the language was removed in GLSL 1.20 "
		       "and is unlikely to be supported for 1.10 in Mesa.\n");
	 i = 0;
      }
      if (ir != last) {
	 this->name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);
      } else {
	 offset = i;
      }
      return visit_continue;
   }

   struct gl_shader_program *shader_program;
   const char *name;
   void *mem_ctx;
   int offset;
   ir_dereference *last;
};

int
_mesa_get_sampler_uniform_value(class ir_dereference *sampler,
				struct gl_shader_program *shader_program,
				const struct gl_program *prog)
{
   get_sampler_name getname(sampler, shader_program);

   GLuint shader = _mesa_program_enum_to_shader_stage(prog->Target);

   sampler->accept(&getname);

   unsigned location;
   if (!shader_program->UniformHash->get(location, getname.name)) {
      linker_error(shader_program,
		   "failed to find sampler named %s.\n", getname.name);
      return 0;
   }

   if (!shader_program->UniformStorage[location].sampler[shader].active) {
      assert(0 && "cannot return a sampler");
      linker_error(shader_program,
		   "cannot return a sampler named %s, because it is not "
                   "used in this shader stage. This is a driver bug.\n",
                   getname.name);
      return 0;
   }

   return shader_program->UniformStorage[location].sampler[shader].index +
          getname.offset;
}

class ir_rvalue *
_mesa_get_sampler_array_nonconst_index(class ir_dereference *sampler)
{
   ir_dereference_array *deref_arr = sampler->as_dereference_array();
   if (!deref_arr || deref_arr->array_index->as_constant())
      return NULL;

   return deref_arr->array_index;
}
<|endoftext|>


<commit_before>#include <Riostream.h>
#include "TFluka.h"
#ifndef WIN32
# define usdraw usdraw_
#else
# define usdraw USDRAW
#endif
extern "C" {
void usdraw(Int_t& icode, Int_t& mreg,
            Double_t& xsco, Double_t& ysco, Double_t& zsco)
{
  ((TFluka*) gMC)->SetIcode(icode);
  ((TFluka*) gMC)->SetMreg(mreg);
  ((TFluka*) gMC)->SetXsco(xsco);
  ((TFluka*) gMC)->SetYsco(ysco);
  ((TFluka*) gMC)->SetZsco(zsco);
  cout << endl << " !!! I am in usdraw" << endl;
  ((TFluka*) gMC)->FutoTest();
} // end of usdraw
} // end of extern "C"

<commit_msg>print statement commented<commit_after>#include <Riostream.h>
#include "TFluka.h"
#ifndef WIN32
# define usdraw usdraw_
#else
# define usdraw USDRAW
#endif
extern "C" {
void usdraw(Int_t& icode, Int_t& mreg,
            Double_t& xsco, Double_t& ysco, Double_t& zsco)
{
  ((TFluka*) gMC)->SetIcode(icode);
  ((TFluka*) gMC)->SetMreg(mreg);
  ((TFluka*) gMC)->SetXsco(xsco);
  ((TFluka*) gMC)->SetYsco(ysco);
  ((TFluka*) gMC)->SetZsco(zsco);
  ((TFluka*) gMC)->FutoTest();
//  cout << endl << " !!! I am in usdraw - calling Stepping()" << mreg << endl;
} // end of usdraw
} // end of extern "C"

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions Inc. 1990-2013.  All rights reserved
 */
//      TEST    Foundation::Containers::SortedTally
//      STATUS  very minimal/incomplete
#include    "Stroika/Foundation/StroikaPreComp.h"

#include    "Stroika/Foundation/Containers/SortedMapping.h"
#include    "Stroika/Foundation/Containers/Concrete/SortedMapping_stdmap.h"
#include    "Stroika/Foundation/Debug/Assertions.h"
#include    "Stroika/Foundation/Debug/Trace.h"

#include    "../TestHarness/SimpleClass.h"
#include    "../TestHarness/TestHarness.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;

using   Concrete::SortedMapping_stdmap;

namespace {
    template <typename MappingOfKeyT>
    void    SimpleTest_1_ (MappingOfKeyT m)
    {
        MappingOfKeyT s;
    }
}

namespace {
    template <typename MappingOfKeyT>
    void    SimpleTest_2_ (MappingOfKeyT m)
    {
        m.Add (1, 2);
        VerifyTestResult (m.size () == 1);
        Verify (m.Lookup (1, nullptr));
        Verify (not m.Lookup (2, nullptr));
        m.Add (1, 2);
        VerifyTestResult (m.size () == 1);
        m.Remove (1);
        VerifyTestResult (m.size () == 0);
        m.RemoveAll ();
        VerifyTestResult (m.size () == 0);
    }
}

namespace {
    template <typename MappingOfKeyT>
    void    SimpleTest_3_Iteration_ (MappingOfKeyT m)
    {
        m.Add (1, 2);
        VerifyTestResult (m.size () == 1);
        for (auto i : m) {
            VerifyTestResult (i.first == 1);
            VerifyTestResult (i.second == 2);
        }
        m.Add (1, 2);
        VerifyTestResult (m.size () == 1);
        for (auto i : m) {
            VerifyTestResult (i.first == 1);
            VerifyTestResult (i.second == 2);
        }
        m.Remove (1);
        VerifyTestResult (m.size () == 0);
        for (auto i : m) {
            VerifyTestResult (false);
        }
        m.Add (2, 3);
        m.Add (1, 2);
        m.Add (3, 4);
        unsigned int cnt = 0;
        for (auto i : m) {
            cnt++;
            if (cnt == 1) {
                VerifyTestResult (i.first == 1);
                VerifyTestResult (i.second == 2);
            }
            if (cnt == 2) {
                VerifyTestResult (i.first == 2);
                VerifyTestResult (i.second == 3);
            }
            if (cnt == 3) {
                VerifyTestResult (i.first == 3);
                VerifyTestResult (i.second == 4);
            }
        }
        VerifyTestResult (cnt == 3);
        m.RemoveAll ();
        VerifyTestResult (m.size () == 0);
    }
}

namespace {
    template <typename MappingOfKeyT>
    void    SimpleMappingTest_All_For_Type ()
    {
        MappingOfKeyT m;
        SimpleTest_1_ (m);
        SimpleTest_2_ (m);
        SimpleTest_3_Iteration_ (m);
    }
}

namespace   {
    void    DoRegressionTests_ ()
    {
        SimpleMappingTest_All_For_Type<SortedMapping<size_t, size_t>> ();
        SimpleMappingTest_All_For_Type<SortedMapping<SimpleClass, SimpleClass>> ();

        SimpleMappingTest_All_For_Type<SortedMapping_stdmap<size_t, size_t>> ();
        SimpleMappingTest_All_For_Type<SortedMapping_stdmap<SimpleClass, SimpleClass>> ();
    }
}

int     main (int argc, const char* argv[])
{
    Stroika::TestHarness::Setup ();
    Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
    return EXIT_SUCCESS;
}
<commit_msg>draft of Tests for sortedtally - though no sorted tally class yet<commit_after>/*
 * Copyright(c) Sophist Solutions Inc. 1990-2013.  All rights reserved
 */
//      TEST    Foundation::Containers::SortedTally
//      STATUS  very minimal/incomplete
#include    "Stroika/Foundation/StroikaPreComp.h"

/// WRONG - we dont have SortedTally Yet - but when we do!!!
#include    "Stroika/Foundation/Containers/Tally.h"
#include    "Stroika/Foundation/Containers/Concrete/Tally_Array.h"
#include    "Stroika/Foundation/Containers/Concrete/Tally_LinkedList.h"
#include    "Stroika/Foundation/Debug/Assertions.h"
#include    "Stroika/Foundation/Debug/Trace.h"

#include    "../TestCommon/CommonTests_Tally.h"
#include    "../TestHarness/SimpleClass.h"
#include    "../TestHarness/TestHarness.h"

#include    "../TestCommon/CommonTests_Tally.h"
#include    "../TestHarness/SimpleClass.h"
#include    "../TestHarness/TestHarness.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;

using   Concrete::Tally_Array;
using   Concrete::Tally_LinkedList;

namespace   {

    void    DoRegressionTests_ ()
    {
        using namespace CommonTests::TallyTests;

        SimpleTallyTest_All_For_Type<size_t, Tally_LinkedList<size_t>> ();
        SimpleTallyTest_All_For_Type<SimpleClass, Tally_LinkedList<SimpleClass>> ();

        SimpleTallyTest_All_For_Type<size_t, Tally_Array<size_t>> ();
        SimpleTallyTest_All_For_Type<SimpleClass, Tally_Array<SimpleClass>> ();

        SimpleTallyTest_All_For_Type<size_t, Tally<size_t>> ();
        SimpleTallyTest_All_For_Type<SimpleClass, Tally<SimpleClass>> ();
    }

}

int     main (int argc, const char* argv[])
{
    Stroika::TestHarness::Setup ();
    Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>
// Includes.
#include "UI/MainWindow.h"
#include "UI/NodeItem.h"
#include "UI/ConnectionItem.h"
#include "UI/ParametersDialog.h"
#include "App/App.h"
#include "App/Boundary/NodeProxy.h"
#include "App/Boundary/ConnectionProxy.h"

// Qt.
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QListWidget>
#include <QStringListModel>
#include <QGraphicsLineItem>
#include <QMouseEvent>
#include <QDrag>
#include <QMimeData>
#include <QCheckBox>

class TypesWidget : public QListWidget
{
public:
    TypesWidget(QWidget* parent = nullptr) : QListWidget(parent) {}

protected:

    virtual void mousePressEvent(QMouseEvent* e)
    {
        QListWidget::mousePressEvent(e);
        if (e->button() == Qt::LeftButton)
        {
            drag_start_position_ = e->pos();
        }
    }

    virtual void mouseMoveEvent(QMouseEvent *e)
    {
        QListWidget::mouseMoveEvent(e);

        if ((e->buttons() & Qt::LeftButton) == 0)
        {
            return;
        }
        else
        {
            QDrag *drag = new QDrag(this);
            QMimeData *mimeData = new QMimeData;

            QListWidgetItem* item = itemAt(e->pos());
            if (item != nullptr)
            {
                QString text = item->text();
                mimeData->setData("node/type", text.toUtf8());
                drag->setMimeData(mimeData);
                drag->exec(Qt::CopyAction | Qt::MoveAction);
            }
        }
    }

private:

    QPoint drag_start_position_;

};

MainWindow::MainWindow(App *app, QWidget *parent)
    : QMainWindow(parent)
    , types_list_(nullptr)
    , scene_view_(nullptr)
    , log_view_(nullptr)
    , show_types_box_(nullptr)
    , scene_(nullptr)
    , app_(app)
    , temp_line_item_(new QGraphicsLineItem)
    , selected_connector_on_press_(false)
    , selected_output_node_id_("")
    , selected_output_index_(-1)
    , selected_input_node_id_("")
    , selected_input_index_(-1)
{
    scene_ = new QGraphicsScene;

    QPushButton* add_node_button = new QPushButton(tr("Add node"));
    connect(add_node_button, &QPushButton::clicked, this, &MainWindow::addNodeClicked);
    QPushButton* execute_button = new QPushButton(tr("Execute"));
    connect(execute_button, &QPushButton::clicked, this, &MainWindow::executeClicked);
    QPushButton* clear_button = new QPushButton(tr("Clear"));
    connect(clear_button, &QPushButton::clicked, this, &MainWindow::clearClicked);
    QPushButton* test_button = new QPushButton(tr("Test"));
    connect(test_button, &QPushButton::clicked, this, &MainWindow::testClicked);
    show_types_box_ = new QCheckBox(tr("Show types"));
    connect(show_types_box_, &QCheckBox::stateChanged, this, &MainWindow::showTypes);

    QHBoxLayout* toolbar_layout = new QHBoxLayout;
    toolbar_layout->addWidget(add_node_button);
    toolbar_layout->addWidget(execute_button);
    toolbar_layout->addWidget(clear_button);
    toolbar_layout->addWidget(test_button);
    toolbar_layout->addWidget(show_types_box_);
    toolbar_layout->addStretch();

    scene_view_ = new NetworkSceneView(scene_);
    scene_view_->setDelegate(this);
    scene_view_->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
    scene_view_->setAcceptDrops(true);

    QStringList types;
    std::vector<std::string> available_types = app->availableNodeTypes();
    for (int i = 0; i < (int)available_types.size(); ++i)
    {
        types << QString::fromStdString(available_types[i]);
    }
    types_list_ = new TypesWidget;
    types_list_->setMaximumWidth(150);
    types_list_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
    types_list_->addItems(types);
    types_list_->setSelectionMode(QAbstractItemView::SingleSelection);

    QHBoxLayout* central_layout = new QHBoxLayout;
    central_layout->addWidget(types_list_);
    central_layout->addWidget(scene_view_);

    log_view_ = new QTextEdit();
    log_view_->setReadOnly(true);
    log_view_->setMaximumHeight(200);
    log_view_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);

    QVBoxLayout* main_layout = new QVBoxLayout;
    main_layout->addLayout(toolbar_layout);
    main_layout->addLayout(central_layout);
    main_layout->addWidget(log_view_);

    QWidget* central_widget = new QWidget;
    central_widget->setLayout(main_layout);
    setCentralWidget(central_widget);

    Logger::instance().addDelegate(this);
}

MainWindow::~MainWindow()
{
    scene_view_->setScene(nullptr);
    delete scene_;
    delete temp_line_item_;
    node_items_.clear();
    connection_items_.clear();

    Logger::instance().removeDelegate(this);
}

std::string MainWindow::promptString(const std::string &message)
{
    std::string text = QInputDialog::getText(this, tr("Enter Input:"), QString::fromStdString(message)).toStdString();
    return text;
}

bool MainWindow::promptBool(const std::string &message)
{
    QMessageBox::StandardButton button = QMessageBox::question(this, tr("Enter Input:"), QString::fromStdString(message));
    return button == QMessageBox::Yes;
}

std::map<std::string, std::string> MainWindow::promptParameters(const std::vector<std::string> &parameters)
{
    ParametersDialog dialog(parameters, this);
    dialog.setWindowTitle(tr("Enter parameters:"));

    int result = dialog.exec();
    if (result == QDialog::Accepted)
    {
        return dialog.parameterValues();
    }
    else
    {
        return std::map<std::string, std::string>();
    }
}

void MainWindow::displayError(const std::string &message)
{
    QMessageBox::critical(this, "Error!", QString::fromStdString(message));
}

void MainWindow::nodeAdded(NodeProxy node)
{
    addNode(node, this->last_drop_pos_);
}

void MainWindow::connectionAdded(ConnectionProxy connection)
{
    NodeItem* output_node_item = node_items_.value(connection.outputNodeID());
    NodeItem* input_node_item = node_items_.value(connection.inputNodeID());

    ConnectionItem* item = new ConnectionItem(output_node_item, connection.outputIndex(),
                                              input_node_item, connection.inputIndex());
    scene_->addItem(item);

    QString connection_id = createConnectionID(connection.outputNodeID(), connection.outputIndex(),
                                               connection.inputNodeID(), connection.inputIndex());
    connection_items_.insert(connection_id, item);
}

void MainWindow::connectionRemoved(ConnectionProxy connection)
{
    QString connection_id = createConnectionID(connection.outputNodeID(), connection.outputIndex(),
                                               connection.inputNodeID(), connection.inputIndex());
    ConnectionItem* item = connection_items_[connection_id];
    connection_items_.remove(connection_id);

    scene_->removeItem(item);
    scene_->views().at(0)->repaint();

    delete item;
}

void MainWindow::logMessage(const std::string &message)
{
    log_view_->setTextColor(QColor(Qt::black));
    log_view_->append(QString::fromStdString(message));
}

void MainWindow::logError(const std::string &message)
{
    log_view_->setTextColor(QColor(Qt::red));
    log_view_->append(QString::fromStdString(message));
}

void MainWindow::networkSceneViewPressedAt(const QPoint &pos)
{
    selected_input_index_ = -1;
    selected_input_node_id_ = "";
    selected_output_index_ = -1;
    selected_output_node_id_ = "";

    selected_connector_on_press_ = selectInputIfUnderPos(pos) || selectOutputIfUnderPos(pos);

    if (selected_connector_on_press_)
    {
        QPointF item_pos = temp_line_item_->mapFromScene(scene_view_->mapToScene(pos));

        temp_line_.setPoints(item_pos, item_pos);
        temp_line_item_->setLine(temp_line_);
        scene_->addItem(temp_line_item_);
    }
}

void MainWindow::networkSceneViewReleasedAt(const QPoint &pos)
{
    if (temp_line_item_->scene() == scene_)
    {
        scene_->removeItem(temp_line_item_);
    }
    bool selected_connector_on_release = selectInputIfUnderPos(pos) || selectOutputIfUnderPos(pos);

    if (selected_connector_on_press_ && selected_connector_on_release)
    {
        addConnectionBetweenSelectedNodes();
    }

    selected_connector_on_press_ = false;
}

void MainWindow::networkSceneViewMoved(const QPoint &pos)
{
    if (selected_connector_on_press_)
    {
        QPointF item_pos = temp_line_item_->mapFromScene(scene_view_->mapToScene(pos));
        temp_line_.setP2(item_pos);
        temp_line_item_->setLine(temp_line_);
    }
}

void MainWindow::networkSceneViewNodeTypeDroppedAt(const QString &type, const QPoint &pos)
{
    std::string type_str = type.toStdString();
    last_drop_pos_ = pos;
    app_->createNode(type_str);
}

void MainWindow::nodeMoved(NodeItem *item)
{
    scene_->update(scene_view_->sceneRect());
}

bool MainWindow::selectInputIfUnderPos(const QPoint &pos)
{
    QPointF scene_pos = scene_view_->mapToScene(pos);
    NodeItem* item_under_pos = dynamic_cast<NodeItem*>(scene_->itemAt(scene_pos, scene_view_->transform()));

    if (item_under_pos != nullptr)
    {
        QPointF item_pos = item_under_pos->mapFromScene(scene_pos);

        int input_index = item_under_pos->indexOfInputUnder(item_pos);
        if (input_index != -1)
        {
            selected_input_index_ = input_index;
            selected_input_node_id_ = item_under_pos->nodeID();
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

bool MainWindow::selectOutputIfUnderPos(const QPoint& pos)
{
    QPointF scene_pos = scene_view_->mapToScene(pos);
    NodeItem* item_under_pos = dynamic_cast<NodeItem*>(scene_->itemAt(scene_pos, scene_view_->transform()));

    if (item_under_pos != nullptr)
    {
        QPointF item_pos = item_under_pos->mapFromScene(scene_pos);

        int output_index = item_under_pos->indexOfOutputUnder(item_pos);
        if (output_index != -1)
        {
            selected_output_index_ = output_index;
            selected_output_node_id_ = item_under_pos->nodeID();
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

void MainWindow::addNodeClicked()
{
    foreach (QListWidgetItem* item, types_list_->selectedItems())
    {
        std::string type = item->text().toStdString();
        last_drop_pos_ = QPoint(0,0);
        app_->createNode(type);
    }
}

void MainWindow::addNode(const NodeProxy &node, const QPoint &pos)
{
    NodeItem* node_item = new NodeItem(node, show_types_box_->isChecked());

    QPointF scene_pos = scene_view_->mapToScene(pos);
    QTransform transform;
    transform.translate(scene_pos.x(),scene_pos.y());
    node_item->setTransform(transform);

    scene_->addItem(node_item);
    node_items_.insert(node.id(), node_item);
    node_item->addDelegate(this);
}

void MainWindow::addConnectionBetweenSelectedNodes()
{
    if (selected_input_node_id_.empty() || selected_input_index_ == -1 ||
        selected_output_node_id_.empty() || selected_output_index_ == -1)
    {
        return;
    }
    else
    {
        app_->connectNodes(selected_output_node_id_,
                           selected_output_index_,
                           selected_input_node_id_,
                           selected_input_index_);
    }

}

QString MainWindow::createConnectionID(const std::string& outputNodeID, int outputIndex,
                                       const std::string& inputNodeID, int inputIndex) const
{
    QStringList list;

    list << QString::fromStdString(outputNodeID);
    list << QString::number(outputIndex);
    list << QString::fromStdString(inputNodeID);
    list << QString::number(inputIndex);

    return list.join(",");
}

void MainWindow::executeClicked()
{
    app_->executeTerminalNodes();
}

void MainWindow::clearClicked()
{
    bool ok = app_->clearAllNodes();

    if (ok)
    {
        scene_view_->setScene(nullptr);
        delete scene_;
        node_items_.clear();
        connection_items_.clear();

        scene_ = new QGraphicsScene;
        scene_view_->setScene(scene_);
    }
}

void MainWindow::testClicked()
{
    app_->addTestScenario();
}

void MainWindow::showTypes(int state)
{
    foreach (NodeItem* item, node_items_.values())
    {
        item->setShowIONames(state == Qt::Checked);
    }
    scene_->update(scene_view_->sceneRect());
}
<commit_msg>Remove TypesWidget implementation from MainWindow and use the copied implementation.<commit_after>
// Includes.
#include "UI/MainWindow.h"
#include "UI/NodeItem.h"
#include "UI/ConnectionItem.h"
#include "UI/ParametersDialog.h"
#include "UI/TypesWidget.h"
#include "App/App.h"
#include "App/Boundary/NodeProxy.h"
#include "App/Boundary/ConnectionProxy.h"

// Qt.
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QStringListModel>
#include <QGraphicsLineItem>
#include <QCheckBox>

MainWindow::MainWindow(App *app, QWidget *parent)
    : QMainWindow(parent)
    , types_list_(nullptr)
    , scene_view_(nullptr)
    , log_view_(nullptr)
    , show_types_box_(nullptr)
    , scene_(nullptr)
    , app_(app)
    , temp_line_item_(new QGraphicsLineItem)
    , selected_connector_on_press_(false)
    , selected_output_node_id_("")
    , selected_output_index_(-1)
    , selected_input_node_id_("")
    , selected_input_index_(-1)
{
    scene_ = new QGraphicsScene;

    QPushButton* add_node_button = new QPushButton(tr("Add node"));
    connect(add_node_button, &QPushButton::clicked, this, &MainWindow::addNodeClicked);
    QPushButton* execute_button = new QPushButton(tr("Execute"));
    connect(execute_button, &QPushButton::clicked, this, &MainWindow::executeClicked);
    QPushButton* clear_button = new QPushButton(tr("Clear"));
    connect(clear_button, &QPushButton::clicked, this, &MainWindow::clearClicked);
    QPushButton* test_button = new QPushButton(tr("Test"));
    connect(test_button, &QPushButton::clicked, this, &MainWindow::testClicked);
    show_types_box_ = new QCheckBox(tr("Show types"));
    connect(show_types_box_, &QCheckBox::stateChanged, this, &MainWindow::showTypes);

    QHBoxLayout* toolbar_layout = new QHBoxLayout;
    toolbar_layout->addWidget(add_node_button);
    toolbar_layout->addWidget(execute_button);
    toolbar_layout->addWidget(clear_button);
    toolbar_layout->addWidget(test_button);
    toolbar_layout->addWidget(show_types_box_);
    toolbar_layout->addStretch();

    scene_view_ = new NetworkSceneView(scene_);
    scene_view_->setDelegate(this);
    scene_view_->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
    scene_view_->setAcceptDrops(true);

    QStringList types;
    std::vector<std::string> available_types = app->availableNodeTypes();
    for (int i = 0; i < (int)available_types.size(); ++i)
    {
        types << QString::fromStdString(available_types[i]);
    }
    types_list_ = new TypesWidget;
    types_list_->setMaximumWidth(150);
    types_list_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
    types_list_->addItems(types);
    types_list_->setSelectionMode(QAbstractItemView::SingleSelection);

    QHBoxLayout* central_layout = new QHBoxLayout;
    central_layout->addWidget(types_list_);
    central_layout->addWidget(scene_view_);

    log_view_ = new QTextEdit();
    log_view_->setReadOnly(true);
    log_view_->setMaximumHeight(200);
    log_view_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);

    QVBoxLayout* main_layout = new QVBoxLayout;
    main_layout->addLayout(toolbar_layout);
    main_layout->addLayout(central_layout);
    main_layout->addWidget(log_view_);

    QWidget* central_widget = new QWidget;
    central_widget->setLayout(main_layout);
    setCentralWidget(central_widget);

    Logger::instance().addDelegate(this);
}

MainWindow::~MainWindow()
{
    scene_view_->setScene(nullptr);
    delete scene_;
    delete temp_line_item_;
    node_items_.clear();
    connection_items_.clear();

    Logger::instance().removeDelegate(this);
}

std::string MainWindow::promptString(const std::string &message)
{
    std::string text = QInputDialog::getText(this, tr("Enter Input:"), QString::fromStdString(message)).toStdString();
    return text;
}

bool MainWindow::promptBool(const std::string &message)
{
    QMessageBox::StandardButton button = QMessageBox::question(this, tr("Enter Input:"), QString::fromStdString(message));
    return button == QMessageBox::Yes;
}

std::map<std::string, std::string> MainWindow::promptParameters(const std::vector<std::string> &parameters)
{
    ParametersDialog dialog(parameters, this);
    dialog.setWindowTitle(tr("Enter parameters:"));

    int result = dialog.exec();
    if (result == QDialog::Accepted)
    {
        return dialog.parameterValues();
    }
    else
    {
        return std::map<std::string, std::string>();
    }
}

void MainWindow::displayError(const std::string &message)
{
    QMessageBox::critical(this, "Error!", QString::fromStdString(message));
}

void MainWindow::nodeAdded(NodeProxy node)
{
    addNode(node, this->last_drop_pos_);
}

void MainWindow::connectionAdded(ConnectionProxy connection)
{
    NodeItem* output_node_item = node_items_.value(connection.outputNodeID());
    NodeItem* input_node_item = node_items_.value(connection.inputNodeID());

    ConnectionItem* item = new ConnectionItem(output_node_item, connection.outputIndex(),
                                              input_node_item, connection.inputIndex());
    scene_->addItem(item);

    QString connection_id = createConnectionID(connection.outputNodeID(), connection.outputIndex(),
                                               connection.inputNodeID(), connection.inputIndex());
    connection_items_.insert(connection_id, item);
}

void MainWindow::connectionRemoved(ConnectionProxy connection)
{
    QString connection_id = createConnectionID(connection.outputNodeID(), connection.outputIndex(),
                                               connection.inputNodeID(), connection.inputIndex());
    ConnectionItem* item = connection_items_[connection_id];
    connection_items_.remove(connection_id);

    scene_->removeItem(item);
    scene_->views().at(0)->repaint();

    delete item;
}

void MainWindow::logMessage(const std::string &message)
{
    log_view_->setTextColor(QColor(Qt::black));
    log_view_->append(QString::fromStdString(message));
}

void MainWindow::logError(const std::string &message)
{
    log_view_->setTextColor(QColor(Qt::red));
    log_view_->append(QString::fromStdString(message));
}

void MainWindow::networkSceneViewPressedAt(const QPoint &pos)
{
    selected_input_index_ = -1;
    selected_input_node_id_ = "";
    selected_output_index_ = -1;
    selected_output_node_id_ = "";

    selected_connector_on_press_ = selectInputIfUnderPos(pos) || selectOutputIfUnderPos(pos);

    if (selected_connector_on_press_)
    {
        QPointF item_pos = temp_line_item_->mapFromScene(scene_view_->mapToScene(pos));

        temp_line_.setPoints(item_pos, item_pos);
        temp_line_item_->setLine(temp_line_);
        scene_->addItem(temp_line_item_);
    }
}

void MainWindow::networkSceneViewReleasedAt(const QPoint &pos)
{
    if (temp_line_item_->scene() == scene_)
    {
        scene_->removeItem(temp_line_item_);
    }
    bool selected_connector_on_release = selectInputIfUnderPos(pos) || selectOutputIfUnderPos(pos);

    if (selected_connector_on_press_ && selected_connector_on_release)
    {
        addConnectionBetweenSelectedNodes();
    }

    selected_connector_on_press_ = false;
}

void MainWindow::networkSceneViewMoved(const QPoint &pos)
{
    if (selected_connector_on_press_)
    {
        QPointF item_pos = temp_line_item_->mapFromScene(scene_view_->mapToScene(pos));
        temp_line_.setP2(item_pos);
        temp_line_item_->setLine(temp_line_);
    }
}

void MainWindow::networkSceneViewNodeTypeDroppedAt(const QString &type, const QPoint &pos)
{
    std::string type_str = type.toStdString();
    last_drop_pos_ = pos;
    app_->createNode(type_str);
}

void MainWindow::nodeMoved(NodeItem *item)
{
    scene_->update(scene_view_->sceneRect());
}

bool MainWindow::selectInputIfUnderPos(const QPoint &pos)
{
    QPointF scene_pos = scene_view_->mapToScene(pos);
    NodeItem* item_under_pos = dynamic_cast<NodeItem*>(scene_->itemAt(scene_pos, scene_view_->transform()));

    if (item_under_pos != nullptr)
    {
        QPointF item_pos = item_under_pos->mapFromScene(scene_pos);

        int input_index = item_under_pos->indexOfInputUnder(item_pos);
        if (input_index != -1)
        {
            selected_input_index_ = input_index;
            selected_input_node_id_ = item_under_pos->nodeID();
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

bool MainWindow::selectOutputIfUnderPos(const QPoint& pos)
{
    QPointF scene_pos = scene_view_->mapToScene(pos);
    NodeItem* item_under_pos = dynamic_cast<NodeItem*>(scene_->itemAt(scene_pos, scene_view_->transform()));

    if (item_under_pos != nullptr)
    {
        QPointF item_pos = item_under_pos->mapFromScene(scene_pos);

        int output_index = item_under_pos->indexOfOutputUnder(item_pos);
        if (output_index != -1)
        {
            selected_output_index_ = output_index;
            selected_output_node_id_ = item_under_pos->nodeID();
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

void MainWindow::addNodeClicked()
{
    foreach (QListWidgetItem* item, types_list_->selectedItems())
    {
        std::string type = item->text().toStdString();
        last_drop_pos_ = QPoint(0,0);
        app_->createNode(type);
    }
}

void MainWindow::addNode(const NodeProxy &node, const QPoint &pos)
{
    NodeItem* node_item = new NodeItem(node, show_types_box_->isChecked());

    QPointF scene_pos = scene_view_->mapToScene(pos);
    QTransform transform;
    transform.translate(scene_pos.x(),scene_pos.y());
    node_item->setTransform(transform);

    scene_->addItem(node_item);
    node_items_.insert(node.id(), node_item);
    node_item->addDelegate(this);
}

void MainWindow::addConnectionBetweenSelectedNodes()
{
    if (selected_input_node_id_.empty() || selected_input_index_ == -1 ||
        selected_output_node_id_.empty() || selected_output_index_ == -1)
    {
        return;
    }
    else
    {
        app_->connectNodes(selected_output_node_id_,
                           selected_output_index_,
                           selected_input_node_id_,
                           selected_input_index_);
    }

}

QString MainWindow::createConnectionID(const std::string& outputNodeID, int outputIndex,
                                       const std::string& inputNodeID, int inputIndex) const
{
    QStringList list;

    list << QString::fromStdString(outputNodeID);
    list << QString::number(outputIndex);
    list << QString::fromStdString(inputNodeID);
    list << QString::number(inputIndex);

    return list.join(",");
}

void MainWindow::executeClicked()
{
    app_->executeTerminalNodes();
}

void MainWindow::clearClicked()
{
    bool ok = app_->clearAllNodes();

    if (ok)
    {
        scene_view_->setScene(nullptr);
        delete scene_;
        node_items_.clear();
        connection_items_.clear();

        scene_ = new QGraphicsScene;
        scene_view_->setScene(scene_);
    }
}

void MainWindow::testClicked()
{
    app_->addTestScenario();
}

void MainWindow::showTypes(int state)
{
    foreach (NodeItem* item, node_items_.values())
    {
        item->setShowIONames(state == Qt::Checked);
    }
    scene_->update(scene_view_->sceneRect());
}
<|endoftext|>