<commit_before>/*
 * opencog/atomspace/AtomSpace.cc
 *
 * Copyright (c) 2008-2010 OpenCog Foundation
 * Copyright (c) 2009, 2013 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <string>
#include <iostream>
#include <fstream>
#include <list>

#include <stdlib.h>

#include <boost/bind.hpp>

#include <opencog/atomspace/ClassServer.h>
#include <opencog/atomspace/Link.h>
#include <opencog/atomspace/Node.h>
// #include <opencog/atoms/bind/DeleteLink.h>
#include <opencog/atomspace/types.h>
#include <opencog/util/Logger.h>
#include <opencog/util/oc_assert.h>

#include "AtomSpace.h"

//#define DPRINTF printf
#define DPRINTF(...)

using std::string;
using std::cerr;
using std::cout;
using std::endl;
using std::min;
using std::max;
using namespace opencog;

// ====================================================================

AtomSpace::AtomSpace(AtomSpace* parent) :
    atomTable(parent? &parent->atomTable : NULL, this),
    bank(atomTable),
    backing_store(NULL)
{
}

AtomSpace::~AtomSpace()
{
    // Be sure to disconnect the attention bank signals before the
    // atom table destructor runs. XXX FIXME yes this is an ugly hack.
    bank.shutdown();
}

AtomSpace::AtomSpace(const AtomSpace&) :
    atomTable(NULL),
    bank(atomTable),
    backing_store(NULL)
{
     throw opencog::RuntimeException(TRACE_INFO,
         "AtomSpace - Cannot copy an object of this class");
}

AtomSpace& AtomSpace::operator=(const AtomSpace&)
{
     throw opencog::RuntimeException(TRACE_INFO,
         "AtomSpace - Cannot copy an object of this class");
}

// ====================================================================

void AtomSpace::registerBackingStore(BackingStore *bs)
{
    backing_store = bs;
}

void AtomSpace::unregisterBackingStore(BackingStore *bs)
{
    if (bs == backing_store) backing_store = NULL;
}

// ====================================================================

Handle AtomSpace::add_atom(AtomPtr atom, bool async)
{
    // Is this atom already in the atom table?
    Handle hexist(atomTable.getHandle(atom));
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    Type t = atom->getType();
    if (backing_store and not backing_store->ignoreType(t)) {

        Handle ha(atom);
        Handle hb(backing_store->getAtom(ha));
        if (hb.value() != Handle::UNDEFINED.value()) {
            return atomTable.add(hb, async);
        }
    }

    // If we are here, neither the AtomTable nor backing store know
    // about this atom. Just add it.  If it is a DeleteLink, then the
    // addition will fail. Deal with it.
    Handle rh;
    try {
        rh = atomTable.add(atom, async);
    }
    catch (const DeleteException& ex) {
        // Atom deletion has not been implemented in the backing store
        // This is a major to-do item.
        if (backing_store)
// Under construction ....
	        throw RuntimeException(TRACE_INFO, "Not implemented!!!");
    }
    return rh;
}

Handle AtomSpace::add_node(Type t, const string& name,
                           bool async)
{
    // Is this atom already in the atom table?
    Handle hexist(atomTable.getHandle(t, name));
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        NodePtr n(backing_store->getNode(t, name.c_str()));
        if (n) return atomTable.add(n, async);
    }

    // If we are here, neither the AtomTable nor backing store know about
    // this atom. Just add it.
    return atomTable.add(createNode(t, name), async);
}

Handle AtomSpace::get_node(Type t, const string& name)
{
    // Is this atom already in the atom table?
    Handle hexist = atomTable.getHandle(t, name);
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        NodePtr n(backing_store->getNode(t, name.c_str()));
        if (n) {
            return atomTable.add(n, false);
        }
    }

    // If we are here, nobody knows about this.
    return Handle::UNDEFINED;
}

Handle AtomSpace::add_link(Type t, const HandleSeq& outgoing,
                           bool async)
{
    // Is this atom already in the atom table?
    Handle hexist = atomTable.getHandle(t, outgoing);
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        // If any of the outgoing set is ignorable, we will not
        // fetch the thing from the backing store.
        if (not std::any_of(outgoing.begin(), outgoing.end(),
            [this](Handle ho) { return backing_store->ignoreAtom(ho); }))
        {
            LinkPtr l(backing_store->getLink(t, outgoing));
            if (l) {
                // Put the atom into the atomtable, so it gets placed
                // in indices, so we can find it quickly next time.
                return atomTable.add(l, async);
            }
        }
    }

    // If we are here, neither the AtomTable nor backing store know
    // about this atom. Just add it.  If it is a DeleteLink, then the
    // addition will fail. Deal with it.
    Handle rh;
    try {
        rh = atomTable.add(createLink(t, outgoing), async);
    }
    catch (const DeleteException& ex) {
        // Atom deletion has not been implemented in the backing store
        // This is a major to-do item.
        if (backing_store)
// Under construction ....
	        throw RuntimeException(TRACE_INFO, "Not implemented!!!");
    }
    return rh;
}

Handle AtomSpace::get_link(Type t, const HandleSeq& outgoing)
{
    // Is this atom already in the atom table?
    Handle hexist = atomTable.getHandle(t, outgoing);
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        // If any of the outgoing set is ignorable, we will not
        // fetch the thing from the backing store.
        if (not std::any_of(outgoing.begin(), outgoing.end(),
            [this](Handle ho) { return backing_store->ignoreAtom(ho); }))
        {
            LinkPtr l(backing_store->getLink(t, outgoing));
            if (l) {
                // Register the atom with the atomtable (so it gets placed in
                // indices)
                return atomTable.add(l, false);
            }
        }
    }

    // If we are here, nobody knows about this.
    return Handle::UNDEFINED;
}

void AtomSpace::store_atom(Handle h)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    backing_store->storeAtom(h);
}

Handle AtomSpace::fetch_atom(Handle h)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    // OK, we have to handle three distinct cases.
    // 1) If atom table already knows about this uuid or atom, then
    //    this function returns the atom-table's version of the atom.
    //    In particular, no attempt is made to reconcile the possibly
    //    differing truth values in the atomtable vs. backing store.
    // 2) If the handle h holds a UUID but no atom pointer, then get
    //    the corresponding atom from storage, and add it to the atom
    //    table.
    // 3) If the handle h contains a pointer to an atom (that is not
    //    in the atom table), then assume that atom is from some previous
    //    (recursive) query, and add it to the atomtable.
    // For both case 2 & 3, if the atom is a link, then it's outgoing
    // set is fetched as well, as currently, a link cannot be added to
    // the atomtable, unless all of its outgoing set already is in the
    // atomtable.

    // Case 1:
    Handle hb(atomTable.getHandle(h));
    if (atomTable.holds(hb))
        return hb;

    // Case 2 & 3:
    // If we don't have the atom for this UUID, then go get it.
    if (NULL == h.operator->()) {
        AtomPtr a(backing_store->getAtom(h));

        // If we still don't have an atom, then the requested UUID
        // was "insane", that is, unknown by either the atom table
        // (case 1) or the backend.
        if (NULL == a.operator->())
            throw RuntimeException(TRACE_INFO,
                "Asked backend for an unknown handle; UUID=%lu\n",
                h.value());
        h = a;
    }

    // For links, must perform a recursive fetch, as otherwise
    // the atomTable.add() below will throw an error.
    LinkPtr l(LinkCast(h));
    if (l) {
       const HandleSeq& ogs = l->getOutgoingSet();
       size_t arity = ogs.size();
       for (size_t i=0; i<arity; i++)
       {
          Handle oh(fetch_atom(ogs[i]));
          if (oh != ogs[i]) throw RuntimeException(TRACE_INFO,
              "Unexpected handle mismatch! Expected %lu got %lu\n",
              ogs[i].value(), oh.value());
       }
    }

    return atomTable.add(h, false);
}

Handle AtomSpace::fetch_atom(UUID uuid)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    // OK, we have to handle three distinct cases.
    // 1) If atom table already knows about this uuid or atom, then
    //    this function returns the atom-table's version of the atom.
    //    In particular, no attempt is made to reconcile the possibly
    //    differing truth values in the atomtable vs. backing store.
    // 2) If the handle h holds a UUID but no atom pointer, then get
    //    the corresponding atom from storage, and add it to the atom
    //    table.
    // 3) If the handle h contains a pointer to an atom (that is not
    //    in the atom table), then assume that atom is from some previous
    //    (recursive) query, and add it to the atomtable.
    // For both case 2 & 3, if the atom is a link, then it's outgoing
    // set is fetched as well, as currently, a link cannot be added to
    // the atomtable, unless all of its outgoing set already is in the
    // atomtable.

    // Case 1:
    Handle hb(atomTable.getHandle(uuid));
    if (atomTable.holds(hb))
        return hb;

    // Case 2 & 3:
    // We don't have the atom for this UUID, then go get it.
Handle h;
// xxxxxxxxxxxxxxxxxxxxxx
    // Handle h(uuid);
    AtomPtr a(backing_store->getAtom(h));

    // If we still don't have an atom, then the requested UUID
    // was "insane", that is, unknown by either the atom table
    // (case 1) or the backend.
    if (NULL == a.operator->())
        throw RuntimeException(TRACE_INFO,
            "Asked backend for an unknown handle; UUID=%lu\n",
            uuid);
    h = a;

    // For links, must perform a recursive fetch, as otherwise
    // the atomTable.add() below will throw an error.
    LinkPtr l(LinkCast(h));
    if (l) {
       const HandleSeq& ogs = l->getOutgoingSet();
       size_t arity = ogs.size();
       for (size_t i=0; i<arity; i++)
       {
          Handle oh(fetch_atom(ogs[i]));
          if (oh != ogs[i]) throw RuntimeException(TRACE_INFO,
              "Unexpected handle mismatch! Expected %lu got %lu\n",
              ogs[i].value(), oh.value());
       }
    }

    return atomTable.add(h, false);
}

Handle AtomSpace::get_atom(Handle h)
{
    Handle he(atomTable.getHandle(h));
    if (he) return he;
    if (backing_store)
        return fetch_atom(h);
    return Handle::UNDEFINED;
}

Handle AtomSpace::get_atom(UUID uuid)
{
    Handle he(atomTable.getHandle(uuid));
    if (he) return he;
    if (backing_store)
        return fetch_atom(uuid);
    return Handle::UNDEFINED;
}

Handle AtomSpace::fetch_incoming_set(Handle h, bool recursive)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    h = get_atom(h);

    if (Handle::UNDEFINED == h) return Handle::UNDEFINED;

    // Get everything from the backing store.
    HandleSeq iset = backing_store->getIncomingSet(h);
    size_t isz = iset.size();
    for (size_t i=0; i<isz; i++) {
        Handle hi(iset[i]);
        if (recursive) {
            fetch_incoming_set(hi, true);
        } else {
            get_atom(hi);
        }
    }
    return h;
}

bool AtomSpace::remove_atom(Handle h, bool recursive)
{
    if (backing_store) {
        // Atom deletion has not been implemented in the backing store
        // This is a major to-do item.
// Under construction ....
        throw RuntimeException(TRACE_INFO, "Not implemented!!!");
    }
    return 0 < atomTable.extract(h, recursive).size();
}

void AtomSpace::clear()
{
    std::vector<Handle> allAtoms;

    atomTable.getHandlesByType(back_inserter(allAtoms), ATOM, true, false);

    DPRINTF("atoms in allAtoms: %lu\n", allAtoms.size());

    Logger::Level save = logger().getLevel();
    logger().setLevel(Logger::DEBUG);

    // XXX FIXME TODO This is a stunningly inefficient way to clear the
    // atomspace! This will take minutes on any decent-sized atomspace!
    std::vector<Handle>::iterator i;
    for (i = allAtoms.begin(); i != allAtoms.end(); ++i) {
        purge_atom(*i, true);
    }

    allAtoms.clear();
    atomTable.getHandlesByType(back_inserter(allAtoms), ATOM, true, false);
    assert(allAtoms.size() == 0);

    logger().setLevel(save);
}

namespace std {

ostream& operator<<(ostream& out, const opencog::AtomSpace& as) {
    list<opencog::Handle> results;
    as.get_handles_by_type(back_inserter(results), opencog::ATOM, true);
    for (const opencog::Handle& h : results)
	    if (h->getIncomingSetSize() == 0)
		    out << h->toString() << endl;
    return out;
}

} // namespace std
<commit_msg>Still broken for persistence; take another small step.<commit_after>/*
 * opencog/atomspace/AtomSpace.cc
 *
 * Copyright (c) 2008-2010 OpenCog Foundation
 * Copyright (c) 2009, 2013 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <string>
#include <iostream>
#include <fstream>
#include <list>

#include <stdlib.h>

#include <boost/bind.hpp>

#include <opencog/atomspace/ClassServer.h>
#include <opencog/atomspace/Link.h>
#include <opencog/atomspace/Node.h>
// #include <opencog/atoms/bind/DeleteLink.h>
#include <opencog/atomspace/types.h>
#include <opencog/util/Logger.h>
#include <opencog/util/oc_assert.h>

#include "AtomSpace.h"

//#define DPRINTF printf
#define DPRINTF(...)

using std::string;
using std::cerr;
using std::cout;
using std::endl;
using std::min;
using std::max;
using namespace opencog;

// ====================================================================

AtomSpace::AtomSpace(AtomSpace* parent) :
    atomTable(parent? &parent->atomTable : NULL, this),
    bank(atomTable),
    backing_store(NULL)
{
}

AtomSpace::~AtomSpace()
{
    // Be sure to disconnect the attention bank signals before the
    // atom table destructor runs. XXX FIXME yes this is an ugly hack.
    bank.shutdown();
}

AtomSpace::AtomSpace(const AtomSpace&) :
    atomTable(NULL),
    bank(atomTable),
    backing_store(NULL)
{
     throw opencog::RuntimeException(TRACE_INFO,
         "AtomSpace - Cannot copy an object of this class");
}

AtomSpace& AtomSpace::operator=(const AtomSpace&)
{
     throw opencog::RuntimeException(TRACE_INFO,
         "AtomSpace - Cannot copy an object of this class");
}

// ====================================================================

void AtomSpace::registerBackingStore(BackingStore *bs)
{
    backing_store = bs;
}

void AtomSpace::unregisterBackingStore(BackingStore *bs)
{
    if (bs == backing_store) backing_store = NULL;
}

// ====================================================================

Handle AtomSpace::add_atom(AtomPtr atom, bool async)
{
    // Is this atom already in the atom table?
    Handle hexist(atomTable.getHandle(atom));
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    Type t = atom->getType();
    if (backing_store and not backing_store->ignoreType(t)) {

        Handle ha(atom);
        Handle hb(backing_store->getAtom(ha));
        if (hb.value() != Handle::UNDEFINED.value()) {
            return atomTable.add(hb, async);
        }
    }

    // If we are here, neither the AtomTable nor backing store know
    // about this atom. Just add it.  If it is a DeleteLink, then the
    // addition will fail. Deal with it.
    Handle rh;
    try {
        rh = atomTable.add(atom, async);
    }
    catch (const DeleteException& ex) {
        // Atom deletion has not been implemented in the backing store
        // This is a major to-do item.
        if (backing_store)
// Under construction ....
	        throw RuntimeException(TRACE_INFO, "Not implemented!!!");
    }
    return rh;
}

Handle AtomSpace::add_node(Type t, const string& name,
                           bool async)
{
    // Is this atom already in the atom table?
    Handle hexist(atomTable.getHandle(t, name));
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        NodePtr n(backing_store->getNode(t, name.c_str()));
        if (n) return atomTable.add(n, async);
    }

    // If we are here, neither the AtomTable nor backing store know about
    // this atom. Just add it.
    return atomTable.add(createNode(t, name), async);
}

Handle AtomSpace::get_node(Type t, const string& name)
{
    // Is this atom already in the atom table?
    Handle hexist = atomTable.getHandle(t, name);
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        NodePtr n(backing_store->getNode(t, name.c_str()));
        if (n) {
            return atomTable.add(n, false);
        }
    }

    // If we are here, nobody knows about this.
    return Handle::UNDEFINED;
}

Handle AtomSpace::add_link(Type t, const HandleSeq& outgoing,
                           bool async)
{
    // Is this atom already in the atom table?
    Handle hexist = atomTable.getHandle(t, outgoing);
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        // If any of the outgoing set is ignorable, we will not
        // fetch the thing from the backing store.
        if (not std::any_of(outgoing.begin(), outgoing.end(),
            [this](Handle ho) { return backing_store->ignoreAtom(ho); }))
        {
            LinkPtr l(backing_store->getLink(t, outgoing));
            if (l) {
                // Put the atom into the atomtable, so it gets placed
                // in indices, so we can find it quickly next time.
                return atomTable.add(l, async);
            }
        }
    }

    // If we are here, neither the AtomTable nor backing store know
    // about this atom. Just add it.  If it is a DeleteLink, then the
    // addition will fail. Deal with it.
    Handle rh;
    try {
        rh = atomTable.add(createLink(t, outgoing), async);
    }
    catch (const DeleteException& ex) {
        // Atom deletion has not been implemented in the backing store
        // This is a major to-do item.
        if (backing_store)
// Under construction ....
	        throw RuntimeException(TRACE_INFO, "Not implemented!!!");
    }
    return rh;
}

Handle AtomSpace::get_link(Type t, const HandleSeq& outgoing)
{
    // Is this atom already in the atom table?
    Handle hexist = atomTable.getHandle(t, outgoing);
    if (hexist) return hexist;

    // If we are here, the AtomTable does not yet know about this atom.
    // Maybe the backing store knows about this atom.
    if (backing_store and not backing_store->ignoreType(t))
    {
        // If any of the outgoing set is ignorable, we will not
        // fetch the thing from the backing store.
        if (not std::any_of(outgoing.begin(), outgoing.end(),
            [this](Handle ho) { return backing_store->ignoreAtom(ho); }))
        {
            LinkPtr l(backing_store->getLink(t, outgoing));
            if (l) {
                // Register the atom with the atomtable (so it gets placed in
                // indices)
                return atomTable.add(l, false);
            }
        }
    }

    // If we are here, nobody knows about this.
    return Handle::UNDEFINED;
}

void AtomSpace::store_atom(Handle h)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    backing_store->storeAtom(h);
}

Handle AtomSpace::fetch_atom(Handle h)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");
    if (NULL == h) return h;

    // We deal with two distinct cases.
    // 1) If atom table already knows about this atom, then this
    //    function returns the atom-table's version of the atom.
    //    In particular, no attempt is made to reconcile the possibly
    //    differing truth values in the atomtable vs. backing store.
    //    Why?  Because it is likely that the user plans to over-write
    //    what is in the backend.
    // 2) If (1) does not hold, i.e. the atom is not in this table, nor
    //    it's environs, then assume that atom is from some previous
    //    (recursive) query; do fetch it from backing store (i.e. fetch
    //    the TV) and add it to the atomtable.
    // For case 2, if the atom is a link, then it's outgoing set is
    // fetched as well, as currently, a link cannot be added to the
    // atomtable, unless all of its outgoing set already is in the
    // atomtable.

    // Case 1:
    Handle hb(atomTable.getHandle(h));
    if (atomTable.holds(hb))
        return hb;

    // Case 2:
    // This atom is not yet in any (this??) atomspace; go get it.
    if (NULL == h->getAtomTable()) {
        AtomPtr a(backing_store->getAtom(h));

        // If we still don't have an atom, then the requested UUID
        // was "insane", that is, unknown by either the atom table
        // (case 1) or the backend.
        if (NULL == a.operator->())
            throw RuntimeException(TRACE_INFO,
                "Asked backend for an atom %s\n",
                h->toString().c_str());
        h = a;
    }

    // For links, must perform a recursive fetch, as otherwise
    // the atomTable.add() below will throw an error.
    LinkPtr l(LinkCast(h));
    if (l) {
       bool changed = false;
       HandleSeq ogs = l->getOutgoingSet();
       size_t arity = ogs.size();
       for (size_t i=0; i<arity; i++)
       {
          Handle oh(fetch_atom(ogs[i]));
          if (oh != ogs[i])
          {
              changed = true;
              ogs[i] = oh;
          }
       }

       if (changed)
           h = createLink(h->getType(), ogs,
                          h->getTruthValue(), h->getAttentionValue());
    }

    return atomTable.add(h, false);
}

Handle AtomSpace::fetch_atom(UUID uuid)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    // OK, we have to handle three distinct cases.
    // 1) If atom table already knows about this uuid, then this
    //    function returns the atom-table's version of the atom.
    //    In particular, no attempt is made to reconcile the possibly
    //    differing truth values in the atomtable vs. backing store.
    // 2) Else, get the atom corresponding to the UUID from storage.
    // 3) If the handle h contains a pointer to an atom (that is not
    //    in the atom table), then assume that atom is from some previous
    //    (recursive) query, and add it to the atomtable.
    // For both case 2 & 3, if the atom is a link, then it's outgoing
    // set is fetched as well, as currently, a link cannot be added to
    // the atomtable, unless all of its outgoing set already is in the
    // atomtable.

    // Case 1:
    Handle hb(atomTable.getHandle(uuid));
    if (atomTable.holds(hb))
        return hb;

    // Case 2 & 3:
    // We don't have the atom for this UUID, then go get it.
Handle h;
// xxxxxxxxxxxxxxxxxxxxxx
    // Handle h(uuid);
    AtomPtr a(backing_store->getAtom(h));

    // If we still don't have an atom, then the requested UUID
    // was "insane", that is, unknown by either the atom table
    // (case 1) or the backend.
    if (NULL == a.operator->())
        throw RuntimeException(TRACE_INFO,
            "Asked backend for an unknown handle; UUID=%lu\n",
            uuid);
    h = a;

    // For links, must perform a recursive fetch, as otherwise
    // the atomTable.add() below will throw an error.
    LinkPtr l(LinkCast(h));
    if (l) {
       const HandleSeq& ogs = l->getOutgoingSet();
       size_t arity = ogs.size();
       for (size_t i=0; i<arity; i++)
       {
          Handle oh(fetch_atom(ogs[i]));
          if (oh != ogs[i]) throw RuntimeException(TRACE_INFO,
              "Unexpected handle mismatch! Expected %lu got %lu\n",
              ogs[i].value(), oh.value());
       }
    }

    return atomTable.add(h, false);
}

Handle AtomSpace::get_atom(Handle h)
{
    Handle he(atomTable.getHandle(h));
    if (he) return he;
    if (backing_store)
        return fetch_atom(h);
    return Handle::UNDEFINED;
}

Handle AtomSpace::get_atom(UUID uuid)
{
    Handle he(atomTable.getHandle(uuid));
    if (he) return he;
    if (backing_store)
        return fetch_atom(uuid);
    return Handle::UNDEFINED;
}

Handle AtomSpace::fetch_incoming_set(Handle h, bool recursive)
{
    if (NULL == backing_store)
        throw RuntimeException(TRACE_INFO, "No backing store");

    h = get_atom(h);

    if (Handle::UNDEFINED == h) return Handle::UNDEFINED;

    // Get everything from the backing store.
    HandleSeq iset = backing_store->getIncomingSet(h);
    size_t isz = iset.size();
    for (size_t i=0; i<isz; i++) {
        Handle hi(iset[i]);
        if (recursive) {
            fetch_incoming_set(hi, true);
        } else {
            get_atom(hi);
        }
    }
    return h;
}

bool AtomSpace::remove_atom(Handle h, bool recursive)
{
    if (backing_store) {
        // Atom deletion has not been implemented in the backing store
        // This is a major to-do item.
// Under construction ....
        throw RuntimeException(TRACE_INFO, "Not implemented!!!");
    }
    return 0 < atomTable.extract(h, recursive).size();
}

void AtomSpace::clear()
{
    std::vector<Handle> allAtoms;

    atomTable.getHandlesByType(back_inserter(allAtoms), ATOM, true, false);

    DPRINTF("atoms in allAtoms: %lu\n", allAtoms.size());

    Logger::Level save = logger().getLevel();
    logger().setLevel(Logger::DEBUG);

    // XXX FIXME TODO This is a stunningly inefficient way to clear the
    // atomspace! This will take minutes on any decent-sized atomspace!
    std::vector<Handle>::iterator i;
    for (i = allAtoms.begin(); i != allAtoms.end(); ++i) {
        purge_atom(*i, true);
    }

    allAtoms.clear();
    atomTable.getHandlesByType(back_inserter(allAtoms), ATOM, true, false);
    assert(allAtoms.size() == 0);

    logger().setLevel(save);
}

namespace std {

ostream& operator<<(ostream& out, const opencog::AtomSpace& as) {
    list<opencog::Handle> results;
    as.get_handles_by_type(back_inserter(results), opencog::ATOM, true);
    for (const opencog::Handle& h : results)
	    if (h->getIncomingSetSize() == 0)
		    out << h->toString() << endl;
    return out;
}

} // namespace std
<|endoftext|>


<commit_before><commit_msg>lp: added detection of problem type<commit_after><|endoftext|>


<commit_before>/**
@file Rule/Defs.hpp
@brief Rule definitions.

@author Tim Howard
@copyright 2013 Tim Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_RULE_DEFS_HPP_
#define HORD_RULE_DEFS_HPP_

#include <Hord/config.hpp>
#include <Hord/Object/Defs.hpp>
#include <Hord/Hive/Defs.hpp>

namespace Hord {
namespace Rule {

// Forward declarations
class Unit; // external
struct type_info;

/**
	@addtogroup object
	@{
*/
/**
	@addtogroup rule
	@{
*/

