<commit_before>/*************************************************************************
 *
 *  $RCSfile: officeinstallationdirectories.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-05 10:36:13 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Kai Sommerfeld ( kso@sun.com )
 *
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/

#include "osl/file.hxx"
#include "com/sun/star/beans/XPropertySet.hpp"
#include "com/sun/star/util/XMacroExpander.hpp"

#include "officeinstallationdirectories.hxx"

using namespace com::sun::star;

using namespace comphelper;

//=========================================================================
// helpers
//=========================================================================

uno::Sequence< rtl::OUString > SAL_CALL
OfficeInstallationDirectories_getSupportedServiceNames()
    throw()
{
    const rtl::OUString aServiceName(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.util.OfficeInstallationDirectories" ) );
    return uno::Sequence< rtl::OUString >( &aServiceName, 1 );
}

//=========================================================================
rtl::OUString SAL_CALL OfficeInstallationDirectories_getImplementationName()
    throw()
{
    return rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.comp.util.OfficeInstallationDirectories" ) );
}

//=========================================================================
rtl::OUString SAL_CALL OfficeInstallationDirectories_getSingletonName()
    throw()
{
    return rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.util.theOfficeInstallationDirectories" ) );
}

//=========================================================================
rtl::OUString SAL_CALL OfficeInstallationDirectories_getSingletonServiceName()
    throw()
{
    return rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.util.OfficeInstallationDirectories" ) );
}

//=========================================================================
uno::Reference< uno::XInterface > SAL_CALL
OfficeInstallationDirectories_createInstance(
        const uno::Reference< lang::XMultiServiceFactory > & xSMgr )
    throw( uno::Exception )
{
    OSL_ENSURE( xSMgr.is(), "No service manager!" );

    uno::Reference< uno::XComponentContext > xCtx;
    uno::Reference< beans::XPropertySet > xPropSet( xSMgr, uno::UNO_QUERY );
    if ( xPropSet.is() )
    {
        xPropSet->getPropertyValue(
            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
        >>= xCtx;
    }

    if ( !xCtx.is() )
    {
        throw uno::RuntimeException(
            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                "Unable to obtain component context from service manager!" ) ),
            uno::Reference< uno::XInterface >() );
    }

    return static_cast< cppu::OWeakObject * >(
        new OfficeInstallationDirectories( xCtx ) );
}

//=========================================================================
static bool makeCanonicalFileURL( rtl::OUString & rURL )
{
    OSL_ENSURE( rURL.matchAsciiL( "file:", sizeof( "file:" ) - 1 , 0 ) ,
                "File URL expected!" );

    rtl::OUString aNormalizedURL;
    if ( osl::FileBase::getAbsoluteFileURL( rtl::OUString(),
                                            rURL,
                                            aNormalizedURL )
            == osl::DirectoryItem::E_None )
    {
        osl::DirectoryItem aDirItem;
        if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem )
                == osl::DirectoryItem::E_None )
        {
            osl::FileStatus aFileStatus( FileStatusMask_FileURL );

            if ( aDirItem.getFileStatus( aFileStatus )
                    == osl::DirectoryItem::E_None )
            {
                aNormalizedURL = aFileStatus.getFileURL();

                if ( aNormalizedURL.getLength() > 0 )
                {
                    if ( aNormalizedURL
                            .getStr()[ aNormalizedURL.getLength() - 1 ]
                                != sal_Unicode( '/' ) )
                        rURL = aNormalizedURL;
                    else
                        rURL = aNormalizedURL
                                .copy( 0, aNormalizedURL.getLength() - 1 );

                    return true;
                }
            }
        }
    }
    return false;
}

//=========================================================================
//=========================================================================
//
// OfficeInstallationDirectories Implementation.
//
//=========================================================================
//=========================================================================

OfficeInstallationDirectories::OfficeInstallationDirectories(
        const uno::Reference< uno::XComponentContext > & xCtx )
: m_aOfficeDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(baseinsturl)" ) ),
  m_aUserDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(userdataurl)" ) ),
  m_xCtx( xCtx ),
  m_pOfficeDir( 0 ),
  m_pUserDir( 0 )
{
}

//=========================================================================
// virtual
OfficeInstallationDirectories::~OfficeInstallationDirectories()
{
}

//=========================================================================
// util::XOfficeInstallationDirectories
//=========================================================================

// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::getOfficeInstallationDirectoryURL()
    throw ( uno::RuntimeException )
{
    // late init m_pOfficeDir and m_pUserDir
    initDirs();
    return rtl::OUString( *m_pOfficeDir );
}

//=========================================================================
// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::getOfficeUserDataDirectoryURL()
    throw ( uno::RuntimeException )
{
    // late init m_pOfficeDir and m_pUserDir
    initDirs();
    return rtl::OUString( *m_pUserDir );
}

//=========================================================================
// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::makeRelocatableURL( const rtl::OUString& URL )
    throw ( uno::RuntimeException )
{
    if ( URL.getLength() > 0 )
    {
        // late init m_pOfficeDir and m_pUserDir
        initDirs();

        rtl::OUString aCanonicalURL( URL );
        makeCanonicalFileURL( aCanonicalURL );

        sal_Int32 nIndex = aCanonicalURL.indexOf( *m_pOfficeDir );
        if ( nIndex  != -1 )
        {
            return rtl::OUString(
                URL.replaceAt( nIndex,
                               m_pOfficeDir->getLength(),
                               m_aOfficeDirMacro ) );
        }
        else
        {
            sal_Int32 nIndex = aCanonicalURL.indexOf( *m_pUserDir );
            if ( nIndex  != -1 )
            {
                return rtl::OUString(
                    URL.replaceAt( nIndex,
                                   m_pUserDir->getLength(),
                                   m_aUserDirMacro ) );
            }
        }
    }
    return rtl::OUString( URL );
}

//=========================================================================
// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::makeAbsoluteURL( const rtl::OUString& URL )
    throw ( uno::RuntimeException )
{
    if ( URL.getLength() > 0 )
    {
        sal_Int32 nIndex = URL.indexOf( m_aOfficeDirMacro );
        if ( nIndex != -1 )
        {
            // late init m_pOfficeDir and m_pUserDir
            initDirs();

            return rtl::OUString(
                URL.replaceAt( nIndex,
                               m_aOfficeDirMacro.getLength(),
                               *m_pOfficeDir ) );
        }
        else
        {
            sal_Int32 nIndex = URL.indexOf( m_aUserDirMacro );
            if ( nIndex != -1 )
            {
                // late init m_pOfficeDir and m_pUserDir
                initDirs();

                return rtl::OUString(
                    URL.replaceAt( nIndex,
                                   m_aUserDirMacro.getLength(),
                                   *m_pUserDir ) );
            }
        }
    }
    return rtl::OUString( URL );
}

//=========================================================================
// lang::XServiceInfo
//=========================================================================

// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::getImplementationName()
    throw ( uno::RuntimeException )
{
    return OfficeInstallationDirectories_getImplementationName();
}

//=========================================================================
// virtual
sal_Bool SAL_CALL
OfficeInstallationDirectories::supportsService( const rtl::OUString& ServiceName )
    throw ( uno::RuntimeException )
{
    const uno::Sequence< rtl::OUString > & aNames
        = OfficeInstallationDirectories_getSupportedServiceNames();
    const rtl::OUString * p = aNames.getConstArray();
    for ( sal_Int32 nPos = 0; nPos < aNames.getLength(); nPos++ )
    {
        if ( p[ nPos ].equals( ServiceName ) )
            return sal_True;
    }
    return sal_False;

}

//=========================================================================
// virtual
uno::Sequence< ::rtl::OUString > SAL_CALL
OfficeInstallationDirectories::getSupportedServiceNames()
    throw ( uno::RuntimeException )
{
    return OfficeInstallationDirectories_getSupportedServiceNames();
}

//=========================================================================
// non-UNO
//=========================================================================

void OfficeInstallationDirectories::initDirs()
{
    if ( m_pOfficeDir == 0 )
    {
        osl::MutexGuard aGuard( m_aMutex );
        if ( m_pOfficeDir == 0 )
        {
            m_pOfficeDir = new rtl::OUString;
            m_pUserDir   = new rtl::OUString;

            uno::Reference< util::XMacroExpander > xExpander;

            m_xCtx->getValueByName(
                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                    "/singletons/com.sun.star.util.theMacroExpander" ) ) )
            >>= xExpander;

            OSL_ENSURE( xExpander.is(),
                        "Unable to obtain macro expander singleton!" );

            if ( xExpander.is() )
            {
                *m_pOfficeDir =
                    xExpander->expandMacros(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "${$SYSBINDIR/" SAL_CONFIGFILE( "bootstrap" ) ":BaseInstallation}" ) ) );

                OSL_ENSURE( m_pOfficeDir->getLength() > 0,
                        "Unable to obtain office installation directory!" );

                makeCanonicalFileURL( *m_pOfficeDir );

                *m_pUserDir =
                    xExpander->expandMacros(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "${$SYSBINDIR/" SAL_CONFIGFILE( "bootstrap" ) ":UserInstallation}" ) ) );

                OSL_ENSURE( m_pUserDir->getLength() > 0,
                        "Unable to obtain office user data directory!" );

                makeCanonicalFileURL( *m_pUserDir );
            }
        }
    }
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.3.134); FILE MERGED 2005/09/05 15:24:05 rt 1.3.134.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: officeinstallationdirectories.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 02:54:13 $
 *
 *  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
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/

#include "osl/file.hxx"
#include "com/sun/star/beans/XPropertySet.hpp"
#include "com/sun/star/util/XMacroExpander.hpp"

#include "officeinstallationdirectories.hxx"

using namespace com::sun::star;

using namespace comphelper;

//=========================================================================
// helpers
//=========================================================================

uno::Sequence< rtl::OUString > SAL_CALL
OfficeInstallationDirectories_getSupportedServiceNames()
    throw()
{
    const rtl::OUString aServiceName(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.util.OfficeInstallationDirectories" ) );
    return uno::Sequence< rtl::OUString >( &aServiceName, 1 );
}

//=========================================================================
rtl::OUString SAL_CALL OfficeInstallationDirectories_getImplementationName()
    throw()
{
    return rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.comp.util.OfficeInstallationDirectories" ) );
}

//=========================================================================
rtl::OUString SAL_CALL OfficeInstallationDirectories_getSingletonName()
    throw()
{
    return rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.util.theOfficeInstallationDirectories" ) );
}

//=========================================================================
rtl::OUString SAL_CALL OfficeInstallationDirectories_getSingletonServiceName()
    throw()
{
    return rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.util.OfficeInstallationDirectories" ) );
}

//=========================================================================
uno::Reference< uno::XInterface > SAL_CALL
OfficeInstallationDirectories_createInstance(
        const uno::Reference< lang::XMultiServiceFactory > & xSMgr )
    throw( uno::Exception )
{
    OSL_ENSURE( xSMgr.is(), "No service manager!" );

    uno::Reference< uno::XComponentContext > xCtx;
    uno::Reference< beans::XPropertySet > xPropSet( xSMgr, uno::UNO_QUERY );
    if ( xPropSet.is() )
    {
        xPropSet->getPropertyValue(
            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
        >>= xCtx;
    }

    if ( !xCtx.is() )
    {
        throw uno::RuntimeException(
            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                "Unable to obtain component context from service manager!" ) ),
            uno::Reference< uno::XInterface >() );
    }

    return static_cast< cppu::OWeakObject * >(
        new OfficeInstallationDirectories( xCtx ) );
}

//=========================================================================
static bool makeCanonicalFileURL( rtl::OUString & rURL )
{
    OSL_ENSURE( rURL.matchAsciiL( "file:", sizeof( "file:" ) - 1 , 0 ) ,
                "File URL expected!" );

    rtl::OUString aNormalizedURL;
    if ( osl::FileBase::getAbsoluteFileURL( rtl::OUString(),
                                            rURL,
                                            aNormalizedURL )
            == osl::DirectoryItem::E_None )
    {
        osl::DirectoryItem aDirItem;
        if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem )
                == osl::DirectoryItem::E_None )
        {
            osl::FileStatus aFileStatus( FileStatusMask_FileURL );

            if ( aDirItem.getFileStatus( aFileStatus )
                    == osl::DirectoryItem::E_None )
            {
                aNormalizedURL = aFileStatus.getFileURL();

                if ( aNormalizedURL.getLength() > 0 )
                {
                    if ( aNormalizedURL
                            .getStr()[ aNormalizedURL.getLength() - 1 ]
                                != sal_Unicode( '/' ) )
                        rURL = aNormalizedURL;
                    else
                        rURL = aNormalizedURL
                                .copy( 0, aNormalizedURL.getLength() - 1 );

                    return true;
                }
            }
        }
    }
    return false;
}

//=========================================================================
//=========================================================================
//
// OfficeInstallationDirectories Implementation.
//
//=========================================================================
//=========================================================================

OfficeInstallationDirectories::OfficeInstallationDirectories(
        const uno::Reference< uno::XComponentContext > & xCtx )
: m_aOfficeDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(baseinsturl)" ) ),
  m_aUserDirMacro( RTL_CONSTASCII_USTRINGPARAM( "$(userdataurl)" ) ),
  m_xCtx( xCtx ),
  m_pOfficeDir( 0 ),
  m_pUserDir( 0 )
{
}

//=========================================================================
// virtual
OfficeInstallationDirectories::~OfficeInstallationDirectories()
{
}

//=========================================================================
// util::XOfficeInstallationDirectories
//=========================================================================

// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::getOfficeInstallationDirectoryURL()
    throw ( uno::RuntimeException )
{
    // late init m_pOfficeDir and m_pUserDir
    initDirs();
    return rtl::OUString( *m_pOfficeDir );
}

//=========================================================================
// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::getOfficeUserDataDirectoryURL()
    throw ( uno::RuntimeException )
{
    // late init m_pOfficeDir and m_pUserDir
    initDirs();
    return rtl::OUString( *m_pUserDir );
}

//=========================================================================
// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::makeRelocatableURL( const rtl::OUString& URL )
    throw ( uno::RuntimeException )
{
    if ( URL.getLength() > 0 )
    {
        // late init m_pOfficeDir and m_pUserDir
        initDirs();

        rtl::OUString aCanonicalURL( URL );
        makeCanonicalFileURL( aCanonicalURL );

        sal_Int32 nIndex = aCanonicalURL.indexOf( *m_pOfficeDir );
        if ( nIndex  != -1 )
        {
            return rtl::OUString(
                URL.replaceAt( nIndex,
                               m_pOfficeDir->getLength(),
                               m_aOfficeDirMacro ) );
        }
        else
        {
            sal_Int32 nIndex = aCanonicalURL.indexOf( *m_pUserDir );
            if ( nIndex  != -1 )
            {
                return rtl::OUString(
                    URL.replaceAt( nIndex,
                                   m_pUserDir->getLength(),
                                   m_aUserDirMacro ) );
            }
        }
    }
    return rtl::OUString( URL );
}

//=========================================================================
// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::makeAbsoluteURL( const rtl::OUString& URL )
    throw ( uno::RuntimeException )
{
    if ( URL.getLength() > 0 )
    {
        sal_Int32 nIndex = URL.indexOf( m_aOfficeDirMacro );
        if ( nIndex != -1 )
        {
            // late init m_pOfficeDir and m_pUserDir
            initDirs();

            return rtl::OUString(
                URL.replaceAt( nIndex,
                               m_aOfficeDirMacro.getLength(),
                               *m_pOfficeDir ) );
        }
        else
        {
            sal_Int32 nIndex = URL.indexOf( m_aUserDirMacro );
            if ( nIndex != -1 )
            {
                // late init m_pOfficeDir and m_pUserDir
                initDirs();

                return rtl::OUString(
                    URL.replaceAt( nIndex,
                                   m_aUserDirMacro.getLength(),
                                   *m_pUserDir ) );
            }
        }
    }
    return rtl::OUString( URL );
}

//=========================================================================
// lang::XServiceInfo
//=========================================================================

// virtual
rtl::OUString SAL_CALL
OfficeInstallationDirectories::getImplementationName()
    throw ( uno::RuntimeException )
{
    return OfficeInstallationDirectories_getImplementationName();
}

//=========================================================================
// virtual
sal_Bool SAL_CALL
OfficeInstallationDirectories::supportsService( const rtl::OUString& ServiceName )
    throw ( uno::RuntimeException )
{
    const uno::Sequence< rtl::OUString > & aNames
        = OfficeInstallationDirectories_getSupportedServiceNames();
    const rtl::OUString * p = aNames.getConstArray();
    for ( sal_Int32 nPos = 0; nPos < aNames.getLength(); nPos++ )
    {
        if ( p[ nPos ].equals( ServiceName ) )
            return sal_True;
    }
    return sal_False;

}

//=========================================================================
// virtual
uno::Sequence< ::rtl::OUString > SAL_CALL
OfficeInstallationDirectories::getSupportedServiceNames()
    throw ( uno::RuntimeException )
{
    return OfficeInstallationDirectories_getSupportedServiceNames();
}

//=========================================================================
// non-UNO
//=========================================================================

void OfficeInstallationDirectories::initDirs()
{
    if ( m_pOfficeDir == 0 )
    {
        osl::MutexGuard aGuard( m_aMutex );
        if ( m_pOfficeDir == 0 )
        {
            m_pOfficeDir = new rtl::OUString;
            m_pUserDir   = new rtl::OUString;

            uno::Reference< util::XMacroExpander > xExpander;

            m_xCtx->getValueByName(
                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                    "/singletons/com.sun.star.util.theMacroExpander" ) ) )
            >>= xExpander;

            OSL_ENSURE( xExpander.is(),
                        "Unable to obtain macro expander singleton!" );

            if ( xExpander.is() )
            {
                *m_pOfficeDir =
                    xExpander->expandMacros(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "${$SYSBINDIR/" SAL_CONFIGFILE( "bootstrap" ) ":BaseInstallation}" ) ) );

                OSL_ENSURE( m_pOfficeDir->getLength() > 0,
                        "Unable to obtain office installation directory!" );

                makeCanonicalFileURL( *m_pOfficeDir );

                *m_pUserDir =
                    xExpander->expandMacros(
                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "${$SYSBINDIR/" SAL_CONFIGFILE( "bootstrap" ) ":UserInstallation}" ) ) );

                OSL_ENSURE( m_pUserDir->getLength() > 0,
                        "Unable to obtain office user data directory!" );

                makeCanonicalFileURL( *m_pUserDir );
            }
        }
    }
}

<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.net/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * HproseClient.hpp                                       *
 *                                                        *
 * hprose client class for Cpp.                           *
 *                                                        *
 * LastModified: Jul 7, 2015                              *
 * Author: Chen fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

#ifndef HPROSE_CLIENT_HPROSE_CLIENT_HPP
#define HPROSE_CLIENT_HPROSE_CLIENT_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <hprose/io.hpp>
#include <boost/thread.hpp>

namespace hprose {

namespace HproseTags {

const char ResultTags[4] = { TagResult, TagArgument, TagError, TagEnd }; // Todo: Remove

} // namespace HproseTags

class HproseClient {
protected: // structors

    HproseClient() {
    }

    HproseClient(const std::string & uri) {
        UseService(uri);
    }

    virtual ~HproseClient() {
    }

protected:

    virtual void * GetInvokeContext() = 0;

    virtual void SendData(void * context) = 0;

    virtual void EndInvoke(void * context) = 0;

    virtual std::ostream & GetOutputStream(void * context) = 0;

    virtual std::istream & GetInputStream(void * context) = 0;

public:

    virtual void UseService(const std::string & uri) {
        this->uri = uri;
    }

    template<typename ReturnType>
    inline ReturnType Invoke(const std::string & name) {
        std::vector<Any> args;
        return Invoke<ReturnType>(name, args);
    }

    template<typename ReturnType>
    inline void Invoke(ReturnType & ret, const std::string & name) {
        std::vector<Any> args;
        Invoke(ret, name, args);
    }

#ifndef BOOST_NO_INITIALIZER_LISTS
    template<typename ReturnType, typename ArgType>
    inline ReturnType Invoke(const std::string & name, const std::initializer_list<ArgType> & args) {
        return Invoke<ReturnType>(name, args, false);
    }

    template<typename ReturnType, typename ArgType>
    inline void Invoke(ReturnType & ret, const std::string & name, const std::initializer_list<ArgType> & args) {
        Invoke(ret, name, args, false);
    }
#endif

    template<typename ReturnType, typename ArgsType>
    inline ReturnType Invoke(const std::string & name, ArgsType & args, bool ref = false) {
        ReturnType ret = ReturnType();
        Invoke(ret, name, args, ref);
        return ret;
    }

    template<typename ReturnType, typename ArgsType>
    void Invoke(ReturnType & ret, const std::string & name, ArgsType & args, bool ref = false) {
        std::string error;
        void * context = 0;
        context = GetInvokeContext();
        try {
            DoOutput(name, args, ref, GetOutputStream(context));
            SendData(context);
            DoInput(ret, args, error, GetInputStream(context));
        }
        catch (...) {
        }
        EndInvoke(context);
        if (!error.empty()) {
            HPROSE_THROW_EXCEPTION(error);
        }
    }

    template<typename ReturnType, typename Functor>
    inline void AsyncInvoke(const std::string & name, Functor func) {
        static std::vector<Any> args;
        AsyncInvoke<ReturnType>(name, args, func, false);
    }

    template<typename ReturnType, typename ArgsType, typename Functor>
    inline void AsyncInvoke(const std::string & name, const ArgsType & args, Functor func, bool ref = false) {
        boost::thread thread(Async<ReturnType, ArgsType, Functor>(*this, name, args, func, ref));
    }

    template<typename ReturnType, typename ArgsType, typename Functor, size_t ArraySize>
    inline void AsyncInvoke(const std::string & name, const ArgsType (&args)[ArraySize], Functor func, bool ref = false) {
        std::vector<ArgsType> newArgs(ArraySize);
        for (int i = 0; i < ArraySize; ++i) {
            newArgs[i] = args[i];
        }
        AsyncInvoke<ReturnType>(name, newArgs, func, ref);
    }

private:

    template<typename ReturnType, typename ArgsType, typename Functor>
    class Async {
    public:

        Async(HproseClient & client, const std::string & name, ArgsType args, Functor func, bool ref)
            : client(client), name(name), args(args), func(func), ref(ref) {
        }

    public:

        inline void operator()() {
            ReturnType ret = ReturnType();
            client.Invoke(ret, name, args, ref);
            func(ret, args);
        }

    private:

        HproseClient & client;
        std::string name;
        ArgsType args;
        Functor func;
        bool ref;

    }; // class Async

private:

    template<typename ReturnType, typename ArgsType>
    void DoInput(ReturnType & ret, ArgsType & args, std::string & error, std::istream & stream) {
        HproseReader reader(stream);
        while (true) {
            switch (reader.CheckTags(HproseTags::ResultTags)) {
                case HproseTags::TagResult:
                    ret = reader.Unserialize<ReturnType>();
                    break;
                case HproseTags::TagArgument:
                    //args = reader.ReadList<ArgsType>();
                    break;
                case HproseTags::TagError:
                    error = reader.ReadString();
                    return;
                case HproseTags::TagEnd:
                    return;
            }
        }
    }

    template<typename ArgsType>
    void DoOutput(const std::string & name, ArgsType & args, bool ref, std::ostream & stream) {
        HproseWriter writer(stream);
        stream << HproseTags::TagCall;
        writer.WriteString(name, false);
        writer.WriteList(args, false);
        if (ref) {
            writer.WriteBool(true);
        }
        stream << HproseTags::TagEnd;
    }

    template<typename ArgsType, size_t ArraySize>
    void DoOutput(const std::string & name, ArgsType (&args)[ArraySize], bool ref, std::ostream & stream) {
        HproseWriter writer(stream);
        stream << HproseTags::TagCall;
        writer.WriteString(name, false);
        writer.WriteList(args, false);
        if (ref) {
            writer.WriteBool(true);
        }
        stream << HproseTags::TagEnd;
    }

protected:

    std::string uri;

}; // class HproseClient

} // namespace hprose

#endif // HPROSE_CLIENT_HPROSE_CLIENT_HPP
<commit_msg>Omit argument list if empty<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.net/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * HproseClient.hpp                                       *
 *                                                        *
 * hprose client class for Cpp.                           *
 *                                                        *
 * LastModified: Jul 7, 2015                              *
 * Author: Chen fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

#ifndef HPROSE_CLIENT_HPROSE_CLIENT_HPP
#define HPROSE_CLIENT_HPROSE_CLIENT_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <hprose/io.hpp>
#include <boost/thread.hpp>

namespace hprose {

namespace HproseTags {

const char ResultTags[4] = { TagResult, TagArgument, TagError, TagEnd }; // Todo: Remove

} // namespace HproseTags

class HproseClient {
protected: // structors

    HproseClient() {
    }

    HproseClient(const std::string & uri) {
        UseService(uri);
    }

    virtual ~HproseClient() {
    }

protected:

    virtual void * GetInvokeContext() = 0;

    virtual void SendData(void * context) = 0;

    virtual void EndInvoke(void * context) = 0;

    virtual std::ostream & GetOutputStream(void * context) = 0;

    virtual std::istream & GetInputStream(void * context) = 0;

public:

    virtual void UseService(const std::string & uri) {
        this->uri = uri;
    }

    template<typename ReturnType>
    inline ReturnType Invoke(const std::string & name) {
        std::vector<Any> args;
        return Invoke<ReturnType>(name, args);
    }

    template<typename ReturnType>
    inline void Invoke(ReturnType & ret, const std::string & name) {
        std::vector<Any> args;
        Invoke(ret, name, args);
    }

#ifndef BOOST_NO_INITIALIZER_LISTS
    template<typename ReturnType, typename ArgType>
    inline ReturnType Invoke(const std::string & name, const std::initializer_list<ArgType> & args) {
        return Invoke<ReturnType>(name, args, false);
    }

    template<typename ReturnType, typename ArgType>
    inline void Invoke(ReturnType & ret, const std::string & name, const std::initializer_list<ArgType> & args) {
        Invoke(ret, name, args, false);
    }
#endif

    template<typename ReturnType, typename ArgsType>
    inline ReturnType Invoke(const std::string & name, ArgsType & args, bool ref = false) {
        ReturnType ret = ReturnType();
        Invoke(ret, name, args, ref);
        return ret;
    }

    template<typename ReturnType, typename ArgsType>
    void Invoke(ReturnType & ret, const std::string & name, ArgsType & args, bool ref = false) {
        std::string error;
        void * context = 0;
        context = GetInvokeContext();
        try {
            DoOutput(name, args, ref, GetOutputStream(context));
            SendData(context);
            DoInput(ret, args, error, GetInputStream(context));
        }
        catch (...) {
        }
        EndInvoke(context);
        if (!error.empty()) {
            HPROSE_THROW_EXCEPTION(error);
        }
    }

    template<typename ReturnType, typename Functor>
    inline void AsyncInvoke(const std::string & name, Functor func) {
        static std::vector<Any> args;
        AsyncInvoke<ReturnType>(name, args, func, false);
    }

    template<typename ReturnType, typename ArgsType, typename Functor>
    inline void AsyncInvoke(const std::string & name, const ArgsType & args, Functor func, bool ref = false) {
        boost::thread thread(Async<ReturnType, ArgsType, Functor>(*this, name, args, func, ref));
    }

    template<typename ReturnType, typename ArgsType, typename Functor, size_t ArraySize>
    inline void AsyncInvoke(const std::string & name, const ArgsType (&args)[ArraySize], Functor func, bool ref = false) {
        std::vector<ArgsType> newArgs(ArraySize);
        for (int i = 0; i < ArraySize; ++i) {
            newArgs[i] = args[i];
        }
        AsyncInvoke<ReturnType>(name, newArgs, func, ref);
    }

private:

    template<typename ReturnType, typename ArgsType, typename Functor>
    class Async {
    public:

        Async(HproseClient & client, const std::string & name, ArgsType args, Functor func, bool ref)
            : client(client), name(name), args(args), func(func), ref(ref) {
        }

    public:

        inline void operator()() {
            ReturnType ret = ReturnType();
            client.Invoke(ret, name, args, ref);
            func(ret, args);
        }

    private:

        HproseClient & client;
        std::string name;
        ArgsType args;
        Functor func;
        bool ref;

    }; // class Async

private:

    template<typename ReturnType, typename ArgsType>
    void DoInput(ReturnType & ret, ArgsType & args, std::string & error, std::istream & stream) {
        HproseReader reader(stream);
        while (true) {
            switch (reader.CheckTags(HproseTags::ResultTags)) {
                case HproseTags::TagResult:
                    ret = reader.Unserialize<ReturnType>();
                    break;
                case HproseTags::TagArgument:
                    //args = reader.ReadList<ArgsType>();
                    break;
                case HproseTags::TagError:
                    error = reader.ReadString();
                    return;
                case HproseTags::TagEnd:
                    return;
            }
        }
    }

    template<typename ArgsType>
    void DoOutput(const std::string & name, ArgsType & args, bool ref, std::ostream & stream) {
        HproseWriter writer(stream);
        stream << HproseTags::TagCall;
        writer.WriteString(name, false);
        if (!args.empty()) {
            writer.WriteList(args, false);
        }
        if (ref) {
            writer.WriteBool(true);
        }
        stream << HproseTags::TagEnd;
    }

    template<typename ArgsType, size_t ArraySize>
    void DoOutput(const std::string & name, ArgsType (&args)[ArraySize], bool ref, std::ostream & stream) {
        HproseWriter writer(stream);
        stream << HproseTags::TagCall;
        writer.WriteString(name, false);
        if (!args.empty()) {
            writer.WriteList(args, false);
        }
        if (ref) {
            writer.WriteBool(true);
        }
        stream << HproseTags::TagEnd;
    }

protected:

    std::string uri;

}; // class HproseClient

} // namespace hprose

#endif // HPROSE_CLIENT_HPROSE_CLIENT_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2011 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "ui/tracker/main.h"
#include "ui/tracker/tracker.h"
#include "ui/tracker/scene.h"

#include "libmv/tools/tool.h"

#include <QApplication>
#include <QFileDialog>
#include <QFormLayout>
#include <QDockWidget>
#include <QToolButton>
#include <QSettings>
#include <QToolBar>
#include <QAction>
#include <QCache>
#include <QMenu>
#include <QTime>

void Clip::Open(QString path) {
  cache_.setMaxCost(64 * 1024 * 1024);
  if (path.endsWith(".avi")) {
    // TODO(MatthiasF): load videos using ffmpeg
    return;
  }

  clear();
  foreach (QString file, QDir(path).entryList(QStringList("*.jpg") << "*.png",
                                              QDir::Files, QDir::Name)) {
    append( QDir(path).filePath(file) );
  }
}

QImage Clip::Image(int frame) {
  QImage* image = cache_[frame];
  if (!image) {
    image = new QImage(value(frame));
    cache_.insert(frame, image, image->byteCount());
  }
  return *image;
}

MainWindow::MainWindow()
  : clip_(new Clip(this)),
    scene_(new Scene()),
    tracker_(new Tracker(scene_,scene_)),
    current_frame_(-1) {
  setWindowTitle("Tracker");
  setCentralWidget(tracker_);
  connect(tracker_, SIGNAL(trackChanged(QVector<int>)), this, SLOT(updateZooms(QVector<int>)));

  QToolBar* toolbar = addToolBar("Main Toolbar");
  toolbar->setObjectName("mainToolbar");

  toolbar->addAction(QIcon(":/open"), "Open a new sequence...",
                     this, SLOT(open()));

  QAction* tracker_action_ = toolbar->addAction(QIcon(":/view-image"),"Tracker View");
  tracker_action_->setCheckable(true);
  connect(tracker_action_,SIGNAL(triggered(bool)),tracker_,SLOT(setVisible(bool)));

  QAction* zoom_action_ = toolbar->addAction(QIcon(":/view-zoom"),"Zoom View");
  zoom_action_->setCheckable(true);
  connect(zoom_action_,SIGNAL(triggered(bool)),this,SLOT(toggleZoom(bool)));

  QDockWidget* scene_dock = new QDockWidget("Scene View");
  scene_dock->setObjectName("sceneDock");
  addDockWidget(Qt::BottomDockWidgetArea, scene_dock);
  scene_dock->setWidget(scene_);
  scene_dock->toggleViewAction()->setIcon(QIcon(":/view-scene"));
  toolbar->addAction(scene_dock->toggleViewAction());
  connect(scene_, SIGNAL(imageChanged(int)), SLOT(seek(int)));
  connect(scene_, SIGNAL(trackChanged(QVector<int>)), tracker_, SLOT(select(QVector<int>)));

  toolbar->addSeparator();

  QToolButton* delete_button = new QToolButton();
  toolbar->addWidget(delete_button);
  QMenu* delete_popup = new QMenu();
  delete_popup->addAction(QIcon(":/delete"),
                          "Delete current marker",
                          tracker_, SLOT(deleteSelectedMarkers()));
  QAction* delete_track = delete_popup->addAction(QIcon(":/delete-row"),
                                                "Delete current track",
                                                tracker_,
                                                SLOT(deleteSelectedTracks()));
  delete_button->setMenu(delete_popup);
  delete_button->setDefaultAction(delete_track);
  delete_button->setPopupMode(QToolButton::MenuButtonPopup);
  connect(delete_popup,SIGNAL(triggered(QAction*)),
          delete_button,SLOT(setDefaultAction(QAction*)));

  track_action_ = toolbar->addAction(QIcon(":/record"), "Track selected markers");
  track_action_->setCheckable(true);
  connect(track_action_, SIGNAL(triggered(bool)), SLOT(toggleTracking(bool)));
  connect(tracker_action_, SIGNAL(triggered(bool)), track_action_, SLOT(setVisible(bool)));

  QAction* add_action = toolbar->addAction(QIcon(":/add"), "Add object", scene_, SLOT(add()));
  connect(scene_dock->toggleViewAction(), SIGNAL(triggered(bool)),
          add_action, SLOT(setVisible(bool)));

  QAction* link_action = toolbar->addAction(QIcon(":/link"), "Link active object to selected bundles",
                                            scene_, SLOT(link()));
  connect(scene_dock->toggleViewAction(), SIGNAL(triggered(bool)),
          link_action, SLOT(setVisible(bool)));

  toolbar->addSeparator();

  toolbar->addAction(QIcon(":/skip-backward"), "Seek to first frame",
                     this, SLOT(first()));
  toolbar->addAction(QIcon(":/step-backward"),"Step to previous frame",
                     this, SLOT(previous()))->setShortcut(QKeySequence("Left"));
  backward_action_ = toolbar->addAction(QIcon(":/play-backward"),
                                        "Play sequence backwards");
  backward_action_->setCheckable(true);
  connect(backward_action_, SIGNAL(triggered(bool)), SLOT(toggleBackward(bool)));
  connect(&previous_timer_, SIGNAL(timeout()), SLOT(previous()));

  toolbar->addWidget(&spinbox_);
  connect(&spinbox_, SIGNAL(valueChanged(int)), SLOT(seek(int)));
  toolbar->addWidget(&slider_);
  slider_.setOrientation(Qt::Horizontal);
  connect(&slider_, SIGNAL(valueChanged(int)), SLOT(seek(int)));

  forward_action_ = toolbar->addAction(QIcon(":/play-forward"),
                                       "Play sequence forwards");
  forward_action_->setCheckable(true);
  connect(forward_action_, SIGNAL(triggered(bool)), SLOT(toggleForward(bool)));
  connect(&next_timer_, SIGNAL(timeout()), SLOT(next()));
  toolbar->addAction(QIcon(":/step-forward"), "Next Frame",this, SLOT(next()))
      ->setShortcut(QKeySequence("Right"));
  toolbar->addAction(QIcon(":/skip-forward"), "Last Frame",this, SLOT(last()));

  restoreGeometry(QSettings().value("geometry").toByteArray());
  restoreState(QSettings().value("windowState").toByteArray());
}
void MainWindow::Save(QString name,QByteArray data) {
  if(data.isEmpty()) return;
  QFile file(QDir(path_).filePath(name));
  if (file.open(QFile::WriteOnly | QIODevice::Truncate)) {
    file.write(data);
  }
}
MainWindow::~MainWindow() {
  QSettings().setValue("geometry", saveGeometry());
  QSettings().setValue("windowState", saveState());
  if(clip_->isEmpty()) return;
  Save("tracks",tracker_->Save());
  Save("cameras",scene_->SaveCameras());
  Save("bundles",scene_->SaveBundles());
  Save("objects",scene_->SaveObjects());
}

QByteArray MainWindow::Load(QString name) {
  QFile file(QDir(path_).filePath(name));
  return file.open(QFile::ReadOnly) ? file.readAll() : QByteArray();
}
#include <QDebug>
void MainWindow::open() {
  open(QFileDialog::getExistingDirectory(this, "Select sequence folder"));
  if(clip_->isEmpty()) return;
  QSize size = clip_->Image(0).size();
  QDialog dialog(this); dialog.setWindowTitle("Camera Parameters");
  QFormLayout layout( &dialog );

  QDoubleSpinBox focal_length;
  focal_length.setSuffix("px");
  // TODO(MatthiasF): extract from EXIF data
  focal_length.setRange(0,size.width());
  focal_length.setValue(1);
  layout.addRow("Focal Length", &focal_length );

  QDoubleSpinBox principal_point_x;
  principal_point_x.setSuffix("px");
  principal_point_x.setRange(0,size.width());
  principal_point_x.setValue(size.width()/2);
  layout.addRow("Principal Point (X)", &principal_point_x );

  QDoubleSpinBox principal_point_y;
  principal_point_y.setSuffix("px");
  principal_point_y.setRange(0,size.height());
  principal_point_y.setValue(size.height()/2);
  layout.addRow("Principal Point (Y)", &principal_point_y );

  QDoubleSpinBox skew_factor;
  skew_factor.setRange(0,1);
  layout.addRow("Skew Factor", &skew_factor );

  static const char* order[] = { "1st", "2nd", "3rd", "4th", "5th" };
  QDoubleSpinBox radial_distortion_coefficients[5];
  for(int i=0; i<5; i++) {
    layout.addRow(QString(order[i])+" Radial Distortion Coefficient",
                  &radial_distortion_coefficients[i]);
  }
  QDoubleSpinBox tangential_distortion_coefficients[2];
  for(int i=0; i<2; i++) {
    layout.addRow(QString(order[i])+" Tangential Distortion Coefficient",
                  &tangential_distortion_coefficients[i]);
  }

  dialog.exec();
  // TODO(MatthiasF): save and use the calibration data
}

void MainWindow::open(QString path) {
  if (path.isEmpty() || !QDir(path).exists()) return;
  clip_->Open(path);
  if(clip_->isEmpty()) return;
  path_ = path;
  setWindowTitle(QString("Tracker - %1").arg(QDir(path).dirName()));
  tracker_->Load(Load("tracks"));
  scene_->LoadCameras(Load("cameras"));
  scene_->LoadBundles(Load("bundles"));
  scene_->LoadObjects(Load("objects"));
  scene_->upload();
  spinbox_.setMaximum(clip_->size() - 1);
  slider_.setMaximum(clip_->size() - 1);
  first();
}

void MainWindow::seek(int frame) {
  // Bail out if there's nothing to do.
  if (frame == current_frame_) {
    return;
  }
  if (frame < 0 || frame >= clip_->size()) {
    stop();
    return;
  }
  // Track only if the shift is between consecutive frames.
  if ( frame > current_frame_ + 1 || frame < current_frame_ - 1 ) {
    track_action_->setChecked(false);
  }
  current_frame_ = frame;

  slider_.setValue(current_frame_);
  spinbox_.setValue(current_frame_);
  tracker_->SetImage(current_frame_, clip_->Image(current_frame_),
                     track_action_->isChecked());
}

void MainWindow::stop() {
  backward_action_->setChecked(false);
  previous_timer_.stop();
  forward_action_->setChecked(false);
  next_timer_.stop();
}

void MainWindow::first() {
  seek(0);
}

void MainWindow::previous() {
  seek(current_frame_ - 1);
}

void MainWindow::next() {
  seek(current_frame_ + 1);
}

void MainWindow::last() {
  seek(clip_->size() - 1);
}

void MainWindow::toggleTracking(bool track) {
  stop();
  if (track) {
    backward_action_->setText("Track sequence backwards");
    forward_action_->setText("Track sequence forwards");
  } else {
    backward_action_->setText("Play sequence backwards");
    forward_action_->setText("Play sequence forwards");
  }
}

void MainWindow::toggleBackward(bool play) {
  if (play) {
    forward_action_->setChecked(false);
    next_timer_.stop();
    previous_timer_.start(0);
  } else {
    stop();
  }
}

void MainWindow::toggleForward(bool play) {
  if (play) {
    backward_action_->setChecked(false);
    previous_timer_.stop();
    next_timer_.start(0);
  } else {
    stop();
  }
}

void MainWindow::toggleZoom(bool zoom) {
  if (zoom) {
    foreach(QDockWidget* dock, zooms_docks_) {
      dock->show();
    }
  } else {
    foreach(QDockWidget* dock, zooms_docks_) {
      dock->hide();
    }
  }
}

void MainWindow::updateZooms(QVector<int> tracks) {
  if(!zooms_docks_.isEmpty() && tracks.size()*zooms_docks_.first()->width() > width()) {
    tracks.resize(width() / zooms_docks_.first()->width());
  }
  for(int i=tracks.size(); i<zooms_docks_.size(); i++) {
    removeDockWidget(zooms_docks_[i]);
    delete zooms_docks_[i];
    //zoom widget is owned by dock ?
  }
  for(int i=zooms_docks_.size(); i<tracks.size(); i++) {
    QDockWidget* dock = new QDockWidget(QString("Zoom View #%1").arg(tracks[i]));
    dock->setObjectName(QString("zoom%1").arg(tracks[i]));
    addDockWidget(Qt::TopDockWidgetArea, dock);
    Zoom* zoom = new Zoom(0,tracker_);
    dock->setWidget(zoom);
    addDockWidget(Qt::TopDockWidgetArea,dock);
    zooms_ << zoom;
    zooms_docks_ << dock;
  }
  zooms_docks_.resize(tracks.size());
  zooms_.resize(tracks.size());
  for(int i=0; i<tracks.size(); i++) {
    zooms_[i]->SetMarker(current_frame_,tracks[i]);
  }
}

int main(int argc, char *argv[]) {
  libmv::Init("", &argc, &argv);
  QApplication app(argc, argv);
  app.setOrganizationName("libmv");
  app.setApplicationName("tracker");
  MainWindow window;
  window.show();
  window.open(app.arguments().value(1));
  return app.exec();
}

<commit_msg>Persistent Settings.<commit_after>// Copyright (c) 2011 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "ui/tracker/main.h"
#include "ui/tracker/tracker.h"
#include "ui/tracker/scene.h"

#include "libmv/tools/tool.h"

#include <QApplication>
#include <QFileDialog>
#include <QFormLayout>
#include <QDockWidget>
#include <QToolButton>
#include <QSettings>
#include <QToolBar>
#include <QAction>
#include <QCache>
#include <QMenu>
#include <QTime>

void Clip::Open(QString path) {
  cache_.setMaxCost(64 * 1024 * 1024);
  if (path.endsWith(".avi")) {
    // TODO(MatthiasF): load videos using ffmpeg
    return;
  }

  clear();
  foreach (QString file, QDir(path).entryList(QStringList("*.jpg") << "*.png",
                                              QDir::Files, QDir::Name)) {
    append( QDir(path).filePath(file) );
  }
}

QImage Clip::Image(int frame) {
  QImage* image = cache_[frame];
  if (!image) {
    image = new QImage(value(frame));
    cache_.insert(frame, image, image->byteCount());
  }
  return *image;
}

MainWindow::MainWindow()
  : clip_(new Clip(this)),
    scene_(new Scene()),
    tracker_(new Tracker(scene_,scene_)),
    current_frame_(-1) {
  setWindowTitle("Tracker");
  setCentralWidget(tracker_);
  connect(tracker_, SIGNAL(trackChanged(QVector<int>)), this, SLOT(updateZooms(QVector<int>)));

  QToolBar* toolbar = addToolBar("Main Toolbar");
  toolbar->setObjectName("mainToolbar");

  toolbar->addAction(QIcon(":/open"), "Open a new sequence...",
                     this, SLOT(open()));

  QAction* tracker_action_ = toolbar->addAction(QIcon(":/view-image"),"Tracker View");
  tracker_action_->setCheckable(true);
  connect(tracker_action_,SIGNAL(triggered(bool)),tracker_,SLOT(setVisible(bool)));

  QAction* zoom_action_ = toolbar->addAction(QIcon(":/view-zoom"),"Zoom View");
  zoom_action_->setCheckable(true);
  connect(zoom_action_,SIGNAL(triggered(bool)),this,SLOT(toggleZoom(bool)));

  QDockWidget* scene_dock = new QDockWidget("Scene View");
  scene_dock->setObjectName("sceneDock");
  addDockWidget(Qt::BottomDockWidgetArea, scene_dock);
  scene_dock->setWidget(scene_);
  scene_dock->toggleViewAction()->setIcon(QIcon(":/view-scene"));
  toolbar->addAction(scene_dock->toggleViewAction());
  connect(scene_, SIGNAL(imageChanged(int)), SLOT(seek(int)));
  connect(scene_, SIGNAL(trackChanged(QVector<int>)), tracker_, SLOT(select(QVector<int>)));

  toolbar->addSeparator();

  QToolButton* delete_button = new QToolButton();
  toolbar->addWidget(delete_button);
  QMenu* delete_popup = new QMenu();
  delete_popup->addAction(QIcon(":/delete"),
                          "Delete current marker",
                          tracker_, SLOT(deleteSelectedMarkers()));
  QAction* delete_track = delete_popup->addAction(QIcon(":/delete-row"),
                                                "Delete current track",
                                                tracker_,
                                                SLOT(deleteSelectedTracks()));
  delete_button->setMenu(delete_popup);
  delete_button->setDefaultAction(delete_track);
  delete_button->setPopupMode(QToolButton::MenuButtonPopup);
  connect(delete_popup,SIGNAL(triggered(QAction*)),
          delete_button,SLOT(setDefaultAction(QAction*)));

  track_action_ = toolbar->addAction(QIcon(":/record"), "Track selected markers");
  track_action_->setCheckable(true);
  connect(track_action_, SIGNAL(triggered(bool)), SLOT(toggleTracking(bool)));
  connect(tracker_action_, SIGNAL(triggered(bool)), track_action_, SLOT(setVisible(bool)));

  QAction* add_action = toolbar->addAction(QIcon(":/add"), "Add object", scene_, SLOT(add()));
  connect(scene_dock->toggleViewAction(), SIGNAL(triggered(bool)),
          add_action, SLOT(setVisible(bool)));

  QAction* link_action = toolbar->addAction(QIcon(":/link"), "Link active object to selected bundles",
                                            scene_, SLOT(link()));
  connect(scene_dock->toggleViewAction(), SIGNAL(triggered(bool)),
          link_action, SLOT(setVisible(bool)));

  toolbar->addSeparator();

  toolbar->addAction(QIcon(":/skip-backward"), "Seek to first frame",
                     this, SLOT(first()));
  toolbar->addAction(QIcon(":/step-backward"),"Step to previous frame",
                     this, SLOT(previous()))->setShortcut(QKeySequence("Left"));
  backward_action_ = toolbar->addAction(QIcon(":/play-backward"),
                                        "Play sequence backwards");
  backward_action_->setCheckable(true);
  connect(backward_action_, SIGNAL(triggered(bool)), SLOT(toggleBackward(bool)));
  connect(&previous_timer_, SIGNAL(timeout()), SLOT(previous()));

  toolbar->addWidget(&spinbox_);
  connect(&spinbox_, SIGNAL(valueChanged(int)), SLOT(seek(int)));
  toolbar->addWidget(&slider_);
  slider_.setOrientation(Qt::Horizontal);
  connect(&slider_, SIGNAL(valueChanged(int)), SLOT(seek(int)));

  forward_action_ = toolbar->addAction(QIcon(":/play-forward"),
                                       "Play sequence forwards");
  forward_action_->setCheckable(true);
  connect(forward_action_, SIGNAL(triggered(bool)), SLOT(toggleForward(bool)));
  connect(&next_timer_, SIGNAL(timeout()), SLOT(next()));
  toolbar->addAction(QIcon(":/step-forward"), "Next Frame",this, SLOT(next()))
      ->setShortcut(QKeySequence("Right"));
  toolbar->addAction(QIcon(":/skip-forward"), "Last Frame",this, SLOT(last()));

  restoreGeometry(QSettings().value("geometry").toByteArray());
  restoreState(QSettings().value("windowState").toByteArray());
}
void MainWindow::Save(QString name,QByteArray data) {
  if(data.isEmpty()) return;
  QFile file(QDir(path_).filePath(name));
  if (file.open(QFile::WriteOnly | QIODevice::Truncate)) {
    file.write(data);
  }
}
MainWindow::~MainWindow() {
  QSettings().setValue("geometry", saveGeometry());
  QSettings().setValue("windowState", saveState());
  if(clip_->isEmpty()) return;
  Save("tracks",tracker_->Save());
  Save("cameras",scene_->SaveCameras());
  Save("bundles",scene_->SaveBundles());
  Save("objects",scene_->SaveObjects());
}

QByteArray MainWindow::Load(QString name) {
  QFile file(QDir(path_).filePath(name));
  return file.open(QFile::ReadOnly) ? file.readAll() : QByteArray();
}

struct Parameter {
  const char* name;
  const char* suffix;
  double min;
  double max;
  double value;
};

void MainWindow::open() {
  open(QFileDialog::getExistingDirectory(this, "Select sequence folder"));
  if(clip_->isEmpty()) return;
  QSize size = clip_->Image(0).size();
  QDialog dialog(this); dialog.setWindowTitle("Camera Parameters");
  QFormLayout layout( &dialog );

  const Parameter parameters[] = {
    {"Focal Length",              "px", 0, size.width(),  1               },
    {"Principal Point (X)",       "px", 0, size.width(),  size.width()/2  },
    {"Principal Point (Y)",       "px", 0, size.height(), size.height()/2 },
    {"Skew Factor",               "",   0, 1,             0               },
    {"1st Radial Distortion",     "",   0, 1,             0               },
    {"2nd Radial Distortion",     "",   0, 1,             0               },
    {"3rd Radial Distortion",     "",   0, 1,             0               },
    {"4th Radial Distortion",     "",   0, 1,             0               },
    {"5th Radial Distortion",     "",   0, 1,             0               },
    {"1st Tangential Distortion", "",   0, 1,             0               },
    {"2nd Tangential Distortion", "",   0, 1,             0               },
  };
  const int count = sizeof(parameters)/sizeof(Parameter);
  QDoubleSpinBox spinbox[count];

  QByteArray data = Load("settings");
  data.reserve(count*sizeof(float));
  float* values = (float*)data.data();
  for(int i=0; i<count; i++) {
    Parameter parameter = parameters[i];
    spinbox[i].setSuffix(parameter.suffix);
    spinbox[i].setRange(parameter.min,parameter.max);
    if(data.isEmpty()) {
      spinbox[i].setValue(parameter.value);
    } else {
      spinbox[i].setValue(values[i]);
    }
    layout.addRow(parameter.name,&spinbox[i]);
  }
  dialog.exec();
  data.resize(count*sizeof(float));
  for(int i=0; i<count; i++) {
    values[i]=spinbox[i].value();
  }
  Save("settings",data);
  // TODO(MatthiasF): use the calibration data
}

void MainWindow::open(QString path) {
  if (path.isEmpty() || !QDir(path).exists()) return;
  clip_->Open(path);
  if(clip_->isEmpty()) return;
  path_ = path;
  setWindowTitle(QString("Tracker - %1").arg(QDir(path).dirName()));
  tracker_->Load(Load("tracks"));
  scene_->LoadCameras(Load("cameras"));
  scene_->LoadBundles(Load("bundles"));
  scene_->LoadObjects(Load("objects"));
  scene_->upload();
  spinbox_.setMaximum(clip_->size() - 1);
  slider_.setMaximum(clip_->size() - 1);
  first();
}

void MainWindow::seek(int frame) {
  // Bail out if there's nothing to do.
  if (frame == current_frame_) {
    return;
  }
  if (frame < 0 || frame >= clip_->size()) {
    stop();
    return;
  }
  // Track only if the shift is between consecutive frames.
  if ( frame > current_frame_ + 1 || frame < current_frame_ - 1 ) {
    track_action_->setChecked(false);
  }
  current_frame_ = frame;

  slider_.setValue(current_frame_);
  spinbox_.setValue(current_frame_);
  tracker_->SetImage(current_frame_, clip_->Image(current_frame_),
                     track_action_->isChecked());
}

void MainWindow::stop() {
  backward_action_->setChecked(false);
  previous_timer_.stop();
  forward_action_->setChecked(false);
  next_timer_.stop();
}

void MainWindow::first() {
  seek(0);
}

void MainWindow::previous() {
  seek(current_frame_ - 1);
}

void MainWindow::next() {
  seek(current_frame_ + 1);
}

void MainWindow::last() {
  seek(clip_->size() - 1);
}

void MainWindow::toggleTracking(bool track) {
  stop();
  if (track) {
    backward_action_->setText("Track sequence backwards");
    forward_action_->setText("Track sequence forwards");
  } else {
    backward_action_->setText("Play sequence backwards");
    forward_action_->setText("Play sequence forwards");
  }
}

void MainWindow::toggleBackward(bool play) {
  if (play) {
    forward_action_->setChecked(false);
    next_timer_.stop();
    previous_timer_.start(0);
  } else {
    stop();
  }
}

void MainWindow::toggleForward(bool play) {
  if (play) {
    backward_action_->setChecked(false);
    previous_timer_.stop();
    next_timer_.start(0);
  } else {
    stop();
  }
}

void MainWindow::toggleZoom(bool zoom) {
  if (zoom) {
    foreach(QDockWidget* dock, zooms_docks_) {
      dock->show();
    }
  } else {
    foreach(QDockWidget* dock, zooms_docks_) {
      dock->hide();
    }
  }
}

void MainWindow::updateZooms(QVector<int> tracks) {
  if(!zooms_docks_.isEmpty() && tracks.size()*zooms_docks_.first()->width() > width()) {
    tracks.resize(width() / zooms_docks_.first()->width());
  }
  for(int i=tracks.size(); i<zooms_docks_.size(); i++) {
    removeDockWidget(zooms_docks_[i]);
    delete zooms_docks_[i];
    //zoom widget is owned by dock ?
  }
  for(int i=zooms_docks_.size(); i<tracks.size(); i++) {
    QDockWidget* dock = new QDockWidget(QString("Zoom View #%1").arg(tracks[i]));
    dock->setObjectName(QString("zoom%1").arg(tracks[i]));
    addDockWidget(Qt::TopDockWidgetArea, dock);
    Zoom* zoom = new Zoom(0,tracker_);
    dock->setWidget(zoom);
    addDockWidget(Qt::TopDockWidgetArea,dock);
    zooms_ << zoom;
    zooms_docks_ << dock;
  }
  zooms_docks_.resize(tracks.size());
  zooms_.resize(tracks.size());
  for(int i=0; i<tracks.size(); i++) {
    zooms_[i]->SetMarker(current_frame_,tracks[i]);
  }
}

int main(int argc, char *argv[]) {
  libmv::Init("", &argc, &argv);
  QApplication app(argc, argv);
  app.setOrganizationName("libmv");
  app.setApplicationName("tracker");
  MainWindow window;
  window.show();
  window.open(app.arguments().value(1));
  return app.exec();
}

<|endoftext|>


<commit_before>//  test_helpers.cpp : functions to aid in testing and test reporting
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

// test reporting helper
int ReportTestResult(int nrOfFailedTests, std::string description, std::string test_operation)
{
	if (nrOfFailedTests > 0) {
		std::cout << description << " " << test_operation << " FAIL " << nrOfFailedTests << " failed test cases" << std::endl;
	}
	else {
		std::cout << description << " " << test_operation << " PASS" << std::endl;
	}
	return nrOfFailedTests;
}

<commit_msg>performance fix passing std::string as const reference<commit_after>//  test_helpers.cpp : functions to aid in testing and test reporting
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

// test reporting helper
int ReportTestResult(int nrOfFailedTests, const std::string& description, const std::string& test_operation)
{
	if (nrOfFailedTests > 0) {
		std::cout << description << " " << test_operation << " FAIL " << nrOfFailedTests << " failed test cases" << std::endl;
	}
	else {
		std::cout << description << " " << test_operation << " PASS" << std::endl;
	}
	return nrOfFailedTests;
}

<|endoftext|>


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

#include "SkRTConf.h"
#include "SkOSFile.h"

SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) {

    SkFILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag);

    if (!fp) {
        return;
    }

    char line[1024];

    while (!sk_feof(fp)) {

        if (!sk_fgets(line, sizeof(line), fp)) {
            break;
        }

        char *commentptr = strchr(line, '#');
        if (commentptr == line) {
            continue;
        }
        if (NULL != commentptr) {
            *commentptr = '\0';
        }

        char sep[] = " \t\r\n";

        char *keyptr = strtok(line, sep);
        if (!keyptr) {
            continue;
        }

        char *valptr = strtok(NULL, sep);
        if (!valptr) {
            continue;
        }

        SkString* key = new SkString(keyptr);
        SkString* val = new SkString(valptr);

        fConfigFileKeys.append(1, &key);
        fConfigFileValues.append(1, &val);
    }
    sk_fclose(fp);
}

const char *SkRTConfRegistry::configFileLocation() const {
    return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever.
}

// dump all known runtime config options to the file with their default values.
// to trigger this, make a config file of zero size.
void SkRTConfRegistry::possiblyDumpFile() const {
    const char *path = configFileLocation();
    SkFILE *fp = sk_fopen(path, kRead_SkFILE_Flag);
    if (!fp) {
        return;
    }
    size_t configFileSize = sk_fgetsize(fp);
    if (configFileSize == 0) {
        printAll(path);
    }
    sk_fclose(fp);
}

// Run through every provided configuration option and print a warning if the user hasn't
// declared a correponding configuration object somewhere.
void SkRTConfRegistry::validate() const {
    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfs.find(fConfigFileKeys[i]->c_str())) {
            SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str());
        }
    }
}

void SkRTConfRegistry::printAll(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }

    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (confArray->getAt(0)->isDefault()) {
            o->writeText("# ");
        }
        confArray->getAt(0)->print(o);
        o->newline();
    }

    delete o;
}

void SkRTConfRegistry::printNonDefault(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }
    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (!confArray->getAt(0)->isDefault()) {
            confArray->getAt(0)->print(o);
            o->newline();
        }
    }

    delete o;
}

// register a configuration variable after its value has been set by the parser.
// we maintain a vector of these things instead of just a single one because the
// user might set the value after initialization time and we need to have
// all the pointers lying around, not just one.
void SkRTConfRegistry::registerConf(SkRTConfBase *conf) {
    SkTDArray<SkRTConfBase *> *confArray;
    if (fConfs.find(conf->getName(), &confArray)) {
        if (!conf->equals(confArray->getAt(0))) {
            SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName());
        } else {
            confArray->append(1, &conf);
        }
    } else {
        confArray = new SkTDArray<SkRTConfBase *>;
        confArray->append(1, &conf);
        fConfs.set(conf->getName(),confArray);
    }
}

template <typename T> T doParse(const char *, bool *success ) {
    SkDebugf("WARNING: Invoked non-specialized doParse function...\n");
    if (success) {
        *success = false;
    }
    return (T) 0;
}

template<> bool doParse<bool>(const char *s, bool *success) {
    if (success) {
        *success = true;
    }
    if (!strcmp(s,"1") || !strcmp(s,"true")) {
        return true;
    }
    if (!strcmp(s,"0") || !strcmp(s,"false")) {
        return false;
    }
    if (success) {
        *success = false;
    }
    return false;
}

template<> const char * doParse<const char *>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return s;
}

template<> int doParse<int>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return atoi(s);
}

template<> unsigned int doParse<unsigned int>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return (unsigned int) atoi(s);
}

template<> float doParse<float>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return (float) atof(s);
}

template<> double doParse<double>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return atof(s);
}

static inline void str_replace(char *s, char search, char replace) {
    for (char *ptr = s ; *ptr ; ptr++) {
        if (*ptr == search) {
            *ptr = replace;
        }
    }
}

template<typename T> bool SkRTConfRegistry::parse(const char *name, T* value) {
    SkString *str = NULL;

    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfigFileKeys[i]->equals(name)) {
            str = fConfigFileValues[i];
        }
    }

    SkString environment_variable("skia.");
    environment_variable.append(name);

    const char *environment_value = getenv(environment_variable.c_str());
    if (environment_value) {
        str->set(environment_value);
    } else {
        // apparently my shell doesn't let me have environment variables that
        // have periods in them, so also let the user substitute underscores.
        SkString underscore_environment_variable("skia_");
        char *underscore_name = SkStrDup(name);
        str_replace(underscore_name,'.','_');
        underscore_environment_variable.append(underscore_name);
        sk_free(underscore_name);
        environment_value = getenv(underscore_environment_variable.c_str());
        if (environment_value) {
            str->set(environment_value);
        }
    }

    if (!str) {
        return false;
    }

    bool success;
    T new_value = doParse<T>(str->c_str(),&success);
    if (success) {
        *value = new_value;
    } else {
        SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", str->c_str(), name);
    }
    return success;
}

// need to explicitly instantiate the parsing function for every config type we might have...

template bool SkRTConfRegistry::parse(const char *name, bool *value);
template bool SkRTConfRegistry::parse(const char *name, int *value);
template bool SkRTConfRegistry::parse(const char *name, unsigned int *value);
template bool SkRTConfRegistry::parse(const char *name, float *value);
template bool SkRTConfRegistry::parse(const char *name, double *value);
template bool SkRTConfRegistry::parse(const char *name, const char **value);

template <typename T> void SkRTConfRegistry::set(const char *name, T value) {

    SkTDArray<SkRTConfBase *> *confArray;
    if (!fConfs.find(name, &confArray)) {
        SkDebugf("WARNING: Attempting to set configuration value \"%s\", but I've never heard of that.\n", name);
        return;
    }

    for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) {
        // static_cast here is okay because there's only one kind of child class.
        SkRTConf<T> *concrete = static_cast<SkRTConf<T> *>(*confBase);

        if (concrete) {
            concrete->set(value);
        }
    }
}

template void SkRTConfRegistry::set(const char *name, bool value);
template void SkRTConfRegistry::set(const char *name, int value);
template void SkRTConfRegistry::set(const char *name, unsigned int value);
template void SkRTConfRegistry::set(const char *name, float value);
template void SkRTConfRegistry::set(const char *name, double value);
template void SkRTConfRegistry::set(const char *name, char * value);

SkRTConfRegistry &skRTConfRegistry() {
    static SkRTConfRegistry r;
    return r;
}
<commit_msg>fix boolean check for unknown rtconf variables in files.<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRTConf.h"
#include "SkOSFile.h"

SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) {

    SkFILE *fp = sk_fopen(configFileLocation(), kRead_SkFILE_Flag);

    if (!fp) {
        return;
    }

    char line[1024];

    while (!sk_feof(fp)) {

        if (!sk_fgets(line, sizeof(line), fp)) {
            break;
        }

        char *commentptr = strchr(line, '#');
        if (commentptr == line) {
            continue;
        }
        if (NULL != commentptr) {
            *commentptr = '\0';
        }

        char sep[] = " \t\r\n";

        char *keyptr = strtok(line, sep);
        if (!keyptr) {
            continue;
        }

        char *valptr = strtok(NULL, sep);
        if (!valptr) {
            continue;
        }

        SkString* key = new SkString(keyptr);
        SkString* val = new SkString(valptr);

        fConfigFileKeys.append(1, &key);
        fConfigFileValues.append(1, &val);
    }
    sk_fclose(fp);
}

const char *SkRTConfRegistry::configFileLocation() const {
    return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever.
}

// dump all known runtime config options to the file with their default values.
// to trigger this, make a config file of zero size.
void SkRTConfRegistry::possiblyDumpFile() const {
    const char *path = configFileLocation();
    SkFILE *fp = sk_fopen(path, kRead_SkFILE_Flag);
    if (!fp) {
        return;
    }
    size_t configFileSize = sk_fgetsize(fp);
    if (configFileSize == 0) {
        printAll(path);
    }
    sk_fclose(fp);
}

// Run through every provided configuration option and print a warning if the user hasn't
// declared a correponding configuration object somewhere.
void SkRTConfRegistry::validate() const {
    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (!fConfs.find(fConfigFileKeys[i]->c_str())) {
            SkDebugf("WARNING: You have config value %s in your configuration file, but I've never heard of that.\n", fConfigFileKeys[i]->c_str());
        }
    }
}

void SkRTConfRegistry::printAll(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }

    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (confArray->getAt(0)->isDefault()) {
            o->writeText("# ");
        }
        confArray->getAt(0)->print(o);
        o->newline();
    }

    delete o;
}

void SkRTConfRegistry::printNonDefault(const char *fname) const {
    SkWStream *o;

    if (NULL != fname) {
        o = new SkFILEWStream(fname);
    } else {
        o = new SkDebugWStream();
    }
    ConfMap::Iter iter(fConfs);
    SkTDArray<SkRTConfBase *> *confArray;

    while (iter.next(&confArray)) {
        if (!confArray->getAt(0)->isDefault()) {
            confArray->getAt(0)->print(o);
            o->newline();
        }
    }

    delete o;
}

// register a configuration variable after its value has been set by the parser.
// we maintain a vector of these things instead of just a single one because the
// user might set the value after initialization time and we need to have
// all the pointers lying around, not just one.
void SkRTConfRegistry::registerConf(SkRTConfBase *conf) {
    SkTDArray<SkRTConfBase *> *confArray;
    if (fConfs.find(conf->getName(), &confArray)) {
        if (!conf->equals(confArray->getAt(0))) {
            SkDebugf("WARNING: Skia config \"%s\" was registered more than once in incompatible ways.\n", conf->getName());
        } else {
            confArray->append(1, &conf);
        }
    } else {
        confArray = new SkTDArray<SkRTConfBase *>;
        confArray->append(1, &conf);
        fConfs.set(conf->getName(),confArray);
    }
}

template <typename T> T doParse(const char *, bool *success ) {
    SkDebugf("WARNING: Invoked non-specialized doParse function...\n");
    if (success) {
        *success = false;
    }
    return (T) 0;
}

template<> bool doParse<bool>(const char *s, bool *success) {
    if (success) {
        *success = true;
    }
    if (!strcmp(s,"1") || !strcmp(s,"true")) {
        return true;
    }
    if (!strcmp(s,"0") || !strcmp(s,"false")) {
        return false;
    }
    if (success) {
        *success = false;
    }
    return false;
}

template<> const char * doParse<const char *>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return s;
}

template<> int doParse<int>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return atoi(s);
}

template<> unsigned int doParse<unsigned int>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return (unsigned int) atoi(s);
}

template<> float doParse<float>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return (float) atof(s);
}

template<> double doParse<double>(const char * s, bool *success) {
    if (success) {
        *success = true;
    }
    return atof(s);
}

static inline void str_replace(char *s, char search, char replace) {
    for (char *ptr = s ; *ptr ; ptr++) {
        if (*ptr == search) {
            *ptr = replace;
        }
    }
}

template<typename T> bool SkRTConfRegistry::parse(const char *name, T* value) {
    SkString *str = NULL;

    for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
        if (fConfigFileKeys[i]->equals(name)) {
            str = fConfigFileValues[i];
        }
    }

    SkString environment_variable("skia.");
    environment_variable.append(name);

    const char *environment_value = getenv(environment_variable.c_str());
    if (environment_value) {
        str->set(environment_value);
    } else {
        // apparently my shell doesn't let me have environment variables that
        // have periods in them, so also let the user substitute underscores.
        SkString underscore_environment_variable("skia_");
        char *underscore_name = SkStrDup(name);
        str_replace(underscore_name,'.','_');
        underscore_environment_variable.append(underscore_name);
        sk_free(underscore_name);
        environment_value = getenv(underscore_environment_variable.c_str());
        if (environment_value) {
            str->set(environment_value);
        }
    }

    if (!str) {
        return false;
    }

    bool success;
    T new_value = doParse<T>(str->c_str(),&success);
    if (success) {
        *value = new_value;
    } else {
        SkDebugf("WARNING: Couldn't parse value \'%s\' for variable \'%s\'\n", str->c_str(), name);
    }
    return success;
}

// need to explicitly instantiate the parsing function for every config type we might have...

template bool SkRTConfRegistry::parse(const char *name, bool *value);
template bool SkRTConfRegistry::parse(const char *name, int *value);
template bool SkRTConfRegistry::parse(const char *name, unsigned int *value);
template bool SkRTConfRegistry::parse(const char *name, float *value);
template bool SkRTConfRegistry::parse(const char *name, double *value);
template bool SkRTConfRegistry::parse(const char *name, const char **value);

template <typename T> void SkRTConfRegistry::set(const char *name, T value) {

    SkTDArray<SkRTConfBase *> *confArray;
    if (!fConfs.find(name, &confArray)) {
        SkDebugf("WARNING: Attempting to set configuration value \"%s\", but I've never heard of that.\n", name);
        return;
    }

    for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) {
        // static_cast here is okay because there's only one kind of child class.
        SkRTConf<T> *concrete = static_cast<SkRTConf<T> *>(*confBase);

        if (concrete) {
            concrete->set(value);
        }
    }
}

template void SkRTConfRegistry::set(const char *name, bool value);
template void SkRTConfRegistry::set(const char *name, int value);
template void SkRTConfRegistry::set(const char *name, unsigned int value);
template void SkRTConfRegistry::set(const char *name, float value);
template void SkRTConfRegistry::set(const char *name, double value);
template void SkRTConfRegistry::set(const char *name, char * value);

SkRTConfRegistry &skRTConfRegistry() {
    static SkRTConfRegistry r;
    return r;
}
<|endoftext|>


<commit_before>#pragma once

#include "exception.hpp"
#include "debug.hpp"

#include <memory>

namespace utki{

/**
 * @brief Intrusive singleton base class.
 * This is a basic intrusive singleton template.
 * Template params: T - your singletone class type, T_InstanceOwner - class which owns the static 'instance' variable.
 * In most cases T_InstanceOwner is the same as T.
 * Usage as follows:
 * @code
 *	class my_singleton : public utki::intrusive_singleton<my_singleton, my_singleton>{
 *		friend class utki::intrusive_singleton<my_singleton, my_singleton>;
 *		static utki::intrusive_singleton<my_singleton, my_singleton>::T_Instance instance;
 *
 *	public:
 *		void do_something(){
 *			//...
 *		}
 *  };
 *
 *	//define the static variable somewhere in .cpp file.
 *  utki::intrusive_singleton<my_singleton, my_singleton>::T_Instance my_singleton::instance;
 *
 *	int main(int, char**){
 *		my_singleton my_singleton_instance;
 *
 *		my_singleton::inst().do_something();
 *	}
 * @endcode
 */
