<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DomainMapperTableHandler.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: os $ $Date: 2007-05-09 13:54:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include <DomainMapperTableHandler.hxx>
#ifndef _COM_SUN_STAR_TEXT_HORIORIENTATION_HDL_
#include <com/sun/star/text/HoriOrientation.hpp>
#endif
#ifdef DEBUG
#include <iostream>
#endif
namespace dmapper {

using namespace ::com::sun::star;
using namespace ::std;

#define DEF_BORDER_DIST 190  //0,19cm

#ifdef DEBUG
static void lcl_printHandle(const Handle_t rHandle)
{
    rtl::OUString aOUStr = rHandle->getString();
    rtl::OString aOStr(aOUStr.getStr(), aOUStr.getLength(),  RTL_TEXTENCODING_ASCII_US );

    clog << aOStr.getStr() << endl;
}
static void  lcl_printProperties( PropertyMapPtr pProps )
{
    if( pProps.get() )
    {
        clog << "<properties>";
        PropertyMap::const_iterator aMapIter = pProps->begin();
        PropertyMap::const_iterator aEndIter = pProps->end();
        for( ; aMapIter != aEndIter; ++aMapIter )
        {
            rtl::OUString aOUStr = aMapIter->first;
            rtl::OString aOStr(aOUStr.getStr(), aOUStr.getLength(),  RTL_TEXTENCODING_ASCII_US );
            clog << aOStr.getStr() << '-';
        }
        clog << endl;
    }
}
#endif

void DomainMapperTableHandler::startTable(unsigned int nRows,
                                          unsigned int /*nDepth*/,
                                          PropertyMapPtr pProps)
{
    m_aTableProperties = pProps;
    m_pTableSeq = TableSequencePointer_t(new TableSequence_t(nRows));
    m_nRowIndex = 0;

#ifdef DEBUG
    char sBuffer[256];
    snprintf(sBuffer, sizeof(sBuffer), "%d", nRows);
    clog << "<table rows=\"" << sBuffer << "\">" << endl;
    lcl_printProperties( pProps );
#endif
}

void DomainMapperTableHandler::endTable()
{
#ifdef DEBUG
{
    clog << "
" << endl;
    sal_uInt32 nCells = 0;
    sal_uInt32 nRows = m_aRowProperties.size();
    if( nRows == m_aCellProperties.size() )
    {
        for( sal_uInt32 nRow = 0; nRow < nRows; ++nRow )
            nCells += m_aCellProperties[nRow].size();
    }
    sal_uInt32 nTblPropSize = m_aTableProperties.get() ? m_aTableProperties->size() : 0;
    (void)nTblPropSize;
}
#endif

    //  expands to uno::Sequence< Sequence< beans::PropertyValues > >
    CellPropertyValuesSeq_t     aCellProperties( m_aCellProperties.size() );

    // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
    PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
    PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
    sal_Int32 nRow = 0;
    PropertyNameSupplier& rPropSupplier = PropertyNameSupplier::GetPropertyNameSupplier();

    //it's a uno::Sequence< beans::PropertyValues >*
    RowPropertyValuesSeq_t* pCellProperties = aCellProperties.getArray();
    while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
    {
        //aRowOfCellsIterator points to a vector of PropertyMapPtr
        PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
        PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();

        sal_Int32 nCell = 0;
        pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
        beans::PropertyValues* pSingleCellProperties = pCellProperties->getArray();
        while( aCellIterator != aCellIteratorEnd )
        {
            //TODO: aCellIterator contains HorizontalBorder and VerticalBorder
            // they have to be removed, depending on the position of the cell they
            // have to be moved to BottomBorder/RightBorder respectively
            //aCellIterator points to a PropertyMapPtr;
            if( aCellIterator->get() )
            {

                const PropertyMap::iterator aVerticalIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(META_PROP_VERTICAL_BORDER) );
                const PropertyMap::iterator aHorizontalIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(META_PROP_HORIZONTAL_BORDER) );
                const PropertyMap::const_iterator aRightIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_RIGHT_BORDER) );
                const PropertyMap::const_iterator aBottomIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_BOTTOM_BORDER) );
                if( aVerticalIter != aCellIterator->get()->end())
                    aCellIterator->get()->erase( aVerticalIter );
                if( aHorizontalIter != aCellIterator->get()->end())
                    aCellIterator->get()->erase( aHorizontalIter );
                //now set the default left+right border distance TODO: there's an sprm containing the default distance!
                const PropertyMap::const_iterator aLeftDistanceIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_LEFT_BORDER_DISTANCE) );
                if( aLeftDistanceIter == aCellIterator->get()->end() )
                    aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE, uno::makeAny((sal_Int32) DEF_BORDER_DIST ) );
                const PropertyMap::const_iterator aRightDistanceIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_RIGHT_BORDER_DISTANCE) );
                if( aRightDistanceIter == aCellIterator->get()->end() )
                    aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE, uno::makeAny((sal_Int32) DEF_BORDER_DIST ) );

                pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues();
            }
            ++nCell;
            ++aCellIterator;
        }
        ++nRow;
        ++aRowOfCellsIterator;
    }

    RowPropertyValuesSeq_t      aRowProperties( m_aRowProperties.size() );
    PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
    PropertyMapVector1::const_iterator aRowIterEnd = m_aRowProperties.end();
    nRow = 0;
    while( aRowIter != aRowIterEnd )
    {
        if( aRowIter->get() )
        {
            //set default to 'break across pages"
            if( aRowIter->get()->find(rPropSupplier.GetName(PROP_IS_SPLIT_ALLOWED)) == aRowIter->get()->end())
                aRowIter->get()->Insert( PROP_IS_SPLIT_ALLOWED, uno::makeAny(sal_True ) );

            aRowProperties[nRow] = aRowIter->get()->GetPropertyValues();
        }
        ++nRow;
        ++aRowIter;
    }

    TablePropertyValues_t       aTableProperties;
    if( m_aTableProperties.get() )
    {
        //fill default value - if not available
        const PropertyMap::const_iterator aRepeatIter =
                                m_aTableProperties->find( rPropSupplier.GetName(PROP_HEADER_ROW_COUNT) );
        if( aRepeatIter == m_aTableProperties->end() )
            m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( (sal_Int32)0 ));

        //set default orientation if not already set
        const PropertyMap::const_iterator aOrientIter =
                    m_aTableProperties->find( rPropSupplier.GetName( PROP_HORI_ORIENT ));
        if( aOrientIter == m_aTableProperties->end() )
            m_aTableProperties->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::LEFT_AND_WIDTH ) );
        aTableProperties = m_aTableProperties->GetPropertyValues();
    }

    if (m_pTableSeq->getLength() > 0)
    {
        try
        {
#ifdef DEBUG
    {
        sal_Int32 nCellPropertiesRows = aCellProperties.getLength();
        sal_Int32 nCellPropertiesCells = aCellProperties[0].getLength();
        sal_Int32 nCellPropertiesProperties = aCellProperties[0][0].getLength();
        (void) nCellPropertiesRows;
        (void) nCellPropertiesCells;
        (void) nCellPropertiesProperties;
        ++nCellPropertiesProperties;
    }
#endif
            m_xText->convertToTable(*m_pTableSeq,
                                    aCellProperties,
                                    aRowProperties,
                                    aTableProperties);
        }
        catch (lang::IllegalArgumentException e)
        {
#ifdef DEBUG
            clog << "failed to import table!" << endl;
#endif
        }
    }
}

void DomainMapperTableHandler::startRow(unsigned int nCells,
                                        PropertyMapPtr pProps)
{
    m_aRowProperties.push_back( pProps );
    m_aCellProperties.push_back( PropertyMapVector1() );

#ifdef DEBUG
    char sBuffer[256];
    snprintf(sBuffer, sizeof(sBuffer), "%d", nCells);

    clog << "<table.row cells=\"" << sBuffer << "\">" << endl;
    lcl_printProperties( pProps );
#endif

    m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
    m_nCellIndex = 0;
}

