<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: RangeHighlighter.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 17:47:11 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "RangeHighlighter.hxx"
#include "WeakListenerAdapter.hxx"
#include "ChartModelHelper.hxx"
#include "DataSourceHelper.hxx"
#include "ContainerHelper.hxx"
#include "macros.hxx"
#include "ObjectIdentifier.hxx"

#include <com/sun/star/chart2/XDataSeries.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>

#define PREFERED_DEFAULT_COLOR 0x0000ff

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

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;

namespace
{

void lcl_fillRanges(
    Sequence< chart2::data::HighlightedRange > & rOutRanges,
    Sequence< OUString > aRangeStrings,
    sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR,
    sal_Int32 nIndex = -1 )
{
    rOutRanges.realloc( aRangeStrings.getLength());
    for( sal_Int32 i=0; i<aRangeStrings.getLength(); ++i )
    {
        rOutRanges[i].RangeRepresentation = aRangeStrings[i];
        rOutRanges[i].PreferredColor = nPreferredColor;
        rOutRanges[i].AllowMerginigWithOtherRanges = sal_False;
        rOutRanges[i].Index = nIndex;
    }
}

sal_Int32 lcl_getColor( const Reference< beans::XPropertySet > & xProp )
{
    sal_Int32 nResult = PREFERED_DEFAULT_COLOR;

    try
    {
        if( xProp.is())
            xProp->getPropertyValue( C2U("Color")) >>= nResult;
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }

    return nResult;
}

} // anonymous namespace

namespace chart
{

RangeHighlighter::RangeHighlighter(
    const Reference< view::XSelectionSupplier > & xSelectionSupplier ) :
        impl::RangeHighlighter_Base( m_aMutex ),
        m_xSelectionSupplier( xSelectionSupplier ),
        m_nAddedListenerCount( 0 )
{
}

RangeHighlighter::~RangeHighlighter()
{}

// ____ XRangeHighlighter ____
Sequence< chart2::data::HighlightedRange > SAL_CALL RangeHighlighter::getSelectedRanges()
    throw (uno::RuntimeException)
{
    return m_aSelectedRanges;
}

void RangeHighlighter::determineRanges()
{
    m_aSelectedRanges.realloc( 0 );
    if( m_xSelectionSupplier.is())
    {
        try
        {
            Reference< frame::XController > xController( m_xSelectionSupplier, uno::UNO_QUERY );
            Reference< frame::XModel > xChartModel;
            if( xController.is())
                xChartModel.set( xController->getModel());

            uno::Any aSelection( m_xSelectionSupplier->getSelection());
            OUString aCID;
            if(( aSelection >>= aCID ) &&
               aCID.getLength() > 0 )
            {
                // @todo??: maybe getSelection() should return a model object rather than a CID

                ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
                sal_Int32 nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aCID );
                Reference< chart2::XDataSeries > xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID, xChartModel ) );
                if( OBJECTTYPE_LEGEND_ENTRY == eObjectType )
                {
                    OUString aParentParticel( ObjectIdentifier::getFullParentParticle( aCID ) );
                    ObjectType eParentObjectType = ObjectIdentifier::getObjectType( aParentParticel );
                    eObjectType = eParentObjectType;
                    if( OBJECTTYPE_DATA_POINT == eObjectType )
                        nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aParentParticel );
                }

                if( OBJECTTYPE_DATA_POINT == eObjectType || OBJECTTYPE_DATA_LABEL == eObjectType )
                {
                    // Data Point
                    fillRangesForDataPoint( xDataSeries, nIndex );
                    return;
                }
                else if( OBJECTTYPE_DATA_ERRORS == eObjectType )
                {
                    // select error bar ranges, or data series, if the style is
                    // not set to FROM_DATA
                    fillRangesForErrorBars( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), xDataSeries );
                    return;
                }
                else if( xDataSeries.is() )
                {
                    // Data Series
                    fillRangesForDataSeries( xDataSeries );
                    return;
                }
                else if( OBJECTTYPE_AXIS == eObjectType )
                {
                    // Axis (Categories)
                    Reference< chart2::XAxis > xAxis( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), uno::UNO_QUERY );
                    if( xAxis.is())
                    {
                        fillRangesForCategories( xAxis );
                        return;
                    }
                }
                else if( OBJECTTYPE_PAGE == eObjectType
                         || OBJECTTYPE_DIAGRAM == eObjectType
                         || OBJECTTYPE_DIAGRAM_WALL == eObjectType
                         || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType
                    )
                {
                    // Diagram
                    Reference< chart2::XDiagram > xDia( ObjectIdentifier::getDiagramForCID( aCID, xChartModel ) );
                    if( xDia.is())
                    {
                        fillRangesForDiagram( xDia );
                        return;
                    }
                }
            }
            else
            {
                //if nothing is selected select all ranges
                Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY_THROW );
                fillRangesForDiagram( xChartDoc->getFirstDiagram() );
                return;
            }
        }
        catch( const uno::Exception & ex )
        {
            ASSERT_EXCEPTION( ex );
        }
    }
}

void RangeHighlighter::fillRangesForDiagram( const Reference< chart2::XDiagram > & xDiagram )
{
    Sequence< OUString > aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram ));
    m_aSelectedRanges.realloc( aSelectedRanges.getLength());
    // @todo: merge ranges
    for( sal_Int32 i=0; i<aSelectedRanges.getLength(); ++i )
    {
        m_aSelectedRanges[i].RangeRepresentation = aSelectedRanges[i];
        m_aSelectedRanges[i].Index = -1;
        m_aSelectedRanges[i].PreferredColor = PREFERED_DEFAULT_COLOR;
        m_aSelectedRanges[i].AllowMerginigWithOtherRanges = sal_True;
    }
}

void RangeHighlighter::fillRangesForDataSeries( const uno::Reference< chart2::XDataSeries > & xSeries )
{
    sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR;
//         lcl_getColor( Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ));
    Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
    if( xSource.is())
        lcl_fillRanges( m_aSelectedRanges,
                        ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
                        nPreferredColor );
}

void RangeHighlighter::fillRangesForErrorBars(
    const uno::Reference< beans::XPropertySet > & xErrorBar,
    const uno::Reference< chart2::XDataSeries > & xSeries )
{
    // only show error bar ranges, if the style is set to FROM_DATA
    bool bUsesRangesAsErrorBars = false;
    try
    {
        sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
        bUsesRangesAsErrorBars =
            ( xErrorBar.is() &&
              (xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle) &&
              nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }

    if( bUsesRangesAsErrorBars )
    {
        sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR;
        Reference< chart2::data::XDataSource > xSource( xErrorBar, uno::UNO_QUERY );
        if( xSource.is())
            lcl_fillRanges( m_aSelectedRanges,
                            ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
                            nPreferredColor );
    }
    else
    {
        fillRangesForDataSeries( xSeries );
    }
}

void RangeHighlighter::fillRangesForCategories( const Reference< chart2::XAxis > & xAxis )
{
    if( ! xAxis.is())
        return;
    chart2::ScaleData aData( xAxis->getScaleData());
    lcl_fillRanges( m_aSelectedRanges,
                    DataSourceHelper::getRangesFromLabeledDataSequence( aData.Categories ));
}

void RangeHighlighter::fillRangesForDataPoint( const Reference< uno::XInterface > & xDataSeries, sal_Int32 nIndex )
{
    sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR;
//         lcl_getColor( Reference< beans::XPropertySet >( xDataPoint, uno::UNO_QUERY ));
    if( xDataSeries.is())
    {
        Reference< chart2::data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY );
        if( xSource.is() )
        {
            ::std::vector< chart2::data::HighlightedRange > aHilightedRanges;
            Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences());
            for( sal_Int32 i=0; i<aLSeqSeq.getLength(); ++i )
            {
                Reference< chart2::data::XDataSequence > xLabel( aLSeqSeq[i]->getLabel());
                Reference< chart2::data::XDataSequence > xValues( aLSeqSeq[i]->getValues());

                if( xLabel.is())
                    aHilightedRanges.push_back(
                        chart2::data::HighlightedRange(
                            xLabel->getSourceRangeRepresentation(),
                            -1,
                            nPreferredColor,
                            sal_False ));
                if( xValues.is())
                    aHilightedRanges.push_back(
                        chart2::data::HighlightedRange(
                            xValues->getSourceRangeRepresentation(),
                            nIndex,
                            nPreferredColor,
                            sal_False ));
            }
            m_aSelectedRanges = ContainerHelper::ContainerToSequence( aHilightedRanges );
        }
    }
}

void SAL_CALL RangeHighlighter::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
    throw (uno::RuntimeException)
{
    if(!xListener.is())
        return;

    if( m_nAddedListenerCount == 0 )
        startListening();
    rBHelper.addListener( ::getCppuType( & xListener ), xListener);
    ++m_nAddedListenerCount;

    //bring the new listener up to the current state
    lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
    xListener->selectionChanged( aEvent );
}

void SAL_CALL RangeHighlighter::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
    throw (uno::RuntimeException)
{
    rBHelper.removeListener( ::getCppuType( & xListener ), xListener );
    --m_nAddedListenerCount;
    if( m_nAddedListenerCount == 0 )
        stopListening();
}

// ____ XSelectionChangeListener ____
void SAL_CALL RangeHighlighter::selectionChanged( const lang::EventObject& /*aEvent*/ )
    throw (uno::RuntimeException)
{
    determineRanges();

    // determine ranges of selected view objects
    // if changed, fire an event
    fireSelectionEvent();
}

void RangeHighlighter::fireSelectionEvent()
{
    ::cppu::OInterfaceContainerHelper* pIC = rBHelper.getContainer(
        ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0) );
    if( pIC )
    {
        lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
        ::cppu::OInterfaceIteratorHelper aIt( *pIC );
        while( aIt.hasMoreElements() )
            (static_cast< view::XSelectionChangeListener*>(aIt.next()))->selectionChanged( aEvent );
    }
}

void SAL_CALL RangeHighlighter::disposing( const lang::EventObject& Source )
    throw (uno::RuntimeException)
{
    if( Source.Source == m_xSelectionSupplier )
    {
        m_xSelectionSupplier.clear();
        m_aSelectedRanges.realloc( 0 );
        fireSelectionEvent();
    }
}

void RangeHighlighter::startListening()
{
    if( m_xSelectionSupplier.is())
    {
        if( ! m_xListener.is())
        {
            m_xListener.set( new WeakSelectionChangeListenerAdapter( this ));
            determineRanges();
        }
        m_xSelectionSupplier->addSelectionChangeListener( m_xListener );
    }
}

