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

#include "SceneGraph.h"
#include "sg/volume/Volume.h"
#include "sg/volume/AMRVolume.h"
// hdf
#include "ospcommon/box.h"
#include "ospcommon/array3D/Range.h"

#include "hdf5.h"

namespace ospray {

using namespace ospcommon;
using namespace sg;

using std::endl;
using std::cout;

using ospcommon::vec3f;
using ospcommon::box3f;
using ospcommon::vec3i;
using ospcommon::box3i;

//! namespace amr declares various functions for loading AMR data
namespace amr
{

//! stores AMR Level data
struct Level {
  Level(int levelID) : levelID(levelID) {};

  int levelID;
  // apparently, the refinement factor of this level
  double dt;
  /*! the 'outputGhost' variable, specifying the number of ghost cells on all sides */
  vec3i numGhostCells;

  inline vec3i boxSize(const int boxID) const
  { return boxes[boxID].size()+vec3i(1); }

  inline double getValue(int boxID,
                         int compID,
                         const vec3i &coordNoGhost)
  {
    assert(compID >= 0);
    const vec3i sizeNoGhosts = boxSize(boxID);
    const vec3i sizeWithGhosts = sizeNoGhosts + 2 * numGhostCells;
    size_t brickOfs = offsets[boxID] + compID *
                    (size_t)sizeWithGhosts.x*
                    (size_t)sizeWithGhosts.y*
                    (size_t)sizeWithGhosts.z;
    const vec3i coordWithGhosts = coordNoGhost+numGhostCells;
    return data[brickOfs
                    +coordWithGhosts.x
                    +sizeWithGhosts.x*(coordWithGhosts.y+
                    sizeWithGhosts.y*coordWithGhosts.z)];
  }

  std::vector<box3i>   boxes;
  std::vector<int64_t> offsets;
  std::vector<double>  data;

  box3f getWorldBounds(const int boxID) const;
  box3f getWorldBounds() const;
};

//! struct AMR used for storing intermediate AMR representation for
//!   file loading
struct AMR {
  std::vector<Level *>     level;
  //! array of component names
  std::vector<std::string> component;

  static AMR *parse(const std::string &fileName, int maxLevel=1<<30);
  box3f getWorldBounds() const;
};

//! parses out level data from hdf5 files
void parseBoxes(hid_t file, Level *level)
{
  herr_t status;
  char dataName[1000];
  sprintf(dataName,"level_%i/boxes",level->levelID);
  hid_t data = H5Dopen(file,dataName,H5P_DEFAULT);
  if (data < 0)
    throw std::runtime_error("does not exist");
  hid_t space = H5Dget_space(data);
  const size_t nDims = H5Sget_simple_extent_ndims(space);
  hsize_t dims[nDims];
  H5Sget_simple_extent_dims(space,dims,NULL);
  size_t numBoxes = dims[0];

  // create compound data type for a box
  hid_t boxType = H5Tcreate (H5T_COMPOUND, sizeof (box3i));
  status = H5Tinsert (boxType, "lo_i", HOFFSET (box3i, lower.x), H5T_NATIVE_INT);
  status = H5Tinsert (boxType, "lo_j", HOFFSET (box3i, lower.y), H5T_NATIVE_INT);
  status = H5Tinsert (boxType, "lo_k", HOFFSET (box3i, lower.z), H5T_NATIVE_INT);
  status = H5Tinsert (boxType, "hi_i", HOFFSET (box3i, upper.x), H5T_NATIVE_INT);
  status = H5Tinsert (boxType, "hi_j", HOFFSET (box3i, upper.y), H5T_NATIVE_INT);
  status = H5Tinsert (boxType, "hi_k", HOFFSET (box3i, upper.z), H5T_NATIVE_INT);

  level->boxes.resize(numBoxes);
  H5Dread(data,boxType,H5S_ALL,H5S_ALL,H5P_DEFAULT,&level->boxes[0]);
  H5Dclose(data);
}

//! parses out refinement levels for amr data
void parseOffsets(hid_t file, Level *level)
{
  herr_t status;
  char dataName[1000];
  sprintf(dataName,"level_%i/data:offsets=0",level->levelID);
  hid_t data = H5Dopen(file,dataName,H5P_DEFAULT);
  if (data < 0)
    throw std::runtime_error("does not exist");
  hid_t space = H5Dget_space(data);
  const size_t nDims = H5Sget_simple_extent_ndims(space);
  hsize_t dims[nDims];
  H5Sget_simple_extent_dims(space,dims,NULL);
  size_t numOffsets = dims[0];

  level->offsets.resize(numOffsets);
  H5Dread(data,H5T_NATIVE_INT64,H5S_ALL,H5S_ALL,H5P_DEFAULT,&level->offsets[0]);
  H5Dclose(data);
}

//! parse scalar data from hdf5 file
void parseData(hid_t file,
               Level *level)
{
  herr_t status;
  char dataName[1000];
  sprintf(dataName,"level_%i/data:datatype=0",level->levelID);
  hid_t data = H5Dopen(file,dataName,H5P_DEFAULT);
  hid_t space = H5Dget_space(data);
  const size_t nDims = H5Sget_simple_extent_ndims(space);
  hsize_t dims[nDims];
  H5Sget_simple_extent_dims(space,dims,NULL);
  size_t numData = dims[0];

  level->data.resize(numData);
  H5Dread(data,H5T_NATIVE_DOUBLE,H5S_ALL,H5S_ALL,H5P_DEFAULT,&level->data[0]);

  H5Dclose(data);
}

//! parse attributes in hdf5 amr data
void parseDataAttributes(hid_t file,
                         Level *level,
                         const std::string &levelName)
{
  const std::string dataAttrName = "/"+levelName+"/"+"data_attributes";
  hid_t attr_ghost = H5Aopen_by_name(file, dataAttrName.c_str(),"outputGhost",
                                     H5P_DEFAULT,H5P_DEFAULT);
  size_t ghostSize = H5Aget_storage_size(attr_ghost);
  hid_t ghostType = H5Aget_type(attr_ghost);
  assert(ghostSize == sizeof(vec3i));
  H5Aread(attr_ghost, ghostType, &level->numGhostCells);
  H5Aclose(attr_ghost);
}

//! parse individual level in amr data
void parseLevel(hid_t file, Level *level)
{
  char levelName[1000];
  sprintf(levelName,"level_%i",level->levelID);
  hid_t attr_dt = H5Aopen_by_name(file, levelName, "dx", H5P_DEFAULT,H5P_DEFAULT);
  H5Aread(attr_dt, H5T_NATIVE_DOUBLE, &level->dt);
  H5Aclose(attr_dt);

  parseDataAttributes(file, level, levelName);
  parseBoxes(file, level);
  parseData(file, level);
  parseOffsets(file, level);

  ospLogF(1) << "read input level #" << level->levelID << ", cellWidth is " << level->dt << endl;
}

//! parse hdf5 file
AMR *AMR::parse(const std::string &fileName, int maxLevel)
{
  AMR *cd = new AMR;
  char *maxLevelEnv = getenv("AMR_MAX_LEVEL");
  if (maxLevelEnv) {
    maxLevel = atoi(maxLevelEnv);
  } else {
  }
  hid_t file = H5Fopen(fileName.c_str(),H5F_ACC_RDONLY,H5P_DEFAULT);
  if (!file)
    throw std::runtime_error("could not open AMR HDF file '"+fileName+"'");

  // read components ...
  int numComponents = -1;
  {
    hid_t attr_num_components
                    = H5Aopen_by_name(file, "/", "num_components", H5P_DEFAULT,H5P_DEFAULT);
    H5Aread(attr_num_components, H5T_NATIVE_INT, &numComponents);
    H5Aclose(attr_num_components);
  }
  if (numComponents < 1)
    throw std::runtime_error("could not parse num components");
  for (ssize_t i=0;i<numComponents;i++) {
    char compName[10000];
    sprintf(compName,"component_%li",i);

    hid_t att = H5Aopen_name(file, compName);
    hid_t ftype = H5Aget_type(att);
    hid_t type_class = H5Tget_class (ftype);
    assert (type_class == H5T_STRING);

    size_t len = H5Tget_size(ftype);
    char comp[len+1];
    comp[len] = 0;

    hid_t type = H5Tget_native_type(ftype, H5T_DIR_ASCEND);
    H5Aread(att, type, comp);
    H5Aclose(att);

    cd->component.push_back(comp);
  }

  unsigned long long numObjectsInFile;
  H5Gget_num_objs(file, &numObjectsInFile);

  for (ssize_t objID=0;objID<numObjectsInFile;objID++) {
    const int MAX_NAME_SIZE=1000;
    char name[MAX_NAME_SIZE];
    ssize_t res = H5Gget_objname_by_idx(file, objID, name, MAX_NAME_SIZE);

    if (objID == 0) {
      if (strcmp(name,"Chombo_global"))
      {
        std::cout << name << std::endl;
        throw std::runtime_error("missing 'Chombo_global' object - apparently this is not a chombo file!?");
      }
      continue;
    }
    int levelID;
    int rc = sscanf(name,"level_%d",&levelID);
    if (rc == 1) {
      if (levelID > maxLevel) {
        ospLogF(1)  << "#osp:amr: skipping amr level #" << levelID << " as instructed by amr_MAX_LEVEL envvar" << endl;
        continue;
      }

      Level *level = new Level(levelID);
      parseLevel(file, level);
      cd->level.push_back(level);
      continue;
    }
    ospLogF(1)  << "#osp:qtv:amr: unknown HDF5 block '" << name << "'" << endl;
  }

  H5Fclose(file);
  return cd;
}

//! get bounds for leaf level
box3f Level::getWorldBounds(const int boxID) const
{
  return box3f(float(dt)*vec3f(boxes[boxID].lower),
               float(dt)*vec3f(boxes[boxID].upper+vec3i(1)));
}

//! get bounds for a level
box3f Level::getWorldBounds() const
{
  box3f bounds = getWorldBounds(0);
  for (int i=1;i<boxes.size();i++)
    bounds.extend(getWorldBounds(i));
  return bounds;
}

//! get bounds of enditre amr struct
box3f AMR::getWorldBounds() const
{
  box3f bounds = empty;
  for (int i=0;i<level.size();i++)
    bounds.extend(level[i]->getWorldBounds());
  return bounds;
}

}
namespace sg {

//! parse Chombo hdf5 file into world node
void importAMRChombo(std::shared_ptr<sg::Node> &world, const FileName &fileName,
                  const std::string &desiredComponent,
                  const Range<float> *clampRange)
{
  auto node = sg::createNode("amr", "AMRVolume")->nodeAs<sg::AMRVolume>();
  parseAMRChomboFile(node,fileName,desiredComponent, clampRange);
  world->add(node);
}

//! parse Chombo hdf5 file into AMRVolume node
void parseAMRChomboFile(std::shared_ptr<sg::AMRVolume> &node, const FileName &fileName,
                  const std::string &desiredComponent,
                  const Range<float> *clampRange, int maxLevel)
{
  amr::AMR *amr = ospray::amr::AMR::parse(fileName.str(), maxLevel);
  assert(!amr->level.empty());

  box3i rootLevelBounds = empty;
  for (int i=0;i<amr->level[0]->boxes.size();i++)
    rootLevelBounds.extend(amr->level[0]->boxes[i]);
  assert(rootLevelBounds.lower == vec3i(0));

  node->child("bounds") = amr->getWorldBounds();

  node->componentID = -1;
  for (int i=0;i<amr->component.size();i++)
  {
    if (amr->component[i] == desiredComponent) {
      node->componentID = i;
    }
  }
  if (node->componentID < 0) {
    if (desiredComponent == "") {
      ospLogF(1) << "no component specified - defaulting to component 0" << endl;
      node->componentID = 0;
    } else
      throw std::runtime_error("could not find desird component '"+desiredComponent+"'");
  }

  for (int levelID=0;levelID<amr->level.size();levelID++) {
    amr::Level *level = amr->level[levelID];
    ospLogF(1) << " - level: " << levelID << " : " << level->boxes.size() << " boxes" << endl;
    for (int brickID=0;brickID<level->boxes.size();brickID++) {
      AMRVolume::BrickInfo bi;
      bi.box = level->boxes[brickID];
      bi.dt = level->dt;
      bi.level = levelID;

      node->brickInfo.push_back(bi);

      size_t numValues = bi.size().product();
      float *f = new float[numValues];
      node->brickPtrs.push_back(f);
      for (int iz=0;iz<bi.size().z;iz++)
        for (int iy=0;iy<bi.size().y;iy++)
          for (int ix=0;ix<bi.size().x;ix++) {
            vec3i coord(ix,iy,iz);
            double v = level->getValue(brickID,node->componentID,coord);
            if (clampRange) v = clampRange->clamp(v);
            node->valueRange.extend(v);
            *f++ = v;
          }
    }
    level->data.clear();
  }
  ospLogF(1) << "found " << node->brickInfo.size() << " bricks" << endl;
}

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

#include "SceneGraph.h"
#include "sg/volume/AMRVolume.h"
#include "sg/volume/Volume.h"
// hdf
#include "ospcommon/array3D/Range.h"
#include "ospcommon/box.h"

#include "hdf5.h"

namespace ospray {

