<commit_before>/*
 * ccookies.hpp
 *
 *  Created on: 19.11.2014
 *      Author: andreas
 */

#ifndef CCOOKIES_HPP_
#define CCOOKIES_HPP_

#include <inttypes.h>

#include <rofl/common/crofdpt.h>
#include <rofl/common/cauxid.h>
#include <rofl/common/crandom.h>
#include <rofl/common/openflow/messages/cofmsg_packet_in.h>
#include <rofl/common/openflow/messages/cofmsg_flow_removed.h>

namespace roflibs {
namespace common {
namespace openflow {

class ccookiebox; // forward declaration, see below

class ccookie_owner {
public:

	/**
	 *
	 */
	virtual
	~ccookie_owner();

public:

	/**
	 *
	 */
	uint64_t
	acquire_cookie();

	/**
	 *
	 */
	void
	release_cookie(uint64_t cookie);

protected:

	friend class ccookiebox;

	/**
	 *
	 */
	virtual void
	handle_packet_in(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_packet_in& msg) = 0;

	/**
	 *
	 */
	virtual void
	handle_flow_removed(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_flow_removed& msg) = 0;
};

class ccookie_find_by_owner {
	ccookie_owner* owner;
public:
	ccookie_find_by_owner(ccookie_owner* owner) :
		owner(owner) {};
	bool operator() (const std::pair<uint64_t, ccookie_owner*>& p) {
		return (p.second == owner);
	};
};

class ccookiebox {
private:

	static ccookiebox* 					cookiebox;
	uint64_t 							next_cookie;
	std::map<uint64_t, ccookie_owner*> 	cookiestore;
	ccookiebox() : next_cookie(rofl::crandom(8).uint64()) {};
	~ccookiebox() {};

public:

	/**
	 *
	 */
	static ccookiebox&
	get_instance() {
		if ((ccookiebox*)0 == ccookiebox::cookiebox) {
			ccookiebox::cookiebox = new ccookiebox();
		}
		return *(ccookiebox::cookiebox);
	};

	/**
	 *
	 */
	void
	handle_packet_in(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_packet_in& msg) {
		if (cookiestore.find(msg.get_cookie()) == cookiestore.end()) {
			return;
		}
		cookiestore[msg.get_cookie()]->handle_packet_in(dpt, auxid, msg);
	};

	/**
	 *
	 */
	void
	handle_flow_removed(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_flow_removed& msg) {
		if (cookiestore.find(msg.get_cookie()) == cookiestore.end()) {
			return;
		}
		cookiestore[msg.get_cookie()]->handle_flow_removed(dpt, auxid, msg);
	};

private:

	friend class ccookie_owner;

	/**
	 *
	 */
	void
	deregister_cookie_owner(ccookie_owner* owner) {
		std::map<uint64_t, ccookie_owner*>::iterator it;
		while ((it = find_if(cookiestore.begin(), cookiestore.end(),
				ccookie_find_by_owner(owner))) != cookiestore.end()) {
			cookiestore.erase(it);
		}
	};

	/**
	 *
	 */
	uint64_t
	acquire_cookie(ccookie_owner* owner) {
		do {
			next_cookie++;
		} while (cookiestore.find(next_cookie) != cookiestore.end());
		cookiestore[next_cookie] = owner;
		return next_cookie;
	};

	/**
	 *
	 */
	void
	release_cookie(ccookie_owner* owner, uint64_t cookie) {
		if (cookiestore.find(cookie) == cookiestore.end()) {
			return;
		}
		if (cookiestore[cookie] != owner) {
			return;
		}
		cookiestore.erase(cookie);
	};
};

}; // end of namespace openflow
}; // end of namespace common
}; // end of namespace roflibs

#endif /* CCOOKIES_HPP_ */
<commit_msg>ccookiebox => added more debug output<commit_after>/*
 * ccookies.hpp
 *
 *  Created on: 19.11.2014
 *      Author: andreas
 */

#ifndef CCOOKIES_HPP_
#define CCOOKIES_HPP_

#include <inttypes.h>

#include <rofl/common/crofdpt.h>
#include <rofl/common/cauxid.h>
#include <rofl/common/crandom.h>
#include <rofl/common/openflow/messages/cofmsg_packet_in.h>
#include <rofl/common/openflow/messages/cofmsg_flow_removed.h>

#include "roflibs/netlink/clogging.hpp"

namespace roflibs {
namespace common {
namespace openflow {

class ccookiebox; // forward declaration, see below

class ccookie_owner {
public:

	/**
	 *
	 */
	virtual
	~ccookie_owner();

public:

	/**
	 *
	 */
	uint64_t
	acquire_cookie();

	/**
	 *
	 */
	void
	release_cookie(uint64_t cookie);

protected:

	friend class ccookiebox;

	/**
	 *
	 */
	virtual void
	handle_packet_in(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_packet_in& msg) = 0;

	/**
	 *
	 */
	virtual void
	handle_flow_removed(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_flow_removed& msg) = 0;
};

class ccookie_find_by_owner {
	ccookie_owner* owner;
public:
	ccookie_find_by_owner(ccookie_owner* owner) :
		owner(owner) {};
	bool operator() (const std::pair<uint64_t, ccookie_owner*>& p) {
		return (p.second == owner);
	};
};

class ccookiebox {
private:

	static ccookiebox* 					cookiebox;
	uint64_t 							next_cookie;
	std::map<uint64_t, ccookie_owner*> 	cookiestore;
	ccookiebox() : next_cookie(rofl::crandom(8).uint64()) {};
	~ccookiebox() {};

public:

	/**
	 *
	 */
	static ccookiebox&
	get_instance() {
		if ((ccookiebox*)0 == ccookiebox::cookiebox) {
			ccookiebox::cookiebox = new ccookiebox();
		}
		return *(ccookiebox::cookiebox);
	};

	/**
	 *
	 */
	void
	handle_packet_in(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_packet_in& msg) {
		if (cookiestore.find(msg.get_cookie()) == cookiestore.end()) {
			rofcore::logging::debug << "[ccookiebox][handle_packet_in] cookie:" << (unsigned long long)msg.get_cookie()
					<< " not found, dropping packet" << std::endl;
			return;
		}
		cookiestore[msg.get_cookie()]->handle_packet_in(dpt, auxid, msg);
	};

	/**
	 *
	 */
	void
	handle_flow_removed(
			rofl::crofdpt& dpt, const rofl::cauxid& auxid, rofl::openflow::cofmsg_flow_removed& msg) {
		if (cookiestore.find(msg.get_cookie()) == cookiestore.end()) {
			rofcore::logging::debug << "[ccookiebox][handle_flow_removed] cookie:" << (unsigned long long)msg.get_cookie()
					<< " not found, dropping packet" << std::endl;
			return;
		}
		cookiestore[msg.get_cookie()]->handle_flow_removed(dpt, auxid, msg);
	};

private:

	friend class ccookie_owner;

	/**
	 *
	 */
	void
	deregister_cookie_owner(ccookie_owner* owner) {
		std::map<uint64_t, ccookie_owner*>::iterator it;
		while ((it = find_if(cookiestore.begin(), cookiestore.end(),
				ccookie_find_by_owner(owner))) != cookiestore.end()) {
			cookiestore.erase(it);
		}
	};

	/**
	 *
	 */
	uint64_t
	acquire_cookie(ccookie_owner* owner) {
		do {
			next_cookie++;
		} while (cookiestore.find(next_cookie) != cookiestore.end());
		cookiestore[next_cookie] = owner;
		return next_cookie;
	};

	/**
	 *
	 */
	void
	release_cookie(ccookie_owner* owner, uint64_t cookie) {
		if (cookiestore.find(cookie) == cookiestore.end()) {
			return;
		}
		if (cookiestore[cookie] != owner) {
			return;
		}
		cookiestore.erase(cookie);
	};
};

}; // end of namespace openflow
}; // end of namespace common
}; // end of namespace roflibs

#endif /* CCOOKIES_HPP_ */
<|endoftext|>


<commit_before>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "sacnuniverselistmodel.h"
#include <QDebug>
#include <QNetworkInterface>
#include "streamingacn.h"
#include "streamcommon.h"
#include "ipaddr.h"
#include "preferences.h"
#include "sacnsocket.h"
#include "consts.h"

sACNUniverseInfo::sACNUniverseInfo(int u)
{
    universe = u;
}

sACNUniverseInfo::~sACNUniverseInfo()
{
    qDeleteAll(sources);
    sources.clear();
    sourcesByCid.clear();
}

sACNBasicSourceInfo::sACNBasicSourceInfo(sACNUniverseInfo *p)
{
    parent = p;
}

sACNUniverseListModel::sACNUniverseListModel(QObject *parent) : QAbstractItemModel(parent)
{
    m_start = MIN_SACN_UNIVERSE;

    setStartUniverse(m_start);

    m_checkTimeoutTimer = new QTimer(this);
    connect(m_checkTimeoutTimer, SIGNAL(timeout()), this, SLOT(checkTimeouts()));
    m_checkTimeoutTimer->start(5000);
}

