<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2020 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Graphics/Glyphs/TensorGlyphBuilder.h>
#include <Graphics/Glyphs/GlyphGeomUtility.h>
#include <Core/GeometryPrimitives/Transform.h>
#include <Core/Math/MiscMath.h>

using namespace SCIRun;
using namespace Graphics;
using namespace Core::Geometry;
using namespace Core::Datatypes;

TensorGlyphBuilder::TensorGlyphBuilder(const Tensor& t, const Point& center)
{
  t_ = t;
  center_ = Point(center);
}

void TensorGlyphBuilder::scaleTensor(double scale)
{
  t_ = t_ * scale;
}

std::vector<Vector> TensorGlyphBuilder::getEigenVectors()
{
  std::vector<Vector> eigvecs(DIMENSIONS_);
  t_.get_eigenvectors(eigvecs[0], eigvecs[1], eigvecs[2]);
  return eigvecs;
}

std::vector<double> TensorGlyphBuilder::getEigenValues()
{
  std::vector<double> eigvals(DIMENSIONS_);
  t_.get_eigenvalues(eigvals[0], eigvals[1], eigvals[2]);
  return eigvals;
}

void TensorGlyphBuilder::normalizeTensor()
{
  auto eigvecs = getEigenVectors();
  for (auto& v : eigvecs)
    v.normalize();

  auto norm = t_.euclidean_norm();
  t_.set_outside_eigens(eigvecs[0] * norm[0], eigvecs[1] * norm[1], eigvecs[2] * norm[2],
                        norm[0], norm[1], norm[2]);
}

void TensorGlyphBuilder::setColor(const ColorRGB& color)
{
  color_ = color;
}

void TensorGlyphBuilder::setResolution(double resolution)
{
  resolution_ = resolution;
}

void TensorGlyphBuilder::reorderTensorValues(std::vector<Vector>& eigvecs,
                                             std::vector<double>& eigvals)
{
  std::vector<std::pair<double, Vector>> sortList(3);
  for(int d = 0; d < DIMENSIONS_; ++d)
    sortList[d] = std::make_pair(eigvals[d], eigvecs[d]);

  std::sort(std::begin(sortList), std::end(sortList), std::greater<std::pair<double, Vector>>());

  for(int d = 0; d < DIMENSIONS_; ++d)
  {
    eigvals[d] = sortList[d].first;
    eigvecs[d] = sortList[d].second;
  }
}
void TensorGlyphBuilder::makeTensorPositive()
{
  static const double zeroThreshold = 0.000001;

  auto eigvals = getEigenValues();
  auto eigvecs = getEigenVectors();
  for (auto& e : eigvals)
  {
    e = fabs(e);
    if(e <= zeroThreshold)
      e = 0;
  }

  // These are exactly zero after thresholding
  flatTensor_ = eigvals[0] == 0 || eigvals[1] == 0 || eigvals[2] == 0;

  if (flatTensor_)
    reorderTensorValues(eigvecs, eigvals);

  for (int d = 0; d < DIMENSIONS_; ++d)
    if (eigvals[d] == 0)
    {
      zeroNorm_ = Cross(eigvecs[(d+1) % DIMENSIONS_], eigvecs[(d+2) % DIMENSIONS_]).normal();
      eigvecs[d] = zeroNorm_ * eigvals[d];
      break;
    }

  t_.set_outside_eigens(eigvecs[0], eigvecs[1], eigvecs[2],
                        eigvals[0], eigvals[1], eigvals[2]);
}

void TensorGlyphBuilder::computeSinCosTable(bool half)
{
  nv_ = resolution_;
  nu_ = resolution_ + 1;

  // Should only happen when doing half ellipsoids.
  if (half) nv_ /= 2;
  if (nv_ < 2) nv_ = 2;

  double end = half ? M_PI : 2.0 * M_PI;
  tab1_ = SinCosTable(nu_, 0, end);
  tab2_ = SinCosTable(nv_, 0, M_PI);
}

void TensorGlyphBuilder::computeTransforms()
{
  auto eigvecs = getEigenVectors();
  for (auto& v : eigvecs)
    v.normalize();
  GlyphGeomUtility::generateTransforms(center_, eigvecs[0], eigvecs[1], eigvecs[2], trans_, rotate_);
}

void TensorGlyphBuilder::postScaleTransorms()
{
  auto eigvals = getEigenValues();
  Vector eigvalsVector(eigvals[0], eigvals[1], eigvals[2]);

  trans_.post_scale( Vector(1.0,1.0,1.0) * eigvalsVector);
  rotate_.post_scale(Vector(1.0,1.0,1.0) / eigvalsVector);
}

void TensorGlyphBuilder::generateEllipsoid(GlyphConstructor& constructor, bool half)
{
  computeTransforms();
  postScaleTransorms();
  computeSinCosTable(half);

  for (int v = 0; v < nv_ - 1; ++v)
  {
    double sinPhi[2];
    sinPhi[0] = tab2_.sin(v+1);
    sinPhi[1] = tab2_.sin(v);

    double cosPhi[2];
    cosPhi[0] = tab2_.cos(v+1);
    cosPhi[1] = tab2_.cos(v);

    for (int u = 0; u < nu_; ++u)
    {
      double sinTheta = tab1_.sin(u);
      double cosTheta = tab1_.cos(u);

      // Transorm points and add to points list
      constructor.setOffset();
      for (int i = 0; i < 2; ++i)
      {
        Point point = evaluateEllipsoidPoint(sinPhi[i], cosPhi[i], sinTheta, cosTheta);
        Vector pVector = Vector(trans_ * point);

        Vector normal;
        if(flatTensor_)
        {
          // Avoids recalculating norm vector and prevents vectors with infinite length
          bool first_half = v < nv_/2;
          normal = first_half ? zeroNorm_ : -zeroNorm_;
        }
        else
        {
          normal = rotate_ * Vector(point);
          normal.safe_normalize();
        }

        constructor.addVertex(pVector, normal, color_);
      }

      constructor.addIndicesToOffset(0, 1, 2);
      constructor.addIndicesToOffset(2, 1, 3);
    }
    constructor.popIndicesNTimes(6);
  }
}

Point TensorGlyphBuilder::evaluateEllipsoidPoint(double sinPhi, double cosPhi,
                                                 double sinTheta, double cosTheta)
{
  double x, y, z;
  x = sinPhi * sinTheta;
  y = sinPhi * cosTheta;
  z = cosPhi;
  return Point(x, y, z);
}

void TensorGlyphBuilder::generateSuperquadricTensor(GlyphConstructor& constructor, double emphasis)
{
  makeTensorPositive();
  computeTransforms();
  postScaleTransorms();
  computeSinCosTable(false);

  double cl = t_.linearCertainty();
  double cp = t_.planarCertainty();
  bool linear = cl >= cp;

  double pPower = GlyphGeomUtility::spow((1.0 - cp), emphasis);
  double lPower = GlyphGeomUtility::spow((1.0 - cl), emphasis);
  double A = linear ? pPower : lPower;
  double B = linear ? lPower : pPower;

  double normalA = 2.0-A;
  double normalB = 2.0-B;

  for (int v = 0; v < nv_ - 1; ++v)
  {
    double sinPhi[2];
    sinPhi[0] = tab2_.sin(v);
    sinPhi[1] = tab2_.sin(v+1);

    double cosPhi[2];
    cosPhi[0] = tab2_.cos(v);
    cosPhi[1] = tab2_.cos(v+1);

    for (int u = 0; u < nu_; ++u)
    {
      constructor.setOffset();
      double sinTheta = tab1_.sin(u);
      double cosTheta = tab1_.cos(u);

      for(int i = 0; i < 2; ++i)
      {
        // Transorm points and add to points list
        Point p = evaluateSuperquadricPoint(linear, sinPhi[i], cosPhi[i], sinTheta, cosTheta, A, B);
        Vector pVector = Vector(trans_ * p);

        Vector normal;
        if(flatTensor_)
        {
          // Avoids recalculating norm vector and prevents vectors with infinite length
          bool first_half = v < nv_/2;
          normal = first_half ? zeroNorm_ : -zeroNorm_;
        }
        else
        {
          normal = Vector(evaluateSuperquadricPoint(linear, sinPhi[i], cosPhi[i],
                                                    sinTheta, cosTheta, normalA, normalB));
          normal = rotate_ * normal;
          normal.safe_normalize();
        }

        constructor.addVertex(pVector, normal, color_);
      }

      constructor.addIndicesToOffset(0, 1, 2);
      constructor.addIndicesToOffset(2, 1, 3);
    }
  }
  constructor.popIndicesNTimes(6);
}

Point TensorGlyphBuilder::evaluateSuperquadricPoint(bool linear, double sinPhi, double cosPhi,
                                                    double sinTheta, double cosTheta,
                                                    double A, double B)
{
  if (linear)
    return evaluateSuperquadricPointLinear(sinPhi, cosPhi, sinTheta, cosTheta, A, B);
  else
    return evaluateSuperquadricPointPlanar(sinPhi, cosPhi, sinTheta, cosTheta, A, B);
}

// Generate around x-axis
Point TensorGlyphBuilder::evaluateSuperquadricPointLinear(double sinPhi, double cosPhi,
                                                          double sinTheta, double cosTheta,
                                                          double A, double B)
{
  double x, y, z;
  x =  GlyphGeomUtility::spow(cosPhi, B);
  y = -GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(sinTheta, A);
  z =  GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(cosTheta, A);
  return Point(x, y, z);
}

// Generate around z-axis
Point TensorGlyphBuilder::evaluateSuperquadricPointPlanar(double sinPhi, double cosPhi,
                                                          double sinTheta, double cosTheta,
                                                          double A, double B)
{
  double x, y, z;
  x = GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(cosTheta, A);
  y = GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(sinTheta, A);
  z = GlyphGeomUtility::spow(cosPhi, B);
  return Point(x, y, z);
}

void TensorGlyphBuilder::generateBox(GlyphConstructor& constructor)
{
  computeTransforms();

  std::vector<Vector> box_points = generateBoxPoints();
  std::vector<Vector> normals = rotate_.get_column_vectors();
  if(flatTensor_)
    for(int d = 0; d < DIMENSIONS_; ++d)
      normals[d] = zeroNorm_;

  generateBoxSide(constructor, box_points[5], box_points[4], box_points[7], box_points[6],  normals[0]);
  generateBoxSide(constructor, box_points[7], box_points[6], box_points[3], box_points[2],  normals[1]);
  generateBoxSide(constructor, box_points[1], box_points[5], box_points[3], box_points[7],  normals[2]);
  generateBoxSide(constructor, box_points[3], box_points[2], box_points[1], box_points[0], -normals[0]);
  generateBoxSide(constructor, box_points[1], box_points[0], box_points[5], box_points[4], -normals[1]);
  generateBoxSide(constructor, box_points[2], box_points[6], box_points[0], box_points[4], -normals[2]);
}

