<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#include <uielement/uielement.hxx>

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#include <com/sun/star/ui/DockingArea.hpp>

//_________________________________________________________________________________________________________________
//  namespace
//_________________________________________________________________________________________________________________

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

namespace framework
{

    bool UIElement::operator< ( const ::framework::UIElement& aUIElement ) const
{
    if ( !m_xUIElement.is() && aUIElement.m_xUIElement.is() )
        return false;
    else if ( m_xUIElement.is() && !aUIElement.m_xUIElement.is() )
        return true;
    else if ( !m_bVisible && aUIElement.m_bVisible )
        return false;
    else if ( m_bVisible && !aUIElement.m_bVisible )
        return true;
    else if ( !m_bFloating && aUIElement.m_bFloating )
        return true;
    else if ( m_bFloating && !aUIElement.m_bFloating )
        return false;
    else
    {
        if ( m_bFloating )
        {
            bool bEqual = ( m_aFloatingData.m_aPos.Y == aUIElement.m_aFloatingData.m_aPos.Y );
            if ( bEqual )
                return ( m_aFloatingData.m_aPos.X < aUIElement.m_aFloatingData.m_aPos.X );
            else
                return ( m_aFloatingData.m_aPos.Y < aUIElement.m_aFloatingData.m_aPos.Y );
        }
        else
        {
            if ( m_aDockedData.m_nDockedArea < aUIElement.m_aDockedData.m_nDockedArea )
                return true;
            else if ( m_aDockedData.m_nDockedArea > aUIElement.m_aDockedData.m_nDockedArea )
                return false;
            else
            {
                if ( m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP ||
                     m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
                {
                    if ( !( m_aDockedData.m_aPos.Y == aUIElement.m_aDockedData.m_aPos.Y ) )
                        return  ( m_aDockedData.m_aPos.Y < aUIElement.m_aDockedData.m_aPos.Y );
                    else
                    {
                        bool bEqual = ( m_aDockedData.m_aPos.X == aUIElement.m_aDockedData.m_aPos.X );
                        if ( bEqual )
                        {
                            if ( m_bUserActive && !aUIElement.m_bUserActive )
                                return sal_True;
                            else if ( !m_bUserActive && aUIElement.m_bUserActive )
                                return sal_False;
                            else
                                return sal_False;
                        }
                        else
                            return ( m_aDockedData.m_aPos.X <= aUIElement.m_aDockedData.m_aPos.X );
                    }
                }
                else
                {
                    if ( !( m_aDockedData.m_aPos.X == aUIElement.m_aDockedData.m_aPos.X ) )
                        return ( m_aDockedData.m_aPos.X < aUIElement.m_aDockedData.m_aPos.X );
                    else
                    {
                        bool bEqual = ( m_aDockedData.m_aPos.Y == aUIElement.m_aDockedData.m_aPos.Y );
                        if ( bEqual )
                        {
                            if ( m_bUserActive && !aUIElement.m_bUserActive )
                                return sal_True;
                            else if ( !m_bUserActive && aUIElement.m_bUserActive )
                                return sal_False;
                            else
                                return sal_False;
                        }
                        else
                            return ( m_aDockedData.m_aPos.Y <= aUIElement.m_aDockedData.m_aPos.Y );
                    }
                }
            }
        }
    }
}

UIElement& UIElement::operator= ( const UIElement& rUIElement )
{
    if (&rUIElement != this)
    {
        m_aType             = rUIElement.m_aType;
        m_aName             = rUIElement.m_aName;
        m_aUIName           = rUIElement.m_aUIName;
        m_xUIElement        = rUIElement.m_xUIElement;
        m_bFloating         = rUIElement.m_bFloating;
        m_bVisible          = rUIElement.m_bVisible;
        m_bUserActive       = rUIElement.m_bUserActive;
        m_bCreateNewRowCol0 = rUIElement.m_bCreateNewRowCol0;
        m_bDeactiveHide     = rUIElement.m_bDeactiveHide;
        m_bMasterHide       = rUIElement.m_bMasterHide;
        m_bContextSensitive = rUIElement.m_bContextSensitive;
        m_bContextActive    = rUIElement.m_bContextActive;
        m_bNoClose          = rUIElement.m_bNoClose;
        m_bSoftClose        = rUIElement.m_bSoftClose;
        m_bStateRead        = rUIElement.m_bStateRead;
        m_nStyle            = rUIElement.m_nStyle;
        m_aDockedData       = rUIElement.m_aDockedData;
        m_aFloatingData     = rUIElement.m_aFloatingData;
    }
    return *this;
}

} // namespace framework

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>WaE: duplicateBranch<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#include <uielement/uielement.hxx>

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#include <com/sun/star/ui/DockingArea.hpp>

//_________________________________________________________________________________________________________________
//  namespace
//_________________________________________________________________________________________________________________

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

namespace framework
{