void sACNUniverseListModel::setStartUniverse(int start)
{
    QMutexLocker locker(&mutex_readPendingDatagrams);

    QNetworkInterface iface = Preferences::getInstance()->networkInterface();

    // Limit max value
    static const int startMax = (MAX_SACN_UNIVERSE - NUM_UNIVERSES_LISTED) + 1;
    if (start > startMax) start = startMax;

    beginResetModel();

    qDeleteAll(m_universes);
    m_universes.clear();

    // Destroy all old sockets
    qDeleteAll(m_sockets);
    m_sockets.clear();

    // Listen unicast
    m_sockets.push_back(new sACNRxSocket(this));
    m_sockets.back()->bindUnicast();
    connect(m_sockets.back(), SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

    // Listen multicast
    m_start = start;
    for(int universe=m_start; universe<m_start+NUM_UNIVERSES_LISTED; universe++)
    {
        CIPAddr addr;
        GetUniverseAddress(universe, addr);

        m_sockets.push_back(new sACNRxSocket(this));
        m_sockets.back()->bindMulticast(universe);
        connect(m_sockets.back(), SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

        m_universes << new sACNUniverseInfo(universe);
    }

    endResetModel();
}

int sACNUniverseListModel::rowCount(const QModelIndex &parent) const
{
    if(parent.isValid() && parent.internalPointer()==NULL)
    {
        return m_universes[parent.row()]->sources.count();

    }
    if(!parent.isValid())
    {
        return m_universes.count();
    }

    return 0;
}

int sACNUniverseListModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 1;
}

QVariant sACNUniverseListModel::data(const QModelIndex &index, int role) const
{
    if(role==Qt::DisplayRole)
    {
        if(index.parent().isValid())
        {
            sACNBasicSourceInfo *info = (sACNBasicSourceInfo *) index.internalPointer();
            return tr("%1 (%2)").arg(info->name).arg(info->address.toString());
        }
        else
            return QVariant(tr("Universe %1").arg(index.row() + m_start));
    }
    return QVariant();
}

QModelIndex sACNUniverseListModel::index(int row, int column, const QModelIndex &parent) const
{
    if(!hasIndex(row, column, parent))
        return QModelIndex();
    if(!parent.isValid()) // This is a root item
        return createIndex(row, column);
    if(parent.isValid() && !parent.parent().isValid())
    {
        if(m_universes[parent.row()]->sources.count() >= row)
        {
            return createIndex(row, column, m_universes[parent.row()]->sources.at(row));
        }
    }

    return QModelIndex();
}

QModelIndex sACNUniverseListModel::parent(const QModelIndex &index) const
{
    if(!index.isValid())
        return QModelIndex();

    sACNBasicSourceInfo *i = static_cast<sACNBasicSourceInfo *>(index.internalPointer());
    if(i)
    {
        int parentRow = i->parent->universe - m_start;
        return createIndex(parentRow, 0);
    }

    return QModelIndex();
}

void sACNUniverseListModel::readPendingDatagrams()
{
    QMutexLocker locker(&mutex_readPendingDatagrams);

    // Check all sockets
    foreach (sACNRxSocket* m_socket, m_sockets)
    {
        while(m_socket->hasPendingDatagrams())
        {
            QByteArray datagram;
            datagram.resize(m_socket->pendingDatagramSize());
            QHostAddress sender;
            quint16 senderPort;

            m_socket->readDatagram(datagram.data(), datagram.size(),
                                    &sender, &senderPort);

            // Process the data
            CID source_cid;
            uint1 start_code;
            uint1 sequence;
            uint2 universe;
            uint2 slot_count;
            uint1* pdata;
            char source_name [SOURCE_NAME_SIZE];
            uint1 priority;
            //These only apply to the ratified version of the spec, so we will hardwire
            //them to be 0 just in case they never get set.
            uint2 reserved = 0;
            uint1 options = 0;
            uint1 *pbuf = (uint1*)datagram.data();

            if(!ValidateStreamHeader(pbuf, datagram.length(), source_cid, source_name, priority,
                    start_code, reserved, sequence, options, universe, slot_count, pdata))
            {
                // Recieved a packet but not valid. Log and discard
                qDebug() << "Invalid Packet";
                continue;
            }

            sACNBasicSourceInfo *info = 0;
            int univIndex = universe - m_start;
            if (
                    (univIndex > m_universes.count())
                     or (univIndex < 0)
                ) { continue; }

            if(!m_universes[univIndex]->sourcesByCid.contains(source_cid))
            {
                info = new sACNBasicSourceInfo(m_universes[univIndex]);
                info->cid = source_cid;
            }
            else
            {
                info = m_universes[univIndex]->sourcesByCid.value(source_cid);
                info->timeout.restart();
            }

            info->address = sender;
            info->name = source_name;

            if(!m_universes[univIndex]->sourcesByCid.contains(source_cid))
            {
                // We are adding the source for this universe
                QModelIndex parent = index(m_start - universe, 0);
                int firstRow = m_universes[univIndex]->sources.count()+1;
                int lastRow = firstRow;
                beginInsertRows(parent, firstRow, lastRow);
                m_universes[univIndex]->sources << info;
                m_universes[univIndex]->sourcesByCid[source_cid] = info;
                endInsertRows();
            }

        }
    }
}

void sACNUniverseListModel::checkTimeouts()
{
    foreach(sACNUniverseInfo *info, m_universes)
    {
        for(int row=0; row<info->sources.count(); row++)
        {
            sACNBasicSourceInfo *source = info->sources[row];
            if(source->timeout.elapsed() > 5000)
            {
                beginRemoveRows( createIndex(info->universe - m_start, 0),
                            row, row);
                info->sources.removeAll(source);
                info->sourcesByCid.remove(source->cid);
                delete source;
                endRemoveRows();
            }
        }
    }
}

int sACNUniverseListModel::indexToUniverse(const QModelIndex &index)
{
    if(!index.isValid())
        return 0;

    if(index.internalPointer()==NULL)
    {
        // root item
        return m_start + index.row();
    }

    sACNBasicSourceInfo *i = static_cast<sACNBasicSourceInfo *>(index.internalPointer());
    if(i)
    {
        return i->parent->universe;
    }

    return 0;
}
<commit_msg>Fix the build for MSVC<commit_after>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "sacnuniverselistmodel.h"
#include <QDebug>
#include <QNetworkInterface>
#include "streamingacn.h"
#include "streamcommon.h"
#include "ipaddr.h"
#include "preferences.h"
#include "sacnsocket.h"
#include "consts.h"

sACNUniverseInfo::sACNUniverseInfo(int u)
{
    universe = u;
}

sACNUniverseInfo::~sACNUniverseInfo()
{
    qDeleteAll(sources);
    sources.clear();
    sourcesByCid.clear();
}

sACNBasicSourceInfo::sACNBasicSourceInfo(sACNUniverseInfo *p)
{
    parent = p;
}

sACNUniverseListModel::sACNUniverseListModel(QObject *parent) : QAbstractItemModel(parent)
{
    m_start = MIN_SACN_UNIVERSE;

    setStartUniverse(m_start);

    m_checkTimeoutTimer = new QTimer(this);
    connect(m_checkTimeoutTimer, SIGNAL(timeout()), this, SLOT(checkTimeouts()));
    m_checkTimeoutTimer->start(5000);
}

void sACNUniverseListModel::setStartUniverse(int start)
{
    QMutexLocker locker(&mutex_readPendingDatagrams);

    QNetworkInterface iface = Preferences::getInstance()->networkInterface();

    // Limit max value
    static const int startMax = (MAX_SACN_UNIVERSE - NUM_UNIVERSES_LISTED) + 1;
    if (start > startMax) start = startMax;

    beginResetModel();

    qDeleteAll(m_universes);
    m_universes.clear();

    // Destroy all old sockets
    qDeleteAll(m_sockets);
    m_sockets.clear();

    // Listen unicast
    m_sockets.push_back(new sACNRxSocket(this));
    m_sockets.back()->bindUnicast();
    connect(m_sockets.back(), SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

    // Listen multicast
    m_start = start;
    for(int universe=m_start; universe<m_start+NUM_UNIVERSES_LISTED; universe++)
    {
        CIPAddr addr;
        GetUniverseAddress(universe, addr);

        m_sockets.push_back(new sACNRxSocket(this));
        m_sockets.back()->bindMulticast(universe);
        connect(m_sockets.back(), SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

        m_universes << new sACNUniverseInfo(universe);
    }

    endResetModel();
}

int sACNUniverseListModel::rowCount(const QModelIndex &parent) const
{
    if(parent.isValid() && parent.internalPointer()==NULL)
    {
        return m_universes[parent.row()]->sources.count();

    }
    if(!parent.isValid())
    {
        return m_universes.count();
    }

    return 0;
}

int sACNUniverseListModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 1;
}

QVariant sACNUniverseListModel::data(const QModelIndex &index, int role) const
{
    if(role==Qt::DisplayRole)
    {
        if(index.parent().isValid())
        {
            sACNBasicSourceInfo *info = (sACNBasicSourceInfo *) index.internalPointer();
            return tr("%1 (%2)").arg(info->name).arg(info->address.toString());
        }
        else
            return QVariant(tr("Universe %1").arg(index.row() + m_start));
    }
    return QVariant();
}

QModelIndex sACNUniverseListModel::index(int row, int column, const QModelIndex &parent) const
{
    if(!hasIndex(row, column, parent))
        return QModelIndex();
    if(!parent.isValid()) // This is a root item
        return createIndex(row, column);
    if(parent.isValid() && !parent.parent().isValid())
    {
        if(m_universes[parent.row()]->sources.count() >= row)
        {
            return createIndex(row, column, m_universes[parent.row()]->sources.at(row));
        }
    }

    return QModelIndex();
}

QModelIndex sACNUniverseListModel::parent(const QModelIndex &index) const
{
    if(!index.isValid())
        return QModelIndex();

    sACNBasicSourceInfo *i = static_cast<sACNBasicSourceInfo *>(index.internalPointer());
    if(i)
    {
        int parentRow = i->parent->universe - m_start;
        return createIndex(parentRow, 0);
    }

    return QModelIndex();
}

void sACNUniverseListModel::readPendingDatagrams()
{
    QMutexLocker locker(&mutex_readPendingDatagrams);

    // Check all sockets
    foreach (sACNRxSocket* m_socket, m_sockets)
    {
        while(m_socket->hasPendingDatagrams())
        {
            QByteArray datagram;
            datagram.resize(m_socket->pendingDatagramSize());
            QHostAddress sender;
            quint16 senderPort;

            m_socket->readDatagram(datagram.data(), datagram.size(),
                                    &sender, &senderPort);

            // Process the data
            CID source_cid;
            uint1 start_code;
            uint1 sequence;
            uint2 universe;
            uint2 slot_count;
            uint1* pdata;
            char source_name [SOURCE_NAME_SIZE];
            uint1 priority;
            //These only apply to the ratified version of the spec, so we will hardwire
            //them to be 0 just in case they never get set.
            uint2 reserved = 0;
            uint1 options = 0;
            uint1 *pbuf = (uint1*)datagram.data();

            if(!ValidateStreamHeader(pbuf, datagram.length(), source_cid, source_name, priority,
                    start_code, reserved, sequence, options, universe, slot_count, pdata))
            {
                // Recieved a packet but not valid. Log and discard
                qDebug() << "Invalid Packet";
                continue;
            }

            sACNBasicSourceInfo *info = 0;
            int univIndex = universe - m_start;
            if (
                    (univIndex > m_universes.count())
                     || (univIndex < 0)
                ) { continue; }

            if(!m_universes[univIndex]->sourcesByCid.contains(source_cid))
            {
                info = new sACNBasicSourceInfo(m_universes[univIndex]);
                info->cid = source_cid;
            }
            else
            {
                info = m_universes[univIndex]->sourcesByCid.value(source_cid);
                info->timeout.restart();
            }

            info->address = sender;
            info->name = source_name;

            if(!m_universes[univIndex]->sourcesByCid.contains(source_cid))
            {
                // We are adding the source for this universe
                QModelIndex parent = index(m_start - universe, 0);
                int firstRow = m_universes[univIndex]->sources.count()+1;
                int lastRow = firstRow;
                beginInsertRows(parent, firstRow, lastRow);
                m_universes[univIndex]->sources << info;
                m_universes[univIndex]->sourcesByCid[source_cid] = info;
                endInsertRows();
            }

        }
    }
}

void sACNUniverseListModel::checkTimeouts()
{
    foreach(sACNUniverseInfo *info, m_universes)
    {
        for(int row=0; row<info->sources.count(); row++)
        {
            sACNBasicSourceInfo *source = info->sources[row];
            if(source->timeout.elapsed() > 5000)
            {
                beginRemoveRows( createIndex(info->universe - m_start, 0),
                            row, row);
                info->sources.removeAll(source);
                info->sourcesByCid.remove(source->cid);
                delete source;
                endRemoveRows();
            }
        }
    }
}

int sACNUniverseListModel::indexToUniverse(const QModelIndex &index)
{
    if(!index.isValid())
        return 0;

    if(index.internalPointer()==NULL)
    {
        // root item
        return m_start + index.row();
    }

    sACNBasicSourceInfo *i = static_cast<sACNBasicSourceInfo *>(index.internalPointer());
    if(i)
    {
        return i->parent->universe;
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 *
 * TransactionParser
 * ledger-core
 *
 * Created by Pierre Pollastri on 27/03/2017.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
#include "TransactionParser.hpp"
#include "utils/DateUtils.hpp"

#define PROXY_PARSE(method, ...)                                    \
 auto& currentObject = _hierarchy.top();                            \
 if (currentObject == "block") {                                    \
    return _blockParser.method(__VA_ARGS__);                        \
 } else if (currentObject == "inputs") {                            \
    return _inputParser.method(__VA_ARGS__);                        \
 } else if (currentObject == "outputs") {                           \
    return _outputParser.method(__VA_ARGS__);                        \
 } else                                                             \

namespace ledger {
    namespace core {

        bool TransactionParser::Key(const rapidjson::Reader::Ch *str, rapidjson::SizeType length, bool copy) {
            _lastKey = std::string(str, length);
            PROXY_PARSE(Key, str, length, copy) {
                return true;
            }
        }

        bool TransactionParser::StartObject() {
            if (_arrayDepth == 0) {
                _hierarchy.push(_lastKey);
            }

            auto& currentObject = _hierarchy.top();

            if (currentObject == "inputs") {
                BitcoinLikeBlockchainExplorerInput input;
                input.index = _transaction->inputs.size();
                _transaction->inputs.push_back(input);
                _inputParser.init(&_transaction->inputs.back());
            } else if (currentObject == "outputs") {
                BitcoinLikeBlockchainExplorerOutput output;
                _transaction->outputs.push_back(output);
                _outputParser.init(&_transaction->outputs.back());
                // Set block height
                if (_transaction->block.hasValue()) {
                    _transaction->outputs.back().blockHeight = _transaction->block.getValue().height;
                }
            } else if (currentObject == "block") {
                BitcoinLikeBlockchainExplorer::Block block;
                _transaction->block = Option<BitcoinLikeBlockchainExplorer::Block>(block);
                _blockParser.init(&_transaction->block.getValue());
            }

            return true;
        }

        bool TransactionParser::EndObject(rapidjson::SizeType memberCount) {
            auto& currentObject = _hierarchy.top();

            if (_arrayDepth == 0) {
                _hierarchy.pop();
            }
            return true;
        }

        bool TransactionParser::StartArray() {
            if (_arrayDepth == 0) {
                _hierarchy.push(_lastKey);
            }
            _arrayDepth += 1;
            return true;
        }

        bool TransactionParser::EndArray(rapidjson::SizeType elementCount) {
            _arrayDepth -= 1;
            if (_arrayDepth == 0) {
                _hierarchy.pop();
            }
            return true;
        }

        bool TransactionParser::Null() {
            PROXY_PARSE(Null) {
                return true;
            }
        }

        bool TransactionParser::Bool(bool b) {
            PROXY_PARSE(Bool, b) {
                return true;
            }
        }

        bool TransactionParser::Int(int i) {
            return Uint64(i);
        }

        bool TransactionParser::Uint(unsigned i) {
            return Uint64(i);
        }

        bool TransactionParser::Int64(int64_t i) {
            return Uint64(i);
        }

        bool TransactionParser::Uint64(uint64_t i) {
            PROXY_PARSE(Uint64, i) {
                return true;
            }
        }

        bool TransactionParser::Double(double d) {
            PROXY_PARSE(Double, d) {
                return true;
            }
        }

        bool TransactionParser::RawNumber(const rapidjson::Reader::Ch *str, rapidjson::SizeType length, bool copy) {
            PROXY_PARSE(RawNumber, str, length, copy) {
                std::string number(str, length);
                BigInt value = BigInt::fromString(number);
                if (_lastKey == "lock_time") {
                    _transaction->lockTime = value.toUint64();
                } else if (_lastKey == "fees") {
                    _transaction->fees = Option<BigInt>(value);
                } else if (_lastKey == "confirmations") {
                    _transaction->confirmations = value.toUint64();
                }
                return true;
            }
        }

        bool TransactionParser::String(const rapidjson::Reader::Ch *str, rapidjson::SizeType length, bool copy) {
            PROXY_PARSE(String, str, length, copy) {
                std::string value(str, length);
                if (_lastKey == "hash") {
                    _transaction->hash = value;
                } else if (_lastKey == "received_at") {
                    _transaction->receivedAt = DateUtils::fromJSON(value);
                }
                return true;
            }
        }

        TransactionParser::TransactionParser(std::string& lastKey) :
            _lastKey(lastKey), _blockParser(lastKey), _inputParser(lastKey), _outputParser(lastKey)
        {
            _arrayDepth = 0;
        }

        void TransactionParser::init(BitcoinLikeBlockchainExplorerTransaction *transaction) {
            _transaction = transaction;
        }

    }
}<commit_msg>COIN-1420: use of tx id field instead of hash for v3 btc explorers<commit_after>/*
 *
 * TransactionParser
 * ledger-core
 *
 * Created by Pierre Pollastri on 27/03/2017.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
#include "TransactionParser.hpp"
#include "utils/DateUtils.hpp"

#define PROXY_PARSE(method, ...)                                    \
 auto& currentObject = _hierarchy.top();                            \
 if (currentObject == "block") {                                    \
    return _blockParser.method(__VA_ARGS__);                        \
 } else if (currentObject == "inputs") {                            \
    return _inputParser.method(__VA_ARGS__);                        \
 } else if (currentObject == "outputs") {                           \
    return _outputParser.method(__VA_ARGS__);                        \
 } else                                                             \

namespace ledger {
    namespace core {

        bool TransactionParser::Key(const rapidjson::Reader::Ch *str, rapidjson::SizeType length, bool copy) {
            _lastKey = std::string(str, length);
            PROXY_PARSE(Key, str, length, copy) {
                return true;
            }
        }

        bool TransactionParser::StartObject() {
            if (_arrayDepth == 0) {
                _hierarchy.push(_lastKey);
            }

            auto& currentObject = _hierarchy.top();

            if (currentObject == "inputs") {
                BitcoinLikeBlockchainExplorerInput input;
                input.index = _transaction->inputs.size();
                _transaction->inputs.push_back(input);
                _inputParser.init(&_transaction->inputs.back());
            } else if (currentObject == "outputs") {
                BitcoinLikeBlockchainExplorerOutput output;
                _transaction->outputs.push_back(output);
                _outputParser.init(&_transaction->outputs.back());
                // Set block height
                if (_transaction->block.hasValue()) {
                    _transaction->outputs.back().blockHeight = _transaction->block.getValue().height;
                }
            } else if (currentObject == "block") {
                BitcoinLikeBlockchainExplorer::Block block;
                _transaction->block = Option<BitcoinLikeBlockchainExplorer::Block>(block);
                _blockParser.init(&_transaction->block.getValue());
            }

            return true;
        }

        bool TransactionParser::EndObject(rapidjson::SizeType memberCount) {
            auto& currentObject = _hierarchy.top();

            if (_arrayDepth == 0) {
                _hierarchy.pop();
            }
            return true;
        }

        bool TransactionParser::StartArray() {
            if (_arrayDepth == 0) {
                _hierarchy.push(_lastKey);
            }
            _arrayDepth += 1;
            return true;
        }

        bool TransactionParser::EndArray(rapidjson::SizeType elementCount) {
            _arrayDepth -= 1;
            if (_arrayDepth == 0) {
                _hierarchy.pop();
            }
            return true;
        }

        bool TransactionParser::Null() {
            PROXY_PARSE(Null) {
                return true;
            }
        }

        bool TransactionParser::Bool(bool b) {
            PROXY_PARSE(Bool, b) {
                return true;
            }
        }

        bool TransactionParser::Int(int i) {
            return Uint64(i);
        }

        bool TransactionParser::Uint(unsigned i) {
            return Uint64(i);
        }

        bool TransactionParser::Int64(int64_t i) {
            return Uint64(i);
        }

        bool TransactionParser::Uint64(uint64_t i) {
            PROXY_PARSE(Uint64, i) {
                return true;
            }
        }

        bool TransactionParser::Double(double d) {
            PROXY_PARSE(Double, d) {
                return true;
            }
        }

        bool TransactionParser::RawNumber(const rapidjson::Reader::Ch *str, rapidjson::SizeType length, bool copy) {
            PROXY_PARSE(RawNumber, str, length, copy) {
                std::string number(str, length);
                BigInt value = BigInt::fromString(number);
                if (_lastKey == "lock_time") {
                    _transaction->lockTime = value.toUint64();
                } else if (_lastKey == "fees") {
                    _transaction->fees = Option<BigInt>(value);
                } else if (_lastKey == "confirmations") {
                    _transaction->confirmations = value.toUint64();
                }
                return true;
            }
        }

        bool TransactionParser::String(const rapidjson::Reader::Ch *str, rapidjson::SizeType length, bool copy) {
            PROXY_PARSE(String, str, length, copy) {
                std::string value(str, length);
                if (_lastKey == "hash") {
                    if (_transaction->hash.empty()) {
                        _transaction->hash = value;
                    }
                }
                else if (_lastKey == "id") {
                    _transaction->hash = value;
                }
                else if (_lastKey == "received_at") {
                    _transaction->receivedAt = DateUtils::fromJSON(value);
                }
                return true;
            }
        }

        TransactionParser::TransactionParser(std::string& lastKey) :
            _lastKey(lastKey), _blockParser(lastKey), _inputParser(lastKey), _outputParser(lastKey)
        {
            _arrayDepth = 0;
        }

        void TransactionParser::init(BitcoinLikeBlockchainExplorerTransaction *transaction) {
            _transaction = transaction;
        }

    }
}<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperQtWidgetStringListParameter.h"

namespace otb
{
namespace Wrapper
{

QtWidgetStringListParameter::QtWidgetStringListParameter(StringListParameter* param, QtWidgetModel* m)
: QtWidgetParameterBase(param, m),
  m_StringListParam(param)
{
 connect( this, SIGNAL(Change()), GetModel(), SLOT(NotifyUpdate()) );
}

QtWidgetStringListParameter::~QtWidgetStringListParameter()
{
}

void QtWidgetStringListParameter::DoUpdateGUI()
{
  m_LineEditList.clear();

  m_StringLayout = new QVBoxLayout();

  for(unsigned int i=0; i<m_StringListParam->GetValue().size(); i++)
    {
    QtStringSelectionWidget * stringSelection = new QtStringSelectionWidget();
    stringSelection->setFixedHeight( 30 );
    QString val(m_StringListParam->GetNthElement(i).c_str());
    stringSelection->GetInput()->setText( m_StringListParam->GetNthElement(i).c_str() ); //val );
    m_StringLayout->addWidget( stringSelection );
    m_LineEditList.push_back(stringSelection);

    connect( stringSelection->GetInput(), SIGNAL(textChanged(const QString&)), this, SLOT(UpdateStringList()) );
    connect( stringSelection->GetInput(), SIGNAL(textChanged(const QString&)), GetModel(), SLOT(NotifyUpdate()) );
    }

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
}

void QtWidgetStringListParameter::DoCreateWidget()
{
  m_LineEditList.clear();
  const unsigned int sp(2);
  const unsigned int buttonSize(30);

  // Global layout
  QHBoxLayout * hLayout = new QHBoxLayout;
  hLayout->setSpacing(sp);
  hLayout->setContentsMargins(sp, sp, sp, sp);

  if( m_StringListParam->GetRole() != Role_Output )
    {
    // Button layout
    QVBoxLayout * buttonLayout = new QVBoxLayout;
    buttonLayout->setSpacing(sp);
    buttonLayout->setContentsMargins(sp, sp, sp, sp);

    QHBoxLayout * addSupLayout = new QHBoxLayout;
    addSupLayout->setSpacing(sp);
    addSupLayout->setContentsMargins(sp, sp, sp, sp);

    QHBoxLayout * upDownLayout = new QHBoxLayout;
    upDownLayout->setSpacing(sp);
    upDownLayout->setContentsMargins(sp, sp, sp, sp);

    // Add file button
    QPushButton * addButton = new QPushButton;
    addButton->setText("+");
    addButton->setFixedWidth(buttonSize);
    addButton->setToolTip("Add a string selector...");
    connect( addButton, SIGNAL(clicked()), this, SLOT(AddString()) );
    addSupLayout->addWidget(addButton);

    // Supress file button
    QPushButton * supButton = new QPushButton;
    supButton->setText("-");
    supButton->setFixedWidth(buttonSize);
    supButton->setToolTip("Supress the selected string...");
    connect( supButton, SIGNAL(clicked()), this, SLOT(SupressString()) );
    addSupLayout->addWidget(supButton);
    buttonLayout->addLayout(addSupLayout);

    // Up file edit
    QPushButton * upButton = new QPushButton;
    upButton->setText("Up");
    upButton->setFixedWidth(buttonSize);
    upButton->setToolTip("Up the selected string in the list...");
    connect( upButton, SIGNAL(clicked()), this, SLOT(UpString()) );
    upDownLayout->addWidget(upButton);

    // Down file edit
    QPushButton * downButton = new QPushButton;
    downButton->setText("Down");
    downButton->setFixedWidth(buttonSize);
    downButton->setToolTip("Down the selected string in the list...");
    connect( downButton, SIGNAL(clicked()), this, SLOT(DownString()) );
    upDownLayout->addWidget(downButton);
    buttonLayout->addLayout(upDownLayout);

    // Erase file edit
    QPushButton * eraseButton = new QPushButton;
    eraseButton->setText("Erase");
    eraseButton->setFixedWidth(2*(buttonSize+sp));
    eraseButton->setToolTip("Erase the selected string of the list...");
    connect( eraseButton, SIGNAL(clicked()), this, SLOT(EraseString()) );
    buttonLayout->addWidget(eraseButton);

    hLayout->addLayout(buttonLayout);
    }

  QVBoxLayout * fileLayout = new QVBoxLayout();
  fileLayout->setSpacing(0);

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(fileLayout);
  QScrollArea * scroll = new QScrollArea();
  scroll->setWidget(mainGroup);
  scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  scroll->setWidgetResizable(true);

  hLayout->addWidget(scroll);

  this->setLayout(hLayout);

  //m_StringLayout = fileLayout;
  m_HLayout = hLayout;
  m_Scroll = scroll;

}

void
QtWidgetStringListParameter::UpdateStringList()
{
  // save value
  for(unsigned int j=0; j<m_StringListParam->GetValue().size(); j++ )
    {
      m_StringListParam->SetNthElement(j, m_LineEditList[j]->GetStringName());
    }
  emit Change();
}

void
QtWidgetStringListParameter::UpString()
{
 if(m_LineEditList.size() < 2 )
    return;

  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(2);

  // Map link between old and new index in the list
  std::map<unsigned int, unsigned int> idMap;

  // Init map
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    idMap[i] = i;
    }

  // If the first item is checked, uncheck it...
  // It won't be moved
  if( m_LineEditList[0]->IsChecked() )
    {
    m_LineEditList[0]->SetChecked(false);
    }

  // If other item are checked, up the index
  // Starts at 1 because the first item mustn't move
  for(unsigned int i=1; i<m_LineEditList.size(); i++ )
    {
    if( m_LineEditList[i]->IsChecked() )
      {
      unsigned int tmp = idMap[i];
      idMap[i] = i-1;
      idMap[idMap[i-1]] = tmp;
      }
    }

  this->UpdateStringList( idMap );

  this->RecreateStringList();
}

void
QtWidgetStringListParameter::DownString()
{
  if(m_LineEditList.size() < 2 )
    return;

  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(0);

  // Map link between old and new index in the list
  std::map<unsigned int, unsigned int> idMap;

  // Init map
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    idMap[i] = i;
    }

  // If the last item is checked, uncheck it...
  // It won't be moved
  if( m_LineEditList[m_LineEditList.size()-1]->IsChecked() )
    {
    m_LineEditList[m_LineEditList.size()-1]->SetChecked(false);
    }

  // If other item are checked, up the index
  // Stops at size-1 because the last item mustn't move
  for(int i=m_LineEditList.size()-2; i>=0; i-- )
    {
    if( m_LineEditList[i]->IsChecked() )
      {
      unsigned int tmp = idMap[i];
      idMap[i] = i+1;
       idMap[idMap[i+1]] = tmp;
      }
    }

  this->UpdateStringList( idMap );

  this->RecreateStringList();
}

void
QtWidgetStringListParameter::UpdateStringList( std::map<unsigned int, unsigned int> idMap )
{
  std::vector<QtStringSelectionWidget *> tmpList;
  // Keys become values and inverse
  std::map<unsigned int, unsigned int> idMapBis;
  for(unsigned int i=0; i<idMap.size(); i++ )
    {
    idMapBis[ idMap[i] ] = i;
    }

  // Create the new item list
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    m_StringLayout->addWidget( m_LineEditList[ idMapBis[i] ] );
    tmpList.push_back(m_LineEditList[ idMapBis[i] ]);
    }

  m_LineEditList =  tmpList;
  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();

    // notify of value change
  QString key( m_StringListParam->GetKey() );
  emit ParameterChanged(key);
}

void QtWidgetStringListParameter::SetString(const QString& value)
{
  m_StringListParam->AddString(value.toAscii().constData());
  m_StringListParam->SetUserValue(true);
  QString key( m_StringListParam->GetKey() );
  emit ParameterChanged(key);
}

void
QtWidgetStringListParameter::AddString()
{
  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(0);

  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    m_StringLayout->addWidget( m_LineEditList[i] );
    }

  QtStringSelectionWidget * stringInput = new  QtStringSelectionWidget();
  stringInput->setFixedHeight( 30 );
  m_StringLayout->addWidget( stringInput );
  m_LineEditList.push_back(stringInput);
  m_StringListParam->AddNullElement();
  connect( stringInput->GetInput(), SIGNAL(textChanged(const QString&)), this, SLOT(UpdateStringList()));
  connect( stringInput->GetInput(), SIGNAL(textChanged(const QString&)), GetModel(), SLOT(NotifyUpdate()) );

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
}

void
QtWidgetStringListParameter::SupressString()
{
  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(0);
  std::vector<QtStringSelectionWidget *> tmpList;
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    if( !m_LineEditList[i]->IsChecked() )
      {
      m_StringLayout->addWidget( m_LineEditList[i] );
      tmpList.push_back(m_LineEditList[i]);
      }
    }

  m_LineEditList =  tmpList;

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
  this->RecreateStringList();
}

void
QtWidgetStringListParameter::EraseString()
{
  m_LineEditList.clear();

  m_StringLayout = new QVBoxLayout();

  QtStringSelectionWidget * stringSelection = new QtStringSelectionWidget();
  stringSelection->setFixedHeight( 30 );
  m_StringLayout->addWidget( stringSelection );
  m_LineEditList.push_back(stringSelection);
  m_StringListParam->AddNullElement();
  connect( stringSelection->GetInput(), SIGNAL(textChanged(const QString&)), this, SLOT(UpdateStringList()) );

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
  this->RecreateStringList();
}

void QtWidgetStringListParameter::RecreateStringList()
{
  // save value
  m_StringListParam->ClearValue();

  if( m_LineEditList.size() != 0)
    {
    for(unsigned int j=0; j<m_LineEditList.size(); j++ )
      {
      m_StringListParam->AddString(m_LineEditList[j]->GetStringName());
      }

    emit Change();
    // notify of value change
    QString key( m_StringListParam->GetKey() );
    emit ParameterChanged(key);
    }
}

}
}
<commit_msg>ENH: adapted QtWidgetStringListParameter to StringSelectionWidget revamp<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperQtWidgetStringListParameter.h"

namespace otb
{
namespace Wrapper
{

QtWidgetStringListParameter::QtWidgetStringListParameter(StringListParameter* param, QtWidgetModel* m)
: QtWidgetParameterBase(param, m),
  m_StringListParam(param)
{
  /*
 connect( this,
          SIGNAL(Change()),
          GetModel(),
          SLOT(NotifyUpdate()) );
          */
}

QtWidgetStringListParameter::~QtWidgetStringListParameter()
{
}

void QtWidgetStringListParameter::DoUpdateGUI()
{
  m_LineEditList.clear();

  m_StringLayout = new QVBoxLayout();

  for(unsigned int i=0; i<m_StringListParam->GetValue().size(); i++)
    {
    QtStringSelectionWidget * stringSelection = new QtStringSelectionWidget();
    stringSelection->setFixedHeight( 30 );
    stringSelection->SetText( m_StringListParam->GetNthElement(i).c_str() );
    m_StringLayout->addWidget( stringSelection );
    m_LineEditList.push_back(stringSelection);

    connect( stringSelection,
             SIGNAL( InternalQLineEditEditionFinished() ),
             this,
             SLOT( UpdateStringList() )
             );

   connect( stringSelection,
             SIGNAL(InternalQLineEditEditionFinished()),
             GetModel(),
             SLOT(NotifyUpdate())
             );
   std::cout << "NotifyUpdate" << std::endl;
    }

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
}

void QtWidgetStringListParameter::DoCreateWidget()
{
  m_LineEditList.clear();
  const unsigned int sp(2);
  const unsigned int buttonSize(30);

  // Global layout
  QHBoxLayout * hLayout = new QHBoxLayout;
  hLayout->setSpacing(sp);
  hLayout->setContentsMargins(sp, sp, sp, sp);

  if( m_StringListParam->GetRole() != Role_Output )
    {
    // Button layout
    QVBoxLayout * buttonLayout = new QVBoxLayout;
    buttonLayout->setSpacing(sp);
    buttonLayout->setContentsMargins(sp, sp, sp, sp);

    QHBoxLayout * addSupLayout = new QHBoxLayout;
    addSupLayout->setSpacing(sp);
    addSupLayout->setContentsMargins(sp, sp, sp, sp);

    QHBoxLayout * upDownLayout = new QHBoxLayout;
    upDownLayout->setSpacing(sp);
    upDownLayout->setContentsMargins(sp, sp, sp, sp);

    // Add file button
    QPushButton * addButton = new QPushButton;
    addButton->setText("+");
    addButton->setFixedWidth(buttonSize);
    addButton->setToolTip("Add a string selector...");
    connect( addButton, SIGNAL(clicked()), this, SLOT(AddString()) );
    addSupLayout->addWidget(addButton);

    // Supress file button
    QPushButton * supButton = new QPushButton;
    supButton->setText("-");
    supButton->setFixedWidth(buttonSize);
    supButton->setToolTip("Supress the selected string...");
    connect( supButton, SIGNAL(clicked()), this, SLOT(SupressString()) );
    addSupLayout->addWidget(supButton);
    buttonLayout->addLayout(addSupLayout);

    // Up file edit
    QPushButton * upButton = new QPushButton;
    upButton->setText("Up");
    upButton->setFixedWidth(buttonSize);
    upButton->setToolTip("Up the selected string in the list...");
    connect( upButton, SIGNAL(clicked()), this, SLOT(UpString()) );
    upDownLayout->addWidget(upButton);

    // Down file edit
    QPushButton * downButton = new QPushButton;
    downButton->setText("Down");
    downButton->setFixedWidth(buttonSize);
    downButton->setToolTip("Down the selected string in the list...");
    connect( downButton, SIGNAL(clicked()), this, SLOT(DownString()) );
    upDownLayout->addWidget(downButton);
    buttonLayout->addLayout(upDownLayout);

    // Erase file edit
    QPushButton * eraseButton = new QPushButton;
    eraseButton->setText("Erase");
    eraseButton->setFixedWidth(2*(buttonSize+sp));
    eraseButton->setToolTip("Erase the selected string of the list...");
    connect( eraseButton, SIGNAL(clicked()), this, SLOT(EraseString()) );
    buttonLayout->addWidget(eraseButton);

    hLayout->addLayout(buttonLayout);
    }

  QVBoxLayout * fileLayout = new QVBoxLayout();
  fileLayout->setSpacing(0);

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(fileLayout);
  QScrollArea * scroll = new QScrollArea();
  scroll->setWidget(mainGroup);
  scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  scroll->setWidgetResizable(true);

  hLayout->addWidget(scroll);

  this->setLayout(hLayout);

  //m_StringLayout = fileLayout;
  m_HLayout = hLayout;
  m_Scroll = scroll;

}

void
QtWidgetStringListParameter::UpdateStringList()
{
  // save value
  for(unsigned int j=0; j<m_StringListParam->GetValue().size(); j++ )
    {
     m_StringListParam->SetNthElement(j, m_LineEditList[j]->ToStdString());
    }

  // notify model text changed
  emit Change();
}

void
QtWidgetStringListParameter::UpString()
{
 if(m_LineEditList.size() < 2 )
    return;

  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(2);

  // Map link between old and new index in the list
  std::map<unsigned int, unsigned int> idMap;

  // Init map
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    idMap[i] = i;
    }

  // If the first item is checked, uncheck it...
  // It won't be moved
  if( m_LineEditList[0]->IsChecked() )
    {
    m_LineEditList[0]->SetChecked(false);
    }

  // If other item are checked, up the index
  // Starts at 1 because the first item mustn't move
  for(unsigned int i=1; i<m_LineEditList.size(); i++ )
    {
    if( m_LineEditList[i]->IsChecked() )
      {
      unsigned int tmp = idMap[i];
      idMap[i] = i-1;
      idMap[idMap[i-1]] = tmp;
      }
    }

  this->UpdateStringList( idMap );

  this->RecreateStringList();
}

void
QtWidgetStringListParameter::DownString()
{
  if(m_LineEditList.size() < 2 )
    return;

  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(0);

  // Map link between old and new index in the list
  std::map<unsigned int, unsigned int> idMap;

  // Init map
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    idMap[i] = i;
    }

  // If the last item is checked, uncheck it...
  // It won't be moved
  if( m_LineEditList[m_LineEditList.size()-1]->IsChecked() )
    {
    m_LineEditList[m_LineEditList.size()-1]->SetChecked(false);
    }

  // If other item are checked, up the index
  // Stops at size-1 because the last item mustn't move
  for(int i=m_LineEditList.size()-2; i>=0; i-- )
    {
    if( m_LineEditList[i]->IsChecked() )
      {
      unsigned int tmp = idMap[i];
      idMap[i] = i+1;
       idMap[idMap[i+1]] = tmp;
      }
    }

  this->UpdateStringList( idMap );

  this->RecreateStringList();
}

void
QtWidgetStringListParameter::UpdateStringList( std::map<unsigned int, unsigned int> idMap )
{
  std::vector<QtStringSelectionWidget *> tmpList;
  // Keys become values and inverse
  std::map<unsigned int, unsigned int> idMapBis;
  for(unsigned int i=0; i<idMap.size(); i++ )
    {
    idMapBis[ idMap[i] ] = i;
    }

  // Create the new item list
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    m_StringLayout->addWidget( m_LineEditList[ idMapBis[i] ] );
    tmpList.push_back(m_LineEditList[ idMapBis[i] ]);
    }

  m_LineEditList =  tmpList;
  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();

  // notify of value change
  QString key( m_StringListParam->GetKey() );
  emit ParameterChanged(key);
}

