<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */

/**
 * @author Matthew Hoyt (mhoyt@ca.ibm.com)
 */

#if !defined(XALANDEQUE_HEADER_GUARD_1357924680)
#define XALANDEQUE_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanMemoryManagement.hpp>

XALAN_CPP_NAMESPACE_BEGIN

template <class Value>
struct XalanDequeIteratorTraits
{
	typedef Value	        value_type;
	typedef Value&	        reference;
	typedef Value*	        pointer;
    typedef const Value&    const_reference;
};

template <class Value>
struct XalanDequeConstIteratorTraits
{
	typedef Value	        value_type;
	typedef const Value&	reference;
	typedef const Value*	pointer;
    typedef const Value&	const_reference;
};

template <class XalanDequeTraits, class XalanDeque>
struct  XalanDequeIterator
{
    typedef size_t  size_type;
    typedef typename XalanDequeTraits::value_type       value_type;
    typedef typename XalanDequeTraits::reference        reference;
    typedef typename XalanDequeTraits::pointer          pointer;
    typedef typename XalanDequeTraits::const_reference  const_reference;
    typedef ptrdiff_t		                            difference_type;

    typedef XalanDequeIterator<XalanDequeIteratorTraits<value_type>, XalanDeque> Iterator;

	typedef XALAN_STD_QUALIFIER random_access_iterator_tag iterator_category;

    XalanDequeIterator(XalanDeque*  deque,
                       size_type    pos) :
        m_deque(deque),
        m_pos(pos)
    {
    }

    XalanDequeIterator(const Iterator & iterator) :
        m_deque(iterator.m_deque),
        m_pos(iterator.m_pos)
    {
    }

    XalanDequeIterator& operator=(const Iterator & iterator)
    {
        m_deque = iterator.m_deque;
        m_pos = iterator.m_pos;
        return *this;
    }

    XalanDequeIterator& operator++()
    {
        ++m_pos;
        return *this;
    }

    XalanDequeIterator operator++(int)
    {
        XalanDequeIterator temp = *this;
        ++m_pos;
        return temp;
    }

    XalanDequeIterator& operator--()
    {
        --m_pos;
        return *this;
    }

    pointer operator->()
    {
        return &(*m_deque[m_pos]);
    }

    reference operator*()
    {
        return (*m_deque)[m_pos];
    }

    const_reference operator*() const
    {
        return (*m_deque)[m_pos];
    }

    XalanDequeIterator operator+(difference_type difference) const
    {
        return XalanDequeIterator(m_deque, m_pos + difference);
    }

    XalanDequeIterator operator-(difference_type difference) const
    {
        return XalanDequeIterator(m_deque, m_pos - difference);
    }

    difference_type operator-(const XalanDequeIterator &theRhs) const
    {
        return m_pos - theRhs.m_pos;
    }

    bool operator==(const XalanDequeIterator & theRhs) const
    {
        return (theRhs.m_deque == m_deque)
            &&  theRhs.m_pos == m_pos;
    }

    bool operator!=(const XalanDequeIterator & theRhs) const
    {
        return !(theRhs == *this);
    }

    XalanDeque* m_deque;
    size_type   m_pos;
};

/**
 * Xalan implementation of deque
 */
template <class Type, class ConstructionTraits = MemoryManagedConstructionTraits<Type> >
class XalanDeque
{
public:

    typedef size_t  size_type;

    typedef Type            value_type;
    typedef Type&           reference;
    typedef const Type&     const_reference;

    typedef XalanVector<Type, ConstructionTraits>	    BlockType;

    typedef XalanVector<BlockType*> BlockIndexType;

    typedef XalanDequeIterator<XalanDequeIteratorTraits<value_type>, XalanDeque> iterator;
    typedef XalanDequeIterator<XalanDequeConstIteratorTraits<value_type>, XalanDeque> const_iterator;

#if defined(XALAN_HAS_STD_ITERATORS)
    typedef XALAN_STD_QUALIFIER reverse_iterator<iterator>          reverse_iterator_;
    typedef XALAN_STD_QUALIFIER reverse_iterator<const_iterator>    const_reverse_iterator_;
#elif defined(XALAN_RW_NO_CLASS_PARTIAL_SPEC)
    typedef XALAN_STD_QUALIFIER reverse_iterator<
        iterator,
        XALAN_STD_QUALIFIER random_access_iterator_tag,
        value_type> reverse_iterator_;
    typedef XALAN_STD_QUALIFIER reverse_iterator<
        const_iterator,
        XALAN_STD_QUALIFIER random_access_iterator_tag,
        const value_type> const_reverse_iterator_;
#else
    typedef XALAN_STD_QUALIFIER reverse_iterator<iterator, value_type>                          reverse_iterator_;
    typedef XALAN_STD_QUALIFIER reverse_iterator<const_iterator, value_type, const_reference>   const_reverse_iterator_;
#endif

    typedef reverse_iterator_           reverse_iterator;
    typedef const_reverse_iterator_     const_reverse_iterator;

    XalanDeque(
    		MemoryManagerType& memoryManager,
            size_type initialSize = 0,
            size_type blockSize = 10) :
        m_memoryManager(&memoryManager),
        m_blockSize(blockSize),
        m_blockIndex(memoryManager,
                    initialSize / blockSize + (initialSize % blockSize == 0 ? 0 : 1)),
        m_freeBlockVector(memoryManager)
    {
        typename ConstructionTraits::Constructor::ConstructableType defaultValue(*m_memoryManager);

        XALAN_STD_QUALIFIER fill_n(XALAN_STD_QUALIFIER back_inserter(*this), initialSize, defaultValue.value);
    }

    XalanDeque(const XalanDeque& theRhs, MemoryManagerType& memoryManager) :
        m_memoryManager(&memoryManager),
        m_blockSize(theRhs.m_blockSize),
        m_blockIndex(*theRhs.m_memoryManager,
                    theRhs.size() / theRhs.m_blockSize + (theRhs.size() % theRhs.m_blockSize == 0 ? 0 : 1)),
        m_freeBlockVector(memoryManager)
    {
        XALAN_STD_QUALIFIER copy(theRhs.begin(), theRhs.end(), XALAN_STD_QUALIFIER back_inserter(*this));
    }

   static XalanDeque*
   create(
            MemoryManagerType&  theManager,
            size_type initialSize = 0,
            size_type blockSize = 10)
    {
        typedef XalanDeque ThisType;

        XalanMemMgrAutoPtr<ThisType, false> theGuard( theManager , (ThisType*)theManager.allocate(sizeof(ThisType)));

        ThisType* theResult = theGuard.get();

        new (theResult) ThisType(theManager, initialSize, blockSize);

        theGuard.release();

        return theResult;
    }

    ~XalanDeque()
    {
        clear();
        typename BlockIndexType::iterator iter = m_freeBlockVector.begin();

        while (iter != m_freeBlockVector.end())
        {
            (*iter)->~XalanVector<Type, ConstructionTraits>();
            deallocate(*iter);
            ++iter;
        }
    }

    iterator begin()
    {
        return iterator(this, 0);
    }

    const_iterator begin() const
    {
        return const_iterator(const_cast<XalanDeque*>(this), 0);
    }

    iterator end()
    {
        return iterator(this, size());
    }

    const_iterator end() const
    {
         return const_iterator(const_cast<XalanDeque*>(this), size());
    }

    const_reverse_iterator rbegin() const
    {
        return const_reverse_iterator(end());
    }

    const_reverse_iterator rend() const
    {
        return const_reverse_iterator(begin());
    }

    bool empty() const
    {
        return m_blockIndex.empty();
    }

    size_type size() const
    {
       if (m_blockIndex.empty())
       {
           return 0;
       }
       else
       {
           return (m_blockIndex.size() - 1) * m_blockSize
               +  m_blockIndex.back()->size();
       }
    }

    value_type& back()
    {
        return m_blockIndex.back()->back();
    }

    value_type& operator[](size_type index)
    {
        BlockType & block = *(m_blockIndex[index / m_blockSize]);
        return block[index % m_blockSize];
    }

    const value_type& operator[](size_type index) const
    {
        BlockType & block = *(m_blockIndex[index / m_blockSize]);
        return block[index % m_blockSize];
    }

    void clear()
    {
        typename BlockIndexType::iterator iter = m_blockIndex.begin();

        m_freeBlockVector.reserve(m_freeBlockVector.size() + m_blockIndex.size());

        while (iter != m_blockIndex.end())
        {
            (*iter)->clear();
            m_freeBlockVector.push_back(*iter);
            ++iter;
        }

        m_blockIndex.clear();
    }

    void push_back(const value_type & value)
    {
        if (m_blockIndex.empty() ||
            m_blockIndex.back()->size() >= m_blockSize)
        {
            m_blockIndex.push_back(getNewBlock());
        }

        m_blockIndex.back()->push_back(value);
    }

    void pop_back()
    {
        BlockType & lastBlock = *(m_blockIndex.back());
        lastBlock.pop_back();
        if (lastBlock.empty())
        {
            m_freeBlockVector.push_back(&lastBlock);
            m_blockIndex.pop_back();
        }
    }

    void resize(size_type newSize)
    {
        typename ConstructionTraits::Constructor::ConstructableType defaultValue(*m_memoryManager);
        if (newSize > size())
        {
            for (size_type i = 0; i < newSize - size(); ++i)
            {
                push_back(defaultValue.value);
            }
        }
        else
        {
            for (size_type i = 0; i < size() - newSize; ++i)
            {
                pop_back();
            }
        }
    }

    void swap(XalanDeque& theRhs)
    {
        MemoryManagerType* tempMemoryManager = m_memoryManager;
        m_memoryManager = theRhs.m_memoryManager;
        theRhs.m_memoryManager = tempMemoryManager;

        theRhs.m_blockIndex.swap(m_blockIndex);
        theRhs.m_freeBlockVector.swap(m_freeBlockVector);
    }

    XalanDeque & operator=(const XalanDeque & theRhs)
    {
        clear();
        XALAN_STD_QUALIFIER copy(theRhs.begin(), theRhs.end(), XALAN_STD_QUALIFIER back_inserter(*this));
        return *this;
    }

    MemoryManagerType&
    getMemoryManager()
    {
        assert (m_memoryManager != 0);

        return *m_memoryManager;
    }
protected:

    BlockType* getNewBlock()
    {
        BlockType * newBlock;

        if (m_freeBlockVector.empty())
        {
            newBlock = allocate(1);
            new (&*newBlock) BlockType(*m_memoryManager, m_blockSize);
        }
        else
        {
            newBlock = m_freeBlockVector.back();
            m_freeBlockVector.pop_back();
        }

        assert (newBlock != 0);

        return newBlock;
    }