template <class T, class T_InstanceOwner = T> class intrusive_singleton{

protected://use only as a base class
	intrusive_singleton(){
		if(T_InstanceOwner::instance){
			throw utki::invalid_state("Singleton::Singleton(): instance is already created");
		}

		T_InstanceOwner::instance.reset(static_cast<T*>(this));
	}

	typedef intrusive_singleton<T> T_Singleton;

	//Use unique_ptr because it is automatically initialized to nullptr. Automatic object destruction is not used.
	typedef std::unique_ptr<T> T_Instance;

public:

	intrusive_singleton(const intrusive_singleton&) = delete;
	intrusive_singleton& operator=(const intrusive_singleton&) = delete;

public:

	/**
	 * @brief tells if singleton object is created or not.
	 * Note, this function is not thread safe.
	 * @return true if object is created.
	 * @return false otherwise.
	 */
	static bool is_created(){
		return T_InstanceOwner::instance.operator bool();
	}

	//TODO: deprecated, remove.
	static bool isCreated(){
		return is_created();
	}

	/**
	 * @brief get singleton instance.
	 * @return reference to singleton object instance.
	 */
	static T& inst(){
		ASSERT_INFO(is_created(), "intrusive_singleton::inst(): singleton object is not created")
		return *T_InstanceOwner::instance;
	}

	virtual ~intrusive_singleton()noexcept{
		ASSERT(T_InstanceOwner::instance.operator->() == static_cast<T*>(this))
		T_InstanceOwner::instance.release();
	}
};