/**
	Rule ID.

	@note This type is only to telegraph intent in functions;
	it is entirely equivalent to @c Object::ID.

	@sa Object::ID,
		Hive::ID,
		Node::ID
*/
using ID = Object::ID;

/**
	Rule type.
*/
using Type = uint32_t;

/**
	Standard rule types.

	@note Values in [0, 8] are reserved for standard
	types (@c 0 is invalid). Userspace may specify further types in
	the range [9, (2 ^ 32) - 1].

	@sa
		Rule::Unit
*/
enum class StandardTypes : Rule::Type {
	/**
		Special non-type.

		@note This type defines the lack of rule/structure.
		%Rules cannot be registered with this type.
	*/
	None = 0,
	/**
		Composition of types.

		@sa CompositionRule
	*/
	Composition,
	/**
		Delimited set of rules.

		@sa DelimitedSetRule
	*/
	DelimitedSet,
	/**
		Value matcher.

		@sa MatchRule
	*/
	Match,
	/**
		Number limiter.

		@sa LimitRule
	*/
	Limit,
	/**
		List.

		@sa ListRule
	*/
	List,
	/**
		Date-time.

		@sa DateTimeRule
	*/
	DateTime,
	/**
		Timespan.

		@sa TimespanRule
	*/
	Timespan,
/// @{
	/**
		Reserved types (@c 8).
	*/
	Reserved1,
	ReservedFirst = Reserved1,
	ReservedLast = Reserved1
/// @}
};