void QtWidgetStringListParameter::SetString(const QString& value)
{
  m_StringListParam->AddString(value.toAscii().constData());
  m_StringListParam->SetUserValue(true);
  QString key( m_StringListParam->GetKey() );
  emit ParameterChanged(key);
}

void
QtWidgetStringListParameter::AddString()
{
  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(0);

  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    m_StringLayout->addWidget( m_LineEditList[i] );
    }

  QtStringSelectionWidget * stringInput = new  QtStringSelectionWidget();
  stringInput->setFixedHeight( 30 );
  m_StringLayout->addWidget( stringInput );
  m_LineEditList.push_back(stringInput);
  m_StringListParam->AddNullElement();
  connect( stringInput,
           SIGNAL(InternalQLineEditEditionFinished()),
           this,
           SLOT(UpdateStringList()));

  connect( stringInput,
           SIGNAL(InternalQLineEditEditionFinished()),
           GetModel(),
           SLOT(NotifyUpdate()) );

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
}

void
QtWidgetStringListParameter::SupressString()
{
  m_StringLayout = new QVBoxLayout();
  m_StringLayout->setSpacing(0);
  std::vector<QtStringSelectionWidget *> tmpList;
  for(unsigned int i=0; i<m_LineEditList.size(); i++ )
    {
    if( !m_LineEditList[i]->IsChecked() )
      {
      m_StringLayout->addWidget( m_LineEditList[i] );
      tmpList.push_back(m_LineEditList[i]);
      }
    }

  m_LineEditList =  tmpList;

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
  this->RecreateStringList();
}

