<commit_before>/*-
 * Copyright (c) 2009, Ascent Group.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of the Ascent Group nor the names of its contributors
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <common/Database.h>
#include <psql/Schema.h>
#include <psql/Table.h>
#include <psql/Tools.h>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>

#include <QtDebug>

namespace DbObjects
{

namespace Psql
{

/*!
 * Constructor
 *
 * \param[in] ipName - Name of the given table
 * \param[in] ipSchema - Handle to schema containing this view
 */
Table::Table(QString ipName, const DbSchemaPtr &ipSchema)
    :DbTable(ipName, ipSchema)
{
    // load column definitions
//    loadData();
}

/*!
 * Destructor
 */
Table::~Table()
{

}

/*!
 * Load column definitions data
 *
 * \return true If data has been successfully loaded
 * \return false Otherwise
 */
bool
Table::loadData()
{
//    int *p = 0;
//    *p = 7;
    if (mIsLoaded) {
        return true;
    }

    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);
    QString qstr;

    /*! \todo Before creating a query we need to find out postgres version;
     *        Bersion check can help support different Postgres versions,
     *        especcialy when the system catalogs change in newer versions
     */
    Tools::Version version = Tools::version();

    /*! \todo version check */
    /*! \todo do version specific actions */

    // create query
    qstr = QString("SELECT "
                        "pga.attname, "
                        "pg_catalog.format_type(pga.atttypid, pga.atttypmod), "
                        "pga.attnotnull "
                    "FROM "
                        "pg_catalog.pg_attribute pga "
                    "WHERE "
                        "pga.attnum > 0 "
                        "AND NOT pga.attisdropped "
                        "AND pga.attrelid = ("
                        "SELECT pgc.oid FROM pg_catalog.pg_class pgc "
                        "LEFT JOIN pg_catalog.pg_namespace pgn ON pgn.oid = pgc.relnamespace "
                        "WHERE pgc.relname = '%1' and pgn.nspname = '%2'); ")
//          "AND pg_catalog.pg_table_is_visible(pgc.oid));")
        .arg(mName)
        .arg(mSchema->name());

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::loadData> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();
        return false;
    }

    // if query result is empty
    if (!query.first()) {
        return false;
    }

    // for each retrieved row
    do {
        /* temporary debug output */
#if DEBUG_TRACE
        qDebug() << query.value(0).toString();
        qDebug() << query.value(1).toString();
        qDebug() << query.value(2).toString();
#endif

        // create column definition
        struct ColumnDefinition cDef;

        // populate column definition
        cDef.name = query.value(0).toString();
        cDef.type = query.value(1).toString();
        cDef.isNullable = !query.value(2).toBool();
        cDef.isPrimaryKey = checkPrimaryKey(cDef.name);
        cDef.isForeignKey = checkForeignKey(cDef.name, cDef.foreignSchemaName, cDef.foreignTableName, cDef.foreignFieldNames);
        cDef.isUnique = checkUnique(cDef.name);

        /* temporary debug output */
#if DEBUG_TRACE
        qDebug() << "NAME: " << cDef.name;
        qDebug() << "isPrimaryKey: " << cDef.isPrimaryKey;
        qDebug() << "isForeignKey: " << cDef.isForeignKey;
        qDebug() << "isUnique: " << cDef.isUnique;
        qDebug() << "FKEY_SCHEMA: " << cDef.foreignSchemaName;
        qDebug() << "FKEY_TABLE: " << cDef.foreignTableName;
#endif

        // add column definition
        mColumnDefs.push_back(cDef);
    } while (query.next());

    // clear result from previous query
    query.clear();

    // try to find parents if they exist
    qstr = QString("SELECT "
//                       "childns.nspname AS child_schema, "
//                       "child.relname AS child_name, "
                       "parentns.nspname AS parent_schema, "
                       "parent.relname AS parent_name "
                   "FROM "
                       "pg_catalog.pg_inherits i, "
                       "pg_catalog.pg_class child, "
                       "pg_catalog.pg_class parent, "
                       "pg_catalog.pg_namespace childns, "
                       "pg_catalog.pg_namespace parentns "
                   "WHERE "
                       "i.inhrelid = child.oid AND "
                       "i.inhparent = parent.oid AND "
                       "childns.oid = child.relnamespace AND "
                       "parentns.oid = parent.relnamespace AND "
                       "childns.nspname = '%1' AND "
                       "child.relname = '%2' "
                   "ORDER BY i.inhseqno;")
        .arg(mSchema.name())
        .arg(mName);

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::loadData> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();
        return false;
    }

    // if query result is empty
    if (query.first()) {

        do {
            DbSchemaPtr schema = Common::Database::instance()->findSchema(query.value(0).toString());
            // devtime assert
            Q_ASSERT(0 != schema.get());

            DbTablePtr table = schema->findTable(query.value(1).toString());
            // devtime assert
            Q_ASSERT(0 != table.get());

            // store handle to parent table
            mParentTables.push_back(table);

            qDebug() << "Psql::Table::loadData> Parent table: " << table.name();
        } while (query.next());
    }

    return DbTable::loadData();
}

/*!
 * Checks if column is a primary key for the given table
 *
 * \param[in] ipColumnName - Name of the column
 *
 * \return true If the column is primary key
 * \return false Otherwise
 */
bool
Table::checkPrimaryKey(const QString &ipColumnName) const
{
    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);

    // create query
    QString qstr = QString("SELECT "
                        "pgc.relname, "
                        "pga.attname "
                    "FROM "
                        "pg_class pgc, "
                        "pg_attribute pga, "
                        "pg_index pgi, "
                        "pg_namespace pgn "
                    "WHERE "
                        "pgc.oid = pga.attrelid "
                        "AND pgc.oid = pgi.indrelid "
                        "AND pgi.indkey[0] = pga.attnum "
                        "AND pgi.indisprimary = 't' "
                        "AND pgn.oid = pgc.relnamespace "
                        "AND pgn.nspname = '%1' "
                        "AND pgc.relname = '%2' "
                        "AND pga.attname = '%3';")
                .arg(mSchema->name())
                .arg(mName)
                .arg(ipColumnName);

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::checkPrimaryKey> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();

        return false;
    }

    // primary constraint definition found
    return query.first();
}

/*!
 * Checks if ipColumnName is a foreign key for ipTableName
 *
 * \param[in] ipColumnName - Name of the column
 * \param[out] opForeignSchemaName - Name of the schema that contains the reference table
 * \param[out] opForeignTableName - Name of the table references by this column
 * \param[out] opForeignFieldsNames - Names of fields references by this column
 *
 * \return true If the column is a foreign key
 * \return false Otherwise
 */
bool
Table::checkForeignKey(const QString &ipColumnName,
               QString &opForeignSchemaName,
               QString &opForeignTableName,
               QStringList &opForeignFieldsNames) const
{
    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);

    // create query
    QString qstr = QString("SELECT "
                                "p1.relname, "
                                "a1.attname, "
                                "pgn2.nspname AS foreign_schema, "
                                "p2.relname AS reltable, "
                                "a2.attname AS ref_field "
                            "FROM "
                                "pg_constraint c, "
                                "pg_class p1, "
                                "pg_class p2, "
                                "pg_attribute a1, "
                                "pg_attribute a2, "
                                "pg_namespace pgn1, "
                                "pg_namespace pgn2 "
                            "WHERE "
                                "c.contype = 'f' "
                                "AND c.confrelid > 0 "
                                "AND c.conrelid = p1.oid "
                                "AND c.confrelid = p2.oid "
                                "AND c.conrelid = a1.attrelid "
                                "AND a1.attnum = ANY (c.conkey) "
                                "AND c.confrelid = a2.attrelid "
                                "AND a2.attnum = ANY (c.confkey) "
                                "AND p2.relnamespace = pgn2.oid "
                                "AND pgn1.oid = p1.relnamespace "
                                "AND pgn1.nspname = '%1' "
                                "AND p1.relname = '%2' "
                                "AND a1.attname = '%3';")
        .arg(mSchema->name())
        .arg(mName)
        .arg(ipColumnName);

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::checkForeignKey> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();

        return false;
    }

    bool flag = false;
    qint32 colId;

    // if query result is empty
    if (!query.first()) {
    return flag;
    }

    // if we are here then the result is not empty
    flag = true;

    // this needs to be don only once for all fields
    colId = query.record().indexOf("reltable");
    opForeignTableName = query.value(colId).toString();

    colId = query.record().indexOf("foreign_schema");
    opForeignSchemaName = query.value(colId).toString();

    // fields themselves
    do {
        colId = query.record().indexOf("ref_field");
        opForeignFieldsNames.push_back(query.value(colId).toString());
    } while (query.next());

    // foreign key constraint definition found
    return flag;
}

/*!
 * Checks if ipColumnName is unique for ipTableName
 *
 * \param[in] ipColumnName - Name of the column
 *
 * \return true If the column has unique constraint
 * \return false Otherwise
 */
bool
Table::checkUnique(const QString &ipColumnName) const
{
    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);

    // create query
    QString qstr = QString("SELECT "
                                "pgc.relname, "
                                "pga.attname, "
                "pgc.relnamespace "
                            "FROM "
                                "pg_constraint constr, "
                                "pg_class pgc, "
                                "pg_attribute pga, "
                                "pg_namespace pgn "
                            "WHERE "
                                "pga.attnum = ANY (constr.conkey) "
                                "AND constr.contype = 'u' "
                                "AND constr.conrelid = pgc.oid "
                                "AND constr.conrelid = pga.attrelid "
                                "AND pgn.oid = pgc.relnamespace "
                                "AND pgn.nspname = '%1' "
                                "AND pgc.relname = '%2' "
                                "AND pga.attname = '%3';")
        .arg(mSchema->name())
        .arg(mName)
        .arg(ipColumnName);

#if DEBUG_QUERY
    qDebug() << "Psql::Table::checkUnique> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();

        return false;
    }

    // unique constraint definition found
    return query.first();
}

} // namespace Psql

} // namespace DbObjects

<commit_msg>* Fixed the query for determining whether the column is primary key or not. The old   query used to work only when the first column was PK, and didn't work for composite   primary keys.<commit_after>/*-
 * Copyright (c) 2009, Ascent Group.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of the Ascent Group nor the names of its contributors
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <common/Database.h>
#include <psql/Schema.h>
#include <psql/Table.h>
#include <psql/Tools.h>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>

#include <QtDebug>

namespace DbObjects
{

namespace Psql
{

/*!
 * Constructor
 *
 * \param[in] ipName - Name of the given table
 * \param[in] ipSchema - Handle to schema containing this view
 */
Table::Table(QString ipName, const DbSchemaPtr &ipSchema)
    :DbTable(ipName, ipSchema)
{
    // load column definitions
//    loadData();
}

/*!
 * Destructor
 */
Table::~Table()
{

}

/*!
 * Load column definitions data
 *
 * \return true If data has been successfully loaded
 * \return false Otherwise
 */
bool
Table::loadData()
{
//    int *p = 0;
//    *p = 7;
    if (mIsLoaded) {
        return true;
    }

    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);
    QString qstr;