  using namespace ospcommon;
  using namespace sg;

  using std::endl;
  using std::cout;

  using ospcommon::vec3f;
  using ospcommon::box3f;
  using ospcommon::vec3i;
  using ospcommon::box3i;

  //! namespace amr declares various functions for loading AMR data
  namespace amr {

    //! stores AMR Level data
    struct Level
    {
      Level(int levelID) : levelID(levelID){};

      int levelID;
      // apparently, the refinement factor of this level
      double dt;
      /*! the 'outputGhost' variable, specifying the number of ghost cells on
       * all sides */
      vec3i numGhostCells;

      inline vec3i boxSize(const int boxID) const
      {
        return boxes[boxID].size() + vec3i(1);
      }

      inline double getValue(int boxID, int compID, const vec3i &coordNoGhost)
      {
        assert(compID >= 0);
        const vec3i sizeNoGhosts   = boxSize(boxID);
        const vec3i sizeWithGhosts = sizeNoGhosts + 2 * numGhostCells;
        size_t brickOfs            = offsets[boxID] +
                          compID * (size_t)sizeWithGhosts.x *
                              (size_t)sizeWithGhosts.y *
                              (size_t)sizeWithGhosts.z;
        const vec3i coordWithGhosts = coordNoGhost + numGhostCells;
        return data[brickOfs + coordWithGhosts.x +
                    sizeWithGhosts.x * (coordWithGhosts.y +
                                        sizeWithGhosts.y * coordWithGhosts.z)];
      }

      std::vector<box3i> boxes;
      std::vector<int64_t> offsets;
      std::vector<double> data;

      box3f getWorldBounds(const int boxID) const;
      box3f getWorldBounds() const;
    };

    //! struct AMR used for storing intermediate AMR representation for
    //!   file loading
    struct AMR
    {
      std::vector<Level *> level;
      //! array of component names
      std::vector<std::string> component;

      static AMR *parse(const std::string &fileName, int maxLevel = 1 << 30);
      box3f getWorldBounds() const;
    };

    //! parses out level data from hdf5 files
    void parseBoxes(hid_t file, Level *level)
    {
      herr_t status;
      char dataName[1000];
      sprintf(dataName, "level_%i/boxes", level->levelID);
      hid_t data = H5Dopen(file, dataName, H5P_DEFAULT);
      if (data < 0)
        throw std::runtime_error("does not exist");
      hid_t space        = H5Dget_space(data);
      const size_t nDims = H5Sget_simple_extent_ndims(space);
      hsize_t dims[nDims];
      H5Sget_simple_extent_dims(space, dims, NULL);
      size_t numBoxes = dims[0];

      // create compound data type for a box
      hid_t boxType = H5Tcreate(H5T_COMPOUND, sizeof(box3i));
      status =
          H5Tinsert(boxType, "lo_i", HOFFSET(box3i, lower.x), H5T_NATIVE_INT);
      status =
          H5Tinsert(boxType, "lo_j", HOFFSET(box3i, lower.y), H5T_NATIVE_INT);
      status =
          H5Tinsert(boxType, "lo_k", HOFFSET(box3i, lower.z), H5T_NATIVE_INT);
      status =
          H5Tinsert(boxType, "hi_i", HOFFSET(box3i, upper.x), H5T_NATIVE_INT);
      status =
          H5Tinsert(boxType, "hi_j", HOFFSET(box3i, upper.y), H5T_NATIVE_INT);
      status =
          H5Tinsert(boxType, "hi_k", HOFFSET(box3i, upper.z), H5T_NATIVE_INT);

      level->boxes.resize(numBoxes);
      H5Dread(data, boxType, H5S_ALL, H5S_ALL, H5P_DEFAULT, &level->boxes[0]);
      H5Dclose(data);
    }

    //! parses out refinement levels for amr data
    void parseOffsets(hid_t file, Level *level)
    {
      herr_t status;
      char dataName[1000];
      sprintf(dataName, "level_%i/data:offsets=0", level->levelID);
      hid_t data = H5Dopen(file, dataName, H5P_DEFAULT);
      if (data < 0)
        throw std::runtime_error("does not exist");
      hid_t space        = H5Dget_space(data);
      const size_t nDims = H5Sget_simple_extent_ndims(space);
      hsize_t dims[nDims];
      H5Sget_simple_extent_dims(space, dims, NULL);
      size_t numOffsets = dims[0];

      level->offsets.resize(numOffsets);
      H5Dread(data,
              H5T_NATIVE_INT64,
              H5S_ALL,
              H5S_ALL,
              H5P_DEFAULT,
              &level->offsets[0]);
      H5Dclose(data);
    }

    //! parse scalar data from hdf5 file
    void parseData(hid_t file, Level *level)
    {
      herr_t status;
      char dataName[1000];
      sprintf(dataName, "level_%i/data:datatype=0", level->levelID);
      hid_t data         = H5Dopen(file, dataName, H5P_DEFAULT);
      hid_t space        = H5Dget_space(data);
      const size_t nDims = H5Sget_simple_extent_ndims(space);
      hsize_t dims[nDims];
      H5Sget_simple_extent_dims(space, dims, NULL);
      size_t numData = dims[0];

      level->data.resize(numData);
      H5Dread(data,
              H5T_NATIVE_DOUBLE,
              H5S_ALL,
              H5S_ALL,
              H5P_DEFAULT,
              &level->data[0]);

      H5Dclose(data);
    }

    //! parse attributes in hdf5 amr data
    void parseDataAttributes(hid_t file,
                             Level *level,
                             const std::string &levelName)
    {
      const std::string dataAttrName =
          "/" + levelName + "/" + "data_attributes";
      hid_t attr_ghost = H5Aopen_by_name(
          file, dataAttrName.c_str(), "outputGhost", H5P_DEFAULT, H5P_DEFAULT);
      size_t ghostSize = H5Aget_storage_size(attr_ghost);
      hid_t ghostType  = H5Aget_type(attr_ghost);
      assert(ghostSize == sizeof(vec3i));
      H5Aread(attr_ghost, ghostType, &level->numGhostCells);
      H5Aclose(attr_ghost);
    }

    //! parse individual level in amr data
    void parseLevel(hid_t file, Level *level)
    {
      char levelName[1000];
      sprintf(levelName, "level_%i", level->levelID);
      hid_t attr_dt =
          H5Aopen_by_name(file, levelName, "dx", H5P_DEFAULT, H5P_DEFAULT);
      H5Aread(attr_dt, H5T_NATIVE_DOUBLE, &level->dt);
      H5Aclose(attr_dt);

      parseDataAttributes(file, level, levelName);
      parseBoxes(file, level);
      parseData(file, level);
      parseOffsets(file, level);

      ospLogF(1) << "read input level #" << level->levelID << ", cellWidth is "
                 << level->dt << endl;
    }

    //! parse hdf5 file
    AMR *AMR::parse(const std::string &fileName, int maxLevel)
    {
      AMR *cd           = new AMR;
      char *maxLevelEnv = getenv("AMR_MAX_LEVEL");
      if (maxLevelEnv) {
        maxLevel = atoi(maxLevelEnv);
      } else {
      }
      hid_t file = H5Fopen(fileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
      if (!file)
        throw std::runtime_error("could not open AMR HDF file '" + fileName +
                                 "'");

      // read components ...
      int numComponents = -1;
      {
        hid_t attr_num_components = H5Aopen_by_name(
            file, "/", "num_components", H5P_DEFAULT, H5P_DEFAULT);
        H5Aread(attr_num_components, H5T_NATIVE_INT, &numComponents);
        H5Aclose(attr_num_components);
      }
      if (numComponents < 1)
        throw std::runtime_error("could not parse num components");
      for (ssize_t i = 0; i < numComponents; i++) {
        char compName[10000];
        sprintf(compName, "component_%li", i);

        hid_t att        = H5Aopen_name(file, compName);
        hid_t ftype      = H5Aget_type(att);
        hid_t type_class = H5Tget_class(ftype);
        assert(type_class == H5T_STRING);

        size_t len = H5Tget_size(ftype);
        char comp[len + 1];
        comp[len] = 0;

        hid_t type = H5Tget_native_type(ftype, H5T_DIR_ASCEND);
        H5Aread(att, type, comp);
        H5Aclose(att);

        cd->component.push_back(comp);
      }

      unsigned long long numObjectsInFile;
      H5Gget_num_objs(file, &numObjectsInFile);

      for (ssize_t objID = 0; objID < numObjectsInFile; objID++) {
        const int MAX_NAME_SIZE = 1000;
        char name[MAX_NAME_SIZE];
        ssize_t res = H5Gget_objname_by_idx(file, objID, name, MAX_NAME_SIZE);

        if (objID == 0) {
          if (strcmp(name, "Chombo_global")) {
            std::cout << name << std::endl;
            throw std::runtime_error(
                "missing 'Chombo_global' object - apparently this is not a "
                "chombo file!?");
          }
          continue;
        }
        int levelID;
        int rc = sscanf(name, "level_%d", &levelID);
        if (rc == 1) {
          if (levelID > maxLevel) {
            ospLogF(1) << "#osp:amr: skipping amr level #" << levelID
                       << " as instructed by amr_MAX_LEVEL envvar" << endl;
            continue;
          }

          Level *level = new Level(levelID);
          parseLevel(file, level);
          cd->level.push_back(level);
          continue;
        }
        ospLogF(1) << "#osp:qtv:amr: unknown HDF5 block '" << name << "'"
                   << endl;
      }

      H5Fclose(file);
      return cd;
    }

    //! get bounds for leaf level
    box3f Level::getWorldBounds(const int boxID) const
    {
      return box3f(float(dt) * vec3f(boxes[boxID].lower),
                   float(dt) * vec3f(boxes[boxID].upper + vec3i(1)));
    }

    //! get bounds for a level
    box3f Level::getWorldBounds() const
    {
      box3f bounds = getWorldBounds(0);
      for (int i = 1; i < boxes.size(); i++)
        bounds.extend(getWorldBounds(i));
      return bounds;
    }

    //! get bounds of enditre amr struct
    box3f AMR::getWorldBounds() const
    {
      box3f bounds = empty;
      for (int i = 0; i < level.size(); i++)
        bounds.extend(level[i]->getWorldBounds());
      return bounds;
    }
  }
  namespace sg {

    //! parse Chombo hdf5 file into world node
    void importAMRChombo(std::shared_ptr<sg::Node> &world,
                         const FileName &fileName,
                         const std::string &desiredComponent,
                         const Range<float> *clampRange)
    {
      auto node = sg::createNode("amr", "AMRVolume")->nodeAs<sg::AMRVolume>();
      parseAMRChomboFile(node, fileName, desiredComponent, clampRange);
      world->add(node);
    }