void
QtWidgetStringListParameter::EraseString()
{
  m_LineEditList.clear();

  m_StringLayout = new QVBoxLayout();

  QtStringSelectionWidget * stringSelection = new QtStringSelectionWidget();
  stringSelection->setFixedHeight( 30 );
  m_StringLayout->addWidget( stringSelection );
  m_LineEditList.push_back(stringSelection);
  m_StringListParam->AddNullElement();
  connect( stringSelection,
           SIGNAL(InternalQLineEditEditionFinished()),
           this,
           SLOT(UpdateStringList()) );

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(m_StringLayout);
  m_Scroll->setWidget(mainGroup);

  this->update();
  this->RecreateStringList();
}

void QtWidgetStringListParameter::RecreateStringList()
{
  // save value
  m_StringListParam->ClearValue();

  if( m_LineEditList.size() != 0)
    {
    for(unsigned int j=0; j<m_LineEditList.size(); j++ )
      {
      m_StringListParam->AddString(m_LineEditList[j]->ToStdString());
      }

    emit Change();
    // notify of value change
    QString key( m_StringListParam->GetKey() );
    emit ParameterChanged(key);
    }
}

}
}
<|endoftext|>


<commit_before>// ヘッダのインクルード
#include <iostream> // C++標準入出力
#include <cstring> // C文字列処理