    bool UIElement::operator< ( const ::framework::UIElement& aUIElement ) const
{
    if ( !m_xUIElement.is() && aUIElement.m_xUIElement.is() )
        return false;
    else if ( m_xUIElement.is() && !aUIElement.m_xUIElement.is() )
        return true;
    else if ( !m_bVisible && aUIElement.m_bVisible )
        return false;
    else if ( m_bVisible && !aUIElement.m_bVisible )
        return true;
    else if ( !m_bFloating && aUIElement.m_bFloating )
        return true;
    else if ( m_bFloating && !aUIElement.m_bFloating )
        return false;
    else
    {
        if ( m_bFloating )
        {
            bool bEqual = ( m_aFloatingData.m_aPos.Y == aUIElement.m_aFloatingData.m_aPos.Y );
            if ( bEqual )
                return ( m_aFloatingData.m_aPos.X < aUIElement.m_aFloatingData.m_aPos.X );
            else
                return ( m_aFloatingData.m_aPos.Y < aUIElement.m_aFloatingData.m_aPos.Y );
        }
        else
        {
            if ( m_aDockedData.m_nDockedArea < aUIElement.m_aDockedData.m_nDockedArea )
                return true;
            else if ( m_aDockedData.m_nDockedArea > aUIElement.m_aDockedData.m_nDockedArea )
                return false;
            else
            {
                if ( m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP ||
                     m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
                {
                    if ( !( m_aDockedData.m_aPos.Y == aUIElement.m_aDockedData.m_aPos.Y ) )
                        return  ( m_aDockedData.m_aPos.Y < aUIElement.m_aDockedData.m_aPos.Y );
                    else
                    {
                        bool bEqual = ( m_aDockedData.m_aPos.X == aUIElement.m_aDockedData.m_aPos.X );
                        if ( bEqual )
                        {
                            if ( m_bUserActive && !aUIElement.m_bUserActive )
                                return sal_True;
                            else
                                return sal_False;
                        }
                        else
                            return ( m_aDockedData.m_aPos.X <= aUIElement.m_aDockedData.m_aPos.X );
                    }
                }
                else
                {
                    if ( !( m_aDockedData.m_aPos.X == aUIElement.m_aDockedData.m_aPos.X ) )
                        return ( m_aDockedData.m_aPos.X < aUIElement.m_aDockedData.m_aPos.X );
                    else
                    {
                        bool bEqual = ( m_aDockedData.m_aPos.Y == aUIElement.m_aDockedData.m_aPos.Y );
                        if ( bEqual )
                        {
                            if ( m_bUserActive && !aUIElement.m_bUserActive )
                                return sal_True;
                            else
                                return sal_False;
                        }
                        else
                            return ( m_aDockedData.m_aPos.Y <= aUIElement.m_aDockedData.m_aPos.Y );
                    }
                }
            }
        }
    }
}

UIElement& UIElement::operator= ( const UIElement& rUIElement )
{
    if (&rUIElement != this)
    {
        m_aType             = rUIElement.m_aType;
        m_aName             = rUIElement.m_aName;
        m_aUIName           = rUIElement.m_aUIName;
        m_xUIElement        = rUIElement.m_xUIElement;
        m_bFloating         = rUIElement.m_bFloating;
        m_bVisible          = rUIElement.m_bVisible;
        m_bUserActive       = rUIElement.m_bUserActive;
        m_bCreateNewRowCol0 = rUIElement.m_bCreateNewRowCol0;
        m_bDeactiveHide     = rUIElement.m_bDeactiveHide;
        m_bMasterHide       = rUIElement.m_bMasterHide;
        m_bContextSensitive = rUIElement.m_bContextSensitive;
        m_bContextActive    = rUIElement.m_bContextActive;
        m_bNoClose          = rUIElement.m_bNoClose;
        m_bSoftClose        = rUIElement.m_bSoftClose;
        m_bStateRead        = rUIElement.m_bStateRead;
        m_nStyle            = rUIElement.m_nStyle;
        m_aDockedData       = rUIElement.m_aDockedData;
        m_aFloatingData     = rUIElement.m_aFloatingData;
    }
    return *this;
}

} // namespace framework

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdI18nApplication.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "mvdAlgorithm.h"
#include "mvdDatasetModel.h"
#include "mvdSystemError.h"
#include "mvdVectorImageModel.h"

namespace mvd
{
/*
  TRANSLATOR mvd::I18nApplication

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

const char* I18nApplication::DEFAULT_CACHE_DIR_NAME = "mvd2";

const char* I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME = "result";

const char* I18nApplication::DATASET_EXT = ".ds";

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*******************************************************************************/
bool
I18nApplication
::IsCacheDirValid( const QString& path )
{
  QDir dir( path );
  QFileInfo fileInfo( path );

  return
    fileInfo.exists() &&
    fileInfo.isDir() &&
    fileInfo.isReadable() &&
    fileInfo.isWritable() &&
    dir.dirName()==I18nApplication::DEFAULT_CACHE_DIR_NAME;
}

/*******************************************************************************/
bool
I18nApplication
::MakeDirTree( const QString& path, const QString& tree )
{
  QDir pathDir( path );

  /*
  qDebug() << path;
  qDebug() << pathDir.currentPath();
  qDebug() << pathDir.path();
  */

  if( !pathDir.exists() )
    throw SystemError( ToStdString( QString( "('%1')" ).arg( path ) ) );

  QDir treeDir( pathDir.filePath( tree ) );
  if( treeDir.exists() )
    return false;

  if( !pathDir.mkpath( tree ) )
    throw SystemError(
      ToStdString(
	QString( "('%1')" ).arg( pathDir.filePath( tree ) )
      )
    );

  return true;
}

/*****************************************************************************/
void
I18nApplication
::DatasetPathName( QString& path,
		   QString& name,
		   const QString& imageFilename )
{
  // '/tmp/archive.tar.gz'
  QFileInfo fileInfo( imageFilename );

#if 0
  // Dataset is stored into image-file path.
  // E.g. '/tmp'
  path = fileInfo.path();
#else
  // Dataset is stored into application cache-directory.
  // E.g. '$HOME/<CACHE_DIR>'
  path = I18nApplication::Instance()->GetCacheDir().path();
#endif

  // '[_tmp_]archive.tar.gz.<SUFFIX>'
  name =
#if 1
    fileInfo.canonicalPath().replace( QRegExp( "[/\\\\:]+" ), "_") +
    "_" +
#endif
    fileInfo.fileName() +
    I18nApplication::DATASET_EXT;
}

/*****************************************************************************/
DatasetModel*
I18nApplication
::LoadDatasetModel( const QString& imageFilename,
		    int width,
		    int height )
{
  // New model.
  DatasetModel* model = new DatasetModel();

  // Retrive path and name.
  QString path;
  QString name;

  I18nApplication::DatasetPathName( path, name, imageFilename );
  qDebug() << "Dataset path: " << path;
  qDebug() << "Dataset name: " << name;

  // Setup QObject
  model->setObjectName( QDir( path ).filePath( name ) );

  try
    {
    // try if the filename is valid
    VectorImageModel::EnsureValidImage(imageFilename);

    // get the basename from the filename to be used as an Alias
    QFileInfo finfo( imageFilename );

    // Build model (relink to cached data).
    DatasetModel::BuildContext context( path, name, finfo.baseName(), width, height );
    model->BuildModel( &context );

    // Load image if DatasetModel is empty.
    if( !model->HasSelectedImageModel() )
      {
      // Import image from filename given (w; h) size to choose
      // best-fit resolution.
      model->ImportImage( imageFilename, width, height );
      }
    }

  catch( std::exception& exc )
    {
    delete model;
    model = NULL;

    throw;
    }

  return model;
}

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
I18nApplication
::I18nApplication( int& argc, char** argv ) :
  QApplication( argc, argv ),
  m_CacheDir(),
  m_Settings( NULL ),
  m_Model( NULL ),
  m_IsRunningFromBuildDir( false )
{
}

/*******************************************************************************/
I18nApplication
::~I18nApplication()
{
}

/*******************************************************************************/
void
I18nApplication
::Initialize()
{
  // Initialize internationlization.
  InitializeLocale();

  //
  // Force numeric options of locale to "C"
  // See issue #635
  //
  // TODO: Move into I18nApplication.
  setlocale( LC_NUMERIC, "C" );

  // Initialize QCoreApplication.
  virtual_InitializeCore();

  // Initialize settings.
  InitializeSettings();
}

/*******************************************************************************/
void
I18nApplication
::SetModel( AbstractModel* model )
{
  emit AboutToChangeModel( model );

  delete m_Model;

  m_Model = model;

  if( model!=NULL )
    m_Model->setParent( this );

  emit ModelChanged( m_Model );
}

/*******************************************************************************/
bool
I18nApplication
::MakeCacheDir( const QString& cacheDirStr )
{
  qDebug() << this << "::MakeCacheDir(" << cacheDirStr << ")";

  QDir homeDir (cacheDirStr);

  if (!homeDir.exists())
    SystemError( ToStdString( QString( "('%1')" ).arg( homeDir.path() ) ) );

  bool isNew = I18nApplication::MakeDirTree(
    homeDir.path(), I18nApplication::DEFAULT_CACHE_DIR_NAME );

  QDir cacheDir( homeDir );

  if( !cacheDir.cd( I18nApplication::DEFAULT_CACHE_DIR_NAME ) )
    throw SystemError(
      ToStdString(
	QString( "('%1')" ).arg(
	  homeDir.filePath( I18nApplication::DEFAULT_CACHE_DIR_NAME )
	)
      )
    );

  m_CacheDir = cacheDir;

  StoreSettingsKey( "cacheDir", QDir::cleanPath( m_CacheDir.path() ) );

  return isNew;
}

/*******************************************************************************/
bool
I18nApplication
::MakeResultCacheDir( const QString& cacheDirStr )
{
  //
  QDir homeDir (cacheDirStr);

  //
  // create result directory in  CacheDir
  QDir cacheDir( homeDir.filePath( I18nApplication::DEFAULT_CACHE_DIR_NAME ) );
  QDir resultDir(cacheDir.filePath ( I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME ) );

  if ( !resultDir.exists() &&
       !cacheDir.mkpath( I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME ) )
    {
    throw SystemError(
      ToStdString(
	QString( "('%1')" ).arg( cacheDir.filePath(I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME ) )
        )
      );
    }

  return true;
}

/*******************************************************************************/
void
I18nApplication
::InitializeLocale()
{
  QTextCodec::setCodecForTr( QTextCodec::codecForName( "utf8" ) );

  //
  // 1. default UI language is english (no translation).
  QLocale sys_lc( QLocale::system() );
  if( sys_lc.language() == QLocale::C ||
      ( sys_lc.language() == QLocale::English &&
        sys_lc.country() == QLocale::UnitedStates ) )
    {
    return;
    }

  //
  // 2. Choose i18n path between build dir and install dir.

  // Begin from the executable path
  QDir bin_dir( QDir::cleanPath(QCoreApplication::applicationDirPath()) );
  qDebug() << tr( "Executable dir : %1" ).arg( bin_dir.path() );

  // Go up in the directory hierarchy until we have a candidate install prefix
  bool prefixFound = false;
  QDir prefix( bin_dir );
  while ( prefix.cdUp() )
    {
    if ( QDir(prefix).cd(Monteverdi2_INSTALL_BIN_DIR) )
      {
      prefixFound = true;
      break;
      }
    }

  if (prefixFound)
    {
    qDebug() << tr( "Candidate install prefix found : %1" ).arg( prefix.path() );
    }
  else
    {
    QString message( tr( "Unable to locate translation files" ) );
    qDebug() << message;
    QMessageBox::critical( NULL, tr( "Critical error" ), message );
    return;
    }

  QDir i18n_dir;

  // At this point the candidate install prefix can also be the build dir root
  if ( prefix.exists( Monteverdi2_CONFIGURE_FILE )
       && prefix.exists("i18n") )
    {
    m_IsRunningFromBuildDir = true;

    // Report found build dir root
    qDebug() << tr( "Running from build directory '%1'." ).arg( prefix.path() );

    // Go into the i18n dir (it exists we just checked for it)
    i18n_dir = prefix;
    i18n_dir.cd("i18n");

    qDebug() << tr( "Using translation dir '%1'." ).arg( i18n_dir.path() );
    }
  else
    {
    m_IsRunningFromBuildDir = false;

    // Report found install prefix
    qDebug() << tr( "Running from install directory '%1'." ).arg( prefix.path() );

    // Go into the i18n dir configured at cmake-time
    i18n_dir = prefix;

    if (i18n_dir.cd(Monteverdi2_INSTALL_DATA_I18N_DIR))
      {
      qDebug() << tr( "Using translation dir '%1'." ).arg( i18n_dir.path() );
      }
    else
      {
      QString message( tr( "Failed to access translation-files directory '%1'" )
                       .arg(QDir::cleanPath(prefix.path()
                             + QDir::separator()
                             + Monteverdi2_INSTALL_DATA_I18N_DIR)) );
      qDebug() << message;
      QMessageBox::critical( NULL, tr( "Critical error" ), message );
      return;
      }
    }

  //
  // 3.1 Stack Qt translator.
  LoadAndInstallTranslator(
    "qt_" + sys_lc.name(),
    QLibraryInfo::location( QLibraryInfo::TranslationsPath  )
  );

  //
  // 3.2 Stack Monteverdi2 translator as prioritary over Qt translator.
  LoadAndInstallTranslator( sys_lc.name(), i18n_dir.path() );

  // TODO: Record locale translation filename(s) used in UI component (e.g.
  // AboutDialog, Settings dialog, Information dialog etc.)
}

/*******************************************************************************/
void
I18nApplication
::InitializeCore( const QString& appName,
		  const QString& appVersion,
		  const QString& orgName,
		  const QString& orgDomain )
{
  setObjectName( "Application" );

  //
  // Setup application tags.
  //
  QCoreApplication::setApplicationName(
    appName
  );
  QCoreApplication::setApplicationVersion(
    appVersion
  );

  //
  // Setup organization tags.
  //
  QCoreApplication::setOrganizationName( orgName );
  QCoreApplication::setOrganizationDomain( orgDomain );

#ifndef Q_WS_MAC
    setWindowIcon( QIcon( QLatin1String( ":/images/application_icon" ) ) );
#endif
}

/*******************************************************************************/
void
I18nApplication
::InitializeSettings()
{
  //
  // Create settings proxy.
  m_Settings = new QSettings(
    // TODO: Change QSettings::NativeFormat by QSettings::IniFormat.
    QSettings::NativeFormat,
    QSettings::UserScope,
    QCoreApplication::organizationName(),
    QCoreApplication::applicationName(),
    this
  );

  //
  // Restore cache directory.
  QVariant value( RetrieveSettingsKey( "cacheDir" ) );

  if( !value.isNull() )
    {
    QString path( value.toString() );

    qDebug() << "Settings/cacheDir:" << path;

    if( I18nApplication::IsCacheDirValid( path ) )
      {
      m_CacheDir.setPath( path );
      }
    }
}

/*******************************************************************************/
bool
I18nApplication
::LoadAndInstallTranslator(const QString& filename,
                           const QString& directory,
                           const QString& searchDelimiters,
                           const QString& suffix )
{
  QString filename_ext(
    filename +
    ( suffix.isNull()
      ? ".qm"
      : suffix )
  );

  // (a) Do need to new QTranslator() here!
  QTranslator* lc_translator = new QTranslator( this );

  if( !lc_translator->load( filename, directory, searchDelimiters, suffix ) )
    {
    QString message(
      tr( "Failed to load '%1' translation file from '%2'." )
      .arg( filename_ext )
      .arg( directory )
    );

    // TODO: Use log system to trace error while loading locale translation file.

    qWarning() << message;

    // TODO: morph into better HMI design.
#if defined( _DEBUG )
    QMessageBox::warning( NULL, tr( "Warning!" ), message );
#endif

    return false;
    }

  // (a) ...because QTranslator needs to be alive during the whole
  // lifespan of the application.
  QCoreApplication::installTranslator( lc_translator );

  QString message(
    tr( "Successfully loaded '%1' translation file from '%2'." )
    .arg( filename_ext )
    .arg( directory )
  );

  // TODO: Log locale translation filename used.

  qDebug() << message;

  return true;
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/

} // end namespace 'mvd'
<commit_msg>ENH: use the md5 hash of the filename to get the dataset directory name (thanks to JMK)<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdI18nApplication.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "mvdAlgorithm.h"
#include "mvdDatasetModel.h"
#include "mvdSystemError.h"
#include "mvdVectorImageModel.h"

namespace mvd
{
/*
  TRANSLATOR mvd::I18nApplication

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

const char* I18nApplication::DEFAULT_CACHE_DIR_NAME = "mvd2";

const char* I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME = "result";

const char* I18nApplication::DATASET_EXT = ".ds";

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*******************************************************************************/
bool
I18nApplication
::IsCacheDirValid( const QString& path )
{
  QDir dir( path );
  QFileInfo fileInfo( path );

  return
    fileInfo.exists() &&
    fileInfo.isDir() &&
    fileInfo.isReadable() &&
    fileInfo.isWritable() &&
    dir.dirName()==I18nApplication::DEFAULT_CACHE_DIR_NAME;
}

/*******************************************************************************/
bool
I18nApplication
::MakeDirTree( const QString& path, const QString& tree )
{
  QDir pathDir( path );

  /*
  qDebug() << path;
  qDebug() << pathDir.currentPath();
  qDebug() << pathDir.path();
  */

  if( !pathDir.exists() )
    throw SystemError( ToStdString( QString( "('%1')" ).arg( path ) ) );

  QDir treeDir( pathDir.filePath( tree ) );
  if( treeDir.exists() )
    return false;

  if( !pathDir.mkpath( tree ) )
    throw SystemError(
      ToStdString(
	QString( "('%1')" ).arg( pathDir.filePath( tree ) )
      )
    );

  return true;
}

/*****************************************************************************/
void
I18nApplication
::DatasetPathName( QString& path,
		   QString& name,
		   const QString& imageFilename )
{
  // convenient QFileInfo
  QFileInfo fileInfo( imageFilename );

  // Dataset is stored into application cache-directory.
  // E.g. '$HOME/<CACHE_DIR>'
  path = I18nApplication::Instance()->GetCacheDir().path();

  // get the md5 of the filename
  QByteArray result = QCryptographicHash::hash(imageFilename.toAscii(), QCryptographicHash::Md5);

  // store the md5 + the dataset extension at the end
  name = result.toHex() + I18nApplication::DATASET_EXT;
}

/*****************************************************************************/
DatasetModel*
I18nApplication
::LoadDatasetModel( const QString& imageFilename,
		    int width,
		    int height )
{
  // New model.
  DatasetModel* model = new DatasetModel();

  // Retrive path and name.
  QString path;
  QString name;

  I18nApplication::DatasetPathName( path, name, imageFilename );
  qDebug() << "Dataset path: " << path;
  qDebug() << "Dataset name: " << name;

  // Setup QObject
  model->setObjectName( QDir( path ).filePath( name ) );

  try
    {
    // try if the filename is valid
    VectorImageModel::EnsureValidImage(imageFilename);

    // get the basename from the filename to be used as an Alias
    QFileInfo finfo( imageFilename );

    // Build model (relink to cached data).
    DatasetModel::BuildContext context( path, name, finfo.baseName(), width, height );
    model->BuildModel( &context );

    // Load image if DatasetModel is empty.
    if( !model->HasSelectedImageModel() )
      {
      // Import image from filename given (w; h) size to choose
      // best-fit resolution.
      model->ImportImage( imageFilename, width, height );
      }
    }

  catch( std::exception& exc )
    {
    delete model;
    model = NULL;

    throw;
    }

  return model;
}

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
I18nApplication
::I18nApplication( int& argc, char** argv ) :
  QApplication( argc, argv ),
  m_CacheDir(),
  m_Settings( NULL ),
  m_Model( NULL ),
  m_IsRunningFromBuildDir( false )
{
}

/*******************************************************************************/
I18nApplication
::~I18nApplication()
{
}

/*******************************************************************************/
void
I18nApplication
::Initialize()
{
  // Initialize internationlization.
  InitializeLocale();

  //
  // Force numeric options of locale to "C"
  // See issue #635
  //
  // TODO: Move into I18nApplication.
  setlocale( LC_NUMERIC, "C" );

  // Initialize QCoreApplication.
  virtual_InitializeCore();

  // Initialize settings.
  InitializeSettings();
}

/*******************************************************************************/
void
I18nApplication
::SetModel( AbstractModel* model )
{
  emit AboutToChangeModel( model );

  delete m_Model;

  m_Model = model;

  if( model!=NULL )
    m_Model->setParent( this );

  emit ModelChanged( m_Model );
}

/*******************************************************************************/
bool
I18nApplication
::MakeCacheDir( const QString& cacheDirStr )
{
  qDebug() << this << "::MakeCacheDir(" << cacheDirStr << ")";

  QDir homeDir (cacheDirStr);

  if (!homeDir.exists())
    SystemError( ToStdString( QString( "('%1')" ).arg( homeDir.path() ) ) );

  bool isNew = I18nApplication::MakeDirTree(
    homeDir.path(), I18nApplication::DEFAULT_CACHE_DIR_NAME );

  QDir cacheDir( homeDir );

  if( !cacheDir.cd( I18nApplication::DEFAULT_CACHE_DIR_NAME ) )
    throw SystemError(
      ToStdString(
	QString( "('%1')" ).arg(
	  homeDir.filePath( I18nApplication::DEFAULT_CACHE_DIR_NAME )
	)
      )
    );

  m_CacheDir = cacheDir;

  StoreSettingsKey( "cacheDir", QDir::cleanPath( m_CacheDir.path() ) );

  return isNew;
}

/*******************************************************************************/
bool
I18nApplication
::MakeResultCacheDir( const QString& cacheDirStr )
{
  //
  QDir homeDir (cacheDirStr);

  //
  // create result directory in  CacheDir
  QDir cacheDir( homeDir.filePath( I18nApplication::DEFAULT_CACHE_DIR_NAME ) );
  QDir resultDir(cacheDir.filePath ( I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME ) );

  if ( !resultDir.exists() &&
       !cacheDir.mkpath( I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME ) )
    {
    throw SystemError(
      ToStdString(
	QString( "('%1')" ).arg( cacheDir.filePath(I18nApplication::DEFAULT_CACHE_RESULT_DIR_NAME ) )
        )
      );
    }

  return true;
}

/*******************************************************************************/
void
I18nApplication
::InitializeLocale()
{
  QTextCodec::setCodecForTr( QTextCodec::codecForName( "utf8" ) );

  //
  // 1. default UI language is english (no translation).
  QLocale sys_lc( QLocale::system() );
  if( sys_lc.language() == QLocale::C ||
      ( sys_lc.language() == QLocale::English &&
        sys_lc.country() == QLocale::UnitedStates ) )
    {
    return;
    }

  //
  // 2. Choose i18n path between build dir and install dir.

  // Begin from the executable path
  QDir bin_dir( QDir::cleanPath(QCoreApplication::applicationDirPath()) );
  qDebug() << tr( "Executable dir : %1" ).arg( bin_dir.path() );

  // Go up in the directory hierarchy until we have a candidate install prefix
  bool prefixFound = false;
  QDir prefix( bin_dir );
  while ( prefix.cdUp() )
    {
    if ( QDir(prefix).cd(Monteverdi2_INSTALL_BIN_DIR) )
      {
      prefixFound = true;
      break;
      }
    }

  if (prefixFound)
    {
    qDebug() << tr( "Candidate install prefix found : %1" ).arg( prefix.path() );
    }
  else
    {
    QString message( tr( "Unable to locate translation files" ) );
    qDebug() << message;
    QMessageBox::critical( NULL, tr( "Critical error" ), message );
    return;
    }

  QDir i18n_dir;

  // At this point the candidate install prefix can also be the build dir root
  if ( prefix.exists( Monteverdi2_CONFIGURE_FILE )
       && prefix.exists("i18n") )
    {
    m_IsRunningFromBuildDir = true;

    // Report found build dir root
    qDebug() << tr( "Running from build directory '%1'." ).arg( prefix.path() );

    // Go into the i18n dir (it exists we just checked for it)
    i18n_dir = prefix;
    i18n_dir.cd("i18n");

    qDebug() << tr( "Using translation dir '%1'." ).arg( i18n_dir.path() );
    }
  else
    {
    m_IsRunningFromBuildDir = false;

    // Report found install prefix
    qDebug() << tr( "Running from install directory '%1'." ).arg( prefix.path() );

    // Go into the i18n dir configured at cmake-time
    i18n_dir = prefix;

    if (i18n_dir.cd(Monteverdi2_INSTALL_DATA_I18N_DIR))
      {
      qDebug() << tr( "Using translation dir '%1'." ).arg( i18n_dir.path() );
      }
    else
      {
      QString message( tr( "Failed to access translation-files directory '%1'" )
                       .arg(QDir::cleanPath(prefix.path()
                             + QDir::separator()
                             + Monteverdi2_INSTALL_DATA_I18N_DIR)) );
      qDebug() << message;
      QMessageBox::critical( NULL, tr( "Critical error" ), message );
      return;
      }
    }

  //
  // 3.1 Stack Qt translator.
  LoadAndInstallTranslator(
    "qt_" + sys_lc.name(),
    QLibraryInfo::location( QLibraryInfo::TranslationsPath  )
  );

  //
  // 3.2 Stack Monteverdi2 translator as prioritary over Qt translator.
  LoadAndInstallTranslator( sys_lc.name(), i18n_dir.path() );

  // TODO: Record locale translation filename(s) used in UI component (e.g.
  // AboutDialog, Settings dialog, Information dialog etc.)
}

/*******************************************************************************/
void
I18nApplication
::InitializeCore( const QString& appName,
		  const QString& appVersion,
		  const QString& orgName,
		  const QString& orgDomain )
{
  setObjectName( "Application" );

  //
  // Setup application tags.
  //
  QCoreApplication::setApplicationName(
    appName
  );
  QCoreApplication::setApplicationVersion(
    appVersion
  );

  //
  // Setup organization tags.
  //
  QCoreApplication::setOrganizationName( orgName );
  QCoreApplication::setOrganizationDomain( orgDomain );

#ifndef Q_WS_MAC
    setWindowIcon( QIcon( QLatin1String( ":/images/application_icon" ) ) );
#endif
}

/*******************************************************************************/
void
I18nApplication
::InitializeSettings()
{
  //
  // Create settings proxy.
  m_Settings = new QSettings(
    // TODO: Change QSettings::NativeFormat by QSettings::IniFormat.
    QSettings::NativeFormat,
    QSettings::UserScope,
    QCoreApplication::organizationName(),
    QCoreApplication::applicationName(),
    this
  );

  //
  // Restore cache directory.
  QVariant value( RetrieveSettingsKey( "cacheDir" ) );

  if( !value.isNull() )
    {
    QString path( value.toString() );

    qDebug() << "Settings/cacheDir:" << path;

    if( I18nApplication::IsCacheDirValid( path ) )
      {
      m_CacheDir.setPath( path );
      }
    }
}

/*******************************************************************************/
bool
I18nApplication
::LoadAndInstallTranslator(const QString& filename,
                           const QString& directory,
                           const QString& searchDelimiters,
                           const QString& suffix )
{
  QString filename_ext(
    filename +
    ( suffix.isNull()
      ? ".qm"
      : suffix )
  );

  // (a) Do need to new QTranslator() here!
  QTranslator* lc_translator = new QTranslator( this );

  if( !lc_translator->load( filename, directory, searchDelimiters, suffix ) )
    {
    QString message(
      tr( "Failed to load '%1' translation file from '%2'." )
      .arg( filename_ext )
      .arg( directory )
    );

    // TODO: Use log system to trace error while loading locale translation file.

    qWarning() << message;

    // TODO: morph into better HMI design.
#if defined( _DEBUG )
    QMessageBox::warning( NULL, tr( "Warning!" ), message );
#endif

    return false;
    }

  // (a) ...because QTranslator needs to be alive during the whole
  // lifespan of the application.
  QCoreApplication::installTranslator( lc_translator );

  QString message(
    tr( "Successfully loaded '%1' translation file from '%2'." )
    .arg( filename_ext )
    .arg( directory )
  );

  // TODO: Log locale translation filename used.

  qDebug() << message;

  return true;
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/

} // end namespace 'mvd'
<|endoftext|>


<commit_before>#include <iostream>
#include <condition_variable>
#include <thread>
#include <queue>
#include <string>

std::mutex m;
std::queue<std::string> messages;
std::condition_variable data_condition;

void data_reading()
{
	std::string line;
	std::cout << "Input: (Empty line exits) ";
	while ( getline(std::cin, line) )
	{
		if ( line.empty() )
			break;
		std::lock_guard<std::mutex> lg(m);
		messages.push(line);
		data_condition.notify_one();
	}
}

void data_printing()
{
	while (true)
	{
		std::unique_lock<std::mutex> l(m);
		data_condition.wait( l, [] { return ! messages.empty(); });
		auto message = std::move(messages.front());
		messages.pop();
		l.unlock();
		std::cout << "READ: " << message << std::endl;
	}
}

int main(int argc, char* argv[])
{
	std::thread t_read(data_reading);
	std::thread t_print(data_printing);
	t_print.detach();
	t_read.join();
}

<commit_msg>Sleep now lets us fill the queue faster than it is emptied<commit_after>#include <iostream>
#include <condition_variable>
#include <thread>
#include <queue>
#include <string>

std::mutex m;
std::queue<std::string> messages;
std::condition_variable data_condition;

void data_reading()
{
	std::string line;
	std::cout << "Input: (Empty line exits) ";
	while ( getline(std::cin, line) )
	{
		std::lock_guard<std::mutex> lg(m);
		messages.push(line);
		data_condition.notify_one();
		if ( line.empty() )
			break;
	}
}

void data_printing()
{
	while (true)
	{
		std::unique_lock<std::mutex> l(m);
		data_condition.wait( l, [] { return ! messages.empty(); });
		auto message = std::move(messages.front());
		messages.pop();
		l.unlock();
		if ( message.empty() )
			break;
		std::cout << "READ: " << message << std::endl;
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
	}
}

int main(int argc, char* argv[])
{
	std::thread t_read(data_reading);
	std::thread t_print(data_printing);
	t_print.join();
	t_read.join();
}

<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TEST_COMPASS
#include "boost/test/unit_test.hpp"

#include <vector>
#include <iostream>
#include <string>
#include <algorithm>

#include "compass.hpp"
#include "compass_fixture.hpp"

BOOST_AUTO_TEST_SUITE( compass_fundamentals )

BOOST_AUTO_TEST_CASE( compass_works_at_runtime ){

  auto value = compass::runtime::works();

  BOOST_CHECK(value);

}

BOOST_AUTO_TEST_CASE( compass_yields_vendor_name ){

  auto value = compass::runtime::vendor();
  BOOST_CHECK_NE(value.size(),0u);

}
BOOST_AUTO_TEST_SUITE_END()

BOOST_FIXTURE_TEST_SUITE( machine_specific, host_reference )

BOOST_AUTO_TEST_CASE( vendor_right  ){

  auto value = compass::runtime::vendor();

  BOOST_CHECK_NE(value.size(),0u);

  std::transform(value.begin(), value.end(),
         value.begin(),
         ::tolower);

  BOOST_CHECK(value.find(expected_vendor)!=std::string::npos);

}

BOOST_AUTO_TEST_CASE( brand_right  ){

  auto value = compass::runtime::brand();

  BOOST_CHECK_NE(value.size(),0u);

  BOOST_CHECK_MESSAGE(value.find(expected_brand)!=std::string::npos,
                      "[brand retrieved]\t_" << value.c_str() << "_");

}

BOOST_AUTO_TEST_CASE( device_name_right  ){

  auto value = compass::runtime::device_name();

  BOOST_CHECK_NE(value.size(),0u);

  BOOST_CHECK_MESSAGE(value.find(expected_device_name)!=std::string::npos,
                      "[device_name]\t_"<<value<<"_ is not "<< expected_device_name);

}

BOOST_AUTO_TEST_CASE( ncores_right  ){

  auto value = compass::runtime::ncores();

  BOOST_CHECK_NE(value,0);
  BOOST_CHECK_EQUAL(value,expected_ncores);
}

BOOST_AUTO_TEST_CASE( has_sse_right  ){

  auto value = compass::runtime::has(compass::feature::sse());

  BOOST_CHECK_EQUAL(value,expected_has_sse);

}

BOOST_AUTO_TEST_CASE( has_sse2_right  ){

  auto value = compass::runtime::has(compass::feature::sse2());

  BOOST_CHECK_EQUAL(value,expected_has_sse2);

}

BOOST_AUTO_TEST_CASE( has_sse3_right  ){

  auto value = compass::runtime::has(compass::feature::sse3());

  BOOST_CHECK_EQUAL(value,expected_has_sse3);

}

BOOST_AUTO_TEST_CASE( has_sse4_right  ){

  auto value = compass::runtime::has(compass::feature::sse4());

  BOOST_CHECK_EQUAL(value,expected_has_sse4);

}

BOOST_AUTO_TEST_CASE( has_avx_right  ){

  auto value = compass::runtime::has(compass::feature::avx());

  BOOST_CHECK_EQUAL(value,expected_has_avx);

}

BOOST_AUTO_TEST_CASE( has_avx2_right  ){

  auto value = compass::runtime::has(compass::feature::avx2());

  BOOST_CHECK_EQUAL(value,expected_has_avx2);

}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>added error message to avx2 test<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TEST_COMPASS
#include "boost/test/unit_test.hpp"

#include <vector>
#include <iostream>
#include <string>
#include <algorithm>

#include "compass.hpp"
#include "compass_fixture.hpp"

BOOST_AUTO_TEST_SUITE( compass_fundamentals )

BOOST_AUTO_TEST_CASE( compass_works_at_runtime ){

  auto value = compass::runtime::works();

  BOOST_CHECK(value);

}

BOOST_AUTO_TEST_CASE( compass_yields_vendor_name ){

  auto value = compass::runtime::vendor();
  BOOST_CHECK_NE(value.size(),0u);

}
BOOST_AUTO_TEST_SUITE_END()

BOOST_FIXTURE_TEST_SUITE( machine_specific, host_reference )

BOOST_AUTO_TEST_CASE( vendor_right  ){

  auto value = compass::runtime::vendor();

  BOOST_CHECK_NE(value.size(),0u);

  std::transform(value.begin(), value.end(),
         value.begin(),
         ::tolower);

  BOOST_CHECK(value.find(expected_vendor)!=std::string::npos);

}

BOOST_AUTO_TEST_CASE( brand_right  ){

  auto value = compass::runtime::brand();

  BOOST_CHECK_NE(value.size(),0u);

  BOOST_CHECK_MESSAGE(value.find(expected_brand)!=std::string::npos,
                      "[brand retrieved]\t_" << value.c_str() << "_");

}

BOOST_AUTO_TEST_CASE( device_name_right  ){

  auto value = compass::runtime::device_name();

  BOOST_CHECK_NE(value.size(),0u);

  BOOST_CHECK_MESSAGE(value.find(expected_device_name)!=std::string::npos,
                      "[device_name]\t_"<<value<<"_ is not "<< expected_device_name);

}

BOOST_AUTO_TEST_CASE( ncores_right  ){

  auto value = compass::runtime::ncores();

  BOOST_CHECK_NE(value,0);
  BOOST_CHECK_EQUAL(value,expected_ncores);
}

BOOST_AUTO_TEST_CASE( has_sse_right  ){

  auto value = compass::runtime::has(compass::feature::sse());

  BOOST_CHECK_EQUAL(value,expected_has_sse);

}

BOOST_AUTO_TEST_CASE( has_sse2_right  ){

  auto value = compass::runtime::has(compass::feature::sse2());

  BOOST_CHECK_EQUAL(value,expected_has_sse2);

}

BOOST_AUTO_TEST_CASE( has_sse3_right  ){

  auto value = compass::runtime::has(compass::feature::sse3());

  BOOST_CHECK_EQUAL(value,expected_has_sse3);

}

BOOST_AUTO_TEST_CASE( has_sse4_right  ){

  auto value = compass::runtime::has(compass::feature::sse4());

  BOOST_CHECK_EQUAL(value,expected_has_sse4);

}

BOOST_AUTO_TEST_CASE( has_avx_right  ){

  auto value = compass::runtime::has(compass::feature::avx());

  BOOST_CHECK_EQUAL(value,expected_has_avx);

}

BOOST_AUTO_TEST_CASE( has_avx2_right  ){

  auto value = compass::runtime::has(compass::feature::avx2());

  BOOST_CHECK_MESSAGE(value==expected_has_avx2, "detected " << (value ? "AVX2" : "no AVX2") << " on " << hostname << " (expected: " <<  (expected_has_avx2 ? "AVX2" : "no AVX2"));

}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkLevelWindow.h"
#include "mitkImageSliceSelector.h"

#include <ipFunc/ipFunc.h>
#include <algorithm>

mitk::LevelWindow::LevelWindow(mitk::ScalarType level, mitk::ScalarType window) : m_Min(level-window/2.0), m_Max(level+window/2.0), m_RangeMin(-1024), m_RangeMax(4096)
{

}

mitk::LevelWindow::LevelWindow(const mitk::LevelWindow& levWin)
{
  *this=levWin;
}

mitk::LevelWindow::~LevelWindow()
{
}

mitk::ScalarType mitk::LevelWindow::GetLevel() const
{
  return (m_Max-m_Min)/2.0 + m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetWindow() const
{
  return (m_Max-m_Min);
}

mitk::ScalarType mitk::LevelWindow::GetMin() const
{
  return m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetMax() const
{
  return m_Max;
}

void mitk::LevelWindow::SetLevel(mitk::ScalarType level)
{
  mitk::ScalarType halfWindow = (m_Max - m_Min) / 2;
  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetWindow(mitk::ScalarType window)
{
  mitk::ScalarType level = m_Min + (m_Max - m_Min) / 2;
  mitk::ScalarType halfWindow = window / 2;

  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetLevelWindow(mitk::ScalarType level, mitk::ScalarType window)
{
  m_Min = level - window / 2.0;
  m_Max = level + window / 2.0;

  testValues();
}

void mitk::LevelWindow::SetMin(mitk::ScalarType min)
{
  m_Min = min;
  testValues();
}

void mitk::LevelWindow::SetMax(mitk::ScalarType max)
{
  m_Max = max;
  testValues();
}

void mitk::LevelWindow::SetMinMax(mitk::ScalarType min, mitk::ScalarType max)
{
  if(min>max)
    std::swap(min,max);

  SetMin(min);
  SetMax(max);
}

void mitk::LevelWindow::SetRangeMin(mitk::ScalarType min)
{
  m_RangeMin = min;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

void mitk::LevelWindow::SetRangeMax(mitk::ScalarType max)
{
  m_RangeMax = max;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

mitk::ScalarType mitk::LevelWindow::GetRangeMin() const
{
  return m_RangeMin;
}

mitk::ScalarType mitk::LevelWindow::GetRangeMax() const
{
  return m_RangeMax;
}

mitk::ScalarType mitk::LevelWindow::GetRange() const
{
  return  m_RangeMax - m_RangeMin;
}

/*!
This method initializes a mitk::LevelWindow from an mitk::Image. The algorithm is as follows:

Default to taking the central image slice for quick analysis.

Compute the smallest (minValue), second smallest (min2ndValue), second largest (max2ndValue), and
largest (maxValue) data value by traversing the pixel values only once. In the
same scan it also computes the count of minValue values and maxValue values.
After that a basic histogram with specific information about the
extrems is complete.

If minValue == maxValue, the center slice is uniform and the above scan is repeated for
the complete image, not just one slice

Next, special cases of images with only 1, 2 or 3 distinct data values
have hand assigned level window ranges.

Next the level window is set relative to the inner range IR = lengthOf([min2ndValue, max2ndValue])

For count(minValue) > 20% the smallest values are frequent and should be
distinct from the min2ndValue and larger values (minValue may be std:min, may signify
something special) hence the lower end of the level window is set to min2ndValue - 0.5 * IR

For count(minValue) <= 20% the smallest values are not so important and can
blend with the next ones => min(level window) = min2ndValue

And analog for max(level window):
count(max2ndValue) > 20%:  max(level window) = max2ndValue + 0.5 * IR
count(max2ndValue) < 20%:  max(level window) = max2ndValue

In both 20%+ cases the level window bounds are clamped to the [minValue, maxValue] range

In consequence the level window maximizes contrast with minimal amount of
computation and does do useful things if the data contains std::min or
std:max values or has only 1 or 2 or 3 data values.
*/
void mitk::LevelWindow::SetAuto(mitk::Image* image, bool tryPicTags, bool guessByCentralSlice)
{
    if ( image == NULL )
        return;

    if ( tryPicTags )
    {
        if ( SetAutoByPicTags(image->GetPic()) )
            return;
    }

    mitk::Image* wholeImage = image;
    mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
    if ( guessByCentralSlice )
    {
        sliceSelector->SetInput(image);
        sliceSelector->SetSliceNr(image->GetDimension(2)/2);
        sliceSelector->SetTimeNr(image->GetDimension(3)/2);
        sliceSelector->SetChannelNr(image->GetDimension(4)/2);
        sliceSelector->Update();

        image = sliceSelector->GetOutput();
    }
    ScalarType minValue    = image->GetScalarValueMin();
    ScalarType maxValue    = image->GetScalarValueMaxNoRecompute();
    ScalarType min2ndValue = image->GetScalarValue2ndMinNoRecompute();
    ScalarType max2ndValue = image->GetScalarValue2ndMaxNoRecompute();
    unsigned int numPixelsInSlice = image->GetDimensions()[0];
    for ( unsigned int k=0;  k<image->GetDimension();  ++k ) numPixelsInSlice *= image->GetDimensions()[k];
    unsigned int minCount = image->GetCountOfMinValuedVoxelsNoRecompute();
    unsigned int maxCount = image->GetCountOfMaxValuedVoxelsNoRecompute();
    float minCountFraction = minCount/float(numPixelsInSlice);
    float maxCountFraction = maxCount/float(numPixelsInSlice);
    if ( minValue == maxValue )
    {
        // guessByCentralSlice seems to have failed, lets look at all data
        minValue    = wholeImage->GetScalarValueMin();
        maxValue    = wholeImage->GetScalarValueMaxNoRecompute();
        min2ndValue = wholeImage->GetScalarValue2ndMinNoRecompute();
        max2ndValue = wholeImage->GetScalarValue2ndMaxNoRecompute();
        unsigned int numPixelsInDataset = image->GetDimensions()[0];
        for ( unsigned int k=0;  k<image->GetDimension();  ++k ) numPixelsInDataset *= image->GetDimensions()[k];
        minCount = image->GetCountOfMinValuedVoxelsNoRecompute();
        maxCount = image->GetCountOfMaxValuedVoxelsNoRecompute();
        minCountFraction = minCount/float(numPixelsInDataset);
        maxCountFraction = maxCount/float(numPixelsInDataset);
    }
    //// uniform image
    if ( minValue == maxValue )
    {
        maxValue = minValue+1;
    }

    //// binary image
    else if ( min2ndValue == maxValue )
    {
        // noop; full range is fine
    }

    //// triple value image, put middle value in center of gray level ramp
    else if ( min2ndValue == max2ndValue )
    {
        ScalarType minDelta = std::min(min2ndValue-minValue, maxValue-min2ndValue);
        minValue = min2ndValue - minDelta;
        maxValue = min2ndValue + minDelta;
    }
    // now we can assume more than three distict scalar values

    else
    {
        ScalarType innerRange = max2ndValue - min2ndValue;
        //// lots of min values -> make different from rest, but not miles away
        if ( minCountFraction > 0.2 )
        {
            ScalarType halfInnerRangeGapMinValue = min2ndValue - innerRange/2.0;
            minValue = std::max(minValue, halfInnerRangeGapMinValue);
        }
        else
        //// few min values -> focus on innerRange
        {
            minValue = min2ndValue;
        }

        //// lots of max values -> make different from rest
        if ( maxCountFraction > 0.2 )
        {
            ScalarType halfInnerRangeGapMaxValue = max2ndValue + innerRange/2.0;
            maxValue = std::min(maxValue, halfInnerRangeGapMaxValue);
        }
        else
        //// few max values -> focus on innerRange
        {
            maxValue = max2ndValue;
        }
    }

  if(guessByCentralSlice)
  {
    mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
      sliceSelector->SetInput(image);
      sliceSelector->SetSliceNr(image->GetDimension(2)/2);
      sliceSelector->SetTimeNr(image->GetDimension(3)/2);
      sliceSelector->SetChannelNr(image->GetDimension(4)/2);
      sliceSelector->Update();

    mitk::Image* slice = sliceSelector->GetOutput();
    minValue = slice->GetScalarValue2ndMin();
    maxValue = slice->GetScalarValue2ndMaxNoRecompute();
    if (minValue == maxValue)
    {
        // guessByCentralSlice seems to have failed, lets look at all data
        minValue = image->GetScalarValue2ndMin();
        maxValue = image->GetScalarValue2ndMaxNoRecompute();
    }
  }
  else
  {
    minValue = image->GetScalarValue2ndMin();
    maxValue = image->GetScalarValue2ndMaxNoRecompute();
  }

  if (minValue == maxValue)
  {
    maxValue = minValue+1;
  }
  SetRangeMin(minValue);
  SetRangeMax(maxValue);
  SetMinMax(minValue, maxValue);
}

bool mitk::LevelWindow::SetAutoByPicTags(const ipPicDescriptor* aPic)
{
  ipPicDescriptor* pic = const_cast<ipPicDescriptor*>(aPic);
  if ( pic == NULL )
  {
    return false;
  }
  ipPicTSV_t *tsv = ipPicQueryTag( pic, "LEVEL/WINDOW" );
  if( tsv != NULL )
  {
    double level = 0;
    double window = 0;
    #define GET_C_W( type, tsv, C, W )    \
      level = ((type *)tsv->value)[0];    \
      window = ((type *)tsv->value)[1];

    ipPicFORALL_2( GET_C_W, tsv, level, window );

    SetLevelWindow( level, window );
    return true;
  }
  return false;
}

bool mitk::LevelWindow::operator==(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return true;
    }
  else {
    return false;
  }
}

bool mitk::LevelWindow::operator!=(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return false;
    }
  else {
    return true;
  }
}

mitk::LevelWindow& mitk::LevelWindow::operator=(const mitk::LevelWindow& levWin)
{
  if (this == &levWin) {
    return *this;
  }
  else {
    m_RangeMin = levWin.GetRangeMin();
    m_RangeMax = levWin.GetRangeMax();
    m_Min= levWin.GetMin();
    m_Max= levWin.GetMax();
    return *this;
  }
}
<commit_msg>FIX: the default range for level/window starts at -2048 now.<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkLevelWindow.h"
#include "mitkImageSliceSelector.h"

#include <ipFunc/ipFunc.h>
#include <algorithm>

mitk::LevelWindow::LevelWindow(mitk::ScalarType level, mitk::ScalarType window) : m_Min(level-window/2.0), m_Max(level+window/2.0), m_RangeMin(-2048), m_RangeMax(4096)
{

}

mitk::LevelWindow::LevelWindow(const mitk::LevelWindow& levWin)
{
  *this=levWin;
}

mitk::LevelWindow::~LevelWindow()
{
}

mitk::ScalarType mitk::LevelWindow::GetLevel() const
{
  return (m_Max-m_Min)/2.0 + m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetWindow() const
{
  return (m_Max-m_Min);
}

mitk::ScalarType mitk::LevelWindow::GetMin() const
{
  return m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetMax() const
{
  return m_Max;
}

void mitk::LevelWindow::SetLevel(mitk::ScalarType level)
{
  mitk::ScalarType halfWindow = (m_Max - m_Min) / 2;
  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetWindow(mitk::ScalarType window)
{
  mitk::ScalarType level = m_Min + (m_Max - m_Min) / 2;
  mitk::ScalarType halfWindow = window / 2;

  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetLevelWindow(mitk::ScalarType level, mitk::ScalarType window)
{
  m_Min = level - window / 2.0;
  m_Max = level + window / 2.0;

  testValues();
}

void mitk::LevelWindow::SetMin(mitk::ScalarType min)
{
  m_Min = min;
  testValues();
}

void mitk::LevelWindow::SetMax(mitk::ScalarType max)
{
  m_Max = max;
  testValues();
}

void mitk::LevelWindow::SetMinMax(mitk::ScalarType min, mitk::ScalarType max)
{
  if(min>max)
    std::swap(min,max);

  SetMin(min);
  SetMax(max);
}

void mitk::LevelWindow::SetRangeMin(mitk::ScalarType min)
{
  m_RangeMin = min;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

void mitk::LevelWindow::SetRangeMax(mitk::ScalarType max)
{
  m_RangeMax = max;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

mitk::ScalarType mitk::LevelWindow::GetRangeMin() const
{
  return m_RangeMin;
}

mitk::ScalarType mitk::LevelWindow::GetRangeMax() const
{
  return m_RangeMax;
}

mitk::ScalarType mitk::LevelWindow::GetRange() const
{
  return  m_RangeMax - m_RangeMin;
}

/*!
This method initializes a mitk::LevelWindow from an mitk::Image. The algorithm is as follows:

Default to taking the central image slice for quick analysis.

Compute the smallest (minValue), second smallest (min2ndValue), second largest (max2ndValue), and
largest (maxValue) data value by traversing the pixel values only once. In the
same scan it also computes the count of minValue values and maxValue values.
After that a basic histogram with specific information about the
extrems is complete.

If minValue == maxValue, the center slice is uniform and the above scan is repeated for
the complete image, not just one slice

Next, special cases of images with only 1, 2 or 3 distinct data values
have hand assigned level window ranges.

Next the level window is set relative to the inner range IR = lengthOf([min2ndValue, max2ndValue])

For count(minValue) > 20% the smallest values are frequent and should be
distinct from the min2ndValue and larger values (minValue may be std:min, may signify
something special) hence the lower end of the level window is set to min2ndValue - 0.5 * IR

For count(minValue) <= 20% the smallest values are not so important and can
blend with the next ones => min(level window) = min2ndValue

And analog for max(level window):
count(max2ndValue) > 20%:  max(level window) = max2ndValue + 0.5 * IR
count(max2ndValue) < 20%:  max(level window) = max2ndValue

In both 20%+ cases the level window bounds are clamped to the [minValue, maxValue] range

In consequence the level window maximizes contrast with minimal amount of
computation and does do useful things if the data contains std::min or
std:max values or has only 1 or 2 or 3 data values.
*/
void mitk::LevelWindow::SetAuto(mitk::Image* image, bool tryPicTags, bool guessByCentralSlice)
{
    if ( image == NULL )
        return;

    if ( tryPicTags )
    {
        if ( SetAutoByPicTags(image->GetPic()) )
            return;
    }

    mitk::Image* wholeImage = image;
    mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
    if ( guessByCentralSlice )
    {
        sliceSelector->SetInput(image);
        sliceSelector->SetSliceNr(image->GetDimension(2)/2);
        sliceSelector->SetTimeNr(image->GetDimension(3)/2);
        sliceSelector->SetChannelNr(image->GetDimension(4)/2);
        sliceSelector->Update();

        image = sliceSelector->GetOutput();
    }
    ScalarType minValue    = image->GetScalarValueMin();
    ScalarType maxValue    = image->GetScalarValueMaxNoRecompute();
    ScalarType min2ndValue = image->GetScalarValue2ndMinNoRecompute();
    ScalarType max2ndValue = image->GetScalarValue2ndMaxNoRecompute();
    unsigned int numPixelsInSlice = image->GetDimensions()[0];
    for ( unsigned int k=0;  k<image->GetDimension();  ++k ) numPixelsInSlice *= image->GetDimensions()[k];
    unsigned int minCount = image->GetCountOfMinValuedVoxelsNoRecompute();
    unsigned int maxCount = image->GetCountOfMaxValuedVoxelsNoRecompute();
    float minCountFraction = minCount/float(numPixelsInSlice);
    float maxCountFraction = maxCount/float(numPixelsInSlice);
    if ( minValue == maxValue )
    {
        // guessByCentralSlice seems to have failed, lets look at all data
        minValue    = wholeImage->GetScalarValueMin();
        maxValue    = wholeImage->GetScalarValueMaxNoRecompute();
        min2ndValue = wholeImage->GetScalarValue2ndMinNoRecompute();
        max2ndValue = wholeImage->GetScalarValue2ndMaxNoRecompute();
        unsigned int numPixelsInDataset = image->GetDimensions()[0];
        for ( unsigned int k=0;  k<image->GetDimension();  ++k ) numPixelsInDataset *= image->GetDimensions()[k];
        minCount = image->GetCountOfMinValuedVoxelsNoRecompute();
        maxCount = image->GetCountOfMaxValuedVoxelsNoRecompute();
        minCountFraction = minCount/float(numPixelsInDataset);
        maxCountFraction = maxCount/float(numPixelsInDataset);
    }
    //// uniform image
    if ( minValue == maxValue )
    {
        maxValue = minValue+1;
    }

    //// binary image
    else if ( min2ndValue == maxValue )
    {
        // noop; full range is fine
    }

    //// triple value image, put middle value in center of gray level ramp
    else if ( min2ndValue == max2ndValue )
    {
        ScalarType minDelta = std::min(min2ndValue-minValue, maxValue-min2ndValue);
        minValue = min2ndValue - minDelta;
        maxValue = min2ndValue + minDelta;
    }
    // now we can assume more than three distict scalar values

    else
    {
        ScalarType innerRange = max2ndValue - min2ndValue;
        //// lots of min values -> make different from rest, but not miles away
        if ( minCountFraction > 0.2 )
        {
            ScalarType halfInnerRangeGapMinValue = min2ndValue - innerRange/2.0;
            minValue = std::max(minValue, halfInnerRangeGapMinValue);
        }
        else
        //// few min values -> focus on innerRange
        {
            minValue = min2ndValue;
        }

        //// lots of max values -> make different from rest
        if ( maxCountFraction > 0.2 )
        {
            ScalarType halfInnerRangeGapMaxValue = max2ndValue + innerRange/2.0;
            maxValue = std::min(maxValue, halfInnerRangeGapMaxValue);
        }
        else
        //// few max values -> focus on innerRange
        {
            maxValue = max2ndValue;
        }
    }

  if(guessByCentralSlice)
  {
    mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
      sliceSelector->SetInput(image);
      sliceSelector->SetSliceNr(image->GetDimension(2)/2);
      sliceSelector->SetTimeNr(image->GetDimension(3)/2);
      sliceSelector->SetChannelNr(image->GetDimension(4)/2);
      sliceSelector->Update();

    mitk::Image* slice = sliceSelector->GetOutput();
    minValue = slice->GetScalarValue2ndMin();
    maxValue = slice->GetScalarValue2ndMaxNoRecompute();
    if (minValue == maxValue)
    {
        // guessByCentralSlice seems to have failed, lets look at all data
        minValue = image->GetScalarValue2ndMin();
        maxValue = image->GetScalarValue2ndMaxNoRecompute();
    }
  }
  else
  {
    minValue = image->GetScalarValue2ndMin();
    maxValue = image->GetScalarValue2ndMaxNoRecompute();
  }

  if (minValue == maxValue)
  {
    maxValue = minValue+1;
  }
  SetRangeMin(minValue);
  SetRangeMax(maxValue);
  SetMinMax(minValue, maxValue);
}

bool mitk::LevelWindow::SetAutoByPicTags(const ipPicDescriptor* aPic)
{
  ipPicDescriptor* pic = const_cast<ipPicDescriptor*>(aPic);
  if ( pic == NULL )
  {
    return false;
  }
  ipPicTSV_t *tsv = ipPicQueryTag( pic, "LEVEL/WINDOW" );
  if( tsv != NULL )
  {
    double level = 0;
    double window = 0;
    #define GET_C_W( type, tsv, C, W )    \
      level = ((type *)tsv->value)[0];    \
      window = ((type *)tsv->value)[1];

    ipPicFORALL_2( GET_C_W, tsv, level, window );

    SetLevelWindow( level, window );
    return true;
  }
  return false;
}

bool mitk::LevelWindow::operator==(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return true;
    }
  else {
    return false;
  }
}

bool mitk::LevelWindow::operator!=(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return false;
    }
  else {
    return true;
  }
}

mitk::LevelWindow& mitk::LevelWindow::operator=(const mitk::LevelWindow& levWin)
{
  if (this == &levWin) {
    return *this;
  }
  else {
    m_RangeMin = levWin.GetRangeMin();
    m_RangeMax = levWin.GetRangeMax();
    m_Min= levWin.GetMin();
    m_Max= levWin.GetMax();
    return *this;
  }
}
<|endoftext|>


<commit_before>#include "Base.h"
#include "GoogleStoreFront.h"
#include "storefront/StoreListener.h"
#include <jni.h>
#include <android_native_app_glue.h>

extern struct android_app* __state;
extern jclass __mainActivityClass;

namespace gameplay
{
    class GoogleStoreFront;
}

static gameplay::GoogleStoreFront * __instance = NULL;
static std::vector< gameplay::StoreProduct > __products;
static std::set<std::string> __requestedProducts;
static bool __iabEnabled = false;
static jmethodID __midQueueSKURequest;
static jmethodID __midFlushSkuDetailsQueue;
static jmethodID __midPurchaseItem;
static jmethodID __midRestorePurchases;

extern "C"
{

JNIEXPORT jint JNICALL GameplayJNI_OnLoad(JavaVM *vm, void *reserved)
{
    JNIEnv* env = NULL;
    vm->GetEnv((void **)&env, JNI_VERSION_1_6);

    __mainActivityClass = (jclass)env->NewGlobalRef(env->FindClass("org/gameplay3d/GamePlayNativeActivity"));
    __midQueueSKURequest = env->GetMethodID(__mainActivityClass, "queueSkuDetailsRequest", "(Ljava/lang/String;)V");
    __midFlushSkuDetailsQueue = env->GetMethodID(__mainActivityClass, "flushSkuDetailsQueue", "()V");
    __midPurchaseItem = env->GetMethodID(__mainActivityClass, "purchaseItem", "(Ljava/lang/String;)V");
    __midRestorePurchases = env->GetMethodID(__mainActivityClass, "restorePurchases", "()V");

    return JNI_VERSION_1_6;
}

// JNI stuff
JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_setIABEnabled(JNIEnv* env, jobject thiz)
{
    __iabEnabled = true;
}

JNIEXPORT int Java_org_gameplay3d_GamePlayNativeActivity_isItemConsumable(JNIEnv* env, jobject thiz, jstring sku)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    bool res = __instance->getListener()->isProductConsumable(productID);
    env->ReleaseStringUTFChars(sku, productID);

    return res ? 1 : 0;
}

JNIEXPORT int Java_org_gameplay3d_GamePlayNativeActivity_isSubscription(JNIEnv* env, jobject thiz, jstring sku)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    bool res = __instance->getListener()->isSubscription(productID);
    env->ReleaseStringUTFChars(sku, productID);

    return res ? 1 : 0;
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_itemRestored(JNIEnv* env, jobject thiz, jstring sku, jlong time, jstring orderId)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* orderID = env->GetStringUTFChars(orderId, NULL);

    __instance->getListener()->paymentTransactionRestoredEvent(productID, 1, time, orderID, NULL);

    env->ReleaseStringUTFChars(orderId, orderID);
    env->ReleaseStringUTFChars(sku, productID);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_itemPurchased(JNIEnv* env, jobject thiz, jstring sku, jlong time, jstring orderId)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* orderID = env->GetStringUTFChars(orderId, NULL);

    __instance->getListener()->paymentTransactionSucceededEvent(productID, 1, time, orderID, NULL);

    env->ReleaseStringUTFChars(orderId, orderID);
    env->ReleaseStringUTFChars(sku, productID);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_itemPurchaseFailed(JNIEnv* env, jobject thiz, jstring sku, jint error, jstring message)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* msg = env->GetStringUTFChars(message, NULL);

    __instance->getListener()->paymentTransactionFailedEvent(productID, 1, error, msg);

    env->ReleaseStringUTFChars(message, msg);
    env->ReleaseStringUTFChars(sku, productID);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_getProductsFailed(JNIEnv* env, jobject thiz, jint error, jstring message)
{
    const char* msg = env->GetStringUTFChars(message, NULL);
    if (__instance)
        __instance->getListener()->getProductsFailedEvent(error, msg);
    env->ReleaseStringUTFChars(message, msg);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_productValidated(JNIEnv* env, jobject thiz, jstring sku, jstring price, jstring title, jstring descr, jstring priceAmount, jstring priceCurrency)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* cPrice = env->GetStringUTFChars(price, NULL);
    const char* cTitle = env->GetStringUTFChars(title, NULL);
    const char* cDescr = env->GetStringUTFChars(descr, NULL);
    const char* cPriceAmount = env->GetStringUTFChars(priceAmount, NULL);
    const char* cPriceCurrency = env->GetStringUTFChars(priceCurrency, NULL);

    gameplay::StoreProduct product(productID, cTitle, cDescr, static_cast<float>(atoi(cPriceAmount)) * 0.000001f, cPrice, cPriceCurrency);
    __products.push_back(product);

    env->ReleaseStringUTFChars(sku, productID);
    env->ReleaseStringUTFChars(price, cPrice);
    env->ReleaseStringUTFChars(title, cTitle);
    env->ReleaseStringUTFChars(descr, cDescr);
    env->ReleaseStringUTFChars(priceAmount, cPriceAmount);
    env->ReleaseStringUTFChars(priceCurrency, cPriceCurrency);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_finishProductsValidation(JNIEnv* env, jobject thiz)
{
    std::vector<std::string> invalidProducts;
    for (const std::string &product : __requestedProducts)
    {
        if (std::find_if(__products.begin(), __products.end(), [&](const gameplay::StoreProduct& p){return p.id == product; }) == __products.end())
            invalidProducts.push_back(product);
    }

    __instance->getListener()->getProductsEvent(__products, invalidProducts);
}

}

namespace gameplay
{

GoogleStoreFront::GoogleStoreFront()
    : _listener( NULL )
{
    __instance = this;
}

GoogleStoreFront::~GoogleStoreFront()
{
}

void GoogleStoreFront::setListener(StoreListener * listener)
{
    _listener = listener;
}

StoreListener * GoogleStoreFront::getListener()
{
    return _listener;
}

void GoogleStoreFront::getProducts(const char ** productIDs) const
{
    __products.clear();
    __requestedProducts.clear();

    android_app* app = __state;
    JNIEnv* env = app->activity->env;
    JavaVM* vm = app->activity->vm;
    vm->AttachCurrentThread(&env, NULL);

    while (*productIDs)
    {
        __requestedProducts.insert(*productIDs);

        jstring paramString = env->NewStringUTF(*productIDs++);
        env->CallVoidMethod(app->activity->clazz, __midQueueSKURequest, paramString);
    }

    env->CallVoidMethod(app->activity->clazz, __midFlushSkuDetailsQueue);

    vm->DetachCurrentThread();
}

void GoogleStoreFront::makePayment(const char * productID, int quantity, const char * usernameHash)
{
    android_app* app = __state;
    JNIEnv* env = app->activity->env;
    JavaVM* vm = app->activity->vm;
    vm->AttachCurrentThread(&env, NULL);

    jstring paramString = env->NewStringUTF(productID);

    while (quantity-- > 0)
        env->CallVoidMethod(app->activity->clazz, __midPurchaseItem, paramString);

    vm->DetachCurrentThread();

    getListener()->paymentTransactionInProcessEvent(productID, quantity);
}

bool GoogleStoreFront::canMakePayments() const
{
    return __iabEnabled;
}

void GoogleStoreFront::restoreTransactions(const char * usernameHash)
{
    android_app* app = __state;
    JNIEnv* env = app->activity->env;
    JavaVM* vm = app->activity->vm;
    vm->AttachCurrentThread(&env, NULL);

    env->CallVoidMethod(app->activity->clazz, __midRestorePurchases);

    vm->DetachCurrentThread();
}

float GoogleStoreFront::getShippingCost(const StoreProduct& product, int quantity) const
{
    return product.price * quantity * 0.3f;
}

void GoogleStoreFront::finishTransaction(void * transactionObject)
{
    // do nothing
}

void GoogleStoreFront::requestReceipt()
{
    GP_ASSERT(!"Not implemented.")
}

}<commit_msg>clear google products after flushing and sending to client app<commit_after>#include "Base.h"
#include "GoogleStoreFront.h"
#include "storefront/StoreListener.h"
#include <jni.h>
#include <android_native_app_glue.h>

extern struct android_app* __state;
extern jclass __mainActivityClass;

namespace gameplay
{
    class GoogleStoreFront;
}

static gameplay::GoogleStoreFront * __instance = NULL;
static std::vector< gameplay::StoreProduct > __products;
static std::set<std::string> __requestedProducts;
static bool __iabEnabled = false;
static jmethodID __midQueueSKURequest;
static jmethodID __midFlushSkuDetailsQueue;
static jmethodID __midPurchaseItem;
static jmethodID __midRestorePurchases;

extern "C"
{

JNIEXPORT jint JNICALL GameplayJNI_OnLoad(JavaVM *vm, void *reserved)
{
    JNIEnv* env = NULL;
    vm->GetEnv((void **)&env, JNI_VERSION_1_6);

    __mainActivityClass = (jclass)env->NewGlobalRef(env->FindClass("org/gameplay3d/GamePlayNativeActivity"));
    __midQueueSKURequest = env->GetMethodID(__mainActivityClass, "queueSkuDetailsRequest", "(Ljava/lang/String;)V");
    __midFlushSkuDetailsQueue = env->GetMethodID(__mainActivityClass, "flushSkuDetailsQueue", "()V");
    __midPurchaseItem = env->GetMethodID(__mainActivityClass, "purchaseItem", "(Ljava/lang/String;)V");
    __midRestorePurchases = env->GetMethodID(__mainActivityClass, "restorePurchases", "()V");

    return JNI_VERSION_1_6;
}

// JNI stuff
JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_setIABEnabled(JNIEnv* env, jobject thiz)
{
    __iabEnabled = true;
}

JNIEXPORT int Java_org_gameplay3d_GamePlayNativeActivity_isItemConsumable(JNIEnv* env, jobject thiz, jstring sku)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    bool res = __instance->getListener()->isProductConsumable(productID);
    env->ReleaseStringUTFChars(sku, productID);

    return res ? 1 : 0;
}

JNIEXPORT int Java_org_gameplay3d_GamePlayNativeActivity_isSubscription(JNIEnv* env, jobject thiz, jstring sku)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    bool res = __instance->getListener()->isSubscription(productID);
    env->ReleaseStringUTFChars(sku, productID);

    return res ? 1 : 0;
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_itemRestored(JNIEnv* env, jobject thiz, jstring sku, jlong time, jstring orderId)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* orderID = env->GetStringUTFChars(orderId, NULL);

    __instance->getListener()->paymentTransactionRestoredEvent(productID, 1, time, orderID, NULL);

    env->ReleaseStringUTFChars(orderId, orderID);
    env->ReleaseStringUTFChars(sku, productID);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_itemPurchased(JNIEnv* env, jobject thiz, jstring sku, jlong time, jstring orderId)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* orderID = env->GetStringUTFChars(orderId, NULL);

    __instance->getListener()->paymentTransactionSucceededEvent(productID, 1, time, orderID, NULL);

    env->ReleaseStringUTFChars(orderId, orderID);
    env->ReleaseStringUTFChars(sku, productID);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_itemPurchaseFailed(JNIEnv* env, jobject thiz, jstring sku, jint error, jstring message)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* msg = env->GetStringUTFChars(message, NULL);

    __instance->getListener()->paymentTransactionFailedEvent(productID, 1, error, msg);

    env->ReleaseStringUTFChars(message, msg);
    env->ReleaseStringUTFChars(sku, productID);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_getProductsFailed(JNIEnv* env, jobject thiz, jint error, jstring message)
{
    const char* msg = env->GetStringUTFChars(message, NULL);
    if (__instance)
        __instance->getListener()->getProductsFailedEvent(error, msg);
    env->ReleaseStringUTFChars(message, msg);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_productValidated(JNIEnv* env, jobject thiz, jstring sku, jstring price, jstring title, jstring descr, jstring priceAmount, jstring priceCurrency)
{
    const char* productID = env->GetStringUTFChars(sku, NULL);
    const char* cPrice = env->GetStringUTFChars(price, NULL);
    const char* cTitle = env->GetStringUTFChars(title, NULL);
    const char* cDescr = env->GetStringUTFChars(descr, NULL);
    const char* cPriceAmount = env->GetStringUTFChars(priceAmount, NULL);
    const char* cPriceCurrency = env->GetStringUTFChars(priceCurrency, NULL);

    gameplay::StoreProduct product(productID, cTitle, cDescr, static_cast<float>(atoi(cPriceAmount)) * 0.000001f, cPrice, cPriceCurrency);
    __products.push_back(product);

    env->ReleaseStringUTFChars(sku, productID);
    env->ReleaseStringUTFChars(price, cPrice);
    env->ReleaseStringUTFChars(title, cTitle);
    env->ReleaseStringUTFChars(descr, cDescr);
    env->ReleaseStringUTFChars(priceAmount, cPriceAmount);
    env->ReleaseStringUTFChars(priceCurrency, cPriceCurrency);
}

JNIEXPORT void Java_org_gameplay3d_GamePlayNativeActivity_finishProductsValidation(JNIEnv* env, jobject thiz)
{
    std::vector<std::string> invalidProducts;
    for (const std::string &product : __requestedProducts)
    {
        if (std::find_if(__products.begin(), __products.end(), [&](const gameplay::StoreProduct& p){return p.id == product; }) == __products.end())
            invalidProducts.push_back(product);
    }

    __instance->getListener()->getProductsEvent(__products, invalidProducts);
    __products.clear();
}

}

namespace gameplay
{

GoogleStoreFront::GoogleStoreFront()
    : _listener( NULL )
{
    __instance = this;
}

GoogleStoreFront::~GoogleStoreFront()
{
}

void GoogleStoreFront::setListener(StoreListener * listener)
{
    _listener = listener;
}

StoreListener * GoogleStoreFront::getListener()
{
    return _listener;
}

void GoogleStoreFront::getProducts(const char ** productIDs) const
{
    __products.clear();
    __requestedProducts.clear();

    android_app* app = __state;
    JNIEnv* env = app->activity->env;
    JavaVM* vm = app->activity->vm;
    vm->AttachCurrentThread(&env, NULL);

    while (*productIDs)
    {
        __requestedProducts.insert(*productIDs);

        jstring paramString = env->NewStringUTF(*productIDs++);
        env->CallVoidMethod(app->activity->clazz, __midQueueSKURequest, paramString);
    }

    env->CallVoidMethod(app->activity->clazz, __midFlushSkuDetailsQueue);

    vm->DetachCurrentThread();
}

void GoogleStoreFront::makePayment(const char * productID, int quantity, const char * usernameHash)
{
    android_app* app = __state;
    JNIEnv* env = app->activity->env;
    JavaVM* vm = app->activity->vm;
    vm->AttachCurrentThread(&env, NULL);

    jstring paramString = env->NewStringUTF(productID);

    while (quantity-- > 0)
        env->CallVoidMethod(app->activity->clazz, __midPurchaseItem, paramString);

    vm->DetachCurrentThread();

    getListener()->paymentTransactionInProcessEvent(productID, quantity);
}

bool GoogleStoreFront::canMakePayments() const
{
    return __iabEnabled;
}

void GoogleStoreFront::restoreTransactions(const char * usernameHash)
{
    android_app* app = __state;
    JNIEnv* env = app->activity->env;
    JavaVM* vm = app->activity->vm;
    vm->AttachCurrentThread(&env, NULL);

    env->CallVoidMethod(app->activity->clazz, __midRestorePurchases);

    vm->DetachCurrentThread();
}

float GoogleStoreFront::getShippingCost(const StoreProduct& product, int quantity) const
{
    return product.price * quantity * 0.3f;
}

void GoogleStoreFront::finishTransaction(void * transactionObject)
{
    // do nothing
}

void GoogleStoreFront::requestReceipt()
{
    GP_ASSERT(!"Not implemented.")
}

}<|endoftext|>