/**
 * @brief Singleton base class.
 * This is a basic non-intrusive singleton template.
 * Note, that Singleton inherits the IntrusiveSingleton class, so it inherits all
 * its static methods, the most important one is Inst().
 * Usage as follows:
 * @code
 *	class my_singleton : public utki::singleton<my_singleton>{
 *	public:
 *		void do_something(){
 *			//...
 *		}
 *  };
 *
 *	int main(int, char**){
 *		my_singleton my_singleton_instance;
 *
 *		my_singleton::inst().do_something();
 *	}
 * @endcode
 */
template <class T> class singleton : public intrusive_singleton<T, singleton<T> >{
	friend class intrusive_singleton<T, singleton<T> >;
protected:
	singleton(){}

public:
	singleton(const singleton&) = delete;
	singleton& operator=(const singleton&) = delete;

private:

	static typename intrusive_singleton<T, singleton<T> >::T_Instance instance;
};

template <class T> typename utki::intrusive_singleton<T, singleton<T> >::T_Instance utki::singleton<T>::instance;

}
<commit_msg>minor formatting corrections<commit_after>#pragma once

#include "exception.hpp"
#include "debug.hpp"

#include <memory>

namespace utki{

/**
 * @brief Intrusive singleton base class.
 * This is a basic intrusive singleton template.
 * Template params: T - your singletone class type, T_InstanceOwner - class which owns the static 'instance' variable.
 * In most cases T_InstanceOwner is the same as T.
 * Usage as follows:
 * @code
 *	class my_singleton : public utki::intrusive_singleton<my_singleton, my_singleton>{
 *		friend class utki::intrusive_singleton<my_singleton, my_singleton>;
 *		static utki::intrusive_singleton<my_singleton, my_singleton>::T_Instance instance;
 *
 *	public:
 *		void do_something(){
 *			//...
 *		}
 *  };
 *
 *	//define the static variable somewhere in .cpp file.
 *  utki::intrusive_singleton<my_singleton, my_singleton>::T_Instance my_singleton::instance;
 *
 *	int main(int, char**){
 *		my_singleton my_singleton_instance;
 *
 *		my_singleton::inst().do_something();
 *	}
 * @endcode
 */
template <class T, class T_InstanceOwner = T> class intrusive_singleton{

protected: // use only as a base class
	intrusive_singleton(){
		if(T_InstanceOwner::instance){
			throw utki::invalid_state("singleton::singleton(): instance is already created");
		}

		T_InstanceOwner::instance.reset(static_cast<T*>(this));
	}

	typedef intrusive_singleton<T> T_Singleton;

	// use unique_ptr because it is automatically initialized to nullptr. Automatic object destruction is not used.
	typedef std::unique_ptr<T> T_Instance;

public:

	intrusive_singleton(const intrusive_singleton&) = delete;
	intrusive_singleton& operator=(const intrusive_singleton&) = delete;

public:

	/**
	 * @brief tells if singleton object is created or not.
	 * Note, this function is not thread safe.
	 * @return true if object is created.
	 * @return false otherwise.
	 */
	static bool is_created(){
		return T_InstanceOwner::instance.operator bool();
	}

	// TODO: deprecated, remove.
	static bool isCreated(){
		return is_created();
	}

	/**
	 * @brief get singleton instance.
	 * @return reference to singleton object instance.
	 */
	static T& inst(){
		ASSERT_INFO(is_created(), "intrusive_singleton::inst(): singleton object is not created")
		return *T_InstanceOwner::instance;
	}

	virtual ~intrusive_singleton()noexcept{
		ASSERT(T_InstanceOwner::instance.operator->() == static_cast<T*>(this))
		T_InstanceOwner::instance.release();
	}
};

/**
 * @brief Singleton base class.
 * This is a basic non-intrusive singleton template.
 * Note, that Singleton inherits the IntrusiveSingleton class, so it inherits all
 * its static methods, the most important one is Inst().
 * Usage as follows:
 * @code
 *	class my_singleton : public utki::singleton<my_singleton>{
 *	public:
 *		void do_something(){
 *			//...
 *		}
 *  };
 *
 *	int main(int, char**){
 *		my_singleton my_singleton_instance;
 *
 *		my_singleton::inst().do_something();
 *	}
 * @endcode
 */
template <class T> class singleton : public intrusive_singleton<T, singleton<T> >{
	friend class intrusive_singleton<T, singleton<T> >;
protected:
	singleton(){}

public:
	singleton(const singleton&) = delete;
	singleton& operator=(const singleton&) = delete;

private:

	static typename intrusive_singleton<T, singleton<T> >::T_Instance instance;
};

template <class T> typename utki::intrusive_singleton<T, singleton<T> >::T_Instance utki::singleton<T>::instance;

}
<|endoftext|>