// クラスclass_profileの定義
class class_profile{ // 簡易名簿

  // privateメンバ
  private: // このクラス内部からのみアクセス可.

    // privateメンバ変数
    char name[32]; // 名前
    int age; // 年齢
    char address[128]; // 住所

  // publicメンバ
  public: // このクラスの外部からもアクセス可.

    // コンストラクタ
    class_profile(); // 各メンバの初期化処理を行うコンストラクタclass_profile

    // publicメンバ関数
    void input(); // 名前(name), 年齢(age), 住所(address)の入力.
    void output(); // 名前(name), 年齢(age), 住所(address)の入力.

};

// class_profileのメンバの定義
// コンストラクタclass_profile()
class_profile::class_profile(){ // name, age, addressの初期化処理

  // name, age, addressの初期化
  strcpy(name, "(none)"); // 名前が無いことを意味する"(none)"に初期化しておく.
  age = -1; // 年齢が無いことを意味する-1に初期化しておく.
  strcpy(address, "(none)"); // 住所が無いことを意味する"(none")に初期化しておく.

}

// メンバ関数input()
void class_profile::input(){ // name, age, addressの入力.

  // name, age, addressの入力.
  std::cout << "name: "; // nameの入力フォーム
  std::cin >> name; // 入力された文字列をnameに格納.
  std::cout << "age: "; // ageの入力フォーム
  std::cin >> age; // 入力された整数をageに格納.
  std::cout << "address: "; // addressの入力フォーム
  std::cin >> address; // 入力された文字列をaddressに格納.

}

