<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ipbm.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-26 17:05:51 $
 *
 *  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_goodies.hxx"

#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <svtools/fltcall.hxx>

//============================ PBMReader ==================================

class PBMReader {

private:

    SvStream*           mpPBM;          // Die einzulesende PBM-Datei

    BOOL                mbStatus;
    BOOL                mbRemark;       // FALSE wenn sich stream in einem Kommentar befindet
    BOOL                mbRaw;          // RAW/ASCII MODE
    ULONG               mnMode;         // 0->PBM, 1->PGM, 2->PPM
    Bitmap              maBmp;
    BitmapWriteAccess*  mpAcc;
    ULONG               mnWidth, mnHeight;  // Bildausmass in Pixeln
    ULONG               mnCol;
    ULONG               mnMaxVal;           // maximaler wert in den
    BOOL                ImplCallback( USHORT nPercent );
    BOOL                ImplReadBody();
    BOOL                ImplReadHeader();

public:
                        PBMReader();
                        ~PBMReader();
    BOOL                ReadPBM( SvStream & rPBM, Graphic & rGraphic );
};

//=================== Methoden von PBMReader ==============================

PBMReader::PBMReader() :
    mbStatus    ( TRUE ),
    mbRemark    ( FALSE ),
    mbRaw       ( TRUE ),
    mpAcc       ( NULL )
{
}

PBMReader::~PBMReader()
{
}

BOOL PBMReader::ImplCallback( USHORT /*nPercent*/ )
{
/*
    if ( pCallback != NULL )
    {
        if ( ( (*pCallback)( pCallerData, nPercent ) ) == TRUE )
        {
            mpPBM->SetError( SVSTREAM_FILEFORMAT_ERROR );
            return TRUE;
        }
    }
*/
    return FALSE;
}

BOOL PBMReader::ReadPBM( SvStream & rPBM, Graphic & rGraphic )
{
    USHORT i;

    if ( rPBM.GetError() )
        return FALSE;

    mpPBM = &rPBM;
    mpPBM->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );

    // Kopf einlesen:

    if ( ( mbStatus = ImplReadHeader() ) == FALSE )
        return FALSE;

    if ( mnWidth == 0 || mnHeight == 0 )
        return FALSE;

    // 0->PBM, 1->PGM, 2->PPM
    switch ( mnMode )
    {
        case 0 :
            maBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
            if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == FALSE )
                return FALSE;
            mpAcc->SetPaletteEntryCount( 2 );
            mpAcc->SetPaletteColor( 0, BitmapColor( 0xff, 0xff, 0xff ) );
            mpAcc->SetPaletteColor( 1, BitmapColor( 0x00, 0x00, 0x00 ) );
            break;

        case 1 :
            if ( mnMaxVal <= 1 )
                maBmp = Bitmap( Size( mnWidth, mnHeight ), 1);
            else if ( mnMaxVal <= 15 )
                maBmp = Bitmap( Size( mnWidth, mnHeight ), 4);
            else
                maBmp = Bitmap( Size( mnWidth, mnHeight ), 8);

            if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == FALSE )
                return FALSE;
            mnCol = (USHORT)mnMaxVal + 1;
            if ( mnCol > 256 )
                mnCol = 256;

            mpAcc->SetPaletteEntryCount( 256 );
            for ( i = 0; i < mnCol; i++ )
            {
                ULONG nCount = 255 * i / mnCol;
                mpAcc->SetPaletteColor( i, BitmapColor( (BYTE)nCount, (BYTE)nCount, (BYTE)nCount ) );
            }
            break;
        case 2 :
            maBmp = Bitmap( Size( mnWidth, mnHeight ), 24 );
            if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == FALSE )
                return FALSE;
            break;
    }

    // Bitmap-Daten einlesen
    mbStatus = ImplReadBody();

    if ( mpAcc )
    {
        maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
    }
    if ( mbStatus )
        rGraphic = maBmp;

    return mbStatus;
}

BOOL PBMReader::ImplReadHeader()
{
    BYTE    nID[ 2 ];
    BYTE    nDat;
    BYTE    nMax, nCount = 0;
    BOOL    bFinished = FALSE;

    *mpPBM >> nID[ 0 ] >> nID[ 1 ];
    if ( nID[ 0 ] != 'P' )
        return FALSE;
    switch ( nID[ 1 ] )
    {
        case '1' :
            mbRaw = FALSE;
        case '4' :
            mnMode = 0;
            nMax = 2;               // number of parameters in Header
            break;
        case '2' :
            mbRaw = FALSE;
        case '5' :
            mnMode = 1;
            nMax = 3;
            break;
        case '3' :
            mbRaw = FALSE;
        case '6' :
            mnMode = 2;
            nMax = 3;
            break;
        default:
            return FALSE;
    }

    mnMaxVal = mnWidth = mnHeight = 0;

    while ( bFinished == FALSE )
    {
        if ( mpPBM->GetError() )
            return FALSE;

        *mpPBM >> nDat;

        if ( nDat == '#' )
        {
            mbRemark = TRUE;
            continue;
        }
        else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
        {
            mbRemark = FALSE;
            nDat = 0x20;
        }
        if ( mbRemark )
            continue;

        if ( ( nDat == 0x20 ) || ( nDat == 0x09 ) )
        {
            if ( ( nCount == 0 ) && mnWidth )
                nCount++;
            else if ( ( nCount == 1 ) && mnHeight )
            {
                if ( ++nCount == nMax )
                    bFinished = TRUE;
            }
            else if ( ( nCount == 2 ) && mnMaxVal )
            {
                bFinished = TRUE;
            }
            continue;
        }
        if ( ( nDat >= '0' ) && ( nDat <= '9' ) )
        {
            nDat -= '0';
            if ( nCount == 0 )
            {
                mnWidth *= 10;
                mnWidth += nDat;
            }
            else if ( nCount == 1 )
            {
                mnHeight *= 10;
                mnHeight += nDat;
            }
            else if ( nCount == 2 )
            {
                mnMaxVal *= 10;
                mnMaxVal += nDat;
            }
        }
        else
            return FALSE;
    }
    return mbStatus;
}

BOOL PBMReader::ImplReadBody()
{
    BOOL    bPara, bFinished = FALSE;
    BYTE    nDat = 0, nCount;
    ULONG   nGrey, nRGB[3];
    ULONG   nWidth = 0;
    ULONG   nHeight = 0;
    signed char nShift = 0;

    if ( mbRaw )
    {
        switch ( mnMode )
        {

            // PBM
            case 0 :
                while ( nHeight != mnHeight )
                {
                    if ( mpPBM->IsEof() || mpPBM->GetError() )
                        return FALSE;

                    if ( --nShift < 0 )
                    {
                        *mpPBM >> nDat;
                        nShift = 7;
                    }
                    mpAcc->SetPixel( nHeight, nWidth, nDat >> nShift );
                    if ( ++nWidth == mnWidth )
                    {
                        nShift = 0;
                        nWidth = 0;
                        nHeight++;
                        ImplCallback( (USHORT)( ( 100 * nHeight ) / mnHeight ) );   // processing output in percent
                    }
                }
                break;

            // PGM
            case 1 :
                while ( nHeight != mnHeight )
                {
                    if ( mpPBM->IsEof() || mpPBM->GetError() )
                        return FALSE;

                    *mpPBM >> nDat;
                    mpAcc->SetPixel( nHeight, nWidth++, nDat);

                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        nHeight++;
                        ImplCallback( (USHORT)( ( 100 * nHeight ) / mnHeight ) );   // processing output in percent
                    }
                }
                break;

            // PPM
            case 2 :
                while ( nHeight != mnHeight )
                {
                    if ( mpPBM->IsEof() || mpPBM->GetError() )
                        return FALSE;

                    BYTE    nR, nG, nB;
                    ULONG   nRed, nGreen, nBlue;
                    *mpPBM >> nR >> nG >> nB;
                    nRed = 255 * nR / mnMaxVal;
                    nGreen = 255 * nG / mnMaxVal;
                    nBlue = 255 * nB / mnMaxVal;
                    mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (BYTE)nRed, (BYTE)nGreen, (BYTE)nBlue ) );
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        nHeight++;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                }
                break;
        }
    }
    else switch  ( mnMode )
    {
        // PBM
        case 0 :
            while ( bFinished == FALSE )
            {
                if ( mpPBM->IsEof() || mpPBM->GetError() )
                    return FALSE;

                *mpPBM >> nDat;

                if ( nDat == '#' )
                {
                    mbRemark = TRUE;
                    continue;
                }
                else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
                {
                    mbRemark = FALSE;
                    continue;
                }
                if ( mbRemark || nDat == 0x20 || nDat == 0x09 )
                    continue;

                if ( nDat == '0' || nDat == '1' )
                {
                    mpAcc->SetPixel( nHeight, nWidth, (BYTE)nDat-'0' );
                    nWidth++;
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        if ( ++nHeight == mnHeight )
                            bFinished = TRUE;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                }
                else
                    return FALSE;
            }
            break;

        // PGM
        case 1 :

            bPara = FALSE;
            nCount = 0;
            nGrey = 0;

            while ( bFinished == FALSE )
            {
                if ( nCount )
                {
                    nCount--;
                    if ( nGrey <= mnMaxVal )
                        nGrey = 255 * nGrey / mnMaxVal;
                        mpAcc->SetPixel( nHeight, nWidth++, (BYTE)nGrey );
                    nGrey = 0;
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        if ( ++nHeight == mnHeight )
                            bFinished = TRUE;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                    continue;
                }

                if ( mpPBM->IsEof() || mpPBM->GetError() )
                    return FALSE;

                *mpPBM >> nDat;

                if ( nDat == '#' )
                {
                    mbRemark = TRUE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
                {
                    mbRemark = FALSE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }

                if ( nDat == 0x20 || nDat == 0x09 )
                {
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                if ( nDat >= '0' && nDat <= '9' )
                {
                    bPara = TRUE;
                    nGrey *= 10;
                    nGrey += nDat-'0';
                    continue;
                }
                else
                    return FALSE;
            }
            break;

        // PPM
        case 2 :

            bPara = FALSE;
            nCount = 0;
            nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;

            while ( bFinished == FALSE )
            {
                if ( nCount == 3 )
                {
                    nCount = 0;
                    mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (BYTE)nRGB[ 0 ], (BYTE)nRGB[ 1 ], (BYTE)nRGB[ 2 ] ) );
                    nCount = 0;
                    nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        if ( ++nHeight == mnHeight )
                            bFinished = TRUE;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                    continue;
                }

                if ( mpPBM->IsEof() || mpPBM->GetError() )
                    return FALSE;

                *mpPBM >> nDat;

                if ( nDat == '#' )
                {
                    mbRemark = TRUE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
                {
                    mbRemark = FALSE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }

                if ( nDat == 0x20 || nDat == 0x09 )
                {
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                if ( nDat >= '0' && nDat <= '9' )
                {
                    bPara = TRUE;
                    nRGB[ nCount ] *= 10;
                    nRGB[ nCount ] += nDat-'0';
                    continue;
                }
                else
                    return FALSE;
            }
            break;
    }
    return mbStatus;
}

//================== GraphicImport - die exportierte Funktion ================

extern "C" BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL )
{
    PBMReader aPBMReader;

    return aPBMReader.ReadPBM( rStream, rGraphic );
}