void TensorGlyphBuilder::generateBoxSide(GlyphConstructor& constructor, const Vector& p1, const Vector& p2, const Vector& p3,
                                         const Vector& p4, const Vector& normal)
{
  constructor.setOffset();
  constructor.addVertex(p1, normal, color_);
  constructor.addVertex(p2, normal, color_);
  constructor.addVertex(p3, normal, color_);
  constructor.addVertex(p4, normal, color_);
  constructor.addIndicesToOffset(2, 0, 3);
  constructor.addIndicesToOffset(1, 3, 0);
}

std::vector<Vector> TensorGlyphBuilder::generateBoxPoints()
{
  auto eigvals = getEigenValues();
  std::vector<Vector> boxPoints;

  for(int x : {-1, 1})
    for(int y : {-1, 1})
      for(int z : {-1, 1})
        boxPoints.emplace_back(trans_ * Point(x * eigvals[0], y * eigvals[1], z * eigvals[2]));

  return boxPoints;
}

<commit_msg>function name changed<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2020 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Graphics/Glyphs/TensorGlyphBuilder.h>
#include <Graphics/Glyphs/GlyphGeomUtility.h>
#include <Core/GeometryPrimitives/Transform.h>
#include <Core/Math/MiscMath.h>

using namespace SCIRun;
using namespace Graphics;
using namespace Core::Geometry;
using namespace Core::Datatypes;

TensorGlyphBuilder::TensorGlyphBuilder(const Tensor& t, const Point& center)
{
  t_ = t;
  center_ = Point(center);
}

void TensorGlyphBuilder::scaleTensor(double scale)
{
  t_ = t_ * scale;
}

std::vector<Vector> TensorGlyphBuilder::getEigenVectors()
{
  std::vector<Vector> eigvecs(DIMENSIONS_);
  t_.get_eigenvectors(eigvecs[0], eigvecs[1], eigvecs[2]);
  return eigvecs;
}

std::vector<double> TensorGlyphBuilder::getEigenValues()
{
  std::vector<double> eigvals(DIMENSIONS_);
  t_.get_eigenvalues(eigvals[0], eigvals[1], eigvals[2]);
  return eigvals;
}

void TensorGlyphBuilder::normalizeTensor()
{
  auto eigvecs = getEigenVectors();
  for (auto& v : eigvecs)
    v.normalize();

  auto norm = t_.euclidean_norm();
  t_.set_outside_eigens(eigvecs[0] * norm[0], eigvecs[1] * norm[1], eigvecs[2] * norm[2],
                        norm[0], norm[1], norm[2]);
}

void TensorGlyphBuilder::setColor(const ColorRGB& color)
{
  color_ = color;
}

void TensorGlyphBuilder::setResolution(double resolution)
{
  resolution_ = resolution;
}

void TensorGlyphBuilder::reorderTensorValues(std::vector<Vector>& eigvecs,
                                             std::vector<double>& eigvals)
{
  std::vector<std::pair<double, Vector>> sortList(3);
  for(int d = 0; d < DIMENSIONS_; ++d)
    sortList[d] = std::make_pair(eigvals[d], eigvecs[d]);

  std::sort(std::begin(sortList), std::end(sortList), std::greater<std::pair<double, Vector>>());

  for(int d = 0; d < DIMENSIONS_; ++d)
  {
    eigvals[d] = sortList[d].first;
    eigvecs[d] = sortList[d].second;
  }
}
void TensorGlyphBuilder::makeTensorPositive()
{
  static const double zeroThreshold = 0.000001;

  auto eigvals = getEigenValues();
  auto eigvecs = getEigenVectors();
  for (auto& e : eigvals)
  {
    e = fabs(e);
    if(e <= zeroThreshold)
      e = 0;
  }

  // These are exactly zero after thresholding
  flatTensor_ = eigvals[0] == 0 || eigvals[1] == 0 || eigvals[2] == 0;

  if (flatTensor_)
    reorderTensorValues(eigvecs, eigvals);

  for (int d = 0; d < DIMENSIONS_; ++d)
    if (eigvals[d] == 0)
    {
      zeroNorm_ = Cross(eigvecs[(d+1) % DIMENSIONS_], eigvecs[(d+2) % DIMENSIONS_]).normal();
      eigvecs[d] = zeroNorm_ * eigvals[d];
      break;
    }

  t_.set_outside_eigens(eigvecs[0], eigvecs[1], eigvecs[2],
                        eigvals[0], eigvals[1], eigvals[2]);
}

void TensorGlyphBuilder::computeSinCosTable(bool half)
{
  nv_ = resolution_;
  nu_ = resolution_ + 1;

  // Should only happen when doing half ellipsoids.
  if (half) nv_ /= 2;
  if (nv_ < 2) nv_ = 2;

  double end = half ? M_PI : 2.0 * M_PI;
  tab1_ = SinCosTable(nu_, 0, end);
  tab2_ = SinCosTable(nv_, 0, M_PI);
}

void TensorGlyphBuilder::computeTransforms()
{
  auto eigvecs = getEigenVectors();
  for (auto& v : eigvecs)
    v.normalize();
  GlyphGeomUtility::generateTransforms(center_, eigvecs[0], eigvecs[1], eigvecs[2], trans_, rotate_);
}

void TensorGlyphBuilder::postScaleTransorms()
{
  auto eigvals = getEigenValues();
  Vector eigvalsVector(eigvals[0], eigvals[1], eigvals[2]);

  trans_.post_scale( Vector(1.0,1.0,1.0) * eigvalsVector);
  rotate_.post_scale(Vector(1.0,1.0,1.0) / eigvalsVector);
}

void TensorGlyphBuilder::generateEllipsoid(GlyphConstructor& constructor, bool half)
{
  computeTransforms();
  postScaleTransorms();
  computeSinCosTable(half);

  for (int v = 0; v < nv_ - 1; ++v)
  {
    double sinPhi[2];
    sinPhi[0] = tab2_.sin(v+1);
    sinPhi[1] = tab2_.sin(v);

    double cosPhi[2];
    cosPhi[0] = tab2_.cos(v+1);
    cosPhi[1] = tab2_.cos(v);

    for (int u = 0; u < nu_; ++u)
    {
      double sinTheta = tab1_.sin(u);
      double cosTheta = tab1_.cos(u);

      // Transorm points and add to points list
      constructor.setOffset();
      for (int i = 0; i < 2; ++i)
      {
        Point point = evaluateEllipsoidPoint(sinPhi[i], cosPhi[i], sinTheta, cosTheta);
        Vector pVector = Vector(trans_ * point);

        Vector normal;
        if(flatTensor_)
        {
          // Avoids recalculating norm vector and prevents vectors with infinite length
          bool first_half = v < nv_/2;
          normal = first_half ? zeroNorm_ : -zeroNorm_;
        }
        else
        {
          normal = rotate_ * Vector(point);
          normal.safe_normalize();
        }

        constructor.addVertex(pVector, normal, color_);
      }

      constructor.addIndicesToOffset(0, 1, 2);
      constructor.addIndicesToOffset(2, 1, 3);
    }
    constructor.popIndicesNTimes(6);
  }
}

Point TensorGlyphBuilder::evaluateEllipsoidPoint(double sinPhi, double cosPhi,
                                                 double sinTheta, double cosTheta)
{
  double x, y, z;
  x = sinPhi * sinTheta;
  y = sinPhi * cosTheta;
  z = cosPhi;
  return Point(x, y, z);
}

void TensorGlyphBuilder::generateSuperquadricTensor(GlyphConstructor& constructor, double emphasis)
{
  makeTensorPositive();
  computeTransforms();
  postScaleTransorms();
  computeSinCosTable(false);

  double cl = t_.linearCertainty();
  double cp = t_.planarCertainty();
  bool linear = cl >= cp;

  double pPower = GlyphGeomUtility::spow((1.0 - cp), emphasis);
  double lPower = GlyphGeomUtility::spow((1.0 - cl), emphasis);
  double A = linear ? pPower : lPower;
  double B = linear ? lPower : pPower;

  double normalA = 2.0-A;
  double normalB = 2.0-B;

  for (int v = 0; v < nv_ - 1; ++v)
  {
    double sinPhi[2];
    sinPhi[0] = tab2_.sin(v);
    sinPhi[1] = tab2_.sin(v+1);

    double cosPhi[2];
    cosPhi[0] = tab2_.cos(v);
    cosPhi[1] = tab2_.cos(v+1);

    for (int u = 0; u < nu_; ++u)
    {
      constructor.setOffset();
      double sinTheta = tab1_.sin(u);
      double cosTheta = tab1_.cos(u);

      for(int i = 0; i < 2; ++i)
      {
        // Transorm points and add to points list
        Point p = evaluateSuperquadricPoint(linear, sinPhi[i], cosPhi[i], sinTheta, cosTheta, A, B);
        Vector pVector = Vector(trans_ * p);

        Vector normal;
        if(flatTensor_)
        {
          // Avoids recalculating norm vector and prevents vectors with infinite length
          bool first_half = v < nv_/2;
          normal = first_half ? zeroNorm_ : -zeroNorm_;
        }
        else
        {
          normal = Vector(evaluateSuperquadricPoint(linear, sinPhi[i], cosPhi[i],
                                                    sinTheta, cosTheta, normalA, normalB));
          normal = rotate_ * normal;
          normal.safe_normalize();
        }

        constructor.addVertex(pVector, normal, color_);
      }

      constructor.addIndicesToOffset(0, 1, 2);
      constructor.addIndicesToOffset(2, 1, 3);
    }
  }
  constructor.popIndicesNTimes(6);
}

Point TensorGlyphBuilder::evaluateSuperquadricPoint(bool linear, double sinPhi, double cosPhi,
                                                    double sinTheta, double cosTheta,
                                                    double A, double B)
{
  if (linear)
    return evaluateSuperquadricPointLinear(sinPhi, cosPhi, sinTheta, cosTheta, A, B);
  else
    return evaluateSuperquadricPointPlanar(sinPhi, cosPhi, sinTheta, cosTheta, A, B);
}

// Generate around x-axis
Point TensorGlyphBuilder::evaluateSuperquadricPointLinear(double sinPhi, double cosPhi,
                                                          double sinTheta, double cosTheta,
                                                          double A, double B)
{
  double x, y, z;
  x =  GlyphGeomUtility::spow(cosPhi, B);
  y = -GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(sinTheta, A);
  z =  GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(cosTheta, A);
  return Point(x, y, z);
}