void RangeHighlighter::stopListening()
{
    if( m_xSelectionSupplier.is() && m_xListener.is())
    {
        m_xSelectionSupplier->removeSelectionChangeListener( m_xListener );
        m_xListener.clear();
    }
}

// ____ WeakComponentImplHelperBase ____
// is called when dispose() is called at this component
void SAL_CALL RangeHighlighter::disposing()
{
    // @todo: remove listener. Currently the controller shows an assertion
    // because it is already disposed
//     stopListening();
    m_xListener.clear();
    m_xSelectionSupplier.clear();
    m_nAddedListenerCount =  0;
    m_aSelectedRanges.realloc( 0 );
}

} //  namespace chart
<commit_msg>INTEGRATION: CWS changefileheader (1.5.20); FILE MERGED 2008/03/28 16:44:24 rt 1.5.20.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: RangeHighlighter.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "RangeHighlighter.hxx"
#include "WeakListenerAdapter.hxx"
#include "ChartModelHelper.hxx"
#include "DataSourceHelper.hxx"
#include "ContainerHelper.hxx"
#include "macros.hxx"
#include "ObjectIdentifier.hxx"

#include <com/sun/star/chart2/XDataSeries.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>

#define PREFERED_DEFAULT_COLOR 0x0000ff

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

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;

namespace
{

void lcl_fillRanges(
    Sequence< chart2::data::HighlightedRange > & rOutRanges,
    Sequence< OUString > aRangeStrings,
    sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR,
    sal_Int32 nIndex = -1 )
{
    rOutRanges.realloc( aRangeStrings.getLength());
    for( sal_Int32 i=0; i<aRangeStrings.getLength(); ++i )
    {
        rOutRanges[i].RangeRepresentation = aRangeStrings[i];
        rOutRanges[i].PreferredColor = nPreferredColor;
        rOutRanges[i].AllowMerginigWithOtherRanges = sal_False;
        rOutRanges[i].Index = nIndex;
    }
}

sal_Int32 lcl_getColor( const Reference< beans::XPropertySet > & xProp )
{
    sal_Int32 nResult = PREFERED_DEFAULT_COLOR;

    try
    {
        if( xProp.is())
            xProp->getPropertyValue( C2U("Color")) >>= nResult;
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }

    return nResult;
}

} // anonymous namespace

namespace chart
{

RangeHighlighter::RangeHighlighter(
    const Reference< view::XSelectionSupplier > & xSelectionSupplier ) :
        impl::RangeHighlighter_Base( m_aMutex ),
        m_xSelectionSupplier( xSelectionSupplier ),
        m_nAddedListenerCount( 0 )
{
}

RangeHighlighter::~RangeHighlighter()
{}

// ____ XRangeHighlighter ____
Sequence< chart2::data::HighlightedRange > SAL_CALL RangeHighlighter::getSelectedRanges()
    throw (uno::RuntimeException)
{
    return m_aSelectedRanges;
}

void RangeHighlighter::determineRanges()
{
    m_aSelectedRanges.realloc( 0 );
    if( m_xSelectionSupplier.is())
    {
        try
        {
            Reference< frame::XController > xController( m_xSelectionSupplier, uno::UNO_QUERY );
            Reference< frame::XModel > xChartModel;
            if( xController.is())
                xChartModel.set( xController->getModel());

            uno::Any aSelection( m_xSelectionSupplier->getSelection());
            OUString aCID;
            if(( aSelection >>= aCID ) &&
               aCID.getLength() > 0 )
            {
                // @todo??: maybe getSelection() should return a model object rather than a CID

                ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
                sal_Int32 nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aCID );
                Reference< chart2::XDataSeries > xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID, xChartModel ) );
                if( OBJECTTYPE_LEGEND_ENTRY == eObjectType )
                {
                    OUString aParentParticel( ObjectIdentifier::getFullParentParticle( aCID ) );
                    ObjectType eParentObjectType = ObjectIdentifier::getObjectType( aParentParticel );
                    eObjectType = eParentObjectType;
                    if( OBJECTTYPE_DATA_POINT == eObjectType )
                        nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aParentParticel );
                }

                if( OBJECTTYPE_DATA_POINT == eObjectType || OBJECTTYPE_DATA_LABEL == eObjectType )
                {
                    // Data Point
                    fillRangesForDataPoint( xDataSeries, nIndex );
                    return;
                }
                else if( OBJECTTYPE_DATA_ERRORS == eObjectType )
                {
                    // select error bar ranges, or data series, if the style is
                    // not set to FROM_DATA
                    fillRangesForErrorBars( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), xDataSeries );
                    return;
                }
                else if( xDataSeries.is() )
                {
                    // Data Series
                    fillRangesForDataSeries( xDataSeries );
                    return;
                }
                else if( OBJECTTYPE_AXIS == eObjectType )
                {
                    // Axis (Categories)
                    Reference< chart2::XAxis > xAxis( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), uno::UNO_QUERY );
                    if( xAxis.is())
                    {
                        fillRangesForCategories( xAxis );
                        return;
                    }
                }
                else if( OBJECTTYPE_PAGE == eObjectType
                         || OBJECTTYPE_DIAGRAM == eObjectType
                         || OBJECTTYPE_DIAGRAM_WALL == eObjectType
                         || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType
                    )
                {
                    // Diagram
                    Reference< chart2::XDiagram > xDia( ObjectIdentifier::getDiagramForCID( aCID, xChartModel ) );
                    if( xDia.is())
                    {
                        fillRangesForDiagram( xDia );
                        return;
                    }
                }
            }
            else
            {
                //if nothing is selected select all ranges
                Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY_THROW );
                fillRangesForDiagram( xChartDoc->getFirstDiagram() );
                return;
            }
        }
        catch( const uno::Exception & ex )
        {
            ASSERT_EXCEPTION( ex );
        }
    }
}

void RangeHighlighter::fillRangesForDiagram( const Reference< chart2::XDiagram > & xDiagram )
{
    Sequence< OUString > aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram ));
    m_aSelectedRanges.realloc( aSelectedRanges.getLength());
    // @todo: merge ranges
    for( sal_Int32 i=0; i<aSelectedRanges.getLength(); ++i )
    {
        m_aSelectedRanges[i].RangeRepresentation = aSelectedRanges[i];
        m_aSelectedRanges[i].Index = -1;
        m_aSelectedRanges[i].PreferredColor = PREFERED_DEFAULT_COLOR;
        m_aSelectedRanges[i].AllowMerginigWithOtherRanges = sal_True;
    }
}

void RangeHighlighter::fillRangesForDataSeries( const uno::Reference< chart2::XDataSeries > & xSeries )
{
    sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR;
//         lcl_getColor( Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ));
    Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
    if( xSource.is())
        lcl_fillRanges( m_aSelectedRanges,
                        ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
                        nPreferredColor );
}

void RangeHighlighter::fillRangesForErrorBars(
    const uno::Reference< beans::XPropertySet > & xErrorBar,
    const uno::Reference< chart2::XDataSeries > & xSeries )
{
    // only show error bar ranges, if the style is set to FROM_DATA
    bool bUsesRangesAsErrorBars = false;
    try
    {
        sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
        bUsesRangesAsErrorBars =
            ( xErrorBar.is() &&
              (xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle) &&
              nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }

    if( bUsesRangesAsErrorBars )
    {
        sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR;
        Reference< chart2::data::XDataSource > xSource( xErrorBar, uno::UNO_QUERY );
        if( xSource.is())
            lcl_fillRanges( m_aSelectedRanges,
                            ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
                            nPreferredColor );
    }
    else
    {
        fillRangesForDataSeries( xSeries );
    }
}

void RangeHighlighter::fillRangesForCategories( const Reference< chart2::XAxis > & xAxis )
{
    if( ! xAxis.is())
        return;
    chart2::ScaleData aData( xAxis->getScaleData());
    lcl_fillRanges( m_aSelectedRanges,
                    DataSourceHelper::getRangesFromLabeledDataSequence( aData.Categories ));
}

void RangeHighlighter::fillRangesForDataPoint( const Reference< uno::XInterface > & xDataSeries, sal_Int32 nIndex )
{
    sal_Int32 nPreferredColor = PREFERED_DEFAULT_COLOR;
//         lcl_getColor( Reference< beans::XPropertySet >( xDataPoint, uno::UNO_QUERY ));
    if( xDataSeries.is())
    {
        Reference< chart2::data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY );
        if( xSource.is() )
        {
            ::std::vector< chart2::data::HighlightedRange > aHilightedRanges;
            Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences());
            for( sal_Int32 i=0; i<aLSeqSeq.getLength(); ++i )
            {
                Reference< chart2::data::XDataSequence > xLabel( aLSeqSeq[i]->getLabel());
                Reference< chart2::data::XDataSequence > xValues( aLSeqSeq[i]->getValues());

                if( xLabel.is())
                    aHilightedRanges.push_back(
                        chart2::data::HighlightedRange(
                            xLabel->getSourceRangeRepresentation(),
                            -1,
                            nPreferredColor,
                            sal_False ));
                if( xValues.is())
                    aHilightedRanges.push_back(
                        chart2::data::HighlightedRange(
                            xValues->getSourceRangeRepresentation(),
                            nIndex,
                            nPreferredColor,
                            sal_False ));
            }
            m_aSelectedRanges = ContainerHelper::ContainerToSequence( aHilightedRanges );
        }
    }
}

void SAL_CALL RangeHighlighter::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
    throw (uno::RuntimeException)
{
    if(!xListener.is())
        return;

    if( m_nAddedListenerCount == 0 )
        startListening();
    rBHelper.addListener( ::getCppuType( & xListener ), xListener);
    ++m_nAddedListenerCount;

    //bring the new listener up to the current state
    lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
    xListener->selectionChanged( aEvent );
}

void SAL_CALL RangeHighlighter::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
    throw (uno::RuntimeException)
{
    rBHelper.removeListener( ::getCppuType( & xListener ), xListener );
    --m_nAddedListenerCount;
    if( m_nAddedListenerCount == 0 )
        stopListening();
}

// ____ XSelectionChangeListener ____
void SAL_CALL RangeHighlighter::selectionChanged( const lang::EventObject& /*aEvent*/ )
    throw (uno::RuntimeException)
{
    determineRanges();

    // determine ranges of selected view objects
    // if changed, fire an event
    fireSelectionEvent();
}