    //! parse Chombo hdf5 file into AMRVolume node
    void parseAMRChomboFile(std::shared_ptr<sg::AMRVolume> &node,
                            const FileName &fileName,
                            const std::string &desiredComponent,
                            const Range<float> *clampRange,
                            int maxLevel)
    {
      amr::AMR *amr = ospray::amr::AMR::parse(fileName.str(), maxLevel);
      assert(!amr->level.empty());

      box3i rootLevelBounds = empty;
      for (int i = 0; i < amr->level[0]->boxes.size(); i++)
        rootLevelBounds.extend(amr->level[0]->boxes[i]);
      assert(rootLevelBounds.lower == vec3i(0));

      node->child("bounds") = amr->getWorldBounds();

      node->componentID = -1;
      for (int i = 0; i < amr->component.size(); i++) {
        if (amr->component[i] == desiredComponent) {
          node->componentID = i;
        }
      }
      if (node->componentID < 0) {
        if (desiredComponent == "") {
          ospLogF(1) << "no component specified - defaulting to component 0"
                     << endl;
          node->componentID = 0;
        } else
          throw std::runtime_error("could not find desird component '" +
                                   desiredComponent + "'");
      }

      for (int levelID = 0; levelID < amr->level.size(); levelID++) {
        amr::Level *level = amr->level[levelID];
        ospLogF(1) << " - level: " << levelID << " : " << level->boxes.size()
                   << " boxes" << endl;
        for (int brickID = 0; brickID < level->boxes.size(); brickID++) {
          AMRVolume::BrickInfo bi;
          bi.box   = level->boxes[brickID];
          bi.dt    = level->dt;
          bi.level = levelID;

          node->brickInfo.push_back(bi);

          size_t numValues = bi.size().product();
          float *f         = new float[numValues];
          node->brickPtrs.push_back(f);
          for (int iz = 0; iz < bi.size().z; iz++)
            for (int iy = 0; iy < bi.size().y; iy++)
              for (int ix = 0; ix < bi.size().x; ix++) {
                vec3i coord(ix, iy, iz);
                double v = level->getValue(brickID, node->componentID, coord);
                if (clampRange)
                  v = clampRange->clamp(v);
                node->valueRange.extend(v);
                *f++ = v;
              }
        }
        level->data.clear();
      }
      ospLogF(1) << "found " << node->brickInfo.size() << " bricks" << endl;
    }
  }
}
<|endoftext|>


<commit_before>#include "TriacDimmer.h"
#include <Arduino.h>
#include <assert.h>

volatile uint16_t TriacDimmer::detail::pulse_length;
volatile uint16_t TriacDimmer::detail::period = 16667;
volatile uint16_t TriacDimmer::detail::ch_A_up;
volatile uint16_t TriacDimmer::detail::ch_A_dn;
volatile uint16_t TriacDimmer::detail::ch_B_up;
volatile uint16_t TriacDimmer::detail::ch_B_dn;

void TriacDimmer::begin(uint16_t pulse_length, uint16_t min_trigger){
	TriacDimmer::detail::pulse_length = pulse_length;
	TriacDimmer::detail::min_trigger = min_trigger;

	TCCR1A = 0;
	TCCR1B = _BV(ICNC1)  //input capture noise cancel
			| _BV(ICES1) //positive edge
			| _BV(CS11); // /8 prescaler

	pinMode(8, INPUT);
	pinMode(9, OUTPUT);
	pinMode(10, OUTPUT);

	TIFR1 = _BV(ICF1); //clear IC interrupt flag
	TIMSK1 = _BV(ICIE1); //enable input capture interrupt
}

void TriacDimmer::end(){
	TIMSK1 = 0; //disable the interrupts first!
	TIFR1 = 0xFF; //clear all flags
	TCCR1A = 0; //clear to reset state
	TCCR1B = 0;
}

void TriacDimmer::setBrightness(uint8_t pin, float value){
	assert(pin == 9 || pin == 10);

	if ((pin & 0x01) == 0x01){ // if (pin == 9){
		TriacDimmer::detail::setChannelA(1 - value);
	} else { // if (pin == 10){
		TriacDimmer::detail::setChannelB(1 - value);
	}
}

float TriacDimmer::getCurrentBrightness(uint8_t pin){
	assert(pin == 9 || pin == 10);

	if ((pin & 0x01) == 0x01){ // if (pin == 9){
		return 1 - TriacDimmer::detail::getChannelA();
	} else { // if (pin == 10){
		return 1 - TriacDimmer::detail::getChannelB();
	}
}

void TriacDimmer::detail::setChannelA(float value){
	TriacDimmer::detail::ch_A_up = TriacDimmer::detail::period * value;
	TriacDimmer::detail::ch_A_dn = constrain(TriacDimmer::detail::ch_A_up + TriacDimmer::detail::pulse_length,
		TriacDimmer::detail::min_trigger, TriacDimmer::detail::period);
}
void TriacDimmer::detail::setChannelB(float value){
	TriacDimmer::detail::ch_B_up = TriacDimmer::detail::period * value;
	TriacDimmer::detail::ch_B_dn = constrain(TriacDimmer::detail::ch_B_up + TriacDimmer::detail::pulse_length,
		TriacDimmer::detail::min_trigger, TriacDimmer::detail::period);
}
float TriacDimmer::detail::getChannelA(){
	return (float)TriacDimmer::detail::ch_A_up / TriacDimmer::detail::period;
}
float TriacDimmer::detail::getChannelB(){
	return (float)TriacDimmer::detail::ch_B_up / TriacDimmer::detail::period;
}

ISR(TIMER1_CAPT_vect){
	TIMSK1 &=~ (_BV(OCIE1A) | _BV(OCIE1B)); //clear interrupts, in case they haven't run yet
	TCCR1A &=~ (_BV(COM1A0) | _BV(COM1B0));
	TCCR1C = _BV(FOC1A) | _BV(FOC1B); //ensure outputs are properly cleared

	OCR1A = ICR1 + TriacDimmer::detail::ch_A_up;
	OCR1B = ICR1 + TriacDimmer::detail::ch_B_up;

	TCCR1A |= _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1); //set OC1x on compare match
	TIFR1 = _BV(OCF1A) | _BV(OCF1B); //clear compare match flags
	TIMSK1 |= _BV(OCIE1A) | _BV(OCIE1B); //enable input capture and compare match interrupts

	static uint16_t last_icr = 0;
	TriacDimmer::detail::period = ICR1 - last_icr;
	last_icr = ICR1;

	if((signed)(TCNT1 - OCR1A) >= 0){
		TCCR1C = _BV(FOC1A); //interrupt ran late, trigger match manually
	}
	if((signed)(TCNT1 - OCR1B) >= 0){
		TCCR1C = _BV(FOC1B); //interrupt ran late, trigger match manually
	}
}

ISR(TIMER1_COMPA_vect){
	TIMSK1 &=~ _BV(OCIE1A); //disable match interrupt
	TCCR1A &=~ _BV(COM1A0); //clear OC1x on compare match

	OCR1A = ICR1 + TriacDimmer::detail::ch_A_dn;

	if((signed)(TCNT1 - OCR1A) >= 0){
		TCCR1C = _BV(FOC1A); //interrupt ran late, trigger match manually
	}
}

ISR(TIMER1_COMPB_vect){
	TIMSK1 &=~ _BV(OCIE1B); //disable match interrupt
	TCCR1A &=~ _BV(COM1B0); //clear OC1x on compare match

	OCR1B = ICR1 + TriacDimmer::detail::ch_B_dn;

	if((signed)(TCNT1 - OCR1B) >= 0){
		TCCR1C = _BV(FOC1B); //interrupt ran late, trigger match manually
	}
}

<commit_msg>added variable for min_trigger<commit_after>#include "TriacDimmer.h"
#include <Arduino.h>
#include <assert.h>

volatile uint16_t TriacDimmer::detail::pulse_length;
volatile uint16_t TriacDimmer::detail::min_trigger;
volatile uint16_t TriacDimmer::detail::period = 16667;
volatile uint16_t TriacDimmer::detail::ch_A_up;
volatile uint16_t TriacDimmer::detail::ch_A_dn;
volatile uint16_t TriacDimmer::detail::ch_B_up;
volatile uint16_t TriacDimmer::detail::ch_B_dn;

void TriacDimmer::begin(uint16_t pulse_length, uint16_t min_trigger){
	TriacDimmer::detail::pulse_length = pulse_length;
	TriacDimmer::detail::min_trigger = min_trigger;

	TCCR1A = 0;
	TCCR1B = _BV(ICNC1)  //input capture noise cancel
			| _BV(ICES1) //positive edge
			| _BV(CS11); // /8 prescaler

	pinMode(8, INPUT);
	pinMode(9, OUTPUT);
	pinMode(10, OUTPUT);

	TIFR1 = _BV(ICF1); //clear IC interrupt flag
	TIMSK1 = _BV(ICIE1); //enable input capture interrupt
}

void TriacDimmer::end(){
	TIMSK1 = 0; //disable the interrupts first!
	TIFR1 = 0xFF; //clear all flags
	TCCR1A = 0; //clear to reset state
	TCCR1B = 0;
}

void TriacDimmer::setBrightness(uint8_t pin, float value){
	assert(pin == 9 || pin == 10);

	if ((pin & 0x01) == 0x01){ // if (pin == 9){
		TriacDimmer::detail::setChannelA(1 - value);
	} else { // if (pin == 10){
		TriacDimmer::detail::setChannelB(1 - value);
	}
}

float TriacDimmer::getCurrentBrightness(uint8_t pin){
	assert(pin == 9 || pin == 10);

	if ((pin & 0x01) == 0x01){ // if (pin == 9){
		return 1 - TriacDimmer::detail::getChannelA();
	} else { // if (pin == 10){
		return 1 - TriacDimmer::detail::getChannelB();
	}
}

void TriacDimmer::detail::setChannelA(float value){
	TriacDimmer::detail::ch_A_up = TriacDimmer::detail::period * value;
	TriacDimmer::detail::ch_A_dn = constrain(TriacDimmer::detail::ch_A_up + TriacDimmer::detail::pulse_length,
		TriacDimmer::detail::min_trigger, TriacDimmer::detail::period);
}
void TriacDimmer::detail::setChannelB(float value){
	TriacDimmer::detail::ch_B_up = TriacDimmer::detail::period * value;
	TriacDimmer::detail::ch_B_dn = constrain(TriacDimmer::detail::ch_B_up + TriacDimmer::detail::pulse_length,
		TriacDimmer::detail::min_trigger, TriacDimmer::detail::period);
}
float TriacDimmer::detail::getChannelA(){
	return (float)TriacDimmer::detail::ch_A_up / TriacDimmer::detail::period;
}
float TriacDimmer::detail::getChannelB(){
	return (float)TriacDimmer::detail::ch_B_up / TriacDimmer::detail::period;
}

ISR(TIMER1_CAPT_vect){
	TIMSK1 &=~ (_BV(OCIE1A) | _BV(OCIE1B)); //clear interrupts, in case they haven't run yet
	TCCR1A &=~ (_BV(COM1A0) | _BV(COM1B0));
	TCCR1C = _BV(FOC1A) | _BV(FOC1B); //ensure outputs are properly cleared

	OCR1A = ICR1 + TriacDimmer::detail::ch_A_up;
	OCR1B = ICR1 + TriacDimmer::detail::ch_B_up;

	TCCR1A |= _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1); //set OC1x on compare match
	TIFR1 = _BV(OCF1A) | _BV(OCF1B); //clear compare match flags
	TIMSK1 |= _BV(OCIE1A) | _BV(OCIE1B); //enable input capture and compare match interrupts

	static uint16_t last_icr = 0;
	TriacDimmer::detail::period = ICR1 - last_icr;
	last_icr = ICR1;

	if((signed)(TCNT1 - OCR1A) >= 0){
		TCCR1C = _BV(FOC1A); //interrupt ran late, trigger match manually
	}
	if((signed)(TCNT1 - OCR1B) >= 0){
		TCCR1C = _BV(FOC1B); //interrupt ran late, trigger match manually
	}
}

ISR(TIMER1_COMPA_vect){
	TIMSK1 &=~ _BV(OCIE1A); //disable match interrupt
	TCCR1A &=~ _BV(COM1A0); //clear OC1x on compare match

	OCR1A = ICR1 + TriacDimmer::detail::ch_A_dn;

	if((signed)(TCNT1 - OCR1A) >= 0){
		TCCR1C = _BV(FOC1A); //interrupt ran late, trigger match manually
	}
}

ISR(TIMER1_COMPB_vect){
	TIMSK1 &=~ _BV(OCIE1B); //disable match interrupt
	TCCR1A &=~ _BV(COM1B0); //clear OC1x on compare match

	OCR1B = ICR1 + TriacDimmer::detail::ch_B_dn;

	if((signed)(TCNT1 - OCR1B) >= 0){
		TCCR1C = _BV(FOC1B); //interrupt ran late, trigger match manually
	}
}

<|endoftext|>


<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    uiserver/decryptemailcommand.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra 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
    General Public License for more details.

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

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "decryptcommand.h"
#include "assuancommandprivatebase_p.h"
#include "kleo-assuan.h"

#include <QObject>
#include <QIODevice>
#include <QHash>
#include <QMap>
#include <QStringList>
#include <QDebug>
#include <QMessageBox>
#include <QFile>

#include <kleo/decryptjob.h>
#include <utils/stl_util.h>

#include <klocale.h>

#include <gpgme++/error.h>
#include <gpgme++/decryptionresult.h>

#include <gpg-error.h>

#include <boost/bind.hpp>

#include <cassert>

using namespace Kleo;

class DecryptCommand::Private;

class DecryptionResultCollector : public QObject
{
    Q_OBJECT
public:
    explicit DecryptionResultCollector( DecryptCommand::Private* parent = 0 );