void DomainMapperTableHandler::endRow()
{
    (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
    ++m_nRowIndex;
    m_nCellIndex = 0;
#ifdef DEBUG
    clog << "
" << endl;
#endif
}

void DomainMapperTableHandler::startCell(const Handle_t & start,
                                         PropertyMapPtr pProps )
{
    sal_uInt32 nRow = m_aRowProperties.size();
    m_aCellProperties[nRow - 1].push_back( pProps );

#ifdef DEBUG
    clog << "
";
    lcl_printHandle(start);
    lcl_printProperties( pProps );
    clog << ",";
#endif

    //add a new 'row' of properties
//    if( m_pCellProperties.size() <= sal::static_int_cast< sal_uInt32, sal_Int32>(m_nRowIndex) )
//        m_pCellProperties.push_back( RowProperties_t() );
//    m_pCellProperties[m_nRowIndex].push_back( pProps );
    m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
    (*m_pCellSeq)[0] = start->getStart();
}

void DomainMapperTableHandler::endCell(const Handle_t & end)
{
#ifdef DEBUG
    lcl_printHandle(end);
    clog << "
" << endl;
#endif

    (*m_pCellSeq)[1] = end->getEnd();
    (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
    ++m_nCellIndex;
}

}
<commit_msg>more debugging support for cell properties<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DomainMapperTableHandler.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: os $ $Date: 2007-05-21 14:21:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include <DomainMapperTableHandler.hxx>
#ifndef _COM_SUN_STAR_TEXT_HORIORIENTATION_HDL_
#include <com/sun/star/text/HoriOrientation.hpp>
#endif
#ifdef DEBUG
#include <iostream>
#endif
namespace dmapper {

using namespace ::com::sun::star;
using namespace ::std;

#define DEF_BORDER_DIST 190  //0,19cm

#ifdef DEBUG
static void lcl_printHandle(const Handle_t rHandle)
{
    rtl::OUString aOUStr = rHandle->getString();
    rtl::OString aOStr(aOUStr.getStr(), aOUStr.getLength(),  RTL_TEXTENCODING_ASCII_US );

    clog << aOStr.getStr() << endl;
}
static void  lcl_printProperties( PropertyMapPtr pProps )
{
    if( pProps.get() )
    {
        clog << "<properties>";
        PropertyMap::const_iterator aMapIter = pProps->begin();
        PropertyMap::const_iterator aEndIter = pProps->end();
        for( ; aMapIter != aEndIter; ++aMapIter )
        {
            rtl::OUString aOUStr = aMapIter->first;
            rtl::OString aOStr(aOUStr.getStr(), aOUStr.getLength(),  RTL_TEXTENCODING_ASCII_US );
            clog << aOStr.getStr() << '-';
        }
        clog << endl;
    }
}
#endif

void DomainMapperTableHandler::startTable(unsigned int nRows,
                                          unsigned int /*nDepth*/,
                                          PropertyMapPtr pProps)
{
    m_aTableProperties = pProps;
    m_pTableSeq = TableSequencePointer_t(new TableSequence_t(nRows));
    m_nRowIndex = 0;

#ifdef DEBUG
    char sBuffer[256];
    snprintf(sBuffer, sizeof(sBuffer), "%d", nRows);
    clog << "<table rows=\"" << sBuffer << "\">" << endl;
    lcl_printProperties( pProps );
#endif
}

void DomainMapperTableHandler::endTable()
{
#ifdef DEBUG
{
    clog << "
" << endl;
    sal_uInt32 nCells = 0;
    sal_uInt32 nRows = m_aRowProperties.size();
    if( nRows == m_aCellProperties.size() )
    {
        for( sal_uInt32 nRow = 0; nRow < nRows; ++nRow )
            nCells += m_aCellProperties[nRow].size();
    }
    sal_uInt32 nTblPropSize = m_aTableProperties.get() ? m_aTableProperties->size() : 0;
    (void)nTblPropSize;
}
#endif

    //  expands to uno::Sequence< Sequence< beans::PropertyValues > >
    CellPropertyValuesSeq_t     aCellProperties( m_aCellProperties.size() );

    // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
    PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
    PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
    sal_Int32 nRow = 0;
    PropertyNameSupplier& rPropSupplier = PropertyNameSupplier::GetPropertyNameSupplier();

    //it's a uno::Sequence< beans::PropertyValues >*
    RowPropertyValuesSeq_t* pCellProperties = aCellProperties.getArray();
    while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
    {
        //aRowOfCellsIterator points to a vector of PropertyMapPtr
        PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
        PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();

        sal_Int32 nCell = 0;
        pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
        beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
        while( aCellIterator != aCellIteratorEnd )
        {
            //TODO: aCellIterator contains HorizontalBorder and VerticalBorder
            // they have to be removed, depending on the position of the cell they
            // have to be moved to BottomBorder/RightBorder respectively
            //aCellIterator points to a PropertyMapPtr;
            if( aCellIterator->get() )
            {

                const PropertyMap::iterator aVerticalIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(META_PROP_VERTICAL_BORDER) );
                const PropertyMap::iterator aHorizontalIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(META_PROP_HORIZONTAL_BORDER) );
                const PropertyMap::const_iterator aRightIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_RIGHT_BORDER) );
                const PropertyMap::const_iterator aBottomIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_BOTTOM_BORDER) );
                if( aVerticalIter != aCellIterator->get()->end())
                    aCellIterator->get()->erase( aVerticalIter );
                if( aHorizontalIter != aCellIterator->get()->end())
                    aCellIterator->get()->erase( aHorizontalIter );
                //now set the default left+right border distance TODO: there's an sprm containing the default distance!
                const PropertyMap::const_iterator aLeftDistanceIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_LEFT_BORDER_DISTANCE) );
                if( aLeftDistanceIter == aCellIterator->get()->end() )
                    aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE, uno::makeAny((sal_Int32) DEF_BORDER_DIST ) );
                const PropertyMap::const_iterator aRightDistanceIter =
                                aCellIterator->get()->find( rPropSupplier.GetName(PROP_RIGHT_BORDER_DISTANCE) );
                if( aRightDistanceIter == aCellIterator->get()->end() )
                    aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE, uno::makeAny((sal_Int32) DEF_BORDER_DIST ) );

                pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues();
            }
            ++nCell;
            ++aCellIterator;
        }
#ifdef DEBUG
//-->debug cell properties
        {
            ::rtl::OUString sNames;
            const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nRow];
            sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
            (void) nDebugCells;
            for( sal_Int32  nDebugCell = 0; nDebugCell < nDebugCells; ++nDebugCell)
            {
                const uno::Sequence< beans::PropertyValue >& aDebugCellProperties = aDebugCurrentRow[nDebugCell];
                sal_Int32 nDebugCellProperties = aDebugCellProperties.getLength();
                for( sal_Int32  nDebugProperty = 0; nDebugProperty < nDebugCellProperties; ++nDebugProperty)
                {
                    const ::rtl::OUString sName = aDebugCellProperties[nDebugProperty].Name;
                    sNames += sName;
                    sNames += ::rtl::OUString('-');
                }
                sNames += ::rtl::OUString(' ');
            }
            (void)sNames;
        }
//--<
#endif
        ++nRow;
        ++aRowOfCellsIterator;
    }
#ifdef DEBUG
//-->debug cell properties of all rows
    {
        ::rtl::OUString sNames;
        for( sal_Int32  nDebugRow = 0; nDebugRow < aCellProperties.getLength(); ++nDebugRow)
        {
            const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nDebugRow];
            sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
            (void) nDebugCells;
            for( sal_Int32  nDebugCell = 0; nDebugCell < nDebugCells; ++nDebugCell)
            {
                const uno::Sequence< beans::PropertyValue >& aDebugCellProperties = aDebugCurrentRow[nDebugCell];
                sal_Int32 nDebugCellProperties = aDebugCellProperties.getLength();
                for( sal_Int32  nDebugProperty = 0; nDebugProperty < nDebugCellProperties; ++nDebugProperty)
                {
                    const ::rtl::OUString sName = aDebugCellProperties[nDebugProperty].Name;
                    sNames += sName;
                    sNames += ::rtl::OUString('-');
                }
                sNames += ::rtl::OUString('+');
            }
            sNames += ::rtl::OUString('|');
        }
        (void)sNames;
    }
//--<
#endif

    RowPropertyValuesSeq_t      aRowProperties( m_aRowProperties.size() );
    PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
    PropertyMapVector1::const_iterator aRowIterEnd = m_aRowProperties.end();
    nRow = 0;
    while( aRowIter != aRowIterEnd )
    {
        if( aRowIter->get() )
        {
            //set default to 'break across pages"
            if( aRowIter->get()->find(rPropSupplier.GetName(PROP_IS_SPLIT_ALLOWED)) == aRowIter->get()->end())
                aRowIter->get()->Insert( PROP_IS_SPLIT_ALLOWED, uno::makeAny(sal_True ) );

            aRowProperties[nRow] = aRowIter->get()->GetPropertyValues();
        }
        ++nRow;
        ++aRowIter;
    }

    TablePropertyValues_t       aTableProperties;
    if( m_aTableProperties.get() )
    {
        //fill default value - if not available
        const PropertyMap::const_iterator aRepeatIter =
                                m_aTableProperties->find( rPropSupplier.GetName(PROP_HEADER_ROW_COUNT) );
        if( aRepeatIter == m_aTableProperties->end() )
            m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( (sal_Int32)0 ));

        //set default orientation if not already set
        const PropertyMap::const_iterator aOrientIter =
                    m_aTableProperties->find( rPropSupplier.GetName( PROP_HORI_ORIENT ));
        if( aOrientIter == m_aTableProperties->end() )
            m_aTableProperties->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::LEFT_AND_WIDTH ) );
        aTableProperties = m_aTableProperties->GetPropertyValues();
    }

    if (m_pTableSeq->getLength() > 0)
    {
        try
        {
#ifdef DEBUG
    {
        sal_Int32 nCellPropertiesRows = aCellProperties.getLength();
        sal_Int32 nCellPropertiesCells = aCellProperties[0].getLength();
        sal_Int32 nCellPropertiesProperties = aCellProperties[0][0].getLength();
        (void) nCellPropertiesRows;
        (void) nCellPropertiesCells;
        (void) nCellPropertiesProperties;
        ++nCellPropertiesProperties;
    }
#endif
            m_xText->convertToTable(*m_pTableSeq,
                                    aCellProperties,
                                    aRowProperties,
                                    aTableProperties);
        }
        catch (lang::IllegalArgumentException e)
        {
#ifdef DEBUG
            clog << "failed to import table!" << endl;
#endif
        }
    }
}

void DomainMapperTableHandler::startRow(unsigned int nCells,
                                        PropertyMapPtr pProps)
{
    m_aRowProperties.push_back( pProps );
    m_aCellProperties.push_back( PropertyMapVector1() );

#ifdef DEBUG
    char sBuffer[256];
    snprintf(sBuffer, sizeof(sBuffer), "%d", nCells);

    clog << "<table.row cells=\"" << sBuffer << "\">" << endl;
    lcl_printProperties( pProps );
#endif

    m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
    m_nCellIndex = 0;
}

