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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt 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 "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "itkRescaleIntensityImageFilter.h"

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROI_QB_MUL_1.png}
//    OUTPUTS: {PCAOutput.tif}, {PCAOutput1.png}, {PCAOutput2.png}, {PCAOutput3.png}
//    3
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// This example illustrates the use of the
// \doxygen{otb}{PCAImageFilter}.
// This filter computes a Principal Component Analysis using an
// efficient method based on the inner product in order to compute the
// covariance matrix.
//
// The first step required to use this filter is to include its header file.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbPCAImageFilter.h"
// Software Guide : EndCodeSnippet

int main(int argc, char* argv[])
{
  typedef double PixelType;
  const unsigned int Dimension = 2;
  const char *       inputFileName = argv[1];
  const char *       outputFilename = argv[2];
  const unsigned int numberOfPrincipalComponentsRequired(atoi(argv[6]));

  // Software Guide : BeginLatex
  //
  // We start by defining the types for the images and the reader and
  // the writer. We choose to work with a \doxygen{otb}{VectorImage},
  // since we will produce a multi-channel image (the principal
  // components) from a multi-channel input image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::VectorImage<PixelType, Dimension> ImageType;
  typedef otb::ImageFileReader<ImageType>        ReaderType;
  typedef otb::ImageFileWriter<ImageType>        WriterType;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We instantiate now the image reader and we set the image file name.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  ReaderType::Pointer reader     = ReaderType::New();
  reader->SetFileName(inputFileName);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We define the type for the filter. It is templated over the input
  // and the output image types and also the transformation direction. The
  // internal structure of this filter is a filter-to-filter like structure.
  // We can now the instantiate the filter.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::PCAImageFilter<ImageType, ImageType,
                              otb::Transform::FORWARD> PCAFilterType;
  PCAFilterType::Pointer pcafilter     = PCAFilterType::New();
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The only parameter needed for the PCA is the number of principal
  // components required as output. We can choose to get less PCs than
  // the number of input bands.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  pcafilter->SetNumberOfPrincipalComponentsRequired(
    numberOfPrincipalComponentsRequired);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We now instantiate the writer and set the file name for the
  // output image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  WriterType::Pointer writer     = WriterType::New();
  writer->SetFileName(outputFilename);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We finally plug the pipeline and trigger the PCA computation with
  // the method \code{Update()} of the writer.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  pcafilter->SetInput(reader->GetOutput());
  writer->SetInput(pcafilter->GetOutput());

  writer->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  // Figure~\ref{fig:PCA_FILTER} shows the result of applying
  // the PCA to a 3 band RGB image.
  // \begin{figure}
  // \center
  // \includegraphics[width=0.25\textwidth]{ROI_QB_MUL_1.eps}
  // \includegraphics[width=0.25\textwidth]{PCAOutput1.eps}
  // \includegraphics[width=0.25\textwidth]{PCAOutput2.eps}
  // \includegraphics[width=0.25\textwidth]{PCAOutput3.eps}
  // \itkcaption[PCA Filter (forward trasnformation)]{Result of applying the
  // \doxygen{otb}{PCAImageFilter} to an image. From left
  // to right and top to bottom:
  // original image, first PC, second PC, third PC.}
  // \label{fig:PCA_FILTER}
  // \end{figure}
  //
  //  Software Guide : EndLatex

  typedef otb::Image<PixelType, Dimension> MonoImageType;

  typedef otb::MultiToMonoChannelExtractROI<PixelType, PixelType>
  ExtractROIFilterType;

  typedef otb::Image<unsigned char,
      2>                                     OutputImageType;
  typedef otb::ImageFileWriter<OutputImageType>
  WriterType2;
  typedef itk::RescaleIntensityImageFilter<MonoImageType,
      OutputImageType> RescalerType;

  for (unsigned int cpt = 0; cpt < numberOfPrincipalComponentsRequired; cpt++)
    {
    ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
    RescalerType::Pointer         rescaler = RescalerType::New();
    WriterType2::Pointer          writer2     = WriterType2::New();

    extractROIFilter->SetInput(pcafilter->GetOutput());
    extractROIFilter->SetChannel(cpt + 1);

    rescaler->SetInput(extractROIFilter->GetOutput());
    rescaler->SetOutputMinimum(0);
    rescaler->SetOutputMaximum(255);

    writer2->SetInput(rescaler->GetOutput());
    writer2->SetFileName(argv[cpt + 3]);
    writer2->Update();
    }

  return EXIT_SUCCESS;
}
<commit_msg>STYLE:kwstyle<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt 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 "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "itkRescaleIntensityImageFilter.h"

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROI_QB_MUL_1.png}
//    OUTPUTS: {PCAOutput.tif}, {PCAOutput1.png}, {PCAOutput2.png}, {PCAOutput3.png}
//    3
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// This example illustrates the use of the
// \doxygen{otb}{PCAImageFilter}.
// This filter computes a Principal Component Analysis using an
// efficient method based on the inner product in order to compute the
// covariance matrix.
//
// The first step required to use this filter is to include its header file.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbPCAImageFilter.h"
// Software Guide : EndCodeSnippet