    struct Result {
        Result() : error(0) { }
        int id;
        GpgME::DecryptionResult result;
        QByteArray stuff;
        int error;
        QString errorString;
        bool isError() const { return error || result.error(); }
    };

    void registerJob( int id, DecryptJob* job );
Q_SIGNALS:
    void finished( const QMap<int, DecryptionResultCollector::Result> & );

private Q_SLOTS:
    void slotDecryptResult(const GpgME::DecryptionResult &, const QByteArray &);

private:
    QMap<int, Result> m_results;
    QHash<QObject*, int> m_senderToId;
    int m_unfinished;
    DecryptCommand::Private* m_command;
    int m_statusSent;
};

class DecryptCommand::Private
  : public AssuanCommandPrivateBaseMixin<DecryptCommand::Private, DecryptCommand>
{
    Q_OBJECT
public:
    Private( DecryptCommand * qq )
        :AssuanCommandPrivateBaseMixin<DecryptCommand::Private, DecryptCommand>()
        , q( qq )
        , collector( new DecryptionResultCollector(this) )
    {}

    DecryptCommand *q;
    QList<Input> analyzeInput( GpgME::Error& error, QString& errorDetails ) const;
    int startDecryption();
    void tryDecryptResult(const GpgME::DecryptionResult &, const QByteArray &, int );
    void trySendingStatus( const QString & str );

public Q_SLOTS:
    void slotDecryptionCollectionResult( const QMap<int, DecryptionResultCollector::Result>& );
    void slotProgress( const QString& what, int current, int total );
private:
    DecryptionResultCollector* collector;

};

static QString resultToString( const GpgME::DecryptionResult & result )
{
    QString resStr( "OK ");
    for ( unsigned int i = 0; i<result.numRecipients(); i++ ) {
        const GpgME::DecryptionResult::Recipient r = result.recipient( i );
        resStr += i18n( " encrypted to " ) + QString( r.keyID() );
    }
    return resStr;
}

DecryptionResultCollector::DecryptionResultCollector( DecryptCommand::Private * parent )
: QObject( parent ), m_command( parent ), m_unfinished( 0 ), m_statusSent( 0 )
{
}

void DecryptionResultCollector::registerJob( int id, DecryptJob* job )
{
    connect( job, SIGNAL( result( GpgME::DecryptionResult,QByteArray ) ),
             this, SLOT( slotDecryptResult( GpgME::DecryptionResult, QByteArray ) ) );
    m_senderToId[job] = id;
    ++m_unfinished;
}

void DecryptionResultCollector::slotDecryptResult(const GpgME::DecryptionResult & result,
                                                  const QByteArray & stuff )
{
    assert( m_senderToId.contains( sender( ) ) );
    const int id = m_senderToId[sender()];

    Result res;
    res.id = id;
    res.stuff = stuff;
    res.result = result;
    m_results[id] = res;

    // send status for all results received so far, but in order of id
    // report status on the command line immediately, and write out results, but
     // only show dialog once all operations are completed, so it can be aggregated
    while ( m_results.contains( m_statusSent ) ) {
        Result result = m_results[m_statusSent];
        QString resultString;
        try {
            m_command->tryDecryptResult( result.result, result.stuff, m_statusSent );
            resultString = resultToString( result.result );
        } catch ( const assuan_exception& e ) {
            result.error = e.error_code();
            result.errorString = e.what();
            m_results[m_statusSent] = result;
            resultString = "ERR " + res.errorString;
            // FIXME ask to continue or cancel
        }
        m_command->trySendingStatus( resultString );
        m_statusSent++;
    }

    --m_unfinished;
    assert( m_unfinished >= 0 );
    if ( m_unfinished == 0 ) {
        emit finished( m_results );
    }
}

DecryptCommand::DecryptCommand()
    : AssuanCommandMixin<DecryptCommand>(),
      d( new Private( this ) )
{
}

DecryptCommand::~DecryptCommand() {}

QList<AssuanCommandPrivateBase::Input> DecryptCommand::Private::analyzeInput( GpgME::Error& error, QString& errorDetails ) const
{
    error = GpgME::Error();
    errorDetails = QString();

    const int numInputs = q->numBulkInputDevices( "INPUT" );
    const int numOutputs = q->numBulkInputDevices( "OUTPUT" );
    const int numMessages = q->numBulkInputDevices( "MESSAGE" );

    if ( numMessages != 0 )
    {
        error = GpgME::Error( GPG_ERR_ASS_NO_INPUT ); //TODO use better error code if possible
        errorDetails = "Only --input can be provided to the decrypt command, no --message";
        return QList<Input>();
    }

    // either the output is discarded, or there ar as many as inputs
    if ( numOutputs > 0 && numInputs != numOutputs )
    {
        error = GpgME::Error( GPG_ERR_ASS_NO_INPUT ); //TODO use better error code if possible
        errorDetails = "For each --input there needs to be an --output";
        return QList<Input>();
    }

    QList<Input> inputs;

    for ( int i = 0; i < numInputs; ++i )
    {
        Input input;
        input.message = q->bulkInputDevice( "INPUT", i );
        input.messageFileName = q->bulkInputDeviceFileName( "INPUT", i );
        assert( input.message );
        input.type = Input::Opaque; // by definition
        inputs.append( input );
    }

    return inputs;
}

void DecryptCommand::Private::trySendingStatus( const QString & str )
{
    if ( const int err = q->sendStatus( "DECRYPT", str ) ) {
        QString errorString = i18n("Problem writing out decryption status.");
        q->done( err, errorString ) ;
    }
}

void DecryptCommand::Private::slotProgress( const QString& what, int current, int total )
{
    // FIXME report progress, via sendStatus()
}

void DecryptCommand::Private::tryDecryptResult(const GpgME::DecryptionResult & result,
                                               const QByteArray & stuff, int id )
{
    assert( id!= -1 );

    const GpgME::Error decryptionError = result.error();
    if ( decryptionError )
        throw assuan_exception( decryptionError, "Decryption failed: " );

    writeToOutputDeviceOrAskForFileName( id, stuff, result.fileName() );
}

void DecryptCommand::Private::slotDecryptionCollectionResult( const QMap<int, DecryptionResultCollector::Result>& results )
{
    assert( !results.isEmpty() );

    std::vector<DecryptionResultCollector::Result> theGood;
    std::vector<DecryptionResultCollector::Result> theBad;

    kdtools::copy_if( results.begin(), results.end(),
                      std::back_inserter( theBad ),
                      boost::bind( &DecryptionResultCollector::Result::isError, _1 ) );
    kdtools::copy_if( results.begin(), results.end(),
                      std::back_inserter( theGood ),
                      !boost::bind( &DecryptionResultCollector::Result::isError, _1 ) );

    if ( !q->hasOption("silent") ) {
        // FIXME find all errors and all successes and display result dialog, unless --silent
        QMessageBox::information( 0, i18n( "Decryption Result" ), QString("%1 files processed. %2 were ok, %3 failed")
                                 .arg( results.size() ).arg( theGood.size() ).arg( theBad.size() ) );
    }
    if ( !theBad.empty() )
        q->done( makeError( GPG_ERR_DECRYPT_FAILED ) );
    else
        q->done();
}

int DecryptCommand::Private::startDecryption()
{
    assert( !inputList.isEmpty() );
    connect( collector, SIGNAL( finished( QMap<int, DecryptionResultCollector::Result> ) ),
             SLOT( slotDecryptionCollectionResult( QMap<int, DecryptionResultCollector::Result> ) ) );

    try {
        int i = 0;
        Q_FOREACH ( const Private::Input input, inputList )
        {
            assert( input.backend );

            //fire off appropriate kleo decrypt job
            DecryptJob * const job = input.backend->decryptJob();
            assert(job);
            collector->registerJob( i, job );

            // FIXME handle file names
            const QByteArray encrypted = input.message->readAll(); // FIXME safe enough?
            const GpgME::Error error = job->start( encrypted );
            if ( error ) throw error;

            ++i;
        }
    } catch ( const GpgME::Error & error ) {
        q->done( error );
        return error;
    }

    return 0;
}

int DecryptCommand::doStart()
{
    /*
    d->parseCommandLine("");
    d->showDetails = !hasOption("silent");
    */

    GpgME::Error error;
    QString details;
    d->inputList = d->analyzeInput( error, details );
    if ( error ) {
        done( error, details );
        return error;
    }

    int err = d->determineInputsAndProtocols( details );
    if ( err ) {
        done( err, details );
        return err;
    }
    err = d->startDecryption();
    return 0;

}

void DecryptCommand::doCanceled()
{
}

#include "decryptcommand.moc"

<commit_msg>Bring up a dialog for this one as well.<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    uiserver/decryptemailcommand.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra 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
    General Public License for more details.

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

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "decryptcommand.h"
#include "assuancommandprivatebase_p.h"
#include "kleo-assuan.h"
#include "resultdialog.h"

#include <QObject>
#include <QIODevice>
#include <QHash>
#include <QMap>
#include <QStringList>
#include <QDebug>
#include <QMessageBox>
#include <QFile>

#include <kleo/decryptjob.h>
#include <utils/stl_util.h>

#include <klocale.h>

#include <gpgme++/error.h>
#include <gpgme++/decryptionresult.h>

#include <gpg-error.h>

#include <boost/bind.hpp>

#include <cassert>

using namespace Kleo;

class DecryptCommand::Private;

class DecryptionResultCollector : public QObject
{
    Q_OBJECT
public:
    explicit DecryptionResultCollector( DecryptCommand::Private* parent = 0 );

    struct Result {
        Result() : error(0) { }
        int id;
        GpgME::DecryptionResult result;
        QByteArray stuff;
        int error;
        QString errorString;
        bool isError() const { return error || result.error(); }
    };

    void registerJob( int id, DecryptJob* job );
    int unfinishedJobs() const { return m_unfinished; }
Q_SIGNALS:
    void finished( const QMap<int, DecryptionResultCollector::Result> & );
    void showResult( int, const DecryptionResultCollector::Result& );

private Q_SLOTS:
    void slotDecryptResult(const GpgME::DecryptionResult &, const QByteArray &);

private:
    QMap<int, Result> m_results;
    QHash<QObject*, int> m_senderToId;
    int m_unfinished;
    DecryptCommand::Private* m_command;
    int m_statusSent;
};

class DecryptResultDisplayWidget : public QWidget
{
public:
    DecryptResultDisplayWidget( QWidget * parent )
    :QWidget( parent )
    {

    }