    /*! \todo Before creating a query we need to find out postgres version;
     *        Bersion check can help support different Postgres versions,
     *        especcialy when the system catalogs change in newer versions
     */
    Tools::Version version = Tools::version();

    /*! \todo version check */
    /*! \todo do version specific actions */

    // create query
    qstr = QString("SELECT "
                        "pga.attname, "
                        "pg_catalog.format_type(pga.atttypid, pga.atttypmod), "
                        "pga.attnotnull "
                    "FROM "
                        "pg_catalog.pg_attribute pga "
                    "WHERE "
                        "pga.attnum > 0 "
                        "AND NOT pga.attisdropped "
                        "AND pga.attrelid = ("
                        "SELECT pgc.oid FROM pg_catalog.pg_class pgc "
                        "LEFT JOIN pg_catalog.pg_namespace pgn ON pgn.oid = pgc.relnamespace "
                        "WHERE pgc.relname = '%1' and pgn.nspname = '%2'); ")
//          "AND pg_catalog.pg_table_is_visible(pgc.oid));")
        .arg(mName)
        .arg(mSchema->name());

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::loadData> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();
        return false;
    }

    // if query result is empty
    if (!query.first()) {
        return false;
    }

    // for each retrieved row
    do {
        /* temporary debug output */
#if DEBUG_TRACE
        qDebug() << query.value(0).toString();
        qDebug() << query.value(1).toString();
        qDebug() << query.value(2).toString();
#endif

        // create column definition
        struct ColumnDefinition cDef;

        // populate column definition
        cDef.name = query.value(0).toString();
        cDef.type = query.value(1).toString();
        cDef.isNullable = !query.value(2).toBool();
        cDef.isPrimaryKey = checkPrimaryKey(cDef.name);
        cDef.isForeignKey = checkForeignKey(cDef.name, cDef.foreignSchemaName, cDef.foreignTableName, cDef.foreignFieldNames);
        cDef.isUnique = checkUnique(cDef.name);

        /* temporary debug output */
#if DEBUG_TRACE
        qDebug() << "NAME: " << cDef.name;
        qDebug() << "isPrimaryKey: " << cDef.isPrimaryKey;
        qDebug() << "isForeignKey: " << cDef.isForeignKey;
        qDebug() << "isUnique: " << cDef.isUnique;
        qDebug() << "FKEY_SCHEMA: " << cDef.foreignSchemaName;
        qDebug() << "FKEY_TABLE: " << cDef.foreignTableName;
#endif

        // add column definition
        mColumnDefs.push_back(cDef);
    } while (query.next());

    // clear result from previous query
    query.clear();

    // try to find parents if they exist
    qstr = QString("SELECT "
//                       "childns.nspname AS child_schema, "
//                       "child.relname AS child_name, "
                       "parentns.nspname AS parent_schema, "
                       "parent.relname AS parent_name "
                   "FROM "
                       "pg_catalog.pg_inherits i, "
                       "pg_catalog.pg_class child, "
                       "pg_catalog.pg_class parent, "
                       "pg_catalog.pg_namespace childns, "
                       "pg_catalog.pg_namespace parentns "
                   "WHERE "
                       "i.inhrelid = child.oid AND "
                       "i.inhparent = parent.oid AND "
                       "childns.oid = child.relnamespace AND "
                       "parentns.oid = parent.relnamespace AND "
                       "childns.nspname = '%1' AND "
                       "child.relname = '%2' "
                   "ORDER BY i.inhseqno;")
        .arg(mSchema.name())
        .arg(mName);

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::loadData> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();
        return false;
    }

    // if query result is empty
    if (query.first()) {

        do {
            DbSchemaPtr schema = Common::Database::instance()->findSchema(query.value(0).toString());
            // devtime assert
            Q_ASSERT(0 != schema.get());

            DbTablePtr table = schema->findTable(query.value(1).toString());
            // devtime assert
            Q_ASSERT(0 != table.get());

            // store handle to parent table
            mParentTables.push_back(table);

            qDebug() << "Psql::Table::loadData> Parent table: " << table.name();
        } while (query.next());
    }

    return DbTable::loadData();
}

/*!
 * Checks if column is a primary key for the given table
 *
 * \param[in] ipColumnName - Name of the column
 *
 * \return true If the column is primary key
 * \return false Otherwise
 */
bool
Table::checkPrimaryKey(const QString &ipColumnName) const
{
    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);

    // create query
    QString qstr = QString("SELECT "
                               "pgc.relname, "
                               "pga.attname "
                           "FROM "
                               "pg_class pgc, "
                               "pg_attribute pga, "
                               "pg_constraint constr, "
                               "pg_namespace pgn "
                           "WHERE "
                               "pgc.oid = pga.attrelid "
                               "AND constr.conrelid = pgc.oid "
                               "AND constr.contype = 'p' "
                               "AND pga.attnum = ANY (constr.conkey) "
                               "AND pgn.oid = pgc.relnamespace "
                               "AND pgn.nspname = '%1' "
                               "AND pgc.relname = '%2' "
                               "AND pga.attname = '%3';")
        .arg(mSchema->name())
        .arg(mName)
        .arg(ipColumnName);

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::checkPrimaryKey> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();

        return false;
    }

    // primary constraint definition found
    return query.first();
}

/*!
 * Checks if ipColumnName is a foreign key for ipTableName
 *
 * \param[in] ipColumnName - Name of the column
 * \param[out] opForeignSchemaName - Name of the schema that contains the reference table
 * \param[out] opForeignTableName - Name of the table references by this column
 * \param[out] opForeignFieldsNames - Names of fields references by this column
 *
 * \return true If the column is a foreign key
 * \return false Otherwise
 */
bool
Table::checkForeignKey(const QString &ipColumnName,
               QString &opForeignSchemaName,
               QString &opForeignTableName,
               QStringList &opForeignFieldsNames) const
{
    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);

    // create query
    QString qstr = QString("SELECT "
                                "p1.relname, "
                                "a1.attname, "
                                "pgn2.nspname AS foreign_schema, "
                                "p2.relname AS reltable, "
                                "a2.attname AS ref_field "
                            "FROM "
                                "pg_constraint c, "
                                "pg_class p1, "
                                "pg_class p2, "
                                "pg_attribute a1, "
                                "pg_attribute a2, "
                                "pg_namespace pgn1, "
                                "pg_namespace pgn2 "
                            "WHERE "
                                "c.contype = 'f' "
                                "AND c.confrelid > 0 "
                                "AND c.conrelid = p1.oid "
                                "AND c.confrelid = p2.oid "
                                "AND c.conrelid = a1.attrelid "
                                "AND a1.attnum = ANY (c.conkey) "
                                "AND c.confrelid = a2.attrelid "
                                "AND a2.attnum = ANY (c.confkey) "
                                "AND p2.relnamespace = pgn2.oid "
                                "AND pgn1.oid = p1.relnamespace "
                                "AND pgn1.nspname = '%1' "
                                "AND p1.relname = '%2' "
                                "AND a1.attname = '%3';")
        .arg(mSchema->name())
        .arg(mName)
        .arg(ipColumnName);

#ifdef DEBUG_QUERY
    qDebug() << "Psql::Table::checkForeignKey> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();

        return false;
    }

    bool flag = false;
    qint32 colId;

    // if query result is empty
    if (!query.first()) {
    return flag;
    }

    // if we are here then the result is not empty
    flag = true;

    // this needs to be don only once for all fields
    colId = query.record().indexOf("reltable");
    opForeignTableName = query.value(colId).toString();

    colId = query.record().indexOf("foreign_schema");
    opForeignSchemaName = query.value(colId).toString();

    // fields themselves
    do {
        colId = query.record().indexOf("ref_field");
        opForeignFieldsNames.push_back(query.value(colId).toString());
    } while (query.next());

    // foreign key constraint definition found
    return flag;
}

/*!
 * Checks if ipColumnName is unique for ipTableName
 *
 * \param[in] ipColumnName - Name of the column
 *
 * \return true If the column has unique constraint
 * \return false Otherwise
 */
bool
Table::checkUnique(const QString &ipColumnName) const
{
    QSqlDatabase db = QSqlDatabase::database("mainConnect");
    QSqlQuery query(db);

    // create query
    QString qstr = QString("SELECT "
                                "pgc.relname, "
                                "pga.attname, "
                "pgc.relnamespace "
                            "FROM "
                                "pg_constraint constr, "
                                "pg_class pgc, "
                                "pg_attribute pga, "
                                "pg_namespace pgn "
                            "WHERE "
                                "pga.attnum = ANY (constr.conkey) "
                                "AND constr.contype = 'u' "
                                "AND constr.conrelid = pgc.oid "
                                "AND constr.conrelid = pga.attrelid "
                                "AND pgn.oid = pgc.relnamespace "
                                "AND pgn.nspname = '%1' "
                                "AND pgc.relname = '%2' "
                                "AND pga.attname = '%3';")
        .arg(mSchema->name())
        .arg(mName)
        .arg(ipColumnName);

#if DEBUG_QUERY
    qDebug() << "Psql::Table::checkUnique> " << qstr;
#endif

    // if query execution failed
    if (!query.exec(qstr)) {
        qDebug() << query.lastError().text();

        return false;
    }

    // unique constraint definition found
    return query.first();
}

} // namespace Psql

} // namespace DbObjects

<|endoftext|>


<commit_before>/*
 * StringUtil.cpp
 *
 * Copyright 2002, Log4cpp Project. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */
#include "StringUtil.hh"
#include <iterator>
#include <stdio.h>

#if defined(_MSC_VER)
    #define VSNPRINTF _vsnprintf
#else
#ifdef LOG4CPP_HAVE_SNPRINTF
    #define VSNPRINTF vsnprintf
#else
/* use alternative snprintf() from http://www.ijs.si/software/snprintf/ */

#define HAVE_SNPRINTF
#define PREFER_PORTABLE_SNPRINTF

#include <stdlib.h>
#include <stdarg.h>

extern "C" {
#include "snprintf.c"
}

#define VSNPRINTF portable_vsnprintf

#endif // LOG4CPP_HAVE_SNPRINTF
#endif // _MSC_VER

namespace log4cpp {

    std::string StringUtil::vform(const char* format, va_list args) {
	size_t size = 1024;
	char* buffer = new char[size];

	while (1) {
            va_list args_copy;
            va_copy(args_copy, args);

            int n = VSNPRINTF(buffer, size, format, args_copy);

            va_end(args_copy);

	    // If that worked, return a string.
	    if ((n > -1) && (static_cast<size_t>(n) < size)) {
		std::string s(buffer);
		delete [] buffer;
		return s;
	    }

	    // Else try again with more space.
            size = (n > -1) ?
                n + 1 :   // ISO/IEC 9899:1999
                size * 2; // twice the old size

	    delete [] buffer;
	    buffer = new char[size];
	}
    }

    std::string StringUtil::trim(const std::string& s) {
        static const char* whiteSpace = " \t\r\n";

        // test for null string
        if(s.empty())
            return s;

        // find first non-space character
        std::string::size_type b = s.find_first_not_of(whiteSpace);
        if(b == std::string::npos) // No non-spaces
            return "";

        // find last non-space character
        std::string::size_type e = s.find_last_not_of(whiteSpace);

        // return the remaining characters
        return std::string(s, b, e - b + 1);
    }

