<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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbStatisticsXMLFileWriter.h"
#include "otbStreamingStatisticsVectorImageFilter.h"

namespace otb
{
namespace Wrapper
{

class EstimateImagesStatistics: public Application
{
public:
  /** Standard class typedefs. */
  typedef EstimateImagesStatistics Self;
  typedef Application Superclass;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(EstimateImagesStatistics, otb::Application);

private:
  EstimateImagesStatistics()
  {
    SetName("EstimateImagesStatistics");
    SetDescription("Estimates mean/standard deviation for all images in the input list and optionally saves the results in an XML file");

    SetDocName("Estimate Image Statistics Application");
    SetDocLongDescription("This application estimates mean/standard deviation for all images in the input list and optionally saves the results in an XML file.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample("otbApplicationLauncherCommandLine EstimateImagesStatistics ${OTB-BIN}/bin  --il ${OTB-Data}/Input/Classification/QB_1_ortho.tif ${OTB-Data}/Input/Classification/QB_2_ortho.tif ${OTB-Data}/Input/Classification/QB_3_ortho.tif --out EstimateImageStatisticsQB123.xml");

    AddDocTag(Tags::Learning);
  }

  virtual ~EstimateImagesStatistics()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImageList, "il", "Input Image List");
    SetParameterDescription( "il", "Input Image List filename." );

    AddParameter(ParameterType_Filename, "out", "Output XML file");
    SetParameterDescription( "out", "Name of the XML file where the statistics are saved for future reuse" );
    MandatoryOff("out");
    SetParameterRole("out", Role_Output);
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    //Statistics estimator
    typedef otb::StreamingStatisticsVectorImageFilter<FloatVectorImageType> StreamingStatisticsVImageFilterType;

    // Samples
    typedef double ValueType;
    typedef itk::VariableLengthVector<ValueType> MeasurementType;

    unsigned int nbSamples = 0;
    unsigned int nbBands = 0;

    // Build a Measurement Vector of mean
    MeasurementType mean;

    // Build a MeasurementVector of variance
    MeasurementType variance;

    FloatVectorImageListType* imageList = GetParameterImageList("il");

    //Iterate over all input images
    for (unsigned int imageId = 0; imageId < imageList->Size(); ++imageId)
      {
      FloatVectorImageType* image = imageList->GetNthElement(imageId);

      if (nbBands == 0)
        {
        nbBands = image->GetNumberOfComponentsPerPixel();
        }
      else if (nbBands != image->GetNumberOfComponentsPerPixel())
        {
        itkExceptionMacro(<< "The image #" << imageId << " has " << image->GetNumberOfComponentsPerPixel()
            << " bands, while the first one has " << nbBands );
        }

      FloatVectorImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();

      //Set the measurement vectors size if it's the first iteration
      if (imageId == 0)
        {
        mean.SetSize(nbBands);
        mean.Fill(0.);
        variance.SetSize(nbBands);
        variance.Fill(0.);
        }

      // Compute Statistics of each VectorImage
      StreamingStatisticsVImageFilterType::Pointer statsEstimator = StreamingStatisticsVImageFilterType::New();
      statsEstimator->SetInput(image);
      statsEstimator->Update();
      mean += statsEstimator->GetMean();
      for (unsigned int itBand = 0; itBand < nbBands; itBand++)
        {
        variance[itBand] += (size[0] * size[1] - 1) * (statsEstimator->GetCovariance())(itBand, itBand);
        }
      //Increment nbSamples
      nbSamples += size[0] * size[1] * nbBands;
      }

    //Divide by the number of input images to get the mean over all layers
    mean /= imageList->Size();
    //Apply the pooled variance formula
    variance /= (nbSamples - imageList->Size());

    MeasurementType stddev;
    stddev.SetSize(nbBands);
    stddev.Fill(0.);
    for (unsigned int i = 0; i < variance.GetSize(); ++i)
      {
      stddev[i] = vcl_sqrt(variance[i]);
      }

    if( HasValue( "out" )==true )
      {
      // Write the Statistics via the statistic writer
      typedef otb::StatisticsXMLFileWriter<MeasurementType> StatisticsWriter;
      StatisticsWriter::Pointer writer = StatisticsWriter::New();
      writer->SetFileName(GetParameterString("out"));
      writer->AddInput("mean", mean);
      writer->AddInput("stddev", stddev);
      writer->Update();
      }
    else
      {
      std::cout<<"Mean: "<<mean<<std::endl;
      std::cout<<"Standard Deviation: "<<stddev<<std::endl;
      }
  }

  itk::LightObject::Pointer m_FilterRef;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::EstimateImagesStatistics)
<commit_msg>STYLE: log outputs redirected to the logger.<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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbStatisticsXMLFileWriter.h"
#include "otbStreamingStatisticsVectorImageFilter.h"

namespace otb
{
namespace Wrapper
{

class EstimateImagesStatistics: public Application
{
public:
  /** Standard class typedefs. */
  typedef EstimateImagesStatistics Self;
  typedef Application Superclass;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(EstimateImagesStatistics, otb::Application);

private:
  EstimateImagesStatistics()
  {
    SetName("EstimateImagesStatistics");
    SetDescription("Estimates mean/standard deviation for all images in the input list and optionally saves the results in an XML file");

    SetDocName("Estimate Image Statistics Application");
    SetDocLongDescription("This application estimates mean/standard deviation for all images in the input list and optionally saves the results in an XML file.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample("otbApplicationLauncherCommandLine EstimateImagesStatistics ${OTB-BIN}/bin  --il ${OTB-Data}/Input/Classification/QB_1_ortho.tif ${OTB-Data}/Input/Classification/QB_2_ortho.tif ${OTB-Data}/Input/Classification/QB_3_ortho.tif --out EstimateImageStatisticsQB123.xml");

    AddDocTag(Tags::Learning);
  }

  virtual ~EstimateImagesStatistics()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImageList, "il", "Input Image List");
    SetParameterDescription( "il", "Input Image List filename." );

    AddParameter(ParameterType_Filename, "out", "Output XML file");
    SetParameterDescription( "out", "Name of the XML file where the statistics are saved for future reuse" );
    MandatoryOff("out");
    SetParameterRole("out", Role_Output);
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    //Statistics estimator
    typedef otb::StreamingStatisticsVectorImageFilter<FloatVectorImageType> StreamingStatisticsVImageFilterType;

    // Samples
    typedef double ValueType;
    typedef itk::VariableLengthVector<ValueType> MeasurementType;

    unsigned int nbSamples = 0;
    unsigned int nbBands = 0;

    // Build a Measurement Vector of mean
    MeasurementType mean;

    // Build a MeasurementVector of variance
    MeasurementType variance;

    FloatVectorImageListType* imageList = GetParameterImageList("il");

    //Iterate over all input images
    for (unsigned int imageId = 0; imageId < imageList->Size(); ++imageId)
      {
      FloatVectorImageType* image = imageList->GetNthElement(imageId);

      if (nbBands == 0)
        {
        nbBands = image->GetNumberOfComponentsPerPixel();
        }
      else if (nbBands != image->GetNumberOfComponentsPerPixel())
        {
        itkExceptionMacro(<< "The image #" << imageId << " has " << image->GetNumberOfComponentsPerPixel()
            << " bands, while the first one has " << nbBands );
        }

      FloatVectorImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();

      //Set the measurement vectors size if it's the first iteration
      if (imageId == 0)
        {
        mean.SetSize(nbBands);
        mean.Fill(0.);
        variance.SetSize(nbBands);
        variance.Fill(0.);
        }

      // Compute Statistics of each VectorImage
      StreamingStatisticsVImageFilterType::Pointer statsEstimator = StreamingStatisticsVImageFilterType::New();
      statsEstimator->SetInput(image);
      statsEstimator->Update();
      mean += statsEstimator->GetMean();
      for (unsigned int itBand = 0; itBand < nbBands; itBand++)
        {
        variance[itBand] += (size[0] * size[1] - 1) * (statsEstimator->GetCovariance())(itBand, itBand);
        }
      //Increment nbSamples
      nbSamples += size[0] * size[1] * nbBands;
      }

    //Divide by the number of input images to get the mean over all layers
    mean /= imageList->Size();
    //Apply the pooled variance formula
    variance /= (nbSamples - imageList->Size());

    MeasurementType stddev;
    stddev.SetSize(nbBands);
    stddev.Fill(0.);
    for (unsigned int i = 0; i < variance.GetSize(); ++i)
      {
      stddev[i] = vcl_sqrt(variance[i]);
      }

    if( HasValue( "out" )==true )
      {
      // Write the Statistics via the statistic writer
      typedef otb::StatisticsXMLFileWriter<MeasurementType> StatisticsWriter;
      StatisticsWriter::Pointer writer = StatisticsWriter::New();
      writer->SetFileName(GetParameterString("out"));
      writer->AddInput("mean", mean);
      writer->AddInput("stddev", stddev);
      writer->Update();
      }
    else
      {
      otbAppLogINFO("Mean: "<<mean<<std::endl);
      otbAppLogINFO("Standard Deviation: "<<stddev<<std::endl);
      }
  }

  itk::LightObject::Pointer m_FilterRef;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::EstimateImagesStatistics)
<|endoftext|>


<commit_before>//
//  EnvelopeGeneratorBase.cpp
//  AudioKit Core
//
//  Created by Shane Dunne, revision history on Github.
//  Copyright © 2018 AudioKit. All rights reserved.
//
#include "EnvelopeGeneratorBase.hpp"
#include <cmath>

namespace AudioKitCore
{

    void ExponentialSegmentGenerator::reset(double initialValue, double targetValue, double tco, int segmentLengthSamples)
    {
        output = segmentLengthSamples > 0 ? initialValue : targetValue;
        target = targetValue;
        isHorizontal = targetValue == initialValue;
        isLinear = tco <= 0.0;
        isRising = targetValue > initialValue;

        printf("initVal %f targetVal %f output %f target %f  len %i\n\n", initialValue, targetValue, output, target, segmentLengthSamples);
        if (isHorizontal)
        {
            tcount = 0;
            segLength = segmentLengthSamples;
        }
        else if (isLinear)
        {
            if (segmentLengthSamples <= 0)
                coefficient = target - output;
            else
                coefficient = (targetValue - initialValue) / segmentLengthSamples;
        }
        else
        {
            if (segmentLengthSamples == 0)
            {
                coefficient = 0.0;
                offset = target;
            }
            else
            {
                // Correction to Pirkle (who uses delta = 1.0 always)
                // According to Redmon (who only discusses the delta = 1.0 case), delta should be defined thus
                double delta = abs(targetValue - initialValue);
                coefficient = exp(-log((delta + tco) / tco) / segmentLengthSamples);
                if (isRising)
                    offset = (target + tco) * (1.0 - coefficient);
                else
                    offset = (target - tco) * (1.0 - coefficient);
            }
        }
    }

    void MultiSegmentEnvelopeGenerator::setupCurSeg()
    {
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        double initValue = seg.initialValue;
        double targetValue = seg.finalValue;
        bool isHorizontal = seg.initialValue == seg.finalValue;
        if (seg.lengthSamples == 0 && isHorizontal) { // if flat and 0 len, skip it completely
            targetValue = output;
            initValue = output;
        }
        printf("autoAdvance %i: init %f final %f len %i - init %f target %f \n", curSegIndex, seg.initialValue, seg.finalValue, seg.lengthSamples, initValue, targetValue);
        ExponentialSegmentGenerator::reset(initValue, targetValue, seg.tco, seg.lengthSamples);
    }