void DomainMapperTableHandler::endRow()
{
    (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
    ++m_nRowIndex;
    m_nCellIndex = 0;
#ifdef DEBUG
    clog << "
" << endl;
#endif
}

void DomainMapperTableHandler::startCell(const Handle_t & start,
                                         PropertyMapPtr pProps )
{
    sal_uInt32 nRow = m_aRowProperties.size();
    m_aCellProperties[nRow - 1].push_back( pProps );

#ifdef DEBUG
    clog << "
";
    lcl_printHandle(start);
    lcl_printProperties( pProps );
    clog << ",";
#endif

    //add a new 'row' of properties
//    if( m_pCellProperties.size() <= sal::static_int_cast< sal_uInt32, sal_Int32>(m_nRowIndex) )
//        m_pCellProperties.push_back( RowProperties_t() );
//    m_pCellProperties[m_nRowIndex].push_back( pProps );
    m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
    (*m_pCellSeq)[0] = start->getStart();
}

void DomainMapperTableHandler::endCell(const Handle_t & end)
{
#ifdef DEBUG
    lcl_printHandle(end);
    clog << "
" << endl;
#endif

    (*m_pCellSeq)[1] = end->getEnd();
    (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
    ++m_nCellIndex;
}

}
<|endoftext|>


<commit_before>/*
Copyright libCellML Contributors

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

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

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

#include "libcellml/analysermodel.h"

#include <vector>

#include "libcellml/variable.h"

#include "analysermodel_p.h"

namespace libcellml {

bool AnalyserModel::AnalyserModelImpl::haveEquivalentVariables(const Variable *variable1,
                                                               const Variable *variable2,
                                                               std::vector<const Variable *> &testedVariables)
{
    if (variable1 == variable2) {
        return true;
    }

    testedVariables.push_back(variable2);

    auto testedVariablesBegin = testedVariables.begin();
    auto testedVariablesEnd = testedVariables.end();

    for (size_t i = 0; i < variable2->equivalentVariableCount(); ++i) {
        Variable *equivalentVariable2 = variable2->equivalentVariable(i).get();

        if ((std::find(testedVariablesBegin, testedVariablesEnd, equivalentVariable2) == testedVariablesEnd)
            && haveEquivalentVariables(variable1, equivalentVariable2, testedVariables)) {
            return true;
        }
    }

    return false;
}

AnalyserModel::AnalyserModel()
    : mPimpl(new AnalyserModelImpl())
{
}

AnalyserModel::~AnalyserModel()
{
    delete mPimpl;
}

bool AnalyserModel::isValid() const
{
    return (mPimpl->mType == AnalyserModel::Type::ALGEBRAIC)
           || (mPimpl->mType == AnalyserModel::Type::ODE);
}

AnalyserModel::Type AnalyserModel::type() const
{
    return mPimpl->mType;
}

AnalyserVariablePtr AnalyserModel::voi() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVoi;
}

size_t AnalyserModel::stateCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mStates.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::states() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mStates;
}

AnalyserVariablePtr AnalyserModel::state(size_t index) const
{
    if (!isValid()
        || (index >= mPimpl->mStates.size())) {
        return {};
    }

    return mPimpl->mStates[index];
}

size_t AnalyserModel::variableCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mVariables.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::variables() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVariables;
}

AnalyserVariablePtr AnalyserModel::variable(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mVariables.size())) {
        return {};
    }

    return mPimpl->mVariables[index];
}

size_t AnalyserModel::equationCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mEquations.size();
}

std::vector<AnalyserEquationPtr> AnalyserModel::equations() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mEquations;
}

AnalyserEquationPtr AnalyserModel::equation(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mEquations.size())) {
        return {};
    }

    return mPimpl->mEquations[index];
}

bool AnalyserModel::needEqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedEqFunction;
}

bool AnalyserModel::needNeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNeqFunction;
}

bool AnalyserModel::needLtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLtFunction;
}

bool AnalyserModel::needLeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLeqFunction;
}

bool AnalyserModel::needGtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGtFunction;
}

bool AnalyserModel::needGeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGeqFunction;
}

bool AnalyserModel::needAndFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAndFunction;
}

bool AnalyserModel::needOrFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedOrFunction;
}

bool AnalyserModel::needXorFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedXorFunction;
}

bool AnalyserModel::needNotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNotFunction;
}

bool AnalyserModel::needMinFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMinFunction;
}

bool AnalyserModel::needMaxFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMaxFunction;
}

bool AnalyserModel::needSecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSecFunction;
}

bool AnalyserModel::needCscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCscFunction;
}

bool AnalyserModel::needCotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCotFunction;
}

bool AnalyserModel::needSechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSechFunction;
}

bool AnalyserModel::needCschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCschFunction;
}

bool AnalyserModel::needCothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCothFunction;
}

bool AnalyserModel::needAsecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsecFunction;
}

bool AnalyserModel::needAcscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcscFunction;
}

bool AnalyserModel::needAcotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcotFunction;
}

bool AnalyserModel::needAsechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsechFunction;
}

bool AnalyserModel::needAcschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcschFunction;
}

bool AnalyserModel::needAcothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcothFunction;
}

bool AnalyserModel::isSameOrEquivalentVariable(const VariablePtr &variable1,
                                               const VariablePtr &variable2)
{
    if (variable1 == variable2) {
        return true;
    }

    auto key = reinterpret_cast<intptr_t>(variable1.get()) * reinterpret_cast<intptr_t>(variable2.get());
    auto cacheKey = mPimpl->mCachedEquivalentVariables.find(key);

    if (cacheKey != mPimpl->mCachedEquivalentVariables.end()) {
        return cacheKey->second;
    }

    std::vector<const Variable *> testedVariables;
    bool res = mPimpl->haveEquivalentVariables(variable1.get(), variable2.get(), testedVariables);

    mPimpl->mCachedEquivalentVariables[key] = res;

    return res;
}

} // namespace libcellml
<commit_msg>Make Linux happy.<commit_after>/*
Copyright libCellML Contributors

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

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

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

#include "libcellml/analysermodel.h"

#include <algorithm>

#include "libcellml/variable.h"

#include "analysermodel_p.h"

namespace libcellml {

bool AnalyserModel::AnalyserModelImpl::haveEquivalentVariables(const Variable *variable1,
                                                               const Variable *variable2,
                                                               std::vector<const Variable *> &testedVariables)
{
    if (variable1 == variable2) {
        return true;
    }

    testedVariables.push_back(variable2);

    auto testedVariablesBegin = testedVariables.begin();
    auto testedVariablesEnd = testedVariables.end();

    for (size_t i = 0; i < variable2->equivalentVariableCount(); ++i) {
        Variable *equivalentVariable2 = variable2->equivalentVariable(i).get();

        if ((std::find(testedVariablesBegin, testedVariablesEnd, equivalentVariable2) == testedVariablesEnd)
            && haveEquivalentVariables(variable1, equivalentVariable2, testedVariables)) {
            return true;
        }
    }

    return false;
}

AnalyserModel::AnalyserModel()
    : mPimpl(new AnalyserModelImpl())
{
}

AnalyserModel::~AnalyserModel()
{
    delete mPimpl;
}

bool AnalyserModel::isValid() const
{
    return (mPimpl->mType == AnalyserModel::Type::ALGEBRAIC)
           || (mPimpl->mType == AnalyserModel::Type::ODE);
}

AnalyserModel::Type AnalyserModel::type() const
{
    return mPimpl->mType;
}

AnalyserVariablePtr AnalyserModel::voi() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVoi;
}

size_t AnalyserModel::stateCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mStates.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::states() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mStates;
}

AnalyserVariablePtr AnalyserModel::state(size_t index) const
{
    if (!isValid()
        || (index >= mPimpl->mStates.size())) {
        return {};
    }

    return mPimpl->mStates[index];
}

size_t AnalyserModel::variableCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mVariables.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::variables() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVariables;
}

AnalyserVariablePtr AnalyserModel::variable(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mVariables.size())) {
        return {};
    }

    return mPimpl->mVariables[index];
}

size_t AnalyserModel::equationCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mEquations.size();
}

std::vector<AnalyserEquationPtr> AnalyserModel::equations() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mEquations;
}

AnalyserEquationPtr AnalyserModel::equation(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mEquations.size())) {
        return {};
    }

    return mPimpl->mEquations[index];
}

bool AnalyserModel::needEqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedEqFunction;
}

bool AnalyserModel::needNeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNeqFunction;
}

bool AnalyserModel::needLtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLtFunction;
}

bool AnalyserModel::needLeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLeqFunction;
}

bool AnalyserModel::needGtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGtFunction;
}

bool AnalyserModel::needGeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGeqFunction;
}

bool AnalyserModel::needAndFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAndFunction;
}

bool AnalyserModel::needOrFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedOrFunction;
}

bool AnalyserModel::needXorFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedXorFunction;
}

bool AnalyserModel::needNotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNotFunction;
}

bool AnalyserModel::needMinFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMinFunction;
}

bool AnalyserModel::needMaxFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMaxFunction;
}

bool AnalyserModel::needSecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSecFunction;
}

bool AnalyserModel::needCscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCscFunction;
}

bool AnalyserModel::needCotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCotFunction;
}

bool AnalyserModel::needSechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSechFunction;
}

bool AnalyserModel::needCschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCschFunction;
}

bool AnalyserModel::needCothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCothFunction;
}

bool AnalyserModel::needAsecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsecFunction;
}

bool AnalyserModel::needAcscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcscFunction;
}

bool AnalyserModel::needAcotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcotFunction;
}

bool AnalyserModel::needAsechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsechFunction;
}

bool AnalyserModel::needAcschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcschFunction;
}

bool AnalyserModel::needAcothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcothFunction;
}

bool AnalyserModel::isSameOrEquivalentVariable(const VariablePtr &variable1,
                                               const VariablePtr &variable2)
{
    if (variable1 == variable2) {
        return true;
    }

    auto key = reinterpret_cast<intptr_t>(variable1.get()) * reinterpret_cast<intptr_t>(variable2.get());
    auto cacheKey = mPimpl->mCachedEquivalentVariables.find(key);

    if (cacheKey != mPimpl->mCachedEquivalentVariables.end()) {
        return cacheKey->second;
    }

    std::vector<const Variable *> testedVariables;
    bool res = mPimpl->haveEquivalentVariables(variable1.get(), variable2.get(), testedVariables);

    mPimpl->mCachedEquivalentVariables[key] = res;

    return res;
}

} // namespace libcellml
<|endoftext|>


<commit_before>#ifndef ALEPH_TOPOLOGY_IO_MATRIX_HH__
#define ALEPH_TOPOLOGY_IO_MATRIX_HH__

#include <aleph/utilities/String.hh>

#include <aleph/topology/filtrations/Data.hh>

#include <algorithm>
#include <fstream>
#include <istream>
#include <string>
#include <unordered_map>
#include <vector>

#include <cmath>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class BipartiteAdjacencyMatrixReader
  @brief Reads bipartite adjacency matrices in text format

  This reader class is meant to load bipartite adjacency matrices in
  text format. Every row of the matrix represents edges that connect
  nodes from the first class with nodes of the second class. Weights
  that are non-zero are used to indicate the presence of an edge.

  The number of rows and columns must not vary over the file. An *empty*
  line is permitted, though. Likewise, lines starting with `#` will just
  be ignored. An example of a 2-by-3 matrix follows:

  \code
  0 1 2
  3 4 5
  \endcode

  All simplicial complexes created by this class will be reported
  in filtration order, following the detected weights.
*/

class BipartiteAdjacencyMatrixReader
{
public:

  /**
    Reads a simplicial complex from a file.

    @param filename Input filename
    @param  K       Simplicial complex
  */

  template <class SimplicialComplex> void operator()( const std::string& filename, SimplicialComplex& K )
  {
    std::ifstream in( filename );
    if( !in )
      throw std::runtime_error( "Unable to read input file" );

    this->operator()( in, K );
  }

  /** @overload operator()( const std::string&, SimplicialComplex& ) */
  template <class SimplicialComplex> void operator()( std::istream& in, SimplicialComplex& K )
  {
    using Simplex    = typename SimplicialComplex::ValueType;
    using DataType   = typename Simplex::DataType;

    auto position = in.tellg();

    std::size_t height = 0;
    std::size_t width  = 0;

    using namespace aleph::utilities;

    {
      std::string line;
      while( std::getline( in, line ) )
      {
        line           = trim( line );
        auto numTokens = countTokens( line );

        if( width == 0 )
          width = numTokens;
        else if( width != numTokens )
          throw std::runtime_error( "Format error: number of columns must not vary" );

        ++height;
      }

      in.clear();
      in.seekg( position );
    }

    _height = height;
    _width  = width;

    using Simplex    = typename SimplicialComplex::ValueType;
    using DataType   = typename Simplex::DataType;
    using VertexType = typename Simplex::VertexType;

    std::vector<DataType> values;
    values.reserve( _height * _width );

    std::copy( std::istream_iterator<DataType>( in ), std::istream_iterator<DataType>(),
               std::back_inserter( values ) );

    // We cannot fill an empt simplicial complex. It might be useful to
    // throw an error here, though.
    if( values.empty() )
      return;

    // This is required in order to assign the weight of nodes
    // correctly; we cannot trust the weights to be positive.
    auto minData = *std::min_element( values.begin(), values.end() );

    std::vector<Simplex> simplices;

    // Edges -----------------------------------------------------------
    //
    // Create the edges first and update information about their weights
    // along with them.

    // For determining the minimum weight, we first loop over all
    // possible edges, create a lookup table for the weights, and
    // finally create all the vertices using this lookup table. A
    // vertex will only information stored here if the right flag
    // has been set by the client.
    std::unordered_map<VertexType, DataType> minWeight;

    auto updateOrSetWeight
      = [&minWeight] ( const VertexType& v, const DataType& w )
        {
          if( minWeight.find( v ) == minWeight.end() )
            minWeight[v] = w;
          else
            minWeight[v] = std::min( minWeight[v], w );
        };

    for( std::size_t y = 0; y < _height; y++ )
    {
      for( std::size_t x = 0; x < _width; x++ )
      {
        auto i = static_cast<VertexType>( width * y + x   );
        auto w = values.at( i );

        // Map matrix indices to the corresponding vertex indices as
        // outline above.
        auto u = VertexType(y);
        auto v = VertexType(x + _height);

        updateOrSetWeight( u, w );
        updateOrSetWeight( v, w );

        simplices.push_back( Simplex( {u,v}, w ) );
      }
    }

    // Vertices --------------------------------------------------------
    //
    // Create a vertex for every node in the input data. An (n,m)-matrix
    // thus gives rise to n+m nodes.

    for( std::size_t i = 0; i < _height + _width; i++ )
    {
      simplices.push_back(
        Simplex( VertexType( i ),
          _assignMinimumVertexWeight
            ?  minWeight.at( VertexType(i) )
            :  minData )
      );
    }

    K = SimplicialComplex( simplices.begin(), simplices.end() );

    // Establish filtration order based on weights. There does not seem
    // to be much of a point to make this configurable; the edge weight
    // is a given property of the data.
    K.sort(
      filtrations::Data<Simplex>()
    );
  }

  /** @returns Height of matrix that was read last */
  std::size_t height() const noexcept { return _height; }

  /** @returns Width of matrix that was read last */
  std::size_t width()  const noexcept { return _width;  }

  /** Permits changing the behaviour of vertex weight assignment */
  void setAssignMinimumVertexWeight( bool value = true )
  {
    _assignMinimumVertexWeight = value;
  }

  /** @returns Flag whether vertex weights are assigned to be minimal or not */
  bool assignMinimumVertexWeight() const noexcept
  {
    return _assignMinimumVertexWeight;
  }

private:
  std::size_t _height = 0;
  std::size_t _width  = 0;

  /**
    If set, assigns the minimum vertex weight according to the minimum
    edge weight that is connected to the given vertex. Else, *all* the
    vertices will get a weight of zero.
  */

  bool _assignMinimumVertexWeight = false;
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<commit_msg>Simplified value extraction for bipartite adjacency matrices<commit_after>#ifndef ALEPH_TOPOLOGY_IO_MATRIX_HH__
#define ALEPH_TOPOLOGY_IO_MATRIX_HH__

#include <aleph/utilities/String.hh>

#include <aleph/topology/filtrations/Data.hh>

#include <algorithm>
#include <fstream>
#include <istream>
#include <string>
#include <unordered_map>
#include <vector>

#include <cmath>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class BipartiteAdjacencyMatrixReader
  @brief Reads bipartite adjacency matrices in text format

  This reader class is meant to load bipartite adjacency matrices in
  text format. Every row of the matrix represents edges that connect
  nodes from the first class with nodes of the second class. Weights
  that are non-zero are used to indicate the presence of an edge.

  The number of rows and columns must not vary over the file. An *empty*
  line is permitted, though. Likewise, lines starting with `#` will just
  be ignored. An example of a 2-by-3 matrix follows:

  \code
  0 1 2
  3 4 5
  \endcode

  All simplicial complexes created by this class will be reported
  in filtration order, following the detected weights.
*/

class BipartiteAdjacencyMatrixReader
{
public:

  /**
    Reads a simplicial complex from a file.

    @param filename Input filename
    @param  K       Simplicial complex
  */

  template <class SimplicialComplex> void operator()( const std::string& filename, SimplicialComplex& K )
  {
    std::ifstream in( filename );
    if( !in )
      throw std::runtime_error( "Unable to read input file" );

    this->operator()( in, K );
  }

  /** @overload operator()( const std::string&, SimplicialComplex& ) */
  template <class SimplicialComplex> void operator()( std::istream& in, SimplicialComplex& K )
  {
    using Simplex    = typename SimplicialComplex::ValueType;
    using DataType   = typename Simplex::DataType;
    using VertexType = typename Simplex::VertexType;

    auto position      = in.tellg();
    std::size_t height = 0;

    // An 'unrolled' version of all edge weights that can be read from
    // the file. They are supposed to correspond to a matrix with some
    // number of columns and some number of rows.
    std::vector<DataType> values;

    using namespace aleph::utilities;

    {
      std::string line;
      while( std::getline( in, line ) )
        ++height;

      in.clear();
      in.seekg( position );
    }

    std::copy( std::istream_iterator<DataType>( in ), std::istream_iterator<DataType>(),
               std::back_inserter( values ) );

    // We cannot fill an empty simplicial complex. It might be useful to
    // throw an error here, though.
    if( values.empty() )
      return;

    _height = height;
    _width  = values.size() / height;
    if( values.size() % height != 0 )
      throw std::runtime_error( "Format error: number of columns must not vary" );

    // This is required in order to assign the weight of nodes
    // correctly; we cannot trust the weights to be positive.
    auto minData = *std::min_element( values.begin(), values.end() );

    std::vector<Simplex> simplices;

    // Edges -----------------------------------------------------------
    //
    // Create the edges first and update information about their weights
    // along with them.

    // For determining the minimum weight, we first loop over all
    // possible edges, create a lookup table for the weights, and
    // finally create all the vertices using this lookup table. A
    // vertex will only information stored here if the right flag
    // has been set by the client.
    std::unordered_map<VertexType, DataType> minWeight;

    auto updateOrSetWeight
      = [&minWeight] ( const VertexType& v, const DataType& w )
        {
          if( minWeight.find( v ) == minWeight.end() )
            minWeight[v] = w;
          else
            minWeight[v] = std::min( minWeight[v], w );
        };

    for( std::size_t y = 0; y < _height; y++ )
    {
      for( std::size_t x = 0; x < _width; x++ )
      {
        auto i = static_cast<VertexType>( _width * y + x   );
        auto w = values.at( i );

        // Map matrix indices to the corresponding vertex indices as
        // outline above.
        auto u = VertexType(y);
        auto v = VertexType(x + _height);

        updateOrSetWeight( u, w );
        updateOrSetWeight( v, w );

        simplices.push_back( Simplex( {u,v}, w ) );
      }
    }

    // Vertices --------------------------------------------------------
    //
    // Create a vertex for every node in the input data. An (n,m)-matrix
    // thus gives rise to n+m nodes.

    for( std::size_t i = 0; i < _height + _width; i++ )
    {
      simplices.push_back(
        Simplex( VertexType( i ),
          _assignMinimumVertexWeight
            ?  minWeight.at( VertexType(i) )
            :  minData )
      );
    }

    K = SimplicialComplex( simplices.begin(), simplices.end() );

    // Establish filtration order based on weights. There does not seem
    // to be much of a point to make this configurable; the edge weight
    // is a given property of the data.
    K.sort(
      filtrations::Data<Simplex>()
    );
  }

  /** @returns Height of matrix that was read last */
  std::size_t height() const noexcept { return _height; }

  /** @returns Width of matrix that was read last */
  std::size_t width()  const noexcept { return _width;  }

  /** Permits changing the behaviour of vertex weight assignment */
  void setAssignMinimumVertexWeight( bool value = true )
  {
    _assignMinimumVertexWeight = value;
  }

  /** @returns Flag whether vertex weights are assigned to be minimal or not */
  bool assignMinimumVertexWeight() const noexcept
  {
    return _assignMinimumVertexWeight;
  }

private:
  std::size_t _height = 0;
  std::size_t _width  = 0;

  /**
    If set, assigns the minimum vertex weight according to the minimum
    edge weight that is connected to the given vertex. Else, *all* the
    vertices will get a weight of zero.
  */

  bool _assignMinimumVertexWeight = false;
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<|endoftext|>


<commit_before>/* conduitConfigDialog.cc                KPilot
**
** Copyright (C) 2001 by Dan Pilone
**
** This file defines a .ui-based configuration dialog for conduits.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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 in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
** MA 02139, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

static const char *conduitconfigdialog_id =
	"$Id$";

#include "options.h"

#include <qlistview.h>
#include <qlabel.h>
#include <qtooltip.h>
#include <qfile.h>
#include <qpushbutton.h>

#include <kservice.h>
#include <kservicetype.h>
#include <kuserprofile.h>
#include <kprocess.h>
#include <kmessagebox.h>
#include <kglobal.h>
#include <kstddirs.h>
#include <klibloader.h>

#include "plugin.h"
#include "kpilotConfig.h"

#include "conduitConfigDialog_base.h"
#include "conduitConfigDialog.moc"

#define CONDUIT_NAME    (0)
#define CONDUIT_COMMENT (1)
#define CONDUIT_DESKTOP (2)
#define CONDUIT_LIBRARY (3)

class ConduitTip : public QToolTip
{
public:
	ConduitTip(QListView *parent);
	virtual ~ConduitTip();

protected:
	virtual void maybeTip(const QPoint &);

	QListView *fListView;
} ;

ConduitTip::ConduitTip(QListView *p) :
	QToolTip(p->viewport(),0L),
	fListView(p)
{
	FUNCTIONSETUP;
}

ConduitTip::~ConduitTip()
{
	FUNCTIONSETUP;
}

/* virtual */ void ConduitTip::maybeTip(const QPoint &p)
{
	FUNCTIONSETUP;

	QListViewItem *l = fListView->itemAt(p);

	if (!l) return;

	// ConduitListItem *q = static_cast<ConduitListItem *>(l);

#ifdef DEBUG
	DEBUGKPILOT << fname
		<< ": Tip over "
		<< l->text(CONDUIT_NAME)
		<< " with text "
		<< l->text(CONDUIT_COMMENT)
		<< endl;
#endif

	QString s = l->text(CONDUIT_COMMENT);

	if (s.isEmpty()) return;
	if (s.find("<qt>",0,false) == -1)
	{
		s.prepend("<qt>");
		s.append("</qt>");
	}

	tip(fListView->itemRect(l),s);
}

ConduitConfigDialog::ConduitConfigDialog(QWidget * _w, const char *n,
	bool m) : UIDialog(_w, n, m)
{
	FUNCTIONSETUP;

	fConfigWidget = new ConduitConfigWidget(widget());

	fillLists();

	fConfigWidget->active->adjustSize();
	fConfigWidget->available->adjustSize();

	int w = QMAX(fConfigWidget->active->width(),
		fConfigWidget->available->width());

	fConfigWidget->available->resize(w,fConfigWidget->available->height());
	fConfigWidget->active->resize(w,fConfigWidget->active->height());
	fConfigWidget->available->setColumnWidth(0,w);
	fConfigWidget->active->setColumnWidth(0,w);
	fConfigWidget->available->setColumnWidthMode(0,QListView::Manual);
	fConfigWidget->active->setColumnWidthMode(0,QListView::Manual);

	QObject::connect(fConfigWidget->active,
		SIGNAL(selectionChanged(QListViewItem *)),
		this,SLOT(selected(QListViewItem *)));
	QObject::connect(fConfigWidget->available,
		SIGNAL(selectionChanged(QListViewItem *)),
		this,SLOT(selected(QListViewItem *)));
	QObject::connect(fConfigWidget->active,
		SIGNAL(doubleClicked(QListViewItem *)),
		this,SLOT(configureConduit()));

	QObject::connect(fConfigWidget->enableButton,
		SIGNAL(clicked()),
		this,SLOT(enableConduit()));
	QObject::connect(fConfigWidget->disableButton,
		SIGNAL(clicked()),
		this,SLOT(disableConduit()));
	QObject::connect(fConfigWidget->configButton,
		SIGNAL(clicked()),
		this,SLOT(configureConduit()));

	fConfigWidget->adjustSize();

	(void) new ConduitTip(fConfigWidget->active);
	(void) new ConduitTip(fConfigWidget->available);

	selected(0L);

	(void) conduitconfigdialog_id;
}

ConduitConfigDialog::~ConduitConfigDialog()
{
	FUNCTIONSETUP;
}

void ConduitConfigDialog::fillLists()
{
	FUNCTIONSETUP;

	QStringList potentiallyInstalled =
		KPilotConfig::getConfig().setConduitGroup().
		getInstalledConduits();
	KServiceTypeProfile::OfferList offers =
		KServiceTypeProfile::offers("KPilotConduit");

	// Now actually fill the two list boxes, just make
	// sure that nothing gets listed in both.
	//
	//
	QValueListIterator < KServiceOffer > availList(offers.begin());
	while (availList != offers.end())
	{
		KSharedPtr < KService > o = (*availList).service();

#ifdef DEBUG
		DEBUGKPILOT << fname << ": "
			<< o->desktopEntryName()
			<< " = " << o->name() << endl;
#endif

		QListViewItem *p = 0L;

		if (!o->exec().isEmpty())
		{
			kdWarning() << k_funcinfo
				<< ": Old-style conduit found "
				<< o->name()
				<< endl;
		}

		if (potentiallyInstalled.contains(o->desktopEntryName()) == 0)
		{
			p = new QListViewItem(fConfigWidget->available,
				o->name(),
				o->comment(),
				o->desktopEntryName(),
				o->library());
		}
		else
		{
			p = new QListViewItem(fConfigWidget->active,
				o->name(),
				o->comment(),
				o->desktopEntryName(),
				o->library());
		}

		++availList;
	}
}

void ConduitConfigDialog::selected(QListViewItem *p)
{
	FUNCTIONSETUP;

	if (!p)
	{
		fConfigWidget->configButton->setEnabled(false);
		fConfigWidget->enableButton->setEnabled(false);
		fConfigWidget->disableButton->setEnabled(false);
		return;
	}

	if (p->listView() == fConfigWidget->active)
	{
		fConfigWidget->configButton->setEnabled(true);
		fConfigWidget->enableButton->setEnabled(false);
		fConfigWidget->disableButton->setEnabled(true);
		fConfigWidget->available->clearSelection();
	}
	else
	{
		fConfigWidget->configButton->setEnabled(false);
		fConfigWidget->enableButton->setEnabled(true);
		fConfigWidget->disableButton->setEnabled(false);
		fConfigWidget->active->clearSelection();
	}
}

void ConduitConfigDialog::enableConduit()
{
	FUNCTIONSETUP;

	QListViewItem *l = fConfigWidget->available->currentItem();
	if (!l) return;

	fConfigWidget->available->takeItem(l);
	fConfigWidget->active->clearSelection();
	fConfigWidget->active->insertItem(l);
	fConfigWidget->active->setSelected(l,true);
	selected(l);
}

void ConduitConfigDialog::disableConduit()
{
	FUNCTIONSETUP;

	QListViewItem *l = fConfigWidget->active->currentItem();
	if (!l) return;

	fConfigWidget->active->takeItem(l);
	fConfigWidget->available->clearSelection();
	fConfigWidget->available->insertItem(l);
	fConfigWidget->available->setSelected(l,true);
	selected(l);
	fConfigWidget->available->setFocus();
}

void ConduitConfigDialog::configureConduit()
{
	FUNCTIONSETUP;

	QListViewItem *p = fConfigWidget->active->currentItem();

	if (!p)
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": Executed NULL conduit?"
			<< endl;
#endif
		return;
	}

#ifdef DEBUG
	DEBUGKPILOT << fname
		<< ": Executing conduit "
		<< p->text(CONDUIT_NAME)
		<< endl;
#endif

	if (p->text(CONDUIT_LIBRARY).isEmpty())
	{
		warnNoExec(p);
		return;
	}

	const char *library = p->text(CONDUIT_LIBRARY);

	KLibFactory *f = KLibLoader::self()->
		factory(library);
	if (!f)
	{
		DEBUGKPILOT << fname
			<< ": No conduit library "
			<< library
			<< " found."
			<< endl;
		warnNoLibrary(p);
		return;
	}

	QStringList a;
	a.append("modal");

	QObject *o = f->create(this, 0L, "ConduitConfig",a);

	if (!o)
	{
		DEBUGKPILOT << fname
			<< ": Can't create object."
			<< endl;

		KLibLoader::self()->unloadLibrary(
			library);
		warnNoLibrary(p);
		return;
	}

	ConduitConfig *d = dynamic_cast<ConduitConfig *>(o);

	if (!d)
	{
		DEBUGKPILOT << fname
			<< ": Can't cast to dialog."
			<< endl;
		delete o;
		KLibLoader::self()->unloadLibrary(
			library);
		warnNoLibrary(p);
		return;
	}

	d->setConfig(&KPilotConfig::getConfig());
	d->readSettings();
	d->exec();

	delete d;
	KLibLoader::self()->unloadLibrary(
		library);
}

void ConduitConfigDialog::warnNoExec(const QListViewItem * p)
{
	FUNCTIONSETUP;

	QString msg = i18n("<qt>No library could be "
		"found for the conduit %1. This means that the "
		"conduit was not installed properly.</qt>")
		.arg(p->text(CONDUIT_NAME));

#ifdef DEBUG
	DEBUGKPILOT << fname << ": " << msg << endl;
#endif

	KMessageBox::error(this, msg, i18n("Conduit error"));
}

void ConduitConfigDialog::warnNoLibrary(const QListViewItem *p)
{
	FUNCTIONSETUP;

	QString msg = i18n("<qt>There was a problem loading the library "
		"for the conduit %1. This means that the "
		"conduit was not installed properly.</qt>")
		.arg(p->text(CONDUIT_NAME));

	KMessageBox::error(this, msg, i18n("Conduit error"));
}

/* virtual */ void ConduitConfigDialog::commitChanges()
{
	FUNCTIONSETUP;

	QStringList activeConduits;
	const QListViewItem *p = fConfigWidget->active->firstChild();
	KPilotConfigSettings & config = KPilotConfig::getConfig();

	while (p)
	{
		activeConduits.append(p->text(CONDUIT_DESKTOP));
		p = p->nextSibling();
	}
	config.setConduitGroup().setInstalledConduits(activeConduits);
	config.sync();
}

// $Log$
// Revision 1.6  2002/01/02 11:42:19  bero
// Fix build.
//
// Revision 1.5  2001/12/31 09:26:15  adridg
// Removed support for old-style Exec= conduits
//
// Revision 1.4  2001/11/18 16:59:55  adridg
// New icons, DCOP changes
//
// Revision 1.3  2001/10/19 14:03:04  adridg
// Qt3 include fixes
//
// Revision 1.2  2001/10/08 22:20:18  adridg
// Changeover to libkpilot, prepare for lib-based conduits
//
// Revision 1.1  2001/10/04 16:53:57  adridg
// New files for newstyle config
//
<commit_msg>Minor debugging fixups by David B<commit_after>/* conduitConfigDialog.cc                KPilot
**
** Copyright (C) 2001 by Dan Pilone
**
** This file defines a .ui-based configuration dialog for conduits.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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 in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
** MA 02139, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

static const char *conduitconfigdialog_id =
	"$Id$";

#include "options.h"

#include <qlistview.h>
#include <qlabel.h>
#include <qtooltip.h>
#include <qfile.h>
#include <qpushbutton.h>

#include <kservice.h>
#include <kservicetype.h>
#include <kuserprofile.h>
#include <kprocess.h>
#include <kmessagebox.h>
#include <kglobal.h>
#include <kstddirs.h>
#include <klibloader.h>

#include "plugin.h"
#include "kpilotConfig.h"

#include "conduitConfigDialog_base.h"
#include "conduitConfigDialog.moc"

#define CONDUIT_NAME    (0)
#define CONDUIT_COMMENT (1)
#define CONDUIT_DESKTOP (2)
#define CONDUIT_LIBRARY (3)

class ConduitTip : public QToolTip
{
public:
	ConduitTip(QListView *parent);
	virtual ~ConduitTip();

protected:
	virtual void maybeTip(const QPoint &);

	QListView *fListView;
} ;

ConduitTip::ConduitTip(QListView *p) :
	QToolTip(p->viewport(),0L),
	fListView(p)
{
	FUNCTIONSETUP;
}

ConduitTip::~ConduitTip()
{
	FUNCTIONSETUP;
}

/* virtual */ void ConduitTip::maybeTip(const QPoint &p)
{
	FUNCTIONSETUP;

	QListViewItem *l = fListView->itemAt(p);

	if (!l) return;

	// ConduitListItem *q = static_cast<ConduitListItem *>(l);

#ifdef DEBUG
	DEBUGKPILOT << fname
		<< ": Tip over "
		<< l->text(CONDUIT_NAME)
		<< " with text "
		<< l->text(CONDUIT_COMMENT)
		<< endl;
#endif

	QString s = l->text(CONDUIT_COMMENT);

	if (s.isEmpty()) return;
	if (s.find("<qt>",0,false) == -1)
	{
		s.prepend("<qt>");
		s.append("</qt>");
	}

	tip(fListView->itemRect(l),s);
}

ConduitConfigDialog::ConduitConfigDialog(QWidget * _w, const char *n,
	bool m) : UIDialog(_w, n, m)
{
	FUNCTIONSETUP;

	fConfigWidget = new ConduitConfigWidget(widget());

	fillLists();

	fConfigWidget->active->adjustSize();
	fConfigWidget->available->adjustSize();

	int w = QMAX(fConfigWidget->active->width(),
		fConfigWidget->available->width());

	fConfigWidget->available->resize(w,fConfigWidget->available->height());
	fConfigWidget->active->resize(w,fConfigWidget->active->height());
	fConfigWidget->available->setColumnWidth(0,w);
	fConfigWidget->active->setColumnWidth(0,w);
	fConfigWidget->available->setColumnWidthMode(0,QListView::Manual);
	fConfigWidget->active->setColumnWidthMode(0,QListView::Manual);

	QObject::connect(fConfigWidget->active,
		SIGNAL(selectionChanged(QListViewItem *)),
		this,SLOT(selected(QListViewItem *)));
	QObject::connect(fConfigWidget->available,
		SIGNAL(selectionChanged(QListViewItem *)),
		this,SLOT(selected(QListViewItem *)));
	QObject::connect(fConfigWidget->active,
		SIGNAL(doubleClicked(QListViewItem *)),
		this,SLOT(configureConduit()));

	QObject::connect(fConfigWidget->enableButton,
		SIGNAL(clicked()),
		this,SLOT(enableConduit()));
	QObject::connect(fConfigWidget->disableButton,
		SIGNAL(clicked()),
		this,SLOT(disableConduit()));
	QObject::connect(fConfigWidget->configButton,
		SIGNAL(clicked()),
		this,SLOT(configureConduit()));

	fConfigWidget->adjustSize();

	(void) new ConduitTip(fConfigWidget->active);
	(void) new ConduitTip(fConfigWidget->available);

	selected(0L);

	(void) conduitconfigdialog_id;
}

ConduitConfigDialog::~ConduitConfigDialog()
{
	FUNCTIONSETUP;
}

void ConduitConfigDialog::fillLists()
{
	FUNCTIONSETUP;

	QStringList potentiallyInstalled =
		KPilotConfig::getConfig().setConduitGroup().
		getInstalledConduits();
	KServiceTypeProfile::OfferList offers =
		KServiceTypeProfile::offers("KPilotConduit");

	// Now actually fill the two list boxes, just make
	// sure that nothing gets listed in both.
	//
	//
	QValueListIterator < KServiceOffer > availList(offers.begin());
	while (availList != offers.end())
	{
		KSharedPtr < KService > o = (*availList).service();

#ifdef DEBUG
		DEBUGKPILOT << fname << ": "
			<< o->desktopEntryName()
			<< " = " << o->name() << endl;
#endif

		QListViewItem *p = 0L;

		if (!o->exec().isEmpty())
		{
			kdWarning() << k_funcinfo
				<< ": Old-style conduit found "
				<< o->name()
				<< endl;
		}

		if (potentiallyInstalled.contains(o->desktopEntryName()) == 0)
		{
			p = new QListViewItem(fConfigWidget->available,
				o->name(),
				o->comment(),
				o->desktopEntryName(),
				o->library());
		}
		else
		{
			p = new QListViewItem(fConfigWidget->active,
				o->name(),
				o->comment(),
				o->desktopEntryName(),
				o->library());
		}

		++availList;
	}
}

void ConduitConfigDialog::selected(QListViewItem *p)
{
	FUNCTIONSETUP;

	if (!p)
	{
		fConfigWidget->configButton->setEnabled(false);
		fConfigWidget->enableButton->setEnabled(false);
		fConfigWidget->disableButton->setEnabled(false);
		return;
	}

	if (p->listView() == fConfigWidget->active)
	{
		fConfigWidget->configButton->setEnabled(true);
		fConfigWidget->enableButton->setEnabled(false);
		fConfigWidget->disableButton->setEnabled(true);
		fConfigWidget->available->clearSelection();
	}
	else
	{
		fConfigWidget->configButton->setEnabled(false);
		fConfigWidget->enableButton->setEnabled(true);
		fConfigWidget->disableButton->setEnabled(false);
		fConfigWidget->active->clearSelection();
	}
}

void ConduitConfigDialog::enableConduit()
{
	FUNCTIONSETUP;

	QListViewItem *l = fConfigWidget->available->currentItem();
	if (!l) return;

	fConfigWidget->available->takeItem(l);
	fConfigWidget->active->clearSelection();
	fConfigWidget->active->insertItem(l);
	fConfigWidget->active->setSelected(l,true);
	selected(l);
}

void ConduitConfigDialog::disableConduit()
{
	FUNCTIONSETUP;

	QListViewItem *l = fConfigWidget->active->currentItem();
	if (!l) return;

	fConfigWidget->active->takeItem(l);
	fConfigWidget->available->clearSelection();
	fConfigWidget->available->insertItem(l);
	fConfigWidget->available->setSelected(l,true);
	selected(l);
	fConfigWidget->available->setFocus();
}

void ConduitConfigDialog::configureConduit()
{
	FUNCTIONSETUP;

	QListViewItem *p = fConfigWidget->active->currentItem();

	if (!p)
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": Executed NULL conduit?"
			<< endl;
#endif
		return;
	}

#ifdef DEBUG
	DEBUGKPILOT << fname
		<< ": Executing conduit "
		<< p->text(CONDUIT_NAME)
		<< endl;
#endif

	if (p->text(CONDUIT_LIBRARY).isEmpty())
	{
		warnNoExec(p);
		return;
	}

	const char *library = p->text(CONDUIT_LIBRARY);

	KLibFactory *f = KLibLoader::self()->
		factory(library);
	if (!f)
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": No conduit library "
			<< library
			<< " found."
			<< endl;
#endif
		warnNoLibrary(p);
		return;
	}

	QStringList a;
	a.append("modal");

	QObject *o = f->create(this, 0L, "ConduitConfig",a);

	if (!o)
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": Can't create object."
			<< endl;
#endif

		KLibLoader::self()->unloadLibrary(
			library);
		warnNoLibrary(p);
		return;
	}

	ConduitConfig *d = dynamic_cast<ConduitConfig *>(o);

	if (!d)
	{
#ifdef DEBUG
		DEBUGKPILOT << fname
			<< ": Can't cast to dialog."
			<< endl;
#endif

		delete o;
		KLibLoader::self()->unloadLibrary(
			library);
		warnNoLibrary(p);
		return;
	}

	d->setConfig(&KPilotConfig::getConfig());
	d->readSettings();
	d->exec();

	delete d;
	KLibLoader::self()->unloadLibrary(
		library);
}