void RangeHighlighter::fireSelectionEvent()
{
    ::cppu::OInterfaceContainerHelper* pIC = rBHelper.getContainer(
        ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0) );
    if( pIC )
    {
        lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
        ::cppu::OInterfaceIteratorHelper aIt( *pIC );
        while( aIt.hasMoreElements() )
            (static_cast< view::XSelectionChangeListener*>(aIt.next()))->selectionChanged( aEvent );
    }
}

void SAL_CALL RangeHighlighter::disposing( const lang::EventObject& Source )
    throw (uno::RuntimeException)
{
    if( Source.Source == m_xSelectionSupplier )
    {
        m_xSelectionSupplier.clear();
        m_aSelectedRanges.realloc( 0 );
        fireSelectionEvent();
    }
}

void RangeHighlighter::startListening()
{
    if( m_xSelectionSupplier.is())
    {
        if( ! m_xListener.is())
        {
            m_xListener.set( new WeakSelectionChangeListenerAdapter( this ));
            determineRanges();
        }
        m_xSelectionSupplier->addSelectionChangeListener( m_xListener );
    }
}

void RangeHighlighter::stopListening()
{
    if( m_xSelectionSupplier.is() && m_xListener.is())
    {
        m_xSelectionSupplier->removeSelectionChangeListener( m_xListener );
        m_xListener.clear();
    }
}

// ____ WeakComponentImplHelperBase ____
// is called when dispose() is called at this component
void SAL_CALL RangeHighlighter::disposing()
{
    // @todo: remove listener. Currently the controller shows an assertion
    // because it is already disposed
//     stopListening();
    m_xListener.clear();
    m_xSelectionSupplier.clear();
    m_nAddedListenerCount =  0;
    m_aSelectedRanges.realloc( 0 );
}

} //  namespace chart
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @author Marek Kotewicz <marek@ethdev.com>
 * @date 2014
 * Unit tests for the solidity compiler JSON Interface output.
 */

#include <boost/test/unit_test.hpp>
#include <libsolidity/CompilerStack.h>
#include <jsoncpp/json/json.h>
#include <libdevcore/Exceptions.h>

namespace dev
{
namespace solidity
{
namespace test
{

class InterfaceChecker
{
public:
	InterfaceChecker(): m_compilerStack(false) {}

	void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
	{
		try
		{
			m_compilerStack.parse(_code);
		}
		catch(boost::exception const& _e)
		{
			auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e);
			BOOST_FAIL(msg);
		}
		std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE);
		Json::Value generatedInterface;
		m_reader.parse(generatedInterfaceString, generatedInterface);
		Json::Value expectedInterface;
		m_reader.parse(_expectedInterfaceString, expectedInterface);
		BOOST_CHECK_MESSAGE(expectedInterface == generatedInterface,
							"Expected " << _expectedInterfaceString <<
							"\n but got:\n" << generatedInterfaceString);
	}

private:
	CompilerStack m_compilerStack;
	Json::Reader m_reader;
};

BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, InterfaceChecker)

BOOST_AUTO_TEST_CASE(basic_test)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"constant": false,
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(empty_contract)
{
	char const* sourceCode = "contract test {\n"
	"}\n";

	char const* interface = "[]";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(multiple_methods)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function g(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"constant": false,
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	},
	{
		"name": "g",
		"constant": false,
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(multiple_params)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"constant": false,
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		},
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
	// methods are expected to be in alpabetical order
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function c(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "c",
		"constant": false,
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	},
	{
		"name": "f",
		"constant": false,
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(const_function)
{
	char const* sourceCode = "contract test {\n"
	"  function foo(uint a, uint b) returns(uint d) { return a + b; }\n"
	"  function boo(uint32 a) constant returns(uint b) { return a * 4; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "foo",
		"constant": false,
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		},
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	},
	{
		"name": "boo",
		"constant": true,
		"inputs": [{
			"name": "a",
			"type": "uint32"
		}],
		"outputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(exclude_fallback_function)
{
	char const* sourceCode = "contract test { function() {} }";

	char const* interface = "[]";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_SUITE_END()

}
}
}
<commit_msg>updated json abi tests<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @author Marek Kotewicz <marek@ethdev.com>
 * @date 2014
 * Unit tests for the solidity compiler JSON Interface output.
 */

#include <boost/test/unit_test.hpp>
#include <libsolidity/CompilerStack.h>
#include <jsoncpp/json/json.h>
#include <libdevcore/Exceptions.h>

namespace dev
{
namespace solidity
{
namespace test
{

class InterfaceChecker
{
public:
	InterfaceChecker(): m_compilerStack(false) {}

	void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
	{
		try
		{
			m_compilerStack.parse(_code);
		}
		catch(boost::exception const& _e)
		{
			auto msg = std::string("Parsing contract failed with: ") + boost::diagnostic_information(_e);
			BOOST_FAIL(msg);
		}
		std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE);
		Json::Value generatedInterface;
		m_reader.parse(generatedInterfaceString, generatedInterface);
		Json::Value expectedInterface;
		m_reader.parse(_expectedInterfaceString, expectedInterface);
		BOOST_CHECK_MESSAGE(expectedInterface == generatedInterface,
							"Expected " << _expectedInterfaceString <<
							"\n but got:\n" << generatedInterfaceString);
	}

private:
	CompilerStack m_compilerStack;
	Json::Reader m_reader;
};

BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, InterfaceChecker)

BOOST_AUTO_TEST_CASE(basic_test)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(empty_contract)
{
	char const* sourceCode = "contract test {\n"
	"}\n";

	char const* interface = "[]";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(multiple_methods)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function g(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	},
	{
		"name": "g",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(multiple_params)
{
	char const* sourceCode = "contract test {\n"
	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "f",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		},
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
	// methods are expected to be in alpabetical order
	char const* sourceCode = "contract test {\n"
	"  function f(uint a) returns(uint d) { return a * 7; }\n"
	"  function c(uint b) returns(uint e) { return b * 8; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "c",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "e",
			"type": "uint256"
		}
		]
	},
	{
		"name": "f",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(const_function)
{
	char const* sourceCode = "contract test {\n"
	"  function foo(uint a, uint b) returns(uint d) { return a + b; }\n"
	"  function boo(uint32 a) constant returns(uint b) { return a * 4; }\n"
	"}\n";

	char const* interface = R"([
	{
		"name": "foo",
		"constant": false,
		"type": "function",
		"inputs": [
		{
			"name": "a",
			"type": "uint256"
		},
		{
			"name": "b",
			"type": "uint256"
		}
		],
		"outputs": [
		{
			"name": "d",
			"type": "uint256"
		}
		]
	},
	{
		"name": "boo",
		"constant": true,
		"type": "function",
		"inputs": [{
			"name": "a",
			"type": "uint32"
		}],
		"outputs": [
		{
			"name": "b",
			"type": "uint256"
		}
		]
	}
	])";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_CASE(exclude_fallback_function)
{
	char const* sourceCode = "contract test { function() {} }";

	char const* interface = "[]";

	checkInterface(sourceCode, interface);
}

BOOST_AUTO_TEST_SUITE_END()

}
}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/snapshot_tab_helper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "net/test/test_server.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/screen.h"

using content::NavigationController;
using content::WebContents;

namespace {

// Include things like browser frame and scrollbar and make sure we're bigger
// than the test pdf document.
static const int kBrowserWidth = 1000;
static const int kBrowserHeight = 600;

class PDFBrowserTest : public InProcessBrowserTest,
                       public content::NotificationObserver {
 public:
  PDFBrowserTest()
      : snapshot_different_(true),
        next_dummy_search_value_(0),
        load_stop_notification_count_(0) {
    EnableDOMAutomation();

    pdf_test_server_.reset(new net::TestServer(
        net::TestServer::TYPE_HTTP,
        net::TestServer::kLocalhost,
        FilePath(FILE_PATH_LITERAL("pdf/test"))));
  }

 protected:
  // Use our own TestServer so that we can serve files from the pdf directory.
  net::TestServer* pdf_test_server() { return pdf_test_server_.get(); }

  int load_stop_notification_count() const {
    return load_stop_notification_count_;
  }

  FilePath GetPDFTestDir() {
    return FilePath(FilePath::kCurrentDirectory).AppendASCII("..").
        AppendASCII("..").AppendASCII("..").AppendASCII("pdf").
        AppendASCII("test");
  }

  void Load() {
    // Make sure to set the window size before rendering, as otherwise rendering
    // to a smaller window and then expanding leads to slight anti-aliasing
    // differences of the text and the pixel comparison fails.
    gfx::Rect bounds(gfx::Rect(0, 0, kBrowserWidth, kBrowserHeight));
    gfx::Rect screen_bounds = gfx::Screen::GetPrimaryMonitorBounds();
    ASSERT_GT(screen_bounds.width(), kBrowserWidth);
    ASSERT_GT(screen_bounds.height(), kBrowserHeight);
    browser()->window()->SetBounds(bounds);

    GURL url(ui_test_utils::GetTestUrl(
        GetPDFTestDir(),
        FilePath(FILE_PATH_LITERAL("pdf_browsertest.pdf"))));
    ui_test_utils::NavigateToURL(browser(), url);
  }

  void VerifySnapshot(const std::string& expected_filename) {
    snapshot_different_ = true;
    expected_filename_ = expected_filename;
    TabContentsWrapper* wrapper =  browser()->GetSelectedTabContentsWrapper();
    wrapper->snapshot_tab_helper()->CaptureSnapshot();
    ui_test_utils::RegisterAndWait(
        this,
        chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN,
        content::Source<WebContents>(wrapper->web_contents()));
    ASSERT_FALSE(snapshot_different_) << "Rendering didn't match, see result "
        "at " << snapshot_filename_.value().c_str();
  }

  void WaitForResponse() {
    // Even if the plugin has loaded the data or scrolled, because of how
    // pepper painting works, we might not have the data.  One way to force this
    // to be flushed is to do a find operation, since on this two-page test
    // document, it'll wait for us to flush the renderer message loop twice and
    // also the browser's once, at which point we're guaranteed to have updated
    // the backingstore.  Hacky, but it works.
    // Note that we need to change the text each time, because if we don't the
    // renderer code will think the second message is to go to next result, but
    // there are none so the plugin will assert.

    string16 query = UTF8ToUTF16(
        std::string("xyzxyz" + base::IntToString(next_dummy_search_value_++)));
    ASSERT_EQ(0, ui_test_utils::FindInPage(
        browser()->GetSelectedTabContentsWrapper(), query, true, false, NULL));
  }

 private:
  // content::NotificationObserver
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) {
    if (type == chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN) {
      MessageLoopForUI::current()->Quit();
      FilePath reference = ui_test_utils::GetTestFilePath(
          GetPDFTestDir(),
          FilePath().AppendASCII(expected_filename_));
      base::PlatformFileInfo info;
      ASSERT_TRUE(file_util::GetFileInfo(reference, &info));
      int size = static_cast<size_t>(info.size);
      scoped_array<char> data(new char[size]);
      ASSERT_EQ(size, file_util::ReadFile(reference, data.get(), size));

      int w, h;
      std::vector<unsigned char> decoded;
      ASSERT_TRUE(gfx::PNGCodec::Decode(
          reinterpret_cast<unsigned char*>(data.get()), size,
          gfx::PNGCodec::FORMAT_BGRA, &decoded, &w, &h));
      int32* ref_pixels = reinterpret_cast<int32*>(&decoded[0]);

      const SkBitmap* bitmap = content::Details<const SkBitmap>(details).ptr();
      int32* pixels = static_cast<int32*>(bitmap->getPixels());

      // Get the background color, and use it to figure out the x-offsets in
      // each image.  The reason is that depending on the theme in the OS, the
      // same browser width can lead to slightly different plugin sizes, so the
      // pdf content will start at different x offsets.
      // Also note that the images we saved are cut off before the scrollbar, as
      // that'll change depending on the theme, and also cut off vertically so
      // that the ui controls don't show up, as those fade-in and so the timing
      // will affect their transparency.
      int32 bg_color = ref_pixels[0];
      int ref_x_offset, snapshot_x_offset;
      for (ref_x_offset = 0; ref_x_offset < w; ++ref_x_offset) {
        if (ref_pixels[ref_x_offset] != bg_color)
          break;
      }

      for (snapshot_x_offset = 0; snapshot_x_offset < bitmap->width();
           ++snapshot_x_offset) {
        if (pixels[snapshot_x_offset] != bg_color)
          break;
      }

      int x_max = std::min(
          w - ref_x_offset, bitmap->width() - snapshot_x_offset);
      int y_max = std::min(h, bitmap->height());
      int stride = bitmap->rowBytes();
      snapshot_different_ = false;
      for (int y = 0; y < y_max && !snapshot_different_; ++y) {
        for (int x = 0; x < x_max && !snapshot_different_; ++x) {
          if (pixels[y * stride / sizeof(int32) + x + snapshot_x_offset] !=
              ref_pixels[y * w + x + ref_x_offset])
            snapshot_different_ = true;
        }
      }

      if (snapshot_different_) {
        std::vector<unsigned char> png_data;
        gfx::PNGCodec::EncodeBGRASkBitmap(*bitmap, false, &png_data);
        if (file_util::CreateTemporaryFile(&snapshot_filename_)) {
          file_util::WriteFile(snapshot_filename_,
              reinterpret_cast<char*>(&png_data[0]), png_data.size());
        }
      }
    } else if (type == content::NOTIFICATION_LOAD_STOP) {
      load_stop_notification_count_++;
    }
  }