    void setResult( const GpgME::DecryptionResult & result )
    {
        // FIXME do something with it
    }
};

class DecryptCommand::Private
  : public AssuanCommandPrivateBaseMixin<DecryptCommand::Private, DecryptCommand>
{
    Q_OBJECT
public:
    Private( DecryptCommand * qq )
        :AssuanCommandPrivateBaseMixin<DecryptCommand::Private, DecryptCommand>()
        , q( qq )
        , collector( new DecryptionResultCollector(this) )
    {}

    DecryptCommand *q;
    QList<Input> analyzeInput( GpgME::Error& error, QString& errorDetails ) const;
    int startDecryption();
    void tryDecryptResult(const GpgME::DecryptionResult &, const QByteArray &, int );
    void trySendingStatus( const QString & str );
    void showDecryptResultDialog();

public Q_SLOTS:
    void slotDecryptionCollectionResult( const QMap<int, DecryptionResultCollector::Result>& );
    void slotProgress( const QString& what, int current, int total );
    void slotDialogClosed();
    void slotShowResult( int, const DecryptionResultCollector::Result& );

private:
    DecryptionResultCollector* collector;
    ResultDialog<DecryptResultDisplayWidget> *dialog;

};

static QString resultToString( const GpgME::DecryptionResult & result )
{
    QString resStr( "OK ");
    for ( unsigned int i = 0; i<result.numRecipients(); i++ ) {
        const GpgME::DecryptionResult::Recipient r = result.recipient( i );
        resStr += i18n( " encrypted to " ) + QString( r.keyID() );
    }
    return resStr;
}

DecryptionResultCollector::DecryptionResultCollector( DecryptCommand::Private * parent )
: QObject( parent ), m_command( parent ), m_unfinished( 0 ), m_statusSent( 0 )
{
}

void DecryptionResultCollector::registerJob( int id, DecryptJob* job )
{
    connect( job, SIGNAL( result( GpgME::DecryptionResult,QByteArray ) ),
             this, SLOT( slotDecryptResult( GpgME::DecryptionResult, QByteArray ) ) );
    m_senderToId[job] = id;
    ++m_unfinished;
}

void DecryptionResultCollector::slotDecryptResult(const GpgME::DecryptionResult & result,
                                                  const QByteArray & stuff )
{
    assert( m_senderToId.contains( sender( ) ) );
    const int id = m_senderToId[sender()];

    Result res;
    res.id = id;
    res.stuff = stuff;
    res.result = result;
    m_results[id] = res;

    // send status for all results received so far, but in order of id
    // report status on the command line immediately, and write out results, but
     // only show dialog once all operations are completed, so it can be aggregated
    while ( m_results.contains( m_statusSent ) ) {
        Result result = m_results[m_statusSent];
        QString resultString;
        try {
            m_command->tryDecryptResult( result.result, result.stuff, m_statusSent );
            resultString = resultToString( result.result );
        } catch ( const assuan_exception& e ) {
            result.error = e.error_code();
            result.errorString = e.what();
            m_results[m_statusSent] = result;
            resultString = "ERR " + res.errorString;
            // FIXME ask to continue or cancel
        }
        emit showResult( m_statusSent, result );
        m_command->trySendingStatus( resultString );
        m_statusSent++;
    }

    --m_unfinished;
    assert( m_unfinished >= 0 );
    if ( m_unfinished == 0 ) {
        emit finished( m_results );
    }
}

DecryptCommand::DecryptCommand()
    : AssuanCommandMixin<DecryptCommand>(),
      d( new Private( this ) )
{
}

DecryptCommand::~DecryptCommand() {}

QList<AssuanCommandPrivateBase::Input> DecryptCommand::Private::analyzeInput( GpgME::Error& error, QString& errorDetails ) const
{
    error = GpgME::Error();
    errorDetails = QString();

    const int numInputs = q->numBulkInputDevices( "INPUT" );
    const int numOutputs = q->numBulkInputDevices( "OUTPUT" );
    const int numMessages = q->numBulkInputDevices( "MESSAGE" );

    if ( numMessages != 0 )
    {
        error = GpgME::Error( GPG_ERR_ASS_NO_INPUT ); //TODO use better error code if possible
        errorDetails = "Only --input can be provided to the decrypt command, no --message";
        return QList<Input>();
    }

    // either the output is discarded, or there ar as many as inputs
    if ( numOutputs > 0 && numInputs != numOutputs )
    {
        error = GpgME::Error( GPG_ERR_ASS_NO_INPUT ); //TODO use better error code if possible
        errorDetails = "For each --input there needs to be an --output";
        return QList<Input>();
    }

    QList<Input> inputs;

    for ( int i = 0; i < numInputs; ++i )
    {
        Input input;
        input.message = q->bulkInputDevice( "INPUT", i );
        input.messageFileName = q->bulkInputDeviceFileName( "INPUT", i );
        assert( input.message );
        input.type = Input::Opaque; // by definition
        inputs.append( input );
    }

    return inputs;
}

void DecryptCommand::Private::trySendingStatus( const QString & str )
{
    if ( const int err = q->sendStatus( "DECRYPT", str ) ) {
        QString errorString = i18n("Problem writing out decryption status.");
        q->done( err, errorString ) ;
    }
}

void DecryptCommand::Private::slotProgress( const QString& what, int current, int total )
{
    // FIXME report progress, via sendStatus()
}

void DecryptCommand::Private::tryDecryptResult(const GpgME::DecryptionResult & result,
                                               const QByteArray & stuff, int id )
{
    assert( id!= -1 );

    const GpgME::Error decryptionError = result.error();
    if ( decryptionError )
        throw assuan_exception( decryptionError, "Decryption failed: " );

    writeToOutputDeviceOrAskForFileName( id, stuff, result.fileName() );
}

void DecryptCommand::Private::slotDecryptionCollectionResult( const QMap<int, DecryptionResultCollector::Result>& results )
{
    assert( !results.isEmpty() );

    std::vector<DecryptionResultCollector::Result> theGood;
    std::vector<DecryptionResultCollector::Result> theBad;

    kdtools::copy_if( results.begin(), results.end(),
                      std::back_inserter( theBad ),
                      boost::bind( &DecryptionResultCollector::Result::isError, _1 ) );
    kdtools::copy_if( results.begin(), results.end(),
                      std::back_inserter( theGood ),
                      !boost::bind( &DecryptionResultCollector::Result::isError, _1 ) );

    if ( !q->hasOption("silent") ) {
        // FIXME find all errors and all successes and display result dialog, unless --silent
        QMessageBox::information( 0, i18n( "Decryption Result" ), QString("%1 files processed. %2 were ok, %3 failed")
                                 .arg( results.size() ).arg( theGood.size() ).arg( theBad.size() ) );
    }
    if ( !theBad.empty() )
        q->done( makeError( GPG_ERR_DECRYPT_FAILED ) );
    else
        q->done();
}

void DecryptCommand::Private::slotDialogClosed()
{
    // FIXME if there was at least one error, and if so declare the whole thing failed.
    q->done();
}

void DecryptCommand::Private::slotShowResult( int id, const DecryptionResultCollector::Result &result )
{
    if ( result.error ) {
         dialog->showError( id, result.errorString );
     } else {
         DecryptResultDisplayWidget * w = dialog->widget( id );
         w->setResult( result.result );
         dialog->showResultWidget( id );
     }
}

void DecryptCommand::Private::showDecryptResultDialog()
{
    dialog = new ResultDialog<DecryptResultDisplayWidget>( 0, collector->unfinishedJobs() ); // fixme opaque parent handle from command line?
    connect( dialog, SIGNAL( accepted() ), this, SLOT( slotDialogClosed() ) );
    connect( dialog, SIGNAL( rejected() ), this, SLOT( slotDialogClosed() ) );
    connect( collector, SIGNAL( showResult( int, DecryptionResultCollector::Result ) ),
             this, SLOT( slotShowResult( int, DecryptionResultCollector::Result ) ) );
    dialog->show();
}

int DecryptCommand::Private::startDecryption()
{
    assert( !inputList.isEmpty() );
    connect( collector, SIGNAL( finished( QMap<int, DecryptionResultCollector::Result> ) ),
             SLOT( slotDecryptionCollectionResult( QMap<int, DecryptionResultCollector::Result> ) ) );

    try {
        int i = 0;
        Q_FOREACH ( const Private::Input input, inputList )
        {
            assert( input.backend );

            //fire off appropriate kleo decrypt job
            DecryptJob * const job = input.backend->decryptJob();
            assert(job);
            collector->registerJob( i, job );

            // FIXME handle file names
            const QByteArray encrypted = input.message->readAll(); // FIXME safe enough?
            const GpgME::Error error = job->start( encrypted );
            if ( error ) throw error;

            ++i;
        }
    } catch ( const GpgME::Error & error ) {
        q->done( error );
        return error;
    }

    return 0;
}

int DecryptCommand::doStart()
{
    GpgME::Error error;
    QString details;
    d->inputList = d->analyzeInput( error, details );
    if ( error ) {
        done( error, details );
        return error;
    }

    int err = d->determineInputsAndProtocols( details );
    if ( err ) {
        done( err, details );
        return err;
    }
    err = d->startDecryption();
    if ( !err && !hasOption( "silent" ) )
        d->showDecryptResultDialog();
    return 0;

}

void DecryptCommand::doCanceled()
{
}

#include "decryptcommand.moc"

<|endoftext|>


<commit_before>#include "UserActions.h"

UserActions::UserActions() : m_mMappings({}) {}

void UserActions::add(std::string name, Command c) {
	if (!m_mMappings.count(name)) {
		std::vector<Command> tempCommands;
		m_mMappings[name] = tempCommands;
	}

	m_mMappings[name].push_back(c);
}

int UserActions::getActionState(std::string name) {
	if (!m_mMappings.count(name)) {
		return 0;
	}

	std::vector<Command> commands = m_mMappings[name];
	int ret = 0;
	InputHandler* handlerInstance = InputHandler::Instance();
	for (unsigned int c = 0; c < commands.size(); c++) {
		switch (commands[c].type) {
			case CONTROLLER_BUTTON:
				ret = !handlerInstance->joysticksInitialised() ? 0 :
					InputHandler::Instance()->getButtonState(0, commands[c].buttonId);
				break;
			case CONTROLLER_STICK:
				ret = !handlerInstance->joysticksInitialised() ? 0 :
					InputHandler::Instance()->stickValue(0, commands[c].stickAxis);
				break;
			case KEYBOARD_KEY:
				break;
		}

		if (ret != 0) {
			break;
		}
	}

	return ret;
}
<commit_msg>already available variable used<commit_after>#include "UserActions.h"

UserActions::UserActions() : m_mMappings({}) {}

void UserActions::add(std::string name, Command c) {
	if (!m_mMappings.count(name)) {
		std::vector<Command> tempCommands;
		m_mMappings[name] = tempCommands;
	}

	m_mMappings[name].push_back(c);
}

int UserActions::getActionState(std::string name) {
	if (!m_mMappings.count(name)) {
		return 0;
	}

	std::vector<Command> commands = m_mMappings[name];
	int ret = 0;
	InputHandler* handlerInstance = InputHandler::Instance();
	for (unsigned int c = 0; c < commands.size(); c++) {
		switch (commands[c].type) {
			case CONTROLLER_BUTTON:
				ret = !handlerInstance->joysticksInitialised() ? 0 :
					handlerInstance->getButtonState(0, commands[c].buttonId);
				break;
			case CONTROLLER_STICK:
				ret = !handlerInstance->joysticksInitialised() ? 0 :
					handlerInstance->stickValue(0, commands[c].stickAxis);
				break;
			case KEYBOARD_KEY:
				break;
		}

		if (ret != 0) {
			break;
		}
	}

	return ret;
}
<|endoftext|>


<commit_before>/*
 * ZED.cpp
 *
 *  Created on: Aug 22, 2015
 *      Author: yankai
 */

#include "../Vision/_ZED.h"

#ifdef USE_ZED

namespace kai
{

_ZED::_ZED()
{
	m_type = zed;
	m_zedResolution = (int) sl::zed::VGA;
	m_zedMinDist = 0.6;
	m_zedMaxDist = 20.0;
	m_pZed = NULL;
	m_zedFPS = DEFAULT_FPS;
	m_zedMode = sl::zed::STANDARD;
	m_zedQuality = sl::zed::PERFORMANCE;
	m_pDepthWin = NULL;
	m_bZedFlip = false;
	m_zedConfidence = 100;
	m_angleH = 66.7;
	m_angleV = 67.1;
	m_zedTrackState = sl::zed::TRACKING_STATE::TRACKING_OFF;
	m_mMotion.setIdentity(4, 4);
	m_trackState = track_idle;
	m_trackConfidence = 0;
	m_vT.init();
	m_vR.init();
	m_tLastTrack = 0;
}

_ZED::~_ZED()
{
	this->_VisionBase::complete();
}

bool _ZED::init(void* pKiss)
{
	IF_F(!_VisionBase::init(pKiss));
	Kiss* pK = (Kiss*) pKiss;
	pK->m_pInst = this;

	string presetDir = "";
	string calibFile;

	F_INFO(pK->root()->o("APP")->v("presetDir", &presetDir));
	F_INFO(pK->v("zedResolution", &m_zedResolution));
	F_INFO(pK->v("zedFPS", &m_zedFPS));
	F_INFO(pK->v("zedQuality", &m_zedQuality));
	F_INFO(pK->v("zedMinDist", &m_zedMinDist));
	F_INFO(pK->v("zedMaxDist", &m_zedMaxDist));
	F_INFO(pK->v("bZedFlip", &m_bZedFlip));
	F_INFO(pK->v("zedConfidence", &m_zedConfidence));

	m_pDepth = new Frame();
	return true;
}

bool _ZED::link(void)
{
	IF_F(!this->_VisionBase::link());
	Kiss* pK = (Kiss*) m_pKiss;

	string iName = "";
	F_INFO(pK->v("depthWindow", &iName));
	m_pDepthWin = (Window*) (pK->root()->getChildInstByName(&iName));

	return true;
}

bool _ZED::open(void)
{
	// Initialize ZED color stream in HD and depth in Performance mode
	m_pZed = new sl::zed::Camera((sl::zed::ZEDResolution_mode) m_zedResolution);

	// define a struct of parameters for the initialization
	sl::zed::InitParams zedParams;
	zedParams.mode = (sl::zed::MODE) m_zedQuality;
	zedParams.unit = sl::zed::UNIT::METER;
	zedParams.verbose = 1;
	zedParams.device = -1;
	zedParams.minimumDistance = m_zedMinDist;
	zedParams.vflip = m_bZedFlip;

	sl::zed::ERRCODE err = m_pZed->init(zedParams);
	if (err != sl::zed::SUCCESS)
	{
		LOG(ERROR)<< "ZED Error code: " << sl::zed::errcode2str(err) << std::endl;
		return false;
	}

	m_pZed->setFPS(m_zedFPS);
	m_pZed->setConfidenceThreshold(m_zedConfidence);
	m_pZed->setDepthClampValue(m_zedMaxDist);
	m_zedMode = sl::zed::STANDARD;

	// Initialize color image and depth
	m_width = m_pZed->getImageSize().width;
	m_height = m_pZed->getImageSize().height;
	m_centerH = m_width / 2;
	m_centerV = m_height / 2;

	startTracking();

	m_bOpen = true;
	return true;
}

bool _ZED::start(void)
{
	m_bThreadON = true;
	int retCode = pthread_create(&m_threadID, 0, getUpdateThread, this);
	if (retCode != 0)
	{
		m_bThreadON = false;
		return false;
	}

	return true;
}

void _ZED::update(void)
{
	while (m_bThreadON)
	{
		if (!m_bOpen)
		{
			if (!open())
			{
				LOG_E("Cannot open ZED");
				this->sleepTime(USEC_1SEC);
				continue;
			}
		}

		this->autoFPSfrom();

		GpuMat gImg;
		GpuMat gImg2;
		GpuMat gDepth;
		GpuMat gDepth2;

		GpuMat* pSrc;
		GpuMat* pDest;
		GpuMat* pSrcD;
		GpuMat* pDestD;
		GpuMat* pTmp;

		// Grab frame and compute depth in FULL sensing mode
		if (!m_pZed->grab(m_zedMode, 1, 1, 1))
		{
			sl::zed::Mat zLeft = m_pZed->retrieveImage_gpu(sl::zed::SIDE::LEFT);
			gImg = GpuMat(Size(zLeft.width, zLeft.height), CV_8UC4, zLeft.data);

			sl::zed::Mat zDepth = m_pZed->normalizeMeasure_gpu(
					sl::zed::MEASURE::DEPTH, m_zedMinDist, m_zedMaxDist);
			gDepth = GpuMat(Size(zDepth.width, zDepth.height), CV_8UC4,
					zDepth.data);

#ifndef USE_OPENCV4TEGRA
			cuda::cvtColor(gImg, gImg2, CV_BGRA2BGR);
			cuda::cvtColor(gDepth, gDepth2, CV_BGRA2GRAY);
#else
			gpu::cvtColor(gImg, gImg2, CV_BGRA2BGR);
			gpu::cvtColor(gDepth, gDepth2, CV_BGRA2GRAY);
#endif
			pSrc = &gImg2;
			pDest = &gImg;
			pSrcD = &gDepth2;
			pDestD = &gDepth;

			if (m_bFlip)
			{
#ifndef USE_OPENCV4TEGRA
				cuda::flip(*pSrc, *pDest, -1);
				cuda::flip(*pSrcD, *pDestD, -1);
#else
				gpu::flip(*pSrc,*pDest,-1);
				gpu::flip(*pSrcD,*pDestD,-1);
#endif
				SWAP(pSrc, pDest, pTmp);
				SWAP(pSrcD, pDestD, pTmp);
			}

			m_pBGR->update(pSrc);
			if (m_pGray)
				m_pGray->getGrayOf(m_pBGR);
			if (m_pHSV)
				m_pHSV->getHSVOf(m_pBGR);

			m_pDepth->update(pSrcD);

			Eigen::Matrix4f m;
			switch (m_trackState)
			{
			case tracking:
				m_zedTrackState = m_pZed->getPosition(m,
						sl::zed::MAT_TRACKING_TYPE::POSE);
				if (m_zedTrackState == sl::zed::TRACKING_STATE::TRACKING_GOOD)
				{
					m_mMotion *= m;
					m_trackConfidence = m_pZed->getTrackingConfidence();
				}
				else if (m_zedTrackState
						== sl::zed::TRACKING_STATE::TRACKING_LOST)
				{
					m_pZed->stopTracking();
					zedTrackReset();
				}
				break;
			case track_start:
				zedTrackReset();
				break;
			case track_stop:
				m_pZed->stopTracking();
				m_trackState = track_idle;
				break;
			}

		}

		this->autoFPSto();
	}
}

void _ZED::startTracking(void)
{
	m_trackState = track_start;
}

void _ZED::stopTracking(void)
{
	m_trackState = track_stop;
}

bool _ZED::isTracking(void)
{
	IF_T(m_trackState == tracking);
	IF_T(m_trackState == track_start);

	return false;
}

void _ZED::zedTrackReset(void)
{
	m_mMotion.setIdentity(4, 4);
	if (m_pZed->enableTracking(m_mMotion, false))
		m_trackState = tracking;
}

int _ZED::getMotionDelta(vDouble3* pT, vDouble3* pR, uint64_t* pDT)
{
	if (m_trackState != tracking)
	{
		return -1;
	}

	m_vT.x = (double) m_mMotion(0, 3);  //Side
	m_vT.y = (double) m_mMotion(1, 3);  //Alt
	m_vT.z = (double) m_mMotion(2, 3);  //Heading
	*pT = m_vT;

	Eigen::Matrix3f mRot = m_mMotion.block(0,0,3,3);
    Eigen::Quaternionf q(mRot);
    float3 euler = eulerAngles(q.x(),q.y(),q.z(),q.w());
    m_vR.x = (double)euler.x;
    m_vR.y = (double)euler.y;
    m_vR.z = (double)euler.z;
    if(m_vR.z > 0)
    	m_vR.z -= M_PI;
    else
    	m_vR.z += M_PI;

    if(abs(m_vT.x + m_vT.y + m_vT.z + m_vR.x + m_vR.y + m_vR.z) < 1.0e-7)
    {
    	return -1;
    }

   	*pR = m_vR;

   	uint64_t t = get_time_usec();
   	*pDT = t - m_tLastTrack;
   	m_tLastTrack = t;

//	Eigen::Matrix3f mRot = m_mMotion.block(0, 0, 3, 3);
//	mRot.normalize();
//	Eigen::Vector3f euler = mRot.eulerAngles(0,1,2);
//	m_vR.m_x = (double) euler(0);
//	m_vR.m_y = (double) euler(1);
//	m_vR.m_z = (double) euler(2);
//	*pR = m_vR;

	m_mMotion.setIdentity(4, 4);
	return m_trackConfidence;
}

void _ZED::setAttitude(vDouble3* pYPR)
{
	NULL_(pYPR);
	IF_(m_trackState != tracking);

	Eigen::AngleAxisf y(pYPR->x, Eigen::Vector3f::UnitY());
	Eigen::AngleAxisf p(pYPR->y, Eigen::Vector3f::UnitX());
	Eigen::AngleAxisf r(pYPR->z, Eigen::Vector3f::UnitZ());

	Eigen::Quaternion<float> q = y * p * r;
	Eigen::Matrix3f mRot = q.matrix();

	m_pZed->setTrackingPrior(mRot);
}

void _ZED::getRange(double* pMin, double* pMax)
{
	NULL_(pMin);
	NULL_(pMax);

	*pMin = m_zedMinDist;
	*pMax = m_zedMaxDist;
}

double _ZED::dist(Rect* pR)
{
	NULL_F(pR);

	GpuMat gMat;
	GpuMat gMat2;
	GpuMat gHist;
	Mat cHist;

	NULL_F(m_pDepth);
	IF_F(m_pDepth->empty());
	gMat = *(m_pDepth->getGMat());
	gMat2 = GpuMat(gMat, *pR);

	int intensity = 0;
	int minPix = pR->area() * 0.5;

#ifndef USE_OPENCV4TEGRA
	cuda::calcHist(gMat2, gHist);
	gHist.download(cHist);

	for (int i = cHist.cols - 1; i > 0; i--)
	{
		intensity += cHist.at<int>(0, i);
		if (intensity > minPix)
		{
			return (255.0f - i) / 255.0f;
		}
	}
#else
	int channels[] =
	{	0};
	int bin_num = 256;
	int bin_nums[] =
	{	bin_num};
	float range[] =
	{	0, 256};
	const float *ranges[] =
	{	range};
	Mat cMat;
	gMat2.download(cMat);
	cv::calcHist(&cMat, 1, channels, cv::Mat(), cHist, 1, bin_nums, ranges);

	for (int i = cHist.rows-1; i > 0; i--)
	{
		intensity += cHist.at<int>(i, 0);
		if(intensity > minPix)
		{
			return (255.0f - i)/255.0f;
		}
	}
#endif

	return -1.0;
}

bool _ZED::draw(void)
{
	Window* pWin;
	Frame* pFrame;

	if (this->BASE::draw())
	{
		IF_F(m_pBGR->empty());
		pWin = (Window*) this->m_pWindow;
		pFrame = pWin->getFrame();
		pFrame->update(m_pBGR);
		this->_VisionBase::draw();

		string msg;
		pWin->tabNext();

		msg = "Tracking confidence: " + i2str(m_trackConfidence);
		pWin->addMsg(&msg);

		msg = "Translation: X=" + f2str(m_vT.x) + ", Y=" + f2str(m_vT.y)
				+ ", Z=" + f2str(m_vT.z);
		pWin->addMsg(&msg);

		msg = "Rotation: Yaw=" + f2str(m_vR.x) + ", Pitch=" + f2str(m_vR.y)
				+ ", Roll=" + f2str(m_vR.z);
		pWin->addMsg(&msg);

		pWin->tabPrev();
	}

	if (m_pDepthWin)
	{
		pFrame = m_pDepthWin->getFrame();
		if (pFrame && !m_pDepth->empty())
		{
			pFrame->update(m_pDepth);
		}
	}

	return true;
}

}

#endif
<commit_msg>Fixed ZED pos delta initial dT<commit_after>/*
 * ZED.cpp
 *
 *  Created on: Aug 22, 2015
 *      Author: yankai
 */

#include "../Vision/_ZED.h"

#ifdef USE_ZED

namespace kai
{

_ZED::_ZED()
{
	m_type = zed;
	m_zedResolution = (int) sl::zed::VGA;
	m_zedMinDist = 0.6;
	m_zedMaxDist = 20.0;
	m_pZed = NULL;
	m_zedFPS = DEFAULT_FPS;
	m_zedMode = sl::zed::STANDARD;
	m_zedQuality = sl::zed::PERFORMANCE;
	m_pDepthWin = NULL;
	m_bZedFlip = false;
	m_zedConfidence = 100;
	m_angleH = 66.7;
	m_angleV = 67.1;
	m_zedTrackState = sl::zed::TRACKING_STATE::TRACKING_OFF;
	m_mMotion.setIdentity(4, 4);
	m_trackState = track_idle;
	m_trackConfidence = 0;
	m_vT.init();
	m_vR.init();
	m_tLastTrack = 0;
}

_ZED::~_ZED()
{
	this->_VisionBase::complete();
}

bool _ZED::init(void* pKiss)
{
	IF_F(!_VisionBase::init(pKiss));
	Kiss* pK = (Kiss*) pKiss;
	pK->m_pInst = this;

	string presetDir = "";
	string calibFile;

	F_INFO(pK->root()->o("APP")->v("presetDir", &presetDir));
	F_INFO(pK->v("zedResolution", &m_zedResolution));
	F_INFO(pK->v("zedFPS", &m_zedFPS));
	F_INFO(pK->v("zedQuality", &m_zedQuality));
	F_INFO(pK->v("zedMinDist", &m_zedMinDist));
	F_INFO(pK->v("zedMaxDist", &m_zedMaxDist));
	F_INFO(pK->v("bZedFlip", &m_bZedFlip));
	F_INFO(pK->v("zedConfidence", &m_zedConfidence));

	m_pDepth = new Frame();
	return true;
}

bool _ZED::link(void)
{
	IF_F(!this->_VisionBase::link());
	Kiss* pK = (Kiss*) m_pKiss;

	string iName = "";
	F_INFO(pK->v("depthWindow", &iName));
	m_pDepthWin = (Window*) (pK->root()->getChildInstByName(&iName));

	return true;
}

bool _ZED::open(void)
{
	// Initialize ZED color stream in HD and depth in Performance mode
	m_pZed = new sl::zed::Camera((sl::zed::ZEDResolution_mode) m_zedResolution);

	// define a struct of parameters for the initialization
	sl::zed::InitParams zedParams;
	zedParams.mode = (sl::zed::MODE) m_zedQuality;
	zedParams.unit = sl::zed::UNIT::METER;
	zedParams.verbose = 1;
	zedParams.device = -1;
	zedParams.minimumDistance = m_zedMinDist;
	zedParams.vflip = m_bZedFlip;

	sl::zed::ERRCODE err = m_pZed->init(zedParams);
	if (err != sl::zed::SUCCESS)
	{
		LOG(ERROR)<< "ZED Error code: " << sl::zed::errcode2str(err) << std::endl;
		return false;
	}

	m_pZed->setFPS(m_zedFPS);
	m_pZed->setConfidenceThreshold(m_zedConfidence);
	m_pZed->setDepthClampValue(m_zedMaxDist);
	m_zedMode = sl::zed::STANDARD;

	// Initialize color image and depth
	m_width = m_pZed->getImageSize().width;
	m_height = m_pZed->getImageSize().height;
	m_centerH = m_width / 2;
	m_centerV = m_height / 2;

	startTracking();

	m_bOpen = true;
	return true;
}

bool _ZED::start(void)
{
	m_bThreadON = true;
	int retCode = pthread_create(&m_threadID, 0, getUpdateThread, this);
	if (retCode != 0)
	{
		m_bThreadON = false;
		return false;
	}

	return true;
}

void _ZED::update(void)
{
	while (m_bThreadON)
	{
		if (!m_bOpen)
		{
			if (!open())
			{
				LOG_E("Cannot open ZED");
				this->sleepTime(USEC_1SEC);
				continue;
			}
		}

		this->autoFPSfrom();

		GpuMat gImg;
		GpuMat gImg2;
		GpuMat gDepth;
		GpuMat gDepth2;

		GpuMat* pSrc;
		GpuMat* pDest;
		GpuMat* pSrcD;
		GpuMat* pDestD;
		GpuMat* pTmp;

		// Grab frame and compute depth in FULL sensing mode
		if (!m_pZed->grab(m_zedMode, 1, 1, 1))
		{
			sl::zed::Mat zLeft = m_pZed->retrieveImage_gpu(sl::zed::SIDE::LEFT);
			gImg = GpuMat(Size(zLeft.width, zLeft.height), CV_8UC4, zLeft.data);

			sl::zed::Mat zDepth = m_pZed->normalizeMeasure_gpu(
					sl::zed::MEASURE::DEPTH, m_zedMinDist, m_zedMaxDist);
			gDepth = GpuMat(Size(zDepth.width, zDepth.height), CV_8UC4,
					zDepth.data);

#ifndef USE_OPENCV4TEGRA
			cuda::cvtColor(gImg, gImg2, CV_BGRA2BGR);
			cuda::cvtColor(gDepth, gDepth2, CV_BGRA2GRAY);
#else
			gpu::cvtColor(gImg, gImg2, CV_BGRA2BGR);
			gpu::cvtColor(gDepth, gDepth2, CV_BGRA2GRAY);
#endif
			pSrc = &gImg2;
			pDest = &gImg;
			pSrcD = &gDepth2;
			pDestD = &gDepth;

			if (m_bFlip)
			{
#ifndef USE_OPENCV4TEGRA
				cuda::flip(*pSrc, *pDest, -1);
				cuda::flip(*pSrcD, *pDestD, -1);
#else
				gpu::flip(*pSrc,*pDest,-1);
				gpu::flip(*pSrcD,*pDestD,-1);
#endif
				SWAP(pSrc, pDest, pTmp);
				SWAP(pSrcD, pDestD, pTmp);
			}

			m_pBGR->update(pSrc);
			if (m_pGray)
				m_pGray->getGrayOf(m_pBGR);
			if (m_pHSV)
				m_pHSV->getHSVOf(m_pBGR);

			m_pDepth->update(pSrcD);

			Eigen::Matrix4f m;
			switch (m_trackState)
			{
			case tracking:
				m_zedTrackState = m_pZed->getPosition(m,
						sl::zed::MAT_TRACKING_TYPE::POSE);
				if (m_zedTrackState == sl::zed::TRACKING_STATE::TRACKING_GOOD)
				{
					m_mMotion *= m;
					m_trackConfidence = m_pZed->getTrackingConfidence();
				}
				else if (m_zedTrackState
						== sl::zed::TRACKING_STATE::TRACKING_LOST)
				{
					m_pZed->stopTracking();
					zedTrackReset();
				}
				break;
			case track_start:
				zedTrackReset();
				break;
			case track_stop:
				m_pZed->stopTracking();
				m_trackState = track_idle;
				break;
			}

		}

		this->autoFPSto();
	}
}

void _ZED::startTracking(void)
{
	m_trackState = track_start;
}

void _ZED::stopTracking(void)
{
	m_trackState = track_stop;
}

bool _ZED::isTracking(void)
{
	IF_T(m_trackState == tracking);
	IF_T(m_trackState == track_start);

	return false;
}

void _ZED::zedTrackReset(void)
{
	m_mMotion.setIdentity(4, 4);
	if (m_pZed->enableTracking(m_mMotion, false))
		m_trackState = tracking;
}

int _ZED::getMotionDelta(vDouble3* pT, vDouble3* pR, uint64_t* pDT)
{
	if (m_trackState != tracking)
	{
		return -1;
	}

	m_vT.x = (double) m_mMotion(0, 3);  //Side
	m_vT.y = (double) m_mMotion(1, 3);  //Alt
	m_vT.z = (double) m_mMotion(2, 3);  //Heading
	*pT = m_vT;

	Eigen::Matrix3f mRot = m_mMotion.block(0,0,3,3);
    Eigen::Quaternionf q(mRot);
    float3 euler = eulerAngles(q.x(),q.y(),q.z(),q.w());
    m_vR.x = (double)euler.x;
    m_vR.y = (double)euler.y;
    m_vR.z = (double)euler.z;
    if(m_vR.z > 0)
    	m_vR.z -= M_PI;
    else
    	m_vR.z += M_PI;

    if(abs(m_vT.x + m_vT.y + m_vT.z + m_vR.x + m_vR.y + m_vR.z) < 1.0e-7)
    {
    	return -1;
    }

   	*pR = m_vR;

   	uint64_t t = get_time_usec();
   	if(m_tLastTrack == 0)
   	{
   	   	m_tLastTrack = t;
   	   	return -1;
   	}

   	*pDT = t - m_tLastTrack;
   	m_tLastTrack = t;

//	Eigen::Matrix3f mRot = m_mMotion.block(0, 0, 3, 3);
//	mRot.normalize();
//	Eigen::Vector3f euler = mRot.eulerAngles(0,1,2);
//	m_vR.m_x = (double) euler(0);
//	m_vR.m_y = (double) euler(1);
//	m_vR.m_z = (double) euler(2);
//	*pR = m_vR;

	m_mMotion.setIdentity(4, 4);
	return m_trackConfidence;
}

void _ZED::setAttitude(vDouble3* pYPR)
{
	NULL_(pYPR);
	IF_(m_trackState != tracking);

	Eigen::AngleAxisf y(pYPR->x, Eigen::Vector3f::UnitY());
	Eigen::AngleAxisf p(pYPR->y, Eigen::Vector3f::UnitX());
	Eigen::AngleAxisf r(pYPR->z, Eigen::Vector3f::UnitZ());

	Eigen::Quaternion<float> q = y * p * r;
	Eigen::Matrix3f mRot = q.matrix();

	m_pZed->setTrackingPrior(mRot);
}

void _ZED::getRange(double* pMin, double* pMax)
{
	NULL_(pMin);
	NULL_(pMax);

	*pMin = m_zedMinDist;
	*pMax = m_zedMaxDist;
}

double _ZED::dist(Rect* pR)
{
	NULL_F(pR);

	GpuMat gMat;
	GpuMat gMat2;
	GpuMat gHist;
	Mat cHist;

	NULL_F(m_pDepth);
	IF_F(m_pDepth->empty());
	gMat = *(m_pDepth->getGMat());
	gMat2 = GpuMat(gMat, *pR);

	int intensity = 0;
	int minPix = pR->area() * 0.5;

#ifndef USE_OPENCV4TEGRA
	cuda::calcHist(gMat2, gHist);
	gHist.download(cHist);

	for (int i = cHist.cols - 1; i > 0; i--)
	{
		intensity += cHist.at<int>(0, i);
		if (intensity > minPix)
		{
			return (255.0f - i) / 255.0f;
		}
	}
#else
	int channels[] =
	{	0};
	int bin_num = 256;
	int bin_nums[] =
	{	bin_num};
	float range[] =
	{	0, 256};
	const float *ranges[] =
	{	range};
	Mat cMat;
	gMat2.download(cMat);
	cv::calcHist(&cMat, 1, channels, cv::Mat(), cHist, 1, bin_nums, ranges);

	for (int i = cHist.rows-1; i > 0; i--)
	{
		intensity += cHist.at<int>(i, 0);
		if(intensity > minPix)
		{
			return (255.0f - i)/255.0f;
		}
	}
#endif

	return -1.0;
}

bool _ZED::draw(void)
{
	Window* pWin;
	Frame* pFrame;

	if (this->BASE::draw())
	{
		IF_F(m_pBGR->empty());
		pWin = (Window*) this->m_pWindow;
		pFrame = pWin->getFrame();
		pFrame->update(m_pBGR);
		this->_VisionBase::draw();

		string msg;
		pWin->tabNext();

		msg = "Tracking confidence: " + i2str(m_trackConfidence);
		pWin->addMsg(&msg);

		msg = "Translation: X=" + f2str(m_vT.x) + ", Y=" + f2str(m_vT.y)
				+ ", Z=" + f2str(m_vT.z);
		pWin->addMsg(&msg);

		msg = "Rotation: Yaw=" + f2str(m_vR.x) + ", Pitch=" + f2str(m_vR.y)
				+ ", Roll=" + f2str(m_vR.z);
		pWin->addMsg(&msg);

		pWin->tabPrev();
	}

	if (m_pDepthWin)
	{
		pFrame = m_pDepthWin->getFrame();
		if (pFrame && !m_pDepth->empty())
		{
			pFrame->update(m_pDepth);
		}
	}

	return true;
}

}

#endif
<|endoftext|>


<commit_before>#ifndef _H_XML_DOCUMENT
#define _H_XML_DOCUMENT

#include <iosfwd>
#include <string>
#include <vector>

#include "XmlElement.hpp"

namespace Xml
{
    // Forward declarations
    class DocumentNode;
    class ProcessingInstruction;