<commit_before>/*
  Q Light Controller Plus
  main.cpp

  Copyright (c) Massimo Callegari

  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.txt

  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 <QApplication>
#include <QCommandLineParser>
#include <QQmlApplicationEngine>

#include "app.h"
#include "qlcconfig.h"

void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    Q_UNUSED(context)
    Q_UNUSED(type)

    QByteArray localMsg = msg.toLocal8Bit();
    //if (type >= QtSystemMsg)
    {
        fprintf(stderr, "%s\n", localMsg.constData());
        fflush(stderr);
    }
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QApplication::setOrganizationName("qlcplus");
    QApplication::setOrganizationDomain("org.qlcplus");
    QApplication::setApplicationName(APPNAME);
    QApplication::setApplicationVersion(QString(APPVERSION));

    QCommandLineParser parser;
    parser.setApplicationDescription("Q Light Controller Plus");

    parser.addHelpOption();
    parser.addVersionOption();
    QCommandLineOption debugOption(QStringList() << "d" << "debug",
                                      "Enable debug messages.");
    parser.addOption(debugOption);

    QCommandLineOption openFileOption(QStringList() << "o" << "open",
                                      "Specify a file to open.",
                                      "filename", "");
    parser.addOption(openFileOption);

    parser.process(app);

    if (parser.isSet(debugOption))
        qInstallMessageHandler(debugMessageHandler);

    App qlcplusApp;
    qlcplusApp.startup();
    qlcplusApp.show();

    QString filename = parser.value(openFileOption);
    if (filename.isEmpty() == false)
        qlcplusApp.loadWorkspace(filename);

    return app.exec();
}
<commit_msg>qmlui: fixed wrong organization domain<commit_after>/*
  Q Light Controller Plus
  main.cpp

  Copyright (c) Massimo Callegari

  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.txt

  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 <QApplication>
#include <QCommandLineParser>
#include <QQmlApplicationEngine>

#include "app.h"
#include "qlcconfig.h"

void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    Q_UNUSED(context)
    Q_UNUSED(type)

    QByteArray localMsg = msg.toLocal8Bit();
    //if (type >= QtSystemMsg)
    {
        fprintf(stderr, "%s\n", localMsg.constData());
        fflush(stderr);
    }
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QApplication::setOrganizationName("qlcplus");
    QApplication::setOrganizationDomain("org");
    QApplication::setApplicationName(APPNAME);
    QApplication::setApplicationVersion(QString(APPVERSION));

    QCommandLineParser parser;
    parser.setApplicationDescription("Q Light Controller Plus");

    parser.addHelpOption();
    parser.addVersionOption();
    QCommandLineOption debugOption(QStringList() << "d" << "debug",
                                      "Enable debug messages.");
    parser.addOption(debugOption);

    QCommandLineOption openFileOption(QStringList() << "o" << "open",
                                      "Specify a file to open.",
                                      "filename", "");
    parser.addOption(openFileOption);

    parser.process(app);

    if (parser.isSet(debugOption))
        qInstallMessageHandler(debugMessageHandler);

    App qlcplusApp;
    qlcplusApp.startup();
    qlcplusApp.show();

    QString filename = parser.value(openFileOption);
    if (filename.isEmpty() == false)
        qlcplusApp.loadWorkspace(filename);

    return app.exec();
}
<|endoftext|>