  // True if the snapshot differed from the expected value.
  bool snapshot_different_;
  // Internal variable used to synchronize to the renderer.
  int next_dummy_search_value_;
  // The filename of the bitmap to compare the snapshot to.
  std::string expected_filename_;
  // If the snapshot is different, holds the location where it's saved.
  FilePath snapshot_filename_;
  // How many times we've seen chrome::LOAD_STOP.
  int load_stop_notification_count_;

  scoped_ptr<net::TestServer> pdf_test_server_;
};

#if defined(OS_CHROMEOS)
// TODO(sanjeevr): http://crbug.com/79837
#define MAYBE_Basic DISABLED_Basic
#else
#define MAYBE_Basic Basic
#endif
// Tests basic PDF rendering.  This can be broken depending on bad merges with
// the vendor, so it's important that we have basic sanity checking.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, MAYBE_Basic) {
  ASSERT_NO_FATAL_FAILURE(Load());
  ASSERT_NO_FATAL_FAILURE(WaitForResponse());
  // OS X uses CoreText, and FreeType renders slightly different on Linux and
  // Win.
#if defined(OS_MACOSX)
  std::string expectation_file = "pdf_browsertest_mac.png";
#elif defined(OS_LINUX)
  std::string expectation_file = "pdf_browsertest_linux.png";
#else
  std::string expectation_file = "pdf_browsertest.png";
#endif
  ASSERT_NO_FATAL_FAILURE(VerifySnapshot(expectation_file));
}

#if defined(OS_CHROMEOS)
// TODO(sanjeevr): http://crbug.com/79837
#define MAYBE_Scroll DISABLED_Scroll
#else
#define MAYBE_Scroll Scroll
#endif
// Tests that scrolling works.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, MAYBE_Scroll) {
  ASSERT_NO_FATAL_FAILURE(Load());

  // We use wheel mouse event since that's the only one we can easily push to
  // the renderer.  There's no way to push a cross-platform keyboard event at
  // the moment.
  WebKit::WebMouseWheelEvent wheel_event;
  wheel_event.type = WebKit::WebInputEvent::MouseWheel;
  wheel_event.deltaY = -200;
  wheel_event.wheelTicksY = -2;
  WebContents* web_contents = browser()->GetSelectedWebContents();
  web_contents->GetRenderViewHost()->ForwardWheelEvent(wheel_event);
  ASSERT_NO_FATAL_FAILURE(WaitForResponse());

  int y_offset = 0;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
      browser()->GetSelectedWebContents()->GetRenderViewHost(),
      std::wstring(),
      L"window.domAutomationController.send(plugin.pageYOffset())",
      &y_offset));
  ASSERT_GT(y_offset, 0);
}

#if defined(OS_CHROMEOS)
// TODO(sanjeevr): http://crbug.com/79837
#define MAYBE_FindAndCopy DISABLED_FindAndCopy
#else
#define MAYBE_FindAndCopy FindAndCopy
#endif
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, MAYBE_FindAndCopy) {
  ASSERT_NO_FATAL_FAILURE(Load());
  // Verifies that find in page works.
  ASSERT_EQ(3, ui_test_utils::FindInPage(
      browser()->GetSelectedTabContentsWrapper(), UTF8ToUTF16("adipiscing"),
      true, false, NULL));

  // Verify that copying selected text works.
  ui::Clipboard clipboard;
  // Reset the clipboard first.
  ui::Clipboard::ObjectMap objects;
  ui::Clipboard::ObjectMapParams params;
  params.push_back(std::vector<char>());
  objects[ui::Clipboard::CBF_TEXT] = params;
  clipboard.WriteObjects(ui::Clipboard::BUFFER_STANDARD, objects);

  browser()->GetSelectedWebContents()->GetRenderViewHost()->Copy();
  ASSERT_NO_FATAL_FAILURE(WaitForResponse());

  std::string text;
  clipboard.ReadAsciiText(ui::Clipboard::BUFFER_STANDARD, &text);
  ASSERT_EQ("adipiscing", text);
}

// Tests that loading async pdfs works correctly (i.e. document fully loads).
// This also loads all documents that used to crash, to ensure we don't have
// regressions.
// Flaky as per http://crbug.com/74548.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, DISABLED_SLOW_Loading) {
  ASSERT_TRUE(pdf_test_server()->Start());

  NavigationController* controller =
      &(browser()->GetSelectedWebContents()->GetController());
  content::NotificationRegistrar registrar;
  registrar.Add(this,
                content::NOTIFICATION_LOAD_STOP,
                content::Source<NavigationController>(controller));
  std::string base_url = std::string("files/");

  file_util::FileEnumerator file_enumerator(
      ui_test_utils::GetTestFilePath(GetPDFTestDir(), FilePath()),
      false,
      file_util::FileEnumerator::FILES,
      FILE_PATH_LITERAL("*.pdf"));
  for (FilePath file_path = file_enumerator.Next();
       !file_path.empty();
       file_path = file_enumerator.Next()) {
    std::string filename = file_path.BaseName().MaybeAsASCII();
    ASSERT_FALSE(filename.empty());

#if defined(OS_POSIX)
    if (filename == "sample.pdf")
      continue;  // Crashes on Mac and Linux.  http://crbug.com/63549
#endif

    LOG(WARNING) << "PDFBrowserTest.Loading: " << filename;

    GURL url = pdf_test_server()->GetURL(base_url + filename);
    ui_test_utils::NavigateToURL(browser(), url);

    while (true) {
      int last_count = load_stop_notification_count();
      // We might get extraneous chrome::LOAD_STOP notifications when
      // doing async loading.  This happens when the first loader is cancelled
      // and before creating a byte-range request loader.
      bool complete = false;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
          browser()->GetSelectedWebContents()->GetRenderViewHost(),
          std::wstring(),
          L"window.domAutomationController.send(plugin.documentLoadComplete())",
          &complete));
      if (complete)
        break;

      // Check if the LOAD_STOP notification could have come while we run a
      // nested message loop for the JS call.
      if (last_count != load_stop_notification_count())
        continue;
      ui_test_utils::WaitForLoadStop(browser()->GetSelectedWebContents());
    }
  }
}

// Flaky as per http://crbug.com/74549.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, DISABLED_OnLoadAndReload) {
  ASSERT_TRUE(pdf_test_server()->Start());

  GURL url = pdf_test_server()->GetURL("files/onload_reload.html");
  ui_test_utils::NavigateToURL(browser(), url);

  ui_test_utils::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::Source<NavigationController>(
          &browser()->GetSelectedWebContents()->GetController()));
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
      browser()->GetSelectedWebContents()->GetRenderViewHost(),
      std::wstring(),
      L"reloadPDF();"));
  observer.Wait();

  ASSERT_EQ("success", browser()->GetSelectedWebContents()->GetURL().query());
}

}  // namespace
<commit_msg>Renable PDFBrowserTest.SLOW_Loading. See bug for more details.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/snapshot_tab_helper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "net/test/test_server.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/screen.h"

using content::NavigationController;
using content::WebContents;