    unsigned int StringUtil::split(std::vector<std::string>& v,
				   const std::string& s,
				   char delimiter, unsigned int maxSegments) {
        v.clear();
        std::back_insert_iterator<std::vector<std::string> > it(v);
        return split(it, s, delimiter, maxSegments);
    }

}
<commit_msg>MSVC and Borland doesn't have va_copy - fallback to simple assigning<commit_after>/*
 * StringUtil.cpp
 *
 * Copyright 2002, Log4cpp Project. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */
#include "StringUtil.hh"
#include <iterator>
#include <stdio.h>

#if defined(_MSC_VER)
    #define VSNPRINTF _vsnprintf
#else
#ifdef LOG4CPP_HAVE_SNPRINTF
    #define VSNPRINTF vsnprintf
#else
/* use alternative snprintf() from http://www.ijs.si/software/snprintf/ */

#define HAVE_SNPRINTF
#define PREFER_PORTABLE_SNPRINTF

#include <stdlib.h>
#include <stdarg.h>

extern "C" {
#include "snprintf.c"
}

#define VSNPRINTF portable_vsnprintf

#endif // LOG4CPP_HAVE_SNPRINTF
#endif // _MSC_VER

namespace log4cpp {

    std::string StringUtil::vform(const char* format, va_list args) {
        size_t size = 1024;
        char* buffer = new char[size];

        while (1) {
            va_list args_copy;

#if defined(_MSC_VER) || defined(__BORLANDC__)
            args_copy = args;
#else
            va_copy(args_copy, args);
#endif

            int n = VSNPRINTF(buffer, size, format, args_copy);

            va_end(args_copy);

            // If that worked, return a string.
            if ((n > -1) && (static_cast<size_t>(n) < size)) {
                std::string s(buffer);
                delete [] buffer;
                return s;
            }

            // Else try again with more space.
            size = (n > -1) ?
                n + 1 :   // ISO/IEC 9899:1999
                size * 2; // twice the old size

            delete [] buffer;
            buffer = new char[size];
        }
    }

    std::string StringUtil::trim(const std::string& s) {
        static const char* whiteSpace = " \t\r\n";

        // test for null string
        if(s.empty())
            return s;

        // find first non-space character
        std::string::size_type b = s.find_first_not_of(whiteSpace);
        if(b == std::string::npos) // No non-spaces
            return "";

        // find last non-space character
        std::string::size_type e = s.find_last_not_of(whiteSpace);

        // return the remaining characters
        return std::string(s, b, e - b + 1);
    }

    unsigned int StringUtil::split(std::vector<std::string>& v,
                                   const std::string& s,
                                   char delimiter, unsigned int maxSegments) {
        v.clear();
        std::back_insert_iterator<std::vector<std::string> > it(v);
        return split(it, s, delimiter, maxSegments);
    }

}
<|endoftext|>


<commit_before>/*
 * StringUtil.cpp
 *
 * Copyright 2002, Log4cpp Project. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */
#include "StringUtil.hh"
#include <iterator>
#include <stdio.h>

#if defined(_MSC_VER)
    #define VSNPRINTF _vsnprintf
#else
#ifdef LOG4CPP_HAVE_SNPRINTF
    #define VSNPRINTF vsnprintf
#else
/* use alternative snprintf() from http://www.ijs.si/software/snprintf/ */

#define HAVE_SNPRINTF
#define PREFER_PORTABLE_SNPRINTF

#include <stdlib.h>
#include <stdarg.h>

extern "C" {
#include "snprintf.c"
}

#define VSNPRINTF portable_vsnprintf

#endif // LOG4CPP_HAVE_SNPRINTF
#endif // _MSC_VER

namespace log4cpp {

    std::string StringUtil::vform(const char* format, va_list args) {
	size_t size = 1024;
	char* buffer = new char[size];

	while (1) {
	    int n = VSNPRINTF(buffer, size, format, args);

	    // If that worked, return a string.
	    if ((n > -1) && (static_cast<size_t>(n) < size)) {
		std::string s(buffer);
		delete [] buffer;
		return s;
	    }

	    // Else try again with more space.
            size = (n > -1) ?
                n + 1 :   // ISO/IEC 9899:1999
                size * 2; // twice the old size

	    delete [] buffer;
	    buffer = new char[size];
	}
    }

    std::string StringUtil::trim(const std::string& s) {
        // test for null string
        if(s.empty())
            return s;

        // find first non-space character
        std::string::size_type b = s.find_first_not_of(" \t");
        if(b == std::string::npos) // No non-spaces
            return "";

        // find last non-space character
        std::string::size_type e = s.find_last_not_of(" \t");

        // return the remaining characters
        return std::string(s, b, e - b + 1);
    }

    unsigned int StringUtil::split(std::vector<std::string>& v,
				   const std::string& s,
				   char delimiter, unsigned int maxSegments) {
        v.clear();
        std::back_insert_iterator<std::vector<std::string> > it(v);
        return split(it, s, delimiter, maxSegments);
    }

}
<commit_msg>added \r and \n to whitespace characters.<commit_after>/*
 * StringUtil.cpp
 *
 * Copyright 2002, Log4cpp Project. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */
#include "StringUtil.hh"
#include <iterator>
#include <stdio.h>

#if defined(_MSC_VER)
    #define VSNPRINTF _vsnprintf
#else
#ifdef LOG4CPP_HAVE_SNPRINTF
    #define VSNPRINTF vsnprintf
#else
/* use alternative snprintf() from http://www.ijs.si/software/snprintf/ */

#define HAVE_SNPRINTF
#define PREFER_PORTABLE_SNPRINTF

#include <stdlib.h>
#include <stdarg.h>

extern "C" {
#include "snprintf.c"
}

#define VSNPRINTF portable_vsnprintf

#endif // LOG4CPP_HAVE_SNPRINTF
#endif // _MSC_VER

namespace log4cpp {

    std::string StringUtil::vform(const char* format, va_list args) {
	size_t size = 1024;
	char* buffer = new char[size];

	while (1) {
	    int n = VSNPRINTF(buffer, size, format, args);

	    // If that worked, return a string.
	    if ((n > -1) && (static_cast<size_t>(n) < size)) {
		std::string s(buffer);
		delete [] buffer;
		return s;
	    }

	    // Else try again with more space.
            size = (n > -1) ?
                n + 1 :   // ISO/IEC 9899:1999
                size * 2; // twice the old size

	    delete [] buffer;
	    buffer = new char[size];
	}
    }

    std::string StringUtil::trim(const std::string& s) {
        static const char* whiteSpace = " \t\r\n";

        // test for null string
        if(s.empty())
            return s;

        // find first non-space character
        std::string::size_type b = s.find_first_not_of(whiteSpace);
        if(b == std::string::npos) // No non-spaces
            return "";

        // find last non-space character
        std::string::size_type e = s.find_last_not_of(whiteSpace);

        // return the remaining characters
        return std::string(s, b, e - b + 1);
    }

    unsigned int StringUtil::split(std::vector<std::string>& v,
				   const std::string& s,
				   char delimiter, unsigned int maxSegments) {
        v.clear();
        std::back_insert_iterator<std::vector<std::string> > it(v);
        return split(it, s, delimiter, maxSegments);
    }

}
<|endoftext|>


<commit_before>//#include <itkImage.h>
#include <itkPhysicalImage.h>
#include <itkFileIOMetaImage.h>
#include <itkWriteMetaImage.h>
#include <itkFileIOToImageFilter.h>

using namespace itk;
using namespace std;

int main ()
{
//  typedef Image<unsigned short, 3> myImageType;
  typedef PhysicalImage<unsigned short, 3> myImageType;
  typedef WriteMetaImage<myImageType> myWriterType;
  typedef FileIOToImageFilter<myImageType> myFilterType;

  ObjectFactoryBase::RegisterFactory(new FileIOMetaImageFactory);
  myWriterType::Pointer writer = myWriterType::New();
  myFilterType::Pointer filter = myFilterType::New();

	filter->SetFileToLoad("D:/research/Angio002Series005.mhd");
  filter->Update();
  writer->SetFileName("D:/research/TestOutput.mhd");
  writer->SetInput(filter->GetOutput());
  writer->Write();

  return 0;
}
<commit_msg>This is the test file that accompanies MetaImageIO. Performs a simple loopback test by reading in a sample MetaImage and then writing it back out.<commit_after>/**
 * This is a demonstration of how to write and read MetaImage files to and from disk
 * using the ImageIO framework. It's a simple loopback test: read a sample file from disk
 * and then write it back out. Currently, the user will have to open both files and do a
 * visual comparison to ensure they're identical, but in the future even this can be
 * automated via a diff command.
 */

#include <itkPhysicalImage.h>
#include <itkFileIOMetaImage.h>
#include <itkWriteMetaImage.h>
#include <itkFileIOToImageFilter.h>

using namespace itk;
using namespace std;

int main ()
{
  /*
   * This defines our image. Note that while we use a PhysicalImage for this test
   * (because MetaImage defines a mapping between image-space to physical-space),
   * you can just as easily substitute an Image in its place.
   */
  typedef PhysicalImage<unsigned short, 3> myImageType;
  /*
   * This defines our MetaImage writer
   */
  typedef WriteMetaImage<myImageType> myWriterType;
  /*
   * This defines our MetaImage "reader-cum-pixel-translator" (filter).
   * It not only reads the file from disk, but also typecasts the pixels from
   * the native pixel type on disk (say, signed char) into the pixel type of our
   * Image (in this case, unsigned short)
   * Note that by subclassing from FileIOToImageFilter, one can perform more sophisticated
   * pixel conversions, e.g. rgb to grayscale conversion.
   */
  typedef FileIOToImageFilter<myImageType> myFilterType;

  /*
   * This call manually registers the MetaImage reader with the master object factory.
   * This establishes a mapping between the class that can handle MetaImage files
   * (FileIOMetaImage), and the file extensions associated with that filetype
   * (.mha, .mhd, .mda)
   * Note that once we compile the MetaImageIO library as a DLL, this call is no longer
   * necessary. It is only needed when using static libraries, as we are currently doing.
   */
  ObjectFactoryBase::RegisterFactory(new FileIOMetaImageFactory);
  myWriterType::Pointer writer = myWriterType::New();
  myFilterType::Pointer filter = myFilterType::New();

  /*
   * Now tell the filter which file to load
   */
	filter->SetFileToLoad("TestInput.mhd");
  /*
   * This call forces the filter to update itself, which in this case causes
   * the file to be loaded from disk.
   * Note that this call will not be needed once filter pipelining and interconnection is
   * implemented, as the call to writer->SetInput() would automatically cause a cascading
   * series of checks up the pipeline to see what filters/datasources/etc. have been
   * modified and need to be re-evaluated.
   */
  filter->Update();
  /*
   * Tell the writer which file to write to
   */
  writer->SetFileName("TestOutput.mhd");
  /*
   * Hook the output of the reader to the input of the writer
   */
  writer->SetInput(filter->GetOutput());
  /*
   * And finally write the image back out to disk
   */
  writer->Write();

  return 0;
}
<|endoftext|>


