<commit_before>#include <pthread.h>
#include <sys/time.h>

#include "stinger_core/xmalloc.h"
#include "stinger_core/x86_full_empty.h"
#include "stinger_core/stinger_shared.h"
#include "stinger_core/stinger.h"
#include "stinger_mon.h"

#define LOG_AT_W
#include "stinger_core/stinger_error.h"

using namespace gt::stinger;

static uint64_t singleton_lock = 0;
static StingerMon * state = NULL;

StingerMon &
StingerMon::get_mon() {
  if(!state) {
    readfe(&singleton_lock);
      if(!state) {
	state = new StingerMon();
      }
    writeef(&singleton_lock, 1);
  }
  return *state;
}

StingerMon::StingerMon() : stinger(NULL),
  stinger_loc(""), stinger_sz(0), algs(NULL), alg_map(NULL),
  waiting(0), wait_lock(0), max_time(-922337203685477580)
{
  pthread_rwlock_init(&alg_lock, NULL);
  sem_init(&sync_lock, 0, 0);
}

StingerMon::~StingerMon()
{
  sem_destroy(&sync_lock);
}

size_t
StingerMon::get_num_algs()
{
  if(algs)
    return algs->size();
  else
    return 0;
}

StingerAlgState *
StingerMon::get_alg(size_t num)
{
  if(algs)
    return (*algs)[num];
  else
    return NULL;
}

StingerAlgState *
StingerMon::get_alg(const std::string & name)
{
  if(alg_map && has_alg(name))
    return (*alg_map)[name];
  else
    return NULL;
}

bool
StingerMon::has_alg(const std::string & name)
{
  if(alg_map)
    return alg_map->count(name) > 0;
  else
    return false;
}

void
StingerMon::get_alg_read_lock()
{
  LOG_D("read lock get");
  pthread_rwlock_rdlock(&alg_lock);
  LOG_D("read lock received");
}