//================== ein bischen Muell fuer Windows ==========================
#ifndef GCC
#endif

#ifdef WIN

static HINSTANCE hDLLInst = 0;      // HANDLE der DLL

extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
{
#ifndef WNT
    if ( nHeap )
        UnlockData( 0 );
#endif

    hDLLInst = hDLL;

    return TRUE;
}

extern "C" int CALLBACK WEP( int )
{
    return 1;
}

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.8.40); FILE MERGED 2008/03/31 13:39:41 rt 1.8.40.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: ipbm.cxx,v $
 * $Revision: 1.9 $
 *
 * 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_goodies.hxx"

#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <svtools/fltcall.hxx>

//============================ PBMReader ==================================

class PBMReader {

private:

    SvStream*           mpPBM;          // Die einzulesende PBM-Datei

    BOOL                mbStatus;
    BOOL                mbRemark;       // FALSE wenn sich stream in einem Kommentar befindet
    BOOL                mbRaw;          // RAW/ASCII MODE
    ULONG               mnMode;         // 0->PBM, 1->PGM, 2->PPM
    Bitmap              maBmp;
    BitmapWriteAccess*  mpAcc;
    ULONG               mnWidth, mnHeight;  // Bildausmass in Pixeln
    ULONG               mnCol;
    ULONG               mnMaxVal;           // maximaler wert in den
    BOOL                ImplCallback( USHORT nPercent );
    BOOL                ImplReadBody();
    BOOL                ImplReadHeader();

public:
                        PBMReader();
                        ~PBMReader();
    BOOL                ReadPBM( SvStream & rPBM, Graphic & rGraphic );
};

//=================== Methoden von PBMReader ==============================

PBMReader::PBMReader() :
    mbStatus    ( TRUE ),
    mbRemark    ( FALSE ),
    mbRaw       ( TRUE ),
    mpAcc       ( NULL )
{
}

PBMReader::~PBMReader()
{
}

BOOL PBMReader::ImplCallback( USHORT /*nPercent*/ )
{
/*
    if ( pCallback != NULL )
    {
        if ( ( (*pCallback)( pCallerData, nPercent ) ) == TRUE )
        {
            mpPBM->SetError( SVSTREAM_FILEFORMAT_ERROR );
            return TRUE;
        }
    }
*/
    return FALSE;
}

BOOL PBMReader::ReadPBM( SvStream & rPBM, Graphic & rGraphic )
{
    USHORT i;

    if ( rPBM.GetError() )
        return FALSE;

    mpPBM = &rPBM;
    mpPBM->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );

    // Kopf einlesen:

    if ( ( mbStatus = ImplReadHeader() ) == FALSE )
        return FALSE;

    if ( mnWidth == 0 || mnHeight == 0 )
        return FALSE;

    // 0->PBM, 1->PGM, 2->PPM
    switch ( mnMode )
    {
        case 0 :
            maBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
            if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == FALSE )
                return FALSE;
            mpAcc->SetPaletteEntryCount( 2 );
            mpAcc->SetPaletteColor( 0, BitmapColor( 0xff, 0xff, 0xff ) );
            mpAcc->SetPaletteColor( 1, BitmapColor( 0x00, 0x00, 0x00 ) );
            break;

        case 1 :
            if ( mnMaxVal <= 1 )
                maBmp = Bitmap( Size( mnWidth, mnHeight ), 1);
            else if ( mnMaxVal <= 15 )
                maBmp = Bitmap( Size( mnWidth, mnHeight ), 4);
            else
                maBmp = Bitmap( Size( mnWidth, mnHeight ), 8);

            if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == FALSE )
                return FALSE;
            mnCol = (USHORT)mnMaxVal + 1;
            if ( mnCol > 256 )
                mnCol = 256;

            mpAcc->SetPaletteEntryCount( 256 );
            for ( i = 0; i < mnCol; i++ )
            {
                ULONG nCount = 255 * i / mnCol;
                mpAcc->SetPaletteColor( i, BitmapColor( (BYTE)nCount, (BYTE)nCount, (BYTE)nCount ) );
            }
            break;
        case 2 :
            maBmp = Bitmap( Size( mnWidth, mnHeight ), 24 );
            if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == FALSE )
                return FALSE;
            break;
    }

    // Bitmap-Daten einlesen
    mbStatus = ImplReadBody();

    if ( mpAcc )
    {
        maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
    }
    if ( mbStatus )
        rGraphic = maBmp;

    return mbStatus;
}

BOOL PBMReader::ImplReadHeader()
{
    BYTE    nID[ 2 ];
    BYTE    nDat;
    BYTE    nMax, nCount = 0;
    BOOL    bFinished = FALSE;

    *mpPBM >> nID[ 0 ] >> nID[ 1 ];
    if ( nID[ 0 ] != 'P' )
        return FALSE;
    switch ( nID[ 1 ] )
    {
        case '1' :
            mbRaw = FALSE;
        case '4' :
            mnMode = 0;
            nMax = 2;               // number of parameters in Header
            break;
        case '2' :
            mbRaw = FALSE;
        case '5' :
            mnMode = 1;
            nMax = 3;
            break;
        case '3' :
            mbRaw = FALSE;
        case '6' :
            mnMode = 2;
            nMax = 3;
            break;
        default:
            return FALSE;
    }

    mnMaxVal = mnWidth = mnHeight = 0;

    while ( bFinished == FALSE )
    {
        if ( mpPBM->GetError() )
            return FALSE;

        *mpPBM >> nDat;

        if ( nDat == '#' )
        {
            mbRemark = TRUE;
            continue;
        }
        else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
        {
            mbRemark = FALSE;
            nDat = 0x20;
        }
        if ( mbRemark )
            continue;

        if ( ( nDat == 0x20 ) || ( nDat == 0x09 ) )
        {
            if ( ( nCount == 0 ) && mnWidth )
                nCount++;
            else if ( ( nCount == 1 ) && mnHeight )
            {
                if ( ++nCount == nMax )
                    bFinished = TRUE;
            }
            else if ( ( nCount == 2 ) && mnMaxVal )
            {
                bFinished = TRUE;
            }
            continue;
        }
        if ( ( nDat >= '0' ) && ( nDat <= '9' ) )
        {
            nDat -= '0';
            if ( nCount == 0 )
            {
                mnWidth *= 10;
                mnWidth += nDat;
            }
            else if ( nCount == 1 )
            {
                mnHeight *= 10;
                mnHeight += nDat;
            }
            else if ( nCount == 2 )
            {
                mnMaxVal *= 10;
                mnMaxVal += nDat;
            }
        }
        else
            return FALSE;
    }
    return mbStatus;
}

BOOL PBMReader::ImplReadBody()
{
    BOOL    bPara, bFinished = FALSE;
    BYTE    nDat = 0, nCount;
    ULONG   nGrey, nRGB[3];
    ULONG   nWidth = 0;
    ULONG   nHeight = 0;
    signed char nShift = 0;

    if ( mbRaw )
    {
        switch ( mnMode )
        {

            // PBM
            case 0 :
                while ( nHeight != mnHeight )
                {
                    if ( mpPBM->IsEof() || mpPBM->GetError() )
                        return FALSE;

                    if ( --nShift < 0 )
                    {
                        *mpPBM >> nDat;
                        nShift = 7;
                    }
                    mpAcc->SetPixel( nHeight, nWidth, nDat >> nShift );
                    if ( ++nWidth == mnWidth )
                    {
                        nShift = 0;
                        nWidth = 0;
                        nHeight++;
                        ImplCallback( (USHORT)( ( 100 * nHeight ) / mnHeight ) );   // processing output in percent
                    }
                }
                break;

            // PGM
            case 1 :
                while ( nHeight != mnHeight )
                {
                    if ( mpPBM->IsEof() || mpPBM->GetError() )
                        return FALSE;

                    *mpPBM >> nDat;
                    mpAcc->SetPixel( nHeight, nWidth++, nDat);

                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        nHeight++;
                        ImplCallback( (USHORT)( ( 100 * nHeight ) / mnHeight ) );   // processing output in percent
                    }
                }
                break;

            // PPM
            case 2 :
                while ( nHeight != mnHeight )
                {
                    if ( mpPBM->IsEof() || mpPBM->GetError() )
                        return FALSE;

                    BYTE    nR, nG, nB;
                    ULONG   nRed, nGreen, nBlue;
                    *mpPBM >> nR >> nG >> nB;
                    nRed = 255 * nR / mnMaxVal;
                    nGreen = 255 * nG / mnMaxVal;
                    nBlue = 255 * nB / mnMaxVal;
                    mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (BYTE)nRed, (BYTE)nGreen, (BYTE)nBlue ) );
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        nHeight++;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                }
                break;
        }
    }
    else switch  ( mnMode )
    {
        // PBM
        case 0 :
            while ( bFinished == FALSE )
            {
                if ( mpPBM->IsEof() || mpPBM->GetError() )
                    return FALSE;

                *mpPBM >> nDat;

                if ( nDat == '#' )
                {
                    mbRemark = TRUE;
                    continue;
                }
                else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
                {
                    mbRemark = FALSE;
                    continue;
                }
                if ( mbRemark || nDat == 0x20 || nDat == 0x09 )
                    continue;

                if ( nDat == '0' || nDat == '1' )
                {
                    mpAcc->SetPixel( nHeight, nWidth, (BYTE)nDat-'0' );
                    nWidth++;
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        if ( ++nHeight == mnHeight )
                            bFinished = TRUE;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                }
                else
                    return FALSE;
            }
            break;

        // PGM
        case 1 :

            bPara = FALSE;
            nCount = 0;
            nGrey = 0;

            while ( bFinished == FALSE )
            {
                if ( nCount )
                {
                    nCount--;
                    if ( nGrey <= mnMaxVal )
                        nGrey = 255 * nGrey / mnMaxVal;
                        mpAcc->SetPixel( nHeight, nWidth++, (BYTE)nGrey );
                    nGrey = 0;
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        if ( ++nHeight == mnHeight )
                            bFinished = TRUE;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                    continue;
                }

                if ( mpPBM->IsEof() || mpPBM->GetError() )
                    return FALSE;

                *mpPBM >> nDat;

                if ( nDat == '#' )
                {
                    mbRemark = TRUE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
                {
                    mbRemark = FALSE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }

                if ( nDat == 0x20 || nDat == 0x09 )
                {
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                if ( nDat >= '0' && nDat <= '9' )
                {
                    bPara = TRUE;
                    nGrey *= 10;
                    nGrey += nDat-'0';
                    continue;
                }
                else
                    return FALSE;
            }
            break;

        // PPM
        case 2 :

            bPara = FALSE;
            nCount = 0;
            nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;

            while ( bFinished == FALSE )
            {
                if ( nCount == 3 )
                {
                    nCount = 0;
                    mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (BYTE)nRGB[ 0 ], (BYTE)nRGB[ 1 ], (BYTE)nRGB[ 2 ] ) );
                    nCount = 0;
                    nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
                    if ( nWidth == mnWidth )
                    {
                        nWidth = 0;
                        if ( ++nHeight == mnHeight )
                            bFinished = TRUE;
                        ImplCallback( (USHORT) ( ( 100 * nHeight ) / mnHeight ) );  // processing output in percent
                    }
                    continue;
                }

                if ( mpPBM->IsEof() || mpPBM->GetError() )
                    return FALSE;

                *mpPBM >> nDat;

                if ( nDat == '#' )
                {
                    mbRemark = TRUE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
                {
                    mbRemark = FALSE;
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }

                if ( nDat == 0x20 || nDat == 0x09 )
                {
                    if ( bPara )
                    {
                        bPara = FALSE;
                        nCount++;
                    }
                    continue;
                }
                if ( nDat >= '0' && nDat <= '9' )
                {
                    bPara = TRUE;
                    nRGB[ nCount ] *= 10;
                    nRGB[ nCount ] += nDat-'0';
                    continue;
                }
                else
                    return FALSE;
            }
            break;
    }
    return mbStatus;
}