<commit_before>#include "serversocket.hpp"

#include <QTcpServer>
#include <QTcpSocket>
#include <QDataStream>

namespace mirrors {

ServerSocket::ServerSocket(QObject *parent)
    : QObject(parent), sock(new QTcpServer(this)), pingTimer(new QTimer(this))
{
    connect(sock, SIGNAL(newConnection()),
            this, SLOT(newConnection()));
    connect(sock, SIGNAL(acceptError(QAbstractSocket::SocketError)),
            this, SLOT(handleError()));

    pingTimer->setInterval(1000);
    connect(pingTimer, SIGNAL(timeout()),
            this,      SLOT(broadcastPing()));
}

bool ServerSocket::isStarted() const {
    return sock->isListening();
}

void ServerSocket::setPortNumber(quint16 portNum) {
    Q_ASSERT(!sock->isListening());
    port = portNum;
}

void ServerSocket::start() {
    sock->listen(QHostAddress::Any, 23369);
    emit started();
}

void ServerSocket::stop() {
    sock->close();
    emit stopped();
}

void ServerSocket::disconnect(QTcpSocket *client) {
    if (clients.contains(client)) {
        clients.removeOne(client);
        if (client->isOpen()) {
            client->close();
        }
        emit clientDisconnected(client);
        client->deleteLater();
    }
}

void ServerSocket::broadcastBytes(QByteArray bytes) {
    foreach (QTcpSocket *client, clients) {
        client->write(bytes);
    }
}

void ServerSocket::broadcastPositionUpdate(int id, cv::Point2f position, float rotation) {
    QByteArray bytes;
    QDataStream stream(&bytes, QIODevice::WriteOnly);
    stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    stream << (qint8) 0
           << position.x
           << position.y
           << rotation
           << (qint32) id;

    broadcastBytes(bytes);
}

void ServerSocket::broadcastDelete(int id) {
    QByteArray bytes;
    QDataStream stream(&bytes, QIODevice::WriteOnly);
    stream << (qint8) 1
           << (qint32) id;
    broadcastBytes(bytes);
}

void ServerSocket::broadcastPing() {
    broadcastBytes(QByteArray(1, 2));
}

void ServerSocket::processUpdates() {
    foreach (QTcpSocket *sock, clients) {
        processUpdates(sock);
    }
}

void ServerSocket::processUpdates(QTcpSocket *client) {
    Q_ASSERT(client != nullptr);
    while (client->bytesAvailable() >= 9) {
        QByteArray data = client->read(9);
        if (data.size() == 9 && data[0] == (char)3) {
            // This message is a rotation update
            broadcastBytes(data);
        }
    }
}

void ServerSocket::newConnection() {
    QTcpSocket *client = sock->nextPendingConnection();
    clients.append(client);
    emit clientConnected(client);
}

void ServerSocket::handleError() {
    emit errorOccurred(sock->errorString());
}

void ServerSocket::handleClientError() {
    QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
    if (client != nullptr) {
        disconnect(client);
    }
}

}
<commit_msg>Fixed server not sending ping messages.<commit_after>#include "serversocket.hpp"

#include <QTcpServer>
#include <QTcpSocket>
#include <QDataStream>

namespace mirrors {

ServerSocket::ServerSocket(QObject *parent)
    : QObject(parent), sock(new QTcpServer(this)), pingTimer(new QTimer(this))
{
    connect(sock, SIGNAL(newConnection()),
            this, SLOT(newConnection()));
    connect(sock, SIGNAL(acceptError(QAbstractSocket::SocketError)),
            this, SLOT(handleError()));

    pingTimer->setInterval(1000);
    connect(pingTimer, SIGNAL(timeout()),
            this,      SLOT(broadcastPing()));
}

bool ServerSocket::isStarted() const {
    return sock->isListening();
}

void ServerSocket::setPortNumber(quint16 portNum) {
    Q_ASSERT(!sock->isListening());
    port = portNum;
}

void ServerSocket::start() {
    sock->listen(QHostAddress::Any, 23369);
    pingTimer->start();
    emit started();
}

void ServerSocket::stop() {
    sock->close();
    pingTimer->stop();
    emit stopped();
}

void ServerSocket::disconnect(QTcpSocket *client) {
    if (clients.contains(client)) {
        clients.removeOne(client);
        if (client->isOpen()) {
            client->close();
        }
        emit clientDisconnected(client);
        client->deleteLater();
    }
}

void ServerSocket::broadcastBytes(QByteArray bytes) {
    foreach (QTcpSocket *client, clients) {
        client->write(bytes);
    }
}

void ServerSocket::broadcastPositionUpdate(int id, cv::Point2f position, float rotation) {
    QByteArray bytes;
    QDataStream stream(&bytes, QIODevice::WriteOnly);
    stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    stream << (qint8) 0
           << position.x
           << position.y
           << rotation
           << (qint32) id;

    broadcastBytes(bytes);
}

void ServerSocket::broadcastDelete(int id) {
    QByteArray bytes;
    QDataStream stream(&bytes, QIODevice::WriteOnly);
    stream << (qint8) 1
           << (qint32) id;
    broadcastBytes(bytes);
}

void ServerSocket::broadcastPing() {
    broadcastBytes(QByteArray(1, 2));
}

void ServerSocket::processUpdates() {
    foreach (QTcpSocket *sock, clients) {
        processUpdates(sock);
    }
}

void ServerSocket::processUpdates(QTcpSocket *client) {
    Q_ASSERT(client != nullptr);
    while (client->bytesAvailable() >= 9) {
        QByteArray data = client->read(9);
        if (data.size() == 9 && data[0] == (char)3) {
            // This message is a rotation update
            broadcastBytes(data);
        }
    }
}

void ServerSocket::newConnection() {
    QTcpSocket *client = sock->nextPendingConnection();
    clients.append(client);
    emit clientConnected(client);
}

void ServerSocket::handleError() {
    emit errorOccurred(sock->errorString());
}

void ServerSocket::handleClientError() {
    QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
    if (client != nullptr) {
        disconnect(client);
    }
}

}
<|endoftext|>