namespace {

// Include things like browser frame and scrollbar and make sure we're bigger
// than the test pdf document.
static const int kBrowserWidth = 1000;
static const int kBrowserHeight = 600;

class PDFBrowserTest : public InProcessBrowserTest,
                       public content::NotificationObserver {
 public:
  PDFBrowserTest()
      : snapshot_different_(true),
        next_dummy_search_value_(0),
        load_stop_notification_count_(0) {
    EnableDOMAutomation();

    pdf_test_server_.reset(new net::TestServer(
        net::TestServer::TYPE_HTTP,
        net::TestServer::kLocalhost,
        FilePath(FILE_PATH_LITERAL("pdf/test"))));
  }

 protected:
  // Use our own TestServer so that we can serve files from the pdf directory.
  net::TestServer* pdf_test_server() { return pdf_test_server_.get(); }

  int load_stop_notification_count() const {
    return load_stop_notification_count_;
  }

  FilePath GetPDFTestDir() {
    return FilePath(FilePath::kCurrentDirectory).AppendASCII("..").
        AppendASCII("..").AppendASCII("..").AppendASCII("pdf").
        AppendASCII("test");
  }

  void Load() {
    // Make sure to set the window size before rendering, as otherwise rendering
    // to a smaller window and then expanding leads to slight anti-aliasing
    // differences of the text and the pixel comparison fails.
    gfx::Rect bounds(gfx::Rect(0, 0, kBrowserWidth, kBrowserHeight));
    gfx::Rect screen_bounds = gfx::Screen::GetPrimaryMonitorBounds();
    ASSERT_GT(screen_bounds.width(), kBrowserWidth);
    ASSERT_GT(screen_bounds.height(), kBrowserHeight);
    browser()->window()->SetBounds(bounds);

    GURL url(ui_test_utils::GetTestUrl(
        GetPDFTestDir(),
        FilePath(FILE_PATH_LITERAL("pdf_browsertest.pdf"))));
    ui_test_utils::NavigateToURL(browser(), url);
  }

  void VerifySnapshot(const std::string& expected_filename) {
    snapshot_different_ = true;
    expected_filename_ = expected_filename;
    TabContentsWrapper* wrapper =  browser()->GetSelectedTabContentsWrapper();
    wrapper->snapshot_tab_helper()->CaptureSnapshot();
    ui_test_utils::RegisterAndWait(
        this,
        chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN,
        content::Source<WebContents>(wrapper->web_contents()));
    ASSERT_FALSE(snapshot_different_) << "Rendering didn't match, see result "
        "at " << snapshot_filename_.value().c_str();
  }

  void WaitForResponse() {
    // Even if the plugin has loaded the data or scrolled, because of how
    // pepper painting works, we might not have the data.  One way to force this
    // to be flushed is to do a find operation, since on this two-page test
    // document, it'll wait for us to flush the renderer message loop twice and
    // also the browser's once, at which point we're guaranteed to have updated
    // the backingstore.  Hacky, but it works.
    // Note that we need to change the text each time, because if we don't the
    // renderer code will think the second message is to go to next result, but
    // there are none so the plugin will assert.

    string16 query = UTF8ToUTF16(
        std::string("xyzxyz" + base::IntToString(next_dummy_search_value_++)));
    ASSERT_EQ(0, ui_test_utils::FindInPage(
        browser()->GetSelectedTabContentsWrapper(), query, true, false, NULL));
  }

 private:
  // content::NotificationObserver
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) {
    if (type == chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN) {
      MessageLoopForUI::current()->Quit();
      FilePath reference = ui_test_utils::GetTestFilePath(
          GetPDFTestDir(),
          FilePath().AppendASCII(expected_filename_));
      base::PlatformFileInfo info;
      ASSERT_TRUE(file_util::GetFileInfo(reference, &info));
      int size = static_cast<size_t>(info.size);
      scoped_array<char> data(new char[size]);
      ASSERT_EQ(size, file_util::ReadFile(reference, data.get(), size));

      int w, h;
      std::vector<unsigned char> decoded;
      ASSERT_TRUE(gfx::PNGCodec::Decode(
          reinterpret_cast<unsigned char*>(data.get()), size,
          gfx::PNGCodec::FORMAT_BGRA, &decoded, &w, &h));
      int32* ref_pixels = reinterpret_cast<int32*>(&decoded[0]);

      const SkBitmap* bitmap = content::Details<const SkBitmap>(details).ptr();
      int32* pixels = static_cast<int32*>(bitmap->getPixels());

      // Get the background color, and use it to figure out the x-offsets in
      // each image.  The reason is that depending on the theme in the OS, the
      // same browser width can lead to slightly different plugin sizes, so the
      // pdf content will start at different x offsets.
      // Also note that the images we saved are cut off before the scrollbar, as
      // that'll change depending on the theme, and also cut off vertically so
      // that the ui controls don't show up, as those fade-in and so the timing
      // will affect their transparency.
      int32 bg_color = ref_pixels[0];
      int ref_x_offset, snapshot_x_offset;
      for (ref_x_offset = 0; ref_x_offset < w; ++ref_x_offset) {
        if (ref_pixels[ref_x_offset] != bg_color)
          break;
      }

      for (snapshot_x_offset = 0; snapshot_x_offset < bitmap->width();
           ++snapshot_x_offset) {
        if (pixels[snapshot_x_offset] != bg_color)
          break;
      }

      int x_max = std::min(
          w - ref_x_offset, bitmap->width() - snapshot_x_offset);
      int y_max = std::min(h, bitmap->height());
      int stride = bitmap->rowBytes();
      snapshot_different_ = false;
      for (int y = 0; y < y_max && !snapshot_different_; ++y) {
        for (int x = 0; x < x_max && !snapshot_different_; ++x) {
          if (pixels[y * stride / sizeof(int32) + x + snapshot_x_offset] !=
              ref_pixels[y * w + x + ref_x_offset])
            snapshot_different_ = true;
        }
      }

      if (snapshot_different_) {
        std::vector<unsigned char> png_data;
        gfx::PNGCodec::EncodeBGRASkBitmap(*bitmap, false, &png_data);
        if (file_util::CreateTemporaryFile(&snapshot_filename_)) {
          file_util::WriteFile(snapshot_filename_,
              reinterpret_cast<char*>(&png_data[0]), png_data.size());
        }
      }
    } else if (type == content::NOTIFICATION_LOAD_STOP) {
      load_stop_notification_count_++;
    }
  }

  // True if the snapshot differed from the expected value.
  bool snapshot_different_;
  // Internal variable used to synchronize to the renderer.
  int next_dummy_search_value_;
  // The filename of the bitmap to compare the snapshot to.
  std::string expected_filename_;
  // If the snapshot is different, holds the location where it's saved.
  FilePath snapshot_filename_;
  // How many times we've seen chrome::LOAD_STOP.
  int load_stop_notification_count_;

  scoped_ptr<net::TestServer> pdf_test_server_;
};

#if defined(OS_CHROMEOS)
// TODO(sanjeevr): http://crbug.com/79837
#define MAYBE_Basic DISABLED_Basic
#else
#define MAYBE_Basic Basic
#endif
// Tests basic PDF rendering.  This can be broken depending on bad merges with
// the vendor, so it's important that we have basic sanity checking.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, MAYBE_Basic) {
  ASSERT_NO_FATAL_FAILURE(Load());
  ASSERT_NO_FATAL_FAILURE(WaitForResponse());
  // OS X uses CoreText, and FreeType renders slightly different on Linux and
  // Win.
#if defined(OS_MACOSX)
  std::string expectation_file = "pdf_browsertest_mac.png";
#elif defined(OS_LINUX)
  std::string expectation_file = "pdf_browsertest_linux.png";
#else
  std::string expectation_file = "pdf_browsertest.png";
#endif
  ASSERT_NO_FATAL_FAILURE(VerifySnapshot(expectation_file));
}

#if defined(OS_CHROMEOS)
// TODO(sanjeevr): http://crbug.com/79837
#define MAYBE_Scroll DISABLED_Scroll
#else
#define MAYBE_Scroll Scroll
#endif
// Tests that scrolling works.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, MAYBE_Scroll) {
  ASSERT_NO_FATAL_FAILURE(Load());

  // We use wheel mouse event since that's the only one we can easily push to
  // the renderer.  There's no way to push a cross-platform keyboard event at
  // the moment.
  WebKit::WebMouseWheelEvent wheel_event;
  wheel_event.type = WebKit::WebInputEvent::MouseWheel;
  wheel_event.deltaY = -200;
  wheel_event.wheelTicksY = -2;
  WebContents* web_contents = browser()->GetSelectedWebContents();
  web_contents->GetRenderViewHost()->ForwardWheelEvent(wheel_event);
  ASSERT_NO_FATAL_FAILURE(WaitForResponse());

  int y_offset = 0;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
      browser()->GetSelectedWebContents()->GetRenderViewHost(),
      std::wstring(),
      L"window.domAutomationController.send(plugin.pageYOffset())",
      &y_offset));
  ASSERT_GT(y_offset, 0);
}

#if defined(OS_CHROMEOS)
// TODO(sanjeevr): http://crbug.com/79837
#define MAYBE_FindAndCopy DISABLED_FindAndCopy
#else
#define MAYBE_FindAndCopy FindAndCopy
#endif
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, MAYBE_FindAndCopy) {
  ASSERT_NO_FATAL_FAILURE(Load());
  // Verifies that find in page works.
  ASSERT_EQ(3, ui_test_utils::FindInPage(
      browser()->GetSelectedTabContentsWrapper(), UTF8ToUTF16("adipiscing"),
      true, false, NULL));

  // Verify that copying selected text works.
  ui::Clipboard clipboard;
  // Reset the clipboard first.
  ui::Clipboard::ObjectMap objects;
  ui::Clipboard::ObjectMapParams params;
  params.push_back(std::vector<char>());
  objects[ui::Clipboard::CBF_TEXT] = params;
  clipboard.WriteObjects(ui::Clipboard::BUFFER_STANDARD, objects);

  browser()->GetSelectedWebContents()->GetRenderViewHost()->Copy();
  ASSERT_NO_FATAL_FAILURE(WaitForResponse());

  std::string text;
  clipboard.ReadAsciiText(ui::Clipboard::BUFFER_STANDARD, &text);
  ASSERT_EQ("adipiscing", text);
}