    BlockType*
    allocate(size_type  size)
    {
        const size_type     theBytesNeeded = size * sizeof(BlockType);

        BlockType* pointer = (BlockType*)m_memoryManager->allocate(theBytesNeeded);

        assert(pointer != 0);

        return pointer;
     }

    void
    deallocate(BlockType*  pointer)
    {
    	m_memoryManager->deallocate(pointer);
    }

    MemoryManagerType*  m_memoryManager;
    const size_type     m_blockSize;

    BlockIndexType     m_blockIndex;
    BlockIndexType     m_freeBlockVector;

private:
	// Not implemented
	XalanDeque();
	XalanDeque(const XalanDeque&);

};

XALAN_CPP_NAMESPACE_END

#endif  // XALANDEQUE_HEADER_GUARD_1357924680

<commit_msg>Fix to enable build on BC++B6<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */

/**
 * @author Matthew Hoyt (mhoyt@ca.ibm.com)
 */

#if !defined(XALANDEQUE_HEADER_GUARD_1357924680)
#define XALANDEQUE_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanMemoryManagement.hpp>

XALAN_CPP_NAMESPACE_BEGIN

template <class Value>
struct XalanDequeIteratorTraits
{
	typedef Value	        value_type;
	typedef Value&	        reference;
	typedef Value*	        pointer;
    typedef const Value&    const_reference;
};

template <class Value>
struct XalanDequeConstIteratorTraits
{
	typedef Value	        value_type;
	typedef const Value&	reference;
	typedef const Value*	pointer;
    typedef const Value&	const_reference;
};

template <class XalanDequeTraits, class XalanDeque>
struct  XalanDequeIterator
{
    typedef size_t  size_type;
    typedef typename XalanDequeTraits::value_type       value_type;
    typedef typename XalanDequeTraits::reference        reference;
    typedef typename XalanDequeTraits::pointer          pointer;
    typedef typename XalanDequeTraits::const_reference  const_reference;
    typedef ptrdiff_t		                            difference_type;

    typedef XalanDequeIterator<XalanDequeIteratorTraits<value_type>, XalanDeque> Iterator;

	typedef XALAN_STD_QUALIFIER random_access_iterator_tag iterator_category;

    XalanDequeIterator(XalanDeque*  deque,
                       size_type    pos) :
        m_deque(deque),
        m_pos(pos)
    {
    }

    XalanDequeIterator(const Iterator & iterator) :
        m_deque(iterator.m_deque),
        m_pos(iterator.m_pos)
    {
    }

    XalanDequeIterator& operator=(const Iterator & iterator)
    {
        m_deque = iterator.m_deque;
        m_pos = iterator.m_pos;
        return *this;
    }

    XalanDequeIterator& operator++()
    {
        ++m_pos;
        return *this;
    }

    XalanDequeIterator operator++(int)
    {
        XalanDequeIterator temp = *this;
        ++m_pos;
        return temp;
    }

    XalanDequeIterator& operator--()
    {
        --m_pos;
        return *this;
    }

    pointer operator->()
    {
        return &(*m_deque[m_pos]);
    }

    reference operator*()
    {
        return (*m_deque)[m_pos];
    }

    const_reference operator*() const
    {
        return (*m_deque)[m_pos];
    }

    XalanDequeIterator operator+(difference_type difference) const
    {
        return XalanDequeIterator(m_deque, m_pos + difference);
    }

    XalanDequeIterator operator-(difference_type difference) const
    {
        return XalanDequeIterator(m_deque, m_pos - difference);
    }

    difference_type operator-(const XalanDequeIterator &theRhs) const
    {
        return m_pos - theRhs.m_pos;
    }

    bool operator==(const XalanDequeIterator & theRhs) const
    {
        return (theRhs.m_deque == m_deque)
            &&  theRhs.m_pos == m_pos;
    }

    bool operator!=(const XalanDequeIterator & theRhs) const
    {
        return !(theRhs == *this);
    }

    XalanDeque* m_deque;
    size_type   m_pos;
};

/**
 * Xalan implementation of deque
 */
template <class Type, class ConstructionTraits = MemoryManagedConstructionTraits<Type> >
class XalanDeque
{
public:

    typedef size_t  size_type;

    typedef Type            value_type;
    typedef Type&           reference;
    typedef const Type&     const_reference;

    typedef XalanVector<Type, ConstructionTraits>	    BlockType;

    typedef XalanVector<BlockType*> BlockIndexType;

    typedef XalanDeque<Type, ConstructionTraits>							ThisType;
    typedef XalanDequeIterator<XalanDequeIteratorTraits<value_type>, ThisType> 		iterator;
    typedef XalanDequeIterator<XalanDequeConstIteratorTraits<value_type>, ThisType> 	const_iterator;

#if defined(XALAN_HAS_STD_ITERATORS)
    typedef XALAN_STD_QUALIFIER reverse_iterator<iterator>          reverse_iterator_;
    typedef XALAN_STD_QUALIFIER reverse_iterator<const_iterator>    const_reverse_iterator_;
#elif defined(XALAN_RW_NO_CLASS_PARTIAL_SPEC)
    typedef XALAN_STD_QUALIFIER reverse_iterator<
        iterator,
        XALAN_STD_QUALIFIER random_access_iterator_tag,
        value_type> reverse_iterator_;
    typedef XALAN_STD_QUALIFIER reverse_iterator<
        const_iterator,
        XALAN_STD_QUALIFIER random_access_iterator_tag,
        const value_type> const_reverse_iterator_;
#else
    typedef XALAN_STD_QUALIFIER reverse_iterator<iterator, value_type>                          reverse_iterator_;
    typedef XALAN_STD_QUALIFIER reverse_iterator<const_iterator, value_type, const_reference>   const_reverse_iterator_;
#endif

    typedef reverse_iterator_           reverse_iterator;
    typedef const_reverse_iterator_     const_reverse_iterator;

    XalanDeque(
    		MemoryManagerType& memoryManager,
            size_type initialSize = 0,
            size_type blockSize = 10) :
        m_memoryManager(&memoryManager),
        m_blockSize(blockSize),
        m_blockIndex(memoryManager,
                    initialSize / blockSize + (initialSize % blockSize == 0 ? 0 : 1)),
        m_freeBlockVector(memoryManager)
    {
        typename ConstructionTraits::Constructor::ConstructableType defaultValue(*m_memoryManager);

        XALAN_STD_QUALIFIER fill_n(XALAN_STD_QUALIFIER back_inserter(*this), initialSize, defaultValue.value);
    }

    XalanDeque(const XalanDeque& theRhs, MemoryManagerType& memoryManager) :
        m_memoryManager(&memoryManager),
        m_blockSize(theRhs.m_blockSize),
        m_blockIndex(*theRhs.m_memoryManager,
                    theRhs.size() / theRhs.m_blockSize + (theRhs.size() % theRhs.m_blockSize == 0 ? 0 : 1)),
        m_freeBlockVector(memoryManager)
    {
        XALAN_STD_QUALIFIER copy(theRhs.begin(), theRhs.end(), XALAN_STD_QUALIFIER back_inserter(*this));
    }

   static XalanDeque*
   create(
            MemoryManagerType&  theManager,
            size_type initialSize = 0,
            size_type blockSize = 10)
    {
        typedef XalanDeque ThisType;

        XalanMemMgrAutoPtr<ThisType, false> theGuard( theManager , (ThisType*)theManager.allocate(sizeof(ThisType)));

        ThisType* theResult = theGuard.get();

        new (theResult) ThisType(theManager, initialSize, blockSize);

        theGuard.release();

        return theResult;
    }

    ~XalanDeque()
    {
        clear();
        typename BlockIndexType::iterator iter = m_freeBlockVector.begin();

        while (iter != m_freeBlockVector.end())
        {
            (*iter)->~XalanVector<Type, ConstructionTraits>();
            deallocate(*iter);
            ++iter;
        }
    }

    iterator begin()
    {
        return iterator(this, 0);
    }

    const_iterator begin() const
    {
        return const_iterator(const_cast<XalanDeque*>(this), 0);
    }

    iterator end()
    {
        return iterator(this, size());
    }

    const_iterator end() const
    {
         return const_iterator(const_cast<XalanDeque*>(this), size());
    }

    const_reverse_iterator rbegin() const
    {
        return const_reverse_iterator(end());
    }

    const_reverse_iterator rend() const
    {
        return const_reverse_iterator(begin());
    }

    bool empty() const
    {
        return m_blockIndex.empty();
    }

    size_type size() const
    {
       if (m_blockIndex.empty())
       {
           return 0;
       }
       else
       {
           return (m_blockIndex.size() - 1) * m_blockSize
               +  m_blockIndex.back()->size();
       }
    }

    value_type& back()
    {
        return m_blockIndex.back()->back();
    }

    value_type& operator[](size_type index)
    {
        BlockType & block = *(m_blockIndex[index / m_blockSize]);
        return block[index % m_blockSize];
    }

    const value_type& operator[](size_type index) const
    {
        BlockType & block = *(m_blockIndex[index / m_blockSize]);
        return block[index % m_blockSize];
    }

    void clear()
    {
        typename BlockIndexType::iterator iter = m_blockIndex.begin();

        m_freeBlockVector.reserve(m_freeBlockVector.size() + m_blockIndex.size());

        while (iter != m_blockIndex.end())
        {
            (*iter)->clear();
            m_freeBlockVector.push_back(*iter);
            ++iter;
        }

        m_blockIndex.clear();
    }

    void push_back(const value_type & value)
    {
        if (m_blockIndex.empty() ||
            m_blockIndex.back()->size() >= m_blockSize)
        {
            m_blockIndex.push_back(getNewBlock());
        }

        m_blockIndex.back()->push_back(value);
    }

    void pop_back()
    {
        BlockType & lastBlock = *(m_blockIndex.back());
        lastBlock.pop_back();
        if (lastBlock.empty())
        {
            m_freeBlockVector.push_back(&lastBlock);
            m_blockIndex.pop_back();
        }
    }

    void resize(size_type newSize)
    {
        typename ConstructionTraits::Constructor::ConstructableType defaultValue(*m_memoryManager);
        if (newSize > size())
        {
            for (size_type i = 0; i < newSize - size(); ++i)
            {
                push_back(defaultValue.value);
            }
        }
        else
        {
            for (size_type i = 0; i < size() - newSize; ++i)
            {
                pop_back();
            }
        }
    }