<commit_before>/*
    Copyright 2009 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 22/10/09.

    This file is part of MRtrix.

    MRtrix 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.

    MRtrix 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "dwi/tractography/roi.h"
#include "image/adapter/subset.h"
#include "image/copy.h"

namespace MR {
  namespace DWI {
    namespace Tractography {

      // TODO This will crash if passed a 4D image, even if the 4th axis has dimension 1

      void ROI::get_image (const std::string& name)
      {
        Image::Buffer<float> data (name);
        Image::Buffer<float>::voxel_type vox (data);
        size_t bottom[] = { std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max() };
        size_t top[] = { 0, 0, 0 };
        float sum = 0.0, max = 0.0;

        Image::Loop loop (0,3);
        for (loop.start (vox); loop.ok(); loop.next (vox)) {
          if (vox.value() > 0.0) {
            sum += vox.value();
            max = std::max (max, float (vox.value()));
            if (size_t(vox[0]) < bottom[0]) bottom[0] = vox[0];
            if (size_t(vox[0]) > top[0])    top[0]    = vox[0];
            if (size_t(vox[1]) < bottom[1]) bottom[1] = vox[1];
            if (size_t(vox[1]) > top[1])    top[1]    = vox[1];
            if (size_t(vox[2]) < bottom[2]) bottom[2] = vox[2];
            if (size_t(vox[2]) > top[2])    top[2]    = vox[2];
          }
          else if (vox.value() < 0.0)
            throw Exception ("cannot have negative values in ROI");
        }

        if (!sum)
          throw Exception ("Cannot use image " + name + " as ROI - image is empty");

        if (bottom[0]) --bottom[0];
        if (bottom[1]) --bottom[1];
        if (bottom[2]) --bottom[2];

        top[0] = std::min (size_t (data.dim(0)-1), top[0]+2-bottom[0]);
        top[1] = std::min (size_t (data.dim(1)-1), top[1]+2-bottom[1]);
        top[2] = std::min (size_t (data.dim(2)-1), top[2]+2-bottom[2]);

        Image::Info new_info (data);
        for (size_t axis = 0; axis != 3; ++axis) {
          new_info.dim(axis) = top[axis];
          for (size_t i = 0; i < 3; ++i)
            new_info.transform()(i,3) += bottom[axis] * new_info.vox(axis) * new_info.transform()(i,axis);
        }

        Image::Adapter::Subset< Image::Buffer<float>::voxel_type > sub (vox, bottom, top);

        image = new SeedImage (sub, new_info, data.name(), max);

        vol = vox.vox(0) * vox.vox(1) * vox.vox(2) * sum;

      }

      void ROI::get_mask (const std::string& name)
      {
        Image::Buffer<bool> data (name);
        Image::Buffer<bool>::voxel_type vox (data);
        size_t bottom[] = { std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max() };
        size_t top[] = { 0, 0, 0 };
        size_t sum = 0;

        Image::Loop loop (0,3);
        for (loop.start (vox); loop.ok(); loop.next (vox)) {
          if (vox.value()) {
            ++sum;
            if (size_t(vox[0]) < bottom[0]) bottom[0] = vox[0];
            if (size_t(vox[0]) > top[0])    top[0]    = vox[0];
            if (size_t(vox[1]) < bottom[1]) bottom[1] = vox[1];
            if (size_t(vox[1]) > top[1])    top[1]    = vox[1];
            if (size_t(vox[2]) < bottom[2]) bottom[2] = vox[2];
            if (size_t(vox[2]) > top[2])    top[2]    = vox[2];
          }
        }

        if (!sum)
          throw Exception ("Cannot use image " + name + " as ROI - image is empty");

        if (bottom[0]) --bottom[0];
        if (bottom[1]) --bottom[1];
        if (bottom[2]) --bottom[2];

        top[0] = std::min (size_t (data.dim(0)-1), top[0]+2-bottom[0]);
        top[1] = std::min (size_t (data.dim(1)-1), top[1]+2-bottom[1]);
        top[2] = std::min (size_t (data.dim(2)-1), top[2]+2-bottom[2]);

        Image::Info new_info (data);
        for (size_t axis = 0; axis != 3; ++axis) {
          new_info.dim(axis) = top[axis];
          for (size_t i = 0; i < 3; ++i)
            new_info.transform()(i,3) += bottom[axis] * new_info.vox(axis) * new_info.transform()(i,axis);
        }

        Image::Adapter::Subset< Image::Buffer<bool>::voxel_type > sub (vox, bottom, top);

        mask = new Mask (sub, new_info, data.name());

        vol = vox.vox(0) * vox.vox(1) * vox.vox(2) * sum;
      }

    }
  }
}

<commit_msg>Small bug fix in reading ROI images where voxels at the upper edges of the image were omitted<commit_after>/*
    Copyright 2009 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 22/10/09.

    This file is part of MRtrix.

    MRtrix 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.

    MRtrix 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "dwi/tractography/roi.h"
#include "image/adapter/subset.h"
#include "image/copy.h"

namespace MR {
  namespace DWI {
    namespace Tractography {

      // TODO This will crash if passed a 4D image, even if the 4th axis has dimension 1

      void ROI::get_image (const std::string& name)
      {
        Image::Buffer<float> data (name);
        Image::Buffer<float>::voxel_type vox (data);
        size_t bottom[] = { std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max() };
        size_t top[] = { 0, 0, 0 };
        float sum = 0.0, max = 0.0;

        Image::Loop loop (0,3);
        for (loop.start (vox); loop.ok(); loop.next (vox)) {
          if (vox.value() > 0.0) {
            sum += vox.value();
            max = std::max (max, float (vox.value()));
            if (size_t(vox[0]) < bottom[0]) bottom[0] = vox[0];
            if (size_t(vox[0]) > top[0])    top[0]    = vox[0];
            if (size_t(vox[1]) < bottom[1]) bottom[1] = vox[1];
            if (size_t(vox[1]) > top[1])    top[1]    = vox[1];
            if (size_t(vox[2]) < bottom[2]) bottom[2] = vox[2];
            if (size_t(vox[2]) > top[2])    top[2]    = vox[2];
          }
          else if (vox.value() < 0.0)
            throw Exception ("cannot have negative values in ROI");
        }

        if (!sum)
          throw Exception ("Cannot use image " + name + " as ROI - image is empty");

        if (bottom[0]) --bottom[0];
        if (bottom[1]) --bottom[1];
        if (bottom[2]) --bottom[2];

        top[0] = std::min (size_t (data.dim(0)-bottom[0]), top[0]+2-bottom[0]);
        top[1] = std::min (size_t (data.dim(1)-bottom[1]), top[1]+2-bottom[1]);
        top[2] = std::min (size_t (data.dim(2)-bottom[2]), top[2]+2-bottom[2]);

        Image::Info new_info (data);
        for (size_t axis = 0; axis != 3; ++axis) {
          new_info.dim(axis) = top[axis];
          for (size_t i = 0; i < 3; ++i)
            new_info.transform()(i,3) += bottom[axis] * new_info.vox(axis) * new_info.transform()(i,axis);
        }

        Image::Adapter::Subset< Image::Buffer<float>::voxel_type > sub (vox, bottom, top);

        image = new SeedImage (sub, new_info, data.name(), max);

        vol = vox.vox(0) * vox.vox(1) * vox.vox(2) * sum;

      }

      void ROI::get_mask (const std::string& name)
      {
        Image::Buffer<bool> data (name);
        Image::Buffer<bool>::voxel_type vox (data);
        size_t bottom[] = { std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max() };
        size_t top[] = { 0, 0, 0 };
        size_t sum = 0;

        Image::Loop loop (0,3);
        for (loop.start (vox); loop.ok(); loop.next (vox)) {
          if (vox.value()) {
            ++sum;
            if (size_t(vox[0]) < bottom[0]) bottom[0] = vox[0];
            if (size_t(vox[0]) > top[0])    top[0]    = vox[0];
            if (size_t(vox[1]) < bottom[1]) bottom[1] = vox[1];
            if (size_t(vox[1]) > top[1])    top[1]    = vox[1];
            if (size_t(vox[2]) < bottom[2]) bottom[2] = vox[2];
            if (size_t(vox[2]) > top[2])    top[2]    = vox[2];
          }
        }

        if (!sum)
          throw Exception ("Cannot use image " + name + " as ROI - image is empty");

        if (bottom[0]) --bottom[0];
        if (bottom[1]) --bottom[1];
        if (bottom[2]) --bottom[2];

        top[0] = std::min (size_t (data.dim(0)-bottom[0]), top[0]+2-bottom[0]);
        top[1] = std::min (size_t (data.dim(1)-bottom[1]), top[1]+2-bottom[1]);
        top[2] = std::min (size_t (data.dim(2)-bottom[2]), top[2]+2-bottom[2]);

        Image::Info new_info (data);
        for (size_t axis = 0; axis != 3; ++axis) {
          new_info.dim(axis) = top[axis];
          for (size_t i = 0; i < 3; ++i)
            new_info.transform()(i,3) += bottom[axis] * new_info.vox(axis) * new_info.transform()(i,axis);
        }

        Image::Adapter::Subset< Image::Buffer<bool>::voxel_type > sub (vox, bottom, top);

        mask = new Mask (sub, new_info, data.name());

        vol = vox.vox(0) * vox.vox(1) * vox.vox(2) * sum;
      }

    }
  }
}

<|endoftext|>


<commit_before>#include "TuiDisplay.h"
#include "GridDisplay.h"
#include <stdexcept>
#include <vector>
#include <ncurses.h>

TuiDisplay::TuiDisplay(GameGrid& g) :
  GridDisplay(g) {}

void TuiDisplay::open() {
  generation = 0;
  delay = 100;
  int rows, cols;
  initscr();
  getmaxyx(stdscr, rows, cols);
  if(rows < 20 || cols < 40) {
    endwin();
    throw std::runtime_error("Not enough space to draw, increase terminal window size");
  }
  std::string gridNameTemp = "Grid Name";
  noecho();
  cbreak();
  keypad(stdscr, true);
  displayBounds = Rect(Point(1, 2), Point(cols-2, rows - 3));
  Point windowBottomLeft(grid.getTerrainBounds().getBottomLeft().getX(), grid.getTerrainBounds().getTopRight().getY() - displayBounds.getHeight() + 1);
  Point windowTopRight(grid.getTerrainBounds().getBottomLeft().getX() + displayBounds.getWidth() - 1, grid.getTerrainBounds().getTopRight().getY());
  grid.setWindowBounds(Rect(windowBottomLeft, windowTopRight));
  drawTopBorder(2, cols);
  drawLeftBorder(0, 3, displayBounds.getHeight());
  drawRightScroll(cols-1, 3, displayBounds.getHeight());
  mvprintw(0, (cols - gridNameTemp.length())/2, "%s", gridNameTemp.c_str());
  drawBottomScroll(rows-2, cols);
  printGrid();
  printInstructions();
  printInfoBar();
  refresh();
  runSimulation();
}

void TuiDisplay::runSimulation() {
  int c = getch();
  while(c != 'q' && c != 'Q') {
    c = getch();
    if(c == KEY_DOWN) {
      Point downbl(grid.getWindowBounds().getBottomLeft().getX(), grid.getWindowBounds().getBottomLeft().getY()-1);
      Point downtr(grid.getWindowBounds().getTopRight().getX(), grid.getWindowBounds().getTopRight().getY()-1);
      if(downbl.getY() >= grid.getTerrainBounds().getBottomLeft().getY()) {
        grid.setWindowBounds(Rect(downbl, downtr));
      }
    }
    if(c == KEY_UP) {
      Point upbl(grid.getWindowBounds().getBottomLeft().getX(), grid.getWindowBounds().getBottomLeft().getY()+1);
      Point uptr(grid.getWindowBounds().getTopRight().getX(), grid.getWindowBounds().getTopRight().getY()+1);
      if(uptr.getY() <= grid.getTerrainBounds().getTopRight().getY()) {
        grid.setWindowBounds(Rect(upbl, uptr));
      }
    }
    if(c == KEY_LEFT) {
      Point leftbl(grid.getWindowBounds().getBottomLeft().getX() - 1, grid.getWindowBounds().getBottomLeft().getY());
      Point lefttr(grid.getWindowBounds().getTopRight().getX() - 1, grid.getWindowBounds().getTopRight().getY());
      if(leftbl.getX() >= grid.getTerrainBounds().getBottomLeft().getX()) {
        grid.setWindowBounds(Rect(leftbl, lefttr));
      }
    }
    if(c == KEY_RIGHT) {
      Point rightbl(grid.getWindowBounds().getBottomLeft().getX() + 1, grid.getWindowBounds().getBottomLeft().getY());
      Point righttr(grid.getWindowBounds().getTopRight().getX() + 1, grid.getWindowBounds().getTopRight().getY());
      if(righttr.getX() <= grid.getTerrainBounds().getTopRight().getX()) {
        grid.setWindowBounds(Rect(rightbl, righttr));
      }
    }
    update();
  }
}

void TuiDisplay::drawTopBorder(int yPos, int width) {
  std::string borderStr;
  borderStr = "+";
  for(int i = 1; i < width - 1; i++) {
    borderStr.push_back('-');
  }
  borderStr.push_back('+');
  mvprintw(yPos, 0, "%s", borderStr.c_str());
}

void TuiDisplay::drawLeftBorder(int xPos, int yStart, int height) {
  for(int i = yStart; i < height + yStart - 1; i++) {
    mvprintw(i, xPos, "|");
  }
}

void TuiDisplay::drawBottomScroll(int yPos, int width) {
  int numCharsInScrollTrack = width - 4;
  mvprintw(yPos, 0, "+<");
  int charsUsedSoFar = 2;
  mvprintw(yPos, width-2, ">+");
  if(grid.getTerrainBounds().getBottomLeft().getX() < grid.getWindowBounds().getBottomLeft().getX()) {
    int colsLeftOfWindow = grid.getWindowBounds().getBottomLeft().getX() - grid.getTerrainBounds().getBottomLeft().getX();
    float ratio = float(colsLeftOfWindow) / grid.getTerrainBounds().getWidth();
    int numCharsLeftScrollTrack = ratio * numCharsInScrollTrack;
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsLeftScrollTrack, '-').c_str());
    charsUsedSoFar += numCharsLeftScrollTrack;
  }
  else {
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsInScrollTrack, '-').c_str());
  }
  if(grid.getTerrainBounds().getWidth() > grid.getWindowBounds().getWidth()) {
    float ratio = float(grid.getWindowBounds().getWidth()) / grid.getTerrainBounds().getWidth();
    int numCharsInScrollBar = ratio * numCharsInScrollTrack;
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsInScrollBar, '#').c_str());
    charsUsedSoFar += numCharsInScrollBar;
  }
  if(grid.getTerrainBounds().getTopRight().getX() > grid.getWindowBounds().getTopRight().getX()) {
    int colsRightOfWindow = grid.getTerrainBounds().getTopRight().getX() - grid.getWindowBounds().getTopRight().getX();
    float ratio = float(colsRightOfWindow) / grid.getTerrainBounds().getWidth();
    int numCharsRightScrollTrack = ratio * numCharsInScrollTrack;
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsRightScrollTrack, '-').c_str());
    charsUsedSoFar += numCharsRightScrollTrack;
  }
}

void TuiDisplay::drawRightScroll(int xPos, int yStart, int height) {
  int numCharsInScrollTrack = height - 2;
  mvprintw(yStart, xPos, "^");
  int charsUsedSoFar = 1;
  mvprintw(yStart + height - 2, xPos, "v");
  if(grid.getTerrainBounds().getTopRight().getY() > grid.getWindowBounds().getTopRight().getY()) {
    int rowsAboveWindow = grid.getTerrainBounds().getTopRight().getY() - grid.getWindowBounds().getTopRight().getY();
    float ratio = float(rowsAboveWindow) / grid.getTerrainBounds().getHeight();
    int numCharsInTopScrollTrack = ratio * numCharsInScrollTrack;
    mvprintw(0, 10, "%d", numCharsInTopScrollTrack);
    for(int i = 0; i < numCharsInTopScrollTrack; i++) {
      mvprintw(yStart + charsUsedSoFar + i, xPos, "|");
    }
  }

  /*
  else {
    for(int i = yStart + 1; i < yStart + height - 2; i++) {
      mvprintw(i, xPos, "|");
    }
  }
  */
}