void ConduitConfigDialog::warnNoExec(const QListViewItem * p)
{
	FUNCTIONSETUP;

	QString msg = i18n("<qt>No library could be "
		"found for the conduit %1. This means that the "
		"conduit was not installed properly.</qt>")
		.arg(p->text(CONDUIT_NAME));

#ifdef DEBUG
	DEBUGKPILOT << fname << ": " << msg << endl;
#endif

	KMessageBox::error(this, msg, i18n("Conduit error"));
}

void ConduitConfigDialog::warnNoLibrary(const QListViewItem *p)
{
	FUNCTIONSETUP;

	QString msg = i18n("<qt>There was a problem loading the library "
		"for the conduit %1. This means that the "
		"conduit was not installed properly.</qt>")
		.arg(p->text(CONDUIT_NAME));

	KMessageBox::error(this, msg, i18n("Conduit error"));
}

/* virtual */ void ConduitConfigDialog::commitChanges()
{
	FUNCTIONSETUP;

	QStringList activeConduits;
	const QListViewItem *p = fConfigWidget->active->firstChild();
	KPilotConfigSettings & config = KPilotConfig::getConfig();

	while (p)
	{
		activeConduits.append(p->text(CONDUIT_DESKTOP));
		p = p->nextSibling();
	}
	config.setConduitGroup().setInstalledConduits(activeConduits);
	config.sync();
}