static_assert(
	8 == static_cast<Rule::Type>(StandardTypes::ReservedLast),
	"StandardTypes must reserve up to 8"
);

/**
	Rule type info.
*/
struct type_info final {
	/**
		%Rule type.

		@sa StandardTypes
	*/
	Type const type;

	/**
		Permitted Data::FieldTypes.

		@note This should be a nonzero combination of
		Data::FieldTypes.

		@sa FieldType
	*/
	uint8_t const permitted_types;

	/**
		Construct a rule of this type.

		@returns
		- The constructed rule; or
		- @c nullptr if construction failed.
		@param owner Owner ID.
		@param id %Object ID.
	*/
	Unit*
	(&construct)(
		Hive::ID const owner,
		Rule::ID const id
	) noexcept;
};

/** @} */ // end of doc-group rule
/** @} */ // end of doc-group object

} // namespace Rule
} // namespace Hord

#endif // HORD_RULE_DEFS_HPP_
<commit_msg>Rule/Defs: corrected type_info::construct() params; doc tidy.¹<commit_after>/**
@file Rule/Defs.hpp
@brief Rule definitions.

@author Tim Howard
@copyright 2013 Tim Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_RULE_DEFS_HPP_
#define HORD_RULE_DEFS_HPP_

#include <Hord/config.hpp>
#include <Hord/Object/Defs.hpp>

namespace Hord {
namespace Rule {

// Forward declarations
class Unit; // external
struct type_info;

/**
	@addtogroup object
	@{
*/
/**
	@addtogroup rule
	@{
*/

/**
	Rule ID.

	@note This type is only to telegraph intent in functions;
	it is entirely equivalent to @c Object::ID.

	@sa Object::ID,
		Hive::ID,
		Node::ID
*/
using ID = Object::ID;

/**
	Rule type.
*/
using Type = uint32_t;

/**
	Standard rule types.

	@note Values in [0, 8] are reserved for standard
	types (@c 0 is invalid). Userspace may specify further types in
	the range [9, (2 ^ 32) - 1].

	@sa
		Rule::Unit
*/
enum class StandardTypes : Rule::Type {
	/**
		Special non-type.

		@note This type defines the lack of rule/structure.
		%Rules cannot be registered with this type.
	*/
	None = 0,

	/**
		Composition of types.

		@sa CompositionRule
	*/
	Composition,

	/**
		Delimited set of rules.

		@sa DelimitedSetRule
	*/
	DelimitedSet,

	/**
		Value matcher.

		@sa MatchRule
	*/
	Match,

	/**
		Number limiter.

		@sa LimitRule
	*/
	Limit,

	/**
		List.

		@sa ListRule
	*/
	List,

	/**
		Date-time.

		@sa DateTimeRule
	*/
	DateTime,

	/**
		Timespan.

		@sa TimespanRule
	*/
	Timespan,

/// @{
	/**
		Reserved types (@c 8).
	*/
	Reserved1,
	ReservedFirst = Reserved1,
	ReservedLast = Reserved1
/// @}
};

static_assert(
	8 == static_cast<Rule::Type>(StandardTypes::ReservedLast),
	"StandardTypes must reserve up to 8"
);

/**
	Rule type info.
*/
struct type_info final {
	/**
		%Rule type.

		@sa Rule::StandardTypes
	*/
	Type const type;

	/**
		Permitted field types.

		@note This should be a nonzero combination of
		Data::FieldTypes.

		@sa Data::FieldType
	*/
	uint8_t const permitted_types;

	/**
		Construct a rule of this type.

		@returns
		- The constructed rule; or
		- @c nullptr if construction failed.
		@param id Object %ID.
		@param parent Parent %ID.
	*/
	Unit*
	(&construct)(
		Rule::ID const id,
		Object::ID const parent
	) noexcept;
};

/** @} */ // end of doc-group rule
/** @} */ // end of doc-group object

} // namespace Rule
} // namespace Hord

#endif // HORD_RULE_DEFS_HPP_
<|endoftext|>


<commit_before>#ifndef COBALT_COM_STD_HPP_INCLUDED
#define COBALT_COM_STD_HPP_INCLUDED

#pragma once

// Classes in this file:
//     equatable
//     comparable
//     hashable
//     copyable
//     coder
//     decodable
//     encodable
//     codable

#include <cobalt/com/error.hpp>
#include <cobalt/utility/intrusive.hpp>
#include <cobalt/utility/uid.hpp>

namespace cobalt {
namespace com {

DECLARE_INTERFACE(com, equatable)
struct equatable : any {
	virtual bool equal(any*) const noexcept = 0;
};

DECLARE_INTERFACE(com, comparable)
struct comparable : equatable {
	virtual bool less(any*) const noexcept = 0;
};

DECLARE_INTERFACE(com, hashable)
struct hashable : equatable {
	virtual size_t hash_value() const noexcept = 0;
};

DECLARE_INTERFACE(com, copyable)
struct copyable : any {
	virtual any* copy() const noexcept = 0;
};

enum class coding_mode {
	encoding,
	decoding
};

DECLARE_INTERFACE(com, coder)
struct coder : any {
	virtual coding_mode mode() const noexcept = 0;