//================== GraphicImport - die exportierte Funktion ================

extern "C" BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL )
{
    PBMReader aPBMReader;

    return aPBMReader.ReadPBM( rStream, rGraphic );
}

//================== ein bischen Muell fuer Windows ==========================
#ifndef GCC
#endif

#ifdef WIN

static HINSTANCE hDLLInst = 0;      // HANDLE der DLL

extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
{
#ifndef WNT
    if ( nHeap )
        UnlockData( 0 );
#endif

    hDLLInst = hDLL;

    return TRUE;
}

extern "C" int CALLBACK WEP( int )
{
    return 1;
}

#endif

<|endoftext|>


<commit_before>/* Rapicorn
 * Copyright (C) 2005 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "buttons.hh"
#include "containerimpl.hh"
#include "painter.hh"
#include "factory.hh"
#include "root.hh"

namespace Rapicorn {

ButtonArea::ButtonArea() :
  sig_check_activate (*this),
  sig_activate (*this)
{}

const PropertyList&
ButtonArea::list_properties()
{
  static Property *properties[] = {
    MakeProperty (ButtonArea, on_click,   _("On CLick"),   _("Command on button1 click"), "", "rw"),
    MakeProperty (ButtonArea, on_click2,  _("On CLick2"),  _("Command on button2 click"), "", "rw"),
    MakeProperty (ButtonArea, on_click3,  _("On CLick3"),  _("Command on button3 click"), "", "rw"),
    MakeProperty (ButtonArea, click_type, _("CLick Type"), _("Click event generation type"), CLICK_ON_RELEASE, "rw"),
  };
  static const PropertyList property_list (properties, Container::list_properties());
  return property_list;
}

class ButtonAreaImpl : public virtual ButtonArea, public virtual EventHandler, public virtual SingleContainerImpl {
  uint m_button, m_repeater;
  ClickType m_click_type;
  FocusFrame *m_focus_frame;
  String m_on_click[3];
public:
  ButtonAreaImpl() :
    m_button (0), m_repeater (0),
    m_click_type (CLICK_ON_RELEASE),
    m_focus_frame (NULL)
  {}
  virtual String    on_click   () const                 { return m_on_click[0]; }
  virtual void      on_click   (const String &command)  { m_on_click[0] = string_strip (command); }
  virtual String    on_click2  () const                 { return m_on_click[1]; }
  virtual void      on_click2  (const String &command)  { m_on_click[1] = string_strip (command); }
  virtual String    on_click3  () const                 { return m_on_click[2]; }
  virtual void      on_click3  (const String &command)  { m_on_click[2] = string_strip (command); }
  virtual ClickType click_type () const                 { return m_click_type; }
  virtual void      click_type (ClickType click_type_v) { reset(); m_click_type = click_type_v; }
  bool
  activate_command()
  {
    if (m_button >= 1 && m_button <= 3 && m_on_click[m_button - 1] != "")
      {
        exec_command (m_on_click[m_button - 1], std::nothrow);
        return TRUE;
      }
    else
      return FALSE;
  }
  void
  activate_click (EventType etype)
  {
    bool need_repeat = etype == BUTTON_PRESS && (m_click_type == CLICK_KEY_REPEAT || m_click_type == CLICK_SLOW_REPEAT || m_click_type == CLICK_FAST_REPEAT);
    bool need_click = need_repeat;
    need_click |= etype == BUTTON_PRESS && m_click_type == CLICK_ON_PRESS;
    need_click |= etype == BUTTON_RELEASE && m_click_type == CLICK_ON_RELEASE;
    bool can_exec = need_click && activate_command();
    need_repeat &= can_exec;
    if (need_repeat && !m_repeater)
      {
        if (m_click_type == CLICK_FAST_REPEAT)
          m_repeater = exec_fast_repeater (slot (*this, &ButtonAreaImpl::activate_command));
        else if (m_click_type == CLICK_SLOW_REPEAT)
          m_repeater = exec_slow_repeater (slot (*this, &ButtonAreaImpl::activate_command));
        else if (m_click_type == CLICK_KEY_REPEAT)
          m_repeater = exec_key_repeater (slot (*this, &ButtonAreaImpl::activate_command));
      }
    else if (!need_repeat && m_repeater)
      {
        remove_exec (m_repeater);
        m_repeater = 0;
      }
  }
  virtual bool
  can_focus () const
  {
    return m_focus_frame != NULL;
  }
  virtual bool
  register_focus_frame (FocusFrame &frame)
  {
    if (!m_focus_frame)
      m_focus_frame = &frame;
    return m_focus_frame == &frame;
  }
  virtual void
  unregister_focus_frame (FocusFrame &frame)
  {
    if (m_focus_frame == &frame)
      m_focus_frame = NULL;
  }
  virtual void
  reset (ResetMode mode = RESET_ALL)
  {
    remove_exec (m_repeater);
    m_repeater = 0;
    m_button = 0;
  }
  virtual bool
  handle_event (const Event &event)
  {
    ButtonArea &view = *this;
    bool handled = false, proper_release = false;
    switch (event.type)
      {
        const EventButton *bevent;
      case MOUSE_ENTER:
        view.impressed (m_button != 0);
        view.prelight (true);
        break;
      case MOUSE_LEAVE:
        view.prelight (false);
        view.impressed (m_button != 0);
        break;
      case BUTTON_PRESS:
      case BUTTON_2PRESS:
      case BUTTON_3PRESS:
        bevent = dynamic_cast<const EventButton*> (&event);
        if (!m_button and bevent->button >= 1 and bevent->button <= 3 and
            m_on_click[bevent->button - 1] != "")
          {
            bool inbutton = view.prelight();
            m_button = bevent->button;
            view.impressed (true);
            view.root()->add_grab (view);
            activate_click (inbutton ? BUTTON_PRESS : BUTTON_CANCELED);
            handled = true;
          }
        break;
      case BUTTON_RELEASE:
      case BUTTON_2RELEASE:
      case BUTTON_3RELEASE:
        proper_release = true;
      case BUTTON_CANCELED:
        bevent = dynamic_cast<const EventButton*> (&event);
        if (m_button == bevent->button)
          {
            bool inbutton = view.prelight();
            view.root()->remove_grab (view);
            activate_click (inbutton && proper_release ? BUTTON_RELEASE : BUTTON_CANCELED);
            view.impressed (false);
            m_button = 0;
            handled = true;
          }
        break;
      case KEY_PRESS:
      case KEY_RELEASE:
        break;
      case FOCUS_IN:
      case FOCUS_OUT:
        break;
      default: break;
      }
    return handled;
  }
};
static const ItemFactory<ButtonAreaImpl> button_area_factory ("Rapicorn::ButtonArea");

} // Rapicorn
<commit_msg>Tue Sep 12 02:25:49 2006  Tim Janik  <timj@gtk.org><commit_after>/* Rapicorn
 * Copyright (C) 2005 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "buttons.hh"
#include "containerimpl.hh"
#include "painter.hh"
#include "factory.hh"
#include "root.hh"

namespace Rapicorn {

ButtonArea::ButtonArea() :
  sig_check_activate (*this),
  sig_activate (*this)
{}

const PropertyList&
ButtonArea::list_properties()
{
  static Property *properties[] = {
    MakeProperty (ButtonArea, on_click,   _("On CLick"),   _("Command on button1 click"), "", "rw"),
    MakeProperty (ButtonArea, on_click2,  _("On CLick2"),  _("Command on button2 click"), "", "rw"),
    MakeProperty (ButtonArea, on_click3,  _("On CLick3"),  _("Command on button3 click"), "", "rw"),
    MakeProperty (ButtonArea, click_type, _("CLick Type"), _("Click event generation type"), CLICK_ON_RELEASE, "rw"),
  };
  static const PropertyList property_list (properties, Container::list_properties());
  return property_list;
}

class ButtonAreaImpl : public virtual ButtonArea, public virtual EventHandler, public virtual SingleContainerImpl {
  uint m_button, m_repeater;
  ClickType m_click_type;
  FocusFrame *m_focus_frame;
  String m_on_click[3];
public:
  ButtonAreaImpl() :
    m_button (0), m_repeater (0),
    m_click_type (CLICK_ON_RELEASE),
    m_focus_frame (NULL)
  {}
  virtual String    on_click   () const                 { return m_on_click[0]; }
  virtual void      on_click   (const String &command)  { m_on_click[0] = string_strip (command); }
  virtual String    on_click2  () const                 { return m_on_click[1]; }
  virtual void      on_click2  (const String &command)  { m_on_click[1] = string_strip (command); }
  virtual String    on_click3  () const                 { return m_on_click[2]; }
  virtual void      on_click3  (const String &command)  { m_on_click[2] = string_strip (command); }
  virtual ClickType click_type () const                 { return m_click_type; }
  virtual void      click_type (ClickType click_type_v) { reset(); m_click_type = click_type_v; }
  bool
  activate_command()
  {
    if (m_button >= 1 && m_button <= 3 && m_on_click[m_button - 1] != "")
      {
        exec_command (m_on_click[m_button - 1], std::nothrow);
        return TRUE;
      }
    else
      return FALSE;
  }
  void
  activate_click (EventType etype)
  {
    bool need_repeat = etype == BUTTON_PRESS && (m_click_type == CLICK_KEY_REPEAT || m_click_type == CLICK_SLOW_REPEAT || m_click_type == CLICK_FAST_REPEAT);
    bool need_click = need_repeat;
    need_click |= etype == BUTTON_PRESS && m_click_type == CLICK_ON_PRESS;
    need_click |= etype == BUTTON_RELEASE && m_click_type == CLICK_ON_RELEASE;
    bool can_exec = need_click && activate_command();
    need_repeat &= can_exec;
    if (need_repeat && !m_repeater)
      {
        if (m_click_type == CLICK_FAST_REPEAT)
          m_repeater = exec_fast_repeater (slot (*this, &ButtonAreaImpl::activate_command));
        else if (m_click_type == CLICK_SLOW_REPEAT)
          m_repeater = exec_slow_repeater (slot (*this, &ButtonAreaImpl::activate_command));
        else if (m_click_type == CLICK_KEY_REPEAT)
          m_repeater = exec_key_repeater (slot (*this, &ButtonAreaImpl::activate_command));
      }
    else if (!need_repeat && m_repeater)
      {
        remove_exec (m_repeater);
        m_repeater = 0;
      }
  }
  virtual bool
  can_focus () const
  {
    return m_focus_frame != NULL;
  }
  bool
  move_focus (FocusDirType fdir)
  {
    if (!has_focus() && can_focus())
      grab_focus();
    return false;
  }
  virtual bool
  register_focus_frame (FocusFrame &frame)
  {
    if (!m_focus_frame)
      m_focus_frame = &frame;
    return m_focus_frame == &frame;
  }
  virtual void
  unregister_focus_frame (FocusFrame &frame)
  {
    if (m_focus_frame == &frame)
      m_focus_frame = NULL;
  }
  virtual void
  reset (ResetMode mode = RESET_ALL)
  {
    remove_exec (m_repeater);
    m_repeater = 0;
    m_button = 0;
  }
  virtual bool
  handle_event (const Event &event)
  {
    ButtonArea &view = *this;
    bool handled = false, proper_release = false;
    switch (event.type)
      {
        const EventButton *bevent;
      case MOUSE_ENTER:
        view.impressed (m_button != 0);
        view.prelight (true);
        break;
      case MOUSE_LEAVE:
        view.prelight (false);
        view.impressed (m_button != 0);
        break;
      case BUTTON_PRESS:
      case BUTTON_2PRESS:
      case BUTTON_3PRESS:
        bevent = dynamic_cast<const EventButton*> (&event);
        if (!m_button and bevent->button >= 1 and bevent->button <= 3 and
            m_on_click[bevent->button - 1] != "")
          {
            bool inbutton = view.prelight();
            m_button = bevent->button;
            view.impressed (true);
            view.root()->add_grab (view);
            activate_click (inbutton ? BUTTON_PRESS : BUTTON_CANCELED);
            handled = true;
          }
        break;
      case BUTTON_RELEASE:
      case BUTTON_2RELEASE:
      case BUTTON_3RELEASE:
        proper_release = true;
      case BUTTON_CANCELED:
        bevent = dynamic_cast<const EventButton*> (&event);
        if (m_button == bevent->button)
          {
            bool inbutton = view.prelight();
            view.root()->remove_grab (view);
            activate_click (inbutton && proper_release ? BUTTON_RELEASE : BUTTON_CANCELED);
            view.impressed (false);
            m_button = 0;
            handled = true;
          }
        break;
      case KEY_PRESS:
      case KEY_RELEASE:
        break;
      case FOCUS_IN:
      case FOCUS_OUT:
        break;
      default: break;
      }
    return handled;
  }
};
static const ItemFactory<ButtonAreaImpl> button_area_factory ("Rapicorn::ButtonArea");

} // Rapicorn
<|endoftext|>


<commit_before>/*
 * SaftyLoss.cpp
 *
 *  Created on: 2013-4-12
 *      Author: fasiondog
 */