// Tests that loading async pdfs works correctly (i.e. document fully loads).
// This also loads all documents that used to crash, to ensure we don't have
// regressions.
// If it flakes, reopen http://crbug.com/74548.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, SLOW_Loading) {
  ASSERT_TRUE(pdf_test_server()->Start());

  NavigationController* controller =
      &(browser()->GetSelectedWebContents()->GetController());
  content::NotificationRegistrar registrar;
  registrar.Add(this,
                content::NOTIFICATION_LOAD_STOP,
                content::Source<NavigationController>(controller));
  std::string base_url = std::string("files/");

  file_util::FileEnumerator file_enumerator(
      ui_test_utils::GetTestFilePath(GetPDFTestDir(), FilePath()),
      false,
      file_util::FileEnumerator::FILES,
      FILE_PATH_LITERAL("*.pdf"));
  for (FilePath file_path = file_enumerator.Next();
       !file_path.empty();
       file_path = file_enumerator.Next()) {
    std::string filename = file_path.BaseName().MaybeAsASCII();
    ASSERT_FALSE(filename.empty());

#if defined(OS_POSIX)
    if (filename == "sample.pdf")
      continue;  // Crashes on Mac and Linux.  http://crbug.com/63549
#endif

    LOG(WARNING) << "PDFBrowserTest.Loading: " << filename;

    GURL url = pdf_test_server()->GetURL(base_url + filename);
    ui_test_utils::NavigateToURL(browser(), url);

    while (true) {
      int last_count = load_stop_notification_count();
      // We might get extraneous chrome::LOAD_STOP notifications when
      // doing async loading.  This happens when the first loader is cancelled
      // and before creating a byte-range request loader.
      bool complete = false;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
          browser()->GetSelectedWebContents()->GetRenderViewHost(),
          std::wstring(),
          L"window.domAutomationController.send(plugin.documentLoadComplete())",
          &complete));
      if (complete)
        break;

      // Check if the LOAD_STOP notification could have come while we run a
      // nested message loop for the JS call.
      if (last_count != load_stop_notification_count())
        continue;
      ui_test_utils::WaitForLoadStop(browser()->GetSelectedWebContents());
    }
  }
}

// Flaky as per http://crbug.com/74549.
IN_PROC_BROWSER_TEST_F(PDFBrowserTest, DISABLED_OnLoadAndReload) {
  ASSERT_TRUE(pdf_test_server()->Start());

  GURL url = pdf_test_server()->GetURL("files/onload_reload.html");
  ui_test_utils::NavigateToURL(browser(), url);

  ui_test_utils::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::Source<NavigationController>(
          &browser()->GetSelectedWebContents()->GetController()));
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
      browser()->GetSelectedWebContents()->GetRenderViewHost(),
      std::wstring(),
      L"reloadPDF();"));
  observer.Wait();

  ASSERT_EQ("success", browser()->GetSelectedWebContents()->GetURL().query());
}

}  // namespace
<|endoftext|>


<commit_before>/**
 * Copyright (c) Sjors Gielen, 2010
 * See LICENSE for license.
 */

#include <config.h>
#include "pluginmanager.h"
#include "testplugin.h"
#include "perlplugin.h"
#include "statistics.h"
#include "database.h"
#include <IrcBuffer>
#include <IrcSession>

QDebug operator<<(QDebug dbg, const Context *c)
{
  dbg.nospace() << "Context[";
  if( c == 0 ) {
    dbg.nospace() << "0";
  } else {
    dbg.nospace() <<  "n=" << c->network
                  << ",r=" << c->receiver
                  << ",s=" << c->sender;
  }
  dbg.nospace() << "]";

  return dbg.maybeSpace();
}

/**
 * @brief Constructor.
 *
 * Does nothing.
 */
PluginManager::PluginManager( Database *db )
: QObject()
, config_( 0 )
, database_( db )
, context_( 0 )
, initialized_( false )
{
}

/**
 * @brief Destructor.
 */
PluginManager::~PluginManager()
{
}

/**
 * @brief Clear the previously set context.
 * @see setContext(), context()
 */
void PluginManager::clearContext()
{
  Q_ASSERT( context_ != 0 );
  delete context_;
  context_ = 0;
}

/**
 * @brief Return the current call context.
 */
const Context *PluginManager::context() const
{
  return context_;
}

/**
 * @brief Gets a property.
 * Name must be fully qualified. The nearest scope will be returned in s if
 * non-null.
 */
QVariant PluginManager::get( const QString &name, Plugin::VariableScope *s  ) const
{
  Q_ASSERT( context_ != 0 );
#warning TODO
  if( s != NULL )
    *s = Plugin::GlobalScope;
  return database_->property( name, context_->network, context_->receiver, context_->sender );
}

/**
 * @brief Initialises plugins.
 *
 * This method takes all configuration from the configuration file, tries to
 * find all modules and load all modules marked 'load on start' (in order of
 * priority), then calls
 * init() on them. If it fails to load and initialize a plugin, it prints an
 * error and, depending on the value of fatalError in the configfile, either
 * ignores the error or stops loading all plugins altogether and returning
 * an error.
 *
 * When the configuration reloads, this method is automatically called to
 * reload all plugins.
 */
bool PluginManager::initialize()
{
  Q_ASSERT( config_ != 0 );
  setContext("");

  Plugin *plugin = new TestPlugin( this );
  plugin->init();
  plugins_.append( plugin );

  Plugin *plugin2 = new PerlPlugin( this );
  plugin2->init();
  plugins_.append( plugin2 );

  Plugin *plugin3 = new Statistics( this );
  plugin3->init();
  plugins_.append( plugin3 );

  clearContext();

  initialized_ = true;
  return true;
}

/**
 * @returns whether this PluginManager is initialized.
 * @see initialize()
 */
bool PluginManager::isInitialized() const
{
  return initialized_;
}

/**
 * @brief Unloads all modules and resets this object.
 */
void PluginManager::reset()
{
  // TODO
}

/**
 * @brief Sets a property in the database on given scope.
 */
void PluginManager::set( Plugin::VariableScope s, const QString &name, const QVariant &value )
{
  bool isSenderScope   =                    s & Plugin::SenderScope;
  bool isReceiverScope = isSenderScope   || s & Plugin::ReceiverScope;
  bool isNetworkScope  = isReceiverScope || s & Plugin::NetworkScope;

  database_->setProperty( name, value,
    isNetworkScope  ? context_->network  : QString(),
    isReceiverScope ? context_->receiver : QString(),
    isSenderScope   ? context_->sender   : QString() );
}

/**
 * @brief Set the configuration of this object.
 * MUST be called before initialize().
 */
void PluginManager::setConfig( Config *c )
{
  config_ = c;
  connect( c,    SIGNAL( configReloaded() ),
           this, SLOT(       initialize() ) );
}

/**
 * @brief Set the context of this call.
 *
 * All PluginManager handlers call this method for later reference. For
 * example, the Database needs to look back at the current call, to save
 * variables in the correct scope.
 */
void PluginManager::setContext(QString network, QString receiver, QString sender)
{
  Q_ASSERT( context_ == 0 );
  context_ = new Context;
  context_->network  = network;
  context_->receiver = receiver;
  context_->sender   = sender;
}

/******* ADDITIONAL HANDLERS **********/

/**
 * @brief welcomed() handler.
 *
 * This method is called when DaVinci finishes a handshake with the IRC server.
 */
void PluginManager::welcomed( Network &n )
{
  setContext( n.config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->welcomed( n );
  }
  clearContext();
}

/**
 * @brief connected() handler.
 *
 * This method is called when DaVinci connects to an IRC server, before authorization.
 */
void PluginManager::connected( Network &n, const Server &s )
{
  setContext( n.config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->connected( n, s );
  }
  clearContext();
}

/**
 * @brief Database getter.
 *
 * Returns the database for this PluginManager and set of plugins.
 */
Database *PluginManager::database() const
{
  return database_;
}

/**
 * @brief disconnected() handler.
 *
 * This method is called when the connection is broken between DaVinci and an IRC server.
 */
void PluginManager::disconnected( Network &n )
{
  setContext( n.config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->disconnected( n );
  }
  clearContext();
}

void PluginManager::motdReceived ( const QString &motd, Irc::Buffer *b ) {
  Network *n = Network::fromBuffer( b );
  Q_ASSERT( n != 0 );
  setContext( n->config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->motdReceived( *n, motd, b );
  }
  clearContext();
}

#define PLUGIN_EVENT_RELAY_1STR( EVENTNAME ) \
void PluginManager::EVENTNAME ( const QString &str, Irc::Buffer *b ) { \
  Network *n = Network::fromBuffer( b ); \
  Q_ASSERT( n != 0 ); \
  setContext( n->config()->name, b->receiver(), str ); \
  foreach( Plugin *p, plugins_ ) \
  { \
    p->EVENTNAME( *n, str, b ); \
  } \
  clearContext(); \
}

#define PLUGIN_EVENT_RELAY_2STR( EVENTNAME ) \
void PluginManager::EVENTNAME ( const QString &str, const QString &str2, Irc::Buffer *b ) { \
  Network *n = Network::fromBuffer( b ); \
  Q_ASSERT( n != 0 ); \
  setContext( n->config()->name, b->receiver(), str ); \
  foreach( Plugin *p, plugins_ ) \
  { \
    p->EVENTNAME( *n, str, str2, b ); \
  } \
  clearContext(); \
}

#define PLUGIN_EVENT_RELAY_3STR( EVENTNAME ) \
void PluginManager::EVENTNAME ( const QString &str, const QString &str2, \
                           const QString &str3, Irc::Buffer *b ) { \
  Network *n = Network::fromBuffer( b ); \
  Q_ASSERT( n != 0 ); \
  setContext( n->config()->name, b->receiver(), str ); \
  foreach( Plugin *p, plugins_ ) \
  { \
    p->EVENTNAME( *n, str, str2, str3, b ); \
  } \
  clearContext(); \
}

PLUGIN_EVENT_RELAY_1STR( joined );
PLUGIN_EVENT_RELAY_2STR( parted );
PLUGIN_EVENT_RELAY_2STR( quit );
PLUGIN_EVENT_RELAY_2STR( nickChanged );
PLUGIN_EVENT_RELAY_3STR( modeChanged );
PLUGIN_EVENT_RELAY_2STR( topicChanged );
PLUGIN_EVENT_RELAY_3STR( invited );
PLUGIN_EVENT_RELAY_3STR( kicked );
PLUGIN_EVENT_RELAY_2STR( messageReceived );
PLUGIN_EVENT_RELAY_2STR( noticeReceived );
PLUGIN_EVENT_RELAY_2STR( ctcpRequestReceived );
PLUGIN_EVENT_RELAY_2STR( ctcpReplyReceived );
PLUGIN_EVENT_RELAY_2STR( ctcpActionReceived );

#undef PLUGIN_EVENT_RELAY_1STR
#undef PLUGIN_EVENT_RELAY_2STR
#undef PLUGIN_EVENT_RELAY_3STR

void PluginManager::numericMessageReceived( const QString &origin, uint code,
                           const QStringList &params, Irc::Buffer *buffer )
{
  Network *n = Network::fromBuffer( buffer );
  Q_ASSERT( n != 0 );
  setContext( n->config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->numericMessageReceived( *n, origin, code, params, buffer );
  }
  clearContext();
}