    void swap(XalanDeque& theRhs)
    {
        MemoryManagerType* tempMemoryManager = m_memoryManager;
        m_memoryManager = theRhs.m_memoryManager;
        theRhs.m_memoryManager = tempMemoryManager;

        theRhs.m_blockIndex.swap(m_blockIndex);
        theRhs.m_freeBlockVector.swap(m_freeBlockVector);
    }

    XalanDeque & operator=(const XalanDeque & theRhs)
    {
        clear();
        XALAN_STD_QUALIFIER copy(theRhs.begin(), theRhs.end(), XALAN_STD_QUALIFIER back_inserter(*this));
        return *this;
    }

    MemoryManagerType&
    getMemoryManager()
    {
        assert (m_memoryManager != 0);

        return *m_memoryManager;
    }
protected:

    BlockType* getNewBlock()
    {
        BlockType * newBlock;

        if (m_freeBlockVector.empty())
        {
            newBlock = allocate(1);
            new (&*newBlock) BlockType(*m_memoryManager, m_blockSize);
        }
        else
        {
            newBlock = m_freeBlockVector.back();
            m_freeBlockVector.pop_back();
        }

        assert (newBlock != 0);

        return newBlock;
    }

    BlockType*
    allocate(size_type  size)
    {
        const size_type     theBytesNeeded = size * sizeof(BlockType);

        BlockType* pointer = (BlockType*)m_memoryManager->allocate(theBytesNeeded);

        assert(pointer != 0);

        return pointer;
     }

    void
    deallocate(BlockType*  pointer)
    {
    	m_memoryManager->deallocate(pointer);
    }

    MemoryManagerType*  m_memoryManager;
    const size_type     m_blockSize;

    BlockIndexType     m_blockIndex;
    BlockIndexType     m_freeBlockVector;

private:
	// Not implemented
	XalanDeque();
	XalanDeque(const XalanDeque&);

};

XALAN_CPP_NAMESPACE_END

#endif  // XALANDEQUE_HEADER_GUARD_1357924680

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "kitmodel.h"

#include "kit.h"
#include "kitmanagerconfigwidget.h"
#include "kitmanager.h"

#include <coreplugin/coreconstants.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>

#include <QApplication>
#include <QLayout>

using namespace Utils;

namespace ProjectExplorer {
namespace Internal {

class KitNode : public TreeItem
{
public:
    KitNode(Kit *k)
    {
        widget = KitManager::createConfigWidget(k);
        if (widget) {
            if (k && k->isAutoDetected())
                widget->makeStickySubWidgetsReadOnly();
            widget->setVisible(false);
        }
    }

    ~KitNode()
    {
        delete widget;
    }

    QVariant data(int, int role) const
    {
        static QIcon warningIcon(QString::fromLatin1(Core::Constants::ICON_WARNING));
        static QIcon errorIcon(QString::fromLatin1(Core::Constants::ICON_ERROR));

        if (widget) {
            if (role == Qt::FontRole) {
                QFont f = QApplication::font();
                if (widget->isDirty())
                    f.setBold(!f.bold());
                if (widget->isDefaultKit())
                    f.setItalic(f.style() != QFont::StyleItalic);
                return f;
            }
            if (role == Qt::DisplayRole) {
                QString baseName = widget->displayName();
                if (widget->isDefaultKit())
                    //: Mark up a kit as the default one.
                    baseName = KitModel::tr("%1 (default)").arg(baseName);
                return baseName;
            }
            if (role == Qt::DecorationRole) {
                if (!widget->isValid())
                    return errorIcon;
                if (widget->hasWarning())
                    return warningIcon;
                return QIcon();
            }
            if (role == Qt::ToolTipRole) {
                return widget->validityMessage();
            }
        }
        return QVariant();
    }

    KitManagerConfigWidget *widget;
};

// --------------------------------------------------------------------------
// KitModel
// --------------------------------------------------------------------------

KitModel::KitModel(QBoxLayout *parentLayout, QObject *parent) :
    TreeModel(parent),
    m_parentLayout(parentLayout),
    m_defaultNode(0),
    m_keepUnique(true)
{
    auto root = new TreeItem(QStringList(tr("Name")));
    m_autoRoot = new TreeItem(QStringList(tr("Auto-detected")));
    m_manualRoot = new TreeItem(QStringList(tr("Manual")));
    root->appendChild(m_autoRoot);
    root->appendChild(m_manualRoot);
    setRootItem(root);

    foreach (Kit *k, KitManager::sortedKits())
        addKit(k);

    changeDefaultKit();

    connect(KitManager::instance(), &KitManager::kitAdded,
            this, &KitModel::addKit);
    connect(KitManager::instance(), &KitManager::kitUpdated,
            this, &KitModel::updateKit);
    connect(KitManager::instance(), &KitManager::unmanagedKitUpdated,
            this, &KitModel::updateKit);
    connect(KitManager::instance(), &KitManager::kitRemoved,
            this, &KitModel::removeKit);
    connect(KitManager::instance(), &KitManager::defaultkitChanged,
            this, &KitModel::changeDefaultKit);
}

Kit *KitModel::kit(const QModelIndex &index)
{
    KitNode *n = kitNode(index);
    return n ? n->widget->workingCopy() : 0;
}

KitNode *KitModel::kitNode(const QModelIndex &index)
{
    TreeItem *n = itemFromIndex(index);
    return n && n->level() == 2 ? static_cast<KitNode *>(n) : 0;
}

QModelIndex KitModel::indexOf(Kit *k) const
{
    KitNode *n = findWorkingCopy(k);
    return indexFromItem(n);
}

void KitModel::setDefaultKit(const QModelIndex &index)
{
    if (KitNode *n = kitNode(index))
        setDefaultNode(n);
}

bool KitModel::isDefaultKit(Kit *k) const
{
    return m_defaultNode && m_defaultNode->widget->workingCopy() == k;
}

KitManagerConfigWidget *KitModel::widget(const QModelIndex &index)
{
    KitNode *n = kitNode(index);
    return n ? n->widget : 0;
}

void KitModel::validateKitNames()
{
    QHash<QString, int> nameHash;
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        const QString displayName = n->widget->displayName();
        if (nameHash.contains(displayName))
            ++nameHash[displayName];
        else
            nameHash.insert(displayName, 1);
    }

    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        const QString displayName = n->widget->displayName();
        n->widget->setHasUniqueName(nameHash.value(displayName) == 1);
    }
}

void KitModel::apply()
{
    // Remove unused kits:
    foreach (KitNode *n, m_toRemoveList)
        n->widget->removeKit();

    // Update kits:
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->isDirty()) {
            n->widget->apply();
            n->update();
        }
    }

    layoutChanged(); // Force update.
}

void KitModel::markForRemoval(Kit *k)
{
    KitNode *node = findWorkingCopy(k);
    if (!node)
        return;

    if (node == m_defaultNode) {
        TreeItem *newDefault = m_autoRoot->firstChild();
        if (!newDefault)
            newDefault = m_manualRoot->firstChild();
        setDefaultNode(static_cast<KitNode *>(newDefault));
    }

    removeItem(node);
    if (node->widget->configures(0))
        delete node;
    else
        m_toRemoveList.append(node);
}

Kit *KitModel::markForAddition(Kit *baseKit)
{
    KitNode *node = createNode(0);
    m_manualRoot->appendChild(node);
    Kit *k = node->widget->workingCopy();
    KitGuard g(k);
    if (baseKit) {
        k->copyFrom(baseKit);
        k->setAutoDetected(false); // Make sure we have a manual kit!
        k->setSdkProvided(false);
        k->setUnexpandedDisplayName(tr("Clone of %1").arg(k->unexpandedDisplayName()));
    } else {
        k->setup();
    }

    if (!m_defaultNode)
        setDefaultNode(node);

    return k;
}

KitNode *KitModel::findWorkingCopy(Kit *k) const
{
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->workingCopy() == k)
            return n;
    }
    return 0;
}

KitNode *KitModel::createNode(Kit *k)
{
    KitNode *node = new KitNode(k);
    m_parentLayout->addWidget(node->widget);
    connect(node->widget, &KitManagerConfigWidget::dirty, [node] {
        node->update();
    });
    return node;
}

void KitModel::setDefaultNode(KitNode *node)
{
    if (m_defaultNode) {
        m_defaultNode->widget->setIsDefaultKit(false);
        m_defaultNode->update();
    }
    m_defaultNode = node;
    if (m_defaultNode) {
        m_defaultNode->widget->setIsDefaultKit(true);
        m_defaultNode->update();
    }
}

void KitModel::addKit(Kit *k)
{
    foreach (TreeItem *n, m_manualRoot->children()) {
        // Was added by us
        if (static_cast<KitNode *>(n)->widget->configures(k))
            return;
    }

    TreeItem *parent = k->isAutoDetected() ? m_autoRoot : m_manualRoot;
    parent->appendChild(createNode(k));

    validateKitNames();
    emit kitStateChanged();
}

void KitModel::updateKit(Kit *)
{
    validateKitNames();
    emit kitStateChanged();
}

void KitModel::removeKit(Kit *k)
{
    QList<KitNode *> nodes = m_toRemoveList;
    foreach (KitNode *n, nodes) {
        if (n->widget->configures(k)) {
            m_toRemoveList.removeOne(n);
            if (m_defaultNode == n)
                m_defaultNode = 0;
            delete n;
            return;
        }
    }

    KitNode *node = 0;
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->configures(k)) {
            node = n;
            break;
        }
    }

    if (m_defaultNode == node)
        m_defaultNode = 0;
    removeItem(node);
    delete node;

    validateKitNames();
    emit kitStateChanged();
}

void KitModel::changeDefaultKit()
{
    Kit *defaultKit = KitManager::defaultKit();
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->configures(defaultKit)) {
            setDefaultNode(n);
            return;
        }
    }
}

} // namespace Internal
} // namespace ProjectExplorer
<commit_msg>KitModel: Fix crash on removing kits introduced in 7fd21d22a<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "kitmodel.h"

#include "kit.h"
#include "kitmanagerconfigwidget.h"
#include "kitmanager.h"

#include <coreplugin/coreconstants.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>

#include <QApplication>
#include <QLayout>

using namespace Utils;

namespace ProjectExplorer {
namespace Internal {

class KitNode : public TreeItem
{
public:
    KitNode(Kit *k)
    {
        widget = KitManager::createConfigWidget(k);
        if (widget) {
            if (k && k->isAutoDetected())
                widget->makeStickySubWidgetsReadOnly();
            widget->setVisible(false);
        }
    }

    ~KitNode()
    {
        delete widget;
    }