// Generate around z-axis
Point TensorGlyphBuilder::evaluateSuperquadricPointPlanar(double sinPhi, double cosPhi,
                                                          double sinTheta, double cosTheta,
                                                          double A, double B)
{
  double x, y, z;
  x = GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(cosTheta, A);
  y = GlyphGeomUtility::spow(sinPhi, B) * GlyphGeomUtility::spow(sinTheta, A);
  z = GlyphGeomUtility::spow(cosPhi, B);
  return Point(x, y, z);
}

void TensorGlyphBuilder::generateBox(GlyphConstructor& constructor)
{
  computeTransforms();

  std::vector<Vector> box_points = generateBoxPoints();
  std::vector<Vector> normals = rotate_.get_rotation();
  if(flatTensor_)
    for(int d = 0; d < DIMENSIONS_; ++d)
      normals[d] = zeroNorm_;

  generateBoxSide(constructor, box_points[5], box_points[4], box_points[7], box_points[6],  normals[0]);
  generateBoxSide(constructor, box_points[7], box_points[6], box_points[3], box_points[2],  normals[1]);
  generateBoxSide(constructor, box_points[1], box_points[5], box_points[3], box_points[7],  normals[2]);
  generateBoxSide(constructor, box_points[3], box_points[2], box_points[1], box_points[0], -normals[0]);
  generateBoxSide(constructor, box_points[1], box_points[0], box_points[5], box_points[4], -normals[1]);
  generateBoxSide(constructor, box_points[2], box_points[6], box_points[0], box_points[4], -normals[2]);
}

void TensorGlyphBuilder::generateBoxSide(GlyphConstructor& constructor, const Vector& p1, const Vector& p2, const Vector& p3,
                                         const Vector& p4, const Vector& normal)
{
  constructor.setOffset();
  constructor.addVertex(p1, normal, color_);
  constructor.addVertex(p2, normal, color_);
  constructor.addVertex(p3, normal, color_);
  constructor.addVertex(p4, normal, color_);
  constructor.addIndicesToOffset(2, 0, 3);
  constructor.addIndicesToOffset(1, 3, 0);
}

std::vector<Vector> TensorGlyphBuilder::generateBoxPoints()
{
  auto eigvals = getEigenValues();
  std::vector<Vector> boxPoints;

  for(int x : {-1, 1})
    for(int y : {-1, 1})
      for(int z : {-1, 1})
        boxPoints.emplace_back(trans_ * Point(x * eigvals[0], y * eigvals[1], z * eigvals[2]));

  return boxPoints;
}

<|endoftext|>


<commit_before>/*
  InputDebounce Arduino Library

  Mario Ban, 05.2015

  GNU General Public License v2.0
  Copyright (C) 2015 Mario Ban
*/

#include "InputDebounce.h"

InputDebounce::InputDebounce(int8_t pinIn, unsigned long debDelay, PinInMode pinInMode)
  : _pinIn(0)
  , _debDelay(0)
  , _pinInMode(PIM_INT_PULL_UP_RES)
  , _enabled(false)
  , _valueLast(false)
  , _stateOn(false)
  , _timeStamp(0)
  , _stateOnCount(0)
{
  xsetup(pinIn, debDelay, pinInMode);
}

void InputDebounce::setup(int8_t pinIn, unsigned long debDelay, PinInMode pinInMode)
{
  if(pinIn >= 0) {
    _pinIn = pinIn;
    _debDelay = debDelay;
    _pinInMode = pinInMode;
    // initialize digital pin as an input
    if(_pinInMode == PIM_INT_PULL_UP_RES) {
      pinMode(_pinIn, INPUT_PULLUP);
    }
    else {
      pinMode(_pinIn, INPUT);
    }
    _enabled = true;
  }
  else {
    _enabled = false;
  }
}

unsigned long InputDebounce::process(unsigned long now)
{
  if(!_enabled) {
    return 0;
  }
  bool value = digitalRead(_pinIn) ? true : false; // LOW (with pull-up res) when button pressed (on)
  // adjust value pressed (on)
  if(_pinInMode != PIM_EXT_PULL_DOWN_RES) {
    value = !value;
  }
  // check if input value changed
  if(_valueLast != value) {
    _valueLast = value;
    _timeStamp = now;
    return 0;
  }
  // wait debouncing time
  if(now - _timeStamp > _debDelay) {
    // input value (state) has been stable longer than the debounce period
    if(_stateOn != _valueLast) {
      _stateOn = _valueLast;
      if(_stateOn) {
        _stateOnCount++;
      }
    }
    return _stateOn ? now - _timeStamp : 0;
  }
  return 0;
}

unsigned long InputDebounce::getStateOnCount() const
{
  return _stateOnCount;
}
<commit_msg>Test Travis CI: build fixed<commit_after>/*
  InputDebounce Arduino Library

  Mario Ban, 05.2015

  GNU General Public License v2.0
  Copyright (C) 2015 Mario Ban
*/

#include "InputDebounce.h"

InputDebounce::InputDebounce(int8_t pinIn, unsigned long debDelay, PinInMode pinInMode)
  : _pinIn(0)
  , _debDelay(0)
  , _pinInMode(PIM_INT_PULL_UP_RES)
  , _enabled(false)
  , _valueLast(false)
  , _stateOn(false)
  , _timeStamp(0)
  , _stateOnCount(0)
{
  setup(pinIn, debDelay, pinInMode);
}

void InputDebounce::setup(int8_t pinIn, unsigned long debDelay, PinInMode pinInMode)
{
  if(pinIn >= 0) {
    _pinIn = pinIn;
    _debDelay = debDelay;
    _pinInMode = pinInMode;
    // initialize digital pin as an input
    if(_pinInMode == PIM_INT_PULL_UP_RES) {
      pinMode(_pinIn, INPUT_PULLUP);
    }
    else {
      pinMode(_pinIn, INPUT);
    }
    _enabled = true;
  }
  else {
    _enabled = false;
  }
}

unsigned long InputDebounce::process(unsigned long now)
{
  if(!_enabled) {
    return 0;
  }
  bool value = digitalRead(_pinIn) ? true : false; // LOW (with pull-up res) when button pressed (on)
  // adjust value pressed (on)
  if(_pinInMode != PIM_EXT_PULL_DOWN_RES) {
    value = !value;
  }
  // check if input value changed
  if(_valueLast != value) {
    _valueLast = value;
    _timeStamp = now;
    return 0;
  }
  // wait debouncing time
  if(now - _timeStamp > _debDelay) {
    // input value (state) has been stable longer than the debounce period
    if(_stateOn != _valueLast) {
      _stateOn = _valueLast;
      if(_stateOn) {
        _stateOnCount++;
      }
    }
    return _stateOn ? now - _timeStamp : 0;
  }
  return 0;
}

unsigned long InputDebounce::getStateOnCount() const
{
  return _stateOnCount;
}
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_DSL_IDENTITY_HPP_
#define _SNARKFRONT_DSL_IDENTITY_HPP_

#include <array>
#include <cstdint>
#include <BigInt.hpp> // snarklib
#include "DSL_base.hpp"

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// identity elements
//

// Boolean
bool zero(const bool& dummy);
bool one(const bool& dummy);

template <typename FR>
c_bool<FR> zero(const bool_x<FR>& dummy) {
    return c_bool<FR>(false);
}

template <typename FR>
c_bool<FR> one(const bool_x<FR>& dummy) {
    return c_bool<FR>(true);
}