void PluginManager::unknownMessageReceived( const QString &origin,
                          const QStringList &params, Irc::Buffer *buffer )
{
  Network *n = Network::fromBuffer( buffer );
  Q_ASSERT( n != 0 );
  setContext( n->config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->unknownMessageReceived( *n, origin, params, buffer );
  }
  clearContext();
}

<commit_msg>make PluginManager ascii safe too.<commit_after>/**
 * Copyright (c) Sjors Gielen, 2010
 * See LICENSE for license.
 */

#include <config.h>
#include "pluginmanager.h"
#include "testplugin.h"
#include "perlplugin.h"
#include "statistics.h"
#include "database.h"
#include <IrcBuffer>
#include <IrcSession>

QDebug operator<<(QDebug dbg, const Context *c)
{
  dbg.nospace() << "Context[";
  if( c == 0 ) {
    dbg.nospace() << "0";
  } else {
    dbg.nospace() <<  "n=" << c->network
                  << ",r=" << c->receiver
                  << ",s=" << c->sender;
  }
  dbg.nospace() << "]";

  return dbg.maybeSpace();
}

/**
 * @brief Constructor.
 *
 * Does nothing.
 */
PluginManager::PluginManager( Database *db )
: QObject()
, config_( 0 )
, database_( db )
, context_( 0 )
, initialized_( false )
{
}

/**
 * @brief Destructor.
 */
PluginManager::~PluginManager()
{
}

/**
 * @brief Clear the previously set context.
 * @see setContext(), context()
 */
void PluginManager::clearContext()
{
  Q_ASSERT( context_ != 0 );
  delete context_;
  context_ = 0;
}

/**
 * @brief Return the current call context.
 */
const Context *PluginManager::context() const
{
  return context_;
}

/**
 * @brief Gets a property.
 * Name must be fully qualified. The nearest scope will be returned in s if
 * non-null.
 */
QVariant PluginManager::get( const QString &name, Plugin::VariableScope *s  ) const
{
  Q_ASSERT( context_ != 0 );
#warning TODO
  if( s != NULL )
    *s = Plugin::GlobalScope;
  return database_->property( name, context_->network, context_->receiver, context_->sender );
}

/**
 * @brief Initialises plugins.
 *
 * This method takes all configuration from the configuration file, tries to
 * find all modules and load all modules marked 'load on start' (in order of
 * priority), then calls
 * init() on them. If it fails to load and initialize a plugin, it prints an
 * error and, depending on the value of fatalError in the configfile, either
 * ignores the error or stops loading all plugins altogether and returning
 * an error.
 *
 * When the configuration reloads, this method is automatically called to
 * reload all plugins.
 */
bool PluginManager::initialize()
{
  Q_ASSERT( config_ != 0 );
  setContext(QString());

  Plugin *plugin = new TestPlugin( this );
  plugin->init();
  plugins_.append( plugin );

  Plugin *plugin2 = new PerlPlugin( this );
  plugin2->init();
  plugins_.append( plugin2 );

  Plugin *plugin3 = new Statistics( this );
  plugin3->init();
  plugins_.append( plugin3 );

  clearContext();

  initialized_ = true;
  return true;
}

/**
 * @returns whether this PluginManager is initialized.
 * @see initialize()
 */
bool PluginManager::isInitialized() const
{
  return initialized_;
}

/**
 * @brief Unloads all modules and resets this object.
 */
void PluginManager::reset()
{
  // TODO
}

/**
 * @brief Sets a property in the database on given scope.
 */
void PluginManager::set( Plugin::VariableScope s, const QString &name, const QVariant &value )
{
  bool isSenderScope   =                    s & Plugin::SenderScope;
  bool isReceiverScope = isSenderScope   || s & Plugin::ReceiverScope;
  bool isNetworkScope  = isReceiverScope || s & Plugin::NetworkScope;

  database_->setProperty( name, value,
    isNetworkScope  ? context_->network  : QString(),
    isReceiverScope ? context_->receiver : QString(),
    isSenderScope   ? context_->sender   : QString() );
}

/**
 * @brief Set the configuration of this object.
 * MUST be called before initialize().
 */
void PluginManager::setConfig( Config *c )
{
  config_ = c;
  connect( c,    SIGNAL( configReloaded() ),
           this, SLOT(       initialize() ) );
}

/**
 * @brief Set the context of this call.
 *
 * All PluginManager handlers call this method for later reference. For
 * example, the Database needs to look back at the current call, to save
 * variables in the correct scope.
 */
void PluginManager::setContext(QString network, QString receiver, QString sender)
{
  Q_ASSERT( context_ == 0 );
  context_ = new Context;
  context_->network  = network;
  context_->receiver = receiver;
  context_->sender   = sender;
}

/******* ADDITIONAL HANDLERS **********/

/**
 * @brief welcomed() handler.
 *
 * This method is called when DaVinci finishes a handshake with the IRC server.
 */
void PluginManager::welcomed( Network &n )
{
  setContext( n.config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->welcomed( n );
  }
  clearContext();
}

/**
 * @brief connected() handler.
 *
 * This method is called when DaVinci connects to an IRC server, before authorization.
 */
void PluginManager::connected( Network &n, const Server &s )
{
  setContext( n.config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->connected( n, s );
  }
  clearContext();
}

/**
 * @brief Database getter.
 *
 * Returns the database for this PluginManager and set of plugins.
 */
Database *PluginManager::database() const
{
  return database_;
}

/**
 * @brief disconnected() handler.
 *
 * This method is called when the connection is broken between DaVinci and an IRC server.
 */
void PluginManager::disconnected( Network &n )
{
  setContext( n.config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->disconnected( n );
  }
  clearContext();
}

void PluginManager::motdReceived ( const QString &motd, Irc::Buffer *b ) {
  Network *n = Network::fromBuffer( b );
  Q_ASSERT( n != 0 );
  setContext( n->config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->motdReceived( *n, motd, b );
  }
  clearContext();
}

#define PLUGIN_EVENT_RELAY_1STR( EVENTNAME ) \
void PluginManager::EVENTNAME ( const QString &str, Irc::Buffer *b ) { \
  Network *n = Network::fromBuffer( b ); \
  Q_ASSERT( n != 0 ); \
  setContext( n->config()->name, b->receiver(), str ); \
  foreach( Plugin *p, plugins_ ) \
  { \
    p->EVENTNAME( *n, str, b ); \
  } \
  clearContext(); \
}

#define PLUGIN_EVENT_RELAY_2STR( EVENTNAME ) \
void PluginManager::EVENTNAME ( const QString &str, const QString &str2, Irc::Buffer *b ) { \
  Network *n = Network::fromBuffer( b ); \
  Q_ASSERT( n != 0 ); \
  setContext( n->config()->name, b->receiver(), str ); \
  foreach( Plugin *p, plugins_ ) \
  { \
    p->EVENTNAME( *n, str, str2, b ); \
  } \
  clearContext(); \
}

#define PLUGIN_EVENT_RELAY_3STR( EVENTNAME ) \
void PluginManager::EVENTNAME ( const QString &str, const QString &str2, \
                           const QString &str3, Irc::Buffer *b ) { \
  Network *n = Network::fromBuffer( b ); \
  Q_ASSERT( n != 0 ); \
  setContext( n->config()->name, b->receiver(), str ); \
  foreach( Plugin *p, plugins_ ) \
  { \
    p->EVENTNAME( *n, str, str2, str3, b ); \
  } \
  clearContext(); \
}

PLUGIN_EVENT_RELAY_1STR( joined );
PLUGIN_EVENT_RELAY_2STR( parted );
PLUGIN_EVENT_RELAY_2STR( quit );
PLUGIN_EVENT_RELAY_2STR( nickChanged );
PLUGIN_EVENT_RELAY_3STR( modeChanged );
PLUGIN_EVENT_RELAY_2STR( topicChanged );
PLUGIN_EVENT_RELAY_3STR( invited );
PLUGIN_EVENT_RELAY_3STR( kicked );
PLUGIN_EVENT_RELAY_2STR( messageReceived );
PLUGIN_EVENT_RELAY_2STR( noticeReceived );
PLUGIN_EVENT_RELAY_2STR( ctcpRequestReceived );
PLUGIN_EVENT_RELAY_2STR( ctcpReplyReceived );
PLUGIN_EVENT_RELAY_2STR( ctcpActionReceived );

#undef PLUGIN_EVENT_RELAY_1STR
#undef PLUGIN_EVENT_RELAY_2STR
#undef PLUGIN_EVENT_RELAY_3STR

void PluginManager::numericMessageReceived( const QString &origin, uint code,
                           const QStringList &params, Irc::Buffer *buffer )
{
  Network *n = Network::fromBuffer( buffer );
  Q_ASSERT( n != 0 );
  setContext( n->config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->numericMessageReceived( *n, origin, code, params, buffer );
  }
  clearContext();
}

void PluginManager::unknownMessageReceived( const QString &origin,
                          const QStringList &params, Irc::Buffer *buffer )
{
  Network *n = Network::fromBuffer( buffer );
  Q_ASSERT( n != 0 );
  setContext( n->config()->name );
  foreach( Plugin *p, plugins_ )
  {
    p->unknownMessageReceived( *n, origin, params, buffer );
  }
  clearContext();
}

<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/theme_background.h"

#include "app/gfx/canvas.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/view.h"

ThemeBackground::ThemeBackground(BrowserView* browser_view)
    : browser_view_(browser_view) {
}

void ThemeBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
  int image_name;
  Browser* browser = browser_view_->browser();
  if (browser->window()->IsActive()) {
    image_name = browser->profile()->IsOffTheRecord() ?
        IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
  } else {
    image_name = browser->profile()->IsOffTheRecord() ?
        IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE;
  }
  ThemeProvider* theme = browser->profile()->GetThemeProvider();
  SkBitmap* background = theme->GetBitmapNamed(image_name);

  gfx::Point origin(0, 0);
  views::View::ConvertPointToView(view,
                                  browser_view_->frame()->GetFrameView(),
                                  &origin);
#if defined(OS_CHROMEOS)
  const int kCustomFrameBackgroundVerticalOffset = 15;
  // TODO(oshima): Remove this once we fully migrated to views.
  // See http://crbug.com/28580.
  if (browser_view_->IsMaximized()) {
    origin.Offset(0, kCustomFrameBackgroundVerticalOffset + 1);
  }
#endif
  canvas->TileImageInt(*background,
                       origin.x(), origin.y(), 0, 0,
                       view->width(), view->height());
}
<commit_msg>Don't theme app/popup window<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/theme_background.h"

#include "app/gfx/canvas.h"
#include "app/resource_bundle.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/view.h"