	virtual bool encode_bool(const char* name, bool& value) noexcept = 0;
	virtual bool encode_int(const char* name, int& value) noexcept = 0;
	virtual bool encode_int_range(const char* name, int& value, int min, int max) noexcept = 0;
	virtual bool encode_float(const char* name, float& value) noexcept = 0;
	virtual bool encode_float_range(const char* name, float& value, float min, float max, float resolution) noexcept = 0;
	virtual bool encode_bytes(const char* name, void* data, size_t size_in_bytes) noexcept = 0;
};

DECLARE_INTERFACE(com, decodable)
struct decodable : any {
	virtual void init(coder*) noexcept = 0;
};

DECLARE_INTERFACE(com, encodable)
struct encodable : any {
	virtual void encode(coder*) const noexcept = 0;
};

DECLARE_INTERFACE(com, codable)
struct codable : decodable, encodable {
};

} // namespace com
} // namespace cobalt

#endif // COBALT_COM_STD_HPP_INCLUDED

<commit_msg>Some changes in com::std.<commit_after>#ifndef COBALT_COM_STD_HPP_INCLUDED
#define COBALT_COM_STD_HPP_INCLUDED

#pragma once

// Classes in this file:
//     equatable
//     comparable
//     hashable
//     copyable
//     clonable
//     decoder
//     encoder
//     decodable
//     encodable

#include <cobalt/com/core.hpp>

#include <system_error>

namespace cobalt {
namespace com {

DECLARE_INTERFACE(com, equatable)
struct equatable : any {
	virtual bool equals(any*) const noexcept = 0;
};

DECLARE_INTERFACE(com, comparable)
struct comparable : equatable {
	virtual bool less(any*) const noexcept = 0;
};

DECLARE_INTERFACE(com, hashable)
struct hashable : equatable {
	virtual size_t hash_value() const noexcept = 0;
};

DECLARE_INTERFACE(com, copyable)
struct copyable : any {
	virtual ref<any> copy() const noexcept = 0;
};

DECLARE_INTERFACE(com, clonable)
struct clonable : copyable {
	virtual ref<any> clone() const noexcept = 0;
};

DECLARE_INTERFACE(com, decoder)
struct decoder : any {
	virtual void decode(const char* key, bool& value) noexcept = 0;
	virtual void decode(const char* key, int& value) noexcept = 0;
	virtual void decode(const char* key, int& value, int min, int max) noexcept = 0;
	virtual void decode(const char* key, float& value) noexcept = 0;
	virtual void decode(const char* key, float& value, float min, float max, float resolution) noexcept = 0;
	virtual void decode(const char* key, void* data, size_t size) noexcept = 0;
};

DECLARE_INTERFACE(com, encoder)
struct encoder : any {
	virtual void encode(const char* key, bool& value) noexcept = 0;
	virtual void encode(const char* key, int& value) noexcept = 0;
	virtual void encode(const char* key, int& value, int min, int max) noexcept = 0;
	virtual void encode(const char* key, float& value) noexcept = 0;
	virtual void encode(const char* key, float& value, float min, float max, float resolution) noexcept = 0;
	virtual void encode(const char* key, void* data, size_t size) noexcept = 0;
};

DECLARE_INTERFACE(com, decodable)
struct decodable : any {
	virtual void init(decoder*, std::error_code& ec) noexcept = 0;
};

DECLARE_INTERFACE(com, encodable)
struct encodable : any {
	virtual void encode(encoder*, std::error_code& ec) const noexcept = 0;
};

} // namespace com
} // namespace cobalt

#endif // COBALT_COM_STD_HPP_INCLUDED

<|endoftext|>


<commit_before>#pragma once

#include "util.hpp"

#include <iostream>
#include <memory>
#include <type_traits>

namespace imu {

  /**
   * A type that can hold any other value. This could be replaced with
   * std::any, once it's not experimental anymore.
   *
   */
  struct value {

    typedef std::shared_ptr<value> p;

    inline value()
      : pad(nullptr)
    {}

    template<typename T>
    inline value(const T& v)
      : pad(new value_pad<typename std::decay<const T>::type>(v))
    {}

    inline value(const value& cpy)
      : pad(cpy.pad ? cpy.pad->clone() : nullptr)
    {}

    inline value(value&& other)
      : pad(other.pad)
    {
      other.pad = nullptr;
    }

    inline ~value() {
      delete pad;
    }

    inline value& operator= (const value& cpy)
    {
      if (cpy.pad) {
        delete pad;
        pad = cpy.pad->clone();
      }
      return *this;
    }

    inline value& operator= (value&& other)
    {
      std::swap(pad, other.pad);
      delete other.pad;
      other.pad = nullptr;
      return *this;
    }

    inline bool is_set() const {
      return (bool) pad;
    }

    inline operator bool() const {
      return is_set();
    }

    template<typename T>
    inline const T& get() const {

      typedef typename std::decay<const T>::type value_type;
      typedef value_pad<value_type> pad_type;

      if (typeid(value_type) != type()) {
        throw bad_value_cast();
      }

      return dynamic_cast<const pad_type*>(pad)->value;
    }

    inline friend bool operator== (const value& l, const value& r) {
      return l.pad->equiv(r.pad);
    }

    template<typename T>
    inline friend bool operator== (const value& l, const T& r) {
      return l.get<T>() == r;
    }

    inline const std::type_info& type() const {
      return pad->type();
    }

    struct value_pad_base {

      typedef std::unique_ptr<value_pad_base> p;

      virtual ~value_pad_base() {}

      virtual value_pad_base* clone() const = 0;

      virtual bool equiv(const value_pad_base* other) const = 0;

      virtual const std::type_info& type() const = 0;
    };

    template<typename T>
    struct value_pad : public value_pad_base {

      T value;

      value_pad(const T& v)
        : value(v)
      {}

      value_pad(const T&& v)
        : value(static_cast<T&&>(v))
      {}

      value_pad_base* clone() const {
        return new value_pad(value);
      }

      bool equiv(const value_pad_base* other) const {
        return value == dynamic_cast<const value_pad*>(other)->value;
      }

      const std::type_info& type() const {
        return typeid(T);
      }
    };

    struct bad_value_cast : public std::bad_cast {

      virtual const char* what() const noexcept {
        return "Bad cast of imu::value to concrete type";
      }
    };

    const value_pad_base* pad;
  };

  template<typename T>
  inline const T& value_cast(const value& v) {
    return v.get<T>();
  }

  template<typename T>
  inline const T& value_cast(const value::p& v) {
    return v->get<T>();
  }

  template<>
  inline const value& value_cast<value>(const value& v) {
    return v;
  }

  template<typename T, typename X>
  inline const T& value_cast(const X& x) {
    return static_cast<const T&>(x);
  }
}
<commit_msg>Use static pointer cast for std::shared_ptr<commit_after>#pragma once

#include "util.hpp"

#include <iostream>
#include <memory>
#include <type_traits>

namespace imu {

  /**
   * A type that can hold any other value. This could be replaced with
   * std::any, once it's not experimental anymore.
   *
   */
  struct value {

    typedef std::shared_ptr<value> p;

    inline value()
      : pad(nullptr)
    {}

    template<typename T>
    inline value(const T& v)
      : pad(new value_pad<typename std::decay<const T>::type>(v))
    {}

    inline value(const value& cpy)
      : pad(cpy.pad ? cpy.pad->clone() : nullptr)
    {}

    inline value(value&& other)
      : pad(other.pad)
    {
      other.pad = nullptr;
    }

    inline ~value() {
      delete pad;
    }

    inline value& operator= (const value& cpy)
    {
      if (cpy.pad) {
        delete pad;
        pad = cpy.pad->clone();
      }
      return *this;
    }

    inline value& operator= (value&& other)
    {
      std::swap(pad, other.pad);
      delete other.pad;
      other.pad = nullptr;
      return *this;
    }

    inline bool is_set() const {
      return (bool) pad;
    }

    inline operator bool() const {
      return is_set();
    }

    template<typename T>
    inline const T& get() const {

      typedef typename std::decay<const T>::type value_type;
      typedef value_pad<value_type> pad_type;

      if (typeid(value_type) != type()) {
        throw bad_value_cast();
      }

      return dynamic_cast<const pad_type*>(pad)->value;
    }

    inline friend bool operator== (const value& l, const value& r) {
      return l.pad->equiv(r.pad);
    }

    template<typename T>
    inline friend bool operator== (const value& l, const T& r) {
      return l.get<T>() == r;
    }

    inline const std::type_info& type() const {
      return pad->type();
    }

    struct value_pad_base {

      typedef std::unique_ptr<value_pad_base> p;

      virtual ~value_pad_base() {}

      virtual value_pad_base* clone() const = 0;

      virtual bool equiv(const value_pad_base* other) const = 0;

      virtual const std::type_info& type() const = 0;
    };

    template<typename T>
    struct value_pad : public value_pad_base {

      T value;

      value_pad(const T& v)
        : value(v)
      {}

      value_pad(const T&& v)
        : value(static_cast<T&&>(v))
      {}

      value_pad_base* clone() const {
        return new value_pad(value);
      }

      bool equiv(const value_pad_base* other) const {
        return value == dynamic_cast<const value_pad*>(other)->value;
      }

      const std::type_info& type() const {
        return typeid(T);
      }
    };

    struct bad_value_cast : public std::bad_cast {

      virtual const char* what() const noexcept {
        return "Bad cast of imu::value to concrete type";
      }
    };

    const value_pad_base* pad;
  };

  template<typename T>
  inline const T& value_cast(const value& v) {
    return v.get<T>();
  }

  template<typename T>
  inline const T& value_cast(const value::p& v) {
    return v->get<T>();
  }

  template<>
  inline const value& value_cast<value>(const value& v) {
    return v;
  }

  template<typename T, typename X>
  inline const T& value_cast(const X& x) {
    return static_cast<const T&>(x);
  }

  template<typename T, typename X>
  inline const T& value_cast(const std::shared_ptr<X>& x) {
    return std::static_pointer_cast<const T&>(x);
  }
}
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*                  Copyright 1998-2003 by Hans Meine                   */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    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.                                   */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_MESHGRID_HXX
#define VIGRA_MESHGRID_HXX

#include "tinyvector.hxx"
#include "diff2D.hxx"

namespace vigra{
/** \addtogroup RangesAndPoints Two-dimensional Ranges and Points

    Specify a 2D position, extent, or rectangle.
*/
//@{

/********************************************************/
/*                                                      */
/*                 MeshGridAccessor                     */
/*                                                      */
/********************************************************/
/** Accessor for turning iteration over Diff2D into a mesh grid.

    The mesh grid concept is adapted from MATLAB. It is a two banded image
    (i.e. with 2D vector pixel type) whose first band contains the x-coordinates
    of the current pixel, and whose second band contains the y-coordinates.
    See \ref meshGrid() for more detailed documentation.
*/
struct MeshGridAccessor
{
        /** the value_type of a mesh grid is a 2D vector
        */
    typedef TinyVector<Diff2D::MoveX, 2> value_type;