    QVariant data(int, int role) const
    {
        static QIcon warningIcon(QString::fromLatin1(Core::Constants::ICON_WARNING));
        static QIcon errorIcon(QString::fromLatin1(Core::Constants::ICON_ERROR));

        if (widget) {
            if (role == Qt::FontRole) {
                QFont f = QApplication::font();
                if (widget->isDirty())
                    f.setBold(!f.bold());
                if (widget->isDefaultKit())
                    f.setItalic(f.style() != QFont::StyleItalic);
                return f;
            }
            if (role == Qt::DisplayRole) {
                QString baseName = widget->displayName();
                if (widget->isDefaultKit())
                    //: Mark up a kit as the default one.
                    baseName = KitModel::tr("%1 (default)").arg(baseName);
                return baseName;
            }
            if (role == Qt::DecorationRole) {
                if (!widget->isValid())
                    return errorIcon;
                if (widget->hasWarning())
                    return warningIcon;
                return QIcon();
            }
            if (role == Qt::ToolTipRole) {
                return widget->validityMessage();
            }
        }
        return QVariant();
    }

    KitManagerConfigWidget *widget;
};

// --------------------------------------------------------------------------
// KitModel
// --------------------------------------------------------------------------

KitModel::KitModel(QBoxLayout *parentLayout, QObject *parent) :
    TreeModel(parent),
    m_parentLayout(parentLayout),
    m_defaultNode(0),
    m_keepUnique(true)
{
    auto root = new TreeItem(QStringList(tr("Name")));
    m_autoRoot = new TreeItem(QStringList(tr("Auto-detected")));
    m_manualRoot = new TreeItem(QStringList(tr("Manual")));
    root->appendChild(m_autoRoot);
    root->appendChild(m_manualRoot);
    setRootItem(root);

    foreach (Kit *k, KitManager::sortedKits())
        addKit(k);

    changeDefaultKit();

    connect(KitManager::instance(), &KitManager::kitAdded,
            this, &KitModel::addKit);
    connect(KitManager::instance(), &KitManager::kitUpdated,
            this, &KitModel::updateKit);
    connect(KitManager::instance(), &KitManager::unmanagedKitUpdated,
            this, &KitModel::updateKit);
    connect(KitManager::instance(), &KitManager::kitRemoved,
            this, &KitModel::removeKit);
    connect(KitManager::instance(), &KitManager::defaultkitChanged,
            this, &KitModel::changeDefaultKit);
}

Kit *KitModel::kit(const QModelIndex &index)
{
    KitNode *n = kitNode(index);
    return n ? n->widget->workingCopy() : 0;
}

KitNode *KitModel::kitNode(const QModelIndex &index)
{
    TreeItem *n = itemFromIndex(index);
    return n && n->level() == 2 ? static_cast<KitNode *>(n) : 0;
}

QModelIndex KitModel::indexOf(Kit *k) const
{
    KitNode *n = findWorkingCopy(k);
    return indexFromItem(n);
}

void KitModel::setDefaultKit(const QModelIndex &index)
{
    if (KitNode *n = kitNode(index))
        setDefaultNode(n);
}

bool KitModel::isDefaultKit(Kit *k) const
{
    return m_defaultNode && m_defaultNode->widget->workingCopy() == k;
}

KitManagerConfigWidget *KitModel::widget(const QModelIndex &index)
{
    KitNode *n = kitNode(index);
    return n ? n->widget : 0;
}

void KitModel::validateKitNames()
{
    QHash<QString, int> nameHash;
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        const QString displayName = n->widget->displayName();
        if (nameHash.contains(displayName))
            ++nameHash[displayName];
        else
            nameHash.insert(displayName, 1);
    }

    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        const QString displayName = n->widget->displayName();
        n->widget->setHasUniqueName(nameHash.value(displayName) == 1);
    }
}

void KitModel::apply()
{
    // Remove unused kits:
    foreach (KitNode *n, m_toRemoveList)
        n->widget->removeKit();

    // Update kits:
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->isDirty()) {
            n->widget->apply();
            n->update();
        }
    }

    layoutChanged(); // Force update.
}

void KitModel::markForRemoval(Kit *k)
{
    KitNode *node = findWorkingCopy(k);
    if (!node)
        return;

    if (node == m_defaultNode) {
        TreeItem *newDefault = m_autoRoot->firstChild();
        if (!newDefault)
            newDefault = m_manualRoot->firstChild();
        setDefaultNode(static_cast<KitNode *>(newDefault));
    }

    removeItem(node);
    if (node->widget->configures(0))
        delete node;
    else
        m_toRemoveList.append(node);
}

Kit *KitModel::markForAddition(Kit *baseKit)
{
    KitNode *node = createNode(0);
    m_manualRoot->appendChild(node);
    Kit *k = node->widget->workingCopy();
    KitGuard g(k);
    if (baseKit) {
        k->copyFrom(baseKit);
        k->setAutoDetected(false); // Make sure we have a manual kit!
        k->setSdkProvided(false);
        k->setUnexpandedDisplayName(tr("Clone of %1").arg(k->unexpandedDisplayName()));
    } else {
        k->setup();
    }

    if (!m_defaultNode)
        setDefaultNode(node);

    return k;
}

KitNode *KitModel::findWorkingCopy(Kit *k) const
{
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->workingCopy() == k)
            return n;
    }
    return 0;
}

KitNode *KitModel::createNode(Kit *k)
{
    KitNode *node = new KitNode(k);
    m_parentLayout->addWidget(node->widget);
    connect(node->widget, &KitManagerConfigWidget::dirty, [this, node] {
        if (m_autoRoot->children().contains(node)
                || m_manualRoot->children().contains(node))
            node->update();
    });
    return node;
}

void KitModel::setDefaultNode(KitNode *node)
{
    if (m_defaultNode) {
        m_defaultNode->widget->setIsDefaultKit(false);
        m_defaultNode->update();
    }
    m_defaultNode = node;
    if (m_defaultNode) {
        m_defaultNode->widget->setIsDefaultKit(true);
        m_defaultNode->update();
    }
}

void KitModel::addKit(Kit *k)
{
    foreach (TreeItem *n, m_manualRoot->children()) {
        // Was added by us
        if (static_cast<KitNode *>(n)->widget->configures(k))
            return;
    }

    TreeItem *parent = k->isAutoDetected() ? m_autoRoot : m_manualRoot;
    parent->appendChild(createNode(k));

    validateKitNames();
    emit kitStateChanged();
}

void KitModel::updateKit(Kit *)
{
    validateKitNames();
    emit kitStateChanged();
}

void KitModel::removeKit(Kit *k)
{
    QList<KitNode *> nodes = m_toRemoveList;
    foreach (KitNode *n, nodes) {
        if (n->widget->configures(k)) {
            m_toRemoveList.removeOne(n);
            if (m_defaultNode == n)
                m_defaultNode = 0;
            delete n;
            return;
        }
    }

    KitNode *node = 0;
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->configures(k)) {
            node = n;
            break;
        }
    }

    if (m_defaultNode == node)
        m_defaultNode = 0;
    removeItem(node);
    delete node;

    validateKitNames();
    emit kitStateChanged();
}

void KitModel::changeDefaultKit()
{
    Kit *defaultKit = KitManager::defaultKit();
    foreach (KitNode *n, treeLevelItems<KitNode *>(2)) {
        if (n->widget->configures(defaultKit)) {
            setDefaultNode(n);
            return;
        }
    }
}

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


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2010      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "signals.h"
#include "MonavPlugin.h"
#include "MonavRunner.h"
#include "MarbleDirs.h"
#include "MarbleDebug.h"
#include "GeoDataLatLonBox.h"
#include "GeoDataParser.h"
#include "GeoDataDocument.h"

#include <QtCore/QProcess>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtCore/QTimer>
#include <QtNetwork/QLocalSocket>

#include <unistd.h>

namespace Marble
{

class MonavMap
{
public:
    QDir m_directory;

    GeoDataLatLonBox m_boundingBox;

    QVector<GeoDataLinearRing> m_tiles;

    void setDirectory( const QDir &dir );

    bool containsPoint( const GeoDataCoordinates &point ) const;

private:
    void parseBoundingBox( const QFileInfo &file );
};

class MonavPluginPrivate
{
public:
    QDir m_mapDir;

    QVector<MonavMap> m_maps;

    bool m_ownsServer;

    MonavPluginPrivate();

    ~MonavPluginPrivate();

    bool startDaemon();

    void stopDaemon();

    bool isDaemonRunning() const;

    void loadMaps();

    static bool bordersFirst( const MonavMap &first, const MonavMap &second );

private:
    void loadMap( const QString &path );
};

void MonavMap::setDirectory( const QDir &dir )
{
    m_directory = dir;
    QFileInfo boundingBox( dir, dir.dirName() + ".kml" );
    if ( boundingBox.exists() ) {
        parseBoundingBox( boundingBox );
    } else {
        mDebug() << "No monav bounding box given for " << boundingBox.absoluteFilePath();
    }
}

void MonavMap::parseBoundingBox( const QFileInfo &file )
{
    GeoDataLineString points;
    QFile input( file.absoluteFilePath() );
    if ( input.open( QFile::ReadOnly ) ) {
        GeoDataParser parser( GeoData_KML );
        if ( !parser.read( &input ) ) {
            mDebug() << "Could not parse file: " << parser.errorString();
            return;
        }

        GeoDocument *doc = parser.releaseDocument();
        GeoDataDocument *document = dynamic_cast<GeoDataDocument*>( doc );
        QVector<GeoDataPlacemark*> placemarks = document->placemarkList();
        if ( placemarks.size() == 1 ) {
            GeoDataPlacemark* placemark = placemarks.first();
            GeoDataMultiGeometry* geometry = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() );
            for ( int i=0; geometry && i<geometry->size(); ++i ) {
                GeoDataLinearRing* poly = dynamic_cast<GeoDataLinearRing*>( geometry->child( i ) );
                if ( poly ) {
                    for ( int j=0; j<poly->size(); ++j ) {
                        points << poly->at( j );
                    }
                    m_tiles.push_back( *poly );
                }
            }
        } else {
            mDebug() << "File " << file.absoluteFilePath() << " does not contain one placemark, but " << placemarks.size();
        }
    }
    m_boundingBox = points.latLonAltBox();
}

bool MonavMap::containsPoint( const GeoDataCoordinates &point ) const
{
    // If we do not have a bounding box at all, we err on the safe side
    if ( m_tiles.isEmpty() ) {
        return true;
    }

    // Quick check for performance reasons
    if ( !m_boundingBox.contains( point ) ) {
        return false;
    }

    foreach( const GeoDataLinearRing &box, m_tiles ) {
        if ( box.contains( point ) ) {
            return true;
        }
    }

    return false;
}

MonavPluginPrivate::MonavPluginPrivate() : m_ownsServer( false )
{
    // nothing to do
}