    void MultiSegmentEnvelopeGenerator::setupCurSeg(double initValue)
    {
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        double targetValue = seg.finalValue;
        bool isHorizontal = seg.initialValue == seg.finalValue;
        int length = seg.lengthSamples;
        if (seg.lengthSamples == 0 && isHorizontal) { // if flat and 0 len, skip it completely
            targetValue = output;
        }
        printf("manualAdvance %i: init %f final %f len %i - init %f target %f \n", curSegIndex, seg.initialValue, seg.finalValue, length, initValue, targetValue);
        ExponentialSegmentGenerator::reset(initValue, targetValue, seg.tco, seg.lengthSamples);
    }

    void MultiSegmentEnvelopeGenerator::reset(Descriptor* pDesc, int initialSegmentIndex)
    {
        segments = pDesc;
        curSegIndex = initialSegmentIndex;
        setupCurSeg();
    }

    void MultiSegmentEnvelopeGenerator::advanceToSegment(int segIndex)
    {
        curSegIndex = segIndex;
        skipEmptySegments();
        setupCurSeg(output); //we are advancing, not restarting, so always start from the value we are currently at
    }

    void MultiSegmentEnvelopeGenerator::startAtSegment(int segIndex)
    {
        curSegIndex = segIndex;
        skipEmptySegments();
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        setupCurSeg(seg.initialValue); // we are restarting, not advancing, so  always start from the first vlaue we get to
    }

    void MultiSegmentEnvelopeGenerator::skipEmptySegments()
    {
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        int length = seg.lengthSamples;
        while (length == 0) { //skip any segments that are 0-length
            curSegIndex++;
            seg = (*segments)[curSegIndex];
            length = seg.lengthSamples;
        }
    }

}
<commit_msg>glitched version - trying to optimise but getting different length values for segments on second note<commit_after>//
//  EnvelopeGeneratorBase.cpp
//  AudioKit Core
//
//  Created by Shane Dunne, revision history on Github.
//  Copyright © 2018 AudioKit. All rights reserved.
//
#include "EnvelopeGeneratorBase.hpp"
#include <cmath>

namespace AudioKitCore
{

    void ExponentialSegmentGenerator::reset(double initialValue, double targetValue, double tco, int segmentLengthSamples)
    {
        output = segmentLengthSamples > 0 ? initialValue : targetValue;
        target = targetValue;
        isHorizontal = targetValue == initialValue;
        isLinear = tco <= 0.0;
        isRising = targetValue > initialValue;

        printf("initVal %f targetVal %f output %f target %f  len %i\n\n", initialValue, targetValue, output, target, segmentLengthSamples);
        if (isHorizontal)
        {
            tcount = 0;
            segLength = segmentLengthSamples;
        }
        else if (isLinear)
        {
            if (segmentLengthSamples <= 0)
                coefficient = target - output;
            else
                coefficient = (targetValue - initialValue) / segmentLengthSamples;
        }
        else
        {
            if (segmentLengthSamples == 0)
            {
                coefficient = 0.0;
                offset = target;
            }
            else
            {
                // Correction to Pirkle (who uses delta = 1.0 always)
                // According to Redmon (who only discusses the delta = 1.0 case), delta should be defined thus
                double delta = abs(targetValue - initialValue);
                coefficient = exp(-log((delta + tco) / tco) / segmentLengthSamples);
                if (isRising)
                    offset = (target + tco) * (1.0 - coefficient);
                else
                    offset = (target - tco) * (1.0 - coefficient);
            }
        }
    }

    void MultiSegmentEnvelopeGenerator::setupCurSeg()
    {
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        double initValue = seg.initialValue;
        double targetValue = seg.finalValue;
        bool isHorizontal = seg.initialValue == seg.finalValue;
        if (isHorizontal) { // if flat, use current values
            targetValue = output;
            initValue = output;
        }
        printf("autoAdvance %i: init %f final %f len %i - init %f target %f \n", curSegIndex, seg.initialValue, seg.finalValue, seg.lengthSamples, initValue, targetValue);
        ExponentialSegmentGenerator::reset(initValue, targetValue, seg.tco, seg.lengthSamples);
    }

    void MultiSegmentEnvelopeGenerator::setupCurSeg(double initValue)
    {
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        double targetValue = seg.finalValue;
        bool isHorizontal = seg.initialValue == seg.finalValue;
        if (isHorizontal) { // if flat, use current values
            targetValue = initValue;
        }
        printf("manualAdvance %i: init %f final %f len %i - init %f target %f \n", curSegIndex, seg.initialValue, seg.finalValue, seg.lengthSamples, initValue, targetValue);
        ExponentialSegmentGenerator::reset(initValue, targetValue, seg.tco, seg.lengthSamples);
    }

    void MultiSegmentEnvelopeGenerator::reset(Descriptor* pDesc, int initialSegmentIndex)
    {
        segments = pDesc;
        curSegIndex = initialSegmentIndex;
        setupCurSeg();
    }

    void MultiSegmentEnvelopeGenerator::advanceToSegment(int segIndex)
    {
        curSegIndex = segIndex;
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        int length = seg.lengthSamples;
        printf("advance seg %i is %i\n", curSegIndex, length);
        skipEmptySegments();
        setupCurSeg(output); //we are advancing, not restarting, so always start from the value we are currently at
    }

    void MultiSegmentEnvelopeGenerator::startAtSegment(int segIndex)
    {
        curSegIndex = segIndex;
        skipEmptySegments();
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        setupCurSeg(seg.initialValue); // we are restarting, not advancing, so  always start from the first vlaue we get to
    }

    void MultiSegmentEnvelopeGenerator::skipEmptySegments()
    {
        SegmentDescriptor& seg = (*segments)[curSegIndex];
        int length = seg.lengthSamples;
        printf("seg %i is %i\n", curSegIndex, length);
        while (length == 0) { //skip any segments that are 0-length
            printf("skipping seg %i\n", curSegIndex);
            ++curSegIndex;
            seg = (*segments)[curSegIndex];
            length = seg.lengthSamples;
        }
    }

}
<|endoftext|>


<commit_before>#ifndef assert_hh_INCLUDED
#define assert_hh_INCLUDED

namespace Kakoune
{

class StringView;

// return true if user asked to ignore the error
bool notify_fatal_error(StringView message);

void on_assert_failed(const char* message);

}

#define STRINGIFY(X) #X
#define TOSTRING(X) STRINGIFY(X)

#ifdef KAK_DEBUG
    #define kak_assert(...) \
        if (not (__VA_ARGS__)) \
            on_assert_failed("assert failed \"" #__VA_ARGS__ \
                             "\" at " __FILE__ ":" TOSTRING(__LINE__))
#else
    #define kak_assert(...)
#endif

#endif // assert_hh_INCLUDED
<commit_msg>Properly wrap `kak_assert` into a do-while scope<commit_after>#ifndef assert_hh_INCLUDED
#define assert_hh_INCLUDED

namespace Kakoune
{

class StringView;

// return true if user asked to ignore the error
bool notify_fatal_error(StringView message);

void on_assert_failed(const char* message);

}

#define STRINGIFY(X) #X
#define TOSTRING(X) STRINGIFY(X)

#ifdef KAK_DEBUG
    #define kak_assert(...) do { \
        if (not (__VA_ARGS__)) \
            on_assert_failed("assert failed \"" #__VA_ARGS__ \
                             "\" at " __FILE__ ":" TOSTRING(__LINE__)); \
    } while (0)
#else
    #define kak_assert(...) do {} while (0)
#endif

#endif // assert_hh_INCLUDED
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/c_api_internal.h"
#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
#include "tensorflow/lite/kernels/internal/tensor.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"

namespace tflite {
namespace ops {
namespace builtin {
namespace range {
namespace {

constexpr int kStartTensor = 0;
constexpr int kLimitTensor = 1;
constexpr int kDeltaTensor = 2;
constexpr int kOutputTensor = 0;

template <typename T>
TfLiteStatus GetSize(TfLiteContext* context, T start, T limit, T delta,
                     int* size) {
  TF_LITE_ENSURE(context, !std::equal_to<T>()(delta, 0));
  TF_LITE_ENSURE(context,
                 (start > limit && delta < 0) || (start < limit && delta > 0));
  *size =
      (std::is_integral<T>::value
           ? ((std::abs(limit - start) + std::abs(delta) - 1) / std::abs(delta))
           : std::ceil(std::abs((limit - start) / delta)));
  return kTfLiteOk;
}

TfLiteStatus ResizeOutput(TfLiteContext* context, const TfLiteTensor* start,
                          const TfLiteTensor* limit, const TfLiteTensor* delta,
                          TfLiteTensor* output) {
  // The output will always be a 1-d array.
  int size = 0;
  switch (start->type) {
    case kTfLiteInt32: {
      TF_LITE_ENSURE_OK(context,
                        GetSize(context, *GetTensorData<int32_t>(start),
                                *GetTensorData<int32_t>(limit),
                                *GetTensorData<int32_t>(delta), &size));
      break;
    }
    case kTfLiteFloat32: {
      TF_LITE_ENSURE_OK(context, GetSize(context, *GetTensorData<float>(start),
                                         *GetTensorData<float>(limit),
                                         *GetTensorData<float>(delta), &size));
      break;
    }
    default: {
      context->ReportError(context, "Unknown data type: %d", start->type);
      return kTfLiteError;
    }
  }
  TfLiteIntArray* output_shape_array = TfLiteIntArrayCreate(1);
  output_shape_array->data[0] = size;
  return context->ResizeTensor(context, output, output_shape_array);
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 3);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);

  const TfLiteTensor* start = GetInput(context, node, kStartTensor);
  const TfLiteTensor* limit = GetInput(context, node, kLimitTensor);
  const TfLiteTensor* delta = GetInput(context, node, kDeltaTensor);
  // Make sure all the inputs are scalars.
  TF_LITE_ENSURE_EQ(context, NumDimensions(start), 0);
  TF_LITE_ENSURE_EQ(context, NumDimensions(limit), 0);
  TF_LITE_ENSURE_EQ(context, NumDimensions(delta), 0);

  // Currently only supports int32 and float.
  // TODO(b/117912892): Support quantization as well.
  const auto dtype = start->type;
  TF_LITE_ENSURE(context, dtype == kTfLiteInt32 || dtype == kTfLiteFloat32);
  TF_LITE_ENSURE_EQ(context, limit->type, dtype);
  TF_LITE_ENSURE_EQ(context, delta->type, dtype);
  TfLiteTensor* output = GetOutput(context, node, kOutputTensor);

  output->type = dtype;

  if (IsConstantTensor(start) && IsConstantTensor(limit) &&
      IsConstantTensor(delta)) {
    return ResizeOutput(context, start, limit, delta, output);
  }

  SetTensorToDynamic(output);
  return kTfLiteOk;
}

template <typename T>
void EvalImpl(const TfLiteTensor* start, const TfLiteTensor* delta,
              TfLiteTensor* output) {
  const T start_value = *GetTensorData<T>(start);
  const T delta_value = *GetTensorData<T>(delta);
  T* output_data = GetTensorData<T>(output);
  const int num_elements = NumElements(output);
  T value = start_value;
  for (int i = 0; i < num_elements; ++i) {
    output_data[i] = value;
    value += delta_value;
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteTensor* start = GetInput(context, node, kStartTensor);
  const TfLiteTensor* limit = GetInput(context, node, kLimitTensor);
  const TfLiteTensor* delta = GetInput(context, node, kDeltaTensor);

  TfLiteTensor* output = GetOutput(context, node, kOutputTensor);

  if (IsDynamicTensor(output)) {
    TF_LITE_ENSURE_OK(context,
                      ResizeOutput(context, start, limit, delta, output));
  }

  switch (output->type) {
    case kTfLiteInt32: {
      EvalImpl<int32_t>(start, delta, output);
      break;
    }
    case kTfLiteFloat32: {
      EvalImpl<float>(start, delta, output);
      break;
    }
    default: {
      context->ReportError(context, "Unsupported data type: %d", output->type);
      return kTfLiteError;
    }
  }
  return kTfLiteOk;
}

}  // namespace
}  // namespace range

TfLiteRegistration* Register_RANGE() {
  static TfLiteRegistration r = {nullptr, nullptr, range::Prepare, range::Eval};
  return &r;
}

}  // namespace builtin
}  // namespace ops
}  // namespace tflite
<commit_msg>[1] Review comments handled<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/c_api_internal.h"
#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
#include "tensorflow/lite/kernels/internal/tensor.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"