        /** read the current data item
        */
    template <class ITERATOR>
    value_type operator()(ITERATOR const & i) const
    {
        return value_type(i->x, i->y);
    }

        /** read the data item at an offset (can be 1D or 2D or higher order difference).
        */
    template <class ITERATOR, class DIFFERENCE>
    value_type operator()(ITERATOR const & i, DIFFERENCE const & diff) const
    {
        return value_type(i->x+diff.x, i->y+diff.y);
    }
};

/** Create a mesh grid for the specified rectangle.

    The mesh grid concept is adapted from MATLAB. It is a two banded image
    (i.e. with 2D vector pixel type) whose first band contains the x-coordinates
    of the current pixel, and whose second band contains the y-coordinates.
    If \a upperLeft is not the point (0,0), the mesh grid is translated relative to
    the pixel indices.

     Declarations:

    \code
    triple<Diff2D, Diff2D, MeshGridAccessor>
    meshGrid(Diff2D upperLeft, Diff2D lowerRight);

    triple<Diff2D, Diff2D, MeshGridAccessor>
    meshGrid(Rect2D const & r);

    \endcode

    Usage:

    \code
    #include <vigra/meshgrid.hxx>
    // create an image whose values are equal to each pixel's distance from the image center
    int width = 5, height = 7;
    int xc = width/2, yc = height/2; // the image center

    FImage dist(width, height);
    Point2D upperLeft(-xc, -yc);

    using namespace vigra::functor;
    transformImage(meshGrid(upperLeft, upperLeft+dist.size()),
                   destImage(dist),
                   norm(Arg1()));
    \endcode
*/
inline
triple<Diff2D, Diff2D, MeshGridAccessor>
meshGrid(Diff2D upperLeft, Diff2D lowerRight)
{
    return triple<Diff2D, Diff2D, MeshGridAccessor>(upperLeft, lowerRight, MeshGridAccessor());
}

inline
triple<Diff2D, Diff2D, MeshGridAccessor>
meshGrid(Rect2D const & r)
{
    return triple<Diff2D, Diff2D, MeshGridAccessor>(r.upperLeft(), r.lowerRight(), MeshGridAccessor());
}

}//namespace vigra
//@}
#endif //VIGRA_MESHGRID_HXX
<commit_msg>fix wrongly capitalized #include and guess copyright of meshgrid.hxx<commit_after>/************************************************************************/
/*                                                                      */
/*                   Copyright 2009 by Ullrich Kthe                    */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    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.                                   */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_MESHGRID_HXX
#define VIGRA_MESHGRID_HXX

#include "tinyvector.hxx"
#include "diff2d.hxx"

namespace vigra{
/** \addtogroup RangesAndPoints Two-dimensional Ranges and Points

    Specify a 2D position, extent, or rectangle.
*/
//@{

/********************************************************/
/*                                                      */
/*                 MeshGridAccessor                     */
/*                                                      */
/********************************************************/
/** Accessor for turning iteration over Diff2D into a mesh grid.

    The mesh grid concept is adapted from MATLAB. It is a two banded image
    (i.e. with 2D vector pixel type) whose first band contains the x-coordinates
    of the current pixel, and whose second band contains the y-coordinates.
    See \ref meshGrid() for more detailed documentation.
*/
struct MeshGridAccessor
{
        /** the value_type of a mesh grid is a 2D vector
        */
    typedef TinyVector<Diff2D::MoveX, 2> value_type;

        /** read the current data item
        */
    template <class ITERATOR>
    value_type operator()(ITERATOR const & i) const
    {
        return value_type(i->x, i->y);
    }

        /** read the data item at an offset (can be 1D or 2D or higher order difference).
        */
    template <class ITERATOR, class DIFFERENCE>
    value_type operator()(ITERATOR const & i, DIFFERENCE const & diff) const
    {
        return value_type(i->x+diff.x, i->y+diff.y);
    }
};

/** Create a mesh grid for the specified rectangle.

    The mesh grid concept is adapted from MATLAB. It is a two banded image
    (i.e. with 2D vector pixel type) whose first band contains the x-coordinates
    of the current pixel, and whose second band contains the y-coordinates.
    If \a upperLeft is not the point (0,0), the mesh grid is translated relative to
    the pixel indices.

     Declarations:

    \code
    triple<Diff2D, Diff2D, MeshGridAccessor>
    meshGrid(Diff2D upperLeft, Diff2D lowerRight);

    triple<Diff2D, Diff2D, MeshGridAccessor>
    meshGrid(Rect2D const & r);

    \endcode

    Usage:

    \code
    #include <vigra/meshgrid.hxx>
    // create an image whose values are equal to each pixel's distance from the image center
    int width = 5, height = 7;
    int xc = width/2, yc = height/2; // the image center

    FImage dist(width, height);
    Point2D upperLeft(-xc, -yc);

    using namespace vigra::functor;
    transformImage(meshGrid(upperLeft, upperLeft+dist.size()),
                   destImage(dist),
                   norm(Arg1()));
    \endcode
*/
inline
triple<Diff2D, Diff2D, MeshGridAccessor>
meshGrid(Diff2D upperLeft, Diff2D lowerRight)
{
    return triple<Diff2D, Diff2D, MeshGridAccessor>(upperLeft, lowerRight, MeshGridAccessor());
}

inline
triple<Diff2D, Diff2D, MeshGridAccessor>
meshGrid(Rect2D const & r)
{
    return triple<Diff2D, Diff2D, MeshGridAccessor>(r.upperLeft(), r.lowerRight(), MeshGridAccessor());
}

}//namespace vigra
//@}
#endif //VIGRA_MESHGRID_HXX
<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_OPTION_HPP__
#define __STOUT_OPTION_HPP__

#include <assert.h>

#include <algorithm>
#include <functional>
#include <type_traits>

#include <boost/functional/hash.hpp>

#include <stout/none.hpp>
#include <stout/some.hpp>

template <typename T>
class Option
{
public:
  static Option<T> none()
  {
    return Option<T>();
  }

  static Option<T> some(const T& t)
  {
    return Option<T>(t);
  }

  Option() : state(NONE) {}

  Option(const T& _t) : state(SOME), t(_t) {}

  Option(T&& _t) : state(SOME), t(std::move(_t)) {}

  template <
    typename U,
    typename = typename std::enable_if<
        std::is_constructible<T, const U&>::value>::type>
  Option(const U& u) : state(SOME), t(u) {}

  Option(const None&) : state(NONE) {}

  template <typename U>
  Option(const _Some<U>& some) : state(SOME), t(some.t) {}

  template <typename U>
  Option(_Some<U>&& some) : state(SOME), t(std::move(some.t)) {}

  Option(const Option<T>& that) : state(that.state)
  {
    if (that.isSome()) {
      new (&t) T(that.t);
    }
  }

  Option(Option<T>&& that)
      noexcept(std::is_nothrow_move_constructible<T>::value)
    : state(std::move(that.state))
  {
    if (that.isSome()) {
      new (&t) T(std::move(that.t));
    }
  }

  ~Option()
  {
    if (isSome()) {
      t.~T();
    }
  }

  Option<T>& operator=(const Option<T>& that)
  {
    if (this != &that) {
      if (isSome()) {
        t.~T();
      }
      state = that.state;
      if (that.isSome()) {
        new (&t) T(that.t);
      }
    }

    return *this;
  }

  Option<T>& operator=(Option<T>&& that)
      noexcept(std::is_nothrow_move_constructible<T>::value)
  {
    if (this != &that) {
      if (isSome()) {
        t.~T();
      }
      state = std::move(that.state);
      if (that.isSome()) {
        new (&t) T(std::move(that.t));
      }
    }

    return *this;
  }

  bool isSome() const { return state == SOME; }
  bool isNone() const { return state == NONE; }

  const T& get() const & { assert(isSome()); return t; }
  T& get() & { assert(isSome()); return t; }
  T&& get() && { assert(isSome()); return std::move(t); }
  const T&& get() const && { assert(isSome()); return std::move(t); }

  const T* operator->() const { return &get(); }
  T* operator->() { return &get(); }

  // This must return a copy to avoid returning a reference to a temporary.
  T getOrElse(const T& _t) const { return isNone() ? _t : t; }

  bool operator==(const Option<T>& that) const
  {
    return (isNone() && that.isNone()) ||
      (isSome() && that.isSome() && t == that.t);
  }

  bool operator!=(const Option<T>& that) const
  {
    return !(*this == that);
  }

  bool operator==(const T& that) const
  {
    return isSome() && t == that;
  }

  bool operator!=(const T& that) const
  {
    return !(*this == that);
  }

private:
  enum State
  {
    SOME,
    NONE,
  };

  State state;

  union {
    // We remove the const qualifier (if there is one) from T so that
    // we can initialize 't' from outside of the initializer list
    // using placement new. This is necessary because sometimes we
    // specialize 'Option' as such: 'Option<const T>'.
    typename std::remove_const<T>::type t;
  };
};

template <typename T>
Option<T> min(const Option<T>& left, const Option<T>& right)
{
  if (left.isSome() && right.isSome()) {
    return std::min(left.get(), right.get());
  } else if (left.isSome()) {
    return left.get();
  } else if (right.isSome()) {
    return right.get();
  } else {
    return Option<T>::none();
  }
}

template <typename T>
Option<T> min(const Option<T>& left, const T& right)
{
  return min(left, Option<T>(right));
}

template <typename T>
Option<T> min(const T& left, const Option<T>& right)
{
  return min(Option<T>(left), right);
}

template <typename T>
Option<T> max(const Option<T>& left, const Option<T>& right)
{
  if (left.isSome() && right.isSome()) {
    return std::max(left.get(), right.get());
  } else if (left.isSome()) {
    return left.get();
  } else if (right.isSome()) {
    return right.get();
  } else {
    return Option<T>::none();
  }
}

template <typename T>
Option<T> max(const Option<T>& left, const T& right)
{
  return max(left, Option<T>(right));
}

template <typename T>
Option<T> max(const T& left, const Option<T>& right)
{
  return max(Option<T>(left), right);
}

namespace std {

template <typename T>
struct hash<Option<T>>
{
  typedef size_t result_type;

  typedef Option<T> argument_type;

  result_type operator()(const argument_type& option) const
  {
    size_t seed = 0;
    if (option.isSome()) {
      boost::hash_combine(seed, hash<T>()(option.get()));
    }
    return seed;
  }
};

} // namespace std {

#endif // __STOUT_OPTION_HPP__
<commit_msg>Avoided copying when possible in Option::getOrElse.<commit_after>// 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.

#ifndef __STOUT_OPTION_HPP__
#define __STOUT_OPTION_HPP__

#include <assert.h>