// メンバ関数output()
void class_profile::output(){ // name, age, addressの出力.

  // name, age, addressの出力.
  std::cout << "name: " << name << std::endl; // nameの内容を出力.
  std::cout << "age: " << age << std::endl; // ageの内容を出力.
  std::cout << "address: " << address << std::endl; // addressの内容を出力.

}

// main関数の定義
int main(){

  // オブジェクトの宣言
  class_profile prof; // class_profileのオブジェクトprofを宣言, この場合はここでコンストラクタが呼ばれる.

  // profの中身がコンストラクタによって初期化されているか確認.
  prof.output(); // output()メンバ関数でデータを出力する.

  // 1行空ける.
  std::cout << std::endl; // std::endlで1行空ける.

  // profに名簿データを入力.
  prof.input(); // input()メンバ関数でデータを入力する.

  // 1行空ける.
  std::cout << std::endl; // std::endlで1行空ける.

  // profの名簿データを出力.
  prof.output(); // output()メンバ関数でデータを出力する.

  // プログラムの終了
  return 0;

}
<commit_msg>fixed comment<commit_after>// ヘッダのインクルード
#include <iostream> // C++標準入出力
#include <cstring> // C文字列処理

// クラスclass_profileの定義
class class_profile{ // 簡易名簿

  // privateメンバ
  private: // このクラス内部からのみアクセス可.

    // privateメンバ変数
    char name[32]; // 名前
    int age; // 年齢
    char address[128]; // 住所

  // publicメンバ
  public: // このクラスの外部からもアクセス可.

    // コンストラクタ
    class_profile(); // 各メンバの初期化処理を行うコンストラクタclass_profile

    // publicメンバ関数
    void input(); // 名前(name), 年齢(age), 住所(address)の入力.
    void output(); // 名前(name), 年齢(age), 住所(address)の出力.

};

// class_profileのメンバの定義
// コンストラクタclass_profile()
class_profile::class_profile(){ // name, age, addressの初期化処理

  // name, age, addressの初期化
  strcpy(name, "(none)"); // 名前が無いことを意味する"(none)"に初期化しておく.
  age = -1; // 年齢が無いことを意味する-1に初期化しておく.
  strcpy(address, "(none)"); // 住所が無いことを意味する"(none")に初期化しておく.

}

// メンバ関数input()
void class_profile::input(){ // name, age, addressの入力.

  // name, age, addressの入力.
  std::cout << "name: "; // nameの入力フォーム
  std::cin >> name; // 入力された文字列をnameに格納.
  std::cout << "age: "; // ageの入力フォーム
  std::cin >> age; // 入力された整数をageに格納.
  std::cout << "address: "; // addressの入力フォーム
  std::cin >> address; // 入力された文字列をaddressに格納.

}

// メンバ関数output()
void class_profile::output(){ // name, age, addressの出力.

  // name, age, addressの出力.
  std::cout << "name: " << name << std::endl; // nameの内容を出力.
  std::cout << "age: " << age << std::endl; // ageの内容を出力.
  std::cout << "address: " << address << std::endl; // addressの内容を出力.

}

// main関数の定義
int main(){

  // オブジェクトの宣言
  class_profile prof; // class_profileのオブジェクトprofを宣言, この場合はここでコンストラクタが呼ばれる.

  // profの中身がコンストラクタによって初期化されているか確認.
  prof.output(); // output()メンバ関数でデータを出力する.

  // 1行空ける.
  std::cout << std::endl; // std::endlで1行空ける.

  // profに名簿データを入力.
  prof.input(); // input()メンバ関数でデータを入力する.

  // 1行空ける.
  std::cout << std::endl; // std::endlで1行空ける.

  // profの名簿データを出力.
  prof.output(); // output()メンバ関数でデータを出力する.

  // プログラムの終了
  return 0;

}
<|endoftext|>