namespace tflite {
namespace ops {
namespace builtin {
namespace range {
namespace {

constexpr int kStartTensor = 0;
constexpr int kLimitTensor = 1;
constexpr int kDeltaTensor = 2;
constexpr int kOutputTensor = 0;

template <typename T>
TfLiteStatus GetSize(TfLiteContext* context, T start, T limit, T delta,
                     int* size) {
  TF_LITE_ENSURE(context, !std::equal_to<T>()(delta, 0));
  TF_LITE_ENSURE(context,
                 (start > limit && delta < 0) || (start < limit && delta > 0));
  *size =
      (std::is_integral<T>::value
           ? ((std::abs(limit - start) + std::abs(delta) - 1) / std::abs(delta))
           : std::ceil(std::abs((limit - start) / delta)));
  return kTfLiteOk;
}

TfLiteStatus ResizeOutput(TfLiteContext* context, const TfLiteTensor* start,
                          const TfLiteTensor* limit, const TfLiteTensor* delta,
                          TfLiteTensor* output) {
  // The output will always be a 1-d array.
  int size = 0;
  switch (start->type) {
    case kTfLiteInt32: {
      TF_LITE_ENSURE_OK(context,
                        GetSize(context, *GetTensorData<int32_t>(start),
                                *GetTensorData<int32_t>(limit),
                                *GetTensorData<int32_t>(delta), &size));
      break;
    }
    case kTfLiteFloat32: {
      TF_LITE_ENSURE_OK(context, GetSize(context, *GetTensorData<float>(start),
                                         *GetTensorData<float>(limit),
                                         *GetTensorData<float>(delta), &size));
      break;
    }
    default: {
      context->ReportError(context, "Unknown data type: %d", start->type);
      return kTfLiteError;
    }
  }
  TfLiteIntArray* output_shape_array = TfLiteIntArrayCreate(1);
  output_shape_array->data[0] = size;
  return context->ResizeTensor(context, output, output_shape_array);
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 3);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);

  const TfLiteTensor* start = GetInput(context, node, kStartTensor);
  const TfLiteTensor* limit = GetInput(context, node, kLimitTensor);
  const TfLiteTensor* delta = GetInput(context, node, kDeltaTensor);
  // Make sure all the inputs are scalars.
  TF_LITE_ENSURE_EQ(context, NumDimensions(start), 0);
  TF_LITE_ENSURE_EQ(context, NumDimensions(limit), 0);
  TF_LITE_ENSURE_EQ(context, NumDimensions(delta), 0);

  // Currently only supports int32 and float.
  // TODO(b/117912892): Support quantization as well.
  const auto dtype = start->type;
  TF_LITE_ENSURE_EQ(context, limit->type, dtype);
  TF_LITE_ENSURE_EQ(context, delta->type, dtype);
  TfLiteTensor* output = GetOutput(context, node, kOutputTensor);

  switch (dtype) {
    case kTfLiteInt32:
    case kTfLiteFloat32:
      output->type = dtype;
      break;
    default:
      context->ReportError(context, "Unknown index output data type: %s",
                           TfLiteTypeGetName(dtype));
      return kTfLiteError;
  }

  if (IsConstantTensor(start) && IsConstantTensor(limit) &&
      IsConstantTensor(delta)) {
    return ResizeOutput(context, start, limit, delta, output);
  }

  SetTensorToDynamic(output);
  return kTfLiteOk;
}

template <typename T>
void EvalImpl(const TfLiteTensor* start, const TfLiteTensor* delta,
              TfLiteTensor* output) {
  const T start_value = *GetTensorData<T>(start);
  const T delta_value = *GetTensorData<T>(delta);
  T* output_data = GetTensorData<T>(output);
  const int num_elements = NumElements(output);
  T value = start_value;
  for (int i = 0; i < num_elements; ++i) {
    output_data[i] = value;
    value += delta_value;
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteTensor* start = GetInput(context, node, kStartTensor);
  const TfLiteTensor* limit = GetInput(context, node, kLimitTensor);
  const TfLiteTensor* delta = GetInput(context, node, kDeltaTensor);

  TfLiteTensor* output = GetOutput(context, node, kOutputTensor);

  if (IsDynamicTensor(output)) {
    TF_LITE_ENSURE_OK(context,
                      ResizeOutput(context, start, limit, delta, output));
  }

  switch (output->type) {
    case kTfLiteInt32: {
      EvalImpl<int32_t>(start, delta, output);
      break;
    }
    case kTfLiteFloat32: {
      EvalImpl<float>(start, delta, output);
      break;
    }
    default: {
      context->ReportError(context, "Unsupported data type: %d", output->type);
      return kTfLiteError;
    }
  }
  return kTfLiteOk;
}

}  // namespace
}  // namespace range

TfLiteRegistration* Register_RANGE() {
  static TfLiteRegistration r = {nullptr, nullptr, range::Prepare, range::Eval};
  return &r;
}

}  // namespace builtin
}  // namespace ops
}  // namespace tflite
<|endoftext|>


<commit_before>/////////////////////////////////////////
//
//             OpenLieroX
//
// code under LGPL, based on JasonBs work,
// enhanced by Dark Charlie and Albert Zeyer
//
//
/////////////////////////////////////////

// Client class - Sending routines
// Created 22/7/02
// Jason Boettcher

#include "LieroX.h"

#include "CClientNetEngine.h"
#include "StringUtils.h"
#include "CClient.h"
#include "Protocol.h"
#include "CWorm.h"
#include "MathLib.h"
#include "ChatCommand.h"
#include "OLXCommand.h"
#include "EndianSwap.h"
#include "CServer.h"
#include "AuxLib.h"
#include "CChannel.h"
#include "DeprecatedGUI/Menu.h"
#include "IRC.h"
#include "OLXConsole.h"
#include "game/Game.h"

// declare them only locally here as nobody really should use them explicitly
std::string OldLxCompatibleString(const std::string &Utf8String);

///////////////////
// Send the worm details
void CClientNetEngine::SendWormDetails()
{
	// Don't flood packets so often
	// we are checking in w->checkPacketNeeded() if we need to send an update
	// we are checking with bandwidth if we should add an update
	/*if ((tLX->currentTime - fLastUpdateSent) <= tLXOptions->fUpdatePeriod)
		if (tGameInfo.iGameType != GME_LOCAL)
			return; */

	// TODO: Have we always used the limitcheck from GameServer here?
	// We should perhaps move it out from GameServer. Looks a bit strange here to use something from GameServer.
	if(	tLX->iGameType == GME_JOIN // we are a client in a netgame
	   && !GameServer::checkUploadBandwidth(client->getChannel()->getOutgoingRate()) )
		return;

	if(!game.gameScript()->gusEngineUsed()) {
		CBytestream bs;
		uint i;

		// If all my worms are dead, don't send
		bool Alive = false;
		for(i=0;i<client->iNumWorms;i++) {
			if(client->cLocalWorms[i] && client->cLocalWorms[i]->getAlive()) {
				Alive = true;
				break;
			}
		}

		if(!Alive)
			return;

		// Check if we need to write the state update
		bool update = false;
		for(i = 0; i < client->iNumWorms; i++)
			if (client->cLocalWorms[i] && client->cLocalWorms[i]->checkPacketNeeded())  {
				update = true;
				break;
			}

		// No update, just quit
		if (!update)
			return;

		// Write the update
		bs.writeByte(C2S_UPDATE);

		for(i = 0; i < client->iNumWorms; i++)
			if(client->cLocalWorms[i])
				client->cLocalWorms[i]->writePacket(&bs, false, NULL);

		client->bsUnreliable.Append(&bs);
	}

	client->fLastUpdateSent = tLX->currentTime;
}

void CClientNetEngine::SendGameReady()
{
	CBytestream bs;
	bs.writeByte(C2S_IMREADY);

	if(client->serverChoosesWeapons()) {
		bs.writeByte(0);
	} else {
		std::list<CWorm*> worms;
		for(unsigned int i=0;i<client->iNumWorms;i++)
			if(client->cLocalWorms[i]) worms.push_back(client->cLocalWorms[i]);

		// Send my worm's weapon details
		bs.writeByte(worms.size());
		for(std::list<CWorm*>::iterator i = worms.begin(); i != worms.end(); ++i)
			(*i)->writeWeapons( &bs );
	}

	client->cNetChan->AddReliablePacketToSend(bs);
}

///////////////////
// Send a death
void CClientNetEngine::SendDeath(int victim, int killer)
{
	CBytestream bs;

	bs.writeByte(C2S_DEATH);
	bs.writeInt(victim,1);
	bs.writeInt(killer,1);

	client->cNetChan->AddReliablePacketToSend(bs);
}

void CClientNetEngineBeta9::SendDeath(int victim, int killer)
{
	// If we have some damage reports in buffer send them first so clients won't sum up updated damage score and reported damage packet sent later
	SendReportDamage(true);

	CClientNetEngine::SendDeath(victim, killer);
}

///////////////////
// Send a string of text
void CClientNetEngine::SendText(const std::string& sText, std::string sWormName)
{
	if(HandleDebugCommand(sText)) return;

	bool chat_command = sText.size() >= 2 && sText[0] == '/' && sText[1] != '/';

	if (sText.find("/irc ") == 0 || sText.find("/chat ") == 0)  { // Send text to IRC
		bool res = false;
		if (GetGlobalIRC())
			res = GetGlobalIRC()->sendChat(sText.substr(sText.find(' ') + 1));
		if (!res)
			client->cChatbox.AddText("Could not send the IRC message", tLX->clNetworkText, TXT_NETWORK, tLX->currentTime);
		return;
	}

	// We can safely send long messages to servers >= beta8
	if (client->getServerVersion() >= OLXBetaVersion(8))  {

		// HTML support since beta 8
		SendTextInternal(OldLxCompatibleString(sText), sWormName);

	// <=beta7 server
	} else {

		if (chat_command &&
			client->getServerVersion() < OLXBetaVersion(3) && // <beta3 clients don't have chat command support
			sText.find("/me ") != 0) // Ignores "/me" special command
		{
			// Try if we can execute the same command in console (mainly for "/suicide" command to work on all servers)
			if( !subStrCaseEqual( sText.substr(1), "suicide", 7 ) )
			    Con_Execute(sText.substr(1));
			else
				client->cChatbox.AddText("HINT: server cannot execute commands, only OLX beta3+ can", tLX->clNotice, TXT_NOTICE, tLX->currentTime);

			return;

		} else if (chat_command &&
				   client->getServerVersion() >= OLXBetaVersion(3)) {
			// we don't have to split chat commands
			// "/me ..." is also save, because server uses SendGlobalText for sending and it splits the text there
			SendTextInternal(OldLxCompatibleString(sText), sWormName);

		} else { // we can savely split the message (and we have to)

			// If the text is too long, split it in smaller pieces and then send (backward comaptibility)
			int name_w = tLX->cFont.GetWidth(sWormName + ": ");
			std::vector<std::string> split = splitstring(StripHtmlTags(sText), 63,
				client->iNetStatus == NET_CONNECTED ? 600 - name_w : 300 - name_w, tLX->cFont);

			// Check
			if (split.size() == 0)  {  // More than weird...
				SendTextInternal(OldLxCompatibleString(StripHtmlTags(sText)), sWormName);
				return;
			}

			// Send the first chunk
			SendTextInternal(OldLxCompatibleString(split[0]), sWormName);

			// Send the text
			for (std::vector<std::string>::const_iterator it = split.begin() + 1; it != split.end(); it++)
				SendTextInternal(OldLxCompatibleString(*it), "");
		}
	}
}