void TuiDisplay::update() {
  printGrid();
  int rows, cols;
  getmaxyx(stdscr, rows, cols);
  drawBottomScroll(rows - 2, cols);
  drawRightScroll(cols - 1, 3, displayBounds.getHeight());
  refresh();
}

void TuiDisplay::printGrid() {
  int rows, cols;
  getmaxyx(stdscr, rows, cols);
  for(int i = displayBounds.getTopRight().getY(); i > displayBounds.getBottomLeft().getY(); i--) {
    int currRowDown = displayBounds.getTopRight().getY() - i;
    int currGridRow = grid.getWindowBounds().getTopRight().getY() - currRowDown;
    mvprintw(rows - i, displayBounds.getBottomLeft().getX(), "%s", grid.getRowAsciiString(currGridRow).c_str());
  }
}

void TuiDisplay::printInstructions() {
  static const std::string arr[] = {"(Q)uit", "(P)lay", "(S)tep", "Arrows:scroll"};
  std::vector<std::string> instructions(arr, arr + sizeof(arr) / sizeof(arr[0]));
  int rows, cols, numInstructChars;
  numInstructChars = 0;
  for(unsigned int i = 0; i < instructions.size(); i++) {
    numInstructChars += instructions[i].size();
  }
  getmaxyx(stdscr, rows, cols);
  int numSpaces = cols - numInstructChars;
  int numPartitions = instructions.size() - 1;
  int spacesPerPartition = numSpaces / numPartitions;
  int currPos = 0;
  mvprintw(rows-1, currPos, "%s", instructions[0].c_str());
  currPos += instructions[0].size() + spacesPerPartition;
  for(unsigned int i = 1; i < instructions.size(); i++) {
    mvprintw(rows-1, currPos, "%s", instructions[i].c_str());
    currPos += instructions[i].size() + spacesPerPartition;
  }
}

void TuiDisplay::printInfoBar() {
  int rows, cols;
  getmaxyx(stdscr, rows, cols);
  mvprintw(1, 0, "Delay: %d (+/-)", delay);
  mvprintw(1, cols - 18, "Generation: %d", generation);
}

void TuiDisplay::close() {
  endwin();
}

void TuiDisplay::setDelay(int d) {
  delay = d;
}
<commit_msg>Implemented vertical scrolling<commit_after>#include "TuiDisplay.h"
#include "GridDisplay.h"
#include <stdexcept>
#include <vector>
#include <ncurses.h>

TuiDisplay::TuiDisplay(GameGrid& g) :
  GridDisplay(g) {}

void TuiDisplay::open() {
  generation = 0;
  delay = 100;
  int rows, cols;
  initscr();
  getmaxyx(stdscr, rows, cols);
  if(rows < 20 || cols < 40) {
    endwin();
    throw std::runtime_error("Not enough space to draw, increase terminal window size");
  }
  std::string gridNameTemp = "Grid Name";
  noecho();
  cbreak();
  keypad(stdscr, true);
  displayBounds = Rect(Point(1, 2), Point(cols-2, rows - 3));
  Point windowBottomLeft(grid.getTerrainBounds().getBottomLeft().getX(), grid.getTerrainBounds().getTopRight().getY() - displayBounds.getHeight() + 1);
  Point windowTopRight(grid.getTerrainBounds().getBottomLeft().getX() + displayBounds.getWidth() - 1, grid.getTerrainBounds().getTopRight().getY());
  grid.setWindowBounds(Rect(windowBottomLeft, windowTopRight));
  drawTopBorder(2, cols);
  drawLeftBorder(0, 3, displayBounds.getHeight());
  drawRightScroll(cols-1, 3, displayBounds.getHeight());
  mvprintw(0, (cols - gridNameTemp.length())/2, "%s", gridNameTemp.c_str());
  drawBottomScroll(rows-2, cols);
  printGrid();
  printInstructions();
  printInfoBar();
  refresh();
  runSimulation();
}

void TuiDisplay::runSimulation() {
  int c = getch();
  while(c != 'q' && c != 'Q') {
    c = getch();
    if(c == KEY_DOWN) {
      Point downbl(grid.getWindowBounds().getBottomLeft().getX(), grid.getWindowBounds().getBottomLeft().getY()-1);
      Point downtr(grid.getWindowBounds().getTopRight().getX(), grid.getWindowBounds().getTopRight().getY()-1);
      if(downbl.getY() >= grid.getTerrainBounds().getBottomLeft().getY()) {
        grid.setWindowBounds(Rect(downbl, downtr));
      }
    }
    if(c == KEY_UP) {
      Point upbl(grid.getWindowBounds().getBottomLeft().getX(), grid.getWindowBounds().getBottomLeft().getY()+1);
      Point uptr(grid.getWindowBounds().getTopRight().getX(), grid.getWindowBounds().getTopRight().getY()+1);
      if(uptr.getY() <= grid.getTerrainBounds().getTopRight().getY()) {
        grid.setWindowBounds(Rect(upbl, uptr));
      }
    }
    if(c == KEY_LEFT) {
      Point leftbl(grid.getWindowBounds().getBottomLeft().getX() - 1, grid.getWindowBounds().getBottomLeft().getY());
      Point lefttr(grid.getWindowBounds().getTopRight().getX() - 1, grid.getWindowBounds().getTopRight().getY());
      if(leftbl.getX() >= grid.getTerrainBounds().getBottomLeft().getX()) {
        grid.setWindowBounds(Rect(leftbl, lefttr));
      }
    }
    if(c == KEY_RIGHT) {
      Point rightbl(grid.getWindowBounds().getBottomLeft().getX() + 1, grid.getWindowBounds().getBottomLeft().getY());
      Point righttr(grid.getWindowBounds().getTopRight().getX() + 1, grid.getWindowBounds().getTopRight().getY());
      if(righttr.getX() <= grid.getTerrainBounds().getTopRight().getX()) {
        grid.setWindowBounds(Rect(rightbl, righttr));
      }
    }
    update();
  }
}

void TuiDisplay::drawTopBorder(int yPos, int width) {
  std::string borderStr;
  borderStr = "+";
  for(int i = 1; i < width - 1; i++) {
    borderStr.push_back('-');
  }
  borderStr.push_back('+');
  mvprintw(yPos, 0, "%s", borderStr.c_str());
}

void TuiDisplay::drawLeftBorder(int xPos, int yStart, int height) {
  for(int i = yStart; i < height + yStart - 1; i++) {
    mvprintw(i, xPos, "|");
  }
}

void TuiDisplay::drawBottomScroll(int yPos, int width) {
  int numCharsInScrollTrack = width - 4;
  mvprintw(yPos, 0, "+<");
  int charsUsedSoFar = 2;
  mvprintw(yPos, width-2, ">+");
  if(grid.getTerrainBounds().getBottomLeft().getX() < grid.getWindowBounds().getBottomLeft().getX()) {
    int colsLeftOfWindow = grid.getWindowBounds().getBottomLeft().getX() - grid.getTerrainBounds().getBottomLeft().getX();
    float ratio = float(colsLeftOfWindow) / grid.getTerrainBounds().getWidth();
    int numCharsLeftScrollTrack = ratio * numCharsInScrollTrack;
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsLeftScrollTrack, '-').c_str());
    charsUsedSoFar += numCharsLeftScrollTrack;
  }
  if(grid.getTerrainBounds().getWidth() > grid.getWindowBounds().getWidth()) {
    float ratio = float(grid.getWindowBounds().getWidth()) / grid.getTerrainBounds().getWidth();
    int numCharsInScrollBar = ratio * numCharsInScrollTrack;
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsInScrollBar, '#').c_str());
    charsUsedSoFar += numCharsInScrollBar;
  }
  else {
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsInScrollTrack, '-').c_str());
  }
  if(grid.getTerrainBounds().getTopRight().getX() > grid.getWindowBounds().getTopRight().getX()) {
    int colsRightOfWindow = grid.getTerrainBounds().getTopRight().getX() - grid.getWindowBounds().getTopRight().getX();
    float ratio = float(colsRightOfWindow) / grid.getTerrainBounds().getWidth();
    int numCharsRightScrollTrack = ratio * numCharsInScrollTrack;
    mvprintw(yPos, charsUsedSoFar, std::string(numCharsRightScrollTrack, '-').c_str());
    charsUsedSoFar += numCharsRightScrollTrack;
  }
}

void TuiDisplay::drawRightScroll(int xPos, int yStart, int height) {
  int numCharsInScrollTrack = height - 2;
  mvprintw(yStart, xPos, "^");
  int charsUsedSoFar = 1;
  mvprintw(yStart + height - 2, xPos, "v");
  if(grid.getTerrainBounds().getTopRight().getY() > grid.getWindowBounds().getTopRight().getY()) {
    int rowsAboveWindow = grid.getTerrainBounds().getTopRight().getY() - grid.getWindowBounds().getTopRight().getY();
    float ratio = float(rowsAboveWindow) / grid.getTerrainBounds().getHeight();
    int numCharsInTopScrollTrack = ratio * numCharsInScrollTrack;
    for(int i = 0; i < numCharsInTopScrollTrack; i++) {
      mvprintw(yStart + charsUsedSoFar + i, xPos, "|");
    }
    charsUsedSoFar += numCharsInTopScrollTrack;
  }
  if(grid.getTerrainBounds().getHeight() > grid.getWindowBounds().getHeight()) {
    float ratio = float(grid.getWindowBounds().getHeight()) / grid.getTerrainBounds().getHeight();
    int numCharsInScrollBar = ratio * numCharsInScrollTrack;
    mvprintw(0, 0, "%d", numCharsInScrollTrack);
    for(int i = 0; i < numCharsInScrollBar; i++) {
      mvprintw(charsUsedSoFar + yStart + i, xPos, "#");
    }
    charsUsedSoFar += numCharsInScrollBar;
  }
  else {
    for(int i = yStart + 1; i < yStart + height - 2; i++) {
      mvprintw(i, xPos, "|");
    }
  }
  if(grid.getTerrainBounds().getBottomLeft().getY() < grid.getWindowBounds().getBottomLeft().getY()) {
    int rowsBelowWindow = grid.getWindowBounds().getBottomLeft().getY() - grid.getTerrainBounds().getBottomLeft().getY();
    float ratio = float(rowsBelowWindow) / grid.getTerrainBounds().getHeight();
    int numCharsInBottomScrollTrack = ratio * numCharsInScrollTrack;
    for(int i = 0; i < numCharsInBottomScrollTrack; i++) {
      mvprintw(yStart + charsUsedSoFar + i, xPos, "|");
    }
    charsUsedSoFar += numCharsInBottomScrollTrack;
  }
}