void
StingerMon::release_alg_read_lock()
{
  LOG_D("read lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("read lock released");
}

void
StingerMon::update_algs(stinger_t * stinger_copy, std::string new_loc, int64_t new_sz,
  std::vector<StingerAlgState *> * new_algs, std::map<std::string, StingerAlgState *> * new_alg_map,
  const StingerBatch & batch)
{
  LOG_D_A("Called with %s, %ld", new_loc.c_str(), (long)new_sz);
  LOG_D("write lock get");
  pthread_rwlock_wrlock(&alg_lock);
  LOG_D("write lock received");
  /* remap stinger */
  if(stinger) {
    stinger_shared_unmap (stinger, stinger_loc.c_str(), stinger_sz);
  }
  stinger = stinger_copy;
  stinger_loc = new_loc;
  stinger_sz = new_sz;

  /* unmap / delete existing algs */
  if(algs) {
    for(int64_t i = 0; i < algs->size(); i++) {
      StingerAlgState * cur_alg = (*algs)[i];
      if(cur_alg) {
	shmunmap(cur_alg->data_loc.c_str(), cur_alg->data, cur_alg->data_per_vertex * stinger->max_nv);
	delete cur_alg;
      }
    }

    delete algs;
  }
  if(alg_map)
    delete alg_map;

  algs = new_algs;
  alg_map = new_alg_map;

  /* update max time with latest insertion time */
  int64_t new_max_time = max_time;
  for(int64_t i = 0; i < batch.insertions_size(); i++) {
    int64_t edge_time = batch.insertions(i).time();
    if(edge_time > new_max_time)
      new_max_time = edge_time;
  }
  max_time = new_max_time;

  LOG_D("write lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("write lock released");
}

int64_t
StingerMon::get_max_time() {
  return max_time;
}

void
StingerMon::wait_for_sync()
{
  readfe((uint64_t *)&wait_lock);
    waiting++;
  writeef((uint64_t *)&wait_lock, 0);

  sem_wait(&sync_lock);
}

void
StingerMon::sync()
{
  readfe((uint64_t *)&wait_lock);
    for(int64_t i = 0; i < waiting; i++)
      sem_post(&sync_lock);
    waiting = 0;
  writeef((uint64_t *)&wait_lock, 0);
}

stinger_t *
StingerMon::get_stinger()
{
  return stinger;
}
<commit_msg>Stinger pointer needs to be checked for NULL here<commit_after>#include <pthread.h>
#include <sys/time.h>

#include "stinger_core/xmalloc.h"
#include "stinger_core/x86_full_empty.h"
#include "stinger_core/stinger_shared.h"
#include "stinger_core/stinger.h"
#include "stinger_mon.h"

#define LOG_AT_W
#include "stinger_core/stinger_error.h"

using namespace gt::stinger;

static uint64_t singleton_lock = 0;
static StingerMon * state = NULL;

StingerMon &
StingerMon::get_mon() {
  if(!state) {
    readfe(&singleton_lock);
      if(!state) {
	state = new StingerMon();
      }
    writeef(&singleton_lock, 1);
  }
  return *state;
}

StingerMon::StingerMon() : stinger(NULL),
  stinger_loc(""), stinger_sz(0), algs(NULL), alg_map(NULL),
  waiting(0), wait_lock(0), max_time(-922337203685477580)
{
  pthread_rwlock_init(&alg_lock, NULL);
  sem_init(&sync_lock, 0, 0);
}

StingerMon::~StingerMon()
{
  sem_destroy(&sync_lock);
}

size_t
StingerMon::get_num_algs()
{
  if(algs)
    return algs->size();
  else
    return 0;
}

StingerAlgState *
StingerMon::get_alg(size_t num)
{
  if(algs)
    return (*algs)[num];
  else
    return NULL;
}

StingerAlgState *
StingerMon::get_alg(const std::string & name)
{
  if(alg_map && has_alg(name))
    return (*alg_map)[name];
  else
    return NULL;
}

bool
StingerMon::has_alg(const std::string & name)
{
  if(alg_map)
    return alg_map->count(name) > 0;
  else
    return false;
}

void
StingerMon::get_alg_read_lock()
{
  LOG_D("read lock get");
  pthread_rwlock_rdlock(&alg_lock);
  LOG_D("read lock received");
}

void
StingerMon::release_alg_read_lock()
{
  LOG_D("read lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("read lock released");
}

void
StingerMon::update_algs(stinger_t * stinger_copy, std::string new_loc, int64_t new_sz,
  std::vector<StingerAlgState *> * new_algs, std::map<std::string, StingerAlgState *> * new_alg_map,
  const StingerBatch & batch)
{
  LOG_D_A("Called with %s, %ld", new_loc.c_str(), (long)new_sz);
  LOG_D("write lock get");
  pthread_rwlock_wrlock(&alg_lock);
  LOG_D("write lock received");
  /* remap stinger */
  if(stinger) {
    stinger_shared_unmap (stinger, stinger_loc.c_str(), stinger_sz);
  }
  stinger = stinger_copy;
  stinger_loc = new_loc;
  stinger_sz = new_sz;

  /* unmap / delete existing algs */
  if(stinger && algs) {
    for(int64_t i = 0; i < algs->size(); i++) {
      StingerAlgState * cur_alg = (*algs)[i];
      if(cur_alg) {
	shmunmap(cur_alg->data_loc.c_str(), cur_alg->data, cur_alg->data_per_vertex * stinger->max_nv);
	delete cur_alg;
      }
    }

    delete algs;
  }
  if(alg_map)
    delete alg_map;

  algs = new_algs;
  alg_map = new_alg_map;

  /* update max time with latest insertion time */
  int64_t new_max_time = max_time;
  for(int64_t i = 0; i < batch.insertions_size(); i++) {
    int64_t edge_time = batch.insertions(i).time();
    if(edge_time > new_max_time)
      new_max_time = edge_time;
  }
  max_time = new_max_time;

  LOG_D("write lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("write lock released");
}

int64_t
StingerMon::get_max_time() {
  return max_time;
}

void
StingerMon::wait_for_sync()
{
  readfe((uint64_t *)&wait_lock);
    waiting++;
  writeef((uint64_t *)&wait_lock, 0);

  sem_wait(&sync_lock);
}

void
StingerMon::sync()
{
  readfe((uint64_t *)&wait_lock);
    for(int64_t i = 0; i < waiting; i++)
      sem_post(&sync_lock);
    waiting = 0;
  writeef((uint64_t *)&wait_lock, 0);
}

stinger_t *
StingerMon::get_stinger()
{
  return stinger;
}
<|endoftext|>


<commit_before>/*
 *            Copyright 2009-2019 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 "iexcitoncl.h"
#include "votca/xtp/segmentmapper.h"

#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <votca/tools/constants.h>
#include <votca/tools/propertyiomanipulator.h>
#include <votca/xtp/eeinteractor.h>
#include <votca/xtp/logger.h>

using namespace std;
using namespace boost::filesystem;
using namespace votca::tools;

namespace votca {
namespace xtp {

// +++++++++++++++++++++++++++++ //
// IEXCITON MEMBER FUNCTIONS         //
// +++++++++++++++++++++++++++++ //

void IEXCITON::Initialize(tools::Property& options) {

  string key = "options." + Identify();
  ParseCommonOptions(options);

  if (options.exists(key + ".states")) {
    string parse_string = options.get(key + ".states").as<string>();
    _statemap = FillParseMaps(parse_string);
  }

  cout << "done" << endl;
}

std::map<std::string, QMState> IEXCITON::FillParseMaps(
    const string& Mapstring) {
  Tokenizer split_options(Mapstring, ", \t\n");
  std::map<std::string, QMState> type2level;
  for (const string& substring : split_options) {
    std::vector<string> segmentpnumber;
    Tokenizer tok(substring, ":");
    tok.ToVector(segmentpnumber);
    if (segmentpnumber.size() != 2) {
      throw runtime_error("Parser iqm: Segment and exciton labels:" +
                          substring + "are not separated properly");
    }
    QMState state = QMState(segmentpnumber[1]);
    if (!state.isTransition()) {
      throw std::runtime_error("State to calculate must be a transition state");
    }
    string segmentname = segmentpnumber[0];
    type2level[segmentname] = state;
  }
  return type2level;
}

Job::JobResult IEXCITON::EvalJob(const Topology& top, Job& job,
                                 QMThread& opThread) {

  // report back to the progress observer
  Job::JobResult jres = Job::JobResult();

  // get the logger from the thread
  Logger& pLog = opThread.getLogger();

  // get the information about the job executed by the thread
  Index job_ID = job.getId();
  Property job_input = job.getInput();
  vector<Property*> segment_list = job_input.Select("segment");
  Index ID_A = segment_list.front()->getAttribute<Index>("id");
  string type_A = segment_list.front()->getAttribute<string>("type");
  string mps_fileA = segment_list.front()->getAttribute<string>("mps_file");
  Index ID_B = segment_list.back()->getAttribute<Index>("id");
  string type_B = segment_list.back()->getAttribute<string>("type");
  string mps_fileB = segment_list.back()->getAttribute<string>("mps_file");

  const Segment& seg_A = top.getSegment(ID_A);
  if (type_A != seg_A.getType()) {
    throw runtime_error("SegmentA: type " + seg_A.getType() +
                        " and type in jobfile " + type_A +
                        " do not agree for ID:" + std::to_string(ID_A));
  }
  const Segment& seg_B = top.getSegment(ID_B);
  if (type_B != seg_B.getType()) {
    throw runtime_error("SegmentB: type " + seg_B.getType() +
                        " and type in jobfile " + type_B +
                        " do not agree for ID:" + std::to_string(ID_B));
  }
  const QMNBList& nblist = top.NBList();
  const QMPair* pair = nblist.FindPair(&seg_A, &seg_B);
  if (pair == nullptr) {
    throw std::runtime_error(
        "pair between segments " + std::to_string(seg_A.getId()) + ":" +
        std::to_string(seg_B.getId()) + " not found in neighborlist ");
  }

  XTP_LOG(Log::error, pLog) << TimeStamp() << " Evaluating pair " << job_ID
                            << " [" << ID_A << ":" << ID_B << "]" << flush;

  StaticMapper map(pLog);
  map.LoadMappingFile(_mapfile);
  StaticSegment seg1 = map.map(*(pair->Seg1()), mps_fileA);
  StaticSegment seg2 = map.map(pair->Seg2PbCopy(), mps_fileB);
  eeInteractor actor;
  double JAB = actor.CalcStaticEnergy(seg1, seg2);
  _cutoff = 0;
  Property job_summary;
  Property& job_output = job_summary.add("output", "");
  Property& pair_summary = job_output.add("pair", "");
  string nameA = seg_A.getType();
  string nameB = seg_B.getType();
  pair_summary.setAttribute("idA", ID_A);
  pair_summary.setAttribute("idB", ID_B);
  pair_summary.setAttribute("typeA", nameA);
  pair_summary.setAttribute("typeB", nameB);
  Property& coupling_summary = pair_summary.add("Coupling", "");
  coupling_summary.setAttribute("jABstatic", JAB * tools::conv::hrt2ev);

  jres.setOutput(job_summary);
  jres.setStatus(Job::COMPLETE);

  return jres;
}

QMState IEXCITON::GetElementFromMap(const std::string& elementname) const {
  QMState state;
  try {
    state = _statemap.at(elementname);
  } catch (std::out_of_range&) {
    std::string errormessage =
        "Map does not have segment of type: " + elementname;
    errormessage += "\n segments in map are:";
    for (const auto& s : _statemap) {
      errormessage += "\n\t" + s.first;
    }
    throw std::runtime_error(errormessage);
  }
  return state;
}

void IEXCITON::WriteJobFile(const Topology& top) {

  cout << endl << "... ... Writing job file " << _jobfile << flush;
  std::ofstream ofs;
  ofs.open(_jobfile, std::ofstream::out);
  if (!ofs.is_open()) {
    throw runtime_error("\nERROR: bad file handle: " + _jobfile);
  }
  const QMNBList& nblist = top.NBList();
  Index jobCount = 0;
  if (nblist.size() == 0) {
    cout << endl << "... ... No pairs in neighbor list, skip." << flush;
    return;
  }

  ofs << "<jobs>" << endl;
  string tag = "";

  for (const QMPair* pair : nblist) {
    if (pair->getType() == QMPair::PairType::Excitoncl) {
      Index id1 = pair->Seg1()->getId();
      string name1 = pair->Seg1()->getType();
      Index id2 = pair->Seg2()->getId();
      string name2 = pair->Seg2()->getType();
      Index id = jobCount;
      QMState state1 = GetElementFromMap(name1);
      QMState state2 = GetElementFromMap(name2);

      string mps_file1 =
          (boost::format("MP_FILES/%s_%s.mps") % name1 % state1.ToString())
              .str();
      string mps_file2 =
          (boost::format("MP_FILES/%s_%s.mps") % name1 % state2.ToString())
              .str();

      Property Input;
      Property& pInput = Input.add("input", "");
      Property& pSegment1 =
          pInput.add("segment", boost::lexical_cast<string>(id1));
      pSegment1.setAttribute<string>("type", name1);
      pSegment1.setAttribute<Index>("id", id1);
      pSegment1.setAttribute<string>("mps_file", mps_file1);
      Property& pSegment2 =
          pInput.add("segment", boost::lexical_cast<string>(id2));
      pSegment2.setAttribute<string>("type", name2);
      pSegment2.setAttribute<Index>("id", id2);
      pSegment2.setAttribute<string>("mps_file", mps_file2);

      Job job(id, tag, Input, Job::AVAILABLE);
      job.ToStream(ofs);
      jobCount++;
    }
  }

  // CLOSE STREAM
  ofs << "</jobs>" << endl;
  ofs.close();

  cout << endl << "... ... In total " << jobCount << " jobs" << flush;
}

void IEXCITON::ReadJobFile(Topology& top) {

  Property xml;
  vector<Property*> records;
  // gets the neighborlist from the topology
  QMNBList& nblist = top.NBList();
  Index number_of_pairs = nblist.size();
  Index current_pairs = 0;
  Logger log;
  log.setReportLevel(Log::current_level);

  // load the QC results in a vector indexed by the pair ID
  xml.LoadFromXML(_jobfile);
  vector<Property*> jobProps = xml.Select("jobs.job");
  records.resize(number_of_pairs + 1);

  // to skip pairs which are not in the jobfile
  for (auto& record : records) {
    record = nullptr;
  }
  // loop over all jobs = pair records in the job file
  for (Property* prop : jobProps) {
    // if job produced an output, then continue with analysis
    if (prop->exists("output") && prop->exists("output.pair")) {
      current_pairs++;
      Property& poutput = prop->get("output.pair");
      Index idA = poutput.getAttribute<Index>("idA");
      Index idB = poutput.getAttribute<Index>("idB");
      Segment& segA = top.getSegment(idA);
      Segment& segB = top.getSegment(idB);
      QMPair* qmp = nblist.FindPair(&segA, &segB);

      if (qmp == nullptr) {
        XTP_LOG(Log::error, log)
            << "No pair " << idA << ":" << idB
            << " found in the neighbor list. Ignoring" << flush;
      } else {
        records[qmp->getId()] = &(prop->get("output.pair"));
      }
    } else {
      Property thebadone = prop->get("id");
      throw runtime_error("\nERROR: Job file incomplete.\n Job with id " +
                          thebadone.as<string>() +
                          " is not finished. Check your job file for FAIL, "
                          "AVAILABLE, or ASSIGNED. Exiting\n");
    }
  }  // finished loading from the file

  // loop over all pairs in the neighbor list
  XTP_LOG(Log::error, log) << "Neighborlist size " << top.NBList().size()
                           << flush;
  for (QMPair* pair : top.NBList()) {

    if (records[pair->getId()] == nullptr) {
      continue;  // skip pairs which are not in the jobfile
    }

    if (pair->getType() == QMPair::Excitoncl) {
      Property* pair_property = records[pair->getId()];
      const Property& pCoupling = pair_property->get("Coupling");
      double jAB = pCoupling.getAttribute<double>("jABstatic");
      double Jeff2 = jAB * jAB * tools::conv::ev2hrt * tools::conv::ev2hrt;
      pair->setJeff2(Jeff2, QMStateType::Singlet);
    }
  }
  XTP_LOG(Log::error, log) << "Pairs [total:updated] " << number_of_pairs << ":"
                           << current_pairs << flush;
  cout << log;
}

}  // namespace xtp
}  // namespace votca
<commit_msg>fixExcitonCoupling<commit_after>/*
 *            Copyright 2009-2019 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 "iexcitoncl.h"
#include "votca/xtp/segmentmapper.h"

#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <votca/tools/constants.h>
#include <votca/tools/propertyiomanipulator.h>
#include <votca/xtp/eeinteractor.h>
#include <votca/xtp/logger.h>

using namespace std;
using namespace boost::filesystem;
using namespace votca::tools;

namespace votca {
namespace xtp {

// +++++++++++++++++++++++++++++ //
// IEXCITON MEMBER FUNCTIONS         //
// +++++++++++++++++++++++++++++ //

void IEXCITON::Initialize(tools::Property& options) {

  string key = "options." + Identify();
  ParseCommonOptions(options);

  if (options.exists(key + ".states")) {
    string parse_string = options.get(key + ".states").as<string>();
    _statemap = FillParseMaps(parse_string);
  }

  cout << "done" << endl;
}

std::map<std::string, QMState> IEXCITON::FillParseMaps(
    const string& Mapstring) {
  Tokenizer split_options(Mapstring, ", \t\n");
  std::map<std::string, QMState> type2level;
  for (const string& substring : split_options) {
    std::vector<string> segmentpnumber;
    Tokenizer tok(substring, ":");
    tok.ToVector(segmentpnumber);
    if (segmentpnumber.size() != 2) {
      throw runtime_error("Parser iqm: Segment and exciton labels:" +
                          substring + "are not separated properly");
    }
    QMState state = QMState(segmentpnumber[1]);
    if (!state.isTransition()) {
      throw std::runtime_error("State to calculate must be a transition state");
    }
    string segmentname = segmentpnumber[0];
    type2level[segmentname] = state;
  }
  return type2level;
}

Job::JobResult IEXCITON::EvalJob(const Topology& top, Job& job,
                                 QMThread& opThread) {

  // report back to the progress observer
  Job::JobResult jres = Job::JobResult();

  // get the logger from the thread
  Logger& pLog = opThread.getLogger();

  // get the information about the job executed by the thread
  Index job_ID = job.getId();
  Property job_input = job.getInput();
  vector<Property*> segment_list = job_input.Select("segment");
  Index ID_A = segment_list.front()->getAttribute<Index>("id");
  string type_A = segment_list.front()->getAttribute<string>("type");
  string mps_fileA = segment_list.front()->getAttribute<string>("mps_file");
  Index ID_B = segment_list.back()->getAttribute<Index>("id");
  string type_B = segment_list.back()->getAttribute<string>("type");
  string mps_fileB = segment_list.back()->getAttribute<string>("mps_file");

  const Segment& seg_A = top.getSegment(ID_A);
  if (type_A != seg_A.getType()) {
    throw runtime_error("SegmentA: type " + seg_A.getType() +
                        " and type in jobfile " + type_A +
                        " do not agree for ID:" + std::to_string(ID_A));
  }
  const Segment& seg_B = top.getSegment(ID_B);
  if (type_B != seg_B.getType()) {
    throw runtime_error("SegmentB: type " + seg_B.getType() +
                        " and type in jobfile " + type_B +
                        " do not agree for ID:" + std::to_string(ID_B));
  }
  const QMNBList& nblist = top.NBList();
  const QMPair* pair = nblist.FindPair(&seg_A, &seg_B);
  if (pair == nullptr) {
    throw std::runtime_error(
        "pair between segments " + std::to_string(seg_A.getId()) + ":" +
        std::to_string(seg_B.getId()) + " not found in neighborlist ");
  }

  XTP_LOG(Log::error, pLog) << TimeStamp() << " Evaluating pair " << job_ID
                            << " [" << ID_A << ":" << ID_B << "]" << flush;

  StaticMapper map(pLog);
  map.LoadMappingFile(_mapfile);
  StaticSegment seg1 = map.map(*(pair->Seg1()), mps_fileA);
  StaticSegment seg2 = map.map(pair->Seg2PbCopy(), mps_fileB);
  eeInteractor actor;
  double JAB = actor.CalcStaticEnergy(seg1, seg2);
  _cutoff = 0;
  Property job_summary;
  Property& job_output = job_summary.add("output", "");
  Property& pair_summary = job_output.add("pair", "");
  string nameA = seg_A.getType();
  string nameB = seg_B.getType();
  pair_summary.setAttribute("idA", ID_A);
  pair_summary.setAttribute("idB", ID_B);
  pair_summary.setAttribute("typeA", nameA);
  pair_summary.setAttribute("typeB", nameB);
  Property& coupling_summary = pair_summary.add("Coupling", "");
  coupling_summary.setAttribute("jABstatic", JAB * tools::conv::hrt2ev);

  jres.setOutput(job_summary);
  jres.setStatus(Job::COMPLETE);

  return jres;
}

QMState IEXCITON::GetElementFromMap(const std::string& elementname) const {
  QMState state;
  try {
    state = _statemap.at(elementname);
  } catch (std::out_of_range&) {
    std::string errormessage =
        "Map does not have segment of type: " + elementname;
    errormessage += "\n segments in map are:";
    for (const auto& s : _statemap) {
      errormessage += "\n\t" + s.first;
    }
    throw std::runtime_error(errormessage);
  }
  return state;
}

void IEXCITON::WriteJobFile(const Topology& top) {

  cout << endl << "... ... Writing job file " << _jobfile << flush;
  std::ofstream ofs;
  ofs.open(_jobfile, std::ofstream::out);
  if (!ofs.is_open()) {
    throw runtime_error("\nERROR: bad file handle: " + _jobfile);
  }
  const QMNBList& nblist = top.NBList();
  Index jobCount = 0;
  if (nblist.size() == 0) {
    cout << endl << "... ... No pairs in neighbor list, skip." << flush;
    return;
  }

  ofs << "<jobs>" << endl;
  string tag = "";

  for (const QMPair* pair : nblist) {
    if (pair->getType() == QMPair::PairType::Excitoncl) {
      Index id1 = pair->Seg1()->getId();
      string name1 = pair->Seg1()->getType();
      Index id2 = pair->Seg2()->getId();
      string name2 = pair->Seg2()->getType();
      Index id = jobCount;
      QMState state1 = GetElementFromMap(name1);
      QMState state2 = GetElementFromMap(name2);

      string mps_file1 =
          (boost::format("MP_FILES/%s_%s.mps") % name1 % state1.ToString())
              .str();
      string mps_file2 =
          (boost::format("MP_FILES/%s_%s.mps") % name2 % state2.ToString())
              .str();

      Property Input;
      Property& pInput = Input.add("input", "");
      Property& pSegment1 =
          pInput.add("segment", boost::lexical_cast<string>(id1));
      pSegment1.setAttribute<string>("type", name1);
      pSegment1.setAttribute<Index>("id", id1);
      pSegment1.setAttribute<string>("mps_file", mps_file1);
      Property& pSegment2 =
          pInput.add("segment", boost::lexical_cast<string>(id2));
      pSegment2.setAttribute<string>("type", name2);
      pSegment2.setAttribute<Index>("id", id2);
      pSegment2.setAttribute<string>("mps_file", mps_file2);

      Job job(id, tag, Input, Job::AVAILABLE);
      job.ToStream(ofs);
      jobCount++;
    }
  }

  // CLOSE STREAM
  ofs << "</jobs>" << endl;
  ofs.close();

  cout << endl << "... ... In total " << jobCount << " jobs" << flush;
}

void IEXCITON::ReadJobFile(Topology& top) {

  Property xml;
  vector<Property*> records;
  // gets the neighborlist from the topology
  QMNBList& nblist = top.NBList();
  Index number_of_pairs = nblist.size();
  Index current_pairs = 0;
  Logger log;
  log.setReportLevel(Log::current_level);

  // load the QC results in a vector indexed by the pair ID
  xml.LoadFromXML(_jobfile);
  vector<Property*> jobProps = xml.Select("jobs.job");
  records.resize(number_of_pairs + 1);

  // to skip pairs which are not in the jobfile
  for (auto& record : records) {
    record = nullptr;
  }
  // loop over all jobs = pair records in the job file
  for (Property* prop : jobProps) {
    // if job produced an output, then continue with analysis
    if (prop->exists("output") && prop->exists("output.pair")) {
      current_pairs++;
      Property& poutput = prop->get("output.pair");
      Index idA = poutput.getAttribute<Index>("idA");
      Index idB = poutput.getAttribute<Index>("idB");
      Segment& segA = top.getSegment(idA);
      Segment& segB = top.getSegment(idB);
      QMPair* qmp = nblist.FindPair(&segA, &segB);

      if (qmp == nullptr) {
        XTP_LOG(Log::error, log)
            << "No pair " << idA << ":" << idB
            << " found in the neighbor list. Ignoring" << flush;
      } else {
        records[qmp->getId()] = &(prop->get("output.pair"));
      }
    } else {
      Property thebadone = prop->get("id");
      throw runtime_error("\nERROR: Job file incomplete.\n Job with id " +
                          thebadone.as<string>() +
                          " is not finished. Check your job file for FAIL, "
                          "AVAILABLE, or ASSIGNED. Exiting\n");
    }
  }  // finished loading from the file

  // loop over all pairs in the neighbor list
  XTP_LOG(Log::error, log) << "Neighborlist size " << top.NBList().size()
                           << flush;
  for (QMPair* pair : top.NBList()) {

    if (records[pair->getId()] == nullptr) {
      continue;  // skip pairs which are not in the jobfile
    }

    if (pair->getType() == QMPair::Excitoncl) {
      Property* pair_property = records[pair->getId()];
      const Property& pCoupling = pair_property->get("Coupling");
      double jAB = pCoupling.getAttribute<double>("jABstatic");
      double Jeff2 = jAB * jAB * tools::conv::ev2hrt * tools::conv::ev2hrt;
      pair->setJeff2(Jeff2, QMStateType::Singlet);
    }
  }
  XTP_LOG(Log::error, log) << "Pairs [total:updated] " << number_of_pairs << ":"
                           << current_pairs << flush;
  cout << log;
}

}  // namespace xtp
}  // namespace votca
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2010-2013 Razor team
 * Authors:
 *   Christopher "VdoP" Regali
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *   Maciej Płaza <plaza.maciej@gmail.com>
 *   Kuzma Shapran <kuzma.shapran@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

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

#include "lxqtclock.h"

#include <QDialog>
#include <QLabel>
#include <QVBoxLayout>
#include <QMouseEvent>

#include <QDateTime>
#include <QTimer>
#include <QPoint>
#include <QRect>
#include <QProxyStyle>
#include <QPainter>

#include <QDebug>

/**
 * @file lxqtclock.cpp
 * @brief implements LXQtclock and LXQtclockgui
 * @author Christopher "VdoP" Regali
 * @author Kuzma Shapran
 */

class DownscaleFontStyle : public QProxyStyle
{
    using QProxyStyle::QProxyStyle;
public:

    virtual void drawItemText(QPainter * painter, const QRect & rect, int flags
            , const QPalette & pal, bool enabled, const QString & text
            , QPalette::ColorRole textRole = QPalette::NoRole) const override
    {
        while (1 < painter->font().pointSize()
                && !(rect.size() - painter->fontMetrics().boundingRect(text).size()).isValid())
        {
            QFont f{painter->font()};
            f.setPointSize(f.pointSize() - 1);
            painter->setFont(f);
        }
        return QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
    }
};

/**
 * @brief constructor
 */
LXQtClock::LXQtClock(const ILXQtPanelPluginStartupInfo &startupInfo):
    QObject(),
    ILXQtPanelPlugin(startupInfo),
    mAutoRotate(true),
    mTextStyle{new DownscaleFontStyle},
    mCurrentCharCount(0)
{
    mMainWidget = new QWidget();
    mRotatedWidget = new LXQt::RotatedWidget(*(new QWidget()), mMainWidget);
    mContent = mRotatedWidget->content();
    mContent->setStyle(mTextStyle.data());
    mTimeLabel = new QLabel(mContent);
    mDateLabel = new QLabel(mContent);

    QVBoxLayout *borderLayout = new QVBoxLayout(mMainWidget);
    borderLayout->setContentsMargins(0, 0, 0, 0);
    borderLayout->setSpacing(0);
    borderLayout->addWidget(mRotatedWidget, 0, Qt::AlignCenter);

    mTimeLabel->setObjectName("TimeLabel");
    mDateLabel->setObjectName("DateLabel");

    mTimeLabel->setAlignment(Qt::AlignCenter);
    mDateLabel->setAlignment(Qt::AlignCenter);

    mContent->setLayout(new QVBoxLayout{mContent});
    mContent->layout()->setContentsMargins(0, 0, 0, 0);
    mContent->layout()->setSpacing(0);
    mContent->layout()->addWidget(mTimeLabel);
    mContent->layout()->addWidget(mDateLabel);

    mClockTimer = new QTimer(this);
    mClockTimer->setTimerType(Qt::PreciseTimer);
    connect (mClockTimer, SIGNAL(timeout()), SLOT(updateTime()));

    mClockFormat = "hh:mm";

    mCalendarPopup = new CalendarPopup(mContent);

    mMainWidget->installEventFilter(this);
    settingsChanged();
}

/**
 * @brief destructor
 */
LXQtClock::~LXQtClock()
{
    delete mMainWidget;
}

QDateTime LXQtClock::currentDateTime()
{
    return QDateTime(mUseUTC ? QDateTime::currentDateTimeUtc() : QDateTime::currentDateTime());
}

/**
 * @brief updates the time
 * Color and font settings can be configured in Qt CSS
 */
void LXQtClock::updateTime()
{
    //XXX: do we need this with PreciseTimer ?
    if (currentDateTime().time().msec() > 500)
        restartTimer();

    showTime();
}

void LXQtClock::showTime()
{
    QDateTime now{currentDateTime()};
    int new_char_count;
    if (mDateOnNewLine)
    {
        QString new_time = QLocale::system().toString(now, mTimeFormat);
        QString new_date = QLocale::system().toString(now, mDateFormat);
        new_char_count = qMax(new_time.size(), new_date.size());
        mTimeLabel->setText(new_time);
        mDateLabel->setText(new_date);
    }
    else
    {
        QString new_time = QLocale::system().toString(now, mClockFormat);
        new_char_count = new_time.size();
        mTimeLabel->setText(new_time);
    }

    //Note: if transformation (custom rendering) is enabled we need the explicit update
    //(update doesn't cause superfluous paint events)
    mRotatedWidget->update();

    if (mCurrentCharCount != new_char_count)
    {
        mCurrentCharCount = new_char_count;
        realign();
    }
}

void LXQtClock::restartTimer()
{
    if (mClockTimer->isActive())
        mClockTimer->stop();
    int updateInterval = mClockTimer->interval();
    QDateTime now{currentDateTime()};
    int delay = updateInterval - ((now.time().msec() + now.time().second() * 1000) % updateInterval);
    QTimer::singleShot(delay, Qt::PreciseTimer, mClockTimer, SLOT(start()));
    QTimer::singleShot(delay, Qt::PreciseTimer, this, SLOT(updateTime()));
}

void LXQtClock::settingsChanged()
{
    mFirstDayOfWeek = settings()->value("firstDayOfWeek", -1).toInt();
    if (-1 == mFirstDayOfWeek)
        mCalendarPopup->setFirstDayOfWeek(QLocale::system().firstDayOfWeek());
    else
        mCalendarPopup->setFirstDayOfWeek(static_cast<Qt::DayOfWeek>(mFirstDayOfWeek));

    mTimeFormat = settings()->value("timeFormat", QLocale::system().timeFormat(QLocale::ShortFormat).toUpper().contains("AP") ? "h:mm AP" : "HH:mm").toString();

    mUseUTC = settings()->value("UTC", false).toBool();
    if (mUseUTC)
        mTimeFormat += "' Z'";

    mDateFormat = settings()->value("dateFormat", Qt::SystemLocaleShortDate).toString();

    bool dateBeforeTime = (settings()->value("showDate", "no").toString().toLower() == "before");
    bool dateAfterTime = (settings()->value("showDate", "no").toString().toLower() == "after");
    mDateOnNewLine = (settings()->value("showDate", "no").toString().toLower() == "below");

    mAutoRotate = settings()->value("autoRotate", true).toBool();

    if (dateBeforeTime)
        mClockFormat = QString("%1 %2").arg(mDateFormat).arg(mTimeFormat);
    else if (dateAfterTime)
        mClockFormat = QString("%1 %2").arg(mTimeFormat).arg(mDateFormat);
    else
        mClockFormat = mTimeFormat;

    mDateLabel->setHidden(!mDateOnNewLine);

    // mDateFormat usually does not contain time portion, but since it's possible to use custom date format - it has to be supported. [Kuzma Shapran]
    int updateInterval = QString(mTimeFormat + " " + mDateFormat).replace(QRegExp("'[^']*'"),"").contains("s") ? 1000 : 60000;

    QDateTime now = currentDateTime();

    showTime();

    if (mClockTimer->interval() != updateInterval)
    {
        mClockTimer->setInterval(updateInterval);

        restartTimer();
    }
}

void LXQtClock::realign()
{
    QSize size{QWIDGETSIZE_MAX, QWIDGETSIZE_MAX};
    Qt::Corner origin = Qt::TopLeftCorner;
    if (mAutoRotate || panel()->isHorizontal())
    {
        switch (panel()->position())
        {
        case ILXQtPanel::PositionTop:
        case ILXQtPanel::PositionBottom:
            origin = Qt::TopLeftCorner;
            break;

        case ILXQtPanel::PositionLeft:
            origin = Qt::BottomLeftCorner;
            break;

        case ILXQtPanel::PositionRight:
            origin = Qt::TopRightCorner;
            break;
        }

        //set minwidth
        QFontMetrics metrics{mTimeLabel->font()};
        //Note: using a constant string of reasonably wide characters for computing the width
        //      (not the current text as width of text can differ for each particular string (based on font))
        size.setWidth(metrics.boundingRect(QString{mCurrentCharCount, 'A'}).width());
    } else if (!panel()->isHorizontal())
    {
        size.setWidth(panel()->globalGometry().width());
    }

    mTimeLabel->setFixedWidth(size.width());
    mDateLabel->setFixedWidth(size.width());

    int label_height = mTimeLabel->sizeHint().height();
    size.setHeight(mDateOnNewLine ? label_height * 2 : label_height);

    const bool changed = mContent->maximumSize() != size || mRotatedWidget->origin() != origin;

    mContent->setFixedSize(size);
    mRotatedWidget->setOrigin(origin);

    if (changed)
    {
        mRotatedWidget->adjustContentSize();
        mRotatedWidget->update();
    }
}

void LXQtClock::activated(ActivationReason reason)
{
    if (reason != ILXQtPanelPlugin::Trigger)
        return;

    if (!mCalendarPopup->isVisible())
    {
        QRect pos = calculatePopupWindowPos(mCalendarPopup->size());
        mCalendarPopup->move(pos.topLeft());
        willShowWindow(mCalendarPopup);
        mCalendarPopup->show();
    }
    else
    {
        mCalendarPopup->hide();
    }
}

QDialog * LXQtClock::configureDialog()
{
     return new LXQtClockConfiguration(settings());
}

bool LXQtClock::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == mMainWidget)
    {
        if (event->type() == QEvent::ToolTip)
            mMainWidget->setToolTip(QDateTime::currentDateTime().toString(Qt::DefaultLocaleLongDate));

        return false;
    }

    return false;
}
<commit_msg>clock: Show deprecation message on startup/add<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2010-2013 Razor team
 * Authors:
 *   Christopher "VdoP" Regali
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *   Maciej Płaza <plaza.maciej@gmail.com>
 *   Kuzma Shapran <kuzma.shapran@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

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

#include "lxqtclock.h"

#include <QDialog>
#include <QLabel>
#include <QVBoxLayout>
#include <QMouseEvent>

#include <QDateTime>
#include <QTimer>
#include <QPoint>
#include <QRect>
#include <QProxyStyle>
#include <QPainter>

#include <QDebug>
#include <LXQt/Notification>

static void notifyAboutDeprecation(PluginSettings * settings)
{
    // this is called only from LXQtClock c-tor...so just from main thread, no locking needed
    // Note: we get/store the "dont_show" in section of particular instance of clock => this is not 100% valid
    // for al possible changes of panel configuration, but we can live with this
    static bool notification_done = settings->value(QLatin1String("dont_show_deprecation"), false).toBool();
    if (!notification_done)
    {
        LXQt::Notification * notification = new LXQt::Notification{LXQtClock::tr("Date&Time (clock) plugin is deprecated")};
        notification->setBody(LXQtClock::tr("The clock plugin is deprecated and will be removed in future version of LXQt. Consider"
                    " replacing it with worldclock.
"));
        notification->setActions({LXQtClock::tr("don't show this again")});
        notification->setTimeout(5000);
        QObject::connect(notification, &LXQt::Notification::actionActivated, settings, [notification, settings] (int actionNumber) -> void
                {
                    if (actionNumber == 0)
                        settings->setValue(QLatin1String("dont_show_deprecation"), true);
                    notification->close();
                });
        QObject::connect(notification, &LXQt::Notification::notificationClosed, notification, &QObject::deleteLater);
        notification->update();
        notification_done = true;
    }
}

/**
 * @file lxqtclock.cpp
 * @brief implements LXQtclock and LXQtclockgui
 * @author Christopher "VdoP" Regali
 * @author Kuzma Shapran
 */

class DownscaleFontStyle : public QProxyStyle
{
    using QProxyStyle::QProxyStyle;
public:

    virtual void drawItemText(QPainter * painter, const QRect & rect, int flags
            , const QPalette & pal, bool enabled, const QString & text
            , QPalette::ColorRole textRole = QPalette::NoRole) const override
    {
        while (1 < painter->font().pointSize()
                && !(rect.size() - painter->fontMetrics().boundingRect(text).size()).isValid())
        {
            QFont f{painter->font()};
            f.setPointSize(f.pointSize() - 1);
            painter->setFont(f);
        }
        return QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
    }
};

/**
 * @brief constructor
 */
LXQtClock::LXQtClock(const ILXQtPanelPluginStartupInfo &startupInfo):
    QObject(),
    ILXQtPanelPlugin(startupInfo),
    mAutoRotate(true),
    mTextStyle{new DownscaleFontStyle},
    mCurrentCharCount(0)
{
    QTimer::singleShot(0, this, [this] { notifyAboutDeprecation(settings()); });

    mMainWidget = new QWidget();
    mRotatedWidget = new LXQt::RotatedWidget(*(new QWidget()), mMainWidget);
    mContent = mRotatedWidget->content();
    mContent->setStyle(mTextStyle.data());
    mTimeLabel = new QLabel(mContent);
    mDateLabel = new QLabel(mContent);

    QVBoxLayout *borderLayout = new QVBoxLayout(mMainWidget);
    borderLayout->setContentsMargins(0, 0, 0, 0);
    borderLayout->setSpacing(0);
    borderLayout->addWidget(mRotatedWidget, 0, Qt::AlignCenter);

    mTimeLabel->setObjectName("TimeLabel");
    mDateLabel->setObjectName("DateLabel");

    mTimeLabel->setAlignment(Qt::AlignCenter);
    mDateLabel->setAlignment(Qt::AlignCenter);

    mContent->setLayout(new QVBoxLayout{mContent});
    mContent->layout()->setContentsMargins(0, 0, 0, 0);
    mContent->layout()->setSpacing(0);
    mContent->layout()->addWidget(mTimeLabel);
    mContent->layout()->addWidget(mDateLabel);

    mClockTimer = new QTimer(this);
    mClockTimer->setTimerType(Qt::PreciseTimer);
    connect (mClockTimer, SIGNAL(timeout()), SLOT(updateTime()));

    mClockFormat = "hh:mm";

    mCalendarPopup = new CalendarPopup(mContent);

    mMainWidget->installEventFilter(this);
    settingsChanged();
}

/**
 * @brief destructor
 */
LXQtClock::~LXQtClock()
{
    delete mMainWidget;
}

QDateTime LXQtClock::currentDateTime()
{
    return QDateTime(mUseUTC ? QDateTime::currentDateTimeUtc() : QDateTime::currentDateTime());
}

/**
 * @brief updates the time
 * Color and font settings can be configured in Qt CSS
 */
void LXQtClock::updateTime()
{
    //XXX: do we need this with PreciseTimer ?
    if (currentDateTime().time().msec() > 500)
        restartTimer();

    showTime();
}

void LXQtClock::showTime()
{
    QDateTime now{currentDateTime()};
    int new_char_count;
    if (mDateOnNewLine)
    {
        QString new_time = QLocale::system().toString(now, mTimeFormat);
        QString new_date = QLocale::system().toString(now, mDateFormat);
        new_char_count = qMax(new_time.size(), new_date.size());
        mTimeLabel->setText(new_time);
        mDateLabel->setText(new_date);
    }
    else
    {
        QString new_time = QLocale::system().toString(now, mClockFormat);
        new_char_count = new_time.size();
        mTimeLabel->setText(new_time);
    }

    //Note: if transformation (custom rendering) is enabled we need the explicit update
    //(update doesn't cause superfluous paint events)
    mRotatedWidget->update();

    if (mCurrentCharCount != new_char_count)
    {
        mCurrentCharCount = new_char_count;
        realign();
    }
}

void LXQtClock::restartTimer()
{
    if (mClockTimer->isActive())
        mClockTimer->stop();
    int updateInterval = mClockTimer->interval();
    QDateTime now{currentDateTime()};
    int delay = updateInterval - ((now.time().msec() + now.time().second() * 1000) % updateInterval);
    QTimer::singleShot(delay, Qt::PreciseTimer, mClockTimer, SLOT(start()));
    QTimer::singleShot(delay, Qt::PreciseTimer, this, SLOT(updateTime()));
}

void LXQtClock::settingsChanged()
{
    mFirstDayOfWeek = settings()->value("firstDayOfWeek", -1).toInt();
    if (-1 == mFirstDayOfWeek)
        mCalendarPopup->setFirstDayOfWeek(QLocale::system().firstDayOfWeek());
    else
        mCalendarPopup->setFirstDayOfWeek(static_cast<Qt::DayOfWeek>(mFirstDayOfWeek));

    mTimeFormat = settings()->value("timeFormat", QLocale::system().timeFormat(QLocale::ShortFormat).toUpper().contains("AP") ? "h:mm AP" : "HH:mm").toString();

    mUseUTC = settings()->value("UTC", false).toBool();
    if (mUseUTC)
        mTimeFormat += "' Z'";

    mDateFormat = settings()->value("dateFormat", Qt::SystemLocaleShortDate).toString();

    bool dateBeforeTime = (settings()->value("showDate", "no").toString().toLower() == "before");
    bool dateAfterTime = (settings()->value("showDate", "no").toString().toLower() == "after");
    mDateOnNewLine = (settings()->value("showDate", "no").toString().toLower() == "below");

    mAutoRotate = settings()->value("autoRotate", true).toBool();

    if (dateBeforeTime)
        mClockFormat = QString("%1 %2").arg(mDateFormat).arg(mTimeFormat);
    else if (dateAfterTime)
        mClockFormat = QString("%1 %2").arg(mTimeFormat).arg(mDateFormat);
    else
        mClockFormat = mTimeFormat;

    mDateLabel->setHidden(!mDateOnNewLine);

    // mDateFormat usually does not contain time portion, but since it's possible to use custom date format - it has to be supported. [Kuzma Shapran]
    int updateInterval = QString(mTimeFormat + " " + mDateFormat).replace(QRegExp("'[^']*'"),"").contains("s") ? 1000 : 60000;

    QDateTime now = currentDateTime();

    showTime();

    if (mClockTimer->interval() != updateInterval)
    {
        mClockTimer->setInterval(updateInterval);

        restartTimer();
    }
}

void LXQtClock::realign()
{
    QSize size{QWIDGETSIZE_MAX, QWIDGETSIZE_MAX};
    Qt::Corner origin = Qt::TopLeftCorner;
    if (mAutoRotate || panel()->isHorizontal())
    {
        switch (panel()->position())
        {
        case ILXQtPanel::PositionTop:
        case ILXQtPanel::PositionBottom:
            origin = Qt::TopLeftCorner;
            break;

        case ILXQtPanel::PositionLeft:
            origin = Qt::BottomLeftCorner;
            break;

        case ILXQtPanel::PositionRight:
            origin = Qt::TopRightCorner;
            break;
        }

        //set minwidth
        QFontMetrics metrics{mTimeLabel->font()};
        //Note: using a constant string of reasonably wide characters for computing the width
        //      (not the current text as width of text can differ for each particular string (based on font))
        size.setWidth(metrics.boundingRect(QString{mCurrentCharCount, 'A'}).width());
    } else if (!panel()->isHorizontal())
    {
        size.setWidth(panel()->globalGometry().width());
    }

    mTimeLabel->setFixedWidth(size.width());
    mDateLabel->setFixedWidth(size.width());

    int label_height = mTimeLabel->sizeHint().height();
    size.setHeight(mDateOnNewLine ? label_height * 2 : label_height);

    const bool changed = mContent->maximumSize() != size || mRotatedWidget->origin() != origin;

    mContent->setFixedSize(size);
    mRotatedWidget->setOrigin(origin);

    if (changed)
    {
        mRotatedWidget->adjustContentSize();
        mRotatedWidget->update();
    }
}

void LXQtClock::activated(ActivationReason reason)
{
    if (reason != ILXQtPanelPlugin::Trigger)
        return;

    if (!mCalendarPopup->isVisible())
    {
        QRect pos = calculatePopupWindowPos(mCalendarPopup->size());
        mCalendarPopup->move(pos.topLeft());
        willShowWindow(mCalendarPopup);
        mCalendarPopup->show();
    }
    else
    {
        mCalendarPopup->hide();
    }
}

QDialog * LXQtClock::configureDialog()
{
     return new LXQtClockConfiguration(settings());
}

bool LXQtClock::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == mMainWidget)
    {
        if (event->type() == QEvent::ToolTip)
            mMainWidget->setToolTip(QDateTime::currentDateTime().toString(Qt::DefaultLocaleLongDate));

        return false;
    }

    return false;
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2014 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "ModelRenderer.h"
#include "../VisualizationException.h"
#include "../items/Item.h"

#include "ModelBase/src/nodes/Node.h"

namespace Visualization {

ModelRenderer::ModelRenderer()
{
	registerVisualizationPurpose("default_purpose");
	registerSemanticZoomLevel("default_zoom_level", 0);
}

ModelRenderer::~ModelRenderer()
{
	szLevelOrderingManager_.clear();
	visualizationGroupsManager_.clear();
	purposes_.clear();
	semanticZoomLevels_.clear();
}

Item* ModelRenderer::render(Item* parent, Model::Node* node, int purpose, int semanticZoomLevel)
{
	auto best = bestVisualizationForContext(parent, node, purpose, semanticZoomLevel);

	Item* rendered = best.second(parent, node);
	if (!parent && rendered->purpose() < 0)
		rendered->setPurpose( purpose < 0 ? 0 : purpose);
	return rendered;
}

bool ModelRenderer::sync(Item*& item, Item* parent, Model::Node* node)
{
	Q_ASSERT(parent); // If this is ever removed, make sure to set the purpose of parentless items explicitly

	if (!node)
	{
		if (item)
		{
			SAFE_DELETE_ITEM(item);
			parent->setUpdateNeeded(Item::StandardUpdate);
			return true;
		}
		else
			return false;
	}

	Q_ASSERT(node);

	auto best = bestVisualizationForContext(parent, node);

	bool changed = false;

	if (item && item->typeId() != best.first)
	{
		changed = true;
		SAFE_DELETE_ITEM(item);
	}

	if (!item)
	{
		changed = true;
		item = best.second(parent, node); // Note that we don't need to set the purpose since we have a parent
	}

	if (changed) parent->setUpdateNeeded(Item::StandardUpdate);

	Q_ASSERT(item);

	if (!changed && item->node() != node)
		item->setUpdateNeeded(Item::StandardUpdate); // Update the item, not the parent

	return changed;
}

QPair<int, VisualizationGroup::ItemConstructor> ModelRenderer::bestVisualizationForContext
(Item* parent, Model::Node* node, int purpose, int semanticZoomLevel)
{
	switch (visualizationChoiceStrategy_)
	{
	case VISUALIZATION_CHOICE_STRATEGY_TYPE_OVER_SEMANTIC_ZOOM_LEVEL_OVER_PURPOSE:
		return visualizationChoiceStrategyTypeOverSemanticZoomLevelOverPurpose(parent, node, purpose, semanticZoomLevel);
	case VISUALIZATION_CHOICE_STRATEGY_TYPE_OVER_PURPOSE_OVER_SEMANTIC_ZOOM_LEVEL:
		return visualizationChoiceStrategyTypeOverPurposeOverSemanticZoomLevel(parent, node, purpose, semanticZoomLevel);
	default:
		Q_ASSERT(false);
		return {};
	}
}

QPair<int, VisualizationGroup::ItemConstructor>
ModelRenderer::visualizationChoiceStrategyTypeOverSemanticZoomLevelOverPurpose(Item* parent, Model::Node* node,
																												 int purpose, int semanticZoomLevel)
{
	return basicStrategy(parent, node, purpose, semanticZoomLevel,
				[this] (int id, int, int semanticZoomLevel)
				 {return this->visualizationGroupsManager_.getByTypeIdAndSemanticZoomLevel(id, semanticZoomLevel); },
				[this] (int id, int purpose, int)
				 {return this->visualizationGroupsManager_.getByTypeIdAndPurpose(id, purpose); },
				[this] (int id, int, int)
				 {return this->visualizationGroupsManager_.getByTypeId(id); });
}

QPair<int, VisualizationGroup::ItemConstructor>
ModelRenderer::visualizationChoiceStrategyTypeOverPurposeOverSemanticZoomLevel(Item* parent, Model::Node* node,
																												 int purpose, int semanticZoomLevel)
{
	return basicStrategy(parent, node, purpose, semanticZoomLevel,
				[this] (int id, int purpose, int)
				 {return this->visualizationGroupsManager_.getByTypeIdAndPurpose(id, purpose); },
				[this] (int id, int, int semanticZoomLevel)
				 {return this->visualizationGroupsManager_.getByTypeIdAndSemanticZoomLevel(id, semanticZoomLevel); },
				[this] (int id, int, int)
				 {return this->visualizationGroupsManager_.getByTypeId(id); });
}

QPair<int, VisualizationGroup::ItemConstructor>
ModelRenderer::basicStrategy(Item* parent, Model::Node* node, int purpose, int semanticZoomLevel,
							std::function<QVector<VisualizationGroup*> ((int id, int purpose, int semanticZoomLevel))> option1,
							std::function<QVector<VisualizationGroup*> ((int id, int purpose, int semanticZoomLevel))> option2,
							std::function<QVector<VisualizationGroup*> ((int id, int purpose, int semanticZoomLevel))> option3)
{
	QList<int> typeIds = node->hierarchyTypeIds();

	int finalPurpose = purpose >= 0 ? purpose : (parent ? parent->childNodePurpose(node) : 0);

	if (finalPurpose >= purposes_.size())
		throw VisualizationException("Trying to render a node with an unregistered purpose id: " + finalPurpose);

	int finalSemanticZoomLevel = semanticZoomLevel >= 0 ? semanticZoomLevel :
																			(parent ? parent->childNodeSemanticZoomLevel(node) : 0);

	if (finalSemanticZoomLevel >= semanticZoomLevels_.size())
		throw VisualizationException("Trying to render a node with an unregistered semantic zoom level id: " +
											  finalSemanticZoomLevel);

	for (int id : typeIds)
	{
		QList<QPair<VisualizationSuitabilityScore, QPair<int, VisualizationGroup::ItemConstructor>>> list;

		// Try to find a match for the specific purpose and semantic zoom level
		VisualizationGroup* group = visualizationGroupsManager_.getExactMatch(id, finalPurpose, finalSemanticZoomLevel);
		if (group)
			list << group->visualizationsForContext(parent, node);

		// If there is no exact match try the first option1
		if (list.isEmpty())
		{
			QVector<VisualizationGroup*> groups = option1(id, finalPurpose, finalSemanticZoomLevel);

			if (!groups.isEmpty())
				list << groups.first()->visualizationsForContext(parent, node);
		}

		// Option1 did not work so we try option2
		if (list.isEmpty())
		{
			QVector<VisualizationGroup*> groups = option2(id, finalPurpose, finalSemanticZoomLevel);

			if (!groups.isEmpty())
				list << groups.first()->visualizationsForContext(parent, node);
		}

		// Option2 did not work so we try option3
		if (list.isEmpty())
		{
			QVector<VisualizationGroup*> groups = option3(id, finalPurpose, finalSemanticZoomLevel);

			if (!groups.isEmpty())
				list << groups.first()->visualizationsForContext(parent, node);
		}

		if (list.size() > 0)
		{
			qSort(list);
			return list.last().second;
		}
	}

	throw VisualizationException("Trying to render a node type that has no registered appropriate visualization. "
			 "The Node type is: " + node->typeName() + " The desired purpose is: " + purposes_[finalPurpose] +
			 "The desired semantic zoom level is: " + semanticZoomLevels_[finalSemanticZoomLevel]);
}

int ModelRenderer::registerVisualizationPurpose(const QString& name)
{
	if (purposes_.contains(name))
		throw VisualizationException("Trying to register a visualization purpose with a name that's already registered:"
						+ name);

	purposes_.append(name);
	return purposes_.size()-1;
}

int ModelRenderer::registerSemanticZoomLevel(const QString& name, int orderingNumber)
{
	if (semanticZoomLevels_.contains(name))
		throw VisualizationException("Trying to register a semantic zoom level with a name that's already registered:"
						+ name);

	if (szLevelOrderingManager_.hasOrderingNumber(orderingNumber))
		throw VisualizationException("Ordering number already in use: " + orderingNumber);

	semanticZoomLevels_.append(name);

	szLevelOrderingManager_.registerOrdering(semanticZoomLevelId(name), orderingNumber);

	return semanticZoomLevels_.size()-1;
}

void ModelRenderer::registerVisualization(int nodeTypeId, int purpose, int semanticZoomLevel,
		VisualizationGroup::ItemConstructor visualization, int itemTypeId)
{
	visualizationGroupsManager_.addVisualization(nodeTypeId, purpose, semanticZoomLevel, visualization, itemTypeId);
}

void ModelRenderer::registerGroup(int nodeTypeId, int purpose, int semanticZoomLevel, VisualizationGroup* group)
{
	visualizationGroupsManager_.addGroup(nodeTypeId, purpose, semanticZoomLevel, group);
}

bool ModelRenderer::hasVisualization(int nodeTypeId, int purpose, int semanticZoomLevel)
{
	return visualizationGroupsManager_.hasVisualization(nodeTypeId, purpose, semanticZoomLevel);
}

int ModelRenderer::getCoarserSemanticZoomLevel(int currentSemanticZoomLevel)
{
	return szLevelOrderingManager_.getCoarserSemanticZoomLevel(currentSemanticZoomLevel);
}

int ModelRenderer::getFinerSemanticZoomLevel(int currentSemanticZoomLevel)
{
	return szLevelOrderingManager_.getFinerSemanticZoomLevel(currentSemanticZoomLevel);
}

}
<commit_msg>Fix the synchronization for different nodes in ModelRenderer<commit_after>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2014 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "ModelRenderer.h"
#include "../VisualizationException.h"
#include "../items/Item.h"

#include "ModelBase/src/nodes/Node.h"

namespace Visualization {

ModelRenderer::ModelRenderer()
{
	registerVisualizationPurpose("default_purpose");
	registerSemanticZoomLevel("default_zoom_level", 0);
}

ModelRenderer::~ModelRenderer()
{
	szLevelOrderingManager_.clear();
	visualizationGroupsManager_.clear();
	purposes_.clear();
	semanticZoomLevels_.clear();
}

Item* ModelRenderer::render(Item* parent, Model::Node* node, int purpose, int semanticZoomLevel)
{
	auto best = bestVisualizationForContext(parent, node, purpose, semanticZoomLevel);

	Item* rendered = best.second(parent, node);
	if (!parent && rendered->purpose() < 0)
		rendered->setPurpose( purpose < 0 ? 0 : purpose);
	return rendered;
}

bool ModelRenderer::sync(Item*& item, Item* parent, Model::Node* node)
{
	Q_ASSERT(parent); // If this is ever removed, make sure to set the purpose of parentless items explicitly

	if (!node)
	{
		if (item)
		{
			SAFE_DELETE_ITEM(item);
			parent->setUpdateNeeded(Item::StandardUpdate);
			return true;
		}
		else
			return false;
	}

	Q_ASSERT(node);

	auto best = bestVisualizationForContext(parent, node);

	bool changed = false;

	if (item && ((item->node() != node) || (item->typeId() != best.first)))
	{
		changed = true;
		SAFE_DELETE_ITEM(item);
	}

	if (!item)
	{
		changed = true;
		item = best.second(parent, node); // Note that we don't need to set the purpose since we have a parent
	}

	if (changed) parent->setUpdateNeeded(Item::StandardUpdate);

	return changed;
}

QPair<int, VisualizationGroup::ItemConstructor> ModelRenderer::bestVisualizationForContext
(Item* parent, Model::Node* node, int purpose, int semanticZoomLevel)
{
	switch (visualizationChoiceStrategy_)
	{
	case VISUALIZATION_CHOICE_STRATEGY_TYPE_OVER_SEMANTIC_ZOOM_LEVEL_OVER_PURPOSE:
		return visualizationChoiceStrategyTypeOverSemanticZoomLevelOverPurpose(parent, node, purpose, semanticZoomLevel);
	case VISUALIZATION_CHOICE_STRATEGY_TYPE_OVER_PURPOSE_OVER_SEMANTIC_ZOOM_LEVEL:
		return visualizationChoiceStrategyTypeOverPurposeOverSemanticZoomLevel(parent, node, purpose, semanticZoomLevel);
	default:
		Q_ASSERT(false);
		return {};
	}
}

QPair<int, VisualizationGroup::ItemConstructor>
ModelRenderer::visualizationChoiceStrategyTypeOverSemanticZoomLevelOverPurpose(Item* parent, Model::Node* node,
																												 int purpose, int semanticZoomLevel)
{
	return basicStrategy(parent, node, purpose, semanticZoomLevel,
				[this] (int id, int, int semanticZoomLevel)
				 {return this->visualizationGroupsManager_.getByTypeIdAndSemanticZoomLevel(id, semanticZoomLevel); },
				[this] (int id, int purpose, int)
				 {return this->visualizationGroupsManager_.getByTypeIdAndPurpose(id, purpose); },
				[this] (int id, int, int)
				 {return this->visualizationGroupsManager_.getByTypeId(id); });
}

QPair<int, VisualizationGroup::ItemConstructor>
ModelRenderer::visualizationChoiceStrategyTypeOverPurposeOverSemanticZoomLevel(Item* parent, Model::Node* node,
																												 int purpose, int semanticZoomLevel)
{
	return basicStrategy(parent, node, purpose, semanticZoomLevel,
				[this] (int id, int purpose, int)
				 {return this->visualizationGroupsManager_.getByTypeIdAndPurpose(id, purpose); },
				[this] (int id, int, int semanticZoomLevel)
				 {return this->visualizationGroupsManager_.getByTypeIdAndSemanticZoomLevel(id, semanticZoomLevel); },
				[this] (int id, int, int)
				 {return this->visualizationGroupsManager_.getByTypeId(id); });
}

QPair<int, VisualizationGroup::ItemConstructor>
ModelRenderer::basicStrategy(Item* parent, Model::Node* node, int purpose, int semanticZoomLevel,
							std::function<QVector<VisualizationGroup*> ((int id, int purpose, int semanticZoomLevel))> option1,
							std::function<QVector<VisualizationGroup*> ((int id, int purpose, int semanticZoomLevel))> option2,
							std::function<QVector<VisualizationGroup*> ((int id, int purpose, int semanticZoomLevel))> option3)
{
	QList<int> typeIds = node->hierarchyTypeIds();

	int finalPurpose = purpose >= 0 ? purpose : (parent ? parent->childNodePurpose(node) : 0);

	if (finalPurpose >= purposes_.size())
		throw VisualizationException("Trying to render a node with an unregistered purpose id: " + finalPurpose);

	int finalSemanticZoomLevel = semanticZoomLevel >= 0 ? semanticZoomLevel :
																			(parent ? parent->childNodeSemanticZoomLevel(node) : 0);

	if (finalSemanticZoomLevel >= semanticZoomLevels_.size())
		throw VisualizationException("Trying to render a node with an unregistered semantic zoom level id: " +
											  finalSemanticZoomLevel);

	for (int id : typeIds)
	{
		QList<QPair<VisualizationSuitabilityScore, QPair<int, VisualizationGroup::ItemConstructor>>> list;

		// Try to find a match for the specific purpose and semantic zoom level
		VisualizationGroup* group = visualizationGroupsManager_.getExactMatch(id, finalPurpose, finalSemanticZoomLevel);
		if (group)
			list << group->visualizationsForContext(parent, node);

		// If there is no exact match try the first option1
		if (list.isEmpty())
		{
			QVector<VisualizationGroup*> groups = option1(id, finalPurpose, finalSemanticZoomLevel);

			if (!groups.isEmpty())
				list << groups.first()->visualizationsForContext(parent, node);
		}

		// Option1 did not work so we try option2
		if (list.isEmpty())
		{
			QVector<VisualizationGroup*> groups = option2(id, finalPurpose, finalSemanticZoomLevel);

			if (!groups.isEmpty())
				list << groups.first()->visualizationsForContext(parent, node);
		}

		// Option2 did not work so we try option3
		if (list.isEmpty())
		{
			QVector<VisualizationGroup*> groups = option3(id, finalPurpose, finalSemanticZoomLevel);

			if (!groups.isEmpty())
				list << groups.first()->visualizationsForContext(parent, node);
		}

		if (list.size() > 0)
		{
			qSort(list);
			return list.last().second;
		}
	}

	throw VisualizationException("Trying to render a node type that has no registered appropriate visualization. "
			 "The Node type is: " + node->typeName() + " The desired purpose is: " + purposes_[finalPurpose] +
			 "The desired semantic zoom level is: " + semanticZoomLevels_[finalSemanticZoomLevel]);
}

int ModelRenderer::registerVisualizationPurpose(const QString& name)
{
	if (purposes_.contains(name))
		throw VisualizationException("Trying to register a visualization purpose with a name that's already registered:"
						+ name);

	purposes_.append(name);
	return purposes_.size()-1;
}

int ModelRenderer::registerSemanticZoomLevel(const QString& name, int orderingNumber)
{
	if (semanticZoomLevels_.contains(name))
		throw VisualizationException("Trying to register a semantic zoom level with a name that's already registered:"
						+ name);

	if (szLevelOrderingManager_.hasOrderingNumber(orderingNumber))
		throw VisualizationException("Ordering number already in use: " + orderingNumber);

	semanticZoomLevels_.append(name);

	szLevelOrderingManager_.registerOrdering(semanticZoomLevelId(name), orderingNumber);

	return semanticZoomLevels_.size()-1;
}

void ModelRenderer::registerVisualization(int nodeTypeId, int purpose, int semanticZoomLevel,
		VisualizationGroup::ItemConstructor visualization, int itemTypeId)
{
	visualizationGroupsManager_.addVisualization(nodeTypeId, purpose, semanticZoomLevel, visualization, itemTypeId);
}

void ModelRenderer::registerGroup(int nodeTypeId, int purpose, int semanticZoomLevel, VisualizationGroup* group)
{
	visualizationGroupsManager_.addGroup(nodeTypeId, purpose, semanticZoomLevel, group);
}

bool ModelRenderer::hasVisualization(int nodeTypeId, int purpose, int semanticZoomLevel)
{
	return visualizationGroupsManager_.hasVisualization(nodeTypeId, purpose, semanticZoomLevel);
}

int ModelRenderer::getCoarserSemanticZoomLevel(int currentSemanticZoomLevel)
{
	return szLevelOrderingManager_.getCoarserSemanticZoomLevel(currentSemanticZoomLevel);
}

int ModelRenderer::getFinerSemanticZoomLevel(int currentSemanticZoomLevel)
{
	return szLevelOrderingManager_.getFinerSemanticZoomLevel(currentSemanticZoomLevel);
}

}
<|endoftext|>


<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                */
/**************************************************************************************/

#if !defined(ioDICOM_INCLUDE_ONCE)
#define ioDICOM_INCLUDE_ONCE

#include <vlCore/ResourceLoadWriter.hpp>
#include <vlCore/ResourceDatabase.hpp>
#include <vlCore/Image.hpp>

namespace vl
{
  class VirtualFile;
  class String;

  //! Loads a DICOM file.
  ref<Image> loadDICOM(VirtualFile* file);
  //! Loads a DICOM file.
  ref<Image> loadDICOM(const String& path);
  //! Writes a DICOM file.
  bool saveDICOM(const Image* src, const String& path);
  //! Writes a DICOM file.
  bool saveDICOM(const Image* src, VirtualFile* file);
  //! Checks if the given file is a DICOM file.
  bool isDICOM(VirtualFile* file);

  //---------------------------------------------------------------------------
  // LoadWriterDICOM
  //---------------------------------------------------------------------------
  /**
   * The LoadWriterDICOM class is a ResourceLoadWriter capable of reading DICOM files.
   */
  class LoadWriterDICOM: public ResourceLoadWriter
  {
  public:
    virtual const char* className() { return "LoadWriterDICOM"; }
    LoadWriterDICOM(): ResourceLoadWriter("|dcm|dicom|dic|ima|ph|mag|", "|dcm|dicom|dic|ima|ph|mag|") {}

    ref<ResourceDatabase> loadResource(const String& path) const
    {
      ref<ResourceDatabase> res_db = new ResourceDatabase;
      ref<Image> img = loadDICOM(path);
      if (img)
        res_db->resources().push_back(img);
      return res_db;
    }

    ref<ResourceDatabase> loadResource(VirtualFile* file) const
    {
      ref<ResourceDatabase> res_db = new ResourceDatabase;
      ref<Image> img = loadDICOM(file);
      if (img)
        res_db->resources().push_back(img);
      return res_db;
    }

    bool writeResource(const String&, ResourceDatabase*) const
    {
      return false;
    }

    bool writeResource(VirtualFile*, ResourceDatabase*) const
    {
      return false;
    }
  };
}

#endif

<commit_msg>GDCM module docs update.<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                */
/**************************************************************************************/

#if !defined(ioDICOM_INCLUDE_ONCE)
#define ioDICOM_INCLUDE_ONCE

#include <vlCore/ResourceLoadWriter.hpp>
#include <vlCore/ResourceDatabase.hpp>
#include <vlCore/Image.hpp>

namespace vl
{
  class VirtualFile;
  class String;

  //! Loads a DICOM file.
  ref<Image> loadDICOM(VirtualFile* file);
  //! Loads a DICOM file.
  ref<Image> loadDICOM(const String& path);
  //! Writes a DICOM file.
  bool saveDICOM(const Image* src, const String& path);
  //! Writes a DICOM file.
  bool saveDICOM(const Image* src, VirtualFile* file);
  //! Checks if the given file is a DICOM file.
  bool isDICOM(VirtualFile* file);

  //---------------------------------------------------------------------------
  // LoadWriterDICOM
  //---------------------------------------------------------------------------
  /** The LoadWriterDICOM class is a ResourceLoadWriter capable of reading DICOM files (.dcm, .dicom, .dic, .ima, .ph, .mag) using GDCM 2.0 library.
  \sa GDCM home page: http://creatis-www.insa-lyon.fr/software/public/Gdcm/Main.html */
  class LoadWriterDICOM: public ResourceLoadWriter
  {
  public:
    virtual const char* className() { return "LoadWriterDICOM"; }

    LoadWriterDICOM(): ResourceLoadWriter("|dcm|dicom|dic|ima|ph|mag|", "|dcm|dicom|dic|ima|ph|mag|") {}

    ref<ResourceDatabase> loadResource(const String& path) const
    {
      ref<ResourceDatabase> res_db = new ResourceDatabase;
      ref<Image> img = loadDICOM(path);
      if (img)
        res_db->resources().push_back(img);
      return res_db;
    }

    ref<ResourceDatabase> loadResource(VirtualFile* file) const
    {
      ref<ResourceDatabase> res_db = new ResourceDatabase;
      ref<Image> img = loadDICOM(file);
      if (img)
        res_db->resources().push_back(img);
      return res_db;
    }

    bool writeResource(const String&, ResourceDatabase*) const
    {
      return false;
    }

    bool writeResource(VirtualFile*, ResourceDatabase*) const
    {
      return false;
    }
  };
}

#endif

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "s60videoplayersession.h"

#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>

#include <coemain.h>    // For CCoeEnv
#include <coecntrl.h>
#include <w32std.h>

#include <QWidget>
#include <QDir>

#include <mmf/common/mmfcontrollerframeworkbase.h>

S60VideoPlayerSession::S60VideoPlayerSession(QObject *parent)
    : S60MediaPlayerSession(parent),
      m_wsSession(0),
      m_screenDevice(0),
      m_window(0),
      m_numberOfMetaDataEntries(0)
{
    m_frameSize = QSize(320,240);
}

S60VideoPlayerSession::~S60VideoPlayerSession()
{
    delete m_player;
}

void S60VideoPlayerSession::load(const QUrl &url)
{
    m_url = url.toLocalFile();
    QString fileName = QDir::toNativeSeparators(m_url.toString());
    TPtrC str(reinterpret_cast<const TUint16*>(fileName.utf16()));
    m_player->OpenFileL(str);
    qDebug() << m_url;
}

qint64 S60VideoPlayerSession::duration() const
{
    return  m_player->DurationL().Int64() / 1000;
}

qint64 S60VideoPlayerSession::position() const
{
    return m_player->PositionL().Int64() / 1000;
}

qreal S60VideoPlayerSession::playbackRate() const
{
    return m_playbackRate;
}

void S60VideoPlayerSession::setPlaybackRate(qreal rate)
{
    //TODO: videoplayrate set but not used.
    m_playbackRate = rate;
}

bool S60VideoPlayerSession::isBuffering() const
{
    return false;
}

int S60VideoPlayerSession::bufferingProgress() const
{
    return 0;
}

int S60VideoPlayerSession::volume() const
{
    return m_volume;
}

bool S60VideoPlayerSession::isMuted() const
{
    return m_muted;
}

void S60VideoPlayerSession::setVideoRenderer(QObject *videoOutput)
{
    m_testWidget = qobject_cast<S60VideoWidgetControl*>(videoOutput);

    const TInt priority = 0;
    const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;

    getNativeHandles();

    TRAPD(err,
        m_player = CVideoPlayerUtility::NewL(*this,
                                  priority,
                                  preference,
                                  *m_wsSession,
                                  *m_screenDevice,
                                  *m_window,
                                  m_windowRect,
                                  m_clipRect)
         );
    // TODO: m_player->SetDisplayWindowL();
}

void S60VideoPlayerSession::getNativeHandles()
{
    CCoeControl* const control =  m_testWidget->videoWidget()->winId();
    control->MakeVisible(ETrue);
    qDebug() << "h: " << m_testWidget->videoWidget()->winId()->Size().iHeight <<  "v: " << m_testWidget->videoWidget()->winId()->Size().iWidth;
    qDebug() << "h: " << m_testWidget->videoWidget()->winId()->Size().iHeight <<  "v: " << m_testWidget->videoWidget()->winId()->Size().iWidth;
    //control->SetSize(TSize(240,245));
    //control->SetPosition(TPoint(0,-50));
    qDebug() << "x: " <<control->Position().iX  << "y: " << control->Position().iY;
    control->ActivateL();

    CCoeEnv* const coeEnv = control->ControlEnv();
    m_wsSession = &(coeEnv->WsSession());
    m_screenDevice = coeEnv->ScreenDevice();
    m_window = control->DrawableWindow();

    m_windowRect = TRect(
        control->DrawableWindow()->AbsPosition(),
        control->DrawableWindow()->Size());
    m_clipRect = m_windowRect;

    qDebug() << "h: " << m_clipRect.Height() << "w: " << m_clipRect.Width();
}

bool S60VideoPlayerSession::isVideoAvailable() const
{
    return m_videoAvailable;
}

bool S60VideoPlayerSession::isSeekable() const
{
    return m_seekable;
}

void S60VideoPlayerSession::play()
{
    startTimer();
    m_player->Play();
    m_state = QMediaPlayer::PlayingState;
    emit stateChanged(QMediaPlayer::PlayingState);
}

void S60VideoPlayerSession::pause()
{
    m_player->PauseL();
    m_state = QMediaPlayer::PausedState;
    emit stateChanged(QMediaPlayer::PausedState);
}

void S60VideoPlayerSession::stop()
{
    m_player->Stop();
    m_state = QMediaPlayer::StoppedState;
    emit stateChanged(QMediaPlayer::StoppedState);
}

void S60VideoPlayerSession::seek(qint64 ms)
{
    m_player->PauseL();
    m_player->SetPositionL(ms*1000);
    m_player->Play();
    emit positionChanged(position());
}

void S60VideoPlayerSession::setVolume(int volume)
{
    m_player->SetVolumeL(volume);
}

void S60VideoPlayerSession::setMuted(bool muted)
{
    if (muted)
        m_player->SetVolumeL(0);
}

void S60VideoPlayerSession::setMediaStatus(QMediaPlayer::MediaStatus status)
{
    if (m_mediaStatus != status) {
        m_mediaStatus = status;
        emit mediaStatusChanged(status);
    }
}

void S60VideoPlayerSession::MvpuoOpenComplete(TInt aError)
{
    m_player->Prepare();
}

void S60VideoPlayerSession::MvpuoPrepareComplete(TInt aError)
{
    m_metaDataMap.clear();
    m_numberOfMetaDataEntries = 0;
    TRAP_IGNORE(m_numberOfMetaDataEntries = m_player->NumberOfMetaDataEntriesL();)

    for (int i=0; i < m_numberOfMetaDataEntries; i++) {
        CMMFMetaDataEntry *entry;
        TRAPD(err, entry = m_player->MetaDataEntryL(i));

        if (err == KErrNone) {
            m_metaDataMap.insert(QString::fromUtf16(entry->Name().Ptr(), entry->Name().Length()), QString::fromUtf16(entry->Value().Ptr(), entry->Value().Length()));
        }
        delete entry;
        entry = NULL;
    }

    emit metaDataChanged();
}

void S60VideoPlayerSession::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
{
    Q_UNUSED(aFrame);
    Q_UNUSED(aError);
}

void S60VideoPlayerSession::MvpuoPlayComplete(TInt aError)
{
    m_state = QMediaPlayer::StoppedState;
    emit stateChanged(QMediaPlayer::StoppedState);
    emit positionChanged(position());
}

void S60VideoPlayerSession::MvpuoEvent(const TMMFEvent &aEvent)
{
    Q_UNUSED(aEvent);
}

bool S60VideoPlayerSession::isMetadataAvailable() const
{
    return (m_numberOfMetaDataEntries > 0);
}

QVariant S60VideoPlayerSession::metaData(const QString& key) const
{
    return m_metaDataMap.value(key);
}
<commit_msg>durationChanged() signal emitted<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "s60videoplayersession.h"

#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>

#include <coemain.h>    // For CCoeEnv
#include <coecntrl.h>
#include <w32std.h>

#include <QWidget>
#include <QDir>

#include <mmf/common/mmfcontrollerframeworkbase.h>

S60VideoPlayerSession::S60VideoPlayerSession(QObject *parent)
    : S60MediaPlayerSession(parent),
      m_wsSession(0),
      m_screenDevice(0),
      m_window(0),
      m_numberOfMetaDataEntries(0)
{
    m_frameSize = QSize(320,240);
}

S60VideoPlayerSession::~S60VideoPlayerSession()
{
    delete m_player;
}

void S60VideoPlayerSession::load(const QUrl &url)
{
    m_url = url.toLocalFile();
    QString fileName = QDir::toNativeSeparators(m_url.toString());
    TPtrC str(reinterpret_cast<const TUint16*>(fileName.utf16()));
    m_player->OpenFileL(str);
    qDebug() << m_url;
}

qint64 S60VideoPlayerSession::duration() const
{
    return  m_player->DurationL().Int64() / 1000;
}

qint64 S60VideoPlayerSession::position() const
{
    return m_player->PositionL().Int64() / 1000;
}

qreal S60VideoPlayerSession::playbackRate() const
{
    return m_playbackRate;
}

void S60VideoPlayerSession::setPlaybackRate(qreal rate)
{
    //TODO: videoplayrate set but not used.
    m_playbackRate = rate;
}

bool S60VideoPlayerSession::isBuffering() const
{
    return false;
}

int S60VideoPlayerSession::bufferingProgress() const
{
    return 0;
}

int S60VideoPlayerSession::volume() const
{
    return m_volume;
}

bool S60VideoPlayerSession::isMuted() const
{
    return m_muted;
}

void S60VideoPlayerSession::setVideoRenderer(QObject *videoOutput)
{
    m_testWidget = qobject_cast<S60VideoWidgetControl*>(videoOutput);

    const TInt priority = 0;
    const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;

    getNativeHandles();

    TRAPD(err,
        m_player = CVideoPlayerUtility::NewL(*this,
                                  priority,
                                  preference,
                                  *m_wsSession,
                                  *m_screenDevice,
                                  *m_window,
                                  m_windowRect,
                                  m_clipRect)
         );
    // TODO: m_player->SetDisplayWindowL();
}

void S60VideoPlayerSession::getNativeHandles()
{
    CCoeControl* const control =  m_testWidget->videoWidget()->winId();
    control->MakeVisible(ETrue);
    qDebug() << "h: " << m_testWidget->videoWidget()->winId()->Size().iHeight <<  "v: " << m_testWidget->videoWidget()->winId()->Size().iWidth;
    qDebug() << "h: " << m_testWidget->videoWidget()->winId()->Size().iHeight <<  "v: " << m_testWidget->videoWidget()->winId()->Size().iWidth;
    //control->SetSize(TSize(240,245));
    //control->SetPosition(TPoint(0,-50));
    qDebug() << "x: " <<control->Position().iX  << "y: " << control->Position().iY;
    control->ActivateL();

    CCoeEnv* const coeEnv = control->ControlEnv();
    m_wsSession = &(coeEnv->WsSession());
    m_screenDevice = coeEnv->ScreenDevice();
    m_window = control->DrawableWindow();

    m_windowRect = TRect(
        control->DrawableWindow()->AbsPosition(),
        control->DrawableWindow()->Size());
    m_clipRect = m_windowRect;

    qDebug() << "h: " << m_clipRect.Height() << "w: " << m_clipRect.Width();
}

bool S60VideoPlayerSession::isVideoAvailable() const
{
    return m_videoAvailable;
}

bool S60VideoPlayerSession::isSeekable() const
{
    return m_seekable;
}

void S60VideoPlayerSession::play()
{
    startTimer();
    m_player->Play();
    m_state = QMediaPlayer::PlayingState;
    emit stateChanged(QMediaPlayer::PlayingState);
}

void S60VideoPlayerSession::pause()
{
    m_player->PauseL();
    m_state = QMediaPlayer::PausedState;
    emit stateChanged(QMediaPlayer::PausedState);
}

void S60VideoPlayerSession::stop()
{
    m_player->Stop();
    m_state = QMediaPlayer::StoppedState;
    emit stateChanged(QMediaPlayer::StoppedState);
}

void S60VideoPlayerSession::seek(qint64 ms)
{
    m_player->PauseL();
    m_player->SetPositionL(ms*1000);
    m_player->Play();
    emit positionChanged(position());
}

void S60VideoPlayerSession::setVolume(int volume)
{
    m_player->SetVolumeL(volume);
}

void S60VideoPlayerSession::setMuted(bool muted)
{
    if (muted)
        m_player->SetVolumeL(0);
}

void S60VideoPlayerSession::setMediaStatus(QMediaPlayer::MediaStatus status)
{
    if (m_mediaStatus != status) {
        m_mediaStatus = status;
        emit mediaStatusChanged(status);
    }
}

void S60VideoPlayerSession::MvpuoOpenComplete(TInt aError)
{
    m_player->Prepare();
}

void S60VideoPlayerSession::MvpuoPrepareComplete(TInt aError)
{
    m_metaDataMap.clear();
    m_numberOfMetaDataEntries = 0;
    TRAP_IGNORE(m_numberOfMetaDataEntries = m_player->NumberOfMetaDataEntriesL();)

    for (int i=0; i < m_numberOfMetaDataEntries; i++) {
        CMMFMetaDataEntry *entry;
        TRAPD(err, entry = m_player->MetaDataEntryL(i));

        if (err == KErrNone) {
            m_metaDataMap.insert(QString::fromUtf16(entry->Name().Ptr(), entry->Name().Length()), QString::fromUtf16(entry->Value().Ptr(), entry->Value().Length()));
        }
        delete entry;
        entry = NULL;
    }

    emit durationChanged(duration());
    emit metaDataChanged();
}

void S60VideoPlayerSession::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
{
    Q_UNUSED(aFrame);
    Q_UNUSED(aError);
}

void S60VideoPlayerSession::MvpuoPlayComplete(TInt aError)
{
    stopTimer();
    m_state = QMediaPlayer::StoppedState;
    emit stateChanged(QMediaPlayer::StoppedState);
    emit positionChanged(position());
}

void S60VideoPlayerSession::MvpuoEvent(const TMMFEvent &aEvent)
{
    Q_UNUSED(aEvent);
}

bool S60VideoPlayerSession::isMetadataAvailable() const
{
    return (m_numberOfMetaDataEntries > 0);
}

QVariant S60VideoPlayerSession::metaData(const QString& key) const
{
    return m_metaDataMap.value(key);
}
<|endoftext|>


<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2015, University of Colorado, Boulder
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the Univ of CO, Boulder nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/* Author: Dave Coleman <dave@dav.ee>
   Desc:   Generate a random trajectory to test the ros_control controller
*/

// ROS
#include <ros/ros.h>
#include <control_msgs/FollowJointTrajectoryAction.h>
#include <trajectory_msgs/JointTrajectory.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>

namespace ros_control_boilerplate
{
static const double SEC_PER_TRAJ_POINT = 5.0;  // time between points
static const std::size_t TRAJ_POINTS = 10;     // number of points to generate

class TestTrajectory
{
public:
  /**
   * \brief Constructor
   */
  TestTrajectory()
    : nh_private_("~")
  {
    std::string action_topic;
    nh_private_.getParam("action_topic", action_topic);
    if (action_topic.empty())
    {
      ROS_FATAL_STREAM_NAMED(
          "test_trajectory",
          "Not follow joint trajectory action topic found on the parameter server");
      exit(-1);
    }
    ROS_INFO_STREAM_NAMED("test_trajectory", "Connecting to action " << action_topic);

    // create the action client
    // true causes the client to spin its own thread
    actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> action_client(
        action_topic, true);

    ROS_INFO_NAMED("test_trajetory", "Waiting for action server to start.");
    // wait for the action server to start
    action_client.waitForServer();  // will wait for infinite time

    ROS_INFO_NAMED("test_trajetory", "Action server started, sending goal.");

    // send a goal to the action
    control_msgs::FollowJointTrajectoryGoal goal;
    goal.trajectory = createTrajectory();
    std::cout << "Trajectory:\n" << goal.trajectory << std::endl;
    action_client.sendGoal(goal);

    // Wait for the action to return
    double wait_extra_padding = 2;  // time to wait longer than trajectory itself
    bool finished_before_timeout = action_client.waitForResult(
        ros::Duration(goal.trajectory.points.back().time_from_start.toSec() + wait_extra_padding));

    if (finished_before_timeout)
    {
      actionlib::SimpleClientGoalState state = action_client.getState();
      ROS_INFO_NAMED("test_trajetory", "Action finished: %s", state.toString().c_str());
    }
    else
      ROS_INFO_NAMED("test_trajetory", "Action did not finish before the time out.");

    ROS_INFO_STREAM_NAMED("test_trajectory", "TestTrajectory Finished");
  }

  /**
   * \brief Create random trajectory
   */
  trajectory_msgs::JointTrajectory createTrajectory()
  {
    std::vector<std::string> joint_names;
    double min_joint_value = -3.14;
    double max_joint_value = 3.14;

    // Get joint names
    nh_private_.getParam("hardware_interface/joints", joint_names);
    if (joint_names.size() == 0)
    {
      ROS_FATAL_STREAM_NAMED(
          "init",
          "Not joints found on parameter server for controller, did you load the proper yaml file?"
              << " Namespace: " << nh_private_.getNamespace() << "/hardware_interface/joints");
      exit(-1);
    }

    nh_private_.getParam("min_joint_value", min_joint_value);
    nh_private_.getParam("max_joint_value", max_joint_value);
    ROS_DEBUG_STREAM_NAMED("test_trajectory", "Creating trajectory with joint values from "
                                                  << min_joint_value << " to " << max_joint_value);

    // Create header
    trajectory_msgs::JointTrajectory trajectory;
    trajectory.header.stamp = ros::Time::now();
    trajectory.joint_names = joint_names;

    // Create trajectory with x points
    trajectory.points.resize(TRAJ_POINTS);
    for (std::size_t i = 0; i < TRAJ_POINTS; ++i)
    {
      trajectory.points[i].positions.resize(joint_names.size());
      // for each joint
      for (std::size_t j = 0; j < joint_names.size(); ++j)
      {
        trajectory.points[i].positions[j] = dRand(min_joint_value, max_joint_value);
        trajectory.points[i].time_from_start = ros::Duration(i * SEC_PER_TRAJ_POINT);
      }
    }

    return trajectory;
  }

  /** \brief Get random number */
  double dRand(double dMin, double dMax)
  {
    double d = (double)rand() / RAND_MAX;
    return dMin + d * (dMax - dMin);
  }

private:
  // A shared node handle
  ros::NodeHandle nh_private_;

};  // end class

// Create boost pointers for this class
typedef boost::shared_ptr<TestTrajectory> TestTrajectoryPtr;
typedef boost::shared_ptr<const TestTrajectory> TestTrajectoryConstPtr;

}  // end namespace

int main(int argc, char** argv)
{
  ros::init(argc, argv, "test_trajectory");
  ROS_INFO_STREAM_NAMED("test_trajectory", "Starting TestTrajectory...");

  // Allow the action server to recieve and send ros messages
  ros::AsyncSpinner spinner(2);
  spinner.start();

  ros_control_boilerplate::TestTrajectory server;

  ROS_INFO_STREAM_NAMED("test_trajectory", "Shutting down.");
  ros::shutdown();

  return 0;
}
<commit_msg>Delete test_trajectory.cpp<commit_after><|endoftext|>