void CClientNetEngineBeta7::SendChatCommandCompletionRequest(const std::string& startStr) {
	CBytestream bs;
	bs.writeByte(C2S_CHATCMDCOMPLREQ);
	bs.writeString(startStr);

	client->cNetChan->AddReliablePacketToSend(bs);
}

void CClientNetEngineBeta7::SendAFK(int wormid, AFK_TYPE afkType, const std::string & message ) {
	if( client->getServerVersion() < OLXBetaVersion(7) )
		return;

	std::string msg = message;
	if( msg == "" )
	{
		switch(afkType) {
			case AFK_BACK_ONLINE: break;
			case AFK_TYPING_CHAT: msg = "(typing)"; break;
			case AFK_AWAY: msg = "(away)"; break;
			case AFK_SELECTING_WPNS: msg = "(selecting weapons)"; break;
			case AFK_CONSOLE: msg = "(console)"; break;
			case AFK_MENU: msg = "(menu)"; break;
		}
	}

	for( int i=0; i < client->getNumWorms(); i++ )
		if(	client->getWorm(i)->getID() == wormid )
			client->getWorm(i)->setAFK(afkType, msg);

	CBytestream bs;
	bs.writeByte(C2S_AFK);
	bs.writeByte(wormid);
	bs.writeByte(afkType);
	if(msg.size() > 127)
		msg = msg.substr(0, 127);
	bs.writeString(msg);

	client->cNetChan->AddReliablePacketToSend(bs);
}

/////////////////////
// Internal function for text sending, does not do any checks or parsing
void CClientNetEngine::SendTextInternal(const std::string& sText, const std::string& sWormName)
{
	if(!client) {
		errors << "CClientNetEngine::SendTextInternal(" << sWormName << ": " << sText << "): my client is unset" << endl;
		return;
	}

	if(!client->cNetChan) {
		errors << "CClientNetEngine::SendTextInternal(" << sWormName << ": " << sText << "): cNetChan of my client (" << client->debugName() << ") is unset" << endl;
		return;
	}

	CBytestream bs;
	bs.writeByte(C2S_CHATTEXT);
	if (sWormName.size() == 0)
		bs.writeString(sText);
	else if( sText.find("/me ") == 0 && client->getServerVersion() < OLXBetaVersion(0,58,1) )	// "/me " chat command
		bs.writeString( "* " + sWormName + " " + sText.substr(4)); // Add star so clients with empty name won't fake others
	else	// "/me " command is server-sided on Beta9
		bs.writeString(sWormName + ": " + sText);

	client->cNetChan->AddReliablePacketToSend(bs);
}

#ifdef FUZZY_ERROR_TESTING
//////////////////
// Send a random packet to server (used for debugging)
void CClientNetEngine::SendRandomPacket()
{
	// don't send random packets from the local client to our own server
	if( tGameInfo.iGameType != GME_JOIN ) return;

	CBytestream bs;

	int random_length = GetRandomInt(50);
	for (int i=0; i < random_length; i++)
		bs.writeByte((uchar)GetRandomInt(255));

	client->cNetChan->AddReliablePacketToSend(bs);

	bs.Clear();

	// Test connectionless packets
	if (GetRandomInt(100) >= 75)  {
		bs.writeInt(-1, 4);
		static const std::string commands[] = { "lx::getchallenge", "lx::connect", "lx::ping", "lx::query",
			"lx::getinfo", "lx::wantsjoin", "lx::traverse", "lx::registered"};
		bs.writeString(commands[GetRandomInt(500) % (sizeof(commands)/sizeof(std::string))]);
		for (int i=0; i < random_length; i++)
			bs.writeByte((uchar)GetRandomInt(255));
		SetRemoteNetAddr(client->tSocket, client->cNetChan->getAddress());
		bs.Send(client->tSocket);
	}
}
#endif

void CClientNetEngine::SendGrabBonus(int id, int wormid)
{
	CBytestream bs;
	bs.writeByte(C2S_GRABBONUS);
	bs.writeByte(id);
	bs.writeByte(wormid);
	bs.writeByte(client->cRemoteWorms[wormid].getCurrentWeapon());

	client->cNetChan->AddReliablePacketToSend(bs);
}

void CClientNetEngine::SendUpdateLobby(bool ready)
{
	CBytestream bs;
	bs.writeByte(C2S_UPDATELOBBY);
	bs.writeByte(ready);
	client->getChannel()->AddReliablePacketToSend(bs);
}

void CClientNetEngine::SendDisconnect()
{
	CBytestream bs;

	bs.writeByte(C2S_DISCONNECT);

	// Send the pack a few times to make sure the server gets the packet
	if( client->cNetChan != NULL)
		for(int i=0;i<3;i++)
			client->cNetChan->Transmit(&bs);
}

void CClientNetEngine::SendFileData()
{
	CBytestream bs;
	bs.writeByte(C2S_SENDFILE);
	client->getUdpFileDownloader()->send(&bs);
	client->getChannel()->AddReliablePacketToSend(bs);
}

void CClientNetEngineBeta9::QueueReportDamage(int victim, float damage, int offender)
{
	// Buffer up all damage and send it once per 0.1 second for LAN nettype, or once per 0.3 seconds for modem
	std::pair< int, int > dmgPair = std::make_pair( victim, offender );
	if( cDamageReport.count( dmgPair ) == 0 )
		cDamageReport[ dmgPair ] = 0;
	cDamageReport[ dmgPair ] += damage;

	SendReportDamage();
}

void CClientNetEngineBeta9::SendReportDamage(bool flush)
{
	if( ! flush && tLX->currentTime - fLastDamageReportSent < 0.1f * ( NST_LOCAL - client->getNetSpeed() ) )
		return;

	CBytestream bs;

	for( std::map< std::pair< int, int >, float > :: iterator it = cDamageReport.begin();
			it != cDamageReport.end(); it++ )
	{
		int victim = it->first.first;
		int offender = it->first.second;
		float damage = it->second;
		bs.writeByte(C2S_REPORTDAMAGE);
		bs.writeByte(victim);
		bs.writeFloat(damage);
		bs.writeByte(offender);
	}

	client->cNetChan->AddReliablePacketToSend(bs);

	cDamageReport.clear();
	fLastDamageReportSent = tLX->currentTime;
}

void CClientNetEngineBeta9NewNet::SendNewNetChecksum()
{
	CBytestream bs;
	bs.writeByte(C2S_NEWNET_CHECKSUM);
	AbsTime time;
	unsigned checksum = NewNet::GetChecksum( &time );
	bs.writeInt(checksum, 4);
	bs.writeInt((unsigned)time.milliseconds(), 4);
	client->cNetChan->AddReliablePacketToSend(bs);
}
<commit_msg>cleanup<commit_after>/////////////////////////////////////////
//
//             OpenLieroX
//
// code under LGPL, based on JasonBs work,
// enhanced by Dark Charlie and Albert Zeyer
//
//
/////////////////////////////////////////

// Client class - Sending routines
// Created 22/7/02
// Jason Boettcher

#include "LieroX.h"

#include "CClientNetEngine.h"
#include "StringUtils.h"
#include "CClient.h"
#include "Protocol.h"
#include "CWorm.h"
#include "MathLib.h"
#include "ChatCommand.h"
#include "OLXCommand.h"
#include "EndianSwap.h"
#include "CServer.h"
#include "AuxLib.h"
#include "CChannel.h"
#include "DeprecatedGUI/Menu.h"
#include "IRC.h"
#include "OLXConsole.h"
#include "game/Game.h"

// declare them only locally here as nobody really should use them explicitly
std::string OldLxCompatibleString(const std::string &Utf8String);

///////////////////
// Send the worm details
void CClientNetEngine::SendWormDetails()
{
	// Don't flood packets so often
	// we are checking in w->checkPacketNeeded() if we need to send an update
	// we are checking with bandwidth if we should add an update
	/*if ((tLX->currentTime - fLastUpdateSent) <= tLXOptions->fUpdatePeriod)
		if (tGameInfo.iGameType != GME_LOCAL)
			return; */

	// TODO: Have we always used the limitcheck from GameServer here?
	// We should perhaps move it out from GameServer. Looks a bit strange here to use something from GameServer.
	if(	tLX->iGameType == GME_JOIN // we are a client in a netgame
	   && !GameServer::checkUploadBandwidth(client->getChannel()->getOutgoingRate()) )
		return;

	if(!game.gameScript()->gusEngineUsed()) {
		// Check if we need to write the state update
		bool update = false;
		for(uint i = 0; i < client->iNumWorms; i++)
			if (client->cLocalWorms[i] && client->cLocalWorms[i]->getAlive() && client->cLocalWorms[i]->checkPacketNeeded())  {
				update = true;
				break;
			}

		if(update) {
			// Write the update
			CBytestream bs;
			bs.writeByte(C2S_UPDATE);

			for(uint i = 0; i < client->iNumWorms; i++)
				if(client->cLocalWorms[i])
					client->cLocalWorms[i]->writePacket(&bs, false, NULL);

			client->bsUnreliable.Append(&bs);

			client->fLastUpdateSent = tLX->currentTime;
		}
	}
}

void CClientNetEngine::SendGameReady()
{
	CBytestream bs;
	bs.writeByte(C2S_IMREADY);

	if(client->serverChoosesWeapons()) {
		bs.writeByte(0);
	} else {
		std::list<CWorm*> worms;
		for(unsigned int i=0;i<client->iNumWorms;i++)
			if(client->cLocalWorms[i]) worms.push_back(client->cLocalWorms[i]);

		// Send my worm's weapon details
		bs.writeByte(worms.size());
		for(std::list<CWorm*>::iterator i = worms.begin(); i != worms.end(); ++i)
			(*i)->writeWeapons( &bs );
	}

	client->cNetChan->AddReliablePacketToSend(bs);
}

///////////////////
// Send a death
void CClientNetEngine::SendDeath(int victim, int killer)
{
	CBytestream bs;

	bs.writeByte(C2S_DEATH);
	bs.writeInt(victim,1);
	bs.writeInt(killer,1);

	client->cNetChan->AddReliablePacketToSend(bs);
}

void CClientNetEngineBeta9::SendDeath(int victim, int killer)
{
	// If we have some damage reports in buffer send them first so clients won't sum up updated damage score and reported damage packet sent later
	SendReportDamage(true);

	CClientNetEngine::SendDeath(victim, killer);
}