#include "SaftyLoss.h"

#if HKU_SUPPORT_SERIALIZATION
BOOST_CLASS_EXPORT(hku::SaftyLoss)
#endif

namespace hku {

SaftyLoss::SaftyLoss() : IndicatorImp("SAFTYLOSS", 1) {
    setParam<int>("n1", 10);
    setParam<int>("n2", 3);
    setParam<double>("p", 2.0);
}

SaftyLoss::~SaftyLoss() {}

bool SaftyLoss::check() {
    int n1 = getParam<int>("n1");
    int n2 = getParam<int>("n2");

    if (n1 < 2) {
        HKU_ERROR("Invalid param[n1] must >= 2 !");
        return false;
    }

    if (n2 < 1) {
        HKU_ERROR("Invalid param[n2] must >= 1 !");
        return false;
    }

    return true;
}

void SaftyLoss::_calculate(const Indicator& data) {
    size_t total = data.size();
    if (total == 0) {
        return;
    }
    _readyBuffer(total, 1);

    int n1 = getParam<int>("n1");
    int n2 = getParam<int>("n2");
    double p = getParam<double>("p");

    m_discard = data.discard() + n1 + n2 - 2;
    if (m_discard >= total) {
        m_discard = total;
        return;
    }

    price_t result(0.0);

    size_t start = discard();
    for (size_t i = start; i < total; ++i) {
        result = 0.0;
        for (size_t j = i + 1 - n2; j <= i; ++j) {
            size_t sum = 0.0;
            size_t num = 0;
            for (size_t k = j + 2 - n1; k <= j; ++k) {
                price_t pre = data[k - 1];
                price_t cur = data[k];
                if (pre > cur) {
                    sum += pre - cur;
                    ++num;
                }
            }

            price_t temp = data[j];
            if (num != 0) {
                temp = temp - (p * sum / num);
            }

            if (temp > result) {
                result = temp;
            }
        }

        _set(result, i);
    }
}

Indicator HKU_API SAFTYLOSS(int n1, int n2, double p) {
    IndicatorImpPtr result = make_shared<SaftyLoss>();
    result->setParam<int>("n1", n1);
    result->setParam<int>("n2", n2);
    result->setParam<double>("p", p);
    return Indicator(result);
}

Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1, int n2, double p) {
    return SAFTYLOSS(n1, n2, p)(data);
}

} /* namespace hku */
<commit_msg>fixed tet_SaftyLoss failed<commit_after>/*
 * SaftyLoss.cpp
 *
 *  Created on: 2013-4-12
 *      Author: fasiondog
 */

#include "SaftyLoss.h"

#if HKU_SUPPORT_SERIALIZATION
BOOST_CLASS_EXPORT(hku::SaftyLoss)
#endif

namespace hku {

SaftyLoss::SaftyLoss() : IndicatorImp("SAFTYLOSS", 1) {
    setParam<int>("n1", 10);
    setParam<int>("n2", 3);
    setParam<double>("p", 2.0);
}

SaftyLoss::~SaftyLoss() {}

bool SaftyLoss::check() {
    int n1 = getParam<int>("n1");
    int n2 = getParam<int>("n2");

    if (n1 < 2) {
        HKU_ERROR("Invalid param[n1] must >= 2 !");
        return false;
    }

    if (n2 < 1) {
        HKU_ERROR("Invalid param[n2] must >= 1 !");
        return false;
    }

    return true;
}

void SaftyLoss::_calculate(const Indicator& data) {
    size_t total = data.size();
    if (total == 0) {
        return;
    }
    _readyBuffer(total, 1);

    int n1 = getParam<int>("n1");
    int n2 = getParam<int>("n2");
    double p = getParam<double>("p");

    m_discard = data.discard() + n1 + n2 - 2;
    if (m_discard >= total) {
        m_discard = total;
        return;
    }

    price_t result(0.0);

    size_t start = discard();
    for (size_t i = start; i < total; ++i) {
        result = 0.0;
        for (size_t j = i + 1 - n2; j <= i; ++j) {
            price_t sum = 0.0;
            size_t num = 0;
            for (size_t k = j + 2 - n1; k <= j; ++k) {
                price_t pre = data[k - 1];
                price_t cur = data[k];
                if (pre > cur) {
                    sum += pre - cur;
                    ++num;
                }
            }

            price_t temp = data[j];
            if (num != 0) {
                temp = temp - (p * sum / num);
            }

            if (temp > result) {
                result = temp;
            }
        }

        _set(result, i);
    }
}

Indicator HKU_API SAFTYLOSS(int n1, int n2, double p) {
    IndicatorImpPtr result = make_shared<SaftyLoss>();
    result->setParam<int>("n1", n1);
    result->setParam<int>("n2", n2);
    result->setParam<double>("p", p);
    return Indicator(result);
}

Indicator HKU_API SAFTYLOSS(const Indicator& data, int n1, int n2, double p) {
    return SAFTYLOSS(n1, n2, p)(data);
}

} /* namespace hku */
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <iomanip>
#include <sstream>

#include "modules/common/log.h"
#include "modules/perception/obstacle/fusion/probabilistic_fusion/pbf_hm_track_object_matcher.h"
#include "modules/perception/obstacle/fusion/probabilistic_fusion/pbf_track_object_distance.h"