void TuiDisplay::update() {
  printGrid();
  int rows, cols;
  getmaxyx(stdscr, rows, cols);
  drawBottomScroll(rows - 2, cols);
  drawRightScroll(cols - 1, 3, displayBounds.getHeight());
  refresh();
}

void TuiDisplay::printGrid() {
  int rows, cols;
  getmaxyx(stdscr, rows, cols);
  for(int i = displayBounds.getTopRight().getY(); i > displayBounds.getBottomLeft().getY(); i--) {
    int currRowDown = displayBounds.getTopRight().getY() - i;
    int currGridRow = grid.getWindowBounds().getTopRight().getY() - currRowDown;
    mvprintw(rows - i, displayBounds.getBottomLeft().getX(), "%s", grid.getRowAsciiString(currGridRow).c_str());
  }
}

void TuiDisplay::printInstructions() {
  static const std::string arr[] = {"(Q)uit", "(P)lay", "(S)tep", "Arrows:scroll"};
  std::vector<std::string> instructions(arr, arr + sizeof(arr) / sizeof(arr[0]));
  int rows, cols, numInstructChars;
  numInstructChars = 0;
  for(unsigned int i = 0; i < instructions.size(); i++) {
    numInstructChars += instructions[i].size();
  }
  getmaxyx(stdscr, rows, cols);
  int numSpaces = cols - numInstructChars;
  int numPartitions = instructions.size() - 1;
  int spacesPerPartition = numSpaces / numPartitions;
  int currPos = 0;
  mvprintw(rows-1, currPos, "%s", instructions[0].c_str());
  currPos += instructions[0].size() + spacesPerPartition;
  for(unsigned int i = 1; i < instructions.size(); i++) {
    mvprintw(rows-1, currPos, "%s", instructions[i].c_str());
    currPos += instructions[i].size() + spacesPerPartition;
  }
}

void TuiDisplay::printInfoBar() {
  int rows, cols;
  getmaxyx(stdscr, rows, cols);
  mvprintw(1, 0, "Delay: %d (+/-)", delay);
  mvprintw(1, cols - 18, "Generation: %d", generation);
}

void TuiDisplay::close() {
  endwin();
}

void TuiDisplay::setDelay(int d) {
  delay = d;
}
<|endoftext|>


<commit_before>#ifndef MOTOR_CONTROLER
#define MOTOR_CONTROLER
#include "ros/ros.h"
#include "ros/console.h"
#include "std_msgs/Float64.h"
#include "geometry_msgs/Twist.h"
#include <tf/transform_listener.h>
#include <string>
#include <vector>
#include <cmath>

// publisher of right and left motor velocity values
ros::Publisher right_motor_pub;
ros::Publisher left_motor_pub;

// robot's index in ROS ecosystem (if multiple instances)
int robot_id = 0;
double WHEELS_HALF_SPACING = 0;
double WHEEL_RADIUS = 0.1;

void callback_val(const geometry_msgs::Twist::ConstPtr &msg) {

  // creating new message
  std_msgs::Float64 msg_right_;
  std_msgs::Float64 msg_left_;
  double yaw = 0;

  if (msg.get()->angular.z < -0.0001 || msg.get()->angular.z > 0.0001)
    yaw = msg.get()->angular.z;
  else if (msg.get()->linear.y < -0.0001 || msg.get()->linear.y > 0.0001) {
    // yaw is not set-- trying to calculate from linear x and y
    ROS_WARN("DPL: in Twist msg no yaw component");
    yaw = std::atan2(msg.get()->linear.y, msg.get()->linear.x);
  }

  // calculate from linear x and yaw speed for each wheel
  msg_right_.data =
      (msg.get()->linear.x + WHEELS_HALF_SPACING * yaw) / WHEEL_RADIUS;
  msg_left_.data =
      (msg.get()->linear.x - WHEELS_HALF_SPACING * yaw) / WHEEL_RADIUS;
  // publishing wheel velocities
  right_motor_pub.publish(move(msg_right_));
  left_motor_pub.publish(move(msg_left_));
}

int main(int argc, char **argv) {
  std::string pub_right_ = "hal/rightMotor/setVel";
  std::string pub_left_ = "hal/leftMotor/setVel";
  std::string sub_twist_topic_ = "/cmd_vel";
  ros::init(argc, argv, "motorControl");

  // read  from command line names of topics to publish data
  if (argc >= 3) {
    std::vector<std::string> argv_(argv + 1, argv + argc);
    pub_right_ = argv_[0];
    pub_left_ = argv_[1];
    if(argc==4) sub_twist_topic_ = argv_[2];
  }
  // set relative node namespace
  ros::NodeHandle n;
  n.getParam("robot_id", robot_id);

  // tf listener for calculation of wheel spacing
  tf::TransformListener listener;
  tf::StampedTransform transform;
  // get length in between wheels
  try {
    listener.waitForTransform(std::to_string(robot_id) + "/base/joint1",
                              std::to_string(robot_id) + "/base/joint0",
                              ros::Time::now(), ros::Duration(3.0));
    listener.lookupTransform(std::to_string(robot_id) + "/base/joint1",
                             std::to_string(robot_id) + "/base/joint0",
                             ros::Time(0), transform);
    WHEELS_HALF_SPACING = transform.getOrigin().absolute().getY() / 2;
    ROS_INFO("DPL: motor_controler WHEELS_HALF_SPACING: %f",
             WHEELS_HALF_SPACING);

  } catch (tf::TransformException ex) {
    ROS_ERROR("Problem with transformation between wheels: %s", ex.what());
  }

  // read msg from standard ROS topic for receiving Twist commands
  ros::Subscriber twist_sub = n.subscribe(sub_twist_topic_, 1000, callback_val);

  right_motor_pub = n.advertise<std_msgs::Float64>(pub_right_, 1000);
  left_motor_pub = n.advertise<std_msgs::Float64>(pub_left_, 1000);
  ROS_INFO("DPL: motor_controler node initialized");

  // run event loop
  ros::spin();
  return 0;
}
#endif
<commit_msg>namespace change of cmd_vel topic  in motor control<commit_after>#ifndef MOTOR_CONTROLER
#define MOTOR_CONTROLER
#include "ros/ros.h"
#include "ros/console.h"
#include "std_msgs/Float64.h"
#include "geometry_msgs/Twist.h"
#include <tf/transform_listener.h>
#include <string>
#include <vector>
#include <cmath>

// publisher of right and left motor velocity values
ros::Publisher right_motor_pub;
ros::Publisher left_motor_pub;

// robot's index in ROS ecosystem (if multiple instances)
int robot_id = 0;
double WHEELS_HALF_SPACING = 0;
double WHEEL_RADIUS = 0.1;

void callback_val(const geometry_msgs::Twist::ConstPtr &msg) {

  // creating new message
  std_msgs::Float64 msg_right_;
  std_msgs::Float64 msg_left_;
  double yaw = 0;

  if (msg.get()->angular.z < -0.0001 || msg.get()->angular.z > 0.0001)
    yaw = msg.get()->angular.z;
  else if (msg.get()->linear.y < -0.0001 || msg.get()->linear.y > 0.0001) {
    // yaw is not set-- trying to calculate from linear x and y
    ROS_WARN("DPL: in Twist msg no yaw component");
    yaw = std::atan2(msg.get()->linear.y, msg.get()->linear.x);
  }

  // calculate from linear x and yaw speed for each wheel
  msg_right_.data =
      (msg.get()->linear.x + WHEELS_HALF_SPACING * yaw) / WHEEL_RADIUS;
  msg_left_.data =
      (msg.get()->linear.x - WHEELS_HALF_SPACING * yaw) / WHEEL_RADIUS;
  // publishing wheel velocities
  right_motor_pub.publish(move(msg_right_));
  left_motor_pub.publish(move(msg_left_));
}

int main(int argc, char **argv) {
  std::string pub_right_ = "hal/rightMotor/setVel";
  std::string pub_left_ = "hal/leftMotor/setVel";
  std::string sub_twist_topic_ = "cmd_vel";
  ros::init(argc, argv, "motorControl");

  // read  from command line names of topics to publish data
  if (argc >= 3) {
    std::vector<std::string> argv_(argv + 1, argv + argc);
    pub_right_ = argv_[0];
    pub_left_ = argv_[1];
    if(argc==4) sub_twist_topic_ = argv_[2];
  }
  // set relative node namespace
  ros::NodeHandle n;
  n.getParam("robot_id", robot_id);

  // tf listener for calculation of wheel spacing
  tf::TransformListener listener;
  tf::StampedTransform transform;
  // get length in between wheels
  try {
    listener.waitForTransform(std::to_string(robot_id) + "/base/joint1",
                              std::to_string(robot_id) + "/base/joint0",
                              ros::Time::now(), ros::Duration(3.0));
    listener.lookupTransform(std::to_string(robot_id) + "/base/joint1",
                             std::to_string(robot_id) + "/base/joint0",
                             ros::Time(0), transform);
    WHEELS_HALF_SPACING = transform.getOrigin().absolute().getY() / 2;
    ROS_INFO("DPL: motor_controler WHEELS_HALF_SPACING: %f",
             WHEELS_HALF_SPACING);

  } catch (tf::TransformException ex) {
    ROS_ERROR("Problem with transformation between wheels: %s", ex.what());
  }

  // read msg from standard ROS topic for receiving Twist commands
  ros::Subscriber twist_sub = n.subscribe(sub_twist_topic_, 1000, callback_val);

  right_motor_pub = n.advertise<std_msgs::Float64>(pub_right_, 1000);
  left_motor_pub = n.advertise<std_msgs::Float64>(pub_left_, 1000);
  ROS_INFO("DPL: motor_controler node initialized");

  // run event loop
  ros::spin();
  return 0;
}
#endif
<|endoftext|>


<commit_before><commit_msg>Also include the toplevel corpus in the pre-order map<commit_after><|endoftext|>


<commit_before><commit_msg>refixed boost version<commit_after><|endoftext|>


<commit_before>#include <cstring>
#include <cctype>

#include <fstream>

#include "keybindings.hpp"

namespace roadagain
{

key::key() : ctrl(false), c(0)
{
    ;
}

key::key(const char* s)
{
    if (std::strncmp("Ctrl", s, 4) == 0){
        this->ctrl = true;
        this->c = s[5];
    }
    else {
        this->ctrl = false;
        this->c = s[0];
    }
}

bool key::operator==(const char* s) const
{
    if (this->ctrl){
        return (s[0] == '^' && std::toupper(s[1]) == std::toupper(this->c));
    }
    else {
        return (s[0] == this->c);
    }
}

keybindings::keybindings(const char* name)
{
    // open file
    std::string filename = "keybindings/";
    filename += name;
    std::ifstream in(filename.c_str(), std::ios::in);
    std::string s;

    // init key bindings
    in >> s;
    this->up = key(s.c_str());
    in >> s;
    this->down = key(s.c_str());
    in >> s;
    this->left = key(s.c_str());
    in >> s;
    this->right = key(s.c_str());

    in.close();
}

int keybindings::dx(const char* s)
{
    if (left == s){
        return (-1);
    }
    else if (right == s){
        return (1);
    }
    else {
        return (0);
    }
}

int keybindings::dy(const char* s)
{
    if (up == s){
        return (-1);
    }
    else if (down == s){
        return (1);
    }
    else {
        return (0);
    }
}

}
<commit_msg>Change file extension to .key<commit_after>#include <cstring>
#include <cctype>