ThemeBackground::ThemeBackground(BrowserView* browser_view)
    : browser_view_(browser_view) {
}

void ThemeBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
  SkBitmap* background;

  // Never theme app and popup windows.
  if (!browser_view_->IsBrowserTypeNormal()) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    if (browser_view_->IsActive())
      background = rb.GetBitmapNamed(IDR_FRAME);
    else
      background = rb.GetBitmapNamed(IDR_THEME_FRAME_INACTIVE);
  } else {
    Profile* profile = browser_view_->browser()->profile();
    ThemeProvider* theme = profile->GetThemeProvider();
    if (browser_view_->IsActive()) {
      background = theme->GetBitmapNamed(
          profile->IsOffTheRecord() ?
          IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME);
    } else {
      background = theme->GetBitmapNamed(
          profile->IsOffTheRecord() ?
          IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE);
    }
  }

  gfx::Point origin(0, 0);
  views::View::ConvertPointToView(view,
                                  browser_view_->frame()->GetFrameView(),
                                  &origin);
#if defined(OS_CHROMEOS)
  const int kCustomFrameBackgroundVerticalOffset = 15;
  // TODO(oshima): Remove this once we fully migrated to views.
  // See http://crbug.com/28580.
  if (browser_view_->IsMaximized()) {
    origin.Offset(0, kCustomFrameBackgroundVerticalOffset + 1);
  }
#endif
  canvas->TileImageInt(*background,
                       origin.x(), origin.y(), 0, 0,
                       view->width(), view->height());
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// CoinVault
//
// requestpaymentdialogview.cpp
//
// Copyright (c) 2013-2014 Eric Lombrozo
//
// All Rights Reserved.

#include "requestpaymentdialog.h"
#include "ui_requestpaymentdialog.h"

#include "accountmodel.h"
#include "coinparams.h"
#include "numberformats.h"
#include "currencyvalidator.h"

#include <QMessageBox>
#include <QClipboard>
#include <QRegExpValidator>

#include <qrencode.h>

RequestPaymentDialog::RequestPaymentDialog(AccountModel* accountModel, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RequestPaymentDialog),
    accountModel_(accountModel)
{
    ui->setupUi(this);
    connect(accountModel_, SIGNAL(updated(const QStringList&)), this, SLOT(setAccounts(const QStringList&)));

    ui->invoiceAmountLineEdit->setValidator(new CurrencyValidator(getCoinParams().currency_max(), getCoinParams().currency_decimals()));
}

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

void RequestPaymentDialog::setAccounts(const QStringList& accountNames)
{
    ui->accountComboBox->clear();
    ui->accountComboBox->addItems(accountNames);
}

void RequestPaymentDialog::setQRCode(const QString& address)
{
    QRcode* qrcode = QRcode_encodeString(address.toUtf8().data(), 0, QR_ECLEVEL_H, QR_MODE_8, 1);
    QImage qrImage(qrcode->width + 6, qrcode->width + 6, QImage::Format_RGB32);
    qrImage.fill(0xffffff);
    unsigned char* p = qrcode->data;
    for (int y = 0; y < qrcode->width; y++)
    {
        for (int x = 0; x < qrcode->width; x++)
        {
            qrImage.setPixel(x + 3, y + 3, ((*p & 1) ? 0x000000 : 0xffffff));
            p++;
        }
    }
    QRcode_free(qrcode);

    ui->qrLabel->setPixmap(QPixmap::fromImage(qrImage).scaled(ui->qrLabel->width(), ui->qrLabel->height()));
}

void RequestPaymentDialog::setCurrentAccount(const QString &accountName)
{
    ui->accountComboBox->setCurrentText(accountName);
    clearInvoice();
}

void RequestPaymentDialog::clearInvoice()
{
        ui->invoiceDetailsLabelLineEdit->clear();
        ui->invoiceDetailsAddressLineEdit->clear();
        ui->invoiceDetailsScriptLineEdit->clear();
        ui->invoiceDetailsUrlLineEdit->clear();
        ui->qrLabel->clear();
}

void RequestPaymentDialog::on_newInvoiceButton_clicked()
{
    try {
        QString accountName = ui->accountComboBox->currentText();
        QString invoiceLabel = ui->invoiceLineEdit->text();
        QString invoiceAmount = ui->invoiceAmountLineEdit->text();
        auto pair = accountModel_->issueNewScript(accountName, invoiceLabel);
        accountModel_->update();
        ui->invoiceDetailsLabelLineEdit->setText(invoiceLabel);
        ui->invoiceDetailsAddressLineEdit->setText(pair.first);
        ui->invoiceDetailsScriptLineEdit->setText(QString::fromStdString(uchar_vector(pair.second).getHex()));
        QString url = QString(getCoinParams().url_prefix()) + ":" + pair.first;
        int nParams = 0;
        if (!invoiceLabel.isEmpty()) {
            url += (nParams == 0) ? "?" : "&";
            url += "label=";
            url += invoiceLabel;
            nParams++;
        }
        if (!invoiceAmount.isEmpty()) {
            url += (nParams == 0) ? "?" : "&";
            url += "amount=";
            url += invoiceAmount;
            nParams++;
        }
        ui->invoiceDetailsUrlLineEdit->setText(url);
        setQRCode(pair.first);
    }
    catch (const std::exception& e) {
        QMessageBox::critical(this, tr("Error"), QString::fromStdString(e.what()));
    }
}

void RequestPaymentDialog::on_addressClipboardButton_clicked()
{
    QApplication::clipboard()->setText(ui->invoiceDetailsAddressLineEdit->text());
}

void RequestPaymentDialog::on_scriptClipboardButton_clicked()
{
    QApplication::clipboard()->setText(ui->invoiceDetailsScriptLineEdit->text());
}

void RequestPaymentDialog::on_urlClipboardButton_clicked()
{
    QApplication::clipboard()->setText(ui->invoiceDetailsUrlLineEdit->text());
}

void RequestPaymentDialog::on_closeButton_clicked()
{
    this->close();
}

<commit_msg>Display currency symbol in invoice.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// CoinVault
//
// requestpaymentdialogview.cpp
//
// Copyright (c) 2013-2014 Eric Lombrozo
//
// All Rights Reserved.

#include "requestpaymentdialog.h"
#include "ui_requestpaymentdialog.h"

#include "accountmodel.h"
#include "coinparams.h"
#include "numberformats.h"
#include "currencyvalidator.h"

#include <QMessageBox>
#include <QClipboard>
#include <QRegExpValidator>

#include <qrencode.h>

RequestPaymentDialog::RequestPaymentDialog(AccountModel* accountModel, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RequestPaymentDialog),
    accountModel_(accountModel)
{
    ui->setupUi(this);
    connect(accountModel_, SIGNAL(updated(const QStringList&)), this, SLOT(setAccounts(const QStringList&)));

    ui->invoiceAmountLabel->setText(tr("Amount") + " (" + getCoinParams().currency_symbol() + "):");
    ui->invoiceAmountLineEdit->setValidator(new CurrencyValidator(getCoinParams().currency_max(), getCoinParams().currency_decimals()));
}

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

void RequestPaymentDialog::setAccounts(const QStringList& accountNames)
{
    ui->accountComboBox->clear();
    ui->accountComboBox->addItems(accountNames);
}

void RequestPaymentDialog::setQRCode(const QString& address)
{
    QRcode* qrcode = QRcode_encodeString(address.toUtf8().data(), 0, QR_ECLEVEL_H, QR_MODE_8, 1);
    QImage qrImage(qrcode->width + 6, qrcode->width + 6, QImage::Format_RGB32);
    qrImage.fill(0xffffff);
    unsigned char* p = qrcode->data;
    for (int y = 0; y < qrcode->width; y++)
    {
        for (int x = 0; x < qrcode->width; x++)
        {
            qrImage.setPixel(x + 3, y + 3, ((*p & 1) ? 0x000000 : 0xffffff));
            p++;
        }
    }
    QRcode_free(qrcode);

    ui->qrLabel->setPixmap(QPixmap::fromImage(qrImage).scaled(ui->qrLabel->width(), ui->qrLabel->height()));
}

void RequestPaymentDialog::setCurrentAccount(const QString &accountName)
{
    ui->accountComboBox->setCurrentText(accountName);
    clearInvoice();
}

void RequestPaymentDialog::clearInvoice()
{
        ui->invoiceDetailsLabelLineEdit->clear();
        ui->invoiceDetailsAddressLineEdit->clear();
        ui->invoiceDetailsScriptLineEdit->clear();
        ui->invoiceDetailsUrlLineEdit->clear();
        ui->qrLabel->clear();
}

void RequestPaymentDialog::on_newInvoiceButton_clicked()
{
    try {
        QString accountName = ui->accountComboBox->currentText();
        QString invoiceLabel = ui->invoiceLineEdit->text();
        QString invoiceAmount = ui->invoiceAmountLineEdit->text();
        auto pair = accountModel_->issueNewScript(accountName, invoiceLabel);
        accountModel_->update();
        ui->invoiceDetailsLabelLineEdit->setText(invoiceLabel);
        ui->invoiceDetailsAddressLineEdit->setText(pair.first);
        ui->invoiceDetailsScriptLineEdit->setText(QString::fromStdString(uchar_vector(pair.second).getHex()));
        QString url = QString(getCoinParams().url_prefix()) + ":" + pair.first;
        int nParams = 0;
        if (!invoiceLabel.isEmpty()) {
            url += (nParams == 0) ? "?" : "&";
            url += "label=";
            url += invoiceLabel;
            nParams++;
        }
        if (!invoiceAmount.isEmpty()) {
            url += (nParams == 0) ? "?" : "&";
            url += "amount=";
            url += invoiceAmount;
            nParams++;
        }
        ui->invoiceDetailsUrlLineEdit->setText(url);
        setQRCode(pair.first);
    }
    catch (const std::exception& e) {
        QMessageBox::critical(this, tr("Error"), QString::fromStdString(e.what()));
    }
}

void RequestPaymentDialog::on_addressClipboardButton_clicked()
{
    QApplication::clipboard()->setText(ui->invoiceDetailsAddressLineEdit->text());
}

void RequestPaymentDialog::on_scriptClipboardButton_clicked()
{
    QApplication::clipboard()->setText(ui->invoiceDetailsScriptLineEdit->text());
}

void RequestPaymentDialog::on_urlClipboardButton_clicked()
{
    QApplication::clipboard()->setText(ui->invoiceDetailsUrlLineEdit->text());
}

void RequestPaymentDialog::on_closeButton_clicked()
{
    this->close();
}

<|endoftext|>