namespace apollo {
namespace perception {

bool PbfHmTrackObjectMatcher::Match(
    const std::vector<PbfTrackPtr> &fusion_tracks,
    const std::vector<std::shared_ptr<PbfSensorObject>> &sensor_objects,
    const TrackObjectMatcherOptions &options,
    std::vector<std::pair<int, int>> *assignments,
    std::vector<int> *unassigned_fusion_tracks,
    std::vector<int> *unassigned_sensor_objects,
    std::vector<double> *track2measurements_dist,
    std::vector<double> *measurement2track_dist) {
  CHECK_NOTNULL(assignments);
  CHECK_NOTNULL(unassigned_fusion_tracks);
  CHECK_NOTNULL(unassigned_sensor_objects);
  CHECK_NOTNULL(track2measurements_dist);
  CHECK_NOTNULL(measurement2track_dist);

  if (options.ref_point == nullptr) {
    AERROR << "reference points is nullptr!";
    return false;
  }

  IdAssign(fusion_tracks, sensor_objects, assignments, unassigned_fusion_tracks,
           unassigned_sensor_objects);
  ADEBUG << "Num of fusion tracks = " << fusion_tracks.size()
         << ", num of sensor objects = " << sensor_objects.size()
         << ", num of assignments = " << assignments->size();

  std::vector<std::vector<double>> association_mat;
  ComputeAssociationMat(fusion_tracks, sensor_objects,
                        *unassigned_fusion_tracks, *unassigned_sensor_objects,
                        *(options.ref_point), &association_mat);

  track2measurements_dist->assign(fusion_tracks.size(), 0);
  measurement2track_dist->assign(sensor_objects.size(), 0);

  std::vector<int> track_ind_g2l(fusion_tracks.size(), -1);
  for (size_t i = 0; i < unassigned_fusion_tracks->size(); ++i) {
    track_ind_g2l[unassigned_fusion_tracks->at(i)] = i;
  }

  std::vector<int> measurement_ind_g2l(sensor_objects.size(), -1);
  for (size_t i = 0; i < unassigned_sensor_objects->size(); ++i) {
    measurement_ind_g2l[unassigned_sensor_objects->at(i)] = i;
  }

  if (unassigned_fusion_tracks->empty() || unassigned_sensor_objects->empty()) {
    return true;
  }

  bool state = HmAssign(association_mat, assignments, unassigned_fusion_tracks,
                        unassigned_sensor_objects);

  for (const auto &track_measurement_pair : *assignments) {
    const int track_ind = track_measurement_pair.first;
    const int measurement_ind = track_measurement_pair.second;
    ADEBUG << "track_ind is matched to measurement_ind for sensor "
           << sensor_objects[0]->sensor_id << " " << track_ind << " "
           << measurement_ind;
    const int track_ind_loc = track_ind_g2l[track_ind];
    const int measurement_ind_loc = measurement_ind_g2l[measurement_ind];
    if (track_ind_loc >= 0 && measurement_ind_loc >= 0) {
      track2measurements_dist->at(track_ind) =
          association_mat[track_ind_loc][measurement_ind_loc];
      measurement2track_dist->at(measurement_ind) =
          association_mat[track_ind_loc][measurement_ind_loc];
    }
  }
  for (size_t i = 0; i < unassigned_fusion_tracks->size(); ++i) {
    const int track_ind = unassigned_fusion_tracks->at(i);
    const int track_ind_loc = track_ind_g2l[track_ind];
    track2measurements_dist->at(track_ind) = association_mat[track_ind_loc][0];
    for (size_t j = 1; j < association_mat[track_ind_loc].size(); ++j) {
      if (track2measurements_dist->at(track_ind) >
          association_mat[track_ind_loc][j]) {
        track2measurements_dist->at(track_ind) =
            association_mat[track_ind_loc][j];
      }
    }
  }

  for (const int m_ind : *unassigned_sensor_objects) {
    const int m_ind_loc = measurement_ind_g2l[m_ind];
    measurement2track_dist->at(m_ind) = association_mat[0][m_ind_loc];
    for (const auto &asso_mat_row : association_mat) {
      if (measurement2track_dist->at(m_ind) > asso_mat_row[m_ind_loc]) {
        measurement2track_dist->at(m_ind) = asso_mat_row[m_ind_loc];
      }
    }
  }
  return state;
}

std::string PbfHmTrackObjectMatcher::name() const {
  return "PbfHmTrackObjectMatcher";
}

void PbfHmTrackObjectMatcher::ComputeAssociationMat(
    const std::vector<PbfTrackPtr> &fusion_tracks,
    const std::vector<std::shared_ptr<PbfSensorObject>> &sensor_objects,
    const std::vector<int> &unassigned_fusion_tracks,
    const std::vector<int> &unassigned_sensor_objects,
    const Eigen::Vector3d &ref_point,
    std::vector<std::vector<double>> *association_mat) {
  CHECK_NOTNULL(association_mat);

  PbfTrackObjectDistance pbf_distance;
  Eigen::Vector3d local_ref_point = ref_point;
  TrackObjectDistanceOptions options;
  options.ref_point = &local_ref_point;
  association_mat->resize(unassigned_fusion_tracks.size());
  for (size_t i = 0; i < unassigned_fusion_tracks.size(); ++i) {
    int fusion_idx = unassigned_fusion_tracks[i];
    (*association_mat)[i].resize(unassigned_sensor_objects.size());
    const PbfTrackPtr &fusion_track = fusion_tracks[fusion_idx];
    for (size_t j = 0; j < unassigned_sensor_objects.size(); ++j) {
      int sensor_idx = unassigned_sensor_objects[j];
      const std::shared_ptr<PbfSensorObject> &sensor_object =
          sensor_objects[sensor_idx];
      double distance =
          pbf_distance.Compute(fusion_track, sensor_object, options);
      ADEBUG << "sensor distance:" << distance;
      (*association_mat)[i][j] = distance;
    }
  }
}

bool PbfHmTrackObjectMatcher::HmAssign(
    const std::vector<std::vector<double>> &association_mat,
    std::vector<std::pair<int, int>> *assignments,
    std::vector<int> *unassigned_fusion_tracks,
    std::vector<int> *unassigned_sensor_objects) {
  double max_dist = s_max_match_distance_;
  std::vector<std::vector<int>> fusion_components;
  std::vector<std::vector<int>> sensor_components;
  ComputeConnectedComponents(association_mat, max_dist, &fusion_components,
                             &sensor_components);

  if (fusion_components.size() != sensor_components.size()) {
    AERROR << "fusion component size it not equal to sensor component size.";
    return false;
  }
  for (size_t i = 0; i < fusion_components.size(); ++i) {
    if (fusion_components[i].empty() || sensor_components[i].empty()) {
      continue;
    } else if (fusion_components[i].size() == 1 &&
               sensor_components[i].size() == 1) {
      int idx_f = fusion_components[i][0];
      int idx_s = sensor_components[i][0];
      if (association_mat[idx_f][idx_s] < max_dist) {
        auto assignment = std::make_pair(unassigned_fusion_tracks->at(idx_f),
                                         unassigned_sensor_objects->at(idx_s));
        assignments->push_back(assignment);
        unassigned_fusion_tracks->at(idx_f) = -1;
        unassigned_sensor_objects->at(idx_s) = -1;
      }
      continue;
    }

    std::vector<std::vector<double>> loc_mat;
    std::vector<int> fusion_l2g;
    std::vector<int> sensor_l2g;
    fusion_l2g.resize(fusion_components[i].size());
    sensor_l2g.resize(sensor_components[i].size());
    loc_mat.resize(fusion_components[i].size());
    for (size_t j = 0; j < fusion_components[i].size(); ++j) {
      loc_mat[j].resize(sensor_components[i].size());
      fusion_l2g[j] = fusion_components[i][j];
      for (size_t k = 0; k < sensor_components[i].size(); ++k) {
        if (j == 0) {
          sensor_l2g[k] = sensor_components[i][k];
        }
        loc_mat[j][k] =
            association_mat[fusion_components[i][j]][sensor_components[i][k]];
      }
    }

    std::vector<int> fusion_idxs;
    std::vector<int> sensor_idxs;
    if (loc_mat.size() != 0 && loc_mat[0].size() != 0) {
      MinimizeAssignment(loc_mat, &fusion_idxs, &sensor_idxs);
    }

    for (size_t j = 0; j < fusion_idxs.size(); ++j) {
      int f_idx = fusion_idxs[j];
      int s_idx = sensor_idxs[j];
      if (loc_mat[f_idx][s_idx] < max_dist) {
        int gf_idx = fusion_l2g[f_idx];
        int gs_idx = sensor_l2g[s_idx];
        auto assignment = std::make_pair((*unassigned_fusion_tracks)[gf_idx],
                                         (*unassigned_sensor_objects)[gs_idx]);
        assignments->push_back(assignment);
        (*unassigned_fusion_tracks)[gf_idx] = -1;
        (*unassigned_sensor_objects)[gs_idx] = -1;
      }
    }
  }

  int unassigned_fusion_num = 0;
  for (size_t i = 0; i < unassigned_fusion_tracks->size(); ++i) {
    if ((*unassigned_fusion_tracks)[i] >= 0) {
      (*unassigned_fusion_tracks)[unassigned_fusion_num++] =
          (*unassigned_fusion_tracks)[i];
    }
  }
  (*unassigned_fusion_tracks).resize(unassigned_fusion_num);

  int unassigned_sensor_num = 0;
  for (size_t i = 0; i < unassigned_sensor_objects->size(); ++i) {
    if ((*unassigned_sensor_objects)[i] >= 0) {
      (*unassigned_sensor_objects)[unassigned_sensor_num++] =
          (*unassigned_sensor_objects)[i];
    }
  }
  unassigned_sensor_objects->resize(unassigned_sensor_num);
  return true;
}

void PbfHmTrackObjectMatcher::MinimizeAssignment(
    const std::vector<std::vector<double>> &association_mat,
    std::vector<int> *ref_idx, std::vector<int> *new_idx) {
  std::vector<std::vector<double>> cost(association_mat.size());
  for (size_t i = 0; i < association_mat.size(); ++i) {
    cost[i].resize(association_mat[i].size());
    for (size_t j = 0; j < association_mat[0].size(); ++j) {
      cost[i][j] = association_mat[i][j];
    }
  }

  HungarianOptimizer hungarian_optimizer(cost);
  hungarian_optimizer.minimize(ref_idx, new_idx);
}

bool PbfHmTrackObjectMatcher::Init() { return true; }

void PbfHmTrackObjectMatcher::ComputeConnectedComponents(
    const std::vector<std::vector<double>> &association_mat,
    const float connected_threshold,
    std::vector<std::vector<int>> *track_components,
    std::vector<std::vector<int>> *obj_components) {
  int no_track = association_mat.size();
  int no_obj = 0;
  if (no_track != 0) {
    no_obj = association_mat[0].size();
  }

  std::vector<std::vector<int>> nb_graph;
  nb_graph.resize(no_track + no_obj);
  for (int i = 0; i < no_track; i++) {
    for (int j = 0; j < no_obj; j++) {
      if (association_mat[i][j] < connected_threshold) {
        nb_graph[i].push_back(no_track + j);
        nb_graph[j + no_track].push_back(i);
      }
    }
  }

  std::vector<std::vector<int>> components;
  ConnectedComponentAnalysis(nb_graph, &components);
  track_components->clear();
  track_components->resize(components.size());
  obj_components->clear();
  obj_components->resize(components.size());
  for (size_t i = 0; i < components.size(); i++) {
    for (size_t j = 0; j < components[i].size(); j++) {
      int id = components[i][j];
      if (id < no_track) {
        (*track_components)[i].push_back(id);
      } else {
        id -= no_track;
        (*obj_components)[i].push_back(id);
      }
    }
  }
}

}  // namespace perception
}  // namespace apollo
<commit_msg>Update pbf_hm_track_object_matcher.cc<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <iomanip>
#include <sstream>

#include "modules/common/log.h"
#include "modules/perception/obstacle/fusion/probabilistic_fusion/pbf_hm_track_object_matcher.h"
#include "modules/perception/obstacle/fusion/probabilistic_fusion/pbf_track_object_distance.h"