///////////////////
// Send a string of text
void CClientNetEngine::SendText(const std::string& sText, std::string sWormName)
{
	if(HandleDebugCommand(sText)) return;

	bool chat_command = sText.size() >= 2 && sText[0] == '/' && sText[1] != '/';

	if (sText.find("/irc ") == 0 || sText.find("/chat ") == 0)  { // Send text to IRC
		bool res = false;
		if (GetGlobalIRC())
			res = GetGlobalIRC()->sendChat(sText.substr(sText.find(' ') + 1));
		if (!res)
			client->cChatbox.AddText("Could not send the IRC message", tLX->clNetworkText, TXT_NETWORK, tLX->currentTime);
		return;
	}

	// We can safely send long messages to servers >= beta8
	if (client->getServerVersion() >= OLXBetaVersion(8))  {

		// HTML support since beta 8
		SendTextInternal(OldLxCompatibleString(sText), sWormName);

	// <=beta7 server
	} else {

		if (chat_command &&
			client->getServerVersion() < OLXBetaVersion(3) && // <beta3 clients don't have chat command support
			sText.find("/me ") != 0) // Ignores "/me" special command
		{
			// Try if we can execute the same command in console (mainly for "/suicide" command to work on all servers)
			if( !subStrCaseEqual( sText.substr(1), "suicide", 7 ) )
			    Con_Execute(sText.substr(1));
			else
				client->cChatbox.AddText("HINT: server cannot execute commands, only OLX beta3+ can", tLX->clNotice, TXT_NOTICE, tLX->currentTime);

			return;

		} else if (chat_command &&
				   client->getServerVersion() >= OLXBetaVersion(3)) {
			// we don't have to split chat commands
			// "/me ..." is also save, because server uses SendGlobalText for sending and it splits the text there
			SendTextInternal(OldLxCompatibleString(sText), sWormName);

		} else { // we can savely split the message (and we have to)

			// If the text is too long, split it in smaller pieces and then send (backward comaptibility)
			int name_w = tLX->cFont.GetWidth(sWormName + ": ");
			std::vector<std::string> split = splitstring(StripHtmlTags(sText), 63,
				client->iNetStatus == NET_CONNECTED ? 600 - name_w : 300 - name_w, tLX->cFont);

			// Check
			if (split.size() == 0)  {  // More than weird...
				SendTextInternal(OldLxCompatibleString(StripHtmlTags(sText)), sWormName);
				return;
			}

			// Send the first chunk
			SendTextInternal(OldLxCompatibleString(split[0]), sWormName);

			// Send the text
			for (std::vector<std::string>::const_iterator it = split.begin() + 1; it != split.end(); it++)
				SendTextInternal(OldLxCompatibleString(*it), "");
		}
	}
}

void CClientNetEngineBeta7::SendChatCommandCompletionRequest(const std::string& startStr) {
	CBytestream bs;
	bs.writeByte(C2S_CHATCMDCOMPLREQ);
	bs.writeString(startStr);

	client->cNetChan->AddReliablePacketToSend(bs);
}

void CClientNetEngineBeta7::SendAFK(int wormid, AFK_TYPE afkType, const std::string & message ) {
	if( client->getServerVersion() < OLXBetaVersion(7) )
		return;

	std::string msg = message;
	if( msg == "" )
	{
		switch(afkType) {
			case AFK_BACK_ONLINE: break;
			case AFK_TYPING_CHAT: msg = "(typing)"; break;
			case AFK_AWAY: msg = "(away)"; break;
			case AFK_SELECTING_WPNS: msg = "(selecting weapons)"; break;
			case AFK_CONSOLE: msg = "(console)"; break;
			case AFK_MENU: msg = "(menu)"; break;
		}
	}

	for( int i=0; i < client->getNumWorms(); i++ )
		if(	client->getWorm(i)->getID() == wormid )
			client->getWorm(i)->setAFK(afkType, msg);

	CBytestream bs;
	bs.writeByte(C2S_AFK);
	bs.writeByte(wormid);
	bs.writeByte(afkType);
	if(msg.size() > 127)
		msg = msg.substr(0, 127);
	bs.writeString(msg);

	client->cNetChan->AddReliablePacketToSend(bs);
}

/////////////////////
// Internal function for text sending, does not do any checks or parsing
void CClientNetEngine::SendTextInternal(const std::string& sText, const std::string& sWormName)
{
	if(!client) {
		errors << "CClientNetEngine::SendTextInternal(" << sWormName << ": " << sText << "): my client is unset" << endl;
		return;
	}

	if(!client->cNetChan) {
		errors << "CClientNetEngine::SendTextInternal(" << sWormName << ": " << sText << "): cNetChan of my client (" << client->debugName() << ") is unset" << endl;
		return;
	}

	CBytestream bs;
	bs.writeByte(C2S_CHATTEXT);
	if (sWormName.size() == 0)
		bs.writeString(sText);
	else if( sText.find("/me ") == 0 && client->getServerVersion() < OLXBetaVersion(0,58,1) )	// "/me " chat command
		bs.writeString( "* " + sWormName + " " + sText.substr(4)); // Add star so clients with empty name won't fake others
	else	// "/me " command is server-sided on Beta9
		bs.writeString(sWormName + ": " + sText);

	client->cNetChan->AddReliablePacketToSend(bs);
}

#ifdef FUZZY_ERROR_TESTING
//////////////////
// Send a random packet to server (used for debugging)
void CClientNetEngine::SendRandomPacket()
{
	// don't send random packets from the local client to our own server
	if( tGameInfo.iGameType != GME_JOIN ) return;

	CBytestream bs;

	int random_length = GetRandomInt(50);
	for (int i=0; i < random_length; i++)
		bs.writeByte((uchar)GetRandomInt(255));

	client->cNetChan->AddReliablePacketToSend(bs);

	bs.Clear();

	// Test connectionless packets
	if (GetRandomInt(100) >= 75)  {
		bs.writeInt(-1, 4);
		static const std::string commands[] = { "lx::getchallenge", "lx::connect", "lx::ping", "lx::query",
			"lx::getinfo", "lx::wantsjoin", "lx::traverse", "lx::registered"};
		bs.writeString(commands[GetRandomInt(500) % (sizeof(commands)/sizeof(std::string))]);
		for (int i=0; i < random_length; i++)
			bs.writeByte((uchar)GetRandomInt(255));
		SetRemoteNetAddr(client->tSocket, client->cNetChan->getAddress());
		bs.Send(client->tSocket);
	}
}
#endif

void CClientNetEngine::SendGrabBonus(int id, int wormid)
{
	CBytestream bs;
	bs.writeByte(C2S_GRABBONUS);
	bs.writeByte(id);
	bs.writeByte(wormid);
	bs.writeByte(client->cRemoteWorms[wormid].getCurrentWeapon());

	client->cNetChan->AddReliablePacketToSend(bs);
}

void CClientNetEngine::SendUpdateLobby(bool ready)
{
	CBytestream bs;
	bs.writeByte(C2S_UPDATELOBBY);
	bs.writeByte(ready);
	client->getChannel()->AddReliablePacketToSend(bs);
}

void CClientNetEngine::SendDisconnect()
{
	CBytestream bs;

	bs.writeByte(C2S_DISCONNECT);

	// Send the pack a few times to make sure the server gets the packet
	if( client->cNetChan != NULL)
		for(int i=0;i<3;i++)
			client->cNetChan->Transmit(&bs);
}

void CClientNetEngine::SendFileData()
{
	CBytestream bs;
	bs.writeByte(C2S_SENDFILE);
	client->getUdpFileDownloader()->send(&bs);
	client->getChannel()->AddReliablePacketToSend(bs);
}

void CClientNetEngineBeta9::QueueReportDamage(int victim, float damage, int offender)
{
	// Buffer up all damage and send it once per 0.1 second for LAN nettype, or once per 0.3 seconds for modem
	std::pair< int, int > dmgPair = std::make_pair( victim, offender );
	if( cDamageReport.count( dmgPair ) == 0 )
		cDamageReport[ dmgPair ] = 0;
	cDamageReport[ dmgPair ] += damage;

	SendReportDamage();
}

void CClientNetEngineBeta9::SendReportDamage(bool flush)
{
	if( ! flush && tLX->currentTime - fLastDamageReportSent < 0.1f * ( NST_LOCAL - client->getNetSpeed() ) )
		return;

	CBytestream bs;

	for( std::map< std::pair< int, int >, float > :: iterator it = cDamageReport.begin();
			it != cDamageReport.end(); it++ )
	{
		int victim = it->first.first;
		int offender = it->first.second;
		float damage = it->second;
		bs.writeByte(C2S_REPORTDAMAGE);
		bs.writeByte(victim);
		bs.writeFloat(damage);
		bs.writeByte(offender);
	}

	client->cNetChan->AddReliablePacketToSend(bs);

	cDamageReport.clear();
	fLastDamageReportSent = tLX->currentTime;
}

void CClientNetEngineBeta9NewNet::SendNewNetChecksum()
{
	CBytestream bs;
	bs.writeByte(C2S_NEWNET_CHECKSUM);
	AbsTime time;
	unsigned checksum = NewNet::GetChecksum( &time );
	bs.writeInt(checksum, 4);
	bs.writeInt((unsigned)time.milliseconds(), 4);
	client->cNetChan->AddReliablePacketToSend(bs);
}
<|endoftext|>


<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Delegate for modifying the predictor in the case of infiltration into dry soil.

  License: BSD
  Authors: Ethan Coon (ATS version) (ecoon@lanl.gov)
*/

#include <boost/math/tools/roots.hpp>
#include "predictor_delegate_bc_flux.hh"