// $Log$
// Revision 1.7  2002/01/26 15:00:11  adridg
// Dblclick to configure
//
// Revision 1.6  2002/01/02 11:42:19  bero
// Fix build.
//
// Revision 1.5  2001/12/31 09:26:15  adridg
// Removed support for old-style Exec= conduits
//
// Revision 1.4  2001/11/18 16:59:55  adridg
// New icons, DCOP changes
//
// Revision 1.3  2001/10/19 14:03:04  adridg
// Qt3 include fixes
//
// Revision 1.2  2001/10/08 22:20:18  adridg
// Changeover to libkpilot, prepare for lib-based conduits
//
// Revision 1.1  2001/10/04 16:53:57  adridg
// New files for newstyle config
//
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This test only works with the GPU backend.

#include "gm.h"

#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrProxyProvider.h"
#include "GrRenderTargetContextPriv.h"
#include "SkGradientShader.h"
#include "SkImage.h"
#include "SkImage_Base.h"
#include "SkSurface.h"
#include "effects/GrTextureDomain.h"
#include "ops/GrDrawOp.h"
#include "ops/GrFillRectOp.h"

namespace skiagm {
/**
 * This GM directly exercises GrTextureDomainEffect.
 */
class TextureDomainEffect : public GpuGM {
public:
    TextureDomainEffect(GrSamplerState::Filter filter)
            : fFilter(filter) {
        this->setBGColor(0xFFFFFFFF);
    }

protected:
    SkString onShortName() override {
        SkString name("texture_domain_effect");
        if (fFilter == GrSamplerState::Filter::kBilerp) {
            name.append("_bilerp");
        } else if (fFilter == GrSamplerState::Filter::kMipMap) {
            name.append("_mipmap");
        }
        return name;
    }