namespace apollo {
namespace perception {

bool PbfHmTrackObjectMatcher::Match(
    const std::vector<PbfTrackPtr> &fusion_tracks,
    const std::vector<std::shared_ptr<PbfSensorObject>> &sensor_objects,
    const TrackObjectMatcherOptions &options,
    std::vector<std::pair<int, int>> *assignments,
    std::vector<int> *unassigned_fusion_tracks,
    std::vector<int> *unassigned_sensor_objects,
    std::vector<double> *track2measurements_dist,
    std::vector<double> *measurement2track_dist) {
  CHECK_NOTNULL(assignments);
  CHECK_NOTNULL(unassigned_fusion_tracks);
  CHECK_NOTNULL(unassigned_sensor_objects);
  CHECK_NOTNULL(track2measurements_dist);
  CHECK_NOTNULL(measurement2track_dist);

  if (options.ref_point == nullptr) {
    AERROR << "reference points is nullptr!";
    return false;
  }

  IdAssign(fusion_tracks, sensor_objects, assignments, unassigned_fusion_tracks,
           unassigned_sensor_objects);
  ADEBUG << "Num of fusion tracks = " << fusion_tracks.size()
         << ", num of sensor objects = " << sensor_objects.size()
         << ", num of assignments = " << assignments->size();

  std::vector<std::vector<double>> association_mat;
  ComputeAssociationMat(fusion_tracks, sensor_objects,
                        *unassigned_fusion_tracks, *unassigned_sensor_objects,
                        *(options.ref_point), &association_mat);

  track2measurements_dist->assign(fusion_tracks.size(), 0);
  measurement2track_dist->assign(sensor_objects.size(), 0);

  std::vector<int> track_ind_g2l(fusion_tracks.size(), -1);
  for (size_t i = 0; i < unassigned_fusion_tracks->size(); ++i) {
    track_ind_g2l[unassigned_fusion_tracks->at(i)] = i;
  }

  std::vector<int> measurement_ind_g2l(sensor_objects.size(), -1);
  for (size_t i = 0; i < unassigned_sensor_objects->size(); ++i) {
    measurement_ind_g2l[unassigned_sensor_objects->at(i)] = i;
  }

  if (unassigned_fusion_tracks->empty() || unassigned_sensor_objects->empty()) {
    return true;
  }

  bool state = HmAssign(association_mat, assignments, unassigned_fusion_tracks,
                        unassigned_sensor_objects);

  for (const auto &track_measurement_pair : *assignments) {
    const int track_ind = track_measurement_pair.first;
    const int measurement_ind = track_measurement_pair.second;
    ADEBUG << "track_ind is matched to measurement_ind for sensor "
           << sensor_objects[0]->sensor_id << " " << track_ind << " "
           << measurement_ind;
    const int track_ind_loc = track_ind_g2l[track_ind];
    const int measurement_ind_loc = measurement_ind_g2l[measurement_ind];
    if (track_ind_loc >= 0 && measurement_ind_loc >= 0) {
      track2measurements_dist->at(track_ind) =
          association_mat[track_ind_loc][measurement_ind_loc];
      measurement2track_dist->at(measurement_ind) =
          association_mat[track_ind_loc][measurement_ind_loc];
    }
  }
  for (size_t i = 0; i < unassigned_fusion_tracks->size(); ++i) {
    const int track_ind = unassigned_fusion_tracks->at(i);
    const int track_ind_loc = track_ind_g2l[track_ind];
    track2measurements_dist->at(track_ind) = association_mat[track_ind_loc][0];
    for (size_t j = 1; j < association_mat[track_ind_loc].size(); ++j) {
      if (track2measurements_dist->at(track_ind) >
          association_mat[track_ind_loc][j]) {
        track2measurements_dist->at(track_ind) =
            association_mat[track_ind_loc][j];
      }
    }
  }

  for (const int m_ind : *unassigned_sensor_objects) {
    const int m_ind_loc = measurement_ind_g2l[m_ind];
    measurement2track_dist->at(m_ind) = association_mat[0][m_ind_loc];
    for (const auto &asso_mat_row : association_mat) {
      if (measurement2track_dist->at(m_ind) > asso_mat_row[m_ind_loc]) {
        measurement2track_dist->at(m_ind) = asso_mat_row[m_ind_loc];
      }
    }
  }
  return state;
}

std::string PbfHmTrackObjectMatcher::name() const {
  return "PbfHmTrackObjectMatcher";
}

void PbfHmTrackObjectMatcher::ComputeAssociationMat(
    const std::vector<PbfTrackPtr> &fusion_tracks,
    const std::vector<std::shared_ptr<PbfSensorObject>> &sensor_objects,
    const std::vector<int> &unassigned_fusion_tracks,
    const std::vector<int> &unassigned_sensor_objects,
    const Eigen::Vector3d &ref_point,
    std::vector<std::vector<double>> *association_mat) {
  CHECK_NOTNULL(association_mat);

  PbfTrackObjectDistance pbf_distance;
  Eigen::Vector3d local_ref_point = ref_point;
  TrackObjectDistanceOptions options;
  options.ref_point = &local_ref_point;
  association_mat->resize(unassigned_fusion_tracks.size());
  for (size_t i = 0; i < unassigned_fusion_tracks.size(); ++i) {
    int fusion_idx = unassigned_fusion_tracks[i];
    (*association_mat)[i].resize(unassigned_sensor_objects.size());
    const PbfTrackPtr &fusion_track = fusion_tracks[fusion_idx];
    for (size_t j = 0; j < unassigned_sensor_objects.size(); ++j) {
      int sensor_idx = unassigned_sensor_objects[j];
      const std::shared_ptr<PbfSensorObject> &sensor_object =
          sensor_objects[sensor_idx];
      double distance =
          pbf_distance.Compute(fusion_track, sensor_object, options);
      ADEBUG << "sensor distance:" << distance;
      (*association_mat)[i][j] = distance;
    }
  }
}

bool PbfHmTrackObjectMatcher::HmAssign(
    const std::vector<std::vector<double>> &association_mat,
    std::vector<std::pair<int, int>> *assignments,
    std::vector<int> *unassigned_fusion_tracks,
    std::vector<int> *unassigned_sensor_objects) {
  double max_dist = s_max_match_distance_;
  std::vector<std::vector<int>> fusion_components;
  std::vector<std::vector<int>> sensor_components;
  ComputeConnectedComponents(association_mat, max_dist, &fusion_components,
                             &sensor_components);

  if (fusion_components.size() != sensor_components.size()) {
    AERROR << "fusion component size it not equal to sensor component size.";
    return false;
  }
  for (size_t i = 0; i < fusion_components.size(); ++i) {
    if (fusion_components[i].empty() || sensor_components[i].empty()) {
      continue;
    } else if (fusion_components[i].size() == 1 &&
               sensor_components[i].size() == 1) {
      int idx_f = fusion_components[i][0];
      int idx_s = sensor_components[i][0];
      if (association_mat[idx_f][idx_s] < max_dist) {
        auto assignment = std::make_pair(unassigned_fusion_tracks->at(idx_f),
                                         unassigned_sensor_objects->at(idx_s));
        assignments->push_back(assignment);
        unassigned_fusion_tracks->at(idx_f) = -1;
        unassigned_sensor_objects->at(idx_s) = -1;
      }
      continue;
    }

    std::vector<std::vector<double>> loc_mat;
    std::vector<int> fusion_l2g;
    std::vector<int> sensor_l2g;
    fusion_l2g.resize(fusion_components[i].size());
    sensor_l2g.resize(sensor_components[i].size());
    loc_mat.resize(fusion_components[i].size());
    for (size_t j = 0; j < fusion_components[i].size(); ++j) {
      loc_mat[j].resize(sensor_components[i].size());
      fusion_l2g[j] = fusion_components[i][j];
      for (size_t k = 0; k < sensor_components[i].size(); ++k) {
        if (j == 0) {
          sensor_l2g[k] = sensor_components[i][k];
        }
        loc_mat[j][k] =
            association_mat[fusion_components[i][j]][sensor_components[i][k]];
      }
    }

    std::vector<int> fusion_idxs;
    std::vector<int> sensor_idxs;
    if (loc_mat.size() != 0 && loc_mat[0].size() != 0) {
      MinimizeAssignment(loc_mat, &fusion_idxs, &sensor_idxs);
    }

    for (size_t j = 0; j < fusion_idxs.size(); ++j) {
      int f_idx = fusion_idxs[j];
      int s_idx = sensor_idxs[j];
      if (loc_mat[f_idx][s_idx] < max_dist) {
        int gf_idx = fusion_l2g[f_idx];
        int gs_idx = sensor_l2g[s_idx];
        auto assignment = std::make_pair((*unassigned_fusion_tracks)[gf_idx],
                                         (*unassigned_sensor_objects)[gs_idx]);
        assignments->push_back(assignment);
        (*unassigned_fusion_tracks)[gf_idx] = -1;
        (*unassigned_sensor_objects)[gs_idx] = -1;
      }
    }
  }

  int unassigned_fusion_num = 0;
  for (size_t i = 0; i < unassigned_fusion_tracks->size(); ++i) {
    if ((*unassigned_fusion_tracks)[i] >= 0) {
      (*unassigned_fusion_tracks)[unassigned_fusion_num++] =
          (*unassigned_fusion_tracks)[i];
    }
  }
  (*unassigned_fusion_tracks).resize(unassigned_fusion_num);

  int unassigned_sensor_num = 0;
  for (size_t i = 0; i < unassigned_sensor_objects->size(); ++i) {
    if ((*unassigned_sensor_objects)[i] >= 0) {
      (*unassigned_sensor_objects)[unassigned_sensor_num++] =
          (*unassigned_sensor_objects)[i];
    }
  }
  unassigned_sensor_objects->resize(unassigned_sensor_num);
  return true;
}

void PbfHmTrackObjectMatcher::MinimizeAssignment(
    const std::vector<std::vector<double>> &association_mat,
    std::vector<int> *ref_idx, std::vector<int> *new_idx) {
  HungarianOptimizer hungarian_optimizer(association_mat);
  hungarian_optimizer.minimize(ref_idx, new_idx);
}

bool PbfHmTrackObjectMatcher::Init() { return true; }

void PbfHmTrackObjectMatcher::ComputeConnectedComponents(
    const std::vector<std::vector<double>> &association_mat,
    const float connected_threshold,
    std::vector<std::vector<int>> *track_components,
    std::vector<std::vector<int>> *obj_components) {
  int no_track = association_mat.size();
  int no_obj = 0;
  if (no_track != 0) {
    no_obj = association_mat[0].size();
  }

  std::vector<std::vector<int>> nb_graph;
  nb_graph.resize(no_track + no_obj);
  for (int i = 0; i < no_track; i++) {
    for (int j = 0; j < no_obj; j++) {
      if (association_mat[i][j] < connected_threshold) {
        nb_graph[i].push_back(no_track + j);
        nb_graph[j + no_track].push_back(i);
      }
    }
  }

  std::vector<std::vector<int>> components;
  ConnectedComponentAnalysis(nb_graph, &components);
  track_components->clear();
  track_components->resize(components.size());
  obj_components->clear();
  obj_components->resize(components.size());
  for (size_t i = 0; i < components.size(); i++) {
    for (size_t j = 0; j < components[i].size(); j++) {
      int id = components[i][j];
      if (id < no_track) {
        (*track_components)[i].push_back(id);
      } else {
        id -= no_track;
        (*obj_components)[i].push_back(id);
      }
    }
  }
}

}  // namespace perception
}  // namespace apollo
<|endoftext|>


<commit_before>/*
 *  traywindow.cpp  -  the KDE system tray applet
 *  Program:  kalarm
 *  (C) 2002 - 2004 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include "kalarm.h"
#include <stdlib.h>

#include <qtooltip.h>

#include <kapplication.h>
#include <klocale.h>
#include <kstdaction.h>
#include <kaboutdata.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kstdguiitem.h>
#include <kconfig.h>
#include <kdebug.h>

#include "kalarmapp.h"
#include "mainwindow.h"
#include "messagewin.h"
#include "alarmcalendar.h"
#include "alarmlistview.h"
#include "daemon.h"
#include "daemongui.h"
#include "preferences.h"
#include "traywindow.moc"

class TrayTooltip : public QToolTip
{
	public:
		TrayTooltip(QWidget* parent) : QToolTip(parent) { }
	protected:
		virtual void maybeTip(const QPoint&);
};

struct TipItem
{
	QDateTime  dateTime;
	QString    text;
};

/*=============================================================================
= Class: TrayWindow
= The KDE system tray window.
=============================================================================*/
const QString TrayWindow::QUIT_WARN = QString::fromLatin1("QuitWarn");