<commit_before>/*
  Copyright 2014 Sarah Wong

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "configuration.h"
#include "ui_configuration.h"

#include <QDebug>
#include <QResource>

#include <portaudiocpp/System.hxx>
#include <portaudiocpp/SystemHostApiIterator.hxx>
#include <portaudiocpp/SystemDeviceIterator.hxx>

#include "tinyscheme/scheme-private.h"
#include "tinyscheme/scheme.h"

namespace {

template <class IndexMapType, class ItemIter, class ItemType, class Callable1,
          class Callable2>
static void insertWithDefault(QComboBox *comboBox, IndexMapType &map,
                              ItemIter begin, ItemIter end,
                              ItemType& defaultItem,
			      Callable1 stringGenerator,
                              Callable2 mapItemGenerator) {
  int itemPosition = 0;

  comboBox->clear();
  map.clear();

  {
    map[itemPosition] = mapItemGenerator(defaultItem);

    comboBox->insertItem(itemPosition++,
                         QLatin1String("Default: ") + stringGenerator(defaultItem));
  }

  comboBox->insertSeparator(itemPosition++);

  while (begin != end) {
    ItemType& item = *begin;

    map[itemPosition] = mapItemGenerator(item);

    comboBox->insertItem(itemPosition++, stringGenerator(item));

    ++begin;
  }

}

struct GetDataFromResource {

  GetDataFromResource(const char *file)
  {
    QResource resource(file);
    Q_ASSERT(resource.isValid());
    if (resource.isCompressed())
      m_byteArray = qUncompress(resource.data(), resource.size());
    else
      m_byteArray = QByteArray(reinterpret_cast<const char*>(resource.data()), resource.size());
  }

  const QByteArray& byteArray() const { return m_byteArray; }

  QByteArray m_byteArray;
};

} // namespace anonymous

Configuration::Configuration(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Configuration)
{
  ui->setupUi(this);

  GetDataFromResource defaultConfigScm(":/tinyscheme/default-config.scm");
  ui->txtConfig->setPlainText(
      QString::fromUtf8(defaultConfigScm.byteArray().data(),
                        defaultConfigScm.byteArray().size()));

  portaudio::System& sys = portaudio::System::instance();

  insertWithDefault(
      ui->cmbAudioHost, m_indexToHostApiTypeId, sys.hostApisBegin(),
      sys.hostApisEnd(), sys.defaultHostApi(),
      [](portaudio::HostApi &hostApi) { return hostApi.name(); },
      [](portaudio::HostApi &hostApi) { return hostApi.typeId(); });
}

PaDeviceIndex Configuration::getDeviceIndex() const
{
  auto index = ui->cmbInputDevice->currentIndex();
  Q_ASSERT(index != -1);
  return m_indexToDeviceIndex[index];
}

void Configuration::on_cmbAudioHost_currentIndexChanged(int index)
{
  if (index == -1)
    return;

  portaudio::HostApi &hostApi = portaudio::System::instance().hostApiByTypeId(
      m_indexToHostApiTypeId[index]);

  insertWithDefault(
      ui->cmbInputDevice, m_indexToDeviceIndex,
      hostApi.devicesBegin(), hostApi.devicesEnd(), hostApi.defaultInputDevice(),
      [](portaudio::Device &device) { return device.name(); },
      [](portaudio::Device &device) { return device.index(); });

}

namespace {

struct Ptr {
  scheme *sc_;
  pointer p_;

  Ptr(scheme *sc, pointer p) : sc_(sc), p_(p) {}

#define P(v) Ptr(sc_, v)

  Ptr nil           ()          { return P(sc_->NIL); }

  bool is_nil       ()          { return p_ == sc_->NIL; }

  bool is_string    ()          { return sc_->vptr->is_string(p_); }
  char *string_value()          { return sc_->vptr->string_value(p_); }
  bool is_number    ()          { return sc_->vptr->is_number(p_); }
  num nvalue        ()          { return sc_->vptr->nvalue(p_); }
  long ivalue       ()          { return sc_->vptr->ivalue(p_); }
  double rvalue     ()          { return sc_->vptr->rvalue(p_); }
  bool is_integer   ()          { return sc_->vptr->is_integer(p_); }
  bool is_real      ()          { return sc_->vptr->is_real(p_); }
  bool is_character ()          { return sc_->vptr->is_character(p_); }
  long charvalue    ()          { return sc_->vptr->charvalue(p_); }
  bool is_list      ()          { return sc_->vptr->is_list(sc_, p_); }
  bool is_vector    ()          { return sc_->vptr->is_vector(p_); }
  int list_length   ()          { return sc_->vptr->list_length(sc_, p_); }
  long vector_length()          { return sc_->vptr->vector_length(p_); }
  Ptr vector_elem   (int ielem) { return P(sc_->vptr->vector_elem(p_, ielem)); }
  bool is_pair      ()          { return sc_->vptr->is_pair(p_); }
  Ptr car           ()          { return P(sc_->vptr->pair_car(p_)); }
  Ptr cdr           ()          { return P(sc_->vptr->pair_cdr(p_)); }

  bool is_symbol    ()          { return sc_->vptr->is_symbol(p_); }
  char *symname     ()          { return sc_->vptr->symname(p_); }

#undef P

};

struct Config {
  Config(const char *configScript) : sc_(scheme_init_new())
  {
    Q_ASSERT(sc_ != nullptr);

    scheme_set_output_port_file(sc_, stdout);

    loadResource(":/tinyscheme/init.scm");
    loadResource(":/tinyscheme/config-helper.scm");

    read_eval("(begin (display 1337) (newline))");

    scheme_load_string(sc_, configScript);
    if (sc_->retcode != 0) qDebug() << "Scheme failed" << __LINE__;

    pointer ret = read_eval("(cdr (assv ':sample-rate (cdr (assv 'audio-config config))))");
    qDebug() << sc_->vptr->ivalue(ret);
  }

  void loadResource(const char *resource)
  {
    GetDataFromResource gdfr(resource);
    scheme_load_string(sc_, gdfr.byteArray().data());
  }

  pointer read_eval(const char* script)
  {
    // tinyscheme bug: When executing
    //
    //   (read (open-input-string script))
    //
    // sc_->inport needs to be set, or there will be an error when
    // read is restoring the previous inport value when returning.
    scheme_set_input_port_file(sc_, stdin); // TODO stdin?

    pointer fun = scheme_eval(sc_, mk_symbol(sc_, "read-eval"));
    pointer arg = mk_string(sc_, script);
    return scheme_call(sc_, fun, _cons(sc_, arg, sc_->NIL, 0));
  }

  scheme *sc_;
};

} // namespace anonymous

void Configuration::on_buttonBox_accepted()
{
  QString configText = ui->txtConfig->toPlainText();
  QByteArray configTextBa = configText.toUtf8();
  Config cfg(configTextBa.constData());

  emit accept();
}

Configuration::~Configuration()
{
    delete ui;
}
<commit_msg>Config read_eval to use new Ptr class!<commit_after>/*
  Copyright 2014 Sarah Wong

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "configuration.h"
#include "ui_configuration.h"

#include <QDebug>
#include <QResource>

#include <portaudiocpp/System.hxx>
#include <portaudiocpp/SystemHostApiIterator.hxx>
#include <portaudiocpp/SystemDeviceIterator.hxx>

#include "tinyscheme/scheme-private.h"
#include "tinyscheme/scheme.h"

namespace {

template <class IndexMapType, class ItemIter, class ItemType, class Callable1,
          class Callable2>
static void insertWithDefault(QComboBox *comboBox, IndexMapType &map,
                              ItemIter begin, ItemIter end,
                              ItemType& defaultItem,
			      Callable1 stringGenerator,
                              Callable2 mapItemGenerator) {
  int itemPosition = 0;

  comboBox->clear();
  map.clear();

  {
    map[itemPosition] = mapItemGenerator(defaultItem);

    comboBox->insertItem(itemPosition++,
                         QLatin1String("Default: ") + stringGenerator(defaultItem));
  }

  comboBox->insertSeparator(itemPosition++);

  while (begin != end) {
    ItemType& item = *begin;

    map[itemPosition] = mapItemGenerator(item);

    comboBox->insertItem(itemPosition++, stringGenerator(item));

    ++begin;
  }

}

struct GetDataFromResource {

  GetDataFromResource(const char *file)
  {
    QResource resource(file);
    Q_ASSERT(resource.isValid());
    if (resource.isCompressed())
      m_byteArray = qUncompress(resource.data(), resource.size());
    else
      m_byteArray = QByteArray(reinterpret_cast<const char*>(resource.data()), resource.size());
  }

  const QByteArray& byteArray() const { return m_byteArray; }

  QByteArray m_byteArray;
};

} // namespace anonymous

Configuration::Configuration(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Configuration)
{
  ui->setupUi(this);

  GetDataFromResource defaultConfigScm(":/tinyscheme/default-config.scm");
  ui->txtConfig->setPlainText(
      QString::fromUtf8(defaultConfigScm.byteArray().data(),
                        defaultConfigScm.byteArray().size()));

  portaudio::System& sys = portaudio::System::instance();

  insertWithDefault(
      ui->cmbAudioHost, m_indexToHostApiTypeId, sys.hostApisBegin(),
      sys.hostApisEnd(), sys.defaultHostApi(),
      [](portaudio::HostApi &hostApi) { return hostApi.name(); },
      [](portaudio::HostApi &hostApi) { return hostApi.typeId(); });
}

PaDeviceIndex Configuration::getDeviceIndex() const
{
  auto index = ui->cmbInputDevice->currentIndex();
  Q_ASSERT(index != -1);
  return m_indexToDeviceIndex[index];
}

void Configuration::on_cmbAudioHost_currentIndexChanged(int index)
{
  if (index == -1)
    return;

  portaudio::HostApi &hostApi = portaudio::System::instance().hostApiByTypeId(
      m_indexToHostApiTypeId[index]);

  insertWithDefault(
      ui->cmbInputDevice, m_indexToDeviceIndex,
      hostApi.devicesBegin(), hostApi.devicesEnd(), hostApi.defaultInputDevice(),
      [](portaudio::Device &device) { return device.name(); },
      [](portaudio::Device &device) { return device.index(); });

}

namespace {

struct Ptr {
  scheme *sc_;
  pointer p_;

  Ptr(scheme *sc, pointer p) : sc_(sc), p_(p) {}

#define P(v) Ptr(sc_, v)

  Ptr nil           ()          { return P(sc_->NIL); }

  bool is_nil       ()          { return p_ == sc_->NIL; }

  bool is_string    ()          { return sc_->vptr->is_string(p_); }
  char *string_value()          { return sc_->vptr->string_value(p_); }
  bool is_number    ()          { return sc_->vptr->is_number(p_); }
  num nvalue        ()          { return sc_->vptr->nvalue(p_); }
  long ivalue       ()          { return sc_->vptr->ivalue(p_); }
  double rvalue     ()          { return sc_->vptr->rvalue(p_); }
  bool is_integer   ()          { return sc_->vptr->is_integer(p_); }
  bool is_real      ()          { return sc_->vptr->is_real(p_); }
  bool is_character ()          { return sc_->vptr->is_character(p_); }
  long charvalue    ()          { return sc_->vptr->charvalue(p_); }
  bool is_list      ()          { return sc_->vptr->is_list(sc_, p_); }
  bool is_vector    ()          { return sc_->vptr->is_vector(p_); }
  int list_length   ()          { return sc_->vptr->list_length(sc_, p_); }
  long vector_length()          { return sc_->vptr->vector_length(p_); }
  Ptr vector_elem   (int ielem) { return P(sc_->vptr->vector_elem(p_, ielem)); }
  bool is_pair      ()          { return sc_->vptr->is_pair(p_); }
  Ptr car           ()          { return P(sc_->vptr->pair_car(p_)); }
  Ptr cdr           ()          { return P(sc_->vptr->pair_cdr(p_)); }

  bool is_symbol    ()          { return sc_->vptr->is_symbol(p_); }
  char *symname     ()          { return sc_->vptr->symname(p_); }

#undef P

};

struct Config {
  Config(const char *configScript) : sc_(scheme_init_new())
  {
    Q_ASSERT(sc_ != nullptr);

    scheme_set_output_port_file(sc_, stdout);

    loadResource(":/tinyscheme/init.scm");
    loadResource(":/tinyscheme/config-helper.scm");

    read_eval("(begin (display 1337) (newline))");

    scheme_load_string(sc_, configScript);
    if (sc_->retcode != 0) qDebug() << "Scheme failed" << __LINE__;

    Ptr ret = read_eval("(cdr (assv ':sample-rate (cdr (assv 'audio-config config))))");
    qDebug() << ret.ivalue();
  }

  void loadResource(const char *resource)
  {
    GetDataFromResource gdfr(resource);
    scheme_load_string(sc_, gdfr.byteArray().data());
  }

  Ptr read_eval(const char* script)
  {
    // tinyscheme bug: When executing
    //
    //   (read (open-input-string script))
    //
    // sc_->inport needs to be set, or there will be an error when
    // read is restoring the previous inport value when returning.
    scheme_set_input_port_file(sc_, stdin); // TODO stdin?

    pointer fun = scheme_eval(sc_, mk_symbol(sc_, "read-eval"));
    pointer arg = mk_string(sc_, script);
    return Ptr(sc_, scheme_call(sc_, fun, _cons(sc_, arg, sc_->NIL, 0)));
  }

  scheme *sc_;
};

} // namespace anonymous

void Configuration::on_buttonBox_accepted()
{
  QString configText = ui->txtConfig->toPlainText();
  QByteArray configTextBa = configText.toUtf8();
  Config cfg(configTextBa.constData());

  emit accept();
}

Configuration::~Configuration()
{
    delete ui;
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2009 Soeren Sonnenburg
 * Written (W) 2012 Heiko Strathmann
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/common.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/features/Features.h>
#include <shogun/features/DummyFeatures.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

void
CCustomKernel::init()
{
	m_row_subset=NULL;
	m_col_subset=NULL;

	SG_ADD((CSGObject**)&m_row_subset, "row_subset", "Subset of rows",
			MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_col_subset, "col_subset", "Subset of columns",
			MS_NOT_AVAILABLE);

	m_parameters->add(&kmatrix, "kmatrix", "Kernel matrix.");
	m_parameters->add(&upper_diagonal, "upper_diagonal");
}

CCustomKernel::CCustomKernel()
: CKernel(10), kmatrix(), upper_diagonal(false)
{
	init();
}

CCustomKernel::CCustomKernel(CKernel* k)
: CKernel(10)
{
	init();

	set_full_kernel_matrix_from_full(k->get_kernel_matrix());
//	SG_PRINT("created custom kernel with kernel matrix:\n");
//	print_kernel_matrix();
}

CCustomKernel::CCustomKernel(SGMatrix<float64_t> km)
: CKernel(10), upper_diagonal(false)
{
	init();
	set_full_kernel_matrix_from_full(km);
}

CCustomKernel::~CCustomKernel()
{
	SG_UNREF(m_row_subset);
	SG_UNREF(m_col_subset);
	cleanup();
}

bool CCustomKernel::dummy_init(int32_t rows, int32_t cols)
{
	return init(new CDummyFeatures(rows), new CDummyFeatures(cols));
}

bool CCustomKernel::init(CFeatures* l, CFeatures* r)
{
	remove_row_subset();
	remove_col_subset();

	CKernel::init(l, r);

	SG_DEBUG( "num_vec_lhs: %d vs num_rows %d\n", l->get_num_vectors(), kmatrix.num_rows);
	SG_DEBUG( "num_vec_rhs: %d vs num_cols %d\n", r->get_num_vectors(), kmatrix.num_cols);
	ASSERT(l->get_num_vectors()==kmatrix.num_rows);
	ASSERT(r->get_num_vectors()==kmatrix.num_cols);
	return init_normalizer();
}

void CCustomKernel::cleanup_custom()
{
	SG_DEBUG("cleanup up custom kernel\n");
	remove_row_subset();
	remove_col_subset();
	SG_FREE(kmatrix.matrix);
	kmatrix.matrix=NULL;
	upper_diagonal=false;
	kmatrix.num_cols=0;
	kmatrix.num_rows=0;
}

void CCustomKernel::cleanup()
{
	remove_row_subset();
	remove_col_subset();
	cleanup_custom();
	CKernel::cleanup();
}

void CCustomKernel::set_row_subset(CSubset* subset)
{
	SG_UNREF(m_row_subset);
	m_row_subset=subset;
	SG_REF(subset);

	/* update num_lhs */
	num_lhs=subset ? subset->get_size() : 0;
}
void CCustomKernel::set_col_subset(CSubset* subset)
{
	SG_UNREF(m_col_subset);
	m_col_subset=subset;
	SG_REF(subset);

	/* update num_rhs */
	num_rhs=subset ? subset->get_size() : 0;
}