#include <fstream>

#include "keybindings.hpp"

namespace roadagain
{

key::key() : ctrl(false), c(0)
{
    ;
}

key::key(const char* s)
{
    if (std::strncmp("Ctrl", s, 4) == 0){
        this->ctrl = true;
        this->c = s[5];
    }
    else {
        this->ctrl = false;
        this->c = s[0];
    }
}

bool key::operator==(const char* s) const
{
    if (this->ctrl){
        return (s[0] == '^' && std::toupper(s[1]) == std::toupper(this->c));
    }
    else {
        return (s[0] == this->c);
    }
}

keybindings::keybindings(const char* name)
{
    // open file
    std::string filename = "keybindings/";
    filename += name;
    filename += ".key";
    std::ifstream in(filename.c_str(), std::ios::in);
    std::string s;

    // init key bindings
    in >> s;
    this->up = key(s.c_str());
    in >> s;
    this->down = key(s.c_str());
    in >> s;
    this->left = key(s.c_str());
    in >> s;
    this->right = key(s.c_str());

    in.close();
}

int keybindings::dx(const char* s)
{
    if (left == s){
        return (-1);
    }
    else if (right == s){
        return (1);
    }
    else {
        return (0);
    }
}

int keybindings::dy(const char* s)
{
    if (up == s){
        return (-1);
    }
    else if (down == s){
        return (1);
    }
    else {
        return (0);
    }
}

}
<|endoftext|>


<commit_before>
#include <zorba/errors.h>

#include "errors/error_messages.h"
#include "error_manager.h"
#include "system/zorba.h"
#include "api/external/xquery.h"
#include "api/external/result_iterator_wrapper.h"

using namespace std;
namespace zorba {

static bool g_throw_exceptions = false;

ZorbaAlertsManager::~ZorbaAlertsManager()
{
}

AlertsManagerImpl::AlertsManagerImpl( )
{
	thread_registered_callback = NULL;
	thread_registered_param = NULL;
	theIsFromUser = true;
//	theAlertMessages = NULL;
  AlertMessagesEnglish* codes = new AlertMessagesEnglish;
	setAlertMessages(codes, false);
//	is_error = false;

	alert_list = new AlertListImpl;
}

AlertsManagerImpl::~AlertsManagerImpl()
{
	//clearAlertList();

  if (!theIsFromUser && theAlertMessages != NULL)
    delete theAlertMessages;
}

void AlertsManagerImpl::clearAlertList()
{
	alert_list = new AlertListImpl;//->clearAlertList();
}

/*
	Register the callback for the thread specific error manager
*/
void AlertsManagerImpl::registerAlertCallback(
    alert_callback* user_alert_callback,
    void* param)
{
	thread_registered_callback = user_alert_callback;
	thread_registered_param = param;
}

AlertMessages& AlertsManagerImpl::getAlertMessages()
{
	return *theAlertMessages;
}

void AlertsManagerImpl::setAlertMessages(AlertMessages* c, bool is_from_user)
{
	if(!theIsFromUser)
		delete theAlertMessages;
	theAlertMessages = c;
	theIsFromUser = is_from_user;
}

int AlertsManagerImpl::sendAlertToUser(Zorba* z, ZorbaAlert_t alert,
																			 bool dont_send_callback)
{
	int		retval = -1;

	if((alert->theKind == ZorbaAlert::ERROR_ALERT) ||
    (alert->theKind == ZorbaAlert::USER_ERROR_ALERT))
		setIsError();

	if(!sendAlertByCallback(z, alert, dont_send_callback, &retval))
	{
		///if no callback was registered, then put the error in list
		alert_list->push_back(alert);
	}

	return retval;
}

bool AlertsManagerImpl::sendAlertByCallback(Zorba* z,
																						ZorbaAlert_t alert,
																						bool dont_send_callback,
																						int *retval)
{
	if(thread_registered_callback)
	{
		if(!dont_send_callback)
		{
			if(z->current_xquery && z->current_xquery->alert_callback_param)
			{
				*retval = thread_registered_callback(alert,
                                        z->current_xquery ? z->current_xquery->xquery : NULL,
																				z->current_xqueryresult,
																				z->current_xquery->alert_callback_param);
			}
			else
			{
				*retval = thread_registered_callback(alert,
                                        z->current_xquery ? z->current_xquery->xquery : NULL,
																				z->current_xqueryresult,
																				thread_registered_param);
			}
			//delete alert;
		}
		return true;
	}
	return false;
}

bool AlertsManagerImpl::isError()
{
	return alert_list->isError();
}

void AlertsManagerImpl::setIsError()
{
	alert_list->setIsError();
}

bool ZorbaAlertsManager::setThrowExceptionsMode(bool throw_exceptions)
{
	bool original_throw_mode = g_throw_exceptions;
	g_throw_exceptions = throw_exceptions;
	return original_throw_mode;
}

bool ZorbaAlertsManager::getThrowExceptionsMode()
{
	return g_throw_exceptions;
}

void AlertsManagerImpl::dumpAlerts(std::ostream &os)
{
	alert_list->dumpAlerts(os);
}

AlertList_t		AlertsManagerImpl::getAlertList()
{
	return &*alert_list;
}

AlertListImpl::AlertListImpl()
{
	is_error = false;
}

AlertListImpl::~AlertListImpl()
{
}

void AlertListImpl::dumpAlerts(std::ostream &os)
{
  AlertListImpl::const_iterator errit;

  for(errit = this->begin(); errit != this->end(); errit++)
  {
    if (errit == this->begin())
      os << endl << "Error list:" << endl;

    (*errit)->dumpAlert(os);
  }

  clearAlertList();
}

void AlertListImpl::clearAlertList()
{
//	AlertListImpl::const_iterator errit;

//	for(errit = begin(); errit != end(); errit++)
//		delete *errit;

	clear();
	is_error = false;
}

bool AlertListImpl::isError()
{
	return is_error;
}

void AlertListImpl::setIsError()
{
	is_error = true;
}

}
<commit_msg>Don't call error callback until the end (errors can be caught)<commit_after>
#include <zorba/errors.h>

#include "errors/error_messages.h"
#include "error_manager.h"
#include "system/zorba.h"
#include "api/external/xquery.h"
#include "api/external/result_iterator_wrapper.h"

using namespace std;
namespace zorba {

static bool g_throw_exceptions = false;

ZorbaAlertsManager::~ZorbaAlertsManager()
{
}

AlertsManagerImpl::AlertsManagerImpl( )
{
	thread_registered_callback = NULL;
	thread_registered_param = NULL;
	theIsFromUser = true;
//	theAlertMessages = NULL;
  AlertMessagesEnglish* codes = new AlertMessagesEnglish;
	setAlertMessages(codes, false);
//	is_error = false;

	alert_list = new AlertListImpl;
}

AlertsManagerImpl::~AlertsManagerImpl()
{
	//clearAlertList();

  if (!theIsFromUser && theAlertMessages != NULL)
    delete theAlertMessages;
}

void AlertsManagerImpl::clearAlertList()
{
	alert_list = new AlertListImpl;//->clearAlertList();
}

/*
	Register the callback for the thread specific error manager
*/
void AlertsManagerImpl::registerAlertCallback(
    alert_callback* user_alert_callback,
    void* param)
{
	thread_registered_callback = user_alert_callback;
	thread_registered_param = param;
}

AlertMessages& AlertsManagerImpl::getAlertMessages()
{
	return *theAlertMessages;
}

void AlertsManagerImpl::setAlertMessages(AlertMessages* c, bool is_from_user)
{
	if(!theIsFromUser)
		delete theAlertMessages;
	theAlertMessages = c;
	theIsFromUser = is_from_user;
}

int AlertsManagerImpl::sendAlertToUser(Zorba* z, ZorbaAlert_t alert,
																			 bool dont_send_callback)
{
 int  retval = -1;

 if((alert->theKind == ZorbaAlert::ERROR_ALERT) ||
    (alert->theKind == ZorbaAlert::USER_ERROR_ALERT))
  setIsError();

 if((alert->theKind == ZorbaAlert::ERROR_ALERT) ||
    (!sendAlertByCallback(z, alert, dont_send_callback, &retval)))
 {
  ///if no callback was registered, then put the error in list
   if((!thread_registered_callback) || (dont_send_callback))
   {
    alert_list->push_back(alert);
    }
 }

 return retval;
}

bool AlertsManagerImpl::sendAlertByCallback(Zorba* z,
																						ZorbaAlert_t alert,
																						bool dont_send_callback,
																						int *retval)
{
	if(thread_registered_callback)
	{
		if(!dont_send_callback)
		{
			if(z->current_xquery && z->current_xquery->alert_callback_param)
			{
				*retval = thread_registered_callback(alert,
                                        z->current_xquery ? z->current_xquery->xquery : NULL,
																				z->current_xqueryresult,
																				z->current_xquery->alert_callback_param);
			}
			else
			{
				*retval = thread_registered_callback(alert,
                                        z->current_xquery ? z->current_xquery->xquery : NULL,
																				z->current_xqueryresult,
																				thread_registered_param);
			}
			//delete alert;
		}
		return true;
	}
	return false;
}

bool AlertsManagerImpl::isError()
{
	return alert_list->isError();
}

void AlertsManagerImpl::setIsError()
{
	alert_list->setIsError();
}

bool ZorbaAlertsManager::setThrowExceptionsMode(bool throw_exceptions)
{
	bool original_throw_mode = g_throw_exceptions;
	g_throw_exceptions = throw_exceptions;
	return original_throw_mode;
}

bool ZorbaAlertsManager::getThrowExceptionsMode()
{
	return g_throw_exceptions;
}

void AlertsManagerImpl::dumpAlerts(std::ostream &os)
{
	alert_list->dumpAlerts(os);
}

AlertList_t		AlertsManagerImpl::getAlertList()
{
	return &*alert_list;
}

AlertListImpl::AlertListImpl()
{
	is_error = false;
}

AlertListImpl::~AlertListImpl()
{
}

void AlertListImpl::dumpAlerts(std::ostream &os)
{
  AlertListImpl::const_iterator errit;

  for(errit = this->begin(); errit != this->end(); errit++)
  {
    if (errit == this->begin())
      os << endl << "Error list:" << endl;

    (*errit)->dumpAlert(os);
  }

  clearAlertList();
}

void AlertListImpl::clearAlertList()
{
//	AlertListImpl::const_iterator errit;

//	for(errit = begin(); errit != end(); errit++)
//		delete *errit;

	clear();
	is_error = false;
}

bool AlertListImpl::isError()
{
	return is_error;
}

void AlertListImpl::setIsError()
{
	is_error = true;
}

}
<|endoftext|>