    /**
     * Defines a XML document
     */
    class Document
    {
    public:

        using NodesList = std::vector<DocumentNode *>;

        /**
         * Constructor
         *
         * @param root Root element of the document
         */
        Document(Element * root = nullptr);

        /**
         * Implements standard stream operator
         */
        std::ostream &
        operator >> (std::ostream & stream) const;

        /**
         * Destructor
         */
        virtual
        ~Document();

        /**
         * Gets the root element of the document (non-const version)
         *
         * @return The root element of the document
         */
        Element *
        root();

        /**
         * Gets the root element of the document (const version)
         *
         * @return The root element of the document
         */
        Element const *
        root() const;

        /**
         * Appends a comment to the document
         *
         * @param comment Text of the comment to append
         */
        void
        appendComment(std::string const & comment);

       /**
         * Appends a processing instruction (PI) to the element
         *
         * @param name Name of the PI to append
         * @param ...keyValues Key and values parameters of the PI
         */
        template <typename ...KeyValues>
        void
        appendProcessingInstruction(std::string const & name, KeyValues && ...keyValues);

        /**
         * Sets the root element of the document
         *
         * @param root New root of the document
         */
        void
        setRoot(Element * root);

        /**
         * Gets the children nodes of the document
         *
         * @return The children nodes of the document
         */
        NodesList const &
        children() const;