namespace Amanzi {
namespace Flow {

#define DEBUG_FLAG 1

bool PredictorDelegateBCFlux::modify_predictor(const Teuchos::Ptr<CompositeVector>& u) {
  int nfaces = bc_values_->size();
  for (int f=0; f!=nfaces; ++f) {
    if ((*bc_markers_)[f] == Operators::Matrix::MATRIX_BC_FLUX) {
      double lambda = (*u)("face",f);
      int ierr = CalculateLambdaToms_(f, u, lambda);
      ASSERT(!ierr);
      if (!ierr) (*u)("face",f) = lambda;
    }
  }
  return true;
}

Teuchos::RCP<PredictorDelegateBCFlux::FluxBCFunctor>
PredictorDelegateBCFlux::CreateFunctor_(int f,
        const Teuchos::Ptr<const CompositeVector>& pres) {
  // inner cell
  AmanziMesh::Entity_ID_List cells;
  mesh_->face_get_cells(f, AmanziMesh::USED, &cells);
  ASSERT(cells.size() == 1);
  int c = cells[0];

  // that cell's faces
  AmanziMesh::Entity_ID_List faces;
  std::vector<int> dirs;
  mesh_->cell_get_faces_and_dirs(c, &faces, &dirs);

  // index within that cell's faces
  int n = std::find(faces.begin(), faces.end(), f) - faces.begin();
  ASSERT(n != faces.size());

  Teuchos::RCP< std::vector<double> > Aff = Teuchos::rcp(new std::vector<double>());
  Aff->resize(faces.size());
  Teuchos::RCP< std::vector<double> > lambda = Teuchos::rcp(new std::vector<double>());
  lambda->resize(faces.size());

  // unscale the Aff for my cell with the rel perm that was used to calculate it
  double Krel = (*S_next_->GetFieldData("numerical_rel_perm"))("face",f);

  // fill the arrays
  for (int i=0; i!=faces.size(); ++i) {
    (*Aff)[i] = matrix_->Aff_cells()[c](n,i) / Krel;
    (*lambda)[i] = (*pres)("face",faces[i]);
  }

  // gravity flux
  double bc_flux = mesh_->face_area(f) * (*bc_values_)[f];
  double gflux = (matrix_->Ff_cells()[c][n] + bc_flux) / Krel;

#if DEBUG_FLAG
  std::cout << "   Aff = ";
  for (int i=0; i!=faces.size(); ++i) std::cout << (*Aff)[i] << ", ";
  std::cout << std::endl << "   lambda = ";
  for (int i=0; i!=faces.size(); ++i) std::cout << (*lambda)[i] << ", ";
  std::cout << std::endl << "   p_cell = " << (*pres)("cell",c) << std::endl;
  std::cout << "    and init K_rel = " << wrms_->second[(*wrms_->first)[c]]->k_relative(101325. - (*lambda)[n]) << std::endl;
  std::cout << "    to match fluxes: bc = " << bc_flux << " and grav = " << gflux << std::endl;
#endif

  // create and return
  return Teuchos::rcp(new FluxBCFunctor(Aff, lambda, n, (*pres)("cell",c),
          bc_flux, gflux, dirs[n], 101325.0, wrms_->second[(*wrms_->first)[c]]));
}

int PredictorDelegateBCFlux::CalculateLambdaToms_(int f,
        const Teuchos::Ptr<const CompositeVector>& pres, double& lambda) {

#if DEBUG_FLAG
  std::cout << " Flux correcting face " << f << ": q = " << (*bc_values_)[f] << std::endl;
#endif

  // start by making sure lambda is a reasonable guess, which may not be the case
  if (std::abs(lambda) > 1.e7) lambda = 101325.;

  Teuchos::RCP<FluxBCFunctor> func = CreateFunctor_(f,pres);

  // -- convergence criteria
  double eps = std::max(1.e-4 * std::abs((*bc_values_)[f]), 1.e-8);
  Tol_ tol(eps);
  int max_it = 100;
  uintmax_t actual_it(max_it);

  double res = (*func)(lambda);
  double left = 0.;
  double right = 0.;
  double lres = 0.;
  double rres = 0.;

  if (res > 0.) {
    left = lambda;
    lres = res;
    right = std::max(lambda,101325.);
    rres = (*func)(right);
    while (rres > 0.) {
      right += 101325.;
      rres = (*func)(right);
    }

  } else {
    right = lambda;
    rres = res;

    std::cout << "RIGHT = " << right << ", " << rres << std::endl;
    left = std::min(101325., lambda);
    lres = (*func)(left);
    while (lres < 0.) {
      std::cout << "LEFT = " << left << ", " << lres << std::endl;
      left -= 101325.;
      lres = (*func)(left);
    }
  }

#if DEBUG_FLAG
  std::cout << "   bracket (res): " << left << " (" << lres << "), "
            << right << " (" << rres << ")" << std::endl;
#endif

  std::pair<double,double> result =
      boost::math::tools::toms748_solve(*func, left, right, lres, rres, tol, actual_it);
  if (actual_it >= max_it) {
    std::cout << " Failed to converged in " << actual_it << " steps." << std::endl;
    return 3;
  }

  lambda = (result.first + result.second) / 2.;
#if DEBUG_FLAG
  std::cout << "  Converged to " << lambda << " in " << actual_it << " steps." << std::endl;

  AmanziMesh::Entity_ID_List cells;
  mesh_->face_get_cells(f, AmanziMesh::USED, &cells);
  ASSERT(cells.size() == 1);
  int c = cells[0];

  std::cout << "      with k_rel = " << wrms_->second[(*wrms_->first)[c]]->k_relative(101325. - lambda) << std::endl;

#endif
  return 0;
}

} // namespace
} // namespace
<commit_msg>turn off BC flux predictor once we are saturated<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Delegate for modifying the predictor in the case of infiltration into dry soil.

  License: BSD
  Authors: Ethan Coon (ATS version) (ecoon@lanl.gov)
*/

#include <boost/math/tools/roots.hpp>
#include "predictor_delegate_bc_flux.hh"

namespace Amanzi {
namespace Flow {

#define DEBUG_FLAG 1

bool PredictorDelegateBCFlux::modify_predictor(const Teuchos::Ptr<CompositeVector>& u) {
  int nfaces = bc_values_->size();
  for (int f=0; f!=nfaces; ++f) {
    if ((*bc_markers_)[f] == Operators::Matrix::MATRIX_BC_FLUX) {
      double lambda = (*u)("face",f);
      // only do if below saturated
      if (lambda < 101325.) {
        int ierr = CalculateLambdaToms_(f, u, lambda);
        ASSERT(!ierr);
        if (!ierr) (*u)("face",f) = lambda;
      }
    }
  }
  return true;
}

Teuchos::RCP<PredictorDelegateBCFlux::FluxBCFunctor>
PredictorDelegateBCFlux::CreateFunctor_(int f,
        const Teuchos::Ptr<const CompositeVector>& pres) {
  // inner cell
  AmanziMesh::Entity_ID_List cells;
  mesh_->face_get_cells(f, AmanziMesh::USED, &cells);
  ASSERT(cells.size() == 1);
  int c = cells[0];

  // that cell's faces
  AmanziMesh::Entity_ID_List faces;
  std::vector<int> dirs;
  mesh_->cell_get_faces_and_dirs(c, &faces, &dirs);

  // index within that cell's faces
  int n = std::find(faces.begin(), faces.end(), f) - faces.begin();
  ASSERT(n != faces.size());

  Teuchos::RCP< std::vector<double> > Aff = Teuchos::rcp(new std::vector<double>());
  Aff->resize(faces.size());
  Teuchos::RCP< std::vector<double> > lambda = Teuchos::rcp(new std::vector<double>());
  lambda->resize(faces.size());

  // unscale the Aff for my cell with the rel perm that was used to calculate it
  double Krel = (*S_next_->GetFieldData("numerical_rel_perm"))("face",f);

  // fill the arrays
  for (int i=0; i!=faces.size(); ++i) {
    (*Aff)[i] = matrix_->Aff_cells()[c](n,i) / Krel;
    (*lambda)[i] = (*pres)("face",faces[i]);
  }

  // gravity flux
  double bc_flux = mesh_->face_area(f) * (*bc_values_)[f];
  double gflux = (matrix_->Ff_cells()[c][n] + bc_flux) / Krel;

#if DEBUG_FLAG
  std::cout << "   Aff = ";
  for (int i=0; i!=faces.size(); ++i) std::cout << (*Aff)[i] << ", ";
  std::cout << std::endl << "   lambda = ";
  for (int i=0; i!=faces.size(); ++i) std::cout << (*lambda)[i] << ", ";
  std::cout << std::endl << "   p_cell = " << (*pres)("cell",c) << std::endl;
  std::cout << "    and init K_rel = " << wrms_->second[(*wrms_->first)[c]]->k_relative(101325. - (*lambda)[n]) << std::endl;
  std::cout << "    to match fluxes: bc = " << bc_flux << " and grav = " << gflux << std::endl;
#endif

  // create and return
  return Teuchos::rcp(new FluxBCFunctor(Aff, lambda, n, (*pres)("cell",c),
          bc_flux, gflux, dirs[n], 101325.0, wrms_->second[(*wrms_->first)[c]]));
}

int PredictorDelegateBCFlux::CalculateLambdaToms_(int f,
        const Teuchos::Ptr<const CompositeVector>& pres, double& lambda) {

#if DEBUG_FLAG
  std::cout << " Flux correcting face " << f << ": q = " << (*bc_values_)[f] << std::endl;
#endif

  // start by making sure lambda is a reasonable guess, which may not be the case
  if (std::abs(lambda) > 1.e7) lambda = 101325.;

  Teuchos::RCP<FluxBCFunctor> func = CreateFunctor_(f,pres);

  // -- convergence criteria
  double eps = std::max(1.e-4 * std::abs((*bc_values_)[f]), 1.e-8);
  Tol_ tol(eps);
  int max_it = 100;
  uintmax_t actual_it(max_it);

  double res = (*func)(lambda);
  double left = 0.;
  double right = 0.;
  double lres = 0.;
  double rres = 0.;

  if (res > 0.) {
    left = lambda;
    lres = res;
    right = std::max(lambda,101325.);
    rres = (*func)(right);
    while (rres > 0.) {
      right += 101325.;
      rres = (*func)(right);
    }

  } else {
    right = lambda;
    rres = res;

    std::cout << "RIGHT = " << right << ", " << rres << std::endl;
    left = std::min(101325., lambda);
    lres = (*func)(left);
    while (lres < 0.) {
      std::cout << "LEFT = " << left << ", " << lres << std::endl;
      left -= 101325.;
      lres = (*func)(left);
    }
  }

#if DEBUG_FLAG
  std::cout << "   bracket (res): " << left << " (" << lres << "), "
            << right << " (" << rres << ")" << std::endl;
#endif

  std::pair<double,double> result =
      boost::math::tools::toms748_solve(*func, left, right, lres, rres, tol, actual_it);
  if (actual_it >= max_it) {
    std::cout << " Failed to converged in " << actual_it << " steps." << std::endl;
    return 3;
  }

  lambda = (result.first + result.second) / 2.;
#if DEBUG_FLAG
  std::cout << "  Converged to " << lambda << " in " << actual_it << " steps." << std::endl;

  AmanziMesh::Entity_ID_List cells;
  mesh_->face_get_cells(f, AmanziMesh::USED, &cells);
  ASSERT(cells.size() == 1);
  int c = cells[0];

  std::cout << "      with k_rel = " << wrms_->second[(*wrms_->first)[c]]->k_relative(101325. - lambda) << std::endl;

#endif
  return 0;
}

} // namespace
} // namespace
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 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 "gettingstartedwelcomepage.h"

#include "exampleslistmodel.h"
#include "screenshotcropper.h"

#include <utils/pathchooser.h>
#include <utils/winutils.h>

#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <coreplugin/modemanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/project.h>

#include <QMutex>
#include <QThread>
#include <QMutexLocker>
#include <QPointer>
#include <QWaitCondition>
#include <QDir>
#include <QBuffer>
#include <QImage>
#include <QImageReader>
#include <QGridLayout>
#include <QLabel>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QMessageBox>
#include <QApplication>
#include <QQuickImageProvider>
#include <QQmlEngine>
#include <QQmlContext>
#include <QDesktopServices>

using namespace Utils;

namespace QtSupport {
namespace Internal {

class ExampleDialog : public QDialog
{
    Q_OBJECT
 public:
    enum ResultCode { Copy = QDialog::Accepted + 1, Keep };
    ExampleDialog(QWidget *parent = 0) : QDialog(parent) {};
 private slots:
    void handleCopyClicked() { done(Copy); };
    void handleKeepClicked() { done(Keep); };
};

const char C_FALLBACK_ROOT[] = "ProjectsFallbackRoot";

QPointer<ExamplesListModel> &examplesModelStatic()
{
    static QPointer<ExamplesListModel> s_examplesModel;
    return s_examplesModel;
}

class Fetcher : public QObject
{
    Q_OBJECT

public:
    Fetcher() : QObject(),  m_shutdown(false)
    {
        connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(shutdown()));
    }

    void wait()
    {
        if (QThread::currentThread() == QApplication::instance()->thread())
            return;
        if (m_shutdown)
            return;

        m_waitcondition.wait(&m_mutex, 4000);
    }

    QByteArray data()
    {
        QMutexLocker lock(&m_dataMutex);
        return m_fetchedData;
    }

    void clearData()
    {
        QMutexLocker lock(&m_dataMutex);
        m_fetchedData.clear();
    }

    bool asynchronousFetchData(const QUrl &url)
    {
        QMutexLocker lock(&m_mutex);

        if (!QMetaObject::invokeMethod(this,
                                       "fetchData",
                                       Qt::AutoConnection,
                                       Q_ARG(QUrl, url))) {
            return false;
        }

        wait();
        return true;
    }

public slots:
    void fetchData(const QUrl &url)
    {
        if (m_shutdown)
            return;

        QMutexLocker lock(&m_mutex);

        if (Core::HelpManager::instance()) {
            QMutexLocker dataLock(&m_dataMutex);
            m_fetchedData = Core::HelpManager::fileData(url);
        }
        m_waitcondition.wakeAll();
    }

private slots:
    void shutdown()
    {
        m_shutdown = true;
    }

public:
    QByteArray m_fetchedData;
    QWaitCondition m_waitcondition;
    QMutex m_mutex;     //This mutex synchronises the wait() and wakeAll() on the wait condition.
                        //We have to ensure that wakeAll() is called always after wait().