#include <algorithm>
#include <functional>
#include <type_traits>

#include <boost/functional/hash.hpp>

#include <stout/none.hpp>
#include <stout/some.hpp>

template <typename T>
class Option
{
public:
  static Option<T> none()
  {
    return Option<T>();
  }

  static Option<T> some(const T& t)
  {
    return Option<T>(t);
  }

  Option() : state(NONE) {}

  Option(const T& _t) : state(SOME), t(_t) {}

  Option(T&& _t) : state(SOME), t(std::move(_t)) {}

  template <
    typename U,
    typename = typename std::enable_if<
        std::is_constructible<T, const U&>::value>::type>
  Option(const U& u) : state(SOME), t(u) {}

  Option(const None&) : state(NONE) {}

  template <typename U>
  Option(const _Some<U>& some) : state(SOME), t(some.t) {}

  template <typename U>
  Option(_Some<U>&& some) : state(SOME), t(std::move(some.t)) {}

  Option(const Option<T>& that) : state(that.state)
  {
    if (that.isSome()) {
      new (&t) T(that.t);
    }
  }

  Option(Option<T>&& that)
      noexcept(std::is_nothrow_move_constructible<T>::value)
    : state(std::move(that.state))
  {
    if (that.isSome()) {
      new (&t) T(std::move(that.t));
    }
  }

  ~Option()
  {
    if (isSome()) {
      t.~T();
    }
  }

  Option<T>& operator=(const Option<T>& that)
  {
    if (this != &that) {
      if (isSome()) {
        t.~T();
      }
      state = that.state;
      if (that.isSome()) {
        new (&t) T(that.t);
      }
    }

    return *this;
  }

  Option<T>& operator=(Option<T>&& that)
      noexcept(std::is_nothrow_move_constructible<T>::value)
  {
    if (this != &that) {
      if (isSome()) {
        t.~T();
      }
      state = std::move(that.state);
      if (that.isSome()) {
        new (&t) T(std::move(that.t));
      }
    }

    return *this;
  }

  bool isSome() const { return state == SOME; }
  bool isNone() const { return state == NONE; }

  const T& get() const & { assert(isSome()); return t; }
  T& get() & { assert(isSome()); return t; }
  T&& get() && { assert(isSome()); return std::move(t); }
  const T&& get() const && { assert(isSome()); return std::move(t); }

  const T* operator->() const { return &get(); }
  T* operator->() { return &get(); }

  template <typename U>
  T getOrElse(U&& u) const &
  {
    return isNone() ? static_cast<T>(std::forward<U>(u)) : t;
  }

  template <typename U>
  T getOrElse(U&& u) &&
  {
    return isNone() ? static_cast<T>(std::forward<U>(u)) : std::move(t);
  }

  bool operator==(const Option<T>& that) const
  {
    return (isNone() && that.isNone()) ||
      (isSome() && that.isSome() && t == that.t);
  }

  bool operator!=(const Option<T>& that) const
  {
    return !(*this == that);
  }

  bool operator==(const T& that) const
  {
    return isSome() && t == that;
  }

  bool operator!=(const T& that) const
  {
    return !(*this == that);
  }

private:
  enum State
  {
    SOME,
    NONE,
  };

  State state;

  union {
    // We remove the const qualifier (if there is one) from T so that
    // we can initialize 't' from outside of the initializer list
    // using placement new. This is necessary because sometimes we
    // specialize 'Option' as such: 'Option<const T>'.
    typename std::remove_const<T>::type t;
  };
};

template <typename T>
Option<T> min(const Option<T>& left, const Option<T>& right)
{
  if (left.isSome() && right.isSome()) {
    return std::min(left.get(), right.get());
  } else if (left.isSome()) {
    return left.get();
  } else if (right.isSome()) {
    return right.get();
  } else {
    return Option<T>::none();
  }
}

template <typename T>
Option<T> min(const Option<T>& left, const T& right)
{
  return min(left, Option<T>(right));
}

template <typename T>
Option<T> min(const T& left, const Option<T>& right)
{
  return min(Option<T>(left), right);
}

template <typename T>
Option<T> max(const Option<T>& left, const Option<T>& right)
{
  if (left.isSome() && right.isSome()) {
    return std::max(left.get(), right.get());
  } else if (left.isSome()) {
    return left.get();
  } else if (right.isSome()) {
    return right.get();
  } else {
    return Option<T>::none();
  }
}

template <typename T>
Option<T> max(const Option<T>& left, const T& right)
{
  return max(left, Option<T>(right));
}

template <typename T>
Option<T> max(const T& left, const Option<T>& right)
{
  return max(Option<T>(left), right);
}

namespace std {

template <typename T>
struct hash<Option<T>>
{
  typedef size_t result_type;

  typedef Option<T> argument_type;

  result_type operator()(const argument_type& option) const
  {
    size_t seed = 0;
    if (option.isSome()) {
      boost::hash_combine(seed, hash<T>()(option.get()));
    }
    return seed;
  }
};

} // namespace std {

#endif // __STOUT_OPTION_HPP__
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkCylinderSource.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkCylinderSource.h"
#include "vtkPoints.h"
#include "vtkNormals.h"
#include "vtkTCoords.h"

vtkCylinderSource::vtkCylinderSource (int res)
{
  this->Resolution = res;
  this->Height = 1.0;
  this->Radius = 0.5;
  this->Capping = 1;
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
}

void vtkCylinderSource::Execute()
{
  float angle= 2.0*3.141592654/this->Resolution;
  int numPolys, numPts;
  float xbot[3], tcbot[2], nbot[3];
  float xtop[3], tctop[2], ntop[3];
  float *center = this->Center;
  int i, idx;
  int pts[VTK_CELL_SIZE];
  vtkPoints *newPoints;
  vtkNormals *newNormals;
  vtkTCoords *newTCoords;
  vtkCellArray *newPolys;
  vtkPolyData *output = this->GetOutput();

//
// Set things up; allocate memory
//

  if ( this->Capping )
    {
    numPts = 4*this->Resolution;
    numPolys = this->Resolution + 2;
    }
  else
    {
    numPts = 2*this->Resolution;
    numPolys = this->Resolution;
    }

  newPoints = vtkPoints::New();
  newPoints->Allocate(numPts);
  newNormals = vtkNormals::New();
  newNormals->Allocate(numPts);
  newTCoords = vtkTCoords::New();
  newTCoords->Allocate(numPts,2);

  newPolys = vtkCellArray::New();
  newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution));
//
// Generate points and point data for sides
//
  for (i=0; i<this->Resolution; i++)
    {
    // x coordinate
    xbot[0] = xtop[0] = nbot[0] = ntop[0] = this->Radius * cos((double)i*angle);
    xbot[0] += center[0]; xtop[0] += center[0];
    tcbot[0] = tctop[0] = fabs(2.0*i/this->Resolution - 1.0);

    // y coordinate
    xbot[1] = 0.5 * this->Height + center[1];
    xtop[1] = -0.5 * this->Height + center[1];
    nbot[1] = ntop[1] = 0.0;
    tcbot[1] = 0.0;
    tctop[1] = 1.0;

    // z coordinate
    xbot[2] = xtop[2] = nbot[2] = ntop[2] = -this->Radius * sin((double)i*angle);
    xbot[2] += center[2]; xtop[2] += center[2];

    idx = 2*i;
    newPoints->InsertPoint(idx,xbot);
    newPoints->InsertPoint(idx+1,xtop);
    newTCoords->InsertTCoord(idx,tcbot);
    newTCoords->InsertTCoord(idx+1,tctop);
    newNormals->InsertNormal(idx,nbot);
    newNormals->InsertNormal(idx+1,ntop);
    }
//
// Generate polygons for sides
//
  for (i=0; i<this->Resolution; i++)
    {
    pts[0] = 2*i;
    pts[1] = pts[0] + 1;
    pts[2] = (pts[1] + 2) % (2*this->Resolution);
    pts[3] = pts[2] - 1;
    newPolys->InsertNextCell(4,pts);
    }
//
// Generate points and point data for top/bottom polygons
//
  if ( this->Capping )
    {
    for (i=0; i<this->Resolution; i++)
      {
      // x coordinate
      xbot[0] = xtop[0] = this->Radius * cos((double)i*angle);
      nbot[0] = ntop[0] = 0.0;
      tcbot[0] = tctop[0] = xbot[0];
      xbot[0] += center[0]; xtop[0] += center[0];

      // y coordinate
      xbot[1] = 0.5 * this->Height;
      xtop[1] = -0.5 * this->Height;
      nbot[1] = 1.0;
      ntop[1] = -1.0;
      xbot[1] += center[1]; xtop[1] += center[1];

      // z coordinate
      xbot[2] = xtop[2] = -this->Radius * sin((double)i*angle);
      tcbot[1] = tctop[1] = xbot[2];
      xbot[2] += center[2]; xtop[2] += center[2];
      nbot[2] = 0.0;
      ntop[2] = 0.0;

      idx = 2*this->Resolution;
      newPoints->InsertPoint(idx+i,xbot);
      newTCoords->InsertTCoord(idx+i,tcbot);
      newNormals->InsertNormal(idx+i,nbot);

      idx = 3*this->Resolution;
      newPoints->InsertPoint(idx+i,xtop);
      newTCoords->InsertTCoord(idx+i,tctop);
      newNormals->InsertNormal(idx+i,ntop);
      }
//
// Generate polygons for top/bottom polygons
//
    for (i=0; i<this->Resolution; i++)
      {
      pts[i] = 2*this->Resolution + i;
      }
    newPolys->InsertNextCell(this->Resolution,pts);
    for (i=0; i<this->Resolution; i++)
      {
      pts[i] = 3*this->Resolution + i;
      }
    newPolys->InsertNextCell(this->Resolution,pts);

    } // if capping
//
// Update ourselves and release memory
//
  output->SetPoints(newPoints);
  newPoints->Delete();

  output->GetPointData()->SetNormals(newNormals);
  newNormals->Delete();

  output->GetPointData()->SetTCoords(newTCoords);
  newTCoords->Delete();

  newPolys->Squeeze(); // since we've estimated size; reclaim some space
  output->SetPolys(newPolys);
  newPolys->Delete();
}

void vtkCylinderSource::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataSource::PrintSelf(os,indent);

  os << indent << "Resolution: " << this->Resolution << "\n";
  os << indent << "Height: " << this->Height << "\n";
  os << indent << "Radius: " << this->Radius << "\n";
  os << indent << "Center: (" << this->Center[0] << ", "
     << this->Center[1] << ", " << this->Center[2] << " )\n";
  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
}
<commit_msg>ERR: top cylinder was oriented wrong.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCylinderSource.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkCylinderSource.h"
#include "vtkPoints.h"
#include "vtkNormals.h"
#include "vtkTCoords.h"