void CCustomKernel::remove_row_subset()
{
	set_row_subset(NULL);

	/* restore num_lhs */
	num_lhs=kmatrix.num_rows;
}

void CCustomKernel::remove_col_subset()
{
	set_col_subset(NULL);

	/* restore num_rhs */
	num_rhs=kmatrix.num_cols;
}

void CCustomKernel::print_kernel_matrix(const char* prefix) const
{
	index_t num_rows=m_row_subset ? m_row_subset->get_size() : kmatrix.num_rows;
	index_t num_cols=m_col_subset ? m_col_subset->get_size() : kmatrix.num_cols;
	for (index_t i=0; i<num_rows; ++i)
	{
		for (index_t j=0; j<num_cols; ++j)
		{
			index_t real_i=row_subset_idx_conversion(i);
			index_t real_j=col_subset_idx_conversion(j);
			SG_PRINT("%s%4.2f", kmatrix.matrix[kmatrix.num_rows*real_j+real_i],
					prefix);
			if (j<num_cols-1)
				SG_PRINT(", \t");
		}
		SG_PRINT("\n");
	}
}
<commit_msg>free kernel matrix only if there is one specified<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2009 Soeren Sonnenburg
 * Written (W) 2012 Heiko Strathmann
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/common.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/features/Features.h>
#include <shogun/features/DummyFeatures.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

void
CCustomKernel::init()
{
	m_row_subset=NULL;
	m_col_subset=NULL;

	SG_ADD((CSGObject**)&m_row_subset, "row_subset", "Subset of rows",
			MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_col_subset, "col_subset", "Subset of columns",
			MS_NOT_AVAILABLE);

	m_parameters->add(&kmatrix, "kmatrix", "Kernel matrix.");
	m_parameters->add(&upper_diagonal, "upper_diagonal");
}

CCustomKernel::CCustomKernel()
: CKernel(10), kmatrix(), upper_diagonal(false)
{
	init();
}

CCustomKernel::CCustomKernel(CKernel* k)
: CKernel(10)
{
	init();

	set_full_kernel_matrix_from_full(k->get_kernel_matrix());
//	SG_PRINT("created custom kernel with kernel matrix:\n");
//	print_kernel_matrix();
}

CCustomKernel::CCustomKernel(SGMatrix<float64_t> km)
: CKernel(10), upper_diagonal(false)
{
	init();
	set_full_kernel_matrix_from_full(km);
}

CCustomKernel::~CCustomKernel()
{
	SG_UNREF(m_row_subset);
	SG_UNREF(m_col_subset);
	cleanup();
}

bool CCustomKernel::dummy_init(int32_t rows, int32_t cols)
{
	return init(new CDummyFeatures(rows), new CDummyFeatures(cols));
}

bool CCustomKernel::init(CFeatures* l, CFeatures* r)
{
	remove_row_subset();
	remove_col_subset();

	CKernel::init(l, r);

	SG_DEBUG( "num_vec_lhs: %d vs num_rows %d\n", l->get_num_vectors(), kmatrix.num_rows);
	SG_DEBUG( "num_vec_rhs: %d vs num_cols %d\n", r->get_num_vectors(), kmatrix.num_cols);
	ASSERT(l->get_num_vectors()==kmatrix.num_rows);
	ASSERT(r->get_num_vectors()==kmatrix.num_cols);
	return init_normalizer();
}

void CCustomKernel::cleanup_custom()
{
	SG_DEBUG("cleanup up custom kernel\n");
	remove_row_subset();
	remove_col_subset();
	if (kmatrix.matrix)
		SG_FREE(kmatrix.matrix);
	kmatrix.matrix=NULL;
	upper_diagonal=false;
	kmatrix.num_cols=0;
	kmatrix.num_rows=0;
}

void CCustomKernel::cleanup()
{
	remove_row_subset();
	remove_col_subset();
	cleanup_custom();
	CKernel::cleanup();
}

void CCustomKernel::set_row_subset(CSubset* subset)
{
	SG_UNREF(m_row_subset);
	m_row_subset=subset;
	SG_REF(subset);

	/* update num_lhs */
	num_lhs=subset ? subset->get_size() : 0;
}
void CCustomKernel::set_col_subset(CSubset* subset)
{
	SG_UNREF(m_col_subset);
	m_col_subset=subset;
	SG_REF(subset);

	/* update num_rhs */
	num_rhs=subset ? subset->get_size() : 0;
}

void CCustomKernel::remove_row_subset()
{
	set_row_subset(NULL);

	/* restore num_lhs */
	num_lhs=kmatrix.num_rows;
}

void CCustomKernel::remove_col_subset()
{
	set_col_subset(NULL);

	/* restore num_rhs */
	num_rhs=kmatrix.num_cols;
}

void CCustomKernel::print_kernel_matrix(const char* prefix) const
{
	index_t num_rows=m_row_subset ? m_row_subset->get_size() : kmatrix.num_rows;
	index_t num_cols=m_col_subset ? m_col_subset->get_size() : kmatrix.num_cols;
	for (index_t i=0; i<num_rows; ++i)
	{
		for (index_t j=0; j<num_cols; ++j)
		{
			index_t real_i=row_subset_idx_conversion(i);
			index_t real_j=col_subset_idx_conversion(j);
			SG_PRINT("%s%4.2f", kmatrix.matrix[kmatrix.num_rows*real_j+real_i],
					prefix);
			if (j<num_cols-1)
				SG_PRINT(", \t");
		}
		SG_PRINT("\n");
	}
}
<|endoftext|>


<commit_before>/*
 *   Copyright (c) 2008-2018 SLIBIO <https://github.com/SLIBIO>
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 */

#include "slib/graphics/drawable.h"

#include "slib/graphics/image.h"
#include "slib/graphics/platform.h"

#include "slib/core/file.h"
#include "slib/core/asset.h"

namespace slib
{

	Ref<Bitmap> Drawable::toBitmap()
	{
		if (isBitmap()) {
			return (Bitmap*)this;
		}
		sl_int32 width = (sl_int32)(getDrawableWidth());
		sl_int32 height = (sl_int32)(getDrawableHeight());
		if (width > 0 && height > 0) {
			Ref<Bitmap> bitmap = Bitmap::create(width, height);
			if (bitmap.isNotNull()) {
				Ref<Canvas> canvas = bitmap->getCanvas();
				if (canvas.isNotNull()) {
					canvas->draw(Rectangle(0, 0, (sl_real)width, (sl_real)height), this);
				}
				return bitmap;
			}
		}
		return sl_null;
	}

	Ref<Image> Drawable::toImage()
	{
		if (isImage()) {
			return (Image*)this;
		}
		Ref<Bitmap> bitmap = toBitmap();
		if (bitmap.isNotNull()) {
			return Image::create(bitmap);
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::create(const Ref<Image>& image)
	{
		if (image.isNotNull()) {
			ImageDesc desc;
			image->getDesc(desc);
			return PlatformDrawable::create(desc);
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::loadFromMemory(const Memory& mem)
	{
		if (mem.isNotNull()) {
			return PlatformDrawable::loadFromMemory(mem.getData(), mem.getSize());
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::loadFromFile(const String& filePath)
	{
		Memory mem = File::readAllBytes(filePath);
		if (mem.isNotNull()) {
			return PlatformDrawable::loadFromMemory(mem);
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::loadFromAsset(const String& path)
	{
		Memory mem = Assets::readAllBytes(path);
		if (mem.isNotNull()) {
			return PlatformDrawable::loadFromMemory(mem);
		}
#if defined(SLIB_PLATFORM_IS_APPLE)
		CGImageRef image = GraphicsPlatform::loadCGImageFromApp(path);
		if (image) {
			Ref<Drawable> ret = GraphicsPlatform::createImageDrawable(image);
			CGImageRelease(image);
			return ret;
		}
#endif
		return sl_null;
	}

}
<commit_msg>graphics: minor fix on conversion from drawable to bitmap<commit_after>/*
 *   Copyright (c) 2008-2018 SLIBIO <https://github.com/SLIBIO>
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 */

#include "slib/graphics/drawable.h"

#include "slib/graphics/image.h"
#include "slib/graphics/platform.h"

#include "slib/core/file.h"
#include "slib/core/asset.h"

namespace slib
{

	Ref<Bitmap> Drawable::toBitmap()
	{
		if (isBitmap()) {
			return (Bitmap*)this;
		}
		sl_int32 width = (sl_int32)(getDrawableWidth());
		sl_int32 height = (sl_int32)(getDrawableHeight());
		if (width > 0 && height > 0) {
			Ref<Bitmap> bitmap = Bitmap::create(width, height);
			if (bitmap.isNotNull()) {
				bitmap->resetPixels(Color::None);
				Ref<Canvas> canvas = bitmap->getCanvas();
				if (canvas.isNotNull()) {
					canvas->draw(Rectangle(0, 0, (sl_real)width, (sl_real)height), this);
				}
				return bitmap;
			}
		}
		return sl_null;
	}

	Ref<Image> Drawable::toImage()
	{
		if (isImage()) {
			return (Image*)this;
		}
		Ref<Bitmap> bitmap = toBitmap();
		if (bitmap.isNotNull()) {
			return Image::create(bitmap);
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::create(const Ref<Image>& image)
	{
		if (image.isNotNull()) {
			ImageDesc desc;
			image->getDesc(desc);
			return PlatformDrawable::create(desc);
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::loadFromMemory(const Memory& mem)
	{
		if (mem.isNotNull()) {
			return PlatformDrawable::loadFromMemory(mem.getData(), mem.getSize());
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::loadFromFile(const String& filePath)
	{
		Memory mem = File::readAllBytes(filePath);
		if (mem.isNotNull()) {
			return PlatformDrawable::loadFromMemory(mem);
		}
		return sl_null;
	}

	Ref<Drawable> PlatformDrawable::loadFromAsset(const String& path)
	{
		Memory mem = Assets::readAllBytes(path);
		if (mem.isNotNull()) {
			return PlatformDrawable::loadFromMemory(mem);
		}
#if defined(SLIB_PLATFORM_IS_APPLE)
		CGImageRef image = GraphicsPlatform::loadCGImageFromApp(path);
		if (image) {
			Ref<Drawable> ret = GraphicsPlatform::createImageDrawable(image);
			CGImageRelease(image);
			return ret;
		}
#endif
		return sl_null;
	}

}
<|endoftext|>