    QMutex m_dataMutex; //This mutex synchronises the access of m_fectedData.
                        //If the wait condition timeouts we otherwise get a race condition.
    bool m_shutdown;
};

class HelpImageProvider : public QQuickImageProvider
{
public:
    HelpImageProvider()
        : QQuickImageProvider(QQuickImageProvider::Image)
    {
    }

    // gets called by declarative in separate thread
    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
    {
        QMutexLocker lock(&m_mutex);

        QUrl url = QUrl::fromEncoded(id.toLatin1());

        if (!m_fetcher.asynchronousFetchData(url) || m_fetcher.data().isEmpty()) {
            if (size) {
                size->setWidth(0);
                size->setHeight(0);
            }
            return QImage();
        }

        QByteArray data = m_fetcher.data();
        QBuffer imgBuffer(&data);
        imgBuffer.open(QIODevice::ReadOnly);
        QImageReader reader(&imgBuffer);
        QImage img = reader.read();

        m_fetcher.clearData();
        img = ScreenshotCropper::croppedImage(img, id, requestedSize);
        if (size)
            *size = img.size();
        return img;

    }
private:
    Fetcher m_fetcher;
    QMutex m_mutex;
};

ExamplesWelcomePage::ExamplesWelcomePage()
    : m_engine(0),  m_showExamples(false)
{
}

void ExamplesWelcomePage::setShowExamples(bool showExamples)
{
    m_showExamples = showExamples;
}

QString ExamplesWelcomePage::title() const
{
    if (m_showExamples)
        return tr("Examples");
    else
        return tr("Tutorials");
}

 int ExamplesWelcomePage::priority() const
 {
     if (m_showExamples)
         return 30;
     else
         return 40;
 }

 bool ExamplesWelcomePage::hasSearchBar() const
 {
     if (m_showExamples)
         return true;
     else
         return false;
 }

QUrl ExamplesWelcomePage::pageLocation() const
{
    // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
    const QString resourcePath = Utils::FileUtils::normalizePathName(Core::ICore::resourcePath());
    if (m_showExamples)
        return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/examples.qml"));
    else
        return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/tutorials.qml"));
}

void ExamplesWelcomePage::facilitateQml(QQmlEngine *engine)
{
    m_engine = engine;
    m_engine->addImageProvider(QLatin1String("helpimage"), new HelpImageProvider);
    connect (examplesModel(), SIGNAL(tagsUpdated()), SLOT(updateTagsModel()));
    ExamplesListModelFilter *proxy = new ExamplesListModelFilter(examplesModel(), this);

    proxy->setDynamicSortFilter(true);
    proxy->sort(0);
    proxy->setFilterCaseSensitivity(Qt::CaseInsensitive);

    QQmlContext *rootContenxt = m_engine->rootContext();
    if (m_showExamples) {
        proxy->setShowTutorialsOnly(false);
        rootContenxt->setContextProperty(QLatin1String("examplesModel"), proxy);
        rootContenxt->setContextProperty(QLatin1String("qtVersionModel"), proxy->qtVersionModel());
    } else {
        rootContenxt->setContextProperty(QLatin1String("tutorialsModel"), proxy);
    }
    rootContenxt->setContextProperty(QLatin1String("gettingStarted"), this);
}

ExamplesWelcomePage::Id ExamplesWelcomePage::id() const
{
    return m_showExamples ? Examples : Tutorials;
}

void ExamplesWelcomePage::openSplitHelp(const QUrl &help)
{
    Core::HelpManager::handleHelpRequest(help.toString()+QLatin1String("?view=split"));
}

void ExamplesWelcomePage::openHelp(const QUrl &help)
{
    Core::HelpManager::handleHelpRequest(help.toString());
}

void ExamplesWelcomePage::openUrl(const QUrl &url)
{
    QDesktopServices::openUrl(url);
}

QStringList ExamplesWelcomePage::tagList() const
{
    return examplesModel()->tags();
}

QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileInfo, QStringList &filesToOpen, const QStringList& dependencies)
{
    const QString projectDir = proFileInfo.canonicalPath();
    ExampleDialog d(Core::ICore::mainWindow());
    QGridLayout *lay = new QGridLayout(&d);
    QLabel *descrLbl = new QLabel;
    d.setWindowTitle(tr("Copy Project to writable Location?"));
    descrLbl->setTextFormat(Qt::RichText);
    descrLbl->setWordWrap(false);
    const QString nativeProjectDir = QDir::toNativeSeparators(projectDir);
    descrLbl->setText(QString::fromLatin1("
%1
").arg(nativeProjectDir));
    descrLbl->setMinimumWidth(descrLbl->sizeHint().width());
    descrLbl->setWordWrap(true);
    descrLbl->setText(tr("
The project you are about to open is located in the "
                         "write-protected location:

%1
"
                         "
Please select a writable location below and click \"Copy Project and Open\" "
                         "to open a modifiable copy of the project or click \"Keep Project and Open\" "
                         "to open the project in location.

Note: You will not "
                         "be able to alter or compile your project in the current location.
")
                      .arg(nativeProjectDir));
    lay->addWidget(descrLbl, 0, 0, 1, 2);
    QLabel *txt = new QLabel(tr("&Location:"));
    PathChooser *chooser = new PathChooser;
    txt->setBuddy(chooser);
    chooser->setExpectedKind(PathChooser::ExistingDirectory);
    chooser->setHistoryCompleter(QLatin1String("Qt.WritableExamplesDir.History"));
    QSettings *settings = Core::ICore::settings();
    chooser->setPath(settings->value(QString::fromLatin1(C_FALLBACK_ROOT),
                                     Core::DocumentManager::projectsDirectory()).toString());
    lay->addWidget(txt, 1, 0);
    lay->addWidget(chooser, 1, 1);
    QDialogButtonBox *bb = new QDialogButtonBox;
    QPushButton *copyBtn = bb->addButton(tr("&Copy Project and Open"), QDialogButtonBox::AcceptRole);
    connect(copyBtn, SIGNAL(released()), &d, SLOT(handleCopyClicked()));
    copyBtn->setDefault(true);
    QPushButton *keepBtn = bb->addButton(tr("&Keep Project and Open"), QDialogButtonBox::RejectRole);
    connect(keepBtn, SIGNAL(released()), &d, SLOT(handleKeepClicked()));
    lay->addWidget(bb, 2, 0, 1, 2);
    connect(chooser, SIGNAL(validChanged(bool)), copyBtn, SLOT(setEnabled(bool)));
    int code = d.exec();
    if (code == ExampleDialog::Copy) {
        QString exampleDirName = proFileInfo.dir().dirName();
        QString destBaseDir = chooser->path();
        settings->setValue(QString::fromLatin1(C_FALLBACK_ROOT), destBaseDir);
        QDir toDirWithExamplesDir(destBaseDir);
        if (toDirWithExamplesDir.cd(exampleDirName)) {
            toDirWithExamplesDir.cdUp(); // step out, just to not be in the way
            QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Use Location"),
                                 tr("The specified location already exists. "
                                    "Please specify a valid location."),
                                 QMessageBox::Ok, QMessageBox::NoButton);
            return QString();
        } else {
            QString error;
            QString targetDir = destBaseDir + QLatin1Char('/') + exampleDirName;
            if (FileUtils::copyRecursively(FileName::fromString(projectDir),
                    FileName::fromString(targetDir), &error)) {
                // set vars to new location
                const QStringList::Iterator end = filesToOpen.end();
                for (QStringList::Iterator it = filesToOpen.begin(); it != end; ++it)
                    it->replace(projectDir, targetDir);

                foreach (const QString &dependency, dependencies) {
                    FileName targetFile = FileName::fromString(targetDir);
                    targetFile.appendPath(QDir(dependency).dirName());
                    if (!FileUtils::copyRecursively(FileName::fromString(dependency), targetFile,
                            &error)) {
                        QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Copy Project"), error);
                        // do not fail, just warn;
                    }
                }

                return targetDir + QLatin1Char('/') + proFileInfo.fileName();
            } else {
                QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Copy Project"), error);
            }

        }
    }
    if (code == ExampleDialog::Keep)
        return proFileInfo.absoluteFilePath();
    return QString();

}

void ExamplesWelcomePage::openProject(const QString &projectFile, const QStringList &additionalFilesToOpen,
                                            const QUrl &help, const QStringList &dependencies, const QStringList &platforms)
{
    QString proFile = projectFile;
    if (proFile.isEmpty())
        return;

    QStringList filesToOpen = additionalFilesToOpen;
    QFileInfo proFileInfo(proFile);
    if (!proFileInfo.exists())
        return;

    // If the Qt is a distro Qt on Linux, it will not be writable, hence compilation will fail
    if (!proFileInfo.isWritable())
        proFile = copyToAlternativeLocation(proFileInfo, filesToOpen, dependencies);

    // don't try to load help and files if loading the help request is being cancelled
    QString errorMessage;
    ProjectExplorer::ProjectExplorerPlugin *peplugin = ProjectExplorer::ProjectExplorerPlugin::instance();
    if (proFile.isEmpty())
        return;
    if (peplugin->openProject(proFile, &errorMessage)) {
        Core::ICore::openFiles(filesToOpen);
        Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
        if (help.isValid())
            Core::HelpManager::handleHelpRequest(help.toString() + QLatin1String("?view=split"));
        Core::ModeManager::activateMode(ProjectExplorer::Constants::MODE_SESSION);
    }
    if (!errorMessage.isEmpty())
        QMessageBox::critical(Core::ICore::mainWindow(), tr("Failed to Open Project"), errorMessage);
}

void ExamplesWelcomePage::updateTagsModel()
{
    m_engine->rootContext()->setContextProperty(QLatin1String("tagsList"), examplesModel()->tags());
    emit tagsUpdated();
}

ExamplesListModel *ExamplesWelcomePage::examplesModel() const
{
    if (examplesModelStatic())
        return examplesModelStatic().data();

    examplesModelStatic() = new ExamplesListModel(const_cast<ExamplesWelcomePage*>(this));
    return examplesModelStatic().data();
}

} // namespace Internal
} // namespace QtSupport