MonavPluginPrivate::~MonavPluginPrivate()
{
    stopDaemon();
}

bool MonavPluginPrivate::isDaemonRunning() const
{
    QLocalSocket socket;
    socket.connectToServer( "MoNavD" );
    return socket.waitForConnected();
}

bool MonavPluginPrivate::startDaemon()
{
    if ( !isDaemonRunning() ) {
        QProcess process;
        if ( process.startDetached( "MoNavD" ) ) {
            m_ownsServer = true;

            // Give MoNavD up to one second to set up its server
            // Without that, the first route request would fail
            for ( int i = 0; i < 10; ++i ) {
                if ( isDaemonRunning() ) {
                    break;
                }
                usleep( 100 * 1000 );
            }

            return true;
        }

        return false;
    }

    return true;
}

void MonavPluginPrivate::stopDaemon()
{
    if ( m_ownsServer ) {
        m_ownsServer = false;
        QProcess process;
        process.startDetached( "MoNavD", QStringList() << "-t" );
    }
}

void MonavPluginPrivate::loadMaps()
{
    QString base = MarbleDirs::localPath() + "/maps/earth/monav/";
    loadMap( base );
    QDir::Filters filters = QDir::AllDirs | QDir::Readable | QDir::NoDotAndDotDot;
    QDirIterator::IteratorFlags flags = QDirIterator::Subdirectories | QDirIterator::FollowSymlinks;
    QDirIterator iter( base, filters, flags );
    while ( iter.hasNext() ) {
        iter.next();
        loadMap( iter.filePath() );
    }
    // Prefer maps where bounding boxes are known
    qSort( m_maps.begin(), m_maps.end(), MonavPluginPrivate::bordersFirst );
}

void MonavPluginPrivate::loadMap( const QString &path )
{
    QDir mapDir( path );
    QFileInfo pluginsFile( mapDir, "plugins.ini" );
    if ( pluginsFile.exists() ) {
        MonavMap map;
        map.setDirectory( mapDir );
        m_maps.append( map );
    }
}

bool MonavPluginPrivate::bordersFirst( const MonavMap &first, const MonavMap &second )
{
    if ( !first.m_tiles.isEmpty() && second.m_tiles.isEmpty() ) {
        return true;
    }

    if ( first.m_tiles.isEmpty() && !second.m_tiles.isEmpty() ) {
        return false;
    }

    return first.m_directory.absolutePath() < second.m_directory.absolutePath();
}

MonavPlugin::MonavPlugin( QObject *parent ) : RunnerPlugin( parent ), d( new MonavPluginPrivate )
{
    setSupportedCelestialBodies( QStringList() << "earth" );
    setCanWorkOffline( true );
    setName( tr( "Monav" ) );
    setNameId( "monav" );
    setDescription( tr( "Retrieves routes from monav" ) );
    setGuiString( tr( "Monav Routing" ) );

    // Check installation
    d->loadMaps();
    bool const haveMap = !d->m_maps.isEmpty();
    setCapabilities( haveMap ? Routing /*| ReverseGeocoding */ : None );
}

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

MarbleAbstractRunner* MonavPlugin::newRunner() const
{
    if ( !d->startDaemon() ) {
        mDebug() << "Failed to connect to MoNavD daemon";
    }

    return new MonavRunner( this );
}

QString MonavPlugin::mapDirectoryForRequest( RouteRequest* request ) const
{
    for ( int j=0; j<d->m_maps.size(); ++j ) {
        bool containsAllPoints = true;
        for ( int i = 0; i < request->size(); ++i ) {
            GeoDataCoordinates via = request->at( i );
            if ( !d->m_maps[j].containsPoint( via ) ) {
                containsAllPoints = false;
                break;
            }
        }

        if ( containsAllPoints ) {
            if ( j ) {
                // Subsequent route requests will likely be in the same country
                qSwap( d->m_maps[0], d->m_maps[j] );
            }
            // mDebug() << "Using " << d->m_maps.first().m_directory.dirName() << " as monav map";
            return d->m_maps.first().m_directory.absolutePath();
        }
    }

    return QString();
}

}

Q_EXPORT_PLUGIN2( MonavPlugin, Marble::MonavPlugin )

#include "MonavPlugin.moc"
<commit_msg>Change sort order of maps from hasBBox/name to hasBBox/area. This has the advantage that smaller maps are automatically preferred, which is useful for overlapping maps (e.g. baden-wurttemberg vs germany vs europe) to prefer the smaller map and only fall back to the larger (slower) one if really needed.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2010      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "signals.h"
#include "MonavPlugin.h"
#include "MonavRunner.h"
#include "MarbleDirs.h"
#include "MarbleDebug.h"
#include "GeoDataLatLonBox.h"
#include "GeoDataParser.h"
#include "GeoDataDocument.h"

#include <QtCore/QProcess>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtCore/QTimer>
#include <QtNetwork/QLocalSocket>

#include <unistd.h>

namespace Marble
{

class MonavMap
{
public:
    QDir m_directory;

    GeoDataLatLonBox m_boundingBox;

    QVector<GeoDataLinearRing> m_tiles;

    void setDirectory( const QDir &dir );

    bool containsPoint( const GeoDataCoordinates &point ) const;

private:
    void parseBoundingBox( const QFileInfo &file );
};

class MonavPluginPrivate
{
public:
    QDir m_mapDir;

    QVector<MonavMap> m_maps;

    bool m_ownsServer;

    MonavPluginPrivate();

    ~MonavPluginPrivate();

    bool startDaemon();

    void stopDaemon();

    bool isDaemonRunning() const;

    void loadMaps();

    static bool areaLessThan( const MonavMap &first, const MonavMap &second );

private:
    void loadMap( const QString &path );
};

void MonavMap::setDirectory( const QDir &dir )
{
    m_directory = dir;
    QFileInfo boundingBox( dir, dir.dirName() + ".kml" );
    if ( boundingBox.exists() ) {
        parseBoundingBox( boundingBox );
    } else {
        mDebug() << "No monav bounding box given for " << boundingBox.absoluteFilePath();
    }
}

void MonavMap::parseBoundingBox( const QFileInfo &file )
{
    GeoDataLineString points;
    QFile input( file.absoluteFilePath() );
    if ( input.open( QFile::ReadOnly ) ) {
        GeoDataParser parser( GeoData_KML );
        if ( !parser.read( &input ) ) {
            mDebug() << "Could not parse file: " << parser.errorString();
            return;
        }

        GeoDocument *doc = parser.releaseDocument();
        GeoDataDocument *document = dynamic_cast<GeoDataDocument*>( doc );
        QVector<GeoDataPlacemark*> placemarks = document->placemarkList();
        if ( placemarks.size() == 1 ) {
            GeoDataPlacemark* placemark = placemarks.first();
            GeoDataMultiGeometry* geometry = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() );
            for ( int i=0; geometry && i<geometry->size(); ++i ) {
                GeoDataLinearRing* poly = dynamic_cast<GeoDataLinearRing*>( geometry->child( i ) );
                if ( poly ) {
                    for ( int j=0; j<poly->size(); ++j ) {
                        points << poly->at( j );
                    }
                    m_tiles.push_back( *poly );
                }
            }
        } else {
            mDebug() << "File " << file.absoluteFilePath() << " does not contain one placemark, but " << placemarks.size();
        }
    }
    m_boundingBox = points.latLonAltBox();
}

bool MonavMap::containsPoint( const GeoDataCoordinates &point ) const
{
    // If we do not have a bounding box at all, we err on the safe side
    if ( m_tiles.isEmpty() ) {
        return true;
    }

    // Quick check for performance reasons
    if ( !m_boundingBox.contains( point ) ) {
        return false;
    }

    foreach( const GeoDataLinearRing &box, m_tiles ) {
        if ( box.contains( point ) ) {
            return true;
        }
    }

    return false;
}

MonavPluginPrivate::MonavPluginPrivate() : m_ownsServer( false )
{
    // nothing to do
}

MonavPluginPrivate::~MonavPluginPrivate()
{
    stopDaemon();
}

bool MonavPluginPrivate::isDaemonRunning() const
{
    QLocalSocket socket;
    socket.connectToServer( "MoNavD" );
    return socket.waitForConnected();
}

bool MonavPluginPrivate::startDaemon()
{
    if ( !isDaemonRunning() ) {
        QProcess process;
        if ( process.startDetached( "MoNavD" ) ) {
            m_ownsServer = true;

            // Give MoNavD up to one second to set up its server
            // Without that, the first route request would fail
            for ( int i = 0; i < 10; ++i ) {
                if ( isDaemonRunning() ) {
                    break;
                }
                usleep( 100 * 1000 );
            }

            return true;
        }

        return false;
    }

    return true;
}

void MonavPluginPrivate::stopDaemon()
{
    if ( m_ownsServer ) {
        m_ownsServer = false;
        QProcess process;
        process.startDetached( "MoNavD", QStringList() << "-t" );
    }
}

void MonavPluginPrivate::loadMaps()
{
    QString base = MarbleDirs::localPath() + "/maps/earth/monav/";
    loadMap( base );
    QDir::Filters filters = QDir::AllDirs | QDir::Readable | QDir::NoDotAndDotDot;
    QDirIterator::IteratorFlags flags = QDirIterator::Subdirectories | QDirIterator::FollowSymlinks;
    QDirIterator iter( base, filters, flags );
    while ( iter.hasNext() ) {
        iter.next();
        loadMap( iter.filePath() );
    }
    // Prefer maps where bounding boxes are known
    qSort( m_maps.begin(), m_maps.end(), MonavPluginPrivate::areaLessThan );
}

void MonavPluginPrivate::loadMap( const QString &path )
{
    QDir mapDir( path );
    QFileInfo pluginsFile( mapDir, "plugins.ini" );
    if ( pluginsFile.exists() ) {
        MonavMap map;
        map.setDirectory( mapDir );
        m_maps.append( map );
    }
}

bool MonavPluginPrivate::areaLessThan( const MonavMap &first, const MonavMap &second )
{
    if ( !first.m_tiles.isEmpty() && second.m_tiles.isEmpty() ) {
        return true;
    }

    if ( first.m_tiles.isEmpty() && !second.m_tiles.isEmpty() ) {
        return false;
    }

    qreal const areaOne = first.m_boundingBox.width() * first.m_boundingBox.height();
    qreal const areaTwo = second.m_boundingBox.width() * second.m_boundingBox.height();
    return areaOne < areaTwo;
}