template <typename FR, std::size_t N>
std::array<c_bool<FR>, N> zero(const std::array<bool_x<FR>, N>& dummy) {
    std::array<c_bool<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// big integer
template <mp_size_t N>
snarklib::BigInt<N> zero(const snarklib::BigInt<N>& dummy) {
    return snarklib::BigInt<N>::zero();
}

template <mp_size_t N>
snarklib::BigInt<N> one(const snarklib::BigInt<N>& dummy) {
    return snarklib::BigInt<N>::one();
}

template <typename FR>
c_bigint<FR> zero(const bigint_x<FR>& dummy) {
    return c_bigint<FR>(bigint_x<FR>::ValueType::zero());
}

template <typename FR>
c_bigint<FR> one(const bigint_x<FR>& dummy) {
    return c_bigint<FR>(bigint_x<FR>::ValueType::one());
}

template <typename FR, std::size_t N>
std::array<c_bigint<FR>, N> zero(const std::array<bigint_x<FR>, N>& dummy) {
    std::array<c_bigint<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// 32-bit word
std::uint32_t zero(const std::uint32_t& dummy);
std::uint32_t one(const std::uint32_t& dummy);

template <typename FR>
c_uint32<FR> zero(const uint32_x<FR>& dummy) {
    return c_uint32<FR>(0);
}

template <typename FR>
c_uint32<FR> one(const uint32_x<FR>& dummy) {
    return c_uint32<FR>(1);
}

template <typename FR, std::size_t N>
std::array<c_uint32<FR>, N> zero(const std::array<uint32_x<FR>, N>& dummy) {
    std::array<c_uint32<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// 64-bit word
std::uint64_t zero(const std::uint64_t& dummy);
std::uint64_t one(const std::uint64_t& dummy);

template <typename FR>
c_uint64<FR> zero(const uint64_x<FR>& dummy) {
    return c_uint64<FR>(0);
}

template <typename FR>
c_uint64<FR> one(const uint64_x<FR>& dummy) {
    return c_uint64<FR>(1);
}

template <typename FR, std::size_t N>
std::array<c_uint64<FR>, N> zero(const std::array<uint64_x<FR>, N>& dummy) {
    std::array<c_uint64<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

} // namespace snarkfront

#endif
<commit_msg>8-bit unsigned int type<commit_after>#ifndef _SNARKFRONT_DSL_IDENTITY_HPP_
#define _SNARKFRONT_DSL_IDENTITY_HPP_

#include <array>
#include <cstdint>
#include <BigInt.hpp> // snarklib
#include "DSL_base.hpp"

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// identity elements
//

// Boolean
bool zero(const bool& dummy);
bool one(const bool& dummy);

template <typename FR>
c_bool<FR> zero(const bool_x<FR>& dummy) {
    return c_bool<FR>(false);
}

template <typename FR>
c_bool<FR> one(const bool_x<FR>& dummy) {
    return c_bool<FR>(true);
}

template <typename FR, std::size_t N>
std::array<c_bool<FR>, N> zero(const std::array<bool_x<FR>, N>& dummy) {
    std::array<c_bool<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// big integer
template <mp_size_t N>
snarklib::BigInt<N> zero(const snarklib::BigInt<N>& dummy) {
    return snarklib::BigInt<N>::zero();
}

template <mp_size_t N>
snarklib::BigInt<N> one(const snarklib::BigInt<N>& dummy) {
    return snarklib::BigInt<N>::one();
}

template <typename FR>
c_bigint<FR> zero(const bigint_x<FR>& dummy) {
    return c_bigint<FR>(bigint_x<FR>::ValueType::zero());
}

template <typename FR>
c_bigint<FR> one(const bigint_x<FR>& dummy) {
    return c_bigint<FR>(bigint_x<FR>::ValueType::one());
}

template <typename FR, std::size_t N>
std::array<c_bigint<FR>, N> zero(const std::array<bigint_x<FR>, N>& dummy) {
    std::array<c_bigint<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// 8-bit octet
std::uint8_t zero(const std::uint8_t& dummy);
std::uint8_t one(const std::uint8_t& dummy);

template <typename FR>
c_uint8<FR> zero(const uint8_x<FR>& dummy) {
    return c_uint8<FR>(0);
}

template <typename FR>
c_uint8<FR> one(const uint8_x<FR>& dummy) {
    return c_uint8<FR>(1);
}

template <typename FR, std::size_t N>
std::array<c_uint8<FR>, N> zero(const std::array<uint8_x<FR>, N>& dummy) {
    std::array<c_uint8<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// 32-bit word
std::uint32_t zero(const std::uint32_t& dummy);
std::uint32_t one(const std::uint32_t& dummy);

template <typename FR>
c_uint32<FR> zero(const uint32_x<FR>& dummy) {
    return c_uint32<FR>(0);
}

template <typename FR>
c_uint32<FR> one(const uint32_x<FR>& dummy) {
    return c_uint32<FR>(1);
}

template <typename FR, std::size_t N>
std::array<c_uint32<FR>, N> zero(const std::array<uint32_x<FR>, N>& dummy) {
    std::array<c_uint32<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

// 64-bit word
std::uint64_t zero(const std::uint64_t& dummy);
std::uint64_t one(const std::uint64_t& dummy);

template <typename FR>
c_uint64<FR> zero(const uint64_x<FR>& dummy) {
    return c_uint64<FR>(0);
}

template <typename FR>
c_uint64<FR> one(const uint64_x<FR>& dummy) {
    return c_uint64<FR>(1);
}

template <typename FR, std::size_t N>
std::array<c_uint64<FR>, N> zero(const std::array<uint64_x<FR>, N>& dummy) {
    std::array<c_uint64<FR>, N> a;

    for (std::size_t i = 0; i < N; ++i)
        a[i] = zero(dummy[i]);

    return a;
}

} // namespace snarkfront

#endif
<|endoftext|>


<commit_before>/* Copyright 2019 Benjamin Worpitz
 *
 * This file is part of Alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <alpaka/acc/AccDevProps.hpp>
#include <alpaka/core/Common.hpp>
#include <alpaka/core/Concepts.hpp>
#include <alpaka/dev/Traits.hpp>
#include <alpaka/kernel/Traits.hpp>
#include <alpaka/dim/Traits.hpp>
#include <alpaka/idx/Traits.hpp>
#include <alpaka/pltf/Traits.hpp>
#include <alpaka/queue/Traits.hpp>

#include <string>
#include <typeinfo>
#include <type_traits>

namespace alpaka
{
    //-----------------------------------------------------------------------------
    //! The accelerator specifics.
    namespace acc
    {
        struct ConceptUniformCudaHip{};

        struct ConceptAcc{};
        //-----------------------------------------------------------------------------
        //! The accelerator traits.
        namespace traits
        {
            //#############################################################################
            //! The accelerator type trait.
            template<
                typename T,
                typename TSfinae = void>
            struct AccType;

            //#############################################################################
            //! The device properties get trait.
            template<
                typename TAcc,
                typename TSfinae = void>
            struct GetAccDevProps;

            //#############################################################################
            //! The accelerator name trait.
            //!
            //! The default implementation returns the mangled class name.
            template<
                typename TAcc,
                typename TSfinae = void>
            struct GetAccName
            {
                //-----------------------------------------------------------------------------
                ALPAKA_FN_HOST static auto getAccName()
                -> std::string
                {
                    return typeid(TAcc).name();
                }
            };

            //#############################################################################
            //! The GPU CUDA accelerator device properties get trait specialization.
            template<typename TAcc>
            struct GetAccDevProps<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                //-----------------------------------------------------------------------------
                ALPAKA_FN_HOST static auto getAccDevProps(
                    typename dev::traits::DevType<TAcc>::type const & dev)
                -> AccDevProps<typename dim::traits::DimType<TAcc>::type, typename idx::traits::IdxType<TAcc>::type>
                {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    return GetAccDevProps<ImplementationBase>::getAccDevProps(dev);
                }
            };
        }

        //#############################################################################
        //! The accelerator type trait alias template to remove the ::type.
        template<
            typename T>
        using Acc = typename traits::AccType<T>::type;

        //-----------------------------------------------------------------------------
        //! \return The acceleration properties on the given device.
        template<
            typename TAcc,
            typename TDev>
        ALPAKA_FN_HOST auto getAccDevProps(
            TDev const & dev)
        -> AccDevProps<dim::Dim<TAcc>, idx::Idx<TAcc>>
        {
            return
                traits::GetAccDevProps<
                    TAcc>
                ::getAccDevProps(
                    dev);
        }

        //-----------------------------------------------------------------------------
        //! \return The accelerator name
        //!
        //! \tparam TAcc The accelerator type.
        template<
            typename TAcc>
        ALPAKA_FN_HOST auto getAccName()
        -> std::string
        {
            return
                traits::GetAccName<
                    TAcc>
                ::getAccName();
        }
    }

    namespace kernel
    {
        namespace detail
        {
            template<typename TAcc>
            struct CheckFnReturnType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                 template<
                    typename TKernelFnObj,
                    typename... TArgs>
                void operator()(
                    TKernelFnObj const & kernelFnObj,
                    TArgs const & ... args)
                {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    CheckFnReturnType<ImplementationBase>{}(
                        kernelFnObj,
                        args...);
                }
            };
        }

    }

    namespace dev
    {
        namespace traits
        {
            //#############################################################################
            //! The GPU HIP accelerator device type trait specialization.
            template<typename TAcc>
            struct DevType<
               TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                using type = typename DevType<ImplementationBase>::type;
            };
        }
    }
    namespace pltf
    {
        namespace traits
        {
            //#############################################################################
            //! The CPU HIP execution task platform type trait specialization.
            template<typename TAcc>
            struct PltfType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
                {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    using type = typename PltfType<ImplementationBase>::type;
                };
        }

    }
    namespace dim
    {
        namespace traits
        {
            //#############################################################################
            //! The GPU HIP accelerator dimension getter trait specialization.
            template<typename TAcc>
            struct DimType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    using type = typename DimType<ImplementationBase>::type;
            };
        }
    }
    namespace idx
    {
        namespace traits
        {
            //#############################################################################
            //! The GPU HIP accelerator idx type trait specialization.
            template<typename TAcc>
            struct IdxType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                using type = typename IdxType<ImplementationBase>::type;
            };
        }
    }

    namespace queue
    {
        namespace traits
        {
            template<
                typename TAcc,
                typename TProperty>
            struct QueueType<
                TAcc,
                TProperty,
                std::enable_if_t<
                    concepts::ImplementsConcept<acc::ConceptAcc, TAcc>::value
                >
            >
            {
                using type = typename QueueType<
                    typename pltf::traits::PltfType<TAcc>::type,
                    TProperty
                >::type;
            };
        }
    }
}
<commit_msg>Fix getAccDevProps: Add ImplementationBase<commit_after>/* Copyright 2019 Benjamin Worpitz
 *
 * This file is part of Alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <alpaka/acc/AccDevProps.hpp>
#include <alpaka/core/Common.hpp>
#include <alpaka/core/Concepts.hpp>
#include <alpaka/dev/Traits.hpp>
#include <alpaka/kernel/Traits.hpp>
#include <alpaka/dim/Traits.hpp>
#include <alpaka/idx/Traits.hpp>
#include <alpaka/pltf/Traits.hpp>
#include <alpaka/queue/Traits.hpp>

#include <string>
#include <typeinfo>
#include <type_traits>

namespace alpaka
{
    //-----------------------------------------------------------------------------
    //! The accelerator specifics.
    namespace acc
    {
        struct ConceptUniformCudaHip{};

        struct ConceptAcc{};
        //-----------------------------------------------------------------------------
        //! The accelerator traits.
        namespace traits
        {
            //#############################################################################
            //! The accelerator type trait.
            template<
                typename T,
                typename TSfinae = void>
            struct AccType;

            //#############################################################################
            //! The device properties get trait.
            template<
                typename TAcc,
                typename TSfinae = void>
            struct GetAccDevProps;

            //#############################################################################
            //! The accelerator name trait.
            //!
            //! The default implementation returns the mangled class name.
            template<
                typename TAcc,
                typename TSfinae = void>
            struct GetAccName
            {
                //-----------------------------------------------------------------------------
                ALPAKA_FN_HOST static auto getAccName()
                -> std::string
                {
                    return typeid(TAcc).name();
                }
            };

            //#############################################################################
            //! The GPU CUDA accelerator device properties get trait specialization.
            template<typename TAcc>
            struct GetAccDevProps<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                //-----------------------------------------------------------------------------
                ALPAKA_FN_HOST static auto getAccDevProps(
                    typename dev::traits::DevType<TAcc>::type const & dev)
                -> AccDevProps<typename dim::traits::DimType<TAcc>::type, typename idx::traits::IdxType<TAcc>::type>
                {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    return GetAccDevProps<ImplementationBase>::getAccDevProps(dev);
                }
            };
        }

        //#############################################################################
        //! The accelerator type trait alias template to remove the ::type.
        template<
            typename T>
        using Acc = typename traits::AccType<T>::type;

        //-----------------------------------------------------------------------------
        //! \return The acceleration properties on the given device.
        template<
            typename TAcc,
            typename TDev>
        ALPAKA_FN_HOST auto getAccDevProps(
            TDev const & dev)
        -> AccDevProps<dim::Dim<TAcc>, idx::Idx<TAcc>>
        {
            using ImplementationBase = concepts::ImplementationBase<ConceptAcc, TAcc>;
            return
                traits::GetAccDevProps<
                    ImplementationBase>
                ::getAccDevProps(
                    dev);
        }

        //-----------------------------------------------------------------------------
        //! \return The accelerator name
        //!
        //! \tparam TAcc The accelerator type.
        template<
            typename TAcc>
        ALPAKA_FN_HOST auto getAccName()
        -> std::string
        {
            return
                traits::GetAccName<
                    TAcc>
                ::getAccName();
        }
    }

    namespace kernel
    {
        namespace detail
        {
            template<typename TAcc>
            struct CheckFnReturnType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                 template<
                    typename TKernelFnObj,
                    typename... TArgs>
                void operator()(
                    TKernelFnObj const & kernelFnObj,
                    TArgs const & ... args)
                {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    CheckFnReturnType<ImplementationBase>{}(
                        kernelFnObj,
                        args...);
                }
            };
        }

    }

    namespace dev
    {
        namespace traits
        {
            //#############################################################################
            //! The GPU HIP accelerator device type trait specialization.
            template<typename TAcc>
            struct DevType<
               TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                using type = typename DevType<ImplementationBase>::type;
            };
        }
    }
    namespace pltf
    {
        namespace traits
        {
            //#############################################################################
            //! The CPU HIP execution task platform type trait specialization.
            template<typename TAcc>
            struct PltfType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
                {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    using type = typename PltfType<ImplementationBase>::type;
                };
        }

    }
    namespace dim
    {
        namespace traits
        {
            //#############################################################################
            //! The GPU HIP accelerator dimension getter trait specialization.
            template<typename TAcc>
            struct DimType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                    using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                    using type = typename DimType<ImplementationBase>::type;
            };
        }
    }
    namespace idx
    {
        namespace traits
        {
            //#############################################################################
            //! The GPU HIP accelerator idx type trait specialization.
            template<typename TAcc>
            struct IdxType<
                TAcc,
                typename std::enable_if<
                    concepts::ImplementsConcept<acc::ConceptUniformCudaHip, TAcc>::value
                >::type>
            {
                using ImplementationBase = typename concepts::ImplementationBase<acc::ConceptUniformCudaHip, TAcc>;
                using type = typename IdxType<ImplementationBase>::type;
            };
        }
    }

    namespace queue
    {
        namespace traits
        {
            template<
                typename TAcc,
                typename TProperty>
            struct QueueType<
                TAcc,
                TProperty,
                std::enable_if_t<
                    concepts::ImplementsConcept<acc::ConceptAcc, TAcc>::value
                >
            >
            {
                using type = typename QueueType<
                    typename pltf::traits::PltfType<TAcc>::type,
                    TProperty
                >::type;
            };
        }
    }
}
<|endoftext|>


<commit_before>/*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

    ---
    Copyright (C) 2004, Anders Lund <anders@alweb.dk>
*/

#include "katemwmodonhddialog.h"

#include "kateapp.h"
#include "katedocmanager.h"
#include "katemainwindow.h"

#include <KMessageBox>
#include <KProcess>
#include <KRun>
#include <KLocalizedString>
#include <KIconLoader>

#include <QTemporaryFile>
#include <QTextStream>
#include <QHeaderView>
#include <QLabel>
#include <QPushButton>

#include <QTreeWidget>
#include <QTreeWidgetItem>

class KateDocItem : public QTreeWidgetItem
{
public:
    KateDocItem(KTextEditor::Document *doc, const QString &status, QTreeWidget *tw)
        : QTreeWidgetItem(tw),
          document(doc) {
        setText(0, doc->url().toString());
        setText(1, status);
        if (! doc->isModified()) {
            setCheckState(0, Qt::Checked);
        } else {
            setCheckState(0, Qt::Unchecked);
        }
    }
    ~KateDocItem()
    {}

    KTextEditor::Document *document;
};

KateMwModOnHdDialog::KateMwModOnHdDialog(DocVector docs, QWidget *parent, const char *name)
    : QDialog(parent),
      m_proc(0),
      m_diffFile(0)
{
    setWindowTitle(i18n("Documents Modified on Disk"));
    setObjectName(QString::fromLatin1(name));
    setModal(true);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    setLayout(mainLayout);

    // Message
    QHBoxLayout *hb = new QHBoxLayout;
    mainLayout->addLayout(hb);

    // dialog text
    QLabel *icon = new QLabel(this);
    hb->addWidget(icon);
    icon->setPixmap(DesktopIcon(QStringLiteral("dialog-warning")));

    QLabel *t = new QLabel(i18n(
                               "<qt>The documents listed below have changed on disk.
Select one "
                               "or more at once, and press an action button until the list is empty.
</qt>"), this);
    hb->addWidget(t);
    hb->setStretchFactor(t, 1000);

    // Document list
    twDocuments = new QTreeWidget(this);
    mainLayout->addWidget(twDocuments);
    QStringList header;
    header << i18n("Filename") << i18n("Status on Disk");
    twDocuments->setHeaderLabels(header);
    twDocuments->setSelectionMode(QAbstractItemView::SingleSelection);
    twDocuments->setRootIsDecorated(false);

    m_stateTexts << QString() << i18n("Modified") << i18n("Created") << i18n("Deleted");
    for (int i = 0; i < docs.size(); i++) {
        new KateDocItem(docs[i], m_stateTexts[(uint)KateApp::self()->documentManager()->documentInfo(docs[i])->modifiedOnDiscReason ], twDocuments);
    }
    twDocuments->header()->setStretchLastSection(false);
    twDocuments->header()->setSectionResizeMode(0, QHeaderView::Stretch);
    twDocuments->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);

    connect(twDocuments, &QTreeWidget::currentItemChanged, this, &KateMwModOnHdDialog::slotSelectionChanged);

    // Diff line
    hb = new QHBoxLayout;
    mainLayout->addLayout(hb);

    btnDiff = new QPushButton(QIcon::fromTheme(QStringLiteral("document-preview")), i18n("&View Difference"), this);
    btnDiff->setWhatsThis(i18n(
                              "Calculates the difference between the editor contents and the disk "
                              "file for the selected document, and shows the difference with the "
                              "default application. Requires diff(1)."));
    hb->addWidget(btnDiff);
    connect(btnDiff, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotDiff);

    // Dialog buttons
    QDialogButtonBox *buttons = new QDialogButtonBox(this);
    mainLayout->addWidget(buttons);

    QPushButton *ignoreButton = new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-warning")), i18n("&Ignore Changes"));
    ignoreButton->setToolTip(i18n("Remove modified flag from selected documents"));
    buttons->addButton(ignoreButton, QDialogButtonBox::RejectRole);
    connect(ignoreButton, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotIgnore);

    QPushButton *overwriteButton = new QPushButton;
    KGuiItem::assign(overwriteButton, KStandardGuiItem::overwrite());
    overwriteButton->setToolTip(i18n("Overwrite selected documents, discarding disk changes"));
    buttons->addButton(overwriteButton, QDialogButtonBox::DestructiveRole);
    connect(overwriteButton, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotOverwrite);

    QPushButton *reloadButton = new QPushButton(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("&Reload"));
    reloadButton->setDefault(true);
    reloadButton->setToolTip(i18n("Reload selected documents from disk"));
    buttons->addButton(reloadButton, QDialogButtonBox::DestructiveRole);
    connect(reloadButton, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotReload);

    slotSelectionChanged(NULL, NULL);
}

KateMwModOnHdDialog::~KateMwModOnHdDialog()
{
    KateMainWindow::unsetModifiedOnDiscDialogIfIf(this);
    delete m_proc;
    m_proc = 0;
    if (m_diffFile) {
        m_diffFile->setAutoRemove(true);
        delete m_diffFile;
        m_diffFile = 0;
    }
}

void KateMwModOnHdDialog::slotIgnore()
{
    handleSelected(Ignore);
}

void KateMwModOnHdDialog::slotOverwrite()
{
    handleSelected(Overwrite);
}

void KateMwModOnHdDialog::slotReload()
{
    handleSelected(Reload);
}

void KateMwModOnHdDialog::handleSelected(int action)
{
    // collect all items we can remove
    QList<QTreeWidgetItem *> itemsToDelete;
    for (QTreeWidgetItemIterator it(twDocuments); *it; ++it) {
        KateDocItem *item = (KateDocItem *) * it;
        if (item->checkState(0) == Qt::Checked) {
            KTextEditor::ModificationInterface::ModifiedOnDiskReason reason = KateApp::self()->documentManager()->documentInfo(item->document)->modifiedOnDiscReason;
            bool success = true;

            if (KTextEditor::ModificationInterface *iface = qobject_cast<KTextEditor::ModificationInterface *>(item->document)) {
                iface->setModifiedOnDisk(KTextEditor::ModificationInterface::OnDiskUnmodified);
            }

            switch (action) {
            case Overwrite:
                success = item->document->save();
                if (! success) {
                    KMessageBox::sorry(this,
                                       i18n("Could not save the document \n'%1'",
                                            item->document->url().toString()));
                }
                break;

            case Reload:
                item->document->documentReload();
                break;

            default:
                break;
            }

            if (success) {
                itemsToDelete.append(item);
            } else {
                if (KTextEditor::ModificationInterface *iface = qobject_cast<KTextEditor::ModificationInterface *>(item->document)) {
                    iface->setModifiedOnDisk(reason);
                }
            }
        }
    }

    // remove the marked items
    for (int i = 0; i < itemsToDelete.count(); ++i) {
        delete itemsToDelete[i];
    }

// any documents left unhandled?
    if (! twDocuments->topLevelItemCount()) {
        accept();
    }
}

void KateMwModOnHdDialog::slotSelectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *)
{
    KateDocItem *currentDocItem = static_cast<KateDocItem *>(current);
    // set the diff button enabled
    btnDiff->setEnabled(currentDocItem &&
                        KateApp::self()->documentManager()->documentInfo(currentDocItem->document)->modifiedOnDiscReason != KTextEditor::ModificationInterface::OnDiskDeleted);
}

// ### the code below is slightly modified from kdelibs/kate/part/katedialogs,
// class KateModOnHdPrompt.
void KateMwModOnHdDialog::slotDiff()
{
    if (!btnDiff->isEnabled()) { // diff button already pressed, proc not finished yet
        return;
    }

    if (! twDocuments->currentItem()) {
        return;
    }

    KTextEditor::Document *doc = (static_cast<KateDocItem *>(twDocuments->currentItem()))->document;

    // don't try to diff a deleted file
    if (KateApp::self()->documentManager()->documentInfo(doc)->modifiedOnDiscReason == KTextEditor::ModificationInterface::OnDiskDeleted) {
        return;
    }

    if (m_diffFile) {
        return;
    }

    m_diffFile = new QTemporaryFile();
    m_diffFile->open();

    // Start a KProcess that creates a diff
    m_proc = new KProcess(this);
    m_proc->setOutputChannelMode(KProcess::MergedChannels);
    *m_proc << QStringLiteral("diff") << QStringLiteral("-ub") << QStringLiteral("-") << doc->url().toLocalFile();
    connect(m_proc, &KProcess::readyRead, this, &KateMwModOnHdDialog::slotDataAvailable);
    connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &KateMwModOnHdDialog::slotPDone);

    setCursor(Qt::WaitCursor);
    btnDiff->setEnabled(false);

    m_proc->start();

    QTextStream ts(m_proc);
    int lastln = doc->lines() - 1;
    for (int l = 0; l < lastln; ++l) {
        ts << doc->line(l) << QLatin1Char('\n');
    }
    ts << doc->line(lastln);
    ts.flush();
    m_proc->closeWriteChannel();
}

void KateMwModOnHdDialog::slotDataAvailable()
{
    m_diffFile->write(m_proc->readAll());
}

void KateMwModOnHdDialog::slotPDone()
{
    setCursor(Qt::ArrowCursor);
    slotSelectionChanged(twDocuments->currentItem(), 0);

    const QProcess::ExitStatus es = m_proc->exitStatus();
    delete m_proc;
    m_proc = 0;

    if (es != QProcess::NormalExit) {
        KMessageBox::sorry(this,
                           i18n("The diff command failed. Please make sure that "
                                "diff(1) is installed and in your PATH."),
                           i18n("Error Creating Diff"));
        delete m_diffFile;
        m_diffFile = 0;
        return;
    }

    if (m_diffFile->size() == 0) {
        KMessageBox::information(this,
                                 i18n("Ignoring amount of white space changed, the files are identical."),
                                 i18n("Diff Output"));
        delete m_diffFile;
        m_diffFile = 0;
        return;
    }

    m_diffFile->setAutoRemove(false);
    QUrl url = QUrl::fromLocalFile(m_diffFile->fileName());
    delete m_diffFile;
    m_diffFile = 0;

    // KRun::runUrl should delete the file, once the client exits
    KRun::runUrl(url, QStringLiteral("text/x-patch"), this, true);
}

void KateMwModOnHdDialog::addDocument(KTextEditor::Document *doc)
{
    for (QTreeWidgetItemIterator it(twDocuments); *it; ++it) {
        KateDocItem *item = (KateDocItem *) * it;
        if (item->document == doc) {
            delete item;
            break;
        }
    }
    uint reason = (uint)KateApp::self()->documentManager()->documentInfo(doc)->modifiedOnDiscReason;
    if (reason) {
        new KateDocItem(doc, m_stateTexts[reason], twDocuments);
    }

    if (! twDocuments->topLevelItemCount()) {
        accept();
    }
}

void KateMwModOnHdDialog::keyPressEvent(QKeyEvent *event)
{
    if (event->modifiers() == 0) {
        if (event->key() == Qt::Key_Escape) {
            event->accept();
            return;
        }
    }
    QDialog::keyPressEvent(event);
}

void KateMwModOnHdDialog::closeEvent(QCloseEvent *e)
{
    if (! twDocuments->topLevelItemCount()) {
        QDialog::closeEvent(e);
    } else {
        e->ignore();
    }
}
<commit_msg>kill process before deleting just in case<commit_after>/*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

    ---
    Copyright (C) 2004, Anders Lund <anders@alweb.dk>
*/

#include "katemwmodonhddialog.h"

#include "kateapp.h"
#include "katedocmanager.h"
#include "katemainwindow.h"

#include <KMessageBox>
#include <KProcess>
#include <KRun>
#include <KLocalizedString>
#include <KIconLoader>

#include <QTemporaryFile>
#include <QTextStream>
#include <QHeaderView>
#include <QLabel>
#include <QPushButton>

#include <QTreeWidget>
#include <QTreeWidgetItem>

class KateDocItem : public QTreeWidgetItem
{
public:
    KateDocItem(KTextEditor::Document *doc, const QString &status, QTreeWidget *tw)
        : QTreeWidgetItem(tw),
          document(doc) {
        setText(0, doc->url().toString());
        setText(1, status);
        if (! doc->isModified()) {
            setCheckState(0, Qt::Checked);
        } else {
            setCheckState(0, Qt::Unchecked);
        }
    }
    ~KateDocItem()
    {}

    KTextEditor::Document *document;
};

KateMwModOnHdDialog::KateMwModOnHdDialog(DocVector docs, QWidget *parent, const char *name)
    : QDialog(parent),
      m_proc(0),
      m_diffFile(0)
{
    setWindowTitle(i18n("Documents Modified on Disk"));
    setObjectName(QString::fromLatin1(name));
    setModal(true);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    setLayout(mainLayout);

    // Message
    QHBoxLayout *hb = new QHBoxLayout;
    mainLayout->addLayout(hb);

    // dialog text
    QLabel *icon = new QLabel(this);
    hb->addWidget(icon);
    icon->setPixmap(DesktopIcon(QStringLiteral("dialog-warning")));

    QLabel *t = new QLabel(i18n(
                               "<qt>The documents listed below have changed on disk.
Select one "
                               "or more at once, and press an action button until the list is empty.
</qt>"), this);
    hb->addWidget(t);
    hb->setStretchFactor(t, 1000);

    // Document list
    twDocuments = new QTreeWidget(this);
    mainLayout->addWidget(twDocuments);
    QStringList header;
    header << i18n("Filename") << i18n("Status on Disk");
    twDocuments->setHeaderLabels(header);
    twDocuments->setSelectionMode(QAbstractItemView::SingleSelection);
    twDocuments->setRootIsDecorated(false);

    m_stateTexts << QString() << i18n("Modified") << i18n("Created") << i18n("Deleted");
    for (int i = 0; i < docs.size(); i++) {
        new KateDocItem(docs[i], m_stateTexts[(uint)KateApp::self()->documentManager()->documentInfo(docs[i])->modifiedOnDiscReason ], twDocuments);
    }
    twDocuments->header()->setStretchLastSection(false);
    twDocuments->header()->setSectionResizeMode(0, QHeaderView::Stretch);
    twDocuments->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);

    connect(twDocuments, &QTreeWidget::currentItemChanged, this, &KateMwModOnHdDialog::slotSelectionChanged);

    // Diff line
    hb = new QHBoxLayout;
    mainLayout->addLayout(hb);

    btnDiff = new QPushButton(QIcon::fromTheme(QStringLiteral("document-preview")), i18n("&View Difference"), this);
    btnDiff->setWhatsThis(i18n(
                              "Calculates the difference between the editor contents and the disk "
                              "file for the selected document, and shows the difference with the "
                              "default application. Requires diff(1)."));
    hb->addWidget(btnDiff);
    connect(btnDiff, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotDiff);

    // Dialog buttons
    QDialogButtonBox *buttons = new QDialogButtonBox(this);
    mainLayout->addWidget(buttons);

    QPushButton *ignoreButton = new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-warning")), i18n("&Ignore Changes"));
    ignoreButton->setToolTip(i18n("Remove modified flag from selected documents"));
    buttons->addButton(ignoreButton, QDialogButtonBox::RejectRole);
    connect(ignoreButton, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotIgnore);

    QPushButton *overwriteButton = new QPushButton;
    KGuiItem::assign(overwriteButton, KStandardGuiItem::overwrite());
    overwriteButton->setToolTip(i18n("Overwrite selected documents, discarding disk changes"));
    buttons->addButton(overwriteButton, QDialogButtonBox::DestructiveRole);
    connect(overwriteButton, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotOverwrite);

    QPushButton *reloadButton = new QPushButton(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("&Reload"));
    reloadButton->setDefault(true);
    reloadButton->setToolTip(i18n("Reload selected documents from disk"));
    buttons->addButton(reloadButton, QDialogButtonBox::DestructiveRole);
    connect(reloadButton, &QPushButton::clicked, this, &KateMwModOnHdDialog::slotReload);

    slotSelectionChanged(NULL, NULL);
}

KateMwModOnHdDialog::~KateMwModOnHdDialog()
{
    KateMainWindow::unsetModifiedOnDiscDialogIfIf(this);
    m_proc->kill();
    m_proc->waitForFinished();
    delete m_proc;
    m_proc = 0;
    if (m_diffFile) {
        m_diffFile->setAutoRemove(true);
        delete m_diffFile;
        m_diffFile = 0;
    }
}

void KateMwModOnHdDialog::slotIgnore()
{
    handleSelected(Ignore);
}

void KateMwModOnHdDialog::slotOverwrite()
{
    handleSelected(Overwrite);
}

void KateMwModOnHdDialog::slotReload()
{
    handleSelected(Reload);
}

void KateMwModOnHdDialog::handleSelected(int action)
{
    // collect all items we can remove
    QList<QTreeWidgetItem *> itemsToDelete;
    for (QTreeWidgetItemIterator it(twDocuments); *it; ++it) {
        KateDocItem *item = (KateDocItem *) * it;
        if (item->checkState(0) == Qt::Checked) {
            KTextEditor::ModificationInterface::ModifiedOnDiskReason reason = KateApp::self()->documentManager()->documentInfo(item->document)->modifiedOnDiscReason;
            bool success = true;

            if (KTextEditor::ModificationInterface *iface = qobject_cast<KTextEditor::ModificationInterface *>(item->document)) {
                iface->setModifiedOnDisk(KTextEditor::ModificationInterface::OnDiskUnmodified);
            }

            switch (action) {
            case Overwrite:
                success = item->document->save();
                if (! success) {
                    KMessageBox::sorry(this,
                                       i18n("Could not save the document \n'%1'",
                                            item->document->url().toString()));
                }
                break;

            case Reload:
                item->document->documentReload();
                break;

            default:
                break;
            }

            if (success) {
                itemsToDelete.append(item);
            } else {
                if (KTextEditor::ModificationInterface *iface = qobject_cast<KTextEditor::ModificationInterface *>(item->document)) {
                    iface->setModifiedOnDisk(reason);
                }
            }
        }
    }

    // remove the marked items
    for (int i = 0; i < itemsToDelete.count(); ++i) {
        delete itemsToDelete[i];
    }

// any documents left unhandled?
    if (! twDocuments->topLevelItemCount()) {
        accept();
    }
}

void KateMwModOnHdDialog::slotSelectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *)
{
    KateDocItem *currentDocItem = static_cast<KateDocItem *>(current);
    // set the diff button enabled
    btnDiff->setEnabled(currentDocItem &&
                        KateApp::self()->documentManager()->documentInfo(currentDocItem->document)->modifiedOnDiscReason != KTextEditor::ModificationInterface::OnDiskDeleted);
}

// ### the code below is slightly modified from kdelibs/kate/part/katedialogs,
// class KateModOnHdPrompt.
void KateMwModOnHdDialog::slotDiff()
{
    if (!btnDiff->isEnabled()) { // diff button already pressed, proc not finished yet
        return;
    }

    if (! twDocuments->currentItem()) {
        return;
    }

    KTextEditor::Document *doc = (static_cast<KateDocItem *>(twDocuments->currentItem()))->document;

    // don't try to diff a deleted file
    if (KateApp::self()->documentManager()->documentInfo(doc)->modifiedOnDiscReason == KTextEditor::ModificationInterface::OnDiskDeleted) {
        return;
    }

    if (m_diffFile) {
        return;
    }

    m_diffFile = new QTemporaryFile();
    m_diffFile->open();

    // Start a KProcess that creates a diff
    m_proc = new KProcess(this);
    m_proc->setOutputChannelMode(KProcess::MergedChannels);
    *m_proc << QStringLiteral("diff") << QStringLiteral("-ub") << QStringLiteral("-") << doc->url().toLocalFile();
    connect(m_proc, &KProcess::readyRead, this, &KateMwModOnHdDialog::slotDataAvailable);
    connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &KateMwModOnHdDialog::slotPDone);

    setCursor(Qt::WaitCursor);
    btnDiff->setEnabled(false);

    m_proc->start();

    QTextStream ts(m_proc);
    int lastln = doc->lines() - 1;
    for (int l = 0; l < lastln; ++l) {
        ts << doc->line(l) << QLatin1Char('\n');
    }
    ts << doc->line(lastln);
    ts.flush();
    m_proc->closeWriteChannel();
}

void KateMwModOnHdDialog::slotDataAvailable()
{
    m_diffFile->write(m_proc->readAll());
}

void KateMwModOnHdDialog::slotPDone()
{
    setCursor(Qt::ArrowCursor);
    slotSelectionChanged(twDocuments->currentItem(), 0);

    const QProcess::ExitStatus es = m_proc->exitStatus();
    delete m_proc;
    m_proc = 0;

    if (es != QProcess::NormalExit) {
        KMessageBox::sorry(this,
                           i18n("The diff command failed. Please make sure that "
                                "diff(1) is installed and in your PATH."),
                           i18n("Error Creating Diff"));
        delete m_diffFile;
        m_diffFile = 0;
        return;
    }

    if (m_diffFile->size() == 0) {
        KMessageBox::information(this,
                                 i18n("Ignoring amount of white space changed, the files are identical."),
                                 i18n("Diff Output"));
        delete m_diffFile;
        m_diffFile = 0;
        return;
    }

    m_diffFile->setAutoRemove(false);
    QUrl url = QUrl::fromLocalFile(m_diffFile->fileName());
    delete m_diffFile;
    m_diffFile = 0;

    // KRun::runUrl should delete the file, once the client exits
    KRun::runUrl(url, QStringLiteral("text/x-patch"), this, true);
}

void KateMwModOnHdDialog::addDocument(KTextEditor::Document *doc)
{
    for (QTreeWidgetItemIterator it(twDocuments); *it; ++it) {
        KateDocItem *item = (KateDocItem *) * it;
        if (item->document == doc) {
            delete item;
            break;
        }
    }
    uint reason = (uint)KateApp::self()->documentManager()->documentInfo(doc)->modifiedOnDiscReason;
    if (reason) {
        new KateDocItem(doc, m_stateTexts[reason], twDocuments);
    }

    if (! twDocuments->topLevelItemCount()) {
        accept();
    }
}

void KateMwModOnHdDialog::keyPressEvent(QKeyEvent *event)
{
    if (event->modifiers() == 0) {
        if (event->key() == Qt::Key_Escape) {
            event->accept();
            return;
        }
    }
    QDialog::keyPressEvent(event);
}

void KateMwModOnHdDialog::closeEvent(QCloseEvent *e)
{
    if (! twDocuments->topLevelItemCount()) {
        QDialog::closeEvent(e);
    } else {
        e->ignore();
    }
}
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"
#include "condor_distribution.h"

#include "MyString.h"

//------------------------------------------------------------------------

static void displayJobShort(AttrList* ad);
static void short_header(void);
static void short_print(int,int,const char*,int,int,int,int,int,int,const char *);
static void short_header (void);
static void shorten (char *, int);
static char* format_date( time_t date );
static char* format_time( int tot_secs );
static char encode_status( int status );
static bool EvalBool(AttrList *ad, ExprTree *tree);

//------------------------------------------------------------------------

static void Usage(char* name)
{
  printf("Usage: %s [-l] [-f history-filename] [-constraint expr | cluster_id | cluster_id.proc_id | owner]\n",name);
  exit(1);
}

//------------------------------------------------------------------------

main(int argc, char* argv[])
{
  char* JobHistoryFileName=NULL;
  int LongFormat=FALSE;
  char* constraint=NULL;
  ExprTree *constraintExpr=NULL;
  int cluster, proc;
  char tmp[512];
  int i;
  myDistro->Init( argc, argv );

  for(i=1; i<argc; i++) {
    if (strcmp(argv[i],"-l")==0) {
      LongFormat=TRUE;
    }
    else if (strcmp(argv[i],"-f")==0) {
      if (i+1==argc || JobHistoryFileName) break;
      i++;
	  JobHistoryFileName=argv[i];
    }
    else if (strcmp(argv[i],"-help")==0) {
	  Usage(argv[0]);
    }
    else if (strcmp(argv[i],"-constraint")==0) {
      if (i+1==argc || constraint) break;
      sprintf(tmp,"(%s)",argv[i+1]);
      constraint=tmp;
      i++;
    }
    else if (sscanf (argv[i], "%d.%d", &cluster, &proc) == 2) {
      if (constraint) break;
      sprintf (tmp, "((%s == %d) && (%s == %d))",
               ATTR_CLUSTER_ID, cluster,ATTR_PROC_ID, proc);
      constraint=tmp;
    }
    else if (sscanf (argv[i], "%d", &cluster) == 1) {
      if (constraint) break;
      sprintf (tmp, "(%s == %d)", ATTR_CLUSTER_ID, cluster);
      constraint=tmp;
    }
    else {
      if (constraint) break;
      sprintf(tmp, "(%s == \"%s\")", ATTR_OWNER, argv[i]);
      constraint=tmp;
    }
  }
  if (i<argc) Usage(argv[0]);

if (constraint) puts(constraint);

  config();
  if (!JobHistoryFileName) {
    JobHistoryFileName=param("HISTORY");
  }

  FILE* LogFile=fopen(JobHistoryFileName,"r");
  if (!LogFile) {
    fprintf(stderr,"History file not found or empty.\n");
    exit(1);
  }

  // printf("HistroyFile=%s\nLongFormat=%d\n",JobHistoryFileName,LongFormat);
  // if (constraint) printf("constraint=%s\n",constraint);

  if( constraint && Parse( constraint, constraintExpr ) ) {
     fprintf( stderr, "Error:  could not parse constraint %s\n", constraint );
     exit( 1 );
  }

  int EndFlag=0;
  int ErrorFlag=0;
  int EmptyFlag=0;
  AttrList *ad=0;
  if (!LongFormat) short_header();
  while(!EndFlag) {
    if( !( ad=new AttrList(LogFile,"***", EndFlag, ErrorFlag, EmptyFlag) ) ){
      fprintf( stderr, "Error:  Out of memory\n" );
      exit( 1 );
    }
    if( ErrorFlag ) {
      printf( "\t*** Warning: Bad history file; skipping malformed ad(s)\n" );
      ErrorFlag=0;
      delete ad;
      continue;
    }
	if( EmptyFlag ) {
      EmptyFlag=0;
      delete ad;
      continue;
    }
    if (!constraint || EvalBool(ad, constraintExpr)) {
      if (LongFormat) {
	    ad->fPrint(stdout); printf("\n");
	  } else {
        displayJobShort(ad);
	  }
    }
    delete ad;
  }

  fclose(LogFile);
  exit(0);
}

//------------------------------------------------------------------------

static void
displayJobShort(AttrList* ad)
{
        int cluster, proc, date, status, prio, image_size, CompDate;
        float utime;
        char owner[64], cmd[2048], args[2048];

	if(!ad->EvalFloat(ATTR_JOB_REMOTE_WALL_CLOCK,NULL,utime)) {
		if(!ad->EvalFloat(ATTR_JOB_REMOTE_USER_CPU,NULL,utime)) {
			utime = 0;
		}
	}

        if (!ad->EvalInteger (ATTR_CLUSTER_ID, NULL, cluster)           ||
                !ad->EvalInteger (ATTR_PROC_ID, NULL, proc)             ||
                !ad->EvalInteger (ATTR_Q_DATE, NULL, date)              ||
                !ad->EvalInteger (ATTR_COMPLETION_DATE, NULL, CompDate)	||
                !ad->EvalInteger (ATTR_JOB_STATUS, NULL, status)        ||
                !ad->EvalInteger (ATTR_JOB_PRIO, NULL, prio)            ||
                !ad->EvalInteger (ATTR_IMAGE_SIZE, NULL, image_size)    ||
                !ad->EvalString  (ATTR_OWNER, NULL, owner)              ||
                !ad->EvalString  (ATTR_JOB_CMD, NULL, cmd) )
        {
                printf (" --- ???? --- \n");
                return;
        }

        shorten (owner, 14);
        if (ad->EvalString ("Args", NULL, args)) strcat (cmd, args);
        shorten (cmd, 15);
        short_print (cluster, proc, owner, date, CompDate, (int)utime, status,
               prio, image_size, cmd);

}

//------------------------------------------------------------------------

static void
short_header (void)
{
    printf( " %-7s %-14s %11s %12s %-2s %11s %-15s\n",
        "ID",
        "OWNER",
        "SUBMITTED",
        "RUN_TIME",
        "ST",
		"COMPLETED",
        "CMD"
    );
}

//------------------------------------------------------------------------

static void
shorten (char *buff, int len)
{
    if ((unsigned int)strlen (buff) > (unsigned int)len) buff[len] = '\0';
}

//------------------------------------------------------------------------

/*
  Print a line of data for the "short" display of a PROC structure.  The
  "short" display is the one used by "condor_q".  N.B. the columns used
  by this routine must match those defined by the short_header routine
  defined above.
*/

static void
short_print(
        int cluster,
        int proc,
        const char *owner,
        int date,
		int CompDate,
        int time,
        int status,
        int prio,
        int image_size,
        const char *cmd
        ) {
		MyString SubmitDateStr=format_date(date);
		MyString CompDateStr=format_date(CompDate);
        printf( "%4d.%-3d %-14s %-11s %-12s %-2c %-11s %-15s\n",
                cluster,
                proc,
                owner,
                SubmitDateStr.Value(),
                format_time(time),
                encode_status(status),
                CompDateStr.Value(),
                cmd
        );
}

//------------------------------------------------------------------------

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/

static char* format_date( time_t date )
{
        static char     buf[ 12 ];
        struct tm       *tm;

		if (date==0) return " ??? ";

        tm = localtime( &date );
        sprintf( buf, "%2d/%-2d %02d:%02d",
                (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
        );
        return buf;
}

//------------------------------------------------------------------------

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/

static char     *
format_time( int tot_secs )
{
        int             days;
        int             hours;
        int             min;
        int             secs;
        static char     answer[25];

		if ( tot_secs < 0 ) {
			sprintf(answer,"[?????]");
			return answer;
		}

        days = tot_secs / DAY;
        tot_secs %= DAY;
        hours = tot_secs / HOUR;
        tot_secs %= HOUR;
        min = tot_secs / MINUTE;
        secs = tot_secs % MINUTE;

        (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
        return answer;
}

//------------------------------------------------------------------------

/*
  Encode a status from a PROC structure as a single letter suited for
  printing.
*/

static char
encode_status( int status )
{
        switch( status ) {
          case UNEXPANDED:
                return 'U';
          case IDLE:
                return 'I';
          case RUNNING:
                return 'R';
          case COMPLETED:
                return 'C';
          case REMOVED:
                return 'X';
          default:
                return ' ';
        }
}

//------------------------------------------------------------------------

static bool EvalBool(AttrList* ad, ExprTree *tree)
{
	EvalResult result;

    // Evaluate constraint with ad in the target scope so that constraints
    // have the same semantics as the collector queries.  --RR
    if (!tree->EvalTree(NULL, ad, &result)) {
        // dprintf(D_ALWAYS, "can't evaluate constraint: %s\n", constraint);
        delete tree;
        return false;
    }

    if (result.type == LX_INTEGER) {
        return (bool)result.i;
    }

    return false;
}

<commit_msg>Upgraded condor_history to use new ClassAds style parsing and replaces all occurrences of AttrLists with ClassAds<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"
#include "condor_distribution.h"

#include "MyString.h"

//------------------------------------------------------------------------

static void displayJobShort(ClassAd* ad);
static void short_header(void);
static void short_print(int,int,const char*,int,int,int,int,int,int,const char *);
static void short_header (void);
static void shorten (char *, int);
static char* format_date( time_t date );
static char* format_time( int tot_secs );
static char encode_status( int status );
static bool EvalBool(ClassAd *ad, ExprTree *tree);

//------------------------------------------------------------------------

static void Usage(char* name)
{
  printf("Usage: %s [-l] [-f history-filename] [-constraint expr | cluster_id | cluster_id.proc_id | owner]\n",name);
  exit(1);
}

//------------------------------------------------------------------------

main(int argc, char* argv[])
{
  char* JobHistoryFileName=NULL;
  int LongFormat=FALSE;
  char* constraint=NULL;
  ExprTree *constraintExpr=NULL;
  int cluster, proc;
  char tmp[512];
  int i;
  myDistro->Init( argc, argv );

  for(i=1; i<argc; i++) {
    if (strcmp(argv[i],"-l")==0) {
      LongFormat=TRUE;
    }
    else if (strcmp(argv[i],"-f")==0) {
      if (i+1==argc || JobHistoryFileName) break;
      i++;
	  JobHistoryFileName=argv[i];
    }
    else if (strcmp(argv[i],"-help")==0) {
	  Usage(argv[0]);
    }
    else if (strcmp(argv[i],"-constraint")==0) {
      if (i+1==argc || constraint) break;
      sprintf(tmp,"(%s)",argv[i+1]);
      constraint=tmp;
      i++;
    }
    else if (sscanf (argv[i], "%d.%d", &cluster, &proc) == 2) {
      if (constraint) break;
      sprintf (tmp, "((%s == %d) && (%s == %d))",
               ATTR_CLUSTER_ID, cluster,ATTR_PROC_ID, proc);
      constraint=tmp;
    }
    else if (sscanf (argv[i], "%d", &cluster) == 1) {
      if (constraint) break;
      sprintf (tmp, "(%s == %d)", ATTR_CLUSTER_ID, cluster);
      constraint=tmp;
    }
    else {
      if (constraint) break;
      sprintf(tmp, "(%s == \"%s\")", ATTR_OWNER, argv[i]);
      constraint=tmp;
    }
  }
  if (i<argc) Usage(argv[0]);

if (constraint) puts(constraint);

  config();
  if (!JobHistoryFileName) {
    JobHistoryFileName=param("HISTORY");
  }

  FILE* LogFile=fopen(JobHistoryFileName,"r");
  if (!LogFile) {
    fprintf(stderr,"History file not found or empty.\n");
    exit(1);
  }

  // printf("HistroyFile=%s\nLongFormat=%d\n",JobHistoryFileName,LongFormat);
  // if (constraint) printf("constraint=%s\n",constraint);

  ClassAdParser parser;	// NAC
  if( constraint && parser.ParseExpression( constraint, constraintExpr )){//NAC
	  fprintf( stderr, "Error:  could not parse constraint %s\n", constraint );
     exit( 1 );
  }

  int EndFlag=0;
  int ErrorFlag=0;
  int EmptyFlag=0;
  ClassAd *ad=0;
  if (!LongFormat) short_header();
  while(!EndFlag) {
    if( !( ad=new ClassAd(LogFile,"***", EndFlag, ErrorFlag, EmptyFlag) ) ){
      fprintf( stderr, "Error:  Out of memory\n" );
      exit( 1 );
    }
    if( ErrorFlag ) {
      printf( "\t*** Warning: Bad history file; skipping malformed ad(s)\n" );
      ErrorFlag=0;
      delete ad;
      continue;
    }
	if( EmptyFlag ) {
      EmptyFlag=0;
      delete ad;
      continue;
    }
    if (!constraint || EvalBool(ad, constraintExpr)) {
      if (LongFormat) {
	    ad->fPrint(stdout); printf("\n");
	  } else {
        displayJobShort(ad);
	  }
    }
    delete ad;
  }

  fclose(LogFile);
  exit(0);
}

//------------------------------------------------------------------------

static void
displayJobShort(ClassAd* ad)
{
        int cluster, proc, date, status, prio, image_size, CompDate;
        float utime;
        char owner[64], cmd[2048], args[2048];

	if(!ad->EvalFloat(ATTR_JOB_REMOTE_WALL_CLOCK,NULL,utime)) {
		if(!ad->EvalFloat(ATTR_JOB_REMOTE_USER_CPU,NULL,utime)) {
			utime = 0;
		}
	}

        if (!ad->EvalInteger (ATTR_CLUSTER_ID, NULL, cluster)           ||
                !ad->EvalInteger (ATTR_PROC_ID, NULL, proc)             ||
                !ad->EvalInteger (ATTR_Q_DATE, NULL, date)              ||
                !ad->EvalInteger (ATTR_COMPLETION_DATE, NULL, CompDate)	||
                !ad->EvalInteger (ATTR_JOB_STATUS, NULL, status)        ||
                !ad->EvalInteger (ATTR_JOB_PRIO, NULL, prio)            ||
                !ad->EvalInteger (ATTR_IMAGE_SIZE, NULL, image_size)    ||
                !ad->EvalString  (ATTR_OWNER, NULL, owner)              ||
                !ad->EvalString  (ATTR_JOB_CMD, NULL, cmd) )
        {
                printf (" --- ???? --- \n");
                return;
        }

        shorten (owner, 14);
        if (ad->EvalString ("Args", NULL, args)) strcat (cmd, args);
        shorten (cmd, 15);
        short_print (cluster, proc, owner, date, CompDate, (int)utime, status,
               prio, image_size, cmd);

}

//------------------------------------------------------------------------

static void
short_header (void)
{
    printf( " %-7s %-14s %11s %12s %-2s %11s %-15s\n",
        "ID",
        "OWNER",
        "SUBMITTED",
        "RUN_TIME",
        "ST",
		"COMPLETED",
        "CMD"
    );
}

//------------------------------------------------------------------------

static void
shorten (char *buff, int len)
{
    if ((unsigned int)strlen (buff) > (unsigned int)len) buff[len] = '\0';
}

//------------------------------------------------------------------------

/*
  Print a line of data for the "short" display of a PROC structure.  The
  "short" display is the one used by "condor_q".  N.B. the columns used
  by this routine must match those defined by the short_header routine
  defined above.
*/

static void
short_print(
        int cluster,
        int proc,
        const char *owner,
        int date,
		int CompDate,
        int time,
        int status,
        int prio,
        int image_size,
        const char *cmd
        ) {
		MyString SubmitDateStr=format_date(date);
		MyString CompDateStr=format_date(CompDate);
        printf( "%4d.%-3d %-14s %-11s %-12s %-2c %-11s %-15s\n",
                cluster,
                proc,
                owner,
                SubmitDateStr.Value(),
                format_time(time),
                encode_status(status),
                CompDateStr.Value(),
                cmd
        );
}

//------------------------------------------------------------------------

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/

static char* format_date( time_t date )
{
        static char     buf[ 12 ];
        struct tm       *tm;

		if (date==0) return " ??? ";

        tm = localtime( &date );
        sprintf( buf, "%2d/%-2d %02d:%02d",
                (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
        );
        return buf;
}

//------------------------------------------------------------------------

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/

static char     *
format_time( int tot_secs )
{
        int             days;
        int             hours;
        int             min;
        int             secs;
        static char     answer[25];

		if ( tot_secs < 0 ) {
			sprintf(answer,"[?????]");
			return answer;
		}

        days = tot_secs / DAY;
        tot_secs %= DAY;
        hours = tot_secs / HOUR;
        tot_secs %= HOUR;
        min = tot_secs / MINUTE;
        secs = tot_secs % MINUTE;

        (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
        return answer;
}

//------------------------------------------------------------------------

/*
  Encode a status from a PROC structure as a single letter suited for
  printing.
*/

static char
encode_status( int status )
{
        switch( status ) {
          case UNEXPANDED:
                return 'U';
          case IDLE:
                return 'I';
          case RUNNING:
                return 'R';
          case COMPLETED:
                return 'C';
          case REMOVED:
                return 'X';
          default:
                return ' ';
        }
}

//------------------------------------------------------------------------

static bool EvalBool(ClassAd* ad, ExprTree *tree)	// NAC
{
	Value result;
	bool boolValue;
	if( !ad->EvaluateExpr( tree, result ) ) {
		delete tree;
		return false;
	}
	if( result.IsBooleanValue( boolValue ) ) {
		return boolValue;
	}

	return false;
}
<|endoftext|>