#include "gettingstartedwelcomepage.moc"
<commit_msg>QtSupport: Fix compiler warning<commit_after>/****************************************************************************
**
** Copyright (C) 2014 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 "gettingstartedwelcomepage.h"

#include "exampleslistmodel.h"
#include "screenshotcropper.h"

#include <utils/pathchooser.h>
#include <utils/winutils.h>

#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <coreplugin/modemanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/project.h>

#include <QMutex>
#include <QThread>
#include <QMutexLocker>
#include <QPointer>
#include <QWaitCondition>
#include <QDir>
#include <QBuffer>
#include <QImage>
#include <QImageReader>
#include <QGridLayout>
#include <QLabel>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QMessageBox>
#include <QApplication>
#include <QQuickImageProvider>
#include <QQmlEngine>
#include <QQmlContext>
#include <QDesktopServices>

using namespace Utils;

namespace QtSupport {
namespace Internal {

class ExampleDialog : public QDialog
{
    Q_OBJECT
 public:
    enum ResultCode { Copy = QDialog::Accepted + 1, Keep };
    ExampleDialog(QWidget *parent = 0) : QDialog(parent) {};
 private slots:
    void handleCopyClicked() { done(Copy); };
    void handleKeepClicked() { done(Keep); };
};

const char C_FALLBACK_ROOT[] = "ProjectsFallbackRoot";

QPointer<ExamplesListModel> &examplesModelStatic()
{
    static QPointer<ExamplesListModel> s_examplesModel;
    return s_examplesModel;
}

class Fetcher : public QObject
{
    Q_OBJECT

public:
    Fetcher() : QObject(),  m_shutdown(false)
    {
        connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(shutdown()));
    }

    void wait()
    {
        if (QThread::currentThread() == QApplication::instance()->thread())
            return;
        if (m_shutdown)
            return;

        m_waitcondition.wait(&m_mutex, 4000);
    }

    QByteArray data()
    {
        QMutexLocker lock(&m_dataMutex);
        return m_fetchedData;
    }

    void clearData()
    {
        QMutexLocker lock(&m_dataMutex);
        m_fetchedData.clear();
    }

    bool asynchronousFetchData(const QUrl &url)
    {
        QMutexLocker lock(&m_mutex);

        if (!QMetaObject::invokeMethod(this,
                                       "fetchData",
                                       Qt::AutoConnection,
                                       Q_ARG(QUrl, url))) {
            return false;
        }

        wait();
        return true;
    }

public slots:
    void fetchData(const QUrl &url)
    {
        if (m_shutdown)
            return;

        QMutexLocker lock(&m_mutex);

        if (Core::HelpManager::instance()) {
            QMutexLocker dataLock(&m_dataMutex);
            m_fetchedData = Core::HelpManager::fileData(url);
        }
        m_waitcondition.wakeAll();
    }

private slots:
    void shutdown()
    {
        m_shutdown = true;
    }

public:
    QByteArray m_fetchedData;
    QWaitCondition m_waitcondition;
    QMutex m_mutex;     //This mutex synchronises the wait() and wakeAll() on the wait condition.
                        //We have to ensure that wakeAll() is called always after wait().

    QMutex m_dataMutex; //This mutex synchronises the access of m_fectedData.
                        //If the wait condition timeouts we otherwise get a race condition.
    bool m_shutdown;
};

class HelpImageProvider : public QQuickImageProvider
{
public:
    HelpImageProvider()
        : QQuickImageProvider(QQuickImageProvider::Image)
    {
    }

    // gets called by declarative in separate thread
    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
    {
        QMutexLocker lock(&m_mutex);

        QUrl url = QUrl::fromEncoded(id.toLatin1());

        if (!m_fetcher.asynchronousFetchData(url) || m_fetcher.data().isEmpty()) {
            if (size) {
                size->setWidth(0);
                size->setHeight(0);
            }
            return QImage();
        }

        QByteArray data = m_fetcher.data();
        QBuffer imgBuffer(&data);
        imgBuffer.open(QIODevice::ReadOnly);
        QImageReader reader(&imgBuffer);
        QImage img = reader.read();

        m_fetcher.clearData();
        img = ScreenshotCropper::croppedImage(img, id, requestedSize);
        if (size)
            *size = img.size();
        return img;

    }
private:
    Fetcher m_fetcher;
    QMutex m_mutex;
};

ExamplesWelcomePage::ExamplesWelcomePage()
    : m_engine(0),  m_showExamples(false)
{
}

void ExamplesWelcomePage::setShowExamples(bool showExamples)
{
    m_showExamples = showExamples;
}

QString ExamplesWelcomePage::title() const
{
    if (m_showExamples)
        return tr("Examples");
    else
        return tr("Tutorials");
}

 int ExamplesWelcomePage::priority() const
 {
     if (m_showExamples)
         return 30;
     else
         return 40;
 }

 bool ExamplesWelcomePage::hasSearchBar() const
 {
     if (m_showExamples)
         return true;
     else
         return false;
 }

QUrl ExamplesWelcomePage::pageLocation() const
{
    // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
    const QString resourcePath = Utils::FileUtils::normalizePathName(Core::ICore::resourcePath());
    if (m_showExamples)
        return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/examples.qml"));
    else
        return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/tutorials.qml"));
}

void ExamplesWelcomePage::facilitateQml(QQmlEngine *engine)
{
    m_engine = engine;
    m_engine->addImageProvider(QLatin1String("helpimage"), new HelpImageProvider);
    connect (examplesModel(), SIGNAL(tagsUpdated()), SLOT(updateTagsModel()));
    ExamplesListModelFilter *proxy = new ExamplesListModelFilter(examplesModel(), this);

    proxy->setDynamicSortFilter(true);
    proxy->sort(0);
    proxy->setFilterCaseSensitivity(Qt::CaseInsensitive);

    QQmlContext *rootContenxt = m_engine->rootContext();
    if (m_showExamples) {
        proxy->setShowTutorialsOnly(false);
        rootContenxt->setContextProperty(QLatin1String("examplesModel"), proxy);
        rootContenxt->setContextProperty(QLatin1String("qtVersionModel"), proxy->qtVersionModel());
    } else {
        rootContenxt->setContextProperty(QLatin1String("tutorialsModel"), proxy);
    }
    rootContenxt->setContextProperty(QLatin1String("gettingStarted"), this);
}

ExamplesWelcomePage::Id ExamplesWelcomePage::id() const
{
    return m_showExamples ? Examples : Tutorials;
}

void ExamplesWelcomePage::openSplitHelp(const QUrl &help)
{
    Core::HelpManager::handleHelpRequest(help.toString()+QLatin1String("?view=split"));
}

void ExamplesWelcomePage::openHelp(const QUrl &help)
{
    Core::HelpManager::handleHelpRequest(help.toString());
}

void ExamplesWelcomePage::openUrl(const QUrl &url)
{
    QDesktopServices::openUrl(url);
}

QStringList ExamplesWelcomePage::tagList() const
{
    return examplesModel()->tags();
}

QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileInfo, QStringList &filesToOpen, const QStringList& dependencies)
{
    const QString projectDir = proFileInfo.canonicalPath();
    ExampleDialog d(Core::ICore::mainWindow());
    QGridLayout *lay = new QGridLayout(&d);
    QLabel *descrLbl = new QLabel;
    d.setWindowTitle(tr("Copy Project to writable Location?"));
    descrLbl->setTextFormat(Qt::RichText);
    descrLbl->setWordWrap(false);
    const QString nativeProjectDir = QDir::toNativeSeparators(projectDir);
    descrLbl->setText(QString::fromLatin1("
%1
").arg(nativeProjectDir));
    descrLbl->setMinimumWidth(descrLbl->sizeHint().width());
    descrLbl->setWordWrap(true);
    descrLbl->setText(tr("
The project you are about to open is located in the "
                         "write-protected location:

%1
"
                         "
Please select a writable location below and click \"Copy Project and Open\" "
                         "to open a modifiable copy of the project or click \"Keep Project and Open\" "
                         "to open the project in location.

Note: You will not "
                         "be able to alter or compile your project in the current location.
")
                      .arg(nativeProjectDir));
    lay->addWidget(descrLbl, 0, 0, 1, 2);
    QLabel *txt = new QLabel(tr("&Location:"));
    PathChooser *chooser = new PathChooser;
    txt->setBuddy(chooser);
    chooser->setExpectedKind(PathChooser::ExistingDirectory);
    chooser->setHistoryCompleter(QLatin1String("Qt.WritableExamplesDir.History"));
    QSettings *settings = Core::ICore::settings();
    chooser->setPath(settings->value(QString::fromLatin1(C_FALLBACK_ROOT),
                                     Core::DocumentManager::projectsDirectory()).toString());
    lay->addWidget(txt, 1, 0);
    lay->addWidget(chooser, 1, 1);
    QDialogButtonBox *bb = new QDialogButtonBox;
    QPushButton *copyBtn = bb->addButton(tr("&Copy Project and Open"), QDialogButtonBox::AcceptRole);
    connect(copyBtn, SIGNAL(released()), &d, SLOT(handleCopyClicked()));
    copyBtn->setDefault(true);
    QPushButton *keepBtn = bb->addButton(tr("&Keep Project and Open"), QDialogButtonBox::RejectRole);
    connect(keepBtn, SIGNAL(released()), &d, SLOT(handleKeepClicked()));
    lay->addWidget(bb, 2, 0, 1, 2);
    connect(chooser, SIGNAL(validChanged(bool)), copyBtn, SLOT(setEnabled(bool)));
    int code = d.exec();
    if (code == ExampleDialog::Copy) {
        QString exampleDirName = proFileInfo.dir().dirName();
        QString destBaseDir = chooser->path();
        settings->setValue(QString::fromLatin1(C_FALLBACK_ROOT), destBaseDir);
        QDir toDirWithExamplesDir(destBaseDir);
        if (toDirWithExamplesDir.cd(exampleDirName)) {
            toDirWithExamplesDir.cdUp(); // step out, just to not be in the way
            QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Use Location"),
                                 tr("The specified location already exists. "
                                    "Please specify a valid location."),
                                 QMessageBox::Ok, QMessageBox::NoButton);
            return QString();
        } else {
            QString error;
            QString targetDir = destBaseDir + QLatin1Char('/') + exampleDirName;
            if (FileUtils::copyRecursively(FileName::fromString(projectDir),
                    FileName::fromString(targetDir), &error)) {
                // set vars to new location
                const QStringList::Iterator end = filesToOpen.end();
                for (QStringList::Iterator it = filesToOpen.begin(); it != end; ++it)
                    it->replace(projectDir, targetDir);

                foreach (const QString &dependency, dependencies) {
                    FileName targetFile = FileName::fromString(targetDir);
                    targetFile.appendPath(QDir(dependency).dirName());
                    if (!FileUtils::copyRecursively(FileName::fromString(dependency), targetFile,
                            &error)) {
                        QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Copy Project"), error);
                        // do not fail, just warn;
                    }
                }

                return targetDir + QLatin1Char('/') + proFileInfo.fileName();
            } else {
                QMessageBox::warning(Core::ICore::mainWindow(), tr("Cannot Copy Project"), error);
            }

        }
    }
    if (code == ExampleDialog::Keep)
        return proFileInfo.absoluteFilePath();
    return QString();

}

void ExamplesWelcomePage::openProject(const QString &projectFile, const QStringList &additionalFilesToOpen,
                                      const QUrl &help, const QStringList &dependencies, const QStringList &)
{
    QString proFile = projectFile;
    if (proFile.isEmpty())
        return;

    QStringList filesToOpen = additionalFilesToOpen;
    QFileInfo proFileInfo(proFile);
    if (!proFileInfo.exists())
        return;

    // If the Qt is a distro Qt on Linux, it will not be writable, hence compilation will fail
    if (!proFileInfo.isWritable())
        proFile = copyToAlternativeLocation(proFileInfo, filesToOpen, dependencies);

    // don't try to load help and files if loading the help request is being cancelled
    QString errorMessage;
    ProjectExplorer::ProjectExplorerPlugin *peplugin = ProjectExplorer::ProjectExplorerPlugin::instance();
    if (proFile.isEmpty())
        return;
    if (peplugin->openProject(proFile, &errorMessage)) {
        Core::ICore::openFiles(filesToOpen);
        Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
        if (help.isValid())
            Core::HelpManager::handleHelpRequest(help.toString() + QLatin1String("?view=split"));
        Core::ModeManager::activateMode(ProjectExplorer::Constants::MODE_SESSION);
    }
    if (!errorMessage.isEmpty())
        QMessageBox::critical(Core::ICore::mainWindow(), tr("Failed to Open Project"), errorMessage);
}

void ExamplesWelcomePage::updateTagsModel()
{
    m_engine->rootContext()->setContextProperty(QLatin1String("tagsList"), examplesModel()->tags());
    emit tagsUpdated();
}

ExamplesListModel *ExamplesWelcomePage::examplesModel() const
{
    if (examplesModelStatic())
        return examplesModelStatic().data();

    examplesModelStatic() = new ExamplesListModel(const_cast<ExamplesWelcomePage*>(this));
    return examplesModelStatic().data();
}

} // namespace Internal
} // namespace QtSupport

#include "gettingstartedwelcomepage.moc"
<|endoftext|>