TrayWindow::TrayWindow(KAlarmMainWindow* parent, const char* name)
	: KSystemTray((theApp()->wantRunInSystemTray() ? parent : 0), name),
	  mAssocMainWindow(parent)
{
	kdDebug(5950) << "TrayWindow::TrayWindow()\n";
	// Set up GUI icons
	mPixmapEnabled  = loadIcon("kalarm");
	mPixmapDisabled = loadIcon("kalarm_disabled");
	if (mPixmapEnabled.isNull() || mPixmapDisabled.isNull())
		KMessageBox::sorry(this, i18n("Cannot load system tray icon."),
		                         i18n("KAlarm Error", "%1 Error").arg(kapp->aboutData()->programName()));
	setAcceptDrops(true);         // allow drag-and-drop onto this window

	// Replace the default handler for the Quit context menu item
	KActionCollection* actcol = actionCollection();
	actcol->remove(actcol->action(KStdAction::stdName(KStdAction::Quit)));
	actcol->insert(KStdAction::quit(this, SLOT(slotQuit()), actcol));

	// Set up the context menu
	ActionAlarmsEnabled* a = theApp()->actionAlarmEnable();
	mAlarmsEnabledId = a->itemId(a->plug(contextMenu()));
	connect(a, SIGNAL(alarmsEnabledChange(bool)), this, SLOT(setEnabledStatus(bool)));
	theApp()->actionNewAlarm()->plug(contextMenu());
	Daemon::actionControl()->plug(contextMenu());
	theApp()->actionPreferences()->plug(contextMenu());

	// Set icon to correspond with the alarms enabled menu status
	DaemonGuiHandler* daemonGui = theApp()->daemonGuiHandler();
	daemonGui->checkStatus();
	setEnabledStatus(daemonGui->monitoringAlarms());

	mTooltip = new TrayTooltip(this);
}

TrayWindow::~TrayWindow()
{
	kdDebug(5950) << "TrayWindow::~TrayWindow()\n";
	delete mTooltip;
	mTooltip = 0;
	theApp()->removeWindow(this);
	emit deleted();
}

/******************************************************************************
* Called just before the context menu is displayed.
* Update the Alarms Enabled item status.
*/
void TrayWindow::contextMenuAboutToShow(KPopupMenu* menu)
{
	theApp()->daemonGuiHandler()->checkStatus();
	KSystemTray::contextMenuAboutToShow(menu);     // needed for KDE <= 3.1 compatibility
}

/******************************************************************************
* Called when the Quit context menu item is selected.
* Closes the system tray window, and if in 'run in system tray' mode closes all
* main windows, but does not exit the program if other windows are still open.
*/
void TrayWindow::slotQuit()
{
	kdDebug(5950)<<"TrayWindow::slotQuit()\n";
	if (theApp()->alarmsDisabledIfStopped()
	&&  KMessageBox::warningYesNo(this, i18n("Quitting will disable alarms\n"
	                                         "(once any alarm message windows are closed)."),
				      QString::null, KStdGuiItem::quit(), KStdGuiItem::cancel(), QUIT_WARN
	                             ) != KMessageBox::Yes)
		return;
	if (theApp()->wantRunInSystemTray())
	{
		if (!MessageWin::instanceCount())
			theApp()->quit();
		else
			KAlarmMainWindow::closeAll();
	}
	theApp()->displayTrayIcon(false);
}

/******************************************************************************
* Called when the Alarms Enabled action status has changed.
* Updates the alarms enabled menu item check state, and the icon pixmap.
*/
void TrayWindow::setEnabledStatus(bool status)
{
	kdDebug(5950) << "TrayWindow::setEnabledStatus(" << (int)status << ")\n";
	setPixmap(status ? mPixmapEnabled : mPixmapDisabled);
	contextMenu()->setItemChecked(mAlarmsEnabledId, status);
}

/******************************************************************************
*  Called when the mouse is clicked over the panel icon.
*  A left click displays the KAlarm main window.
*  A middle button click displays the New Alarm window.
*/
void TrayWindow::mousePressEvent(QMouseEvent* e)
{
	if (e->button() == LeftButton  &&  !theApp()->wantRunInSystemTray())
	{
		// Left click: display/hide the first main window
		mAssocMainWindow = KAlarmMainWindow::toggleWindow(mAssocMainWindow);
	}
	else if (e->button() == MidButton)
		KAlarmMainWindow::executeNew();    // display a New Alarm dialog
	else
		KSystemTray::mousePressEvent(e);
}

/******************************************************************************
*  Called when the mouse is released over the panel icon.
*  The main window (if not hidden) is raised and made the active window.
*  If this is done in mousePressEvent(), it doesn't work.
*/
void TrayWindow::mouseReleaseEvent(QMouseEvent* e)
{
	if (e->button() == LeftButton  &&  mAssocMainWindow  &&  mAssocMainWindow->isVisible())
	{
		mAssocMainWindow->raise();
		mAssocMainWindow->setActiveWindow();
	}
	else
		KSystemTray::mouseReleaseEvent(e);
}

/******************************************************************************
*  Called when the drag cursor enters the panel icon.
*/
void TrayWindow::dragEnterEvent(QDragEnterEvent* e)
{
	KAlarmMainWindow::executeDragEnterEvent(e);
}

/******************************************************************************
*  Called when an object is dropped on the panel icon.
*  If the object is recognised, the edit alarm dialog is opened appropriately.
*/
void TrayWindow::dropEvent(QDropEvent* e)
{
	KAlarmMainWindow::executeDropEvent(0, e);
}

/******************************************************************************
*  Return the tooltip text showing alarms due in the next 24 hours.
*  The limit of 24 hours is because only times, not dates, are displayed.
*/
void TrayWindow::tooltipAlarmText(QString& text) const
{
	KAEvent event;
	Preferences* preferences = Preferences::instance();
	const QString& prefix = preferences->tooltipTimeToPrefix();
	int maxCount = preferences->tooltipAlarmCount();
	QDateTime now = QDateTime::currentDateTime();

	// Get today's and tomorrow's alarms, sorted in time order
	QValueList<TipItem> items;
	QValueList<TipItem>::Iterator iit;
	KCal::Event::List events = theApp()->getCalendar().eventsWithAlarms(now.date(), now.addDays(1));
	for (KCal::Event::List::ConstIterator it = events.begin();  it != events.end();  ++it)
	{
		KCal::Event* kcalEvent = *it;
		event.set(*kcalEvent);
		if (!event.expired()  &&  event.action() == KAEvent::MESSAGE)
		{
			TipItem item;
			DateTime dateTime = event.nextDateTime();
			if (dateTime.date() > now.date())
			{
				// Ignore alarms after tomorrow at the current clock time
				if (dateTime.date() != now.date().addDays(1)
				||  dateTime.time() >= now.time())
					continue;
			}
			item.dateTime = dateTime.dateTime();

			// The alarm is due today, or early tomorrow
			bool space = false;
			if (preferences->showTooltipAlarmTime())
			{
				item.text += KGlobal::locale()->formatTime(item.dateTime.time());
				item.text += ' ';
				space = true;
			}
			if (preferences->showTooltipTimeToAlarm())
			{
				int mins = (now.secsTo(item.dateTime) + 59) / 60;
				if (mins < 0)
					mins = 0;
				char minutes[3] = "00";
				minutes[0] = (mins%60) / 10 + '0';
				minutes[1] = (mins%60) % 10 + '0';
				if (preferences->showTooltipAlarmTime())
					item.text += i18n("prefix + hours:minutes", "(%1%2:%3)").arg(prefix).arg(mins/60).arg(minutes);
				else
					item.text += i18n("prefix + hours:minutes", "%1%2:%3").arg(prefix).arg(mins/60).arg(minutes);
				item.text += ' ';
				space = true;
			}
			if (space)
				item.text += ' ';
			item.text += AlarmListViewItem::alarmText(event);

			// Insert the item into the list in time-sorted order
			for (iit = items.begin();  iit != items.end();  ++iit)
			{
				if (item.dateTime <= (*iit).dateTime)
					break;
			}
			items.insert(iit, item);
		}
        }
	kdDebug(5950) << "TrayWindow::tooltipAlarmText():\n";
	int count = 0;
	for (iit = items.begin();  iit != items.end();  ++iit)
	{
		kdDebug(5950) << "-- " << (count+1) << ") " << (*iit).text << endl;
		text += "\n";
		text += (*iit).text;
		if (++count == maxCount)
			break;
	}
}

/******************************************************************************
* Called when the associated main window is closed.
*/
void TrayWindow::removeWindow(KAlarmMainWindow* win)
{
	if (win == mAssocMainWindow)
		mAssocMainWindow = 0;
}

#ifdef HAVE_X11_HEADERS
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
#endif

/******************************************************************************
* Check whether the widget is in the system tray.
* Note that it is only sometime AFTER the show event that the system tray
* becomes the widget's parent. So for a definitive status, call this method
* only after waiting a bit...
* Reply = true if the widget is in the system tray, or its status can't be determined.
*       = false if it is not currently in the system tray.
*/
bool TrayWindow::inSystemTray() const
{
#ifdef HAVE_X11_HEADERS
	Window  xParent;    // receives parent window
	Window  root;
	Window* children = 0;
	unsigned int nchildren;
	// Find the X parent window of the widget. This is not the same as the Qt parent widget.
	if (!XQueryTree(qt_xdisplay(), winId(), &root, &xParent, &children, &nchildren))
		return true;    // error determining its parent X window
	if (children)
		XFree(children);

	// If it is in the system tray, the system tray window will be its X parent.
	// Otherwise, the root window will be its X parent.
	return xParent != root;
#else
	return true;
#endif // HAVE_X11_HEADERS
}

/******************************************************************************
*  Displays the appropriate tooltip depending on preference settings.
*/
void TrayTooltip::maybeTip(const QPoint&)
{
	TrayWindow* parent = (TrayWindow*)parentWidget();
	QString text;
	if (theApp()->daemonGuiHandler()->monitoringAlarms())
		text = kapp->aboutData()->programName();
	else
		text = i18n("%1 - disabled").arg(kapp->aboutData()->programName());
	kdDebug(5950) << "TrayTooltip::maybeTip(): " << text << endl;
	if (Preferences::instance()->tooltipAlarmCount())
		parent->tooltipAlarmText(text);
	tip(parent->rect(), text);
}
<commit_msg>Fix crash on quit in earlier versions of KDE<commit_after>/*
 *  traywindow.cpp  -  the KDE system tray applet
 *  Program:  kalarm
 *  (C) 2002 - 2004 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include "kalarm.h"
#include <stdlib.h>

#include <qtooltip.h>

#include <kapplication.h>
#include <klocale.h>
#include <kstdaction.h>
#include <kaboutdata.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kstdguiitem.h>
#include <kconfig.h>
#include <kdebug.h>

#include "kalarmapp.h"
#include "mainwindow.h"
#include "messagewin.h"
#include "alarmcalendar.h"
#include "alarmlistview.h"
#include "daemon.h"
#include "daemongui.h"
#include "preferences.h"
#include "traywindow.moc"

class TrayTooltip : public QToolTip
{
	public:
		TrayTooltip(QWidget* parent) : QToolTip(parent) { }
	protected:
		virtual void maybeTip(const QPoint&);
};

struct TipItem
{
	QDateTime  dateTime;
	QString    text;
};

/*=============================================================================
= Class: TrayWindow
= The KDE system tray window.
=============================================================================*/
const QString TrayWindow::QUIT_WARN = QString::fromLatin1("QuitWarn");