int main(int argc, char* argv[])
{
  typedef double PixelType;
  const unsigned int Dimension = 2;
  const char *       inputFileName = argv[1];
  const char *       outputFilename = argv[2];
  const unsigned int numberOfPrincipalComponentsRequired(atoi(argv[6]));

  // Software Guide : BeginLatex
  //
  // We start by defining the types for the images and the reader and
  // the writer. We choose to work with a \doxygen{otb}{VectorImage},
  // since we will produce a multi-channel image (the principal
  // components) from a multi-channel input image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::VectorImage<PixelType, Dimension> ImageType;
  typedef otb::ImageFileReader<ImageType>        ReaderType;
  typedef otb::ImageFileWriter<ImageType>        WriterType;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We instantiate now the image reader and we set the image file name.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  ReaderType::Pointer reader     = ReaderType::New();
  reader->SetFileName(inputFileName);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We define the type for the filter. It is templated over the input
  // and the output image types and also the transformation direction. The
  // internal structure of this filter is a filter-to-filter like structure.
  // We can now the instantiate the filter.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::PCAImageFilter<ImageType, ImageType,
                              otb::Transform::FORWARD> PCAFilterType;
  PCAFilterType::Pointer pcafilter     = PCAFilterType::New();
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The only parameter needed for the PCA is the number of principal
  // components required as output. We can choose to get less PCs than
  // the number of input bands.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  pcafilter->SetNumberOfPrincipalComponentsRequired(
    numberOfPrincipalComponentsRequired);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We now instantiate the writer and set the file name for the
  // output image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  WriterType::Pointer writer     = WriterType::New();
  writer->SetFileName(outputFilename);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We finally plug the pipeline and trigger the PCA computation with
  // the method \code{Update()} of the writer.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  pcafilter->SetInput(reader->GetOutput());
  writer->SetInput(pcafilter->GetOutput());

  writer->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  // Figure~\ref{fig:PCA_FILTER} shows the result of applying
  // the PCA to a 3 band RGB image.
  // \begin{figure}
  // \center
  // \includegraphics[width=0.25\textwidth]{ROI_QB_MUL_1.eps}
  // \includegraphics[width=0.25\textwidth]{PCAOutput1.eps}
  // \includegraphics[width=0.25\textwidth]{PCAOutput2.eps}
  // \includegraphics[width=0.25\textwidth]{PCAOutput3.eps}
  // \itkcaption[PCA Filter (forward trasnformation)]{Result of applying the
  // \doxygen{otb}{PCAImageFilter} to an image. From left
  // to right and top to bottom:
  // original image, first PC, second PC, third PC.}
  // \label{fig:PCA_FILTER}
  // \end{figure}
  //
  //  Software Guide : EndLatex

  typedef otb::Image<PixelType, Dimension> MonoImageType;

  typedef otb::MultiToMonoChannelExtractROI<PixelType, PixelType>
  ExtractROIFilterType;

  typedef otb::Image<unsigned char,
      2>                                     OutputImageType;
  typedef otb::ImageFileWriter<OutputImageType>
  WriterType2;
  typedef itk::RescaleIntensityImageFilter<MonoImageType,
      OutputImageType> RescalerType;

  for (unsigned int cpt = 0; cpt < numberOfPrincipalComponentsRequired; cpt++)
    {
    ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
    RescalerType::Pointer         rescaler = RescalerType::New();
    WriterType2::Pointer          writer2 = WriterType2::New();

    extractROIFilter->SetInput(pcafilter->GetOutput());
    extractROIFilter->SetChannel(cpt + 1);

    rescaler->SetInput(extractROIFilter->GetOutput());
    rescaler->SetOutputMinimum(0);
    rescaler->SetOutputMaximum(255);

    writer2->SetInput(rescaler->GetOutput());
    writer2->SetFileName(argv[cpt + 3]);
    writer2->Update();
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


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

This file is part of the QtMediaHub project on http://www.qtmediahub.com

Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Girish Ramakrishnan girish@forwardbias.in
Contact:  Nokia Corporation donald.carr@nokia.com
Contact:  Nokia Corporation johannes.zellner@nokia.com

You may use this file under the terms of the BSD license as follows:

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

#include "declarativeview.h"
#include <QGraphicsObject>
#include <QDeclarativeEngine>
#include <QDebug>
#include <QPaintEvent>
#include "qmh-config.h"

#ifdef GL
#include <QGLWidget>
#endif

DeclarativeView::DeclarativeView(QWidget *parent)
    : QDeclarativeView(parent),
      m_frameCount(0),
      m_fps(0)
{
    startTimer(1000);
    connect(this, SIGNAL(statusChanged(QDeclarativeView::Status)), this, SLOT(handleStatusChanged(QDeclarativeView::Status)));
}

void DeclarativeView::setSource(const QUrl &url)
{
    m_url = url;
    QMetaObject::invokeMethod(this, "handleSourceChanged", Qt::QueuedConnection);
}

void DeclarativeView::paintEvent(QPaintEvent *event)
{
    static bool isGLViewport
#ifdef GL
            = qobject_cast<QGLWidget*>(viewport());
#else
            = false;
#endif
    if (!isGLViewport) {
        bool isOverlayMode = Config::isEnabled("overlay-mode", false);
        if (isOverlayMode) {
            QPainter painter(viewport());
            painter.fillRect(event->rect(), Qt::transparent);
        }
    }
    QDeclarativeView::paintEvent(event);
    m_timeSigma += m_frameTimer.elapsed();
    ++m_frameCount;
    m_frameTimer.restart();
}

void DeclarativeView::timerEvent(QTimerEvent *event)
{
    if (m_timeSigma) {
        m_fps = 1000*m_frameCount/m_timeSigma;
        m_timeSigma = m_frameCount = 0;
        emit fpsChanged();
    }
    QDeclarativeView::timerEvent(event);
}

void DeclarativeView::handleSourceChanged()
{
    QDeclarativeView::setSource(m_url);
}

void DeclarativeView::handleStatusChanged(QDeclarativeView::Status status)
{
    if (status == QDeclarativeView::Ready) {
        activateWindow();
    }
}

QObject *DeclarativeView::focusItem() const
{
    return qgraphicsitem_cast<QGraphicsObject *>(scene()->focusItem());
}

int DeclarativeView::fps() const
{
    return m_fps;
}

void DeclarativeView::addImportPath(const QString &path)
{
    engine()->addImportPath(path);
}

<commit_msg>Revert "change fps counter to tell us the Qt painting truth"<commit_after>/****************************************************************************

This file is part of the QtMediaHub project on http://www.qtmediahub.com

Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Girish Ramakrishnan girish@forwardbias.in
Contact:  Nokia Corporation donald.carr@nokia.com
Contact:  Nokia Corporation johannes.zellner@nokia.com

You may use this file under the terms of the BSD license as follows:

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

#include "declarativeview.h"
#include <QGraphicsObject>
#include <QDeclarativeEngine>
#include <QDebug>
#include <QPaintEvent>
#include "qmh-config.h"

#ifdef GL
#include <QGLWidget>
#endif

DeclarativeView::DeclarativeView(QWidget *parent)
    : QDeclarativeView(parent),
      m_frameCount(0),
      m_fps(0)
{
    startTimer(1000);
    connect(this, SIGNAL(statusChanged(QDeclarativeView::Status)), this, SLOT(handleStatusChanged(QDeclarativeView::Status)));
}

void DeclarativeView::setSource(const QUrl &url)
{
    m_url = url;
    QMetaObject::invokeMethod(this, "handleSourceChanged", Qt::QueuedConnection);
}

void DeclarativeView::paintEvent(QPaintEvent *event)
{
    static bool isGLViewport
#ifdef GL
            = qobject_cast<QGLWidget*>(viewport());
#else
            = false;
#endif
    if (!isGLViewport) {
        bool isOverlayMode = Config::isEnabled("overlay-mode", false);
        if (isOverlayMode) {
            QPainter painter(viewport());
            painter.fillRect(event->rect(), Qt::transparent);
        }
    }
    m_frameTimer.restart();
    QDeclarativeView::paintEvent(event);
    m_timeSigma += m_frameTimer.elapsed();
    ++m_frameCount;
}

void DeclarativeView::timerEvent(QTimerEvent *event)
{
    if (m_timeSigma) {
        m_fps = 1000*m_frameCount/m_timeSigma;
        m_timeSigma = m_frameCount = 0;
        emit fpsChanged();
    }
    QDeclarativeView::timerEvent(event);
}

void DeclarativeView::handleSourceChanged()
{
    QDeclarativeView::setSource(m_url);
}

void DeclarativeView::handleStatusChanged(QDeclarativeView::Status status)
{
    if (status == QDeclarativeView::Ready) {
        activateWindow();
    }
}

QObject *DeclarativeView::focusItem() const
{
    return qgraphicsitem_cast<QGraphicsObject *>(scene()->focusItem());
}

int DeclarativeView::fps() const
{
    return m_fps;
}

void DeclarativeView::addImportPath(const QString &path)
{
    engine()->addImportPath(path);
}

<|endoftext|>


<commit_before>/*
 Copyright (c) 2018, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the copyright holders nor the names of their contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include "rc_rpc_plugin/commands/mobile/get_interior_vehicle_data_request.h"
#include "rc_rpc_plugin/rc_module_constants.h"
#include "rc_rpc_plugin/rc_helpers.h"
#include "rc_rpc_plugin/rc_rpc_plugin.h"
#include "smart_objects/enum_schema_item.h"
#include "utils/macro.h"
#include "interfaces/MOBILE_API.h"

namespace rc_rpc_plugin {
namespace commands {

using namespace json_keys;
using namespace message_params;

CREATE_LOGGERPTR_GLOBAL(logger_, "RemoteControlModule")

GetInteriorVehicleDataRequest::GetInteriorVehicleDataRequest(
    const app_mngr::commands::MessageSharedPtr& message,
    const RCCommandParams& params)
    : RCCommandRequest(message, params)

    , excessive_subscription_occured_(false) {}

bool CheckIfModuleTypeExistInCapabilities(
    const smart_objects::SmartObject& rc_capabilities,
    const std::string& module_type) {
  LOG4CXX_AUTO_TRACE(logger_);
  const auto& mapping = RCHelpers::GetModuleTypeToCapabilitiesMapping();
  const auto& module_list = RCHelpers::GetModulesList();
  bool is_module_type_valid = false;
  for (const auto& module : module_list) {
    if (module == module_type) {
      if (rc_capabilities.keyExists(mapping(module))) {
        is_module_type_valid = true;
        break;
      }
    }
  }
  return is_module_type_valid;
}

bool GetInteriorVehicleDataRequest::ProcessCapabilities() {
  LOG4CXX_AUTO_TRACE(logger_);
  const smart_objects::SmartObject* rc_capabilities =
      hmi_capabilities_.rc_capability();

  const std::string module_type = ModuleType();
  if (rc_capabilities &&
      !CheckIfModuleTypeExistInCapabilities(*rc_capabilities, module_type)) {
    LOG4CXX_WARN(logger_, "Accessing not supported module data");
    SetResourceState(ModuleType(), ResourceState::FREE);
    SendResponse(false,
                 mobile_apis::Result::UNSUPPORTED_RESOURCE,
                 "Accessing not supported module data");
    return false;
  }
  return true;
}

void GetInteriorVehicleDataRequest::FilterDisabledModuleData(
    smart_objects::SmartObject& module_data) {
  // If radioEnable is false, remove all other radio parameters from the
  // message.
  if (module_data.keyExists(message_params::kRadioEnable) &&
      module_data[message_params::kRadioEnable].asBool() == false) {
    for (auto data = module_data.map_begin(); data != module_data.map_end();
         ++data) {
      if (data->first != message_params::kRadioEnable) {
        module_data.erase(data->first);
      }
    }
  }
  // If hdRadioEnable is false, find and remove the HDChannel if parameter is
  // present.
  if (module_data.keyExists(message_params::kHdRadioEnable) &&
      module_data[message_params::kHdRadioEnable].asBool() == false) {
    module_data.erase(message_params::kHdChannel);
  }
}

void GetInteriorVehicleDataRequest::ProcessResponseToMobileFromCache(
    app_mngr::ApplicationSharedPtr app) {
  LOG4CXX_AUTO_TRACE(logger_);
  const auto& data_mapping = RCHelpers::GetModuleTypeToDataMapping();
  auto data = interior_data_cache_.Retrieve(ModuleType());
  FilterDisabledModuleData(data);
  auto response_msg_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);
  response_msg_params[message_params::kModuleData][data_mapping(ModuleType())] =
      data;
  response_msg_params[message_params::kModuleData]
                     [message_params::kModuleType] = ModuleType();

  const auto& request_msg_params = (*message_)[app_mngr::strings::msg_params];
  LOG4CXX_DEBUG(logger_,
                "kSubscribe exist" << request_msg_params.keyExists(
                    message_params::kSubscribe));
  if (request_msg_params.keyExists(message_params::kSubscribe)) {
    response_msg_params[message_params::kIsSubscribed] =
        request_msg_params[message_params::kSubscribe].asBool();
    if (request_msg_params[message_params::kSubscribe].asBool()) {
      auto extension = RCHelpers::GetRCExtension(*app);
      DCHECK(extension);
      extension->SubscribeToInteriorVehicleData(ModuleType());
    }
  }
  SendResponse(
      true, mobile_apis::Result::SUCCESS, nullptr, &response_msg_params);
  if (AppShouldBeUnsubscribed()) {
    auto extension = RCHelpers::GetRCExtension(*app);
    DCHECK(extension);
    extension->UnsubscribeFromInteriorVehicleData(ModuleType());
  }
}

bool GetInteriorVehicleDataRequest::CheckRateLimits() {
  LOG4CXX_AUTO_TRACE(logger_);
  return interior_data_manager_.CheckRequestsToHMIFrequency(ModuleType());
}

bool GetInteriorVehicleDataRequest::AppShouldBeUnsubscribed() {
  LOG4CXX_AUTO_TRACE(logger_);
  const auto& msg_params = (*message_)[app_mngr::strings::msg_params];
  if (msg_params.keyExists(message_params::kSubscribe)) {
    return !(msg_params[message_params::kSubscribe].asBool());
  }
  return false;
}

bool GetInteriorVehicleDataRequest::TheLastAppShouldBeUnsubscribed(
    app_mngr::ApplicationSharedPtr app) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (AppShouldBeUnsubscribed()) {
    const auto subscribed_to_module_type =
        RCHelpers::AppsSubscribedToModuleType(application_manager_,
                                              ModuleType());
    if (subscribed_to_module_type.size() == 1 &&
        subscribed_to_module_type.front() == app) {
      LOG4CXX_DEBUG(logger_,
                    "The last application unsubscribes from " << ModuleType());
      return true;
    }
  }
  return false;
}

void GetInteriorVehicleDataRequest::Execute() {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!ProcessCapabilities()) {
    return;
  }

  app_mngr::ApplicationSharedPtr app =
      application_manager_.application(connection_key());

  if (TheLastAppShouldBeUnsubscribed(app) ||
      !interior_data_cache_.Contains(ModuleType())) {
    if (HasRequestExcessiveSubscription()) {
      excessive_subscription_occured_ = true;
      is_subscribed =
          (*message_)[app_mngr::strings::msg_params][message_params::kSubscribe]
              .asBool();
      RemoveExcessiveSubscription();
    }
    if (!CheckRateLimits()) {
      LOG4CXX_WARN(logger_, "GetInteriorVehicleData frequency is too high.");
      SendResponse(false, mobile_apis::Result::REJECTED);
      return;
    }
    interior_data_manager_.StoreRequestToHMITime(ModuleType());
    SendHMIRequest(hmi_apis::FunctionID::RC_GetInteriorVehicleData,
                   &(*message_)[app_mngr::strings::msg_params],
                   true);
    return;
  }
  ProcessResponseToMobileFromCache(app);
}

void GetInteriorVehicleDataRequest::on_event(
    const app_mngr::event_engine::Event& event) {
  LOG4CXX_AUTO_TRACE(logger_);
  RCCommandRequest::on_event(event);

  if (hmi_apis::FunctionID::RC_GetInteriorVehicleData != event.id()) {
    return;
  }

  smart_objects::SmartObject& hmi_response =
      const_cast<smart_objects::SmartObject&>(event.smart_object());

  mobile_apis::Result::eType result_code =
      GetMobileResultCode(static_cast<hmi_apis::Common_Result::eType>(
          hmi_response[app_mngr::strings::params][app_mngr::hmi_response::code]
              .asUInt()));

  bool result =
      helpers::Compare<mobile_apis::Result::eType, helpers::EQ, helpers::ONE>(
          result_code,
          mobile_apis::Result::SUCCESS,
          mobile_apis::Result::WARNINGS);

  if (mobile_apis::Result::READ_ONLY == result_code) {
    result = false;
    result_code = mobile_apis::Result::GENERIC_ERROR;
  }

  if (result) {
    app_mngr::ApplicationSharedPtr app =
        application_manager_.application(connection_key());

    DCHECK_OR_RETURN_VOID(app);
    if (TheLastAppShouldBeUnsubscribed(app)) {
      interior_data_cache_.Remove(ModuleType());
    }
    ProccessSubscription(hmi_response);
    if (is_subscribed) {
      const auto& data_mapping = RCHelpers::GetModuleTypeToDataMapping();
      const auto module_data =
          hmi_response[app_mngr::strings::msg_params]
                      [message_params::kModuleData][data_mapping(ModuleType())];
      interior_data_cache_.Add(ModuleType(), module_data);
    }
  } else {
    hmi_response[app_mngr::strings::msg_params].erase(
        message_params::kIsSubscribed);
  }
  std::string response_info;
  GetInfo(hmi_response, response_info);
  SetResourceState(ModuleType(), ResourceState::FREE);

  SendResponse(result,
               result_code,
               response_info.c_str(),
               &hmi_response[app_mngr::strings::msg_params]);
}

GetInteriorVehicleDataRequest::~GetInteriorVehicleDataRequest() {}

void GetInteriorVehicleDataRequest::ProccessSubscription(
    const ns_smart_device_link::ns_smart_objects::SmartObject& hmi_response) {
  LOG4CXX_AUTO_TRACE(logger_);

  const bool is_subscribe_present_in_request =
      (*message_)[app_mngr::strings::msg_params].keyExists(
          message_params::kSubscribe) ||
      excessive_subscription_occured_;

  const bool isSubscribed_present_in_response =
      hmi_response[app_mngr::strings::msg_params].keyExists(
          message_params::kIsSubscribed);

  smart_objects::SmartObject& temp_hmi_response =
      const_cast<smart_objects::SmartObject&>(hmi_response);

  app_mngr::ApplicationSharedPtr app =
      application_manager_.application(CommandRequestImpl::connection_key());
  const auto extension = RCHelpers::GetRCExtension(*app);
  const char* module_type;
  ns_smart_device_link::ns_smart_objects::
      EnumConversionHelper<mobile_apis::ModuleType::eType>::EnumToCString(
          static_cast<mobile_apis::ModuleType::eType>(
              hmi_response[app_mngr::strings::msg_params]
                          [message_params::kModuleData]
                          [message_params::kModuleType].asUInt()),
          &module_type);
  if (excessive_subscription_occured_) {
    is_subscribed = extension->IsSubscibedToInteriorVehicleData(module_type);
    temp_hmi_response[app_mngr::strings::msg_params]
                     [message_params::kIsSubscribed] = is_subscribed;
    return;
  }
  if (!is_subscribe_present_in_request && !isSubscribed_present_in_response) {
    return;
  }

  if (is_subscribe_present_in_request && !isSubscribed_present_in_response) {
    LOG4CXX_WARN(logger_,
                 "conditional mandatory parameter "
                     << message_params::kIsSubscribed
                     << " missed in hmi response");

    is_subscribed = extension->IsSubscibedToInteriorVehicleData(module_type);
    temp_hmi_response[app_mngr::strings::msg_params]
                     [message_params::kIsSubscribed] = is_subscribed;
    return;
  }

  if (!is_subscribe_present_in_request && isSubscribed_present_in_response) {
    LOG4CXX_WARN(logger_,
                 "Parameter " << message_params::kIsSubscribed
                              << " is ignored due to absence '"
                              << message_params::kSubscribe
                              << "' parameter in request");
    smart_objects::SmartObject& temp_hmi_response =
        const_cast<smart_objects::SmartObject&>(hmi_response);
    temp_hmi_response[app_mngr::strings::msg_params].erase(
        message_params::kIsSubscribed);
    return;
  }

  const bool request_subscribe =
      (*message_)[app_mngr::strings::msg_params][message_params::kSubscribe]
          .asBool();
  const bool response_subscribe =
      hmi_response[app_mngr::strings::msg_params][message_params::kIsSubscribed]
          .asBool();
  is_subscribed = response_subscribe;

  LOG4CXX_TRACE(logger_, "request_subscribe = " << request_subscribe);
  LOG4CXX_TRACE(logger_, "response_subscribe = " << response_subscribe);
  if (request_subscribe == response_subscribe) {
    const std::string module_type = ModuleType();
    if (response_subscribe) {
      LOG4CXX_DEBUG(logger_,
                    "SubscribeToInteriorVehicleData " << app->app_id() << " "
                                                      << module_type);
      extension->SubscribeToInteriorVehicleData(module_type);
    } else {
      LOG4CXX_DEBUG(logger_,
                    "UnsubscribeFromInteriorVehicleData "
                        << app->app_id() << " " << module_type);
      extension->UnsubscribeFromInteriorVehicleData(module_type);
    }
  }
}

bool GetInteriorVehicleDataRequest::HasRequestExcessiveSubscription() {
  LOG4CXX_AUTO_TRACE(logger_);
  const bool is_subscribe_present_in_request =
      (*message_)[app_mngr::strings::msg_params].keyExists(
          message_params::kSubscribe);

  if (is_subscribe_present_in_request) {
    app_mngr::ApplicationSharedPtr app =
        application_manager_.application(CommandRequestImpl::connection_key());
    const auto extension = RCHelpers::GetRCExtension(*app);

    const bool is_app_already_subscribed =
        extension->IsSubscibedToInteriorVehicleData(ModuleType());
    const bool app_wants_to_subscribe =
        (*message_)[app_mngr::strings::msg_params][message_params::kSubscribe]
            .asBool();
    if (!app_wants_to_subscribe && !is_app_already_subscribed) {
      return true;
    }
    return app_wants_to_subscribe && is_app_already_subscribed;
  }
  return false;
}

void GetInteriorVehicleDataRequest::RemoveExcessiveSubscription() {
  LOG4CXX_AUTO_TRACE(logger_);
  (*message_)[app_mngr::strings::msg_params].erase(message_params::kSubscribe);
}

std::string GetInteriorVehicleDataRequest::ModuleType() {
  mobile_apis::ModuleType::eType module_type = static_cast<
      mobile_apis::ModuleType::eType>(
      (*message_)[app_mngr::strings::msg_params][message_params::kModuleType]
          .asUInt());
  const char* str;
  const bool ok = ns_smart_device_link::ns_smart_objects::EnumConversionHelper<
      mobile_apis::ModuleType::eType>::EnumToCString(module_type, &str);
  return ok ? str : "unknown";
}

}  // namespace commands
}  // namespace rc_rpc_plugin
<commit_msg>Ensure erase does not invalidate iterator<commit_after>/*
 Copyright (c) 2018, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the copyright holders nor the names of their contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include "rc_rpc_plugin/commands/mobile/get_interior_vehicle_data_request.h"
#include "rc_rpc_plugin/rc_module_constants.h"
#include "rc_rpc_plugin/rc_helpers.h"
#include "rc_rpc_plugin/rc_rpc_plugin.h"
#include "smart_objects/enum_schema_item.h"
#include "utils/macro.h"
#include "interfaces/MOBILE_API.h"

namespace rc_rpc_plugin {
namespace commands {

using namespace json_keys;
using namespace message_params;

CREATE_LOGGERPTR_GLOBAL(logger_, "RemoteControlModule")

GetInteriorVehicleDataRequest::GetInteriorVehicleDataRequest(
    const app_mngr::commands::MessageSharedPtr& message,
    const RCCommandParams& params)
    : RCCommandRequest(message, params)

    , excessive_subscription_occured_(false) {}

bool CheckIfModuleTypeExistInCapabilities(
    const smart_objects::SmartObject& rc_capabilities,
    const std::string& module_type) {
  LOG4CXX_AUTO_TRACE(logger_);
  const auto& mapping = RCHelpers::GetModuleTypeToCapabilitiesMapping();
  const auto& module_list = RCHelpers::GetModulesList();
  bool is_module_type_valid = false;
  for (const auto& module : module_list) {
    if (module == module_type) {
      if (rc_capabilities.keyExists(mapping(module))) {
        is_module_type_valid = true;
        break;
      }
    }
  }
  return is_module_type_valid;
}

bool GetInteriorVehicleDataRequest::ProcessCapabilities() {
  LOG4CXX_AUTO_TRACE(logger_);
  const smart_objects::SmartObject* rc_capabilities =
      hmi_capabilities_.rc_capability();

  const std::string module_type = ModuleType();
  if (rc_capabilities &&
      !CheckIfModuleTypeExistInCapabilities(*rc_capabilities, module_type)) {
    LOG4CXX_WARN(logger_, "Accessing not supported module data");
    SetResourceState(ModuleType(), ResourceState::FREE);
    SendResponse(false,
                 mobile_apis::Result::UNSUPPORTED_RESOURCE,
                 "Accessing not supported module data");
    return false;
  }
  return true;
}

void GetInteriorVehicleDataRequest::FilterDisabledModuleData(
    smart_objects::SmartObject& module_data) {
  // If radioEnable is false, remove all other radio parameters from the
  // message.
  if (module_data.keyExists(message_params::kRadioEnable) &&
      module_data[message_params::kRadioEnable].asBool() == false) {
    for (auto data = module_data.map_begin(); data != module_data.map_end();) {
      auto key = data->first;
      ++data;
      if (key != message_params::kRadioEnable) {
        module_data.erase(key);
      }
    }
  }
  // If hdRadioEnable is false, find and remove the HDChannel if parameter is
  // present.
  if (module_data.keyExists(message_params::kHdRadioEnable) &&
      module_data[message_params::kHdRadioEnable].asBool() == false) {
    module_data.erase(message_params::kHdChannel);
  }
}

void GetInteriorVehicleDataRequest::ProcessResponseToMobileFromCache(
    app_mngr::ApplicationSharedPtr app) {
  LOG4CXX_AUTO_TRACE(logger_);
  const auto& data_mapping = RCHelpers::GetModuleTypeToDataMapping();
  auto data = interior_data_cache_.Retrieve(ModuleType());
  FilterDisabledModuleData(data);
  auto response_msg_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);
  response_msg_params[message_params::kModuleData][data_mapping(ModuleType())] =
      data;
  response_msg_params[message_params::kModuleData]
                     [message_params::kModuleType] = ModuleType();

  const auto& request_msg_params = (*message_)[app_mngr::strings::msg_params];
  LOG4CXX_DEBUG(logger_,
                "kSubscribe exist" << request_msg_params.keyExists(
                    message_params::kSubscribe));
  if (request_msg_params.keyExists(message_params::kSubscribe)) {
    response_msg_params[message_params::kIsSubscribed] =
        request_msg_params[message_params::kSubscribe].asBool();
    if (request_msg_params[message_params::kSubscribe].asBool()) {
      auto extension = RCHelpers::GetRCExtension(*app);
      DCHECK(extension);
      extension->SubscribeToInteriorVehicleData(ModuleType());
    }
  }
  SendResponse(
      true, mobile_apis::Result::SUCCESS, nullptr, &response_msg_params);
  if (AppShouldBeUnsubscribed()) {
    auto extension = RCHelpers::GetRCExtension(*app);
    DCHECK(extension);
    extension->UnsubscribeFromInteriorVehicleData(ModuleType());
  }
}

bool GetInteriorVehicleDataRequest::CheckRateLimits() {
  LOG4CXX_AUTO_TRACE(logger_);
  return interior_data_manager_.CheckRequestsToHMIFrequency(ModuleType());
}

bool GetInteriorVehicleDataRequest::AppShouldBeUnsubscribed() {
  LOG4CXX_AUTO_TRACE(logger_);
  const auto& msg_params = (*message_)[app_mngr::strings::msg_params];
  if (msg_params.keyExists(message_params::kSubscribe)) {
    return !(msg_params[message_params::kSubscribe].asBool());
  }
  return false;
}

bool GetInteriorVehicleDataRequest::TheLastAppShouldBeUnsubscribed(
    app_mngr::ApplicationSharedPtr app) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (AppShouldBeUnsubscribed()) {
    const auto subscribed_to_module_type =
        RCHelpers::AppsSubscribedToModuleType(application_manager_,
                                              ModuleType());
    if (subscribed_to_module_type.size() == 1 &&
        subscribed_to_module_type.front() == app) {
      LOG4CXX_DEBUG(logger_,
                    "The last application unsubscribes from " << ModuleType());
      return true;
    }
  }
  return false;
}

void GetInteriorVehicleDataRequest::Execute() {
  LOG4CXX_AUTO_TRACE(logger_);

  if (!ProcessCapabilities()) {
    return;
  }

  app_mngr::ApplicationSharedPtr app =
      application_manager_.application(connection_key());

  if (TheLastAppShouldBeUnsubscribed(app) ||
      !interior_data_cache_.Contains(ModuleType())) {
    if (HasRequestExcessiveSubscription()) {
      excessive_subscription_occured_ = true;
      is_subscribed =
          (*message_)[app_mngr::strings::msg_params][message_params::kSubscribe]
              .asBool();
      RemoveExcessiveSubscription();
    }
    if (!CheckRateLimits()) {
      LOG4CXX_WARN(logger_, "GetInteriorVehicleData frequency is too high.");
      SendResponse(false, mobile_apis::Result::REJECTED);
      return;
    }
    interior_data_manager_.StoreRequestToHMITime(ModuleType());
    SendHMIRequest(hmi_apis::FunctionID::RC_GetInteriorVehicleData,
                   &(*message_)[app_mngr::strings::msg_params],
                   true);
    return;
  }
  ProcessResponseToMobileFromCache(app);
}

void GetInteriorVehicleDataRequest::on_event(
    const app_mngr::event_engine::Event& event) {
  LOG4CXX_AUTO_TRACE(logger_);
  RCCommandRequest::on_event(event);

  if (hmi_apis::FunctionID::RC_GetInteriorVehicleData != event.id()) {
    return;
  }

  smart_objects::SmartObject& hmi_response =
      const_cast<smart_objects::SmartObject&>(event.smart_object());

  mobile_apis::Result::eType result_code =
      GetMobileResultCode(static_cast<hmi_apis::Common_Result::eType>(
          hmi_response[app_mngr::strings::params][app_mngr::hmi_response::code]
              .asUInt()));

  bool result =
      helpers::Compare<mobile_apis::Result::eType, helpers::EQ, helpers::ONE>(
          result_code,
          mobile_apis::Result::SUCCESS,
          mobile_apis::Result::WARNINGS);

  if (mobile_apis::Result::READ_ONLY == result_code) {
    result = false;
    result_code = mobile_apis::Result::GENERIC_ERROR;
  }

  if (result) {
    app_mngr::ApplicationSharedPtr app =
        application_manager_.application(connection_key());

    DCHECK_OR_RETURN_VOID(app);
    if (TheLastAppShouldBeUnsubscribed(app)) {
      interior_data_cache_.Remove(ModuleType());
    }
    ProccessSubscription(hmi_response);
    if (is_subscribed) {
      const auto& data_mapping = RCHelpers::GetModuleTypeToDataMapping();
      const auto module_data =
          hmi_response[app_mngr::strings::msg_params]
                      [message_params::kModuleData][data_mapping(ModuleType())];
      interior_data_cache_.Add(ModuleType(), module_data);
    }
  } else {
    hmi_response[app_mngr::strings::msg_params].erase(
        message_params::kIsSubscribed);
  }
  std::string response_info;
  GetInfo(hmi_response, response_info);
  SetResourceState(ModuleType(), ResourceState::FREE);

  SendResponse(result,
               result_code,
               response_info.c_str(),
               &hmi_response[app_mngr::strings::msg_params]);
}

GetInteriorVehicleDataRequest::~GetInteriorVehicleDataRequest() {}

void GetInteriorVehicleDataRequest::ProccessSubscription(
    const ns_smart_device_link::ns_smart_objects::SmartObject& hmi_response) {
  LOG4CXX_AUTO_TRACE(logger_);

  const bool is_subscribe_present_in_request =
      (*message_)[app_mngr::strings::msg_params].keyExists(
          message_params::kSubscribe) ||
      excessive_subscription_occured_;

  const bool isSubscribed_present_in_response =
      hmi_response[app_mngr::strings::msg_params].keyExists(
          message_params::kIsSubscribed);

  smart_objects::SmartObject& temp_hmi_response =
      const_cast<smart_objects::SmartObject&>(hmi_response);

  app_mngr::ApplicationSharedPtr app =
      application_manager_.application(CommandRequestImpl::connection_key());
  const auto extension = RCHelpers::GetRCExtension(*app);
  const char* module_type;
  ns_smart_device_link::ns_smart_objects::
      EnumConversionHelper<mobile_apis::ModuleType::eType>::EnumToCString(
          static_cast<mobile_apis::ModuleType::eType>(
              hmi_response[app_mngr::strings::msg_params]
                          [message_params::kModuleData]
                          [message_params::kModuleType].asUInt()),
          &module_type);
  if (excessive_subscription_occured_) {
    is_subscribed = extension->IsSubscibedToInteriorVehicleData(module_type);
    temp_hmi_response[app_mngr::strings::msg_params]
                     [message_params::kIsSubscribed] = is_subscribed;
    return;
  }
  if (!is_subscribe_present_in_request && !isSubscribed_present_in_response) {
    return;
  }

  if (is_subscribe_present_in_request && !isSubscribed_present_in_response) {
    LOG4CXX_WARN(logger_,
                 "conditional mandatory parameter "
                     << message_params::kIsSubscribed
                     << " missed in hmi response");

    is_subscribed = extension->IsSubscibedToInteriorVehicleData(module_type);
    temp_hmi_response[app_mngr::strings::msg_params]
                     [message_params::kIsSubscribed] = is_subscribed;
    return;
  }

  if (!is_subscribe_present_in_request && isSubscribed_present_in_response) {
    LOG4CXX_WARN(logger_,
                 "Parameter " << message_params::kIsSubscribed
                              << " is ignored due to absence '"
                              << message_params::kSubscribe
                              << "' parameter in request");
    smart_objects::SmartObject& temp_hmi_response =
        const_cast<smart_objects::SmartObject&>(hmi_response);
    temp_hmi_response[app_mngr::strings::msg_params].erase(
        message_params::kIsSubscribed);
    return;
  }

  const bool request_subscribe =
      (*message_)[app_mngr::strings::msg_params][message_params::kSubscribe]
          .asBool();
  const bool response_subscribe =
      hmi_response[app_mngr::strings::msg_params][message_params::kIsSubscribed]
          .asBool();
  is_subscribed = response_subscribe;

  LOG4CXX_TRACE(logger_, "request_subscribe = " << request_subscribe);
  LOG4CXX_TRACE(logger_, "response_subscribe = " << response_subscribe);
  if (request_subscribe == response_subscribe) {
    const std::string module_type = ModuleType();
    if (response_subscribe) {
      LOG4CXX_DEBUG(logger_,
                    "SubscribeToInteriorVehicleData " << app->app_id() << " "
                                                      << module_type);
      extension->SubscribeToInteriorVehicleData(module_type);
    } else {
      LOG4CXX_DEBUG(logger_,
                    "UnsubscribeFromInteriorVehicleData "
                        << app->app_id() << " " << module_type);
      extension->UnsubscribeFromInteriorVehicleData(module_type);
    }
  }
}

bool GetInteriorVehicleDataRequest::HasRequestExcessiveSubscription() {
  LOG4CXX_AUTO_TRACE(logger_);
  const bool is_subscribe_present_in_request =
      (*message_)[app_mngr::strings::msg_params].keyExists(
          message_params::kSubscribe);

  if (is_subscribe_present_in_request) {
    app_mngr::ApplicationSharedPtr app =
        application_manager_.application(CommandRequestImpl::connection_key());
    const auto extension = RCHelpers::GetRCExtension(*app);

    const bool is_app_already_subscribed =
        extension->IsSubscibedToInteriorVehicleData(ModuleType());
    const bool app_wants_to_subscribe =
        (*message_)[app_mngr::strings::msg_params][message_params::kSubscribe]
            .asBool();
    if (!app_wants_to_subscribe && !is_app_already_subscribed) {
      return true;
    }
    return app_wants_to_subscribe && is_app_already_subscribed;
  }
  return false;
}

void GetInteriorVehicleDataRequest::RemoveExcessiveSubscription() {
  LOG4CXX_AUTO_TRACE(logger_);
  (*message_)[app_mngr::strings::msg_params].erase(message_params::kSubscribe);
}

std::string GetInteriorVehicleDataRequest::ModuleType() {
  mobile_apis::ModuleType::eType module_type = static_cast<
      mobile_apis::ModuleType::eType>(
      (*message_)[app_mngr::strings::msg_params][message_params::kModuleType]
          .asUInt());
  const char* str;
  const bool ok = ns_smart_device_link::ns_smart_objects::EnumConversionHelper<
      mobile_apis::ModuleType::eType>::EnumToCString(module_type, &str);
  return ok ? str : "unknown";
}

}  // namespace commands
}  // namespace rc_rpc_plugin
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "EyeTrackerRemoteFactory.h"
#include "VRPNConnectionCollection.h"
#include <osvr/Common/ClientInterface.h>
#include <osvr/Common/PathTreeFull.h>
#include <osvr/Util/ChannelCountC.h>
#include <osvr/Util/UniquePtr.h>
#include <osvr/Common/OriginalSource.h>
#include "InterfaceTree.h"
#include <osvr/Util/Verbosity.h>
#include <osvr/Common/CreateDevice.h>

#include <osvr/Common/EyeTrackerComponent.h>
#include <osvr/Common/Location2DComponent.h>
#include <osvr/Common/DirectionComponent.h>
#include <osvr/Common/RoutingConstants.h>
#include <osvr/Common/InterfaceState.h>

// Library/third-party includes
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
#include <boost/variant/get.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <json/value.h>
#include <json/reader.h>

// Standard includes
#include <iostream>
#include <string>

namespace osvr {
namespace client {

    class EyeTrackerRemoteHandler : public RemoteHandler {
      public:
        struct Options {
            Options()
                : reportDirection(false), reportBasePoint(false),
                  reportLocation2D(false), reportBlink(false), dirIface() {}
            bool reportDirection;
            bool reportBasePoint;
            bool reportLocation2D;
            bool reportBlink;
            osvr::common::ClientInterfacePtr dirIface;
            osvr::common::ClientInterfacePtr locationIface;
            osvr::common::ClientInterfacePtr trackerIface;
            osvr::common::ClientInterfacePtr buttonIface;
        };

        EyeTrackerRemoteHandler(vrpn_ConnectionPtr const &conn,
                                std::string const &deviceName,
                                Options const &options,
                                boost::optional<OSVR_ChannelCount> sensor,
                                common::InterfaceList &ifaces)
            : m_dev(common::createClientDevice(deviceName, conn)),
              m_interfaces(ifaces), m_all(!sensor.is_initialized()),
              m_opts(options), m_sensor(sensor) {
            auto eyetracker = common::EyeTrackerComponent::create();
            m_dev->addComponent(eyetracker);
            eyetracker->registerEyeHandler(
                [&](common::OSVR_EyeNotification const &data,
                    util::time::TimeValue const &timestamp) {
                    m_handleEyeTracking(data, timestamp);
                });
            OSVR_DEV_VERBOSE("Constructed an Eye Handler for " << deviceName);
        }

        /// @brief Deleted assignment operator.
        EyeTrackerRemoteHandler &
        operator=(EyeTrackerRemoteHandler const &) = delete;

        virtual ~EyeTrackerRemoteHandler() {
            /// @todo do we need to unregister?
        }

        virtual void update() { m_dev->update(); }

      private:
        void m_handleEyeTracking3d(common::OSVR_EyeNotification const &data,
                                   util::time::TimeValue const &timestamp) {

            OSVR_EyeTracker3DReport report;
            report.sensor = data.sensor;
            report.state.directionValid = false;
            report.state.basePointValid = false;
            util::time::TimeValue timest = timestamp;
            if (m_opts.reportDirection) {
                report.state.directionValid =
                    m_opts.dirIface->getState<OSVR_DirectionReport>(
                        timest, report.state.direction);
            }
            if (m_opts.reportBasePoint) {
                report.state.basePointValid =
                    m_opts.trackerIface->getState<OSVR_PositionReport>(
                        timest, report.state.basePoint);
            }
            if (!(report.state.basePointValid || report.state.directionValid)) {
                return; // don't send an empty report.
            }

            /// @todo what timestamp do we use - the one from the notification
            /// or the ones from the original reports? At least right now
            /// they're theoretically the same, but...
            for (auto &iface : m_interfaces) {
                iface->triggerCallbacks(timestamp, report);
            }
        }

        void m_handleEyeTracking2d(common::OSVR_EyeNotification const &data,
                                   util::time::TimeValue const &timestamp) {

            if (!m_opts.reportLocation2D) {
                return;
            }
            OSVR_EyeTracker2DReport report;
            report.sensor = data.sensor;
            bool locationValid = false;
            util::time::TimeValue reportTime;

            locationValid =
                m_opts.locationIface->getState<OSVR_Location2DReport>(
                    reportTime, report.state);
            if (!locationValid) {
                return; // don't send an empty report.
            }

            /// @todo what timestamp do we use - the one from the notification
            /// or the one from the original report? At least right now they're
            /// the same, but...
            for (auto &iface : m_interfaces) {
                iface->triggerCallbacks(timestamp, report);
            }
        }

        void m_handleEyeBlink(common::OSVR_EyeNotification const &data,
                              util::time::TimeValue const &timestamp) {

            if (!m_opts.reportBlink) {
                return;
            }
            OSVR_EyeTrackerBlinkReport report;
            report.sensor = data.sensor;
            bool haveBlink = false;
            util::time::TimeValue blinkTimestamp;

            haveBlink = m_opts.locationIface->getState<OSVR_ButtonReport>(
                blinkTimestamp, report.state);
            if (!haveBlink) {
                return; // don't send an empty report.
            }
            /// @todo what timestamp do we use - the one from the notification
            /// or the one from the original report? At least right now they're
            /// the same, but...
            for (auto &iface : m_interfaces) {
                iface->triggerCallbacks(timestamp, report);
            }
        }

        void m_handleEyeTracking(common::OSVR_EyeNotification const &data,
                                 util::time::TimeValue const &timestamp) {
            if (!m_all && *m_sensor != data.sensor) {
                /// doesn't match our filter.
                return;
            }

            m_handleEyeTracking3d(data, timestamp);
            m_handleEyeTracking2d(data, timestamp);
            m_handleEyeBlink(data, timestamp);
        }

        common::BaseDevicePtr m_dev;
        common::InterfaceList &m_interfaces;
        bool m_all;
        Options m_opts;
        boost::optional<OSVR_ChannelCount> m_sensor;
    };

    EyeTrackerRemoteFactory::EyeTrackerRemoteFactory(
        VRPNConnectionCollection const &conns)
        : m_conns(conns) {}

    shared_ptr<RemoteHandler> EyeTrackerRemoteFactory::
    operator()(common::OriginalSource const &source,
               common::InterfaceList &ifaces, common::ClientContext &ctx) {

        shared_ptr<RemoteHandler> ret;

        EyeTrackerRemoteHandler::Options opts;

        auto myDescriptor = source.getDeviceElement().getDescriptor();

        if (myDescriptor["interfaces"]["eyetracker"].isMember("direction")) {
            opts.reportDirection = true;
            const std::string iface =
                common::getPathSeparator() +
                source.getDeviceElement().getDeviceName() + "/direction";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.dirIface = ctx.getInterface(iface.c_str());
        }
        if (myDescriptor["interfaces"]["eyetracker"].isMember("tracker")) {
            opts.reportBasePoint = true;
            const std::string iface =
                common::getPathSeparator() +
                source.getDeviceElement().getDeviceName() + "/tracker/";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.trackerIface = ctx.getInterface(iface.c_str());
        }

        if (myDescriptor["interfaces"]["eyetracker"].isMember("location2D")) {
            opts.reportLocation2D = true;
            const std::string iface =
                common::getPathSeparator() +
                source.getDeviceElement().getDeviceName() + "/location2D/";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.locationIface = ctx.getInterface(iface.c_str());
        }
        if (myDescriptor["interfaces"]["eyetracker"].isMember("button")) {
            opts.reportBlink = true;
            const std::string iface =
                common::getPathSeparator() +
                source.getDeviceElement().getDeviceName() + "/button/";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.buttonIface = ctx.getInterface(iface.c_str());
        }

        if (source.hasTransform()) {
            OSVR_DEV_VERBOSE(
                "Ignoring transform found on route for Eye Tracker data!");
        }

        auto const &devElt = source.getDeviceElement();

        ret.reset(new EyeTrackerRemoteHandler(
            m_conns.getConnection(devElt), devElt.getFullDeviceName(), opts,
            source.getSensorNumberAsChannelCount(), ifaces));
        return ret;
    }

} // namespace client
} // namespace osvr<commit_msg>Use getDevicePath in eye tracker remote.<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "EyeTrackerRemoteFactory.h"
#include "VRPNConnectionCollection.h"
#include <osvr/Common/ClientInterface.h>
#include <osvr/Common/PathTreeFull.h>
#include <osvr/Util/ChannelCountC.h>
#include <osvr/Util/UniquePtr.h>
#include <osvr/Common/OriginalSource.h>
#include "InterfaceTree.h"
#include <osvr/Util/Verbosity.h>
#include <osvr/Common/CreateDevice.h>

#include <osvr/Common/EyeTrackerComponent.h>
#include <osvr/Common/Location2DComponent.h>
#include <osvr/Common/DirectionComponent.h>
#include <osvr/Common/RoutingConstants.h>
#include <osvr/Common/InterfaceState.h>

// Library/third-party includes
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
#include <boost/variant/get.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <json/value.h>
#include <json/reader.h>

// Standard includes
#include <iostream>
#include <string>

namespace osvr {
namespace client {

    class EyeTrackerRemoteHandler : public RemoteHandler {
      public:
        struct Options {
            Options()
                : reportDirection(false), reportBasePoint(false),
                  reportLocation2D(false), reportBlink(false), dirIface() {}
            bool reportDirection;
            bool reportBasePoint;
            bool reportLocation2D;
            bool reportBlink;
            osvr::common::ClientInterfacePtr dirIface;
            osvr::common::ClientInterfacePtr locationIface;
            osvr::common::ClientInterfacePtr trackerIface;
            osvr::common::ClientInterfacePtr buttonIface;
        };

        EyeTrackerRemoteHandler(vrpn_ConnectionPtr const &conn,
                                std::string const &deviceName,
                                Options const &options,
                                boost::optional<OSVR_ChannelCount> sensor,
                                common::InterfaceList &ifaces)
            : m_dev(common::createClientDevice(deviceName, conn)),
              m_interfaces(ifaces), m_all(!sensor.is_initialized()),
              m_opts(options), m_sensor(sensor) {
            auto eyetracker = common::EyeTrackerComponent::create();
            m_dev->addComponent(eyetracker);
            eyetracker->registerEyeHandler(
                [&](common::OSVR_EyeNotification const &data,
                    util::time::TimeValue const &timestamp) {
                    m_handleEyeTracking(data, timestamp);
                });
            OSVR_DEV_VERBOSE("Constructed an Eye Handler for " << deviceName);
        }

        /// @brief Deleted assignment operator.
        EyeTrackerRemoteHandler &
        operator=(EyeTrackerRemoteHandler const &) = delete;

        virtual ~EyeTrackerRemoteHandler() {
            /// @todo do we need to unregister?
        }

        virtual void update() { m_dev->update(); }

      private:
        void m_handleEyeTracking3d(common::OSVR_EyeNotification const &data,
                                   util::time::TimeValue const &timestamp) {

            OSVR_EyeTracker3DReport report;
            report.sensor = data.sensor;
            report.state.directionValid = false;
            report.state.basePointValid = false;
            util::time::TimeValue timest = timestamp;
            if (m_opts.reportDirection) {
                report.state.directionValid =
                    m_opts.dirIface->getState<OSVR_DirectionReport>(
                        timest, report.state.direction);
            }
            if (m_opts.reportBasePoint) {
                report.state.basePointValid =
                    m_opts.trackerIface->getState<OSVR_PositionReport>(
                        timest, report.state.basePoint);
            }
            if (!(report.state.basePointValid || report.state.directionValid)) {
                return; // don't send an empty report.
            }

            /// @todo what timestamp do we use - the one from the notification
            /// or the ones from the original reports? At least right now
            /// they're theoretically the same, but...
            for (auto &iface : m_interfaces) {
                iface->triggerCallbacks(timestamp, report);
            }
        }

        void m_handleEyeTracking2d(common::OSVR_EyeNotification const &data,
                                   util::time::TimeValue const &timestamp) {

            if (!m_opts.reportLocation2D) {
                return;
            }
            OSVR_EyeTracker2DReport report;
            report.sensor = data.sensor;
            bool locationValid = false;
            util::time::TimeValue reportTime;

            locationValid =
                m_opts.locationIface->getState<OSVR_Location2DReport>(
                    reportTime, report.state);
            if (!locationValid) {
                return; // don't send an empty report.
            }

            /// @todo what timestamp do we use - the one from the notification
            /// or the one from the original report? At least right now they're
            /// the same, but...
            for (auto &iface : m_interfaces) {
                iface->triggerCallbacks(timestamp, report);
            }
        }

        void m_handleEyeBlink(common::OSVR_EyeNotification const &data,
                              util::time::TimeValue const &timestamp) {

            if (!m_opts.reportBlink) {
                return;
            }
            OSVR_EyeTrackerBlinkReport report;
            report.sensor = data.sensor;
            bool haveBlink = false;
            util::time::TimeValue blinkTimestamp;

            haveBlink = m_opts.locationIface->getState<OSVR_ButtonReport>(
                blinkTimestamp, report.state);
            if (!haveBlink) {
                return; // don't send an empty report.
            }
            /// @todo what timestamp do we use - the one from the notification
            /// or the one from the original report? At least right now they're
            /// the same, but...
            for (auto &iface : m_interfaces) {
                iface->triggerCallbacks(timestamp, report);
            }
        }

        void m_handleEyeTracking(common::OSVR_EyeNotification const &data,
                                 util::time::TimeValue const &timestamp) {
            if (!m_all && *m_sensor != data.sensor) {
                /// doesn't match our filter.
                return;
            }

            m_handleEyeTracking3d(data, timestamp);
            m_handleEyeTracking2d(data, timestamp);
            m_handleEyeBlink(data, timestamp);
        }

        common::BaseDevicePtr m_dev;
        common::InterfaceList &m_interfaces;
        bool m_all;
        Options m_opts;
        boost::optional<OSVR_ChannelCount> m_sensor;
    };

    EyeTrackerRemoteFactory::EyeTrackerRemoteFactory(
        VRPNConnectionCollection const &conns)
        : m_conns(conns) {}

    shared_ptr<RemoteHandler> EyeTrackerRemoteFactory::
    operator()(common::OriginalSource const &source,
               common::InterfaceList &ifaces, common::ClientContext &ctx) {

        shared_ptr<RemoteHandler> ret;

        EyeTrackerRemoteHandler::Options opts;

        auto myDescriptor = source.getDeviceElement().getDescriptor();
        auto devicePath = source.getDevicePath();

        if (myDescriptor["interfaces"]["eyetracker"].isMember("direction")) {
            opts.reportDirection = true;
            const std::string iface = devicePath + "/direction";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.dirIface = ctx.getInterface(iface.c_str());
        }
        if (myDescriptor["interfaces"]["eyetracker"].isMember("tracker")) {
            opts.reportBasePoint = true;
            const std::string iface = devicePath + "/tracker/";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.trackerIface = ctx.getInterface(iface.c_str());
        }

        if (myDescriptor["interfaces"]["eyetracker"].isMember("location2D")) {
            opts.reportLocation2D = true;
            const std::string iface = devicePath + "/location2D/";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.locationIface = ctx.getInterface(iface.c_str());
        }
        if (myDescriptor["interfaces"]["eyetracker"].isMember("button")) {
            opts.reportBlink = true;
            const std::string iface = devicePath + "/button/";
            /// @todo need to append sensor number here!
            // boost::lexical_cast<std::string>(source.getSensorNumberAsChannelCount())
            opts.buttonIface = ctx.getInterface(iface.c_str());
        }

        if (source.hasTransform()) {
            OSVR_DEV_VERBOSE(
                "Ignoring transform found on route for Eye Tracker data!");
        }

        auto const &devElt = source.getDeviceElement();

        ret.reset(new EyeTrackerRemoteHandler(
            m_conns.getConnection(devElt), devElt.getFullDeviceName(), opts,
            source.getSensorNumberAsChannelCount(), ifaces));
        return ret;
    }

} // namespace client
} // namespace osvr<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "cdboptionspage.h"
#include "commonoptionspage.h"
#include "debuggeractions.h"
#include "debuggercore.h"
#include "debuggerinternalconstants.h"
#include "cdbengine.h"
#include "cdbsymbolpathlisteditor.h"

#include <coreplugin/icore.h>

#include <QDialogButtonBox>
#include <QTextStream>

namespace Debugger {
namespace Internal {

const char *CdbOptionsPage::crtDbgReport = "CrtDbgReport";

struct EventsDescription {
    const char *abbreviation;
    bool hasParameter;
    const char *description;
};

// Parameters of the "sxe" command
const EventsDescription eventDescriptions[] =
{
    {"eh", false, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "C++ exception")},
    {"ct", false, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Thread creation")},
    {"et", false, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Thread exit")},
    {"ld", true,  QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Load module:")},
    {"ud", true,  QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Unload module:")},
    {"out", true, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Output:")}
};

static inline int indexOfEvent(const QString &abbrev)
{
    const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
    for (size_t e = 0; e < eventCount; e++)
        if (abbrev == QLatin1String(eventDescriptions[e].abbreviation))
                return int(e);
    return -1;
}

CdbBreakEventWidget::CdbBreakEventWidget(QWidget *parent) : QWidget(parent)
{
    // 1 column with checkboxes only,
    // further columns with checkbox + parameter
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->setMargin(0);
    QVBoxLayout *leftLayout = new QVBoxLayout;
    QFormLayout *parameterLayout = 0;
    mainLayout->addLayout(leftLayout);
    const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
    for (size_t e = 0; e < eventCount; e++) {
        QCheckBox *cb = new QCheckBox(tr(eventDescriptions[e].description));
        QLineEdit *le = 0;
        if (eventDescriptions[e].hasParameter) {
            if (!parameterLayout) {
                parameterLayout = new QFormLayout;
                mainLayout->addSpacerItem(new QSpacerItem(20, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
                mainLayout->addLayout(parameterLayout);
            }
            le = new QLineEdit;
            parameterLayout->addRow(cb, le);
            if (parameterLayout->count() >= 6) // New column
                parameterLayout = 0;
        } else {
            leftLayout->addWidget(cb);
        }
        m_checkBoxes.push_back(cb);
        m_lineEdits.push_back(le);
    }
    setLayout(mainLayout);
}

void CdbBreakEventWidget::clear()
{
    foreach (QLineEdit *l, m_lineEdits) {
        if (l)
            l->clear();
    }
    foreach (QCheckBox *c, m_checkBoxes)
        c->setChecked(false);
}

void CdbBreakEventWidget::setBreakEvents(const QStringList &l)
{
    clear();
    // Split the list of ("eh", "out:MyOutput")
    foreach (const QString &evt, l) {
        const int colonPos = evt.indexOf(QLatin1Char(':'));
        const QString abbrev = colonPos != -1 ? evt.mid(0, colonPos) : evt;
        const int index = indexOfEvent(abbrev);
        if (index != -1)
            m_checkBoxes.at(index)->setChecked(true);
        if (colonPos != -1 && m_lineEdits.at(index))
            m_lineEdits.at(index)->setText(evt.mid(colonPos + 1));
    }
}

QString CdbBreakEventWidget::filterText(int i) const
{
    return m_lineEdits.at(i) ? m_lineEdits.at(i)->text() : QString();
}

QStringList CdbBreakEventWidget::breakEvents() const
{
    // Compile a list of ("eh", "out:MyOutput")
    QStringList rc;
    const int eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
    for (int e = 0; e < eventCount; e++) {
        if (m_checkBoxes.at(e)->isChecked()) {
            const QString filter = filterText(e);
            QString s = QLatin1String(eventDescriptions[e].abbreviation);
            if (!filter.isEmpty()) {
                s += QLatin1Char(':');
                s += filter;
            }
            rc.push_back(s);
        }
    }
    return rc;
}

CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent)
    : QWidget(parent)
    , m_breakEventWidget(new CdbBreakEventWidget)
{
    m_ui.setupUi(this);
    // Squeeze the groupbox layouts vertically to
    // accommodate all options. This page only shows on
    // Windows, which has large margins by default.

    const int margin = layout()->margin();
    const QMargins margins(margin, margin / 3, margin, margin / 3);

    m_ui.startupFormLayout->setContentsMargins(margins);

    QVBoxLayout *eventLayout = new QVBoxLayout;
    eventLayout->setContentsMargins(margins);
    eventLayout->addWidget(m_breakEventWidget);
    m_ui.eventGroupBox->setLayout(eventLayout);
    m_ui.breakCrtDbgReportCheckBox
        ->setText(CommonOptionsPage::msgSetBreakpointAtFunction(CdbOptionsPage::crtDbgReport));
    const QString hint = tr("This is useful to catch runtime error messages, for example caused by assert().");
    m_ui.breakCrtDbgReportCheckBox
        ->setToolTip(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip(CdbOptionsPage::crtDbgReport, hint));

    DebuggerCore *dc = debuggerCore();
    group.insert(dc->action(CdbAdditionalArguments), m_ui.additionalArgumentsLineEdit);
    group.insert(dc->action(CdbBreakOnCrtDbgReport), m_ui.breakCrtDbgReportCheckBox);
    group.insert(dc->action(UseCdbConsole), m_ui.consoleCheckBox);
    group.insert(dc->action(CdbBreakPointCorrection), m_ui.breakpointCorrectionCheckBox);
    group.insert(dc->action(IgnoreFirstChanceAccessViolation),
                 m_ui.ignoreFirstChanceAccessViolationCheckBox);

    m_breakEventWidget->setBreakEvents(dc->stringListSetting(CdbBreakEvents));
}

QStringList CdbOptionsPageWidget::breakEvents() const
{
    return m_breakEventWidget->breakEvents();
}

static QString stripColon(QString s)
{
    const int lastColon = s.lastIndexOf(QLatin1Char(':'));
    if (lastColon != -1)
        s.truncate(lastColon);
    return s;
}

QString CdbOptionsPageWidget::searchKeywords() const
{
    QString rc;
    QTextStream(&rc) << stripColon(m_ui.additionalArgumentsLabel->text());
    rc.remove(QLatin1Char('&'));
    return rc;
}

// ---------- CdbOptionsPage

CdbOptionsPage::CdbOptionsPage()
{
    setId("F.Cda");
    setDisplayName(tr("CDB"));
    setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
    setDisplayCategory(QCoreApplication::translate("Debugger",
        Constants::DEBUGGER_SETTINGS_TR_CATEGORY));
    setCategoryIcon(QLatin1String(Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
}

CdbOptionsPage::~CdbOptionsPage()
{
}

QWidget *CdbOptionsPage::createPage(QWidget *parent)
{
    m_widget = new CdbOptionsPageWidget(parent);
    if (m_searchKeywords.isEmpty())
        m_searchKeywords = m_widget->searchKeywords();
    return m_widget;
}

void CdbOptionsPage::apply()
{
    if (!m_widget)
        return;
    m_widget->group.apply(Core::ICore::settings());
    debuggerCore()->action(CdbBreakEvents)->setValue(m_widget->breakEvents());
}

void CdbOptionsPage::finish()
{
    m_widget->group.finish();
}

bool CdbOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

// ---------- CdbPathsPage

class CdbPathsPageWidget : public QWidget
{
public:
    Utils::SavedActionSet group;

//    CdbPaths m_paths;
    QString m_searchKeywords;

    CdbSymbolPathListEditor *m_symbolPathListEditor;
    Utils::PathListEditor *m_sourcePathListEditor;

    CdbPathsPageWidget(QWidget *parent = 0);
};

CdbPathsPageWidget::CdbPathsPageWidget(QWidget *parent) :
    QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout(this);

    QString title = tr("Symbol Paths");
    m_searchKeywords.append(title);
    QGroupBox* gbSymbolPath = new QGroupBox(this);
    gbSymbolPath->setTitle(title);
    QVBoxLayout *gbSymbolPathLayout = new QVBoxLayout(gbSymbolPath);
    m_symbolPathListEditor = new CdbSymbolPathListEditor(gbSymbolPath);
    gbSymbolPathLayout->addWidget(m_symbolPathListEditor);

    title = tr("Source Paths");
    m_searchKeywords.append(title);
    QGroupBox* gbSourcePath = new QGroupBox(this);
    gbSourcePath->setTitle(title);
    QVBoxLayout *gbSourcePathLayout = new QVBoxLayout(gbSourcePath);
    m_sourcePathListEditor = new Utils::PathListEditor(gbSourcePath);
    gbSourcePathLayout->addWidget(m_sourcePathListEditor);

    layout->addWidget(gbSymbolPath);
    layout->addWidget(gbSourcePath);

    DebuggerCore *dc = debuggerCore();
    group.insert(dc->action(CdbSymbolPaths), m_symbolPathListEditor);
    group.insert(dc->action(CdbSourcePaths), m_sourcePathListEditor);
}

CdbPathsPage::CdbPathsPage()
    : m_widget(0)
{
    setId("F.Cdb");
    setDisplayName(tr("CDB Paths"));
    setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
    setDisplayCategory(QCoreApplication::translate("Debugger",
        Constants::DEBUGGER_SETTINGS_TR_CATEGORY));
    setCategoryIcon(QLatin1String(Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
}

CdbPathsPage::~CdbPathsPage()
{
}

QWidget *CdbPathsPage::createPage(QWidget *parent)
{
    if (!m_widget)
        m_widget = new CdbPathsPageWidget(parent);
    else
        m_widget->setParent(parent);
    return m_widget;
}

void CdbPathsPage::apply()
{
    if (m_widget)
        m_widget->group.apply(Core::ICore::settings());
}

void CdbPathsPage::finish()
{
    if (m_widget)
        m_widget->group.finish();
}

bool CdbPathsPage::matches(const QString &searchKeyWord) const
{
    return m_widget &&
            m_widget->m_searchKeywords.contains(searchKeyWord, Qt::CaseInsensitive);
}

} // namespace Internal
} // namespace Debugger
<commit_msg>Debugger: Fix crash in cdboptionspage.<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "cdboptionspage.h"
#include "commonoptionspage.h"
#include "debuggeractions.h"
#include "debuggercore.h"
#include "debuggerinternalconstants.h"
#include "cdbengine.h"
#include "cdbsymbolpathlisteditor.h"

#include <coreplugin/icore.h>

#include <QDialogButtonBox>
#include <QTextStream>

namespace Debugger {
namespace Internal {

const char *CdbOptionsPage::crtDbgReport = "CrtDbgReport";

struct EventsDescription {
    const char *abbreviation;
    bool hasParameter;
    const char *description;
};

// Parameters of the "sxe" command
const EventsDescription eventDescriptions[] =
{
    {"eh", false, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "C++ exception")},
    {"ct", false, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Thread creation")},
    {"et", false, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Thread exit")},
    {"ld", true,  QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Load module:")},
    {"ud", true,  QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Unload module:")},
    {"out", true, QT_TRANSLATE_NOOP("Debugger::Internal::CdbBreakEventWidget",
                                    "Output:")}
};

static inline int indexOfEvent(const QString &abbrev)
{
    const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
    for (size_t e = 0; e < eventCount; e++)
        if (abbrev == QLatin1String(eventDescriptions[e].abbreviation))
                return int(e);
    return -1;
}

CdbBreakEventWidget::CdbBreakEventWidget(QWidget *parent) : QWidget(parent)
{
    // 1 column with checkboxes only,
    // further columns with checkbox + parameter
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->setMargin(0);
    QVBoxLayout *leftLayout = new QVBoxLayout;
    QFormLayout *parameterLayout = 0;
    mainLayout->addLayout(leftLayout);
    const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
    for (size_t e = 0; e < eventCount; e++) {
        QCheckBox *cb = new QCheckBox(tr(eventDescriptions[e].description));
        QLineEdit *le = 0;
        if (eventDescriptions[e].hasParameter) {
            if (!parameterLayout) {
                parameterLayout = new QFormLayout;
                mainLayout->addSpacerItem(new QSpacerItem(20, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
                mainLayout->addLayout(parameterLayout);
            }
            le = new QLineEdit;
            parameterLayout->addRow(cb, le);
            if (parameterLayout->count() >= 6) // New column
                parameterLayout = 0;
        } else {
            leftLayout->addWidget(cb);
        }
        m_checkBoxes.push_back(cb);
        m_lineEdits.push_back(le);
    }
    setLayout(mainLayout);
}

void CdbBreakEventWidget::clear()
{
    foreach (QLineEdit *l, m_lineEdits) {
        if (l)
            l->clear();
    }
    foreach (QCheckBox *c, m_checkBoxes)
        c->setChecked(false);
}

void CdbBreakEventWidget::setBreakEvents(const QStringList &l)
{
    clear();
    // Split the list of ("eh", "out:MyOutput")
    foreach (const QString &evt, l) {
        const int colonPos = evt.indexOf(QLatin1Char(':'));
        const QString abbrev = colonPos != -1 ? evt.mid(0, colonPos) : evt;
        const int index = indexOfEvent(abbrev);
        if (index != -1)
            m_checkBoxes.at(index)->setChecked(true);
        if (colonPos != -1 && m_lineEdits.at(index))
            m_lineEdits.at(index)->setText(evt.mid(colonPos + 1));
    }
}

QString CdbBreakEventWidget::filterText(int i) const
{
    return m_lineEdits.at(i) ? m_lineEdits.at(i)->text() : QString();
}

QStringList CdbBreakEventWidget::breakEvents() const
{
    // Compile a list of ("eh", "out:MyOutput")
    QStringList rc;
    const int eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
    for (int e = 0; e < eventCount; e++) {
        if (m_checkBoxes.at(e)->isChecked()) {
            const QString filter = filterText(e);
            QString s = QLatin1String(eventDescriptions[e].abbreviation);
            if (!filter.isEmpty()) {
                s += QLatin1Char(':');
                s += filter;
            }
            rc.push_back(s);
        }
    }
    return rc;
}

CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent)
    : QWidget(parent)
    , m_breakEventWidget(new CdbBreakEventWidget)
{
    m_ui.setupUi(this);
    // Squeeze the groupbox layouts vertically to
    // accommodate all options. This page only shows on
    // Windows, which has large margins by default.

    const int margin = layout()->margin();
    const QMargins margins(margin, margin / 3, margin, margin / 3);

    m_ui.startupFormLayout->setContentsMargins(margins);

    QVBoxLayout *eventLayout = new QVBoxLayout;
    eventLayout->setContentsMargins(margins);
    eventLayout->addWidget(m_breakEventWidget);
    m_ui.eventGroupBox->setLayout(eventLayout);
    m_ui.breakCrtDbgReportCheckBox
        ->setText(CommonOptionsPage::msgSetBreakpointAtFunction(CdbOptionsPage::crtDbgReport));
    const QString hint = tr("This is useful to catch runtime error messages, for example caused by assert().");
    m_ui.breakCrtDbgReportCheckBox
        ->setToolTip(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip(CdbOptionsPage::crtDbgReport, hint));

    DebuggerCore *dc = debuggerCore();
    group.insert(dc->action(CdbAdditionalArguments), m_ui.additionalArgumentsLineEdit);
    group.insert(dc->action(CdbBreakOnCrtDbgReport), m_ui.breakCrtDbgReportCheckBox);
    group.insert(dc->action(UseCdbConsole), m_ui.consoleCheckBox);
    group.insert(dc->action(CdbBreakPointCorrection), m_ui.breakpointCorrectionCheckBox);
    group.insert(dc->action(IgnoreFirstChanceAccessViolation),
                 m_ui.ignoreFirstChanceAccessViolationCheckBox);

    m_breakEventWidget->setBreakEvents(dc->stringListSetting(CdbBreakEvents));
}

QStringList CdbOptionsPageWidget::breakEvents() const
{
    return m_breakEventWidget->breakEvents();
}

static QString stripColon(QString s)
{
    const int lastColon = s.lastIndexOf(QLatin1Char(':'));
    if (lastColon != -1)
        s.truncate(lastColon);
    return s;
}

QString CdbOptionsPageWidget::searchKeywords() const
{
    QString rc;
    QTextStream(&rc) << stripColon(m_ui.additionalArgumentsLabel->text());
    rc.remove(QLatin1Char('&'));
    return rc;
}

// ---------- CdbOptionsPage

CdbOptionsPage::CdbOptionsPage()
{
    setId("F.Cda");
    setDisplayName(tr("CDB"));
    setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
    setDisplayCategory(QCoreApplication::translate("Debugger",
        Constants::DEBUGGER_SETTINGS_TR_CATEGORY));
    setCategoryIcon(QLatin1String(Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
}

CdbOptionsPage::~CdbOptionsPage()
{
}

QWidget *CdbOptionsPage::createPage(QWidget *parent)
{
    m_widget = new CdbOptionsPageWidget(parent);
    if (m_searchKeywords.isEmpty())
        m_searchKeywords = m_widget->searchKeywords();
    return m_widget;
}

void CdbOptionsPage::apply()
{
    if (!m_widget)
        return;
    m_widget->group.apply(Core::ICore::settings());
    debuggerCore()->action(CdbBreakEvents)->setValue(m_widget->breakEvents());
}

void CdbOptionsPage::finish()
{
    if (m_widget)
        m_widget->group.finish();
}

bool CdbOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

// ---------- CdbPathsPage

class CdbPathsPageWidget : public QWidget
{
public:
    Utils::SavedActionSet group;

//    CdbPaths m_paths;
    QString m_searchKeywords;

    CdbSymbolPathListEditor *m_symbolPathListEditor;
    Utils::PathListEditor *m_sourcePathListEditor;

    CdbPathsPageWidget(QWidget *parent = 0);
};

CdbPathsPageWidget::CdbPathsPageWidget(QWidget *parent) :
    QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout(this);

    QString title = tr("Symbol Paths");
    m_searchKeywords.append(title);
    QGroupBox* gbSymbolPath = new QGroupBox(this);
    gbSymbolPath->setTitle(title);
    QVBoxLayout *gbSymbolPathLayout = new QVBoxLayout(gbSymbolPath);
    m_symbolPathListEditor = new CdbSymbolPathListEditor(gbSymbolPath);
    gbSymbolPathLayout->addWidget(m_symbolPathListEditor);

    title = tr("Source Paths");
    m_searchKeywords.append(title);
    QGroupBox* gbSourcePath = new QGroupBox(this);
    gbSourcePath->setTitle(title);
    QVBoxLayout *gbSourcePathLayout = new QVBoxLayout(gbSourcePath);
    m_sourcePathListEditor = new Utils::PathListEditor(gbSourcePath);
    gbSourcePathLayout->addWidget(m_sourcePathListEditor);

    layout->addWidget(gbSymbolPath);
    layout->addWidget(gbSourcePath);

    DebuggerCore *dc = debuggerCore();
    group.insert(dc->action(CdbSymbolPaths), m_symbolPathListEditor);
    group.insert(dc->action(CdbSourcePaths), m_sourcePathListEditor);
}

CdbPathsPage::CdbPathsPage()
    : m_widget(0)
{
    setId("F.Cdb");
    setDisplayName(tr("CDB Paths"));
    setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
    setDisplayCategory(QCoreApplication::translate("Debugger",
        Constants::DEBUGGER_SETTINGS_TR_CATEGORY));
    setCategoryIcon(QLatin1String(Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
}

CdbPathsPage::~CdbPathsPage()
{
}

QWidget *CdbPathsPage::createPage(QWidget *parent)
{
    if (!m_widget)
        m_widget = new CdbPathsPageWidget(parent);
    else
        m_widget->setParent(parent);
    return m_widget;
}

void CdbPathsPage::apply()
{
    if (m_widget)
        m_widget->group.apply(Core::ICore::settings());
}

void CdbPathsPage::finish()
{
    if (m_widget)
        m_widget->group.finish();
}

bool CdbPathsPage::matches(const QString &searchKeyWord) const
{
    return m_widget &&
            m_widget->m_searchKeywords.contains(searchKeyWord, Qt::CaseInsensitive);
}

} // namespace Internal
} // namespace Debugger
<|endoftext|>