vtkCylinderSource::vtkCylinderSource (int res)
{
  this->Resolution = res;
  this->Height = 1.0;
  this->Radius = 0.5;
  this->Capping = 1;
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
}

void vtkCylinderSource::Execute()
{
  float angle= 2.0*3.141592654/this->Resolution;
  int numPolys, numPts;
  float xbot[3], tcbot[2], nbot[3];
  float xtop[3], tctop[2], ntop[3];
  float *center = this->Center;
  int i, idx;
  int pts[VTK_CELL_SIZE];
  vtkPoints *newPoints;
  vtkNormals *newNormals;
  vtkTCoords *newTCoords;
  vtkCellArray *newPolys;
  vtkPolyData *output = this->GetOutput();

//
// Set things up; allocate memory
//

  if ( this->Capping )
    {
    numPts = 4*this->Resolution;
    numPolys = this->Resolution + 2;
    }
  else
    {
    numPts = 2*this->Resolution;
    numPolys = this->Resolution;
    }

  newPoints = vtkPoints::New();
  newPoints->Allocate(numPts);
  newNormals = vtkNormals::New();
  newNormals->Allocate(numPts);
  newTCoords = vtkTCoords::New();
  newTCoords->Allocate(numPts,2);

  newPolys = vtkCellArray::New();
  newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution));
//
// Generate points and point data for sides
//
  for (i=0; i<this->Resolution; i++)
    {
    // x coordinate
    xbot[0] = xtop[0] = nbot[0] = ntop[0] = this->Radius * cos((double)i*angle);
    xbot[0] += center[0]; xtop[0] += center[0];
    tcbot[0] = tctop[0] = fabs(2.0*i/this->Resolution - 1.0);

    // y coordinate
    xbot[1] = 0.5 * this->Height + center[1];
    xtop[1] = -0.5 * this->Height + center[1];
    nbot[1] = ntop[1] = 0.0;
    tcbot[1] = 0.0;
    tctop[1] = 1.0;

    // z coordinate
    xbot[2] = xtop[2] = nbot[2] = ntop[2] = -this->Radius * sin((double)i*angle);
    xbot[2] += center[2]; xtop[2] += center[2];

    idx = 2*i;
    newPoints->InsertPoint(idx,xbot);
    newPoints->InsertPoint(idx+1,xtop);
    newTCoords->InsertTCoord(idx,tcbot);
    newTCoords->InsertTCoord(idx+1,tctop);
    newNormals->InsertNormal(idx,nbot);
    newNormals->InsertNormal(idx+1,ntop);
    }
//
// Generate polygons for sides
//
  for (i=0; i<this->Resolution; i++)
    {
    pts[0] = 2*i;
    pts[1] = pts[0] + 1;
    pts[2] = (pts[1] + 2) % (2*this->Resolution);
    pts[3] = pts[2] - 1;
    newPolys->InsertNextCell(4,pts);
    }
//
// Generate points and point data for top/bottom polygons
//
  if ( this->Capping )
    {
    for (i=0; i<this->Resolution; i++)
      {
      // x coordinate
      xbot[0] = xtop[0] = this->Radius * cos((double)i*angle);
      nbot[0] = ntop[0] = 0.0;
      tcbot[0] = tctop[0] = xbot[0];
      xbot[0] += center[0]; xtop[0] += center[0];

      // y coordinate
      xbot[1] = 0.5 * this->Height;
      xtop[1] = -0.5 * this->Height;
      nbot[1] = 1.0;
      ntop[1] = -1.0;
      xbot[1] += center[1]; xtop[1] += center[1];

      // z coordinate
      xbot[2] = xtop[2] = -this->Radius * sin((double)i*angle);
      tcbot[1] = tctop[1] = xbot[2];
      xbot[2] += center[2]; xtop[2] += center[2];
      nbot[2] = 0.0;
      ntop[2] = 0.0;

      idx = 2*this->Resolution;
      newPoints->InsertPoint(idx+i,xbot);
      newTCoords->InsertTCoord(idx+i,tcbot);
      newNormals->InsertNormal(idx+i,nbot);

      idx = 3*this->Resolution;
      newPoints->InsertPoint(idx+this->Resolution-i-1,xtop);
      newTCoords->InsertTCoord(idx+this->Resolution-i-1,tctop);
      newNormals->InsertNormal(idx+this->Resolution-i-1,ntop);
      }
//
// Generate polygons for top/bottom polygons
//
    for (i=0; i<this->Resolution; i++)
      {
      pts[i] = 2*this->Resolution + i;
      }
    newPolys->InsertNextCell(this->Resolution,pts);
    for (i=0; i<this->Resolution; i++)
      {
      pts[i] = 3*this->Resolution + i;
      }
    newPolys->InsertNextCell(this->Resolution,pts);

    } // if capping
//
// Update ourselves and release memory
//
  output->SetPoints(newPoints);
  newPoints->Delete();

  output->GetPointData()->SetNormals(newNormals);
  newNormals->Delete();

  output->GetPointData()->SetTCoords(newTCoords);
  newTCoords->Delete();

  newPolys->Squeeze(); // since we've estimated size; reclaim some space
  output->SetPolys(newPolys);
  newPolys->Delete();
}

void vtkCylinderSource::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyDataSource::PrintSelf(os,indent);

  os << indent << "Resolution: " << this->Resolution << "\n";
  os << indent << "Height: " << this->Height << "\n";
  os << indent << "Radius: " << this->Radius << "\n";
  os << indent << "Center: (" << this->Center[0] << ", "
     << this->Center[1] << ", " << this->Center[2] << " )\n";
  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
}
<|endoftext|>


<commit_before><commit_msg>Draw cicles centred as intended so that folding margin markers look correct.<commit_after><|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "maemodeployconfigurationwidget.h"
#include "ui_maemodeployconfigurationwidget.h"

#include "deploymentsettingsassistant.h"
#include "maemoglobal.h"
#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"

#include <qt4projectmanager/qt4nodes.h>
#include <remotelinux/deployablefile.h>
#include <remotelinux/deployablefilesperprofile.h>
#include <remotelinux/deploymentinfo.h>
#include <remotelinux/remotelinuxdeployconfigurationwidget.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>

#include <QtCore/QFileInfo>
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
#include <QtGui/QPixmap>
#include <QtGui/QVBoxLayout>

using namespace ProjectExplorer;
using namespace Qt4ProjectManager;

namespace RemoteLinux {
namespace Internal {

MaemoDeployConfigurationWidget::MaemoDeployConfigurationWidget(QWidget *parent)
    : DeployConfigurationWidget(parent),
      ui(new Ui::MaemoDeployConfigurationWidget),
      m_remoteLinuxWidget(new RemoteLinuxDeployConfigurationWidget)
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(m_remoteLinuxWidget);
    QWidget * const subWidget = new QWidget;
    ui->setupUi(subWidget);
    mainLayout->addWidget(subWidget);
    mainLayout->addStretch(1);

    connect(m_remoteLinuxWidget, SIGNAL(currentModelChanged(const DeployableFilesPerProFile*)),
        SLOT(handleCurrentModelChanged(const DeployableFilesPerProFile*)));
    handleCurrentModelChanged(0);
}

MaemoDeployConfigurationWidget::~MaemoDeployConfigurationWidget()
{
    delete ui;
}

void MaemoDeployConfigurationWidget::init(DeployConfiguration *dc)
{
    m_remoteLinuxWidget->init(dc);
    connect(ui->addDesktopFileButton, SIGNAL(clicked()), SLOT(addDesktopFile()));
    connect(ui->addIconButton, SIGNAL(clicked()), SLOT(addIcon()));
    connect(deployConfiguration()->deploymentInfo().data(), SIGNAL(modelAboutToBeReset()),
        SLOT(handleDeploymentInfoToBeReset()));
}

Qt4MaemoDeployConfiguration *MaemoDeployConfigurationWidget::deployConfiguration() const
{
    return qobject_cast<Qt4MaemoDeployConfiguration *>(m_remoteLinuxWidget->deployConfiguration());
}

void MaemoDeployConfigurationWidget::handleDeploymentInfoToBeReset()
{
    ui->addDesktopFileButton->setEnabled(false);
    ui->addIconButton->setEnabled(false);
}

void MaemoDeployConfigurationWidget::handleCurrentModelChanged(const DeployableFilesPerProFile *proFileInfo)
{
    ui->addDesktopFileButton->setEnabled(canAddDesktopFile(proFileInfo));
    ui->addIconButton->setEnabled(canAddIcon(proFileInfo));
}

void MaemoDeployConfigurationWidget::addDesktopFile()
{
    DeployableFilesPerProFile * const proFileInfo = m_remoteLinuxWidget->currentModel();
    QTC_ASSERT(canAddDesktopFile(proFileInfo), return);

    const QString desktopFilePath = QFileInfo(proFileInfo->proFilePath()).path()
        + QLatin1Char('/') + proFileInfo->projectName() + QLatin1String(".desktop");
    if (!QFile::exists(desktopFilePath)) {
        const QString desktopTemplate = QLatin1String("[Desktop Entry]\nEncoding=UTF-8\n"
            "Version=1.0\nType=Application\nTerminal=false\nName=%1\nExec=%2\n"
            "Icon=%1\nX-Window-Icon=\nX-HildonDesk-ShowInToolbar=true\n"
            "X-Osso-Type=application/x-executable\n");
        Utils::FileSaver saver(desktopFilePath);
        saver.write(desktopTemplate.arg(proFileInfo->projectName(),
            proFileInfo->remoteExecutableFilePath()).toUtf8());
        if (!saver.finalize(this))
            return;
    }

    DeployableFile d;
    d.remoteDir = QLatin1String("/usr/share/applications");
    if (qobject_cast<Qt4Maemo5Target *>(deployConfiguration()->target()))
        d.remoteDir += QLatin1String("/hildon");
    d.localFilePath = desktopFilePath;
    if (!deployConfiguration()->deploymentSettingsAssistant()->addDeployableToProFile(proFileInfo,
        QLatin1String("desktopfile"), d)) {
        QMessageBox::critical(this, tr("Project File Update Failed"),
            tr("Could not update the project file."));
    } else {
        ui->addDesktopFileButton->setEnabled(false);
    }
}

void MaemoDeployConfigurationWidget::addIcon()
{
    DeployableFilesPerProFile * const proFileInfo = m_remoteLinuxWidget->currentModel();
    const int iconDim = MaemoGlobal::applicationIconSize(deployConfiguration()->supportedOsType());
    const QString origFilePath = QFileDialog::getOpenFileName(this,
        tr("Choose Icon (will be scaled to %1x%1 pixels, if necessary)").arg(iconDim),
        proFileInfo->projectDir(), QLatin1String("(*.png)"));
    if (origFilePath.isEmpty())
        return;
    QPixmap pixmap(origFilePath);
    if (pixmap.isNull()) {
        QMessageBox::critical(this, tr("Invalid Icon"),
            tr("Unable to read image"));
        return;
    }
    const QSize iconSize(iconDim, iconDim);
    if (pixmap.size() != iconSize)
        pixmap = pixmap.scaled(iconSize);
    const QString newFileName = proFileInfo->projectName() + QLatin1Char('.')
        + QFileInfo(origFilePath).suffix();
    const QString newFilePath = proFileInfo->projectDir() + QLatin1Char('/') + newFileName;
    if (!pixmap.save(newFilePath)) {
        QMessageBox::critical(this, tr("Failed to Save Icon"),
            tr("Could not save icon to '%1'.").arg(newFilePath));
        return;
    }

    if (!deployConfiguration()->deploymentSettingsAssistant()->addDeployableToProFile(proFileInfo,
        QLatin1String("icon"), DeployableFile(newFilePath, remoteIconDir()))) {
        QMessageBox::critical(this, tr("Project File Update Failed"),
            tr("Could not update the project file."));
    } else {
        ui->addIconButton->setEnabled(false);
    }
}

bool MaemoDeployConfigurationWidget::canAddDesktopFile(const DeployableFilesPerProFile *proFileInfo) const
{
    return proFileInfo && proFileInfo->isApplicationProject()
        && deployConfiguration()->localDesktopFilePath(proFileInfo).isEmpty();
}

bool MaemoDeployConfigurationWidget::canAddIcon(const DeployableFilesPerProFile *proFileInfo) const
{
    return proFileInfo && proFileInfo->isApplicationProject()
        && remoteIconFilePath(proFileInfo).isEmpty();
}

QString MaemoDeployConfigurationWidget::remoteIconFilePath(const DeployableFilesPerProFile *proFileInfo) const
{
    QTC_ASSERT(proFileInfo->projectType() == ApplicationTemplate, return  QString());

    const QStringList imageTypes = QStringList() << QLatin1String("jpg") << QLatin1String("png")
        << QLatin1String("svg");
    for (int i = 0; i < proFileInfo->rowCount(); ++i) {
        const DeployableFile &d = proFileInfo->deployableAt(i);
        const QString extension = QFileInfo(d.localFilePath).suffix();
        if (d.remoteDir.startsWith(remoteIconDir()) && imageTypes.contains(extension))
            return d.remoteDir + QLatin1Char('/') + QFileInfo(d.localFilePath).fileName();
    }
    return QString();
}

QString MaemoDeployConfigurationWidget::remoteIconDir() const
{
    return QString::fromLocal8Bit("/usr/share/icons/hicolor/%1x%1/apps")
        .arg(MaemoGlobal::applicationIconSize(deployConfiguration()->supportedOsType()));
}

} // namespace Internal
} // namespace RemoteLinux
<commit_msg>MeeGo: Fix initial deployment button state.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "maemodeployconfigurationwidget.h"
#include "ui_maemodeployconfigurationwidget.h"