TrayWindow::TrayWindow(KAlarmMainWindow* parent, const char* name)
	: KSystemTray((theApp()->wantRunInSystemTray() ? parent : 0), name),
	  mAssocMainWindow(parent)
{
	kdDebug(5950) << "TrayWindow::TrayWindow()\n";
	// Set up GUI icons
	mPixmapEnabled  = loadIcon("kalarm");
	mPixmapDisabled = loadIcon("kalarm_disabled");
	if (mPixmapEnabled.isNull() || mPixmapDisabled.isNull())
		KMessageBox::sorry(this, i18n("Cannot load system tray icon."),
		                         i18n("KAlarm Error", "%1 Error").arg(kapp->aboutData()->programName()));
	setAcceptDrops(true);         // allow drag-and-drop onto this window

	// Replace the default handler for the Quit context menu item
	KActionCollection* actcol = actionCollection();
	actcol->remove(actcol->action(KStdAction::stdName(KStdAction::Quit)));
	actcol->insert(KStdAction::quit(this, SLOT(slotQuit()), actcol));

	// Set up the context menu
	ActionAlarmsEnabled* a = theApp()->actionAlarmEnable();
	mAlarmsEnabledId = a->itemId(a->plug(contextMenu()));
	connect(a, SIGNAL(alarmsEnabledChange(bool)), this, SLOT(setEnabledStatus(bool)));
	theApp()->actionNewAlarm()->plug(contextMenu());
	Daemon::actionControl()->plug(contextMenu());
	theApp()->actionPreferences()->plug(contextMenu());

	// Set icon to correspond with the alarms enabled menu status
	DaemonGuiHandler* daemonGui = theApp()->daemonGuiHandler();
	daemonGui->checkStatus();
	setEnabledStatus(daemonGui->monitoringAlarms());

	mTooltip = new TrayTooltip(this);
}

TrayWindow::~TrayWindow()
{
	kdDebug(5950) << "TrayWindow::~TrayWindow()\n";
	delete mTooltip;
	mTooltip = 0;
	theApp()->removeWindow(this);
	emit deleted();
}

/******************************************************************************
* Called just before the context menu is displayed.
* Update the Alarms Enabled item status.
*/
void TrayWindow::contextMenuAboutToShow(KPopupMenu* menu)
{
	KSystemTray::contextMenuAboutToShow(menu);     // needed for KDE <= 3.1 compatibility
	theApp()->daemonGuiHandler()->checkStatus();
}

/******************************************************************************
* Called when the Quit context menu item is selected.
* Closes the system tray window, and if in 'run in system tray' mode closes all
* main windows, but does not exit the program if other windows are still open.
*/
void TrayWindow::slotQuit()
{
	kdDebug(5950) << "TrayWindow::slotQuit()\n";
	if (theApp()->alarmsDisabledIfStopped()
	&&  KMessageBox::warningYesNo(this, i18n("Quitting will disable alarms\n"
	                                         "(once any alarm message windows are closed)."),
				      QString::null, KStdGuiItem::quit(), KStdGuiItem::cancel(), QUIT_WARN
	                             ) != KMessageBox::Yes)
		return;
	if (theApp()->wantRunInSystemTray())
	{
		if (!MessageWin::instanceCount())
		{
			kdDebug(5950) << "TrayWindow::slotQuit(): quitting\n";
			theApp()->quit();
			return;
		}
		KAlarmMainWindow::closeAll();
	}
	theApp()->displayTrayIcon(false);
}

/******************************************************************************
* Called when the Alarms Enabled action status has changed.
* Updates the alarms enabled menu item check state, and the icon pixmap.
*/
void TrayWindow::setEnabledStatus(bool status)
{
	kdDebug(5950) << "TrayWindow::setEnabledStatus(" << (int)status << ")\n";
	setPixmap(status ? mPixmapEnabled : mPixmapDisabled);
	contextMenu()->setItemChecked(mAlarmsEnabledId, status);
}

/******************************************************************************
*  Called when the mouse is clicked over the panel icon.
*  A left click displays the KAlarm main window.
*  A middle button click displays the New Alarm window.
*/
void TrayWindow::mousePressEvent(QMouseEvent* e)
{
	if (e->button() == LeftButton  &&  !theApp()->wantRunInSystemTray())
	{
		// Left click: display/hide the first main window
		mAssocMainWindow = KAlarmMainWindow::toggleWindow(mAssocMainWindow);
	}
	else if (e->button() == MidButton)
		KAlarmMainWindow::executeNew();    // display a New Alarm dialog
	else
		KSystemTray::mousePressEvent(e);
}

/******************************************************************************
*  Called when the mouse is released over the panel icon.
*  The main window (if not hidden) is raised and made the active window.
*  If this is done in mousePressEvent(), it doesn't work.
*/
void TrayWindow::mouseReleaseEvent(QMouseEvent* e)
{
	if (e->button() == LeftButton  &&  mAssocMainWindow  &&  mAssocMainWindow->isVisible())
	{
		mAssocMainWindow->raise();
		mAssocMainWindow->setActiveWindow();
	}
	else
		KSystemTray::mouseReleaseEvent(e);
}

/******************************************************************************
*  Called when the drag cursor enters the panel icon.
*/
void TrayWindow::dragEnterEvent(QDragEnterEvent* e)
{
	KAlarmMainWindow::executeDragEnterEvent(e);
}

/******************************************************************************
*  Called when an object is dropped on the panel icon.
*  If the object is recognised, the edit alarm dialog is opened appropriately.
*/
void TrayWindow::dropEvent(QDropEvent* e)
{
	KAlarmMainWindow::executeDropEvent(0, e);
}

/******************************************************************************
*  Return the tooltip text showing alarms due in the next 24 hours.
*  The limit of 24 hours is because only times, not dates, are displayed.
*/
void TrayWindow::tooltipAlarmText(QString& text) const
{
	KAEvent event;
	Preferences* preferences = Preferences::instance();
	const QString& prefix = preferences->tooltipTimeToPrefix();
	int maxCount = preferences->tooltipAlarmCount();
	QDateTime now = QDateTime::currentDateTime();

	// Get today's and tomorrow's alarms, sorted in time order
	QValueList<TipItem> items;
	QValueList<TipItem>::Iterator iit;
	KCal::Event::List events = theApp()->getCalendar().eventsWithAlarms(now.date(), now.addDays(1));
	for (KCal::Event::List::ConstIterator it = events.begin();  it != events.end();  ++it)
	{
		KCal::Event* kcalEvent = *it;
		event.set(*kcalEvent);
		if (!event.expired()  &&  event.action() == KAEvent::MESSAGE)
		{
			TipItem item;
			DateTime dateTime = event.nextDateTime();
			if (dateTime.date() > now.date())
			{
				// Ignore alarms after tomorrow at the current clock time
				if (dateTime.date() != now.date().addDays(1)
				||  dateTime.time() >= now.time())
					continue;
			}
			item.dateTime = dateTime.dateTime();

			// The alarm is due today, or early tomorrow
			bool space = false;
			if (preferences->showTooltipAlarmTime())
			{
				item.text += KGlobal::locale()->formatTime(item.dateTime.time());
				item.text += ' ';
				space = true;
			}
			if (preferences->showTooltipTimeToAlarm())
			{
				int mins = (now.secsTo(item.dateTime) + 59) / 60;
				if (mins < 0)
					mins = 0;
				char minutes[3] = "00";
				minutes[0] = (mins%60) / 10 + '0';
				minutes[1] = (mins%60) % 10 + '0';
				if (preferences->showTooltipAlarmTime())
					item.text += i18n("prefix + hours:minutes", "(%1%2:%3)").arg(prefix).arg(mins/60).arg(minutes);
				else
					item.text += i18n("prefix + hours:minutes", "%1%2:%3").arg(prefix).arg(mins/60).arg(minutes);
				item.text += ' ';
				space = true;
			}
			if (space)
				item.text += ' ';
			item.text += AlarmListViewItem::alarmText(event);

			// Insert the item into the list in time-sorted order
			for (iit = items.begin();  iit != items.end();  ++iit)
			{
				if (item.dateTime <= (*iit).dateTime)
					break;
			}
			items.insert(iit, item);
		}
        }
	kdDebug(5950) << "TrayWindow::tooltipAlarmText():\n";
	int count = 0;
	for (iit = items.begin();  iit != items.end();  ++iit)
	{
		kdDebug(5950) << "-- " << (count+1) << ") " << (*iit).text << endl;
		text += "\n";
		text += (*iit).text;
		if (++count == maxCount)
			break;
	}
}

/******************************************************************************
* Called when the associated main window is closed.
*/
void TrayWindow::removeWindow(KAlarmMainWindow* win)
{
	if (win == mAssocMainWindow)
		mAssocMainWindow = 0;
}

#ifdef HAVE_X11_HEADERS
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
#endif

/******************************************************************************
* Check whether the widget is in the system tray.
* Note that it is only sometime AFTER the show event that the system tray
* becomes the widget's parent. So for a definitive status, call this method
* only after waiting a bit...
* Reply = true if the widget is in the system tray, or its status can't be determined.
*       = false if it is not currently in the system tray.
*/
bool TrayWindow::inSystemTray() const
{
#ifdef HAVE_X11_HEADERS
	Window  xParent;    // receives parent window
	Window  root;
	Window* children = 0;
	unsigned int nchildren;
	// Find the X parent window of the widget. This is not the same as the Qt parent widget.
	if (!XQueryTree(qt_xdisplay(), winId(), &root, &xParent, &children, &nchildren))
		return true;    // error determining its parent X window
	if (children)
		XFree(children);

	// If it is in the system tray, the system tray window will be its X parent.
	// Otherwise, the root window will be its X parent.
	return xParent != root;
#else
	return true;
#endif // HAVE_X11_HEADERS
}

/******************************************************************************
*  Displays the appropriate tooltip depending on preference settings.
*/
void TrayTooltip::maybeTip(const QPoint&)
{
	TrayWindow* parent = (TrayWindow*)parentWidget();
	QString text;
	if (theApp()->daemonGuiHandler()->monitoringAlarms())
		text = kapp->aboutData()->programName();
	else
		text = i18n("%1 - disabled").arg(kapp->aboutData()->programName());
	kdDebug(5950) << "TrayTooltip::maybeTip(): " << text << endl;
	if (Preferences::instance()->tooltipAlarmCount())
		parent->tooltipAlarmText(text);
	tip(parent->rect(), text);
}
<|endoftext|>