MonavPlugin::MonavPlugin( QObject *parent ) : RunnerPlugin( parent ), d( new MonavPluginPrivate )
{
    setSupportedCelestialBodies( QStringList() << "earth" );
    setCanWorkOffline( true );
    setName( tr( "Monav" ) );
    setNameId( "monav" );
    setDescription( tr( "Retrieves routes from monav" ) );
    setGuiString( tr( "Monav Routing" ) );

    // Check installation
    d->loadMaps();
    bool const haveMap = !d->m_maps.isEmpty();
    setCapabilities( haveMap ? Routing /*| ReverseGeocoding */ : None );
}

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

MarbleAbstractRunner* MonavPlugin::newRunner() const
{
    if ( !d->startDaemon() ) {
        mDebug() << "Failed to connect to MoNavD daemon";
    }

    return new MonavRunner( this );
}

QString MonavPlugin::mapDirectoryForRequest( RouteRequest* request ) const
{
    for ( int j=0; j<d->m_maps.size(); ++j ) {
        bool containsAllPoints = true;
        for ( int i = 0; i < request->size(); ++i ) {
            GeoDataCoordinates via = request->at( i );
            if ( !d->m_maps[j].containsPoint( via ) ) {
                containsAllPoints = false;
                break;
            }
        }

        if ( containsAllPoints ) {
            if ( j ) {
                // Subsequent route requests will likely be in the same country
                qSwap( d->m_maps[0], d->m_maps[j] );
            }
            // mDebug() << "Using " << d->m_maps.first().m_directory.dirName() << " as monav map";
            return d->m_maps.first().m_directory.absolutePath();
        }
    }

    return QString();
}

}

Q_EXPORT_PLUGIN2( MonavPlugin, Marble::MonavPlugin )

#include "MonavPlugin.moc"
<|endoftext|>


<commit_before>#include "RRealtimeTimer.h"
#include "RScopedPointer.h"
#include "RIsr.h"
#include "RThread.h"

#define RREALTIME_TIMER_WAIT_PASS(code) \
  while(pdPASS != (code)) \
  { \
    RThread::yieldCurrentThread(); \
  }

static const int32_t sMaxDelayMS = static_cast<int32_t>(portMAX_DELAY) *
                                   portTICK_PERIOD_MS;

RRealtimeTimer::RRealtimeTimer()
  : mHandle(NULL)
  , mIsSingleShot(false)
  , mExtended(0)
#if (configUSE_16_BIT_TICKS == 1)
  , mExtendedCounter(0)
#endif
{
  // NOTE: Set timer run as idle task by default, but we can't set interval to
  // zero, otherwise the created timer will return to NULL, so we give value 1 .
  mHandle = xTimerCreate(
    "",
    1,
    pdFALSE,                           // one-shot timer
    reinterpret_cast<void *>(0),
    _callback
    );

  vTimerSetTimerID(mHandle, this);
}

RRealtimeTimer::~RRealtimeTimer()
{
  RREALTIME_TIMER_WAIT_PASS(xTimerDelete(mHandle, portMAX_DELAY));
}

int32_t
RRealtimeTimer::interval() const
{
  return static_cast<int32_t>(xTimerGetPeriod(mHandle)) * portTICK_PERIOD_MS
#if (configUSE_16_BIT_TICKS == 1)
         * (mExtended + 1)
#endif
  ;
}

bool
RRealtimeTimer::isActive() const
{
  return xTimerIsTimerActive(mHandle);
}

bool
RRealtimeTimer::isSingleShot() const
{
  return mIsSingleShot;
}

void
RRealtimeTimer::setInterval(int32_t msec)
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtended = static_cast<uint8_t>(msec / sMaxDelayMS);

  // A little trick to generate a fixed delay value, so that we needs not to
  // store the remainder
  msec /= (mExtended + 1);
#endif

  msec /= portTICK_PERIOD_MS;

  if(msec <= 0)
  {
    msec = 1;
  }

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerChangePeriodFromISR(mHandle, static_cast<rtime>(msec),
                              &xHigherPriorityTaskWoken);

    // xTimerChangePeriod will cause timer start, so we need to stop it
    // immediately
    xHigherPriorityTaskWoken = pdFALSE;
    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else if(RThread::currentThreadId() == xTimerGetTimerDaemonTaskHandle())
  {
    xTimerChangePeriod(mHandle, static_cast<rtime>(msec), 0);
    xTimerStop(mHandle, 0);
  }
  else
  {
    RREALTIME_TIMER_WAIT_PASS(xTimerChangePeriod(
                                mHandle, static_cast<rtime>(msec),
                                portMAX_DELAY));
    RREALTIME_TIMER_WAIT_PASS(xTimerStop(mHandle, portMAX_DELAY));
  }
}

void
RRealtimeTimer::setSingleShot(bool singleShot)
{
  mIsSingleShot = singleShot;
}

int
RRealtimeTimer::timerId() const
{
  // WARNING: We shorten handle to id value, but it may lead duplicate id values.
  return rShortenPtr(pvTimerGetTimerID(mHandle));
}

void
RRealtimeTimer::start()
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtendedCounter.store(mExtended);
#endif

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStartFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else if(RThread::currentThreadId() == xTimerGetTimerDaemonTaskHandle())
  {
    xTimerStart(mHandle, 0);
  }
  else
  {
    RREALTIME_TIMER_WAIT_PASS(xTimerStart(mHandle, portMAX_DELAY));
  }
}

void
RRealtimeTimer::start(int32_t msec)
{
  setInterval(msec);
  start();
}

void
RRealtimeTimer::stop()
{
  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else if(RThread::currentThreadId() == xTimerGetTimerDaemonTaskHandle())
  {
    xTimerStop(mHandle, 0);
  }
  else
  {
    RREALTIME_TIMER_WAIT_PASS(xTimerStop(mHandle, portMAX_DELAY));
  }
}

void
RRealtimeTimer::run()
{
}

bool
RRealtimeTimer::_isRestartFromCallback()
{
  return true;
}

void
RRealtimeTimer::_redirectEvents()
{
}

void
RRealtimeTimer::_callback(TimerHandle_t handle)
{
  auto self = static_cast<RRealtimeTimer *>(pvTimerGetTimerID(handle));

#if (configUSE_16_BIT_TICKS == 1)

  if(self->mExtendedCounter.addIfLargeThan(0, -1))
  {
    // Do not use a block time if calling a timer API function from a
    // timer callback function, as doing so could cause a deadlock!
    xTimerStart(self->mHandle, 0);
    return;
  }

#endif

  if(self->_isRestartFromCallback())
  {
    self->run();
  }
  else
  {
    // Do restart action inside event loop
    self->_redirectEvents();
    return;
  }

  if(self->isSingleShot())
  {
    return;
  }

  xTimerStart(self->mHandle, 0);
}
<commit_msg>Only compile freertos RRealtimeTimer when R_OS_FREERTOS defined<commit_after>#ifdef R_OS_FREERTOS

#include "RRealtimeTimer.h"
#include "RScopedPointer.h"
#include "RIsr.h"
#include "RThread.h"

#define RREALTIME_TIMER_WAIT_PASS(code) \
  while(pdPASS != (code)) \
  { \
    RThread::yieldCurrentThread(); \
  }

static const int32_t sMaxDelayMS = static_cast<int32_t>(portMAX_DELAY) *
                                   portTICK_PERIOD_MS;

RRealtimeTimer::RRealtimeTimer()
  : mHandle(NULL)
  , mIsSingleShot(false)
  , mExtended(0)
#if (configUSE_16_BIT_TICKS == 1)
  , mExtendedCounter(0)
#endif
{
  // NOTE: Set timer run as idle task by default, but we can't set interval to
  // zero, otherwise the created timer will return to NULL, so we give value 1 .
  mHandle = xTimerCreate(
    "",
    1,
    pdFALSE,                           // one-shot timer
    reinterpret_cast<void *>(0),
    _callback
    );

  vTimerSetTimerID(mHandle, this);
}

RRealtimeTimer::~RRealtimeTimer()
{
  RREALTIME_TIMER_WAIT_PASS(xTimerDelete(mHandle, portMAX_DELAY));
}

int32_t
RRealtimeTimer::interval() const
{
  return static_cast<int32_t>(xTimerGetPeriod(mHandle)) * portTICK_PERIOD_MS
#if (configUSE_16_BIT_TICKS == 1)
         * (mExtended + 1)
#endif
  ;
}

bool
RRealtimeTimer::isActive() const
{
  return xTimerIsTimerActive(mHandle);
}

bool
RRealtimeTimer::isSingleShot() const
{
  return mIsSingleShot;
}

void
RRealtimeTimer::setInterval(int32_t msec)
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtended = static_cast<uint8_t>(msec / sMaxDelayMS);

  // A little trick to generate a fixed delay value, so that we needs not to
  // store the remainder
  msec /= (mExtended + 1);
#endif

  msec /= portTICK_PERIOD_MS;

  if(msec <= 0)
  {
    msec = 1;
  }

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerChangePeriodFromISR(mHandle, static_cast<rtime>(msec),
                              &xHigherPriorityTaskWoken);

    // xTimerChangePeriod will cause timer start, so we need to stop it
    // immediately
    xHigherPriorityTaskWoken = pdFALSE;
    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else if(RThread::currentThreadId() == xTimerGetTimerDaemonTaskHandle())
  {
    xTimerChangePeriod(mHandle, static_cast<rtime>(msec), 0);
    xTimerStop(mHandle, 0);
  }
  else
  {
    RREALTIME_TIMER_WAIT_PASS(xTimerChangePeriod(
                                mHandle, static_cast<rtime>(msec),
                                portMAX_DELAY));
    RREALTIME_TIMER_WAIT_PASS(xTimerStop(mHandle, portMAX_DELAY));
  }
}

void
RRealtimeTimer::setSingleShot(bool singleShot)
{
  mIsSingleShot = singleShot;
}

int
RRealtimeTimer::timerId() const
{
  // WARNING: We shorten handle to id value, but it may lead duplicate id values.
  return rShortenPtr(pvTimerGetTimerID(mHandle));
}

void
RRealtimeTimer::start()
{
#if (configUSE_16_BIT_TICKS == 1)
  mExtendedCounter.store(mExtended);
#endif

  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStartFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else if(RThread::currentThreadId() == xTimerGetTimerDaemonTaskHandle())
  {
    xTimerStart(mHandle, 0);
  }
  else
  {
    RREALTIME_TIMER_WAIT_PASS(xTimerStart(mHandle, portMAX_DELAY));
  }
}

void
RRealtimeTimer::start(int32_t msec)
{
  setInterval(msec);
  start();
}