    SkISize onISize() override {
        const SkScalar canvasWidth = kDrawPad +
                (kTargetWidth + 2 * kDrawPad) * GrTextureDomain::kModeCount +
                kTestPad * GrTextureDomain::kModeCount;
        return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
    }

    void onOnceBeforeDraw() override {
        // TODO: do this with gpu backend
        SkImageInfo ii = SkImageInfo::Make(kTargetWidth, kTargetHeight, kN32_SkColorType,
                                           kPremul_SkAlphaType);
        auto surface = SkSurface::MakeRaster(ii);
        SkCanvas* canvas = surface->getCanvas();
        canvas->clear(0x00000000);
        SkPaint paint;

        SkColor colors1[] = { SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGRAY };
        paint.setShader(SkGradientShader::MakeSweep(65.f, 75.f, colors1, nullptr,
                                                    SK_ARRAY_COUNT(colors1)));
        canvas->drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                         paint);

        SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
        paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
                                                    SK_ARRAY_COUNT(colors2)));
        paint.setBlendMode(SkBlendMode::kDarken);
        canvas->drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                         paint);

        SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
        paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
                                                    SK_ARRAY_COUNT(colors3)));
        paint.setBlendMode(SkBlendMode::kLighten);
        canvas->drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                         paint);

        fImage = surface->makeImageSnapshot();
    }

    DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
                      SkCanvas* canvas, SkString* errorMsg) override {
        GrProxyProvider* proxyProvider = context->priv().proxyProvider();
        sk_sp<GrTextureProxy> proxy;
        if (fFilter == GrSamplerState::Filter::kMipMap) {
            SkBitmap copy;
            SkImageInfo info = fImage->imageInfo().makeColorType(kN32_SkColorType);
            if (!copy.tryAllocPixels(info) || !fImage->readPixels(copy.pixmap(), 0, 0)) {
                *errorMsg = "Failed to read pixels.";
                return DrawResult::kFail;
            }
            proxy = proxyProvider->createProxyFromBitmap(copy, GrMipMapped::kYes);
        } else {
            proxy = proxyProvider->createTextureProxy(
                fImage, kNone_GrSurfaceFlags, 1, SkBudgeted::kYes, SkBackingFit::kExact);
        }
        if (!proxy) {
            *errorMsg = "Failed to create proxy.";
            return DrawResult::kFail;
        }

        SkTArray<SkMatrix> textureMatrices;
        textureMatrices.push_back() = SkMatrix::I();
        textureMatrices.push_back() = SkMatrix::MakeScale(1.5f, 0.85f);
        textureMatrices.push_back();
        textureMatrices.back().setRotate(45.f, proxy->width() / 2.f, proxy->height() / 2.f);

        const SkIRect texelDomains[] = {
            fImage->bounds(),
            SkIRect::MakeXYWH(fImage->width() / 4 - 1, fImage->height() / 4 - 1,
                              fImage->width() / 2 + 2, fImage->height() / 2 + 2),
        };

        SkRect renderRect = SkRect::Make(fImage->bounds());
        renderRect.outset(kDrawPad, kDrawPad);

        SkScalar y = kDrawPad + kTestPad;
        for (int tm = 0; tm < textureMatrices.count(); ++tm) {
            for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
                SkScalar x = kDrawPad + kTestPad;
                for (int m = 0; m < GrTextureDomain::kModeCount; ++m) {
                    GrTextureDomain::Mode mode = (GrTextureDomain::Mode) m;
                    if (fFilter != GrSamplerState::Filter::kNearest &&
                        mode == GrTextureDomain::kRepeat_Mode) {
                        // Repeat mode doesn't produce correct results with bilerp filtering
                        continue;
                    }

                    GrPaint grPaint;
                    grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
                    auto fp = GrTextureDomainEffect::Make(
                            proxy, textureMatrices[tm],
                            GrTextureDomain::MakeTexelDomain(texelDomains[d], mode),
                            mode, fFilter);

                    if (!fp) {
                        continue;
                    }
                    const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y);
                    grPaint.addColorFragmentProcessor(std::move(fp));
                    renderTargetContext->priv().testingOnly_addDrawOp(
                            GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone,
                                               viewMatrix, renderRect));
                    x += renderRect.width() + kTestPad;
                }
                y += renderRect.height() + kTestPad;
            }
        }
        return DrawResult::kOk;
    }