        /**
         * Saves the XML document into a file.
         *
         * @param path File path
         *
         * @return True if the file has been saved, false otherwise.
         */
        bool
        saveToFile(std::string const & path) const;

    protected:
        /**
         * Appends a DocumentNode to the Document
         *
         * @param documentNode Document node to append
         */
        void
        appendNode(DocumentNode * documentNode);

    protected:
        Element * mRoot;     ///< Root of the XML document
        NodesList mChildren; ///< Children nodes
        //DocType mDocType;  ///< DocType of the XML document //TODO
    };

    /**
     * Defines a sexier standard stream operator
     */
    inline
    std::ostream &
    operator << (std::ostream & stream, Document const & doc)
    {
        return doc >> stream;
    }
}

#include "XmlDocument.inl"

#endif //_H_XML_DOCUMENT
<commit_msg>Fixed doc<commit_after>#ifndef _H_XML_DOCUMENT
#define _H_XML_DOCUMENT

#include <iosfwd>
#include <string>
#include <vector>

#include "XmlElement.hpp"

namespace Xml
{
    // Forward declarations
    class DocumentNode;
    class ProcessingInstruction;

    /**
     * Defines a XML document
     */
    class Document
    {
    public:

        using NodesList = std::vector<DocumentNode *>;

        /**
         * Constructor
         *
         * @param root Root element of the document
         */
        Document(Element * root = nullptr);