void
RRealtimeTimer::stop()
{
  if(_rIsrExecuting())
  {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xTimerStopFromISR(mHandle, &xHigherPriorityTaskWoken);
  }
  else if(RThread::currentThreadId() == xTimerGetTimerDaemonTaskHandle())
  {
    xTimerStop(mHandle, 0);
  }
  else
  {
    RREALTIME_TIMER_WAIT_PASS(xTimerStop(mHandle, portMAX_DELAY));
  }
}

void
RRealtimeTimer::run()
{
}

bool
RRealtimeTimer::_isRestartFromCallback()
{
  return true;
}

void
RRealtimeTimer::_redirectEvents()
{
}

void
RRealtimeTimer::_callback(TimerHandle_t handle)
{
  auto self = static_cast<RRealtimeTimer *>(pvTimerGetTimerID(handle));

#if (configUSE_16_BIT_TICKS == 1)

  if(self->mExtendedCounter.addIfLargeThan(0, -1))
  {
    // Do not use a block time if calling a timer API function from a
    // timer callback function, as doing so could cause a deadlock!
    xTimerStart(self->mHandle, 0);
    return;
  }

#endif

  if(self->_isRestartFromCallback())
  {
    self->run();
  }
  else
  {
    // Do restart action inside event loop
    self->_redirectEvents();
    return;
  }

  if(self->isSingleShot())
  {
    return;
  }

  xTimerStart(self->mHandle, 0);
}

#endif // #ifdef R_OS_FREERTOS
<|endoftext|>


<commit_before>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include <opencv2/core/core.hpp>
#include <map>

#include "../../matlab/profiling.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver) : errorGraph(100, "Difference")
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	std::map<int, cv::Scalar> colors;
	colors[0] = cv::Scalar(0, 255, 0);
	colors[1] = cv::Scalar(0, 255, 255);
	colors[2] = cv::Scalar(255, 0, 255);
	errorGraph.setColors(colors);

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;
	int emptyCount = 0;

	while (!stop) {
		std::vector<CameraData> data = dequeue();

		if (data.size() > 1) {
			emptyCount = 0;

			if (!receivedFirstPosition) {
				receivedFirstPosition = true;
				ROS_INFO("Found quadcopter %d", data[0].quadcopterId);
			}

			// ROS_DEBUG("Got info from camera %d: [%.2f, %.2f, %.2f]", data[0].camNo, data[0].cameraVector.getV1(), data[0].cameraVector.getV2(), data[0].cameraVector.getV3());

			double latency = 0;
			double currentTime = getNanoTime();

			for (std::vector<CameraData>::iterator it = data.begin(); it != data.end(); it++) {
				double newLatency = currentTime - it->time;

				if (newLatency > latency) {
					latency = newLatency;
				}
			}

			ROS_DEBUG("Latency is %.3fms", latency / 1e6);

			Vector position = tracker.updatePosition(data);

			for (size_t i = 0; i < data.size(); i++) {
				errorGraph.nextPoint(tracker.getDistance(), data[i].camNo);
			}

			if (position.isValid()) {
				// Invert x axis for controller
				// position.setV1(-position.getV1());

				std::vector<Vector> positions;
				std::vector<int> ids;
				std::vector<int> updates;
				positions.push_back(position);
				ids.push_back(data[0].quadcopterId);
				updates.push_back(1);

				receiver->updatePositions(positions, ids, updates);
			}
		} else if (receivedFirstPosition) {
			emptyCount++;

			if (emptyCount == 50) {
				// TODO uncomment
				ROS_WARN("Position update buffer is empty!");
				emptyCount = 0;
			}

			boost::mutex::scoped_lock lock(queueMutex);
			queueEmpty.wait(lock);
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId, long int time)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;
	data.time = time;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	enqueue(data);
}

void TrackingWorker::enqueue(CameraData data)
{
	boost::mutex::scoped_lock lock(queueMutex);

	queue.enqueue(data);

	queueEmpty.notify_all();
}

std::vector<CameraData> TrackingWorker::dequeue()
{
	boost::mutex::scoped_lock lock(queueMutex);

	if (!dataAvailable()) {
		queueEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
	}

	if (dataAvailable()) {
		return queue.dequeue();
	} else {
		return std::vector<CameraData>();
	}
}

bool TrackingWorker::dataAvailable()
{
	return queue.dataAvailable();
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}

Vector TrackingWorker::getCameraPosition(int camNo)
{
	return tracker.getPosition(camNo);
}

Matrix TrackingWorker::getRotationMatrix(int camNo)
{
	return tracker.getRotationMatrix(camNo);
}

cv::Mat TrackingWorker::getIntrinsicsMatrix(int camNo)
{
	return tracker.getIntrinsicsMatrix(camNo);
}

cv::Mat TrackingWorker::getDistortionCoefficients(int camNo)
{
	return tracker.getDistortionCoefficients(camNo);
}

void TrackingWorker::updateTrackingArea()
{
	receiver->setTrackingArea(tracker.getTrackingArea());
}
<commit_msg>Flip x values<commit_after>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include <opencv2/core/core.hpp>
#include <map>

#include "../../matlab/profiling.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver) : errorGraph(100, "Difference")
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	std::map<int, cv::Scalar> colors;
	colors[0] = cv::Scalar(0, 255, 0);
	colors[1] = cv::Scalar(0, 255, 255);
	colors[2] = cv::Scalar(255, 0, 255);
	errorGraph.setColors(colors);

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;
	int emptyCount = 0;

	while (!stop) {
		std::vector<CameraData> data = dequeue();

		if (data.size() > 1) {
			emptyCount = 0;

			if (!receivedFirstPosition) {
				receivedFirstPosition = true;
				ROS_INFO("Found quadcopter %d", data[0].quadcopterId);
			}

			// ROS_DEBUG("Got info from camera %d: [%.2f, %.2f, %.2f]", data[0].camNo, data[0].cameraVector.getV1(), data[0].cameraVector.getV2(), data[0].cameraVector.getV3());

			double latency = 0;
			double currentTime = getNanoTime();

			for (std::vector<CameraData>::iterator it = data.begin(); it != data.end(); it++) {
				double newLatency = currentTime - it->time;

				if (newLatency > latency) {
					latency = newLatency;
				}
			}

			ROS_DEBUG("Latency is %.3fms", latency / 1e6);

			Vector position = tracker.updatePosition(data);

			for (size_t i = 0; i < data.size(); i++) {
				errorGraph.nextPoint(tracker.getDistance(), data[i].camNo);
			}

			if (position.isValid()) {
				// Invert x axis for controller
				position.setV1(-position.getV1());

				std::vector<Vector> positions;
				std::vector<int> ids;
				std::vector<int> updates;
				positions.push_back(position);
				ids.push_back(data[0].quadcopterId);
				updates.push_back(1);

				receiver->updatePositions(positions, ids, updates);
			}
		} else if (receivedFirstPosition) {
			emptyCount++;

			if (emptyCount == 50) {
				// TODO uncomment
				ROS_WARN("Position update buffer is empty!");
				emptyCount = 0;
			}

			boost::mutex::scoped_lock lock(queueMutex);
			queueEmpty.wait(lock);
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId, long int time)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;
	data.time = time;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	enqueue(data);
}

void TrackingWorker::enqueue(CameraData data)
{
	boost::mutex::scoped_lock lock(queueMutex);

	queue.enqueue(data);

	queueEmpty.notify_all();
}

std::vector<CameraData> TrackingWorker::dequeue()
{
	boost::mutex::scoped_lock lock(queueMutex);

	if (!dataAvailable()) {
		queueEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
	}

	if (dataAvailable()) {
		return queue.dequeue();
	} else {
		return std::vector<CameraData>();
	}
}

bool TrackingWorker::dataAvailable()
{
	return queue.dataAvailable();
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}

Vector TrackingWorker::getCameraPosition(int camNo)
{
	return tracker.getPosition(camNo);
}

Matrix TrackingWorker::getRotationMatrix(int camNo)
{
	return tracker.getRotationMatrix(camNo);
}

cv::Mat TrackingWorker::getIntrinsicsMatrix(int camNo)
{
	return tracker.getIntrinsicsMatrix(camNo);
}

cv::Mat TrackingWorker::getDistortionCoefficients(int camNo)
{
	return tracker.getDistortionCoefficients(camNo);
}

void TrackingWorker::updateTrackingArea()
{
	receiver->setTrackingArea(tracker.getTrackingArea());
}
<|endoftext|>