private:
    static constexpr SkScalar kDrawPad = 10.f;
    static constexpr SkScalar kTestPad = 10.f;
    static constexpr int      kTargetWidth = 100;
    static constexpr int      kTargetHeight = 100;
    sk_sp<SkImage> fImage;
    GrSamplerState::Filter fFilter;

    typedef GM INHERITED;
};

DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kNearest);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kBilerp);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kMipMap);)

}
<commit_msg>Fix GM that was trying to create mip-mapped proxies without checking caps<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This test only works with the GPU backend.

#include "gm.h"

#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrProxyProvider.h"
#include "GrRenderTargetContextPriv.h"
#include "SkGradientShader.h"
#include "SkImage.h"
#include "SkImage_Base.h"
#include "SkSurface.h"
#include "effects/GrTextureDomain.h"
#include "ops/GrDrawOp.h"
#include "ops/GrFillRectOp.h"

namespace skiagm {
/**
 * This GM directly exercises GrTextureDomainEffect.
 */
class TextureDomainEffect : public GpuGM {
public:
    TextureDomainEffect(GrSamplerState::Filter filter)
            : fFilter(filter) {
        this->setBGColor(0xFFFFFFFF);
    }

protected:
    SkString onShortName() override {
        SkString name("texture_domain_effect");
        if (fFilter == GrSamplerState::Filter::kBilerp) {
            name.append("_bilerp");
        } else if (fFilter == GrSamplerState::Filter::kMipMap) {
            name.append("_mipmap");
        }
        return name;
    }

    SkISize onISize() override {
        const SkScalar canvasWidth = kDrawPad +
                (kTargetWidth + 2 * kDrawPad) * GrTextureDomain::kModeCount +
                kTestPad * GrTextureDomain::kModeCount;
        return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
    }

    void onOnceBeforeDraw() override {
        // TODO: do this with gpu backend
        SkImageInfo ii = SkImageInfo::Make(kTargetWidth, kTargetHeight, kN32_SkColorType,
                                           kPremul_SkAlphaType);
        auto surface = SkSurface::MakeRaster(ii);
        SkCanvas* canvas = surface->getCanvas();
        canvas->clear(0x00000000);
        SkPaint paint;

        SkColor colors1[] = { SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGRAY };
        paint.setShader(SkGradientShader::MakeSweep(65.f, 75.f, colors1, nullptr,
                                                    SK_ARRAY_COUNT(colors1)));
        canvas->drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                         paint);

        SkColor colors2[] = { SK_ColorMAGENTA, SK_ColorLTGRAY, SK_ColorYELLOW };
        paint.setShader(SkGradientShader::MakeSweep(45.f, 55.f, colors2, nullptr,
                                                    SK_ARRAY_COUNT(colors2)));
        paint.setBlendMode(SkBlendMode::kDarken);
        canvas->drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                         paint);

        SkColor colors3[] = { SK_ColorBLUE, SK_ColorLTGRAY, SK_ColorGREEN };
        paint.setShader(SkGradientShader::MakeSweep(25.f, 35.f, colors3, nullptr,
                                                    SK_ARRAY_COUNT(colors3)));
        paint.setBlendMode(SkBlendMode::kLighten);
        canvas->drawOval(SkRect::MakeXYWH(-5.f, -5.f, kTargetWidth + 10.f, kTargetHeight + 10.f),
                         paint);

        fImage = surface->makeImageSnapshot();
    }

    DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
                      SkCanvas* canvas, SkString* errorMsg) override {
        GrProxyProvider* proxyProvider = context->priv().proxyProvider();
        sk_sp<GrTextureProxy> proxy;
        if (fFilter == GrSamplerState::Filter::kMipMap && context->priv().caps()->mipMapSupport()) {
            SkBitmap copy;
            SkImageInfo info = fImage->imageInfo().makeColorType(kN32_SkColorType);
            if (!copy.tryAllocPixels(info) || !fImage->readPixels(copy.pixmap(), 0, 0)) {
                *errorMsg = "Failed to read pixels.";
                return DrawResult::kFail;
            }
            proxy = proxyProvider->createProxyFromBitmap(copy, GrMipMapped::kYes);
        } else {
            proxy = proxyProvider->createTextureProxy(
                fImage, kNone_GrSurfaceFlags, 1, SkBudgeted::kYes, SkBackingFit::kExact);
        }
        if (!proxy) {
            *errorMsg = "Failed to create proxy.";
            return DrawResult::kFail;
        }

        SkTArray<SkMatrix> textureMatrices;
        textureMatrices.push_back() = SkMatrix::I();
        textureMatrices.push_back() = SkMatrix::MakeScale(1.5f, 0.85f);
        textureMatrices.push_back();
        textureMatrices.back().setRotate(45.f, proxy->width() / 2.f, proxy->height() / 2.f);

        const SkIRect texelDomains[] = {
            fImage->bounds(),
            SkIRect::MakeXYWH(fImage->width() / 4 - 1, fImage->height() / 4 - 1,
                              fImage->width() / 2 + 2, fImage->height() / 2 + 2),
        };

        SkRect renderRect = SkRect::Make(fImage->bounds());
        renderRect.outset(kDrawPad, kDrawPad);

        SkScalar y = kDrawPad + kTestPad;
        for (int tm = 0; tm < textureMatrices.count(); ++tm) {
            for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
                SkScalar x = kDrawPad + kTestPad;
                for (int m = 0; m < GrTextureDomain::kModeCount; ++m) {
                    GrTextureDomain::Mode mode = (GrTextureDomain::Mode) m;
                    if (fFilter != GrSamplerState::Filter::kNearest &&
                        mode == GrTextureDomain::kRepeat_Mode) {
                        // Repeat mode doesn't produce correct results with bilerp filtering
                        continue;
                    }

                    GrPaint grPaint;
                    grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
                    auto fp = GrTextureDomainEffect::Make(
                            proxy, textureMatrices[tm],
                            GrTextureDomain::MakeTexelDomain(texelDomains[d], mode),
                            mode, fFilter);

                    if (!fp) {
                        continue;
                    }
                    const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y);
                    grPaint.addColorFragmentProcessor(std::move(fp));
                    renderTargetContext->priv().testingOnly_addDrawOp(
                            GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone,
                                               viewMatrix, renderRect));
                    x += renderRect.width() + kTestPad;
                }
                y += renderRect.height() + kTestPad;
            }
        }
        return DrawResult::kOk;
    }