#include "deploymentsettingsassistant.h"
#include "maemoglobal.h"
#include "qt4maemodeployconfiguration.h"
#include "qt4maemotarget.h"

#include <qt4projectmanager/qt4nodes.h>
#include <remotelinux/deployablefile.h>
#include <remotelinux/deployablefilesperprofile.h>
#include <remotelinux/deploymentinfo.h>
#include <remotelinux/remotelinuxdeployconfigurationwidget.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>

#include <QtCore/QFileInfo>
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
#include <QtGui/QPixmap>
#include <QtGui/QVBoxLayout>

using namespace ProjectExplorer;
using namespace Qt4ProjectManager;

namespace RemoteLinux {
namespace Internal {

MaemoDeployConfigurationWidget::MaemoDeployConfigurationWidget(QWidget *parent)
    : DeployConfigurationWidget(parent),
      ui(new Ui::MaemoDeployConfigurationWidget),
      m_remoteLinuxWidget(new RemoteLinuxDeployConfigurationWidget)
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(m_remoteLinuxWidget);
    QWidget * const subWidget = new QWidget;
    ui->setupUi(subWidget);
    mainLayout->addWidget(subWidget);
    mainLayout->addStretch(1);

    connect(m_remoteLinuxWidget, SIGNAL(currentModelChanged(const DeployableFilesPerProFile*)),
        SLOT(handleCurrentModelChanged(const DeployableFilesPerProFile*)));
    handleCurrentModelChanged(m_remoteLinuxWidget->currentModel());
}

MaemoDeployConfigurationWidget::~MaemoDeployConfigurationWidget()
{
    delete ui;
}

void MaemoDeployConfigurationWidget::init(DeployConfiguration *dc)
{
    m_remoteLinuxWidget->init(dc);
    connect(ui->addDesktopFileButton, SIGNAL(clicked()), SLOT(addDesktopFile()));
    connect(ui->addIconButton, SIGNAL(clicked()), SLOT(addIcon()));
    connect(deployConfiguration()->deploymentInfo().data(), SIGNAL(modelAboutToBeReset()),
        SLOT(handleDeploymentInfoToBeReset()));
}

Qt4MaemoDeployConfiguration *MaemoDeployConfigurationWidget::deployConfiguration() const
{
    return qobject_cast<Qt4MaemoDeployConfiguration *>(m_remoteLinuxWidget->deployConfiguration());
}

void MaemoDeployConfigurationWidget::handleDeploymentInfoToBeReset()
{
    ui->addDesktopFileButton->setEnabled(false);
    ui->addIconButton->setEnabled(false);
}

void MaemoDeployConfigurationWidget::handleCurrentModelChanged(const DeployableFilesPerProFile *proFileInfo)
{
    ui->addDesktopFileButton->setEnabled(canAddDesktopFile(proFileInfo));
    ui->addIconButton->setEnabled(canAddIcon(proFileInfo));
}

void MaemoDeployConfigurationWidget::addDesktopFile()
{
    DeployableFilesPerProFile * const proFileInfo = m_remoteLinuxWidget->currentModel();
    QTC_ASSERT(canAddDesktopFile(proFileInfo), return);

    const QString desktopFilePath = QFileInfo(proFileInfo->proFilePath()).path()
        + QLatin1Char('/') + proFileInfo->projectName() + QLatin1String(".desktop");
    if (!QFile::exists(desktopFilePath)) {
        const QString desktopTemplate = QLatin1String("[Desktop Entry]\nEncoding=UTF-8\n"
            "Version=1.0\nType=Application\nTerminal=false\nName=%1\nExec=%2\n"
            "Icon=%1\nX-Window-Icon=\nX-HildonDesk-ShowInToolbar=true\n"
            "X-Osso-Type=application/x-executable\n");
        Utils::FileSaver saver(desktopFilePath);
        saver.write(desktopTemplate.arg(proFileInfo->projectName(),
            proFileInfo->remoteExecutableFilePath()).toUtf8());
        if (!saver.finalize(this))
            return;
    }

    DeployableFile d;
    d.remoteDir = QLatin1String("/usr/share/applications");
    if (qobject_cast<Qt4Maemo5Target *>(deployConfiguration()->target()))
        d.remoteDir += QLatin1String("/hildon");
    d.localFilePath = desktopFilePath;
    if (!deployConfiguration()->deploymentSettingsAssistant()->addDeployableToProFile(proFileInfo,
        QLatin1String("desktopfile"), d)) {
        QMessageBox::critical(this, tr("Project File Update Failed"),
            tr("Could not update the project file."));
    } else {
        ui->addDesktopFileButton->setEnabled(false);
    }
}

void MaemoDeployConfigurationWidget::addIcon()
{
    DeployableFilesPerProFile * const proFileInfo = m_remoteLinuxWidget->currentModel();
    const int iconDim = MaemoGlobal::applicationIconSize(deployConfiguration()->supportedOsType());
    const QString origFilePath = QFileDialog::getOpenFileName(this,
        tr("Choose Icon (will be scaled to %1x%1 pixels, if necessary)").arg(iconDim),
        proFileInfo->projectDir(), QLatin1String("(*.png)"));
    if (origFilePath.isEmpty())
        return;
    QPixmap pixmap(origFilePath);
    if (pixmap.isNull()) {
        QMessageBox::critical(this, tr("Invalid Icon"),
            tr("Unable to read image"));
        return;
    }
    const QSize iconSize(iconDim, iconDim);
    if (pixmap.size() != iconSize)
        pixmap = pixmap.scaled(iconSize);
    const QString newFileName = proFileInfo->projectName() + QLatin1Char('.')
        + QFileInfo(origFilePath).suffix();
    const QString newFilePath = proFileInfo->projectDir() + QLatin1Char('/') + newFileName;
    if (!pixmap.save(newFilePath)) {
        QMessageBox::critical(this, tr("Failed to Save Icon"),
            tr("Could not save icon to '%1'.").arg(newFilePath));
        return;
    }

    if (!deployConfiguration()->deploymentSettingsAssistant()->addDeployableToProFile(proFileInfo,
        QLatin1String("icon"), DeployableFile(newFilePath, remoteIconDir()))) {
        QMessageBox::critical(this, tr("Project File Update Failed"),
            tr("Could not update the project file."));
    } else {
        ui->addIconButton->setEnabled(false);
    }
}

bool MaemoDeployConfigurationWidget::canAddDesktopFile(const DeployableFilesPerProFile *proFileInfo) const
{
    return proFileInfo && proFileInfo->isApplicationProject()
        && deployConfiguration()->localDesktopFilePath(proFileInfo).isEmpty();
}

bool MaemoDeployConfigurationWidget::canAddIcon(const DeployableFilesPerProFile *proFileInfo) const
{
    return proFileInfo && proFileInfo->isApplicationProject()
        && remoteIconFilePath(proFileInfo).isEmpty();
}

QString MaemoDeployConfigurationWidget::remoteIconFilePath(const DeployableFilesPerProFile *proFileInfo) const
{
    QTC_ASSERT(proFileInfo->projectType() == ApplicationTemplate, return  QString());

    const QStringList imageTypes = QStringList() << QLatin1String("jpg") << QLatin1String("png")
        << QLatin1String("svg");
    for (int i = 0; i < proFileInfo->rowCount(); ++i) {
        const DeployableFile &d = proFileInfo->deployableAt(i);
        const QString extension = QFileInfo(d.localFilePath).suffix();
        if (d.remoteDir.startsWith(remoteIconDir()) && imageTypes.contains(extension))
            return d.remoteDir + QLatin1Char('/') + QFileInfo(d.localFilePath).fileName();
    }
    return QString();
}

QString MaemoDeployConfigurationWidget::remoteIconDir() const
{
    return QString::fromLocal8Bit("/usr/share/icons/hicolor/%1x%1/apps")
        .arg(MaemoGlobal::applicationIconSize(deployConfiguration()->supportedOsType()));
}

} // namespace Internal
} // namespace RemoteLinux
<|endoftext|>