        /**
         * Implements standard stream operator
         */
        std::ostream &
        operator >> (std::ostream & stream) const;

        /**
         * Destructor
         */
        virtual
        ~Document();

        /**
         * Gets the root element of the document (non-const version)
         *
         * @return The root element of the document
         */
        Element *
        root();

        /**
         * Gets the root element of the document (const version)
         *
         * @return The root element of the document
         */
        Element const *
        root() const;

        /**
         * Appends a comment to the document
         *
         * @param comment Text of the comment to append
         */
        void
        appendComment(std::string const & comment);

        /**
         * Appends a processing instruction (PI) to the element
         *
         * @param name Name of the PI to append
         * @param ...keyValues Key and values parameters of the PI
         */
        template <typename ...KeyValues>
        void
        appendProcessingInstruction(std::string const & name, KeyValues && ...keyValues);

        /**
         * Sets the root element of the document
         *
         * @param root New root of the document
         */
        void
        setRoot(Element * root);

        /**
         * Gets the children nodes of the document
         *
         * @return The children nodes of the document
         */
        NodesList const &
        children() const;

        /**
         * Saves the XML document into a file.
         *
         * @param path File path
         *
         * @return True if the file has been saved, false otherwise.
         */
        bool
        saveToFile(std::string const & path) const;

    protected:
        /**
         * Appends a DocumentNode to the Document
         *
         * @param documentNode Document node to append
         */
        void
        appendNode(DocumentNode * documentNode);

    protected:
        Element * mRoot;     ///< Root of the XML document
        NodesList mChildren; ///< Children nodes
        //DocType mDocType;  ///< DocType of the XML document //TODO
    };

    /**
     * Defines a sexier standard stream operator
     */
    inline
    std::ostream &
    operator << (std::ostream & stream, Document const & doc)
    {
        return doc >> stream;
    }
}

#include "XmlDocument.inl"

#endif //_H_XML_DOCUMENT
<|endoftext|>


<commit_before>/*
This file is part of qNotesManager.

qNotesManager is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

qNotesManager 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with qNotesManager. If not, see <http://www.gnu.org/licenses/>.
*/

#include "application.h"

#include <QDir>
#include <QPainter>

using namespace qNotesManager;

/*static*/
Application* Application::I() {
	static Application instance;
	return &instance;
}

Application::Application() :
		QObject(0),
		DefaultNoteIcon(":/icons/standard/Document/document.png"),
		DefaultFolderIcon(":/icons/standard/Folder/folder.png") {
	_currentDocument = 0;
	standardIconsModel = new QStandardItemModel(this);

	LoadIconsFromDir(":/icons/standard/Document");
	LoadIconsFromDir(":/icons/standard/Folder");
	LoadIconsFromDir(":/icons/standard/Misc");
}

void Application::LoadIconsFromDir(const QString& dirName) {
	QDir dir(dirName);
	iconGroups.append(dir.dirName());
	QFileInfoList list = dir.entryInfoList();
	foreach (QFileInfo info, list) {
		QPixmap p(info.absoluteFilePath(), info.suffix().toStdString().c_str());
		standardIcons.insert(info.absoluteFilePath(), p);

		QStandardItem* iconItem = new QStandardItem(p, QString());
		iconItem->setData(info.absoluteFilePath(), Qt::UserRole + 1); // id
		iconItem->setData(dir.dirName(), Qt::UserRole + 2); // filter group
		iconItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
		standardIconsModel->appendRow(iconItem);
	}
}

void Application::SetCurrentDocument(Document* doc) {
	if (doc == _currentDocument) {return;}
	Document* oldDoc = _currentDocument;

	_currentDocument = doc;
	emit sg_CurrentDocumentChanged(oldDoc);
}

Document* Application::CurrentDocument() const {
	return _currentDocument;
}

QList<QString> Application::GetStandardIconGroups()  {
	return iconGroups;
}

QStandardItemModel* Application::GetIconsModel()  {
	return standardIconsModel;
}

int Application::GetStandardIconsCount()  {
	return standardIcons.count();
}

QPixmap Application::GetStandardIcon(const QString& name)  {
	return standardIcons.value(name);
}

QPixmap Application::createImage(const QSize& size, const QString& text, bool loading) const {
	QPainter painter;
	const QBrush backgroundBrush {Qt::lightGray};
	const QRect back {QPoint(0,0), size};
	const QRect border(0, 0, size.width() - 1, size.height() - 1);
	QPixmap image {size};
	const bool smallImage {((size.width() < 100) || (size.height() < 20))};

	if (loading) {
		const int smallestSide {qMin(size.width(), size.height())};
		const int wheelSize {(int)(smallestSide * 0.6)};

		painter.begin(&image);
		painter.setBrush(backgroundBrush);
		painter.setPen(Qt::NoPen);
		painter.drawRect(back);

		// Draw loading icon
		if (wheelSize > 6) {
			const int dotsCount {12};
			const int dotSize {(int)(smallestSide * 0.1)};
			int alpha = 160;
			QColor dotColor {0, 0, 0, alpha};
			const int alphaStep {200 / dotsCount};
			const qreal angle {360.0 / (qreal)dotsCount};
			QBrush dotBrush {dotColor};

			painter.setRenderHint(QPainter::Antialiasing, true);
			painter.save();
			painter.translate(size.width() / 2, size.height() / 2);
			painter.rotate(angle);
			for (int i = 1; i <= dotsCount; ++i) {
				painter.setBrush(dotBrush);

				painter.drawEllipse(0, -size.height() / 3, dotSize, dotSize);

				alpha = alpha - alphaStep;
				alpha = qMax(alpha, 0);
				dotColor.setAlpha(alpha);
				dotBrush.setColor(dotColor);
				painter.rotate(-angle);
			}
			painter.restore();
			painter.setRenderHint(QPainter::Antialiasing, false);
		}
	}

	painter.setBrush(Qt::NoBrush);
	painter.setPen(Qt::black);
	painter.drawRect(border);

	if (!smallImage) {
		painter.drawText(back, Qt::AlignCenter, text);
	}

	painter.end();

	return image;
}

QPixmap Application::GetErrorImage(const QSize& size) const {
	const QSize defaultSize {100, 100};
	QSize newSize = size;
	if (!newSize.isValid() || newSize.isEmpty()) {newSize = defaultSize;}

	if (!errorThumbnails.contains(newSize)) {
		QPixmap image {createImage(newSize, "Error loading image")};
		errorThumbnails.insert(newSize, image);
	}
	return errorThumbnails[newSize];
}

QPixmap Application::GetLoadingImage(const QSize& size) const {
	const QSize defaultSize {100, 100};
	QSize newSize = size;
	if (!newSize.isValid() || newSize.isEmpty()) {newSize = defaultSize;}

	if (!loadingThumbnails.contains(newSize)) {
		QPixmap image {createImage(newSize, "Loading image...", true)};
		loadingThumbnails.insert(newSize, image);
	}
	return loadingThumbnails[newSize];
}

inline uint qHash(const QSize& size, uint seed) {
	return qHash(size.width(), seed) ^ size.height();
}
<commit_msg>Fixed QSize hash calculation for Qt < 5.0<commit_after>/*
This file is part of qNotesManager.

qNotesManager is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

qNotesManager 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with qNotesManager. If not, see <http://www.gnu.org/licenses/>.
*/

#include "application.h"

#include <QDir>
#include <QPainter>

using namespace qNotesManager;

/*static*/
Application* Application::I() {
	static Application instance;
	return &instance;
}

Application::Application() :
		QObject(0),
		DefaultNoteIcon(":/icons/standard/Document/document.png"),
		DefaultFolderIcon(":/icons/standard/Folder/folder.png") {
	_currentDocument = 0;
	standardIconsModel = new QStandardItemModel(this);

	LoadIconsFromDir(":/icons/standard/Document");
	LoadIconsFromDir(":/icons/standard/Folder");
	LoadIconsFromDir(":/icons/standard/Misc");
}

void Application::LoadIconsFromDir(const QString& dirName) {
	QDir dir(dirName);
	iconGroups.append(dir.dirName());
	QFileInfoList list = dir.entryInfoList();
	foreach (QFileInfo info, list) {
		QPixmap p(info.absoluteFilePath(), info.suffix().toStdString().c_str());
		standardIcons.insert(info.absoluteFilePath(), p);

		QStandardItem* iconItem = new QStandardItem(p, QString());
		iconItem->setData(info.absoluteFilePath(), Qt::UserRole + 1); // id
		iconItem->setData(dir.dirName(), Qt::UserRole + 2); // filter group
		iconItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
		standardIconsModel->appendRow(iconItem);
	}
}

void Application::SetCurrentDocument(Document* doc) {
	if (doc == _currentDocument) {return;}
	Document* oldDoc = _currentDocument;

	_currentDocument = doc;
	emit sg_CurrentDocumentChanged(oldDoc);
}

Document* Application::CurrentDocument() const {
	return _currentDocument;
}

QList<QString> Application::GetStandardIconGroups()  {
	return iconGroups;
}

QStandardItemModel* Application::GetIconsModel()  {
	return standardIconsModel;
}

int Application::GetStandardIconsCount()  {
	return standardIcons.count();
}

QPixmap Application::GetStandardIcon(const QString& name)  {
	return standardIcons.value(name);
}

QPixmap Application::createImage(const QSize& size, const QString& text, bool loading) const {
	QPainter painter;
	const QBrush backgroundBrush {Qt::lightGray};
	const QRect back {QPoint(0,0), size};
	const QRect border(0, 0, size.width() - 1, size.height() - 1);
	QPixmap image {size};
	const bool smallImage {((size.width() < 100) || (size.height() < 20))};

	if (loading) {
		const int smallestSide {qMin(size.width(), size.height())};
		const int wheelSize {(int)(smallestSide * 0.6)};

		painter.begin(&image);
		painter.setBrush(backgroundBrush);
		painter.setPen(Qt::NoPen);
		painter.drawRect(back);

		// Draw loading icon
		if (wheelSize > 6) {
			const int dotsCount {12};
			const int dotSize {(int)(smallestSide * 0.1)};
			int alpha = 160;
			QColor dotColor {0, 0, 0, alpha};
			const int alphaStep {200 / dotsCount};
			const qreal angle {360.0 / (qreal)dotsCount};
			QBrush dotBrush {dotColor};

			painter.setRenderHint(QPainter::Antialiasing, true);
			painter.save();
			painter.translate(size.width() / 2, size.height() / 2);
			painter.rotate(angle);
			for (int i = 1; i <= dotsCount; ++i) {
				painter.setBrush(dotBrush);

				painter.drawEllipse(0, -size.height() / 3, dotSize, dotSize);

				alpha = alpha - alphaStep;
				alpha = qMax(alpha, 0);
				dotColor.setAlpha(alpha);
				dotBrush.setColor(dotColor);
				painter.rotate(-angle);
			}
			painter.restore();
			painter.setRenderHint(QPainter::Antialiasing, false);
		}
	}

	painter.setBrush(Qt::NoBrush);
	painter.setPen(Qt::black);
	painter.drawRect(border);

	if (!smallImage) {
		painter.drawText(back, Qt::AlignCenter, text);
	}

	painter.end();

	return image;
}

QPixmap Application::GetErrorImage(const QSize& size) const {
	const QSize defaultSize {100, 100};
	QSize newSize = size;
	if (!newSize.isValid() || newSize.isEmpty()) {newSize = defaultSize;}

	if (!errorThumbnails.contains(newSize)) {
		QPixmap image {createImage(newSize, "Error loading image")};
		errorThumbnails.insert(newSize, image);
	}
	return errorThumbnails[newSize];
}

QPixmap Application::GetLoadingImage(const QSize& size) const {
	const QSize defaultSize {100, 100};
	QSize newSize = size;
	if (!newSize.isValid() || newSize.isEmpty()) {newSize = defaultSize;}

	if (!loadingThumbnails.contains(newSize)) {
		QPixmap image {createImage(newSize, "Loading image...", true)};
		loadingThumbnails.insert(newSize, image);
	}
	return loadingThumbnails[newSize];
}

#if QT_VERSION >= 0x050000
	inline uint qHash(const QSize& size, uint seed) {
		return qHash(size.width(), seed) ^ size.height();
	}
#else
	inline uint qHash(const QSize& size) {
		return qHash(size.width()) ^ size.height();
	}
#endif

<|endoftext|>