private:
    static constexpr SkScalar kDrawPad = 10.f;
    static constexpr SkScalar kTestPad = 10.f;
    static constexpr int      kTargetWidth = 100;
    static constexpr int      kTargetHeight = 100;
    sk_sp<SkImage> fImage;
    GrSamplerState::Filter fFilter;

    typedef GM INHERITED;
};

DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kNearest);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kBilerp);)
DEF_GM(return new TextureDomainEffect(GrSamplerState::Filter::kMipMap);)

}
<|endoftext|>


<commit_before>/**
 * @file windows_volume_catcher.cpp
 * @brief A Windows implementation of volume level control of all audio channels opened by a process.
 *
 * @cond
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 * @endcond
 */

#include "volume_catcher.h"
#include <windows.h>
#include "llsingleton.h"
class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl>
{
friend LLSingleton<VolumeCatcherImpl>;
public:

	void setVolume(F32 volume);
	void setPan(F32 pan);

private:
	// This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance.
	VolumeCatcherImpl();
	~VolumeCatcherImpl();

	typedef void (WINAPI *set_volume_func_t)(F32);
	typedef void (WINAPI *set_mute_func_t)(bool);

	set_volume_func_t mSetVolumeFunc;
	set_mute_func_t mSetMuteFunc;

	F32 	mVolume;
	F32 	mPan;
};
VolumeCatcherImpl::VolumeCatcherImpl()
:	mVolume(1.0f),	// default volume is max
	mPan(0.f)		// default pan is centered
{
	HMODULE handle = ::LoadLibrary(L"winmm.dll");
	if(handle)
	{
		mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume");
		mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute");
	}
}

VolumeCatcherImpl::~VolumeCatcherImpl()
{
}

void VolumeCatcherImpl::setVolume(F32 volume)
{
	mVolume = volume;

	if (mSetMuteFunc)
	{
		mSetMuteFunc(volume == 0.f);
	}
	if (mSetVolumeFunc)
	{
		mSetVolumeFunc(mVolume);
	}
}

void VolumeCatcherImpl::setPan(F32 pan)
{	// remember pan for calculating individual channel levels later
	mPan = pan;
}

/////////////////////////////////////////////////////

VolumeCatcher::VolumeCatcher()
{
	pimpl = VolumeCatcherImpl::getInstance();
}

VolumeCatcher::~VolumeCatcher()
{
	// Let the instance persist until exit.
}

void VolumeCatcher::setVolume(F32 volume)
{
	pimpl->setVolume(volume);
}

void VolumeCatcher::setPan(F32 pan)
{
	pimpl->setPan(pan);
}

void VolumeCatcher::pump()
{
	// No periodic tasks are necessary for this implementation.
}

<commit_msg>FIX (SPECULATIVE) MAINT-1340 - Media Volume control broken on Vista+ systems<commit_after>/**
 * @file windows_volume_catcher.cpp
 * @brief A Windows implementation of volume level control of all audio channels opened by a process.
 *
 * @cond
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 * @endcond
 */

#include "volume_catcher.h"
#include <windows.h>
#include "llsingleton.h"
class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl>
{
friend LLSingleton<VolumeCatcherImpl>;
public:

	void setVolume(F32 volume);
	void setPan(F32 pan);

private:
	// This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance.
	VolumeCatcherImpl();
	~VolumeCatcherImpl();

	typedef void (WINAPI *set_volume_func_t)(F32);
	typedef void (WINAPI *set_mute_func_t)(bool);

	set_volume_func_t mSetVolumeFunc;
	set_mute_func_t mSetMuteFunc;

	// tests if running on Vista, 7, 8 + once in CTOR
	bool isWindowsVistaOrHigher();

	F32 	mVolume;
	F32 	mPan;
	bool mSystemIsVistaOrHigher;
};

bool VolumeCatcherImpl::isWindowsVistaOrHigher()
{
	OSVERSIONINFO osvi;
	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osvi);
	return osvi.dwMajorVersion >= 6;
}

VolumeCatcherImpl::VolumeCatcherImpl()
:	mVolume(1.0f),			// default volume is max
	mPan(0.f)				// default pan is centered
{
	mSystemIsVistaOrHigher = isWindowsVistaOrHigher();

	if ( mSystemIsVistaOrHigher )
	{
		HMODULE handle = ::LoadLibrary(L"winmm.dll");
		if(handle)
		{
			mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume");
			mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute");
		}
	}
}

VolumeCatcherImpl::~VolumeCatcherImpl()
{
}

void VolumeCatcherImpl::setVolume(F32 volume)
{
	mVolume = volume;

	if ( mSystemIsVistaOrHigher )
	{
		// set both left/right to same volume
		// TODO: use pan value to set independently
		DWORD left_channel  = (DWORD)(mVolume * 65535.0f);
		DWORD right_channel =  (DWORD)(mVolume * 65535.0f);
		DWORD hw_volume = left_channel << 16 | right_channel;
		::waveOutSetVolume(NULL, hw_volume);
	}
	else
	{
		if (mSetMuteFunc)
		{
			mSetMuteFunc(volume == 0.f);
		}
		if (mSetVolumeFunc)
		{
			mSetVolumeFunc(mVolume);
		}
	}
}

void VolumeCatcherImpl::setPan(F32 pan)
{	// remember pan for calculating individual channel levels later
	mPan = pan;
}

/////////////////////////////////////////////////////

VolumeCatcher::VolumeCatcher()
{
	pimpl = VolumeCatcherImpl::getInstance();
}

VolumeCatcher::~VolumeCatcher()
{
	// Let the instance persist until exit.
}

void VolumeCatcher::setVolume(F32 volume)
{
	pimpl->setVolume(volume);
}

void VolumeCatcher::setPan(F32 pan)
{
	pimpl->setPan(pan);
}

void VolumeCatcher::pump()
{
	// No periodic tasks are necessary for this implementation.
}

<|endoftext|>


<commit_before>/**
 * @file llupdateinstaller.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <apr_file_io.h>
#include <boost/lexical_cast.hpp>
#include "llapr.h"
#include "llprocesslauncher.h"
#include "llupdateinstaller.h"
#include "lldir.h"

namespace {
	class RelocateError {};

	std::string copy_to_temp(std::string const & path)
	{
		std::string scriptFile = gDirUtilp->getBaseFileName(path);
		std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
		apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
		if(status != APR_SUCCESS) throw RelocateError();

		return newPath;
	}
}

int ll_install_update(std::string const & script,
					  std::string const & updatePath,
					  bool required,
					  LLInstallScriptMode mode)
{
	std::string actualScriptPath;
	switch(mode) {
		case LL_COPY_INSTALL_SCRIPT_TO_TEMP:
			try {
				actualScriptPath = copy_to_temp(script);
			}
			catch (RelocateError &) {
				return -1;
			}
			break;
		case LL_RUN_INSTALL_SCRIPT_IN_PLACE:
			actualScriptPath = script;
			break;
		default:
			llassert(!"unpossible copy mode");
	}

	llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
		actualScriptPath << LL_ENDL;

	LLProcessLauncher launcher;
	launcher.setExecutable(actualScriptPath);
	launcher.addArgument(updatePath);
	launcher.addArgument(ll_install_failed_marker_path().c_str());
	launcher.addArgument(boost::lexical_cast<std::string>(required));
	int result = launcher.launch();
	launcher.orphan();

	return result;
}

std::string const & ll_install_failed_marker_path(void)
{
	static std::string path;
	if(path.empty()) {
		path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeInstallFailed.marker");
	}
	return path;
}
<commit_msg>fix windows build (suppress warning from lexical_cast)<commit_after>/**
 * @file llupdateinstaller.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#pragma warning(disable: 4702)      // disable 'unreachable code' so we can use lexical_cast (really!).

#include "linden_common.h"
#include <apr_file_io.h>
#include <boost/lexical_cast.hpp>
#include "llapr.h"
#include "llprocesslauncher.h"
#include "llupdateinstaller.h"
#include "lldir.h"

namespace {
	class RelocateError {};

	std::string copy_to_temp(std::string const & path)
	{
		std::string scriptFile = gDirUtilp->getBaseFileName(path);
		std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
		apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
		if(status != APR_SUCCESS) throw RelocateError();

		return newPath;
	}
}

int ll_install_update(std::string const & script,
					  std::string const & updatePath,
					  bool required,
					  LLInstallScriptMode mode)
{
	std::string actualScriptPath;
	switch(mode) {
		case LL_COPY_INSTALL_SCRIPT_TO_TEMP:
			try {
				actualScriptPath = copy_to_temp(script);
			}
			catch (RelocateError &) {
				return -1;
			}
			break;
		case LL_RUN_INSTALL_SCRIPT_IN_PLACE:
			actualScriptPath = script;
			break;
		default:
			llassert(!"unpossible copy mode");
	}

	llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
		actualScriptPath << LL_ENDL;

	LLProcessLauncher launcher;
	launcher.setExecutable(actualScriptPath);
	launcher.addArgument(updatePath);
	launcher.addArgument(ll_install_failed_marker_path().c_str());
	launcher.addArgument(boost::lexical_cast<std::string>(required));
	int result = launcher.launch();
	launcher.orphan();

	return result;
}

std::string const & ll_install_failed_marker_path(void)
{
	static std::string path;
	if(path.empty()) {
		path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeInstallFailed.marker");
	}
	return path;
}
<|endoftext|>