<commit_before>/*

This file is part of VROOM.

Copyright (c) 2015-2019, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "problems/cvrp/operators/exchange.h"

namespace vroom {
namespace cvrp {

Exchange::Exchange(const Input& input,
                   const utils::SolutionState& sol_state,
                   RawRoute& s_route,
                   Index s_vehicle,
                   Index s_rank,
                   RawRoute& t_route,
                   Index t_vehicle,
                   Index t_rank)
  : Operator(input,
             sol_state,
             s_route,
             s_vehicle,
             s_rank,
             t_route,
             t_vehicle,
             t_rank) {
  assert(s_vehicle != t_vehicle);
  assert(s_route.size() >= 1);
  assert(t_route.size() >= 1);
  assert(s_rank < s_route.size());
  assert(t_rank < t_route.size());
}

void Exchange::compute_gain() {
  const auto& m = _input.get_matrix();
  const auto& v_source = _input.vehicles[s_vehicle];
  const auto& v_target = _input.vehicles[t_vehicle];

  // For source vehicle, we consider the cost of replacing job at rank
  // s_rank with target job. Part of that cost (for adjacent
  // edges) is stored in _sol_state.edge_costs_around_node.
  Index s_index = _input.jobs[s_route[s_rank]].index();
  Index t_index = _input.jobs[t_route[t_rank]].index();

  // Determine costs added with target job.
  Gain new_previous_cost = 0;
  Gain new_next_cost = 0;

  if (s_rank == 0) {
    if (v_source.has_start()) {
      auto p_index = v_source.start.get().index();
      new_previous_cost = m[p_index][t_index];
    }
  } else {
    auto p_index = _input.jobs[s_route[s_rank - 1]].index();
    new_previous_cost = m[p_index][t_index];
  }

  if (s_rank == s_route.size() - 1) {
    if (v_source.has_end()) {
      auto n_index = v_source.end.get().index();
      new_next_cost = m[t_index][n_index];
    }
  } else {
    auto n_index = _input.jobs[s_route[s_rank + 1]].index();
    new_next_cost = m[t_index][n_index];
  }

  Gain s_gain = _sol_state.edge_costs_around_node[s_vehicle][s_rank] -
                new_previous_cost - new_next_cost;

  // For target vehicle, we consider the cost of replacing job at rank
  // t_rank with source job. Part of that cost (for adjacent
  // edges) is stored in _sol_state.edge_costs_around_node.

  // Determine costs added with source job.
  new_previous_cost = 0;
  new_next_cost = 0;

  if (t_rank == 0) {
    if (v_target.has_start()) {
      auto p_index = v_target.start.get().index();
      new_previous_cost = m[p_index][s_index];
    }
  } else {
    auto p_index = _input.jobs[t_route[t_rank - 1]].index();
    new_previous_cost = m[p_index][s_index];
  }

  if (t_rank == t_route.size() - 1) {
    if (v_target.has_end()) {
      auto n_index = v_target.end.get().index();
      new_next_cost = m[s_index][n_index];
    }
  } else {
    auto n_index = _input.jobs[t_route[t_rank + 1]].index();
    new_next_cost = m[s_index][n_index];
  }

  Gain t_gain = _sol_state.edge_costs_around_node[t_vehicle][t_rank] -
                new_previous_cost - new_next_cost;

  stored_gain = s_gain + t_gain;
  gain_computed = true;
}

bool Exchange::is_valid() {
  auto s_job_rank = s_route[s_rank];
  auto t_job_rank = t_route[t_rank];

  bool valid = _input.vehicle_ok_with_job(t_vehicle, s_job_rank);
  valid &= _input.vehicle_ok_with_job(s_vehicle, t_job_rank);

  valid &= (_sol_state.fwd_amounts[t_vehicle].back() -
              _input.jobs[t_job_rank].amount + _input.jobs[s_job_rank].amount <=
            _input.vehicles[t_vehicle].capacity);

  valid &= (_sol_state.fwd_amounts[s_vehicle].back() -
              _input.jobs[s_job_rank].amount + _input.jobs[t_job_rank].amount <=
            _input.vehicles[s_vehicle].capacity);

  return valid;
}

void Exchange::apply() {
  std::swap(s_route[s_rank], t_route[t_rank]);
}

std::vector<Index> Exchange::addition_candidates() const {
  return {s_vehicle, t_vehicle};
}

std::vector<Index> Exchange::update_candidates() const {
  return {s_vehicle, t_vehicle};
}

} // namespace cvrp
} // namespace vroom
<commit_msg>Update validity checks for Exchange.<commit_after>/*

This file is part of VROOM.

Copyright (c) 2015-2019, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "problems/cvrp/operators/exchange.h"

namespace vroom {
namespace cvrp {

Exchange::Exchange(const Input& input,
                   const utils::SolutionState& sol_state,
                   RawRoute& s_route,
                   Index s_vehicle,
                   Index s_rank,
                   RawRoute& t_route,
                   Index t_vehicle,
                   Index t_rank)
  : Operator(input,
             sol_state,
             s_route,
             s_vehicle,
             s_rank,
             t_route,
             t_vehicle,
             t_rank) {
  assert(s_vehicle != t_vehicle);
  assert(s_route.size() >= 1);
  assert(t_route.size() >= 1);
  assert(s_rank < s_route.size());
  assert(t_rank < t_route.size());
}

void Exchange::compute_gain() {
  const auto& m = _input.get_matrix();
  const auto& v_source = _input.vehicles[s_vehicle];
  const auto& v_target = _input.vehicles[t_vehicle];

  // For source vehicle, we consider the cost of replacing job at rank
  // s_rank with target job. Part of that cost (for adjacent
  // edges) is stored in _sol_state.edge_costs_around_node.
  Index s_index = _input.jobs[s_route[s_rank]].index();
  Index t_index = _input.jobs[t_route[t_rank]].index();

  // Determine costs added with target job.
  Gain new_previous_cost = 0;
  Gain new_next_cost = 0;

  if (s_rank == 0) {
    if (v_source.has_start()) {
      auto p_index = v_source.start.get().index();
      new_previous_cost = m[p_index][t_index];
    }
  } else {
    auto p_index = _input.jobs[s_route[s_rank - 1]].index();
    new_previous_cost = m[p_index][t_index];
  }

  if (s_rank == s_route.size() - 1) {
    if (v_source.has_end()) {
      auto n_index = v_source.end.get().index();
      new_next_cost = m[t_index][n_index];
    }
  } else {
    auto n_index = _input.jobs[s_route[s_rank + 1]].index();
    new_next_cost = m[t_index][n_index];
  }

  Gain s_gain = _sol_state.edge_costs_around_node[s_vehicle][s_rank] -
                new_previous_cost - new_next_cost;

  // For target vehicle, we consider the cost of replacing job at rank
  // t_rank with source job. Part of that cost (for adjacent
  // edges) is stored in _sol_state.edge_costs_around_node.

  // Determine costs added with source job.
  new_previous_cost = 0;
  new_next_cost = 0;

  if (t_rank == 0) {
    if (v_target.has_start()) {
      auto p_index = v_target.start.get().index();
      new_previous_cost = m[p_index][s_index];
    }
  } else {
    auto p_index = _input.jobs[t_route[t_rank - 1]].index();
    new_previous_cost = m[p_index][s_index];
  }

  if (t_rank == t_route.size() - 1) {
    if (v_target.has_end()) {
      auto n_index = v_target.end.get().index();
      new_next_cost = m[s_index][n_index];
    }
  } else {
    auto n_index = _input.jobs[t_route[t_rank + 1]].index();
    new_next_cost = m[s_index][n_index];
  }

  Gain t_gain = _sol_state.edge_costs_around_node[t_vehicle][t_rank] -
                new_previous_cost - new_next_cost;

  stored_gain = s_gain + t_gain;
  gain_computed = true;
}

bool Exchange::is_valid() {
  auto s_job_rank = s_route[s_rank];
  auto t_job_rank = t_route[t_rank];

  bool valid = _input.vehicle_ok_with_job(t_vehicle, s_job_rank);
  valid &= _input.vehicle_ok_with_job(s_vehicle, t_job_rank);

  valid &=
    target.is_valid_addition_for_capacity(_input,
                                          _input.jobs[s_route[s_rank]].pickup,
                                          _input.jobs[s_route[s_rank]].delivery,
                                          t_rank,
                                          t_rank + 1);

  valid &=
    source.is_valid_addition_for_capacity(_input,
                                          _input.jobs[t_route[t_rank]].pickup,
                                          _input.jobs[t_route[t_rank]].delivery,
                                          s_rank,
                                          s_rank + 1);

  return valid;
}

void Exchange::apply() {
  std::swap(s_route[s_rank], t_route[t_rank]);
}

std::vector<Index> Exchange::addition_candidates() const {
  return {s_vehicle, t_vehicle};
}

std::vector<Index> Exchange::update_candidates() const {
  return {s_vehicle, t_vehicle};
}

} // namespace cvrp
} // namespace vroom
<|endoftext|>


<commit_before>//
// BatchEncoder - GetProgress WvUnpackDec
// Copyright (C) 2005-2017 Wiesław Šoltés <wieslaw.soltes@gmail.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>

#include "GetProgress.h"

int GetProgress(char *szLineBuff, int nLineLen)
{
    // NOTE:
    // using my patched console encoder wvunpack.exe 4.31
    // added fflush(...) after all fprintf(...) calls in WvUnpack project
    // because of delayed output from original console encoder

    int j;
    int nPos = 0;
    char szPercentage[32];
    int nProgress = -1;

    memset(szPercentage, 0x00, sizeof(szPercentage));

    // check if we have done the job
    // 'restored 2.wav in 2.86 secs (lossless, 26.56%)'
    if (nLineLen >= 7)
    {
        if (strncmp(szLineBuff, "restored", 8) == 0)
        {
            nProgress = 100;
            return nProgress;
        }
    }

    // search for:
    // 'restoring 2.wav,  20% done...'

    // find % (percentage) char
    for (j = 0; j < (int)nLineLen; j++)
    {
        if (szLineBuff[j] == '%')
        {
            nPos = j;
            break;
        }
    }

    if (nPos >= 3)
    {
        if (szLineBuff[nPos - 3] == ' ') // not a 100.0 %
        {
            if (szLineBuff[nPos - 2] == ' ') // 0 to 9 %
            {
                szPercentage[0] = szLineBuff[nPos - 1];
                szPercentage[1] = '\0';

                nProgress = atoi(szPercentage);
                return nProgress;
            }
            else if (szLineBuff[nPos - 2] >= '0' && szLineBuff[nPos - 2] <= '9') // 10 to 99 %
            {
                szPercentage[0] = szLineBuff[nPos - 2];
                szPercentage[1] = szLineBuff[nPos - 1];
                szPercentage[2] = '\0';

                nProgress = atoi(szPercentage);
                return nProgress;
            }
        }
        else if (szLineBuff[nPos - 3] == '1') // 100.0 %
        {
            nProgress = 100;
            return nProgress;
        }
    }

    return -1;
}
<commit_msg>Update GetProgress.cpp<commit_after>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>

#include "GetProgress.h"

int GetProgress(char *szLineBuff, int nLineLen)
{
    // NOTE:
    // using my patched console encoder wvunpack.exe 4.31
    // added fflush(...) after all fprintf(...) calls in WvUnpack project
    // because of delayed output from original console encoder

    int j;
    int nPos = 0;
    char szPercentage[32];
    int nProgress = -1;

    memset(szPercentage, 0x00, sizeof(szPercentage));

    // check if we have done the job
    // 'restored 2.wav in 2.86 secs (lossless, 26.56%)'
    if (nLineLen >= 7)
    {
        if (strncmp(szLineBuff, "restored", 8) == 0)
        {
            nProgress = 100;
            return nProgress;
        }
    }

    // search for:
    // 'restoring 2.wav,  20% done...'

    // find % (percentage) char
    for (j = 0; j < (int)nLineLen; j++)
    {
        if (szLineBuff[j] == '%')
        {
            nPos = j;
            break;
        }
    }

    if (nPos >= 3)
    {
        if (szLineBuff[nPos - 3] == ' ') // not a 100.0 %
        {
            if (szLineBuff[nPos - 2] == ' ') // 0 to 9 %
            {
                szPercentage[0] = szLineBuff[nPos - 1];
                szPercentage[1] = '\0';

                nProgress = atoi(szPercentage);
                return nProgress;
            }
            else if (szLineBuff[nPos - 2] >= '0' && szLineBuff[nPos - 2] <= '9') // 10 to 99 %
            {
                szPercentage[0] = szLineBuff[nPos - 2];
                szPercentage[1] = szLineBuff[nPos - 1];
                szPercentage[2] = '\0';

                nProgress = atoi(szPercentage);
                return nProgress;
            }
        }
        else if (szLineBuff[nPos - 3] == '1') // 100.0 %
        {
            nProgress = 100;
            return nProgress;
        }
    }

    return -1;
}
<|endoftext|>