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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkSimpleExampleFunctionality.h"
#include "QmitkSimpleExampleControls.h"

#include <qaction.h>
#include "slicer.xpm"

// for slice-navigation
#include <mitkEventMapper.h>
#include <mitkGlobalInteraction.h>
#include <mitkBaseRenderer.h>
#include "QmitkRenderWindow.h"
#include "QmitkSelectableGLWidget.h"
#include "QmitkStdMultiWidget.h"
#include <QmitkStepperAdapter.h>
#include "qpushbutton.h"

// for stereo setting
#include <mitkOpenGLRenderer.h>
#include <mitkVtkRenderWindow.h>
#include <vtkRenderWindow.h>

// for zoom/pan
#include <mitkDisplayCoordinateOperation.h>
#include <mitkDisplayVectorInteractor.h>
#include <mitkDisplayInteractor.h>
#include <mitkInteractionConst.h>

QmitkSimpleExampleFunctionality::QmitkSimpleExampleFunctionality(QObject *parent, const char *name, QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it) : QmitkFunctionality(parent, name, it) ,
controls(NULL), multiWidget(mitkStdMultiWidget), m_NavigatorsInitialized(false)
{
    setAvailability(true);
}

QmitkSimpleExampleFunctionality::~QmitkSimpleExampleFunctionality()
{
//  delete moveNzoom;
}

QWidget * QmitkSimpleExampleFunctionality::createMainWidget(QWidget *parent)
{
    QWidget *result = NULL;

    if (multiWidget == NULL)
    {
        multiWidget = new QmitkStdMultiWidget(parent);
        result = multiWidget;
    }
    else
    {
        result = NULL;
    }

    mitk::GlobalInteraction* globalInteraction = dynamic_cast<mitk::GlobalInteraction*>(mitk::EventMapper::GetGlobalStateMachine());
    if(globalInteraction!=NULL)
    {
      globalInteraction->AddListener(multiWidget->GetMoveAndZoomInteractor() );//sends DisplayCoordinateOperation
    }

    return result;
}

QWidget * QmitkSimpleExampleFunctionality::createControlWidget(QWidget *parent)
{
    if (controls == NULL)
    {
        controls = new QmitkSimpleExampleControls(parent);
        new QmitkStepperAdapter(controls->getSliceNavigatorTransversal(), multiWidget->mitkWidget1->GetSliceNavigationController()->GetSlice(), "sliceNavigatorTransversalFromSimpleExample");
        new QmitkStepperAdapter(controls->getSliceNavigatorSagittal(), multiWidget->mitkWidget2->GetSliceNavigationController()->GetSlice(), "sliceNavigatorSagittalFromSimpleExample");
        new QmitkStepperAdapter(controls->getSliceNavigatorFrontal(), multiWidget->mitkWidget3->GetSliceNavigationController()->GetSlice(), "sliceNavigatorFrontalFromSimpleExample");
        new QmitkStepperAdapter(controls->getSliceNavigatorTime(), multiWidget->GetTimeNavigationController()->GetTime(), "sliceNavigatorTimeFromSimpleExample");
        new QmitkStepperAdapter(controls->getMovieNavigatorTime(), multiWidget->GetTimeNavigationController()->GetTime(), "movieNavigatorTimeFromSimpleExample");

        mitk::GlobalInteraction* globalInteraction = dynamic_cast<mitk::GlobalInteraction*>(mitk::EventMapper::GetGlobalStateMachine());
        if(globalInteraction!=NULL)
        {
          globalInteraction->AddListener(multiWidget->GetMultiplexUpdateController());
        }
    }
    return controls;
}

void QmitkSimpleExampleFunctionality::createConnections()
{
  if ( controls )
  {
    connect(controls->getStereoSelect(), SIGNAL(activated(int)), this, SLOT(stereoSelectionChanged(int)) );
    connect(controls->getReInitializeNavigatorsButton(), SIGNAL(clicked()), this, SLOT(initNavigators()) );
  }
}

QAction * QmitkSimpleExampleFunctionality::createAction(QActionGroup *parent)
{
    QAction* action;
    action = new QAction( tr( "Left" ), QPixmap((const char**)slicer_xpm), tr( "&Left" ), CTRL + Key_L, parent, "simple example" );
    return action;
}

void QmitkSimpleExampleFunctionality::initNavigators()
{
  m_NavigatorsInitialized = multiWidget->InitializeStandardViews(m_DataTreeIterator.GetPointer());
}

void QmitkSimpleExampleFunctionality::treeChanged()
{
  if(m_NavigatorsInitialized==false)
    initNavigators();
}

void QmitkSimpleExampleFunctionality::activated()
{
  QmitkFunctionality::activated();
  assert( multiWidget != NULL );
  // init widget 4 as a 3D widget
  multiWidget->mitkWidget4->GetRenderer()->SetMapperID(2);

  if(m_NavigatorsInitialized)
  {
    multiWidget->ReInitializeStandardViews();
  }
}

void QmitkSimpleExampleFunctionality::stereoSelectionChanged( int id )
{
  vtkRenderWindow * vtkrenderwindow =
    ((mitk::OpenGLRenderer*)(multiWidget->mitkWidget4->GetRenderer()))->GetVtkRenderWindow();
  switch(id)
  {
  case 0:
    vtkrenderwindow->StereoRenderOff();
    break;
  case 1:
    vtkrenderwindow->SetStereoTypeToRedBlue();
    vtkrenderwindow->StereoRenderOn();
    break;
  case 2:
    vtkrenderwindow->SetStereoTypeToDresden();
    vtkrenderwindow->StereoRenderOn();
    break;
  }
  multiWidget->mitkWidget4->GetRenderer()->SetMapperID(2);
  multiWidget->mitkWidget4->GetRenderer()->GetRenderWindow()->Repaint();
}
<commit_msg>ENH: better tooltip text<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkSimpleExampleFunctionality.h"
#include "QmitkSimpleExampleControls.h"

#include <qaction.h>
#include "slicer.xpm"

// for slice-navigation
#include <mitkEventMapper.h>
#include <mitkGlobalInteraction.h>
#include <mitkBaseRenderer.h>
#include "QmitkRenderWindow.h"
#include "QmitkSelectableGLWidget.h"
#include "QmitkStdMultiWidget.h"
#include <QmitkStepperAdapter.h>
#include "qpushbutton.h"

// for stereo setting
#include <mitkOpenGLRenderer.h>
#include <mitkVtkRenderWindow.h>
#include <vtkRenderWindow.h>

// for zoom/pan
#include <mitkDisplayCoordinateOperation.h>
#include <mitkDisplayVectorInteractor.h>
#include <mitkDisplayInteractor.h>
#include <mitkInteractionConst.h>

QmitkSimpleExampleFunctionality::QmitkSimpleExampleFunctionality(QObject *parent, const char *name, QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it) : QmitkFunctionality(parent, name, it) ,
controls(NULL), multiWidget(mitkStdMultiWidget), m_NavigatorsInitialized(false)
{
    setAvailability(true);
}

QmitkSimpleExampleFunctionality::~QmitkSimpleExampleFunctionality()
{
//  delete moveNzoom;
}

QWidget * QmitkSimpleExampleFunctionality::createMainWidget(QWidget *parent)
{
    QWidget *result = NULL;

    if (multiWidget == NULL)
    {
        multiWidget = new QmitkStdMultiWidget(parent);
        result = multiWidget;
    }
    else
    {
        result = NULL;
    }

    mitk::GlobalInteraction* globalInteraction = dynamic_cast<mitk::GlobalInteraction*>(mitk::EventMapper::GetGlobalStateMachine());
    if(globalInteraction!=NULL)
    {
      globalInteraction->AddListener(multiWidget->GetMoveAndZoomInteractor() );//sends DisplayCoordinateOperation
    }

    return result;
}

QWidget * QmitkSimpleExampleFunctionality::createControlWidget(QWidget *parent)
{
    if (controls == NULL)
    {
        controls = new QmitkSimpleExampleControls(parent);
        new QmitkStepperAdapter(controls->getSliceNavigatorTransversal(), multiWidget->mitkWidget1->GetSliceNavigationController()->GetSlice(), "sliceNavigatorTransversalFromSimpleExample");
        new QmitkStepperAdapter(controls->getSliceNavigatorSagittal(), multiWidget->mitkWidget2->GetSliceNavigationController()->GetSlice(), "sliceNavigatorSagittalFromSimpleExample");
        new QmitkStepperAdapter(controls->getSliceNavigatorFrontal(), multiWidget->mitkWidget3->GetSliceNavigationController()->GetSlice(), "sliceNavigatorFrontalFromSimpleExample");
        new QmitkStepperAdapter(controls->getSliceNavigatorTime(), multiWidget->GetTimeNavigationController()->GetTime(), "sliceNavigatorTimeFromSimpleExample");
        new QmitkStepperAdapter(controls->getMovieNavigatorTime(), multiWidget->GetTimeNavigationController()->GetTime(), "movieNavigatorTimeFromSimpleExample");

        mitk::GlobalInteraction* globalInteraction = dynamic_cast<mitk::GlobalInteraction*>(mitk::EventMapper::GetGlobalStateMachine());
        if(globalInteraction!=NULL)
        {
          globalInteraction->AddListener(multiWidget->GetMultiplexUpdateController());
        }
    }
    return controls;
}

void QmitkSimpleExampleFunctionality::createConnections()
{
  if ( controls )
  {
    connect(controls->getStereoSelect(), SIGNAL(activated(int)), this, SLOT(stereoSelectionChanged(int)) );
    connect(controls->getReInitializeNavigatorsButton(), SIGNAL(clicked()), this, SLOT(initNavigators()) );
  }
}

QAction * QmitkSimpleExampleFunctionality::createAction(QActionGroup *parent)
{
    QAction* action;
    action = new QAction( tr( "Simple Example" ), QPixmap((const char**)slicer_xpm), tr( "&Simple Example" ), CTRL + Key_L, parent, "simple example" );
    return action;
}

void QmitkSimpleExampleFunctionality::initNavigators()
{
  m_NavigatorsInitialized = multiWidget->InitializeStandardViews(m_DataTreeIterator.GetPointer());
}

void QmitkSimpleExampleFunctionality::treeChanged()
{
  if(m_NavigatorsInitialized==false)
    initNavigators();
}

void QmitkSimpleExampleFunctionality::activated()
{
  QmitkFunctionality::activated();
  assert( multiWidget != NULL );
  // init widget 4 as a 3D widget
  multiWidget->mitkWidget4->GetRenderer()->SetMapperID(2);

  if(m_NavigatorsInitialized)
  {
    multiWidget->ReInitializeStandardViews();
  }
}

void QmitkSimpleExampleFunctionality::stereoSelectionChanged( int id )
{
  vtkRenderWindow * vtkrenderwindow =
    ((mitk::OpenGLRenderer*)(multiWidget->mitkWidget4->GetRenderer()))->GetVtkRenderWindow();
  switch(id)
  {
  case 0:
    vtkrenderwindow->StereoRenderOff();
    break;
  case 1:
    vtkrenderwindow->SetStereoTypeToRedBlue();
    vtkrenderwindow->StereoRenderOn();
    break;
  case 2:
    vtkrenderwindow->SetStereoTypeToDresden();
    vtkrenderwindow->StereoRenderOn();
    break;
  }
  multiWidget->mitkWidget4->GetRenderer()->SetMapperID(2);
  multiWidget->mitkWidget4->GetRenderer()->GetRenderWindow()->Repaint();
}
<|endoftext|>


<commit_before>#include <binary_search_tree.hpp>
#include <catch.hpp>

SCENARIO("default constructor")
{
	BinarySearchTree<int> bst;
	REQUIRE(bst.root() == nullptr);
	REQUIRE(bst.count() == 0);
}

SCENARIO("insertElement")
{
	BinarySearchTree<int> bst;
	bst.insertElement(7);
	bool n=bst.isFound(7);
	REQUIRE(n=1);
	REQUIRE(bst.count() == 1);
}
<commit_msg>Update init.cpp<commit_after>#include <binary_search_tree.hpp>
#include <catch.hpp>

SCENARIO("default constructor")
{
	BinarySearchTree<int> bst;
	REQUIRE(bst.root() == nullptr);
	REQUIRE(bst.count() == 0);
}

SCENARIO("insertElement")
{
	BinarySearchTree<int> bst;
	bst.isInserted(7);
	bool n=bst.isFound(7);
	REQUIRE(n=1);
	REQUIRE(bst.count() == 1);
}
<|endoftext|>


<commit_before>#pragma once

namespace snap {

#include <scomplex/simplicial_complex.h>
#include <Eigen/Sparse>
#include <scomplex/graph_utils.hpp>
#include <scomplex/nn_utils.hpp>
#include <scomplex/types.hpp>

typedef Eigen::SparseVector<double> vector_t;

class path_snapper {
   private:
    struct impl;
    std::shared_ptr<impl> p_impl;

   public:
    path_snapper(std::vector<point_t>& pts, std::vector<cell_t>& cells);
    path_snapper(simplicial::simplicial_complex&);
    ~path_snapper();
    path_snapper(path_snapper& other);
    path_snapper& operator=(path_snapper& other);

    std::vector<size_t> snap_path(std::vector<point_t> path);
    vector_t get_chain_vector(std::vector<point_t> path);
};
};
<commit_msg>more cleanup<commit_after><|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>

#include <boost/lambda/lambda.hpp>
#include <boost/mem_fn.hpp>

#include <libport/compiler.hh>     // For ECHO
#include <libport/containers.hh>
#include <libport/foreach.hh>

#include <scheduler/job.hh>

namespace scheduler
{
  extern unsigned int Job::alive_jobs_;

  StopException::StopException(unsigned depth, boost::any payload)
    : depth_(depth)
    , payload_(payload)
  {
  }

  void
  Job::run()
  {
    assert(state_ == to_start);
    ECHO("In Job::run for " << this);

    // We may get interrupted during our first run, in which case
    // we better not be in the to_start state while we are executing
    // or we would get removed abruptly from the scheduler pending_
    // list.
    state_ = running;
    try {
      if (pending_exception_ &&
	  dynamic_cast<SchedulerException*>(pending_exception_.get()))
	check_for_pending_exception();
      work();
    }
    catch (TerminateException&)
    {
      // Normal termination requested
    }
    catch (StopException&)
    {
      // Termination through "stop" or "block" on a top-level tag,
      // that is a tag inherited at the job creation time.
    }
    catch (const kernel::exception& e)
    {
      // Signal the exception to each linked job in turn.
      foreach (const rJob& job, links_)
      {
	job->links_.remove(this);
	job->async_throw(e);
      }
    }
    catch (...)
    {
      // Exception is lost and cannot be propagated properly
      std::cerr << "Exception caught in job " << this << ", loosing it\n";
    }

    terminate_cleanup();

    // We should never go there as the scheduler will have terminated us.
    abort();
  }

  void
  Job::terminate_now()
  {
    if (!terminated())
      async_throw(TerminateException());
  }

  void
  Job::terminate_cleanup()
  {
    // Remove pending links.
    foreach (const rJob& job, links_)
      job->links_.remove(this);
    links_.clear();
    // Wake-up waiting jobs.
    foreach (const rJob& job, to_wake_up_)
      if (!job->terminated())
	job->state_set(running);
    to_wake_up_.clear();
    state_ = zombie;
    scheduler_.resume_scheduler(this);
  }

  void
  Job::yield_until_terminated(Job& other)
  {
    if (non_interruptible_ && this != &other)
      throw object::SchedulingError
	("dependency on other task in non-interruptible code");

    if (!other.terminated())
    {
      // We allow enqueuing on ourselves, but without doing it for real.
      if (&other != this)
	other.to_wake_up_.push_back(this);
      state_ = joining;
      try
      {
	scheduler_.resume_scheduler(this);
      }
      catch (...)
      {
	// We have been awoken by an exception; in this case,
	// dequeue ourselves from the other thread queue if
	// we are still enqueued there.
	libport::erase_if(other.to_wake_up_, boost::lambda::_1 == this);
	throw;
      }
    }
  }

  void
  Job::yield_until_terminated(const jobs_type& jobs)
  {
    foreach (const rJob& job, jobs)
      yield_until_terminated(*job);
  }

  void
  Job::yield_until_things_changed()
  {
    if (non_interruptible_ && !frozen())
      throw object::SchedulingError
	("attempt to wait for condition changes in non-interruptible code");

    state_ = waiting;
    scheduler_.resume_scheduler(this);
  }

  bool
  Job::frozen() const
  {
    return libport::has_if(tags_, boost::mem_fn(&scheduler::Tag::frozen));
  }

  void
  Job::async_throw(const kernel::exception& e)
  {
    pending_exception_ = e.clone();
    // A job which has received an exception is no longer side effect
    // free or non-interruptible.
    side_effect_free_ = false;
    non_interruptible_ = false;
    // If this is the current job we are talking about, the exception
    // is synchronous.
    if (scheduler_.is_current_job(*this))
      check_for_pending_exception();
    // Now that we acquired an exception to raise, we are active again,
    // even if we were previously sleeping or waiting for something.
    if (state_ != to_start && state_ != zombie)
      state_ = running;
  }

  void
  Job::register_stopped_tag(const Tag& tag, const boost::any& payload)
  {
    size_t max_tag_check = tags_.size();
    if (pending_exception_)
    {
      // If we are going to terminate, do nothing
      if (dynamic_cast<TerminateException*>(pending_exception_.get()))
	return;
      // If we already have a StopException stored, do not go any
      // further.
      StopException* exc =
	dynamic_cast<StopException*>(pending_exception_.get());
      if (exc)
	max_tag_check = exc->depth_get();
    }

    // Check if we are affected by this tag, up-to max_tag_check from
    // the beginning of the tag list.
    for (unsigned int i = 0; i < max_tag_check; i++)
      if (tags_[i]->derives_from(tag))
      {
	async_throw(StopException(i, payload));
	return;
      }
  }

  void
  Job::check_for_pending_exception()
  {
    // If an exception has been stored for further rethrow, now is
    // a good time to do so.
    if (pending_exception_)
    {
      current_exception_ = pending_exception_;
      pending_exception_ = 0;
      kernel::rethrow(current_exception_);
    }
  }

  void
  Job::recompute_prio()
  {
    if (tags_.empty())
    {
      prio_ = UPRIO_DEFAULT;
      return;
    }
    prio_ = UPRIO_MIN;
    foreach(const rTag& tag, tags_)
      prio_ = std::max(prio_, tag->prio_get());
  }

  void
  Job::recompute_prio(const Tag& tag)
  {
    if (tag.prio_get() >= prio_ || tags_.empty())
      recompute_prio();
  }

  unsigned int
  Job::alive_jobs()
  {
    return alive_jobs_;
  }

}
<commit_msg>Do not use "extern" to declare static members.<commit_after>#include <cstdlib>
#include <iostream>

#include <boost/lambda/lambda.hpp>
#include <boost/mem_fn.hpp>

#include <libport/compiler.hh>     // For ECHO
#include <libport/containers.hh>
#include <libport/foreach.hh>

#include <scheduler/job.hh>

namespace scheduler
{
  unsigned int Job::alive_jobs_;

  StopException::StopException(unsigned depth, boost::any payload)
    : depth_(depth)
    , payload_(payload)
  {
  }

  void
  Job::run()
  {
    assert(state_ == to_start);
    ECHO("In Job::run for " << this);

    // We may get interrupted during our first run, in which case
    // we better not be in the to_start state while we are executing
    // or we would get removed abruptly from the scheduler pending_
    // list.
    state_ = running;
    try {
      if (pending_exception_ &&
	  dynamic_cast<SchedulerException*>(pending_exception_.get()))
	check_for_pending_exception();
      work();
    }
    catch (TerminateException&)
    {
      // Normal termination requested
    }
    catch (StopException&)
    {
      // Termination through "stop" or "block" on a top-level tag,
      // that is a tag inherited at the job creation time.
    }
    catch (const kernel::exception& e)
    {
      // Signal the exception to each linked job in turn.
      foreach (const rJob& job, links_)
      {
	job->links_.remove(this);
	job->async_throw(e);
      }
    }
    catch (...)
    {
      // Exception is lost and cannot be propagated properly
      std::cerr << "Exception caught in job " << this << ", loosing it\n";
    }

    terminate_cleanup();

    // We should never go there as the scheduler will have terminated us.
    abort();
  }

  void
  Job::terminate_now()
  {
    if (!terminated())
      async_throw(TerminateException());
  }

  void
  Job::terminate_cleanup()
  {
    // Remove pending links.
    foreach (const rJob& job, links_)
      job->links_.remove(this);
    links_.clear();
    // Wake-up waiting jobs.
    foreach (const rJob& job, to_wake_up_)
      if (!job->terminated())
	job->state_set(running);
    to_wake_up_.clear();
    state_ = zombie;
    scheduler_.resume_scheduler(this);
  }

  void
  Job::yield_until_terminated(Job& other)
  {
    if (non_interruptible_ && this != &other)
      throw object::SchedulingError
	("dependency on other task in non-interruptible code");

    if (!other.terminated())
    {
      // We allow enqueuing on ourselves, but without doing it for real.
      if (&other != this)
	other.to_wake_up_.push_back(this);
      state_ = joining;
      try
      {
	scheduler_.resume_scheduler(this);
      }
      catch (...)
      {
	// We have been awoken by an exception; in this case,
	// dequeue ourselves from the other thread queue if
	// we are still enqueued there.
	libport::erase_if(other.to_wake_up_, boost::lambda::_1 == this);
	throw;
      }
    }
  }

  void
  Job::yield_until_terminated(const jobs_type& jobs)
  {
    foreach (const rJob& job, jobs)
      yield_until_terminated(*job);
  }

  void
  Job::yield_until_things_changed()
  {
    if (non_interruptible_ && !frozen())
      throw object::SchedulingError
	("attempt to wait for condition changes in non-interruptible code");

    state_ = waiting;
    scheduler_.resume_scheduler(this);
  }

  bool
  Job::frozen() const
  {
    return libport::has_if(tags_, boost::mem_fn(&scheduler::Tag::frozen));
  }

  void
  Job::async_throw(const kernel::exception& e)
  {
    pending_exception_ = e.clone();
    // A job which has received an exception is no longer side effect
    // free or non-interruptible.
    side_effect_free_ = false;
    non_interruptible_ = false;
    // If this is the current job we are talking about, the exception
    // is synchronous.
    if (scheduler_.is_current_job(*this))
      check_for_pending_exception();
    // Now that we acquired an exception to raise, we are active again,
    // even if we were previously sleeping or waiting for something.
    if (state_ != to_start && state_ != zombie)
      state_ = running;
  }

  void
  Job::register_stopped_tag(const Tag& tag, const boost::any& payload)
  {
    size_t max_tag_check = tags_.size();
    if (pending_exception_)
    {
      // If we are going to terminate, do nothing
      if (dynamic_cast<TerminateException*>(pending_exception_.get()))
	return;
      // If we already have a StopException stored, do not go any
      // further.
      StopException* exc =
	dynamic_cast<StopException*>(pending_exception_.get());
      if (exc)
	max_tag_check = exc->depth_get();
    }

    // Check if we are affected by this tag, up-to max_tag_check from
    // the beginning of the tag list.
    for (unsigned int i = 0; i < max_tag_check; i++)
      if (tags_[i]->derives_from(tag))
      {
	async_throw(StopException(i, payload));
	return;
      }
  }

  void
  Job::check_for_pending_exception()
  {
    // If an exception has been stored for further rethrow, now is
    // a good time to do so.
    if (pending_exception_)
    {
      current_exception_ = pending_exception_;
      pending_exception_ = 0;
      kernel::rethrow(current_exception_);
    }
  }

  void
  Job::recompute_prio()
  {
    if (tags_.empty())
    {
      prio_ = UPRIO_DEFAULT;
      return;
    }
    prio_ = UPRIO_MIN;
    foreach(const rTag& tag, tags_)
      prio_ = std::max(prio_, tag->prio_get());
  }

  void
  Job::recompute_prio(const Tag& tag)
  {
    if (tag.prio_get() >= prio_ || tags_.empty())
      recompute_prio();
  }

  unsigned int
  Job::alive_jobs()
  {
    return alive_jobs_;
  }

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2010-2019, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 Universite de Sherbrooke 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 <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>

#include <pcl_ros/transforms.h>

#include <tf/transform_listener.h>

#include <nav_msgs/Odometry.h>
#include <sensor_msgs/PointCloud2.h>

#include <message_filters/subscriber.h>
#include <message_filters/sync_policies/exact_time.h>

#include <rtabmap_ros/MsgConversion.h>
#include <rtabmap_ros/OdomInfo.h>
#include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_filtering.h>

namespace rtabmap_ros
{

/**
 * This nodelet can assemble a number of clouds (max_clouds) coming
 * from the same sensor, taking into account the displacement of the robot based on
 * fixed_frame_id, then publish the resulting cloud.
 * If fixed_frame_id is set to "" (empty), the nodelet will subscribe to
 * an odom topic that should have the exact same stamp than to input cloud.
 * The output cloud has the same stamp and frame than the last assembled cloud.
 */
class PointCloudAssembler : public nodelet::Nodelet
{
public:
	PointCloudAssembler() :
		warningThread_(0),
		callbackCalled_(false),
		exactSync_(0),
		exactInfoSync_(0),
		maxClouds_(0),
		assemblingTime_(0),
		skipClouds_(0),
		cloudsSkipped_(0),
		circularBuffer_(false),
		waitForTransformDuration_(0.1),
		rangeMin_(0),
		rangeMax_(0),
		voxelSize_(0),
		fixedFrameId_("odom")
	{}

	virtual ~PointCloudAssembler()
	{
		delete exactSync_;
		delete exactInfoSync_;

		if(warningThread_)
		{
			callbackCalled_=true;
			warningThread_->join();
			delete warningThread_;
		}
	}

private:
	virtual void onInit()
	{
		ros::NodeHandle & nh = getNodeHandle();
		ros::NodeHandle & pnh = getPrivateNodeHandle();

		int queueSize = 5;
		bool subscribeOdomInfo = false;

		pnh.param("queue_size", queueSize, queueSize);
		pnh.param("fixed_frame_id", fixedFrameId_, fixedFrameId_);
		pnh.param("max_clouds", maxClouds_, maxClouds_);
		pnh.param("assembling_time", assemblingTime_, assemblingTime_);
		pnh.param("skip_clouds", skipClouds_, skipClouds_);
		pnh.param("circular_buffer", circularBuffer_, circularBuffer_);
		pnh.param("wait_for_transform_duration", waitForTransformDuration_, waitForTransformDuration_);
		pnh.param("range_min", rangeMin_, rangeMin_);
		pnh.param("range_max", rangeMax_, rangeMax_);
		pnh.param("voxel_size", voxelSize_, voxelSize_);
		pnh.param("subscribe_odom_info", subscribeOdomInfo, subscribeOdomInfo);
		ROS_ASSERT(maxClouds_>0 || assemblingTime_ >0.0);

		ROS_INFO("%s: queue_size=%d", getName().c_str(), queueSize);
		ROS_INFO("%s: fixed_frame_id=%s", getName().c_str(), fixedFrameId_.c_str());
		ROS_INFO("%s: max_clouds=%d", getName().c_str(), maxClouds_);
		ROS_INFO("%s: assembling_time=%fs", getName().c_str(), assemblingTime_);
		ROS_INFO("%s: skip_clouds=%d", getName().c_str(), skipClouds_);
		ROS_INFO("%s: circular_buffer=%s", getName().c_str(), circularBuffer_?"true":"false");
		ROS_INFO("%s: wait_for_transform_duration=%f", getName().c_str(), waitForTransformDuration_);
		ROS_INFO("%s: range_min=%f", getName().c_str(), rangeMin_);
		ROS_INFO("%s: range_max=%f", getName().c_str(), rangeMax_);
		ROS_INFO("%s: voxel_size=%fm", getName().c_str(), voxelSize_);

		cloudsSkipped_ = skipClouds_;

		std::string subscribedTopicsMsg;
		if(!fixedFrameId_.empty())
		{
			cloudSub_ = nh.subscribe("cloud", 1, &PointCloudAssembler::callbackCloud, this);
			subscribedTopicsMsg = uFormat("\n%s subscribed to %s",
								getName().c_str(),
								cloudSub_.getTopic().c_str());
		}
		else if(subscribeOdomInfo)
		{
			syncCloudSub_.subscribe(nh, "cloud", 1);
			syncOdomSub_.subscribe(nh, "odom", 1);
			syncOdomInfoSub_.subscribe(nh, "odom_info", 1);
			exactInfoSync_ = new message_filters::Synchronizer<syncInfoPolicy>(syncInfoPolicy(queueSize), syncCloudSub_, syncOdomSub_, syncOdomInfoSub_);
			exactInfoSync_->registerCallback(boost::bind(&rtabmap_ros::PointCloudAssembler::callbackCloudOdomInfo, this, _1, _2, _3));
			subscribedTopicsMsg = uFormat("\n%s subscribed to (exact sync):\n   %s,\n   %s",
								getName().c_str(),
								syncCloudSub_.getTopic().c_str(),
								syncOdomSub_.getTopic().c_str(),
								syncOdomInfoSub_.getTopic().c_str());

			warningThread_ = new boost::thread(boost::bind(&PointCloudAssembler::warningLoop, this, subscribedTopicsMsg));
		}
		else
		{
			syncCloudSub_.subscribe(nh, "cloud", 1);
			syncOdomSub_.subscribe(nh, "odom", 1);
			exactSync_ = new message_filters::Synchronizer<syncPolicy>(syncPolicy(queueSize), syncCloudSub_, syncOdomSub_);
			exactSync_->registerCallback(boost::bind(&rtabmap_ros::PointCloudAssembler::callbackCloudOdom, this, _1, _2));
			subscribedTopicsMsg = uFormat("\n%s subscribed to (exact sync):\n   %s,\n   %s",
								getName().c_str(),
								syncCloudSub_.getTopic().c_str(),
								syncOdomSub_.getTopic().c_str());

			warningThread_ = new boost::thread(boost::bind(&PointCloudAssembler::warningLoop, this, subscribedTopicsMsg));
		}

		cloudPub_ = nh.advertise<sensor_msgs::PointCloud2>("assembled_cloud", 1);

		NODELET_INFO("%s", subscribedTopicsMsg.c_str());
	}

	void callbackCloudOdom(
			const sensor_msgs::PointCloud2ConstPtr & cloudMsg,
			const nav_msgs::OdometryConstPtr & odomMsg)
	{
		callbackCalled_ = true;
		rtabmap::Transform odom = rtabmap_ros::transformFromPoseMsg(odomMsg->pose.pose);
		if(!odom.isNull())
		{
			fixedFrameId_ = odomMsg->header.frame_id;
			callbackCloud(cloudMsg);
		}
		else
		{
			NODELET_WARN("Reseting point cloud assembler as null odometry has been received.");
			clouds_.clear();
		}
	}

	void callbackCloudOdomInfo(
			const sensor_msgs::PointCloud2ConstPtr & cloudMsg,
			const nav_msgs::OdometryConstPtr & odomMsg,
			const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg)
	{
		callbackCalled_ = true;
		rtabmap::Transform odom = rtabmap_ros::transformFromPoseMsg(odomMsg->pose.pose);
		if(!odom.isNull())
		{
			if(odomInfoMsg->keyFrameAdded)
			{
				fixedFrameId_ = odomMsg->header.frame_id;
				callbackCloud(cloudMsg);
			}
			else
			{
				NODELET_INFO("Skipping non keyframe...");
			}
		}
		else
		{
			NODELET_WARN("Reseting point cloud assembler as null odometry has been received.");
			clouds_.clear();
		}
	}

	void callbackCloud(const sensor_msgs::PointCloud2ConstPtr & cloudMsg)
	{
		if(cloudPub_.getNumSubscribers())
		{
			if(skipClouds_<=0 || cloudsSkipped_ >= skipClouds_)
			{
				cloudsSkipped_ = 0;

				rtabmap::Transform t = rtabmap_ros::getTransform(
						fixedFrameId_, //fromFrame
						cloudMsg->header.frame_id, //toFrame
						cloudMsg->header.stamp,
						tfListener_,
						waitForTransformDuration_);

				if(t.isNull())
				{
					ROS_ERROR("Cloud not transform all clouds! Resetting...");
					clouds_.clear();
					return;
				}

				pcl::PCLPointCloud2::Ptr newCloud(new pcl::PCLPointCloud2);
				if(rangeMin_ > 0.0 || rangeMax_ > 0.0 || voxelSize_ > 0.0f)
				{
					pcl_conversions::toPCL(*cloudMsg, *newCloud);
					rtabmap::LaserScan scan = rtabmap::util3d::laserScanFromPointCloud(*newCloud);
					scan = rtabmap::util3d::commonFiltering(scan, 1, rangeMin_, rangeMax_, voxelSize_);
					pcl::uint64_t stamp = newCloud->header.stamp;
					newCloud = rtabmap::util3d::laserScanToPointCloud2(scan, t);
					newCloud->header.stamp = stamp;
				}
				else
				{
					sensor_msgs::PointCloud2 output;
					pcl_ros::transformPointCloud(t.toEigen4f(), *cloudMsg, output);
					pcl_conversions::toPCL(output, *newCloud);
				}

				clouds_.push_back(newCloud);

				bool reachedMaxSize =
						((int)clouds_.size() >= maxClouds_ && maxClouds_ > 0)
						||
						((*newCloud).header.stamp >= clouds_.front()->header.stamp + static_cast<pcl::uint64_t>(assemblingTime_*1000000.0) && assemblingTime_ > 0.0);

				if( circularBuffer_ || reachedMaxSize )
				{
					pcl::PCLPointCloud2Ptr assembled(new pcl::PCLPointCloud2);
					for(std::list<pcl::PCLPointCloud2::Ptr>::iterator iter=clouds_.begin(); iter!=clouds_.end(); ++iter)
					{
						if(assembled->data.empty())
						{
							*assembled = *(*iter);
						}
						else
						{
							pcl::PCLPointCloud2Ptr assembledTmp(new pcl::PCLPointCloud2);
							pcl::concatenatePointCloud(*assembled, *(*iter), *assembledTmp);
							assembled = assembledTmp;
						}
					}

					sensor_msgs::PointCloud2 rosCloud;
					if(voxelSize_>0.0)
					{
						pcl::VoxelGrid<pcl::PCLPointCloud2> filter;
						filter.setLeafSize(voxelSize_, voxelSize_, voxelSize_);
						filter.setInputCloud(assembled);
						pcl::PCLPointCloud2Ptr output(new pcl::PCLPointCloud2);
						filter.filter(*output);
						assembled = output;
					}

					pcl_conversions::moveFromPCL(*assembled, rosCloud);
					pcl_ros::transformPointCloud(t.toEigen4f().inverse(), rosCloud, rosCloud);

					rosCloud.header = cloudMsg->header;
					cloudPub_.publish(rosCloud);
					if(circularBuffer_)
					{
						if(reachedMaxSize)
						{
							clouds_.pop_front();
						}
					}
					else
					{
						clouds_.clear();
					}
				}
			}
			else
			{
				++cloudsSkipped_;
			}
		}
	}

	void warningLoop(const std::string & subscribedTopicsMsg)
	{
		ros::Duration r(5.0);
		while(!callbackCalled_)
		{
			r.sleep();
			if(!callbackCalled_)
			{
				ROS_WARN("%s: Did not receive data since 5 seconds! Make sure the input topics are "
						"published (\"$ rostopic hz my_topic\") and the timestamps in their "
						"header are set. %s",
						getName().c_str(),
						subscribedTopicsMsg.c_str());
			}
		}
	}

private:
	boost::thread * warningThread_;
	bool callbackCalled_;

	ros::Subscriber cloudSub_;
	ros::Publisher cloudPub_;

	typedef message_filters::sync_policies::ExactTime<sensor_msgs::PointCloud2, nav_msgs::Odometry> syncPolicy;
	typedef message_filters::sync_policies::ExactTime<sensor_msgs::PointCloud2, nav_msgs::Odometry, rtabmap_ros::OdomInfo> syncInfoPolicy;
	message_filters::Synchronizer<syncPolicy>* exactSync_;
	message_filters::Synchronizer<syncInfoPolicy>* exactInfoSync_;
	message_filters::Subscriber<sensor_msgs::PointCloud2> syncCloudSub_;
	message_filters::Subscriber<nav_msgs::Odometry> syncOdomSub_;
	message_filters::Subscriber<rtabmap_ros::OdomInfo> syncOdomInfoSub_;

	int maxClouds_;
	int skipClouds_;
	int cloudsSkipped_;
	bool circularBuffer_;
	double assemblingTime_;
	double waitForTransformDuration_;
	double rangeMin_;
	double rangeMax_;
	double voxelSize_;
	std::string fixedFrameId_;
	tf::TransformListener tfListener_;

	std::list<pcl::PCLPointCloud2::Ptr> clouds_;
};

PLUGINLIB_EXPORT_CLASS(rtabmap_ros::PointCloudAssembler, nodelet::Nodelet);
}

<commit_msg>Fixed PCL 1.10 deprecated warnings<commit_after>/*
Copyright (c) 2010-2019, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 Universite de Sherbrooke 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 <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>

#include <pcl_ros/transforms.h>

#include <tf/transform_listener.h>

#include <nav_msgs/Odometry.h>
#include <sensor_msgs/PointCloud2.h>

#include <message_filters/subscriber.h>
#include <message_filters/sync_policies/exact_time.h>

#include <rtabmap_ros/MsgConversion.h>
#include <rtabmap_ros/OdomInfo.h>
#include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_filtering.h>

namespace rtabmap_ros
{

/**
 * This nodelet can assemble a number of clouds (max_clouds) coming
 * from the same sensor, taking into account the displacement of the robot based on
 * fixed_frame_id, then publish the resulting cloud.
 * If fixed_frame_id is set to "" (empty), the nodelet will subscribe to
 * an odom topic that should have the exact same stamp than to input cloud.
 * The output cloud has the same stamp and frame than the last assembled cloud.
 */
class PointCloudAssembler : public nodelet::Nodelet
{
public:
	PointCloudAssembler() :
		warningThread_(0),
		callbackCalled_(false),
		exactSync_(0),
		exactInfoSync_(0),
		maxClouds_(0),
		assemblingTime_(0),
		skipClouds_(0),
		cloudsSkipped_(0),
		circularBuffer_(false),
		waitForTransformDuration_(0.1),
		rangeMin_(0),
		rangeMax_(0),
		voxelSize_(0),
		fixedFrameId_("odom")
	{}

	virtual ~PointCloudAssembler()
	{
		delete exactSync_;
		delete exactInfoSync_;

		if(warningThread_)
		{
			callbackCalled_=true;
			warningThread_->join();
			delete warningThread_;
		}
	}

private:
	virtual void onInit()
	{
		ros::NodeHandle & nh = getNodeHandle();
		ros::NodeHandle & pnh = getPrivateNodeHandle();

		int queueSize = 5;
		bool subscribeOdomInfo = false;

		pnh.param("queue_size", queueSize, queueSize);
		pnh.param("fixed_frame_id", fixedFrameId_, fixedFrameId_);
		pnh.param("max_clouds", maxClouds_, maxClouds_);
		pnh.param("assembling_time", assemblingTime_, assemblingTime_);
		pnh.param("skip_clouds", skipClouds_, skipClouds_);
		pnh.param("circular_buffer", circularBuffer_, circularBuffer_);
		pnh.param("wait_for_transform_duration", waitForTransformDuration_, waitForTransformDuration_);
		pnh.param("range_min", rangeMin_, rangeMin_);
		pnh.param("range_max", rangeMax_, rangeMax_);
		pnh.param("voxel_size", voxelSize_, voxelSize_);
		pnh.param("subscribe_odom_info", subscribeOdomInfo, subscribeOdomInfo);
		ROS_ASSERT(maxClouds_>0 || assemblingTime_ >0.0);

		ROS_INFO("%s: queue_size=%d", getName().c_str(), queueSize);
		ROS_INFO("%s: fixed_frame_id=%s", getName().c_str(), fixedFrameId_.c_str());
		ROS_INFO("%s: max_clouds=%d", getName().c_str(), maxClouds_);
		ROS_INFO("%s: assembling_time=%fs", getName().c_str(), assemblingTime_);
		ROS_INFO("%s: skip_clouds=%d", getName().c_str(), skipClouds_);
		ROS_INFO("%s: circular_buffer=%s", getName().c_str(), circularBuffer_?"true":"false");
		ROS_INFO("%s: wait_for_transform_duration=%f", getName().c_str(), waitForTransformDuration_);
		ROS_INFO("%s: range_min=%f", getName().c_str(), rangeMin_);
		ROS_INFO("%s: range_max=%f", getName().c_str(), rangeMax_);
		ROS_INFO("%s: voxel_size=%fm", getName().c_str(), voxelSize_);

		cloudsSkipped_ = skipClouds_;

		std::string subscribedTopicsMsg;
		if(!fixedFrameId_.empty())
		{
			cloudSub_ = nh.subscribe("cloud", 1, &PointCloudAssembler::callbackCloud, this);
			subscribedTopicsMsg = uFormat("\n%s subscribed to %s",
								getName().c_str(),
								cloudSub_.getTopic().c_str());
		}
		else if(subscribeOdomInfo)
		{
			syncCloudSub_.subscribe(nh, "cloud", 1);
			syncOdomSub_.subscribe(nh, "odom", 1);
			syncOdomInfoSub_.subscribe(nh, "odom_info", 1);
			exactInfoSync_ = new message_filters::Synchronizer<syncInfoPolicy>(syncInfoPolicy(queueSize), syncCloudSub_, syncOdomSub_, syncOdomInfoSub_);
			exactInfoSync_->registerCallback(boost::bind(&rtabmap_ros::PointCloudAssembler::callbackCloudOdomInfo, this, _1, _2, _3));
			subscribedTopicsMsg = uFormat("\n%s subscribed to (exact sync):\n   %s,\n   %s",
								getName().c_str(),
								syncCloudSub_.getTopic().c_str(),
								syncOdomSub_.getTopic().c_str(),
								syncOdomInfoSub_.getTopic().c_str());

			warningThread_ = new boost::thread(boost::bind(&PointCloudAssembler::warningLoop, this, subscribedTopicsMsg));
		}
		else
		{
			syncCloudSub_.subscribe(nh, "cloud", 1);
			syncOdomSub_.subscribe(nh, "odom", 1);
			exactSync_ = new message_filters::Synchronizer<syncPolicy>(syncPolicy(queueSize), syncCloudSub_, syncOdomSub_);
			exactSync_->registerCallback(boost::bind(&rtabmap_ros::PointCloudAssembler::callbackCloudOdom, this, _1, _2));
			subscribedTopicsMsg = uFormat("\n%s subscribed to (exact sync):\n   %s,\n   %s",
								getName().c_str(),
								syncCloudSub_.getTopic().c_str(),
								syncOdomSub_.getTopic().c_str());

			warningThread_ = new boost::thread(boost::bind(&PointCloudAssembler::warningLoop, this, subscribedTopicsMsg));
		}

		cloudPub_ = nh.advertise<sensor_msgs::PointCloud2>("assembled_cloud", 1);

		NODELET_INFO("%s", subscribedTopicsMsg.c_str());
	}

	void callbackCloudOdom(
			const sensor_msgs::PointCloud2ConstPtr & cloudMsg,
			const nav_msgs::OdometryConstPtr & odomMsg)
	{
		callbackCalled_ = true;
		rtabmap::Transform odom = rtabmap_ros::transformFromPoseMsg(odomMsg->pose.pose);
		if(!odom.isNull())
		{
			fixedFrameId_ = odomMsg->header.frame_id;
			callbackCloud(cloudMsg);
		}
		else
		{
			NODELET_WARN("Reseting point cloud assembler as null odometry has been received.");
			clouds_.clear();
		}
	}

	void callbackCloudOdomInfo(
			const sensor_msgs::PointCloud2ConstPtr & cloudMsg,
			const nav_msgs::OdometryConstPtr & odomMsg,
			const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg)
	{
		callbackCalled_ = true;
		rtabmap::Transform odom = rtabmap_ros::transformFromPoseMsg(odomMsg->pose.pose);
		if(!odom.isNull())
		{
			if(odomInfoMsg->keyFrameAdded)
			{
				fixedFrameId_ = odomMsg->header.frame_id;
				callbackCloud(cloudMsg);
			}
			else
			{
				NODELET_INFO("Skipping non keyframe...");
			}
		}
		else
		{
			NODELET_WARN("Reseting point cloud assembler as null odometry has been received.");
			clouds_.clear();
		}
	}

	void callbackCloud(const sensor_msgs::PointCloud2ConstPtr & cloudMsg)
	{
		if(cloudPub_.getNumSubscribers())
		{
			if(skipClouds_<=0 || cloudsSkipped_ >= skipClouds_)
			{
				cloudsSkipped_ = 0;

				rtabmap::Transform t = rtabmap_ros::getTransform(
						fixedFrameId_, //fromFrame
						cloudMsg->header.frame_id, //toFrame
						cloudMsg->header.stamp,
						tfListener_,
						waitForTransformDuration_);

				if(t.isNull())
				{
					ROS_ERROR("Cloud not transform all clouds! Resetting...");
					clouds_.clear();
					return;
				}

				pcl::PCLPointCloud2::Ptr newCloud(new pcl::PCLPointCloud2);
				if(rangeMin_ > 0.0 || rangeMax_ > 0.0 || voxelSize_ > 0.0f)
				{
					pcl_conversions::toPCL(*cloudMsg, *newCloud);
					rtabmap::LaserScan scan = rtabmap::util3d::laserScanFromPointCloud(*newCloud);
					scan = rtabmap::util3d::commonFiltering(scan, 1, rangeMin_, rangeMax_, voxelSize_);
#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
					std::uint64_t stamp = newCloud->header.stamp;
#else
					pcl::uint64_t stamp = newCloud->header.stamp;
#endif
					newCloud = rtabmap::util3d::laserScanToPointCloud2(scan, t);
					newCloud->header.stamp = stamp;
				}
				else
				{
					sensor_msgs::PointCloud2 output;
					pcl_ros::transformPointCloud(t.toEigen4f(), *cloudMsg, output);
					pcl_conversions::toPCL(output, *newCloud);
				}

				clouds_.push_back(newCloud);

#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
				bool reachedMaxSize =
						((int)clouds_.size() >= maxClouds_ && maxClouds_ > 0)
						||
						((*newCloud).header.stamp >= clouds_.front()->header.stamp + static_cast<std::uint64_t>(assemblingTime_*1000000.0) && assemblingTime_ > 0.0);
#else
				bool reachedMaxSize =
						((int)clouds_.size() >= maxClouds_ && maxClouds_ > 0)
						||
						((*newCloud).header.stamp >= clouds_.front()->header.stamp + static_cast<pcl::uint64_t>(assemblingTime_*1000000.0) && assemblingTime_ > 0.0);
#endif

				if( circularBuffer_ || reachedMaxSize )
				{
					pcl::PCLPointCloud2Ptr assembled(new pcl::PCLPointCloud2);
					for(std::list<pcl::PCLPointCloud2::Ptr>::iterator iter=clouds_.begin(); iter!=clouds_.end(); ++iter)
					{
						if(assembled->data.empty())
						{
							*assembled = *(*iter);
						}
						else
						{
							pcl::PCLPointCloud2Ptr assembledTmp(new pcl::PCLPointCloud2);
#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
							pcl::concatenate(*assembled, *(*iter), *assembledTmp);
#else
							pcl::concatenatePointCloud(*assembled, *(*iter), *assembledTmp);
#endif
							assembled = assembledTmp;
						}
					}

					sensor_msgs::PointCloud2 rosCloud;
					if(voxelSize_>0.0)
					{
						pcl::VoxelGrid<pcl::PCLPointCloud2> filter;
						filter.setLeafSize(voxelSize_, voxelSize_, voxelSize_);
						filter.setInputCloud(assembled);
						pcl::PCLPointCloud2Ptr output(new pcl::PCLPointCloud2);
						filter.filter(*output);
						assembled = output;
					}

					pcl_conversions::moveFromPCL(*assembled, rosCloud);
					pcl_ros::transformPointCloud(t.toEigen4f().inverse(), rosCloud, rosCloud);

					rosCloud.header = cloudMsg->header;
					cloudPub_.publish(rosCloud);
					if(circularBuffer_)
					{
						if(reachedMaxSize)
						{
							clouds_.pop_front();
						}
					}
					else
					{
						clouds_.clear();
					}
				}
			}
			else
			{
				++cloudsSkipped_;
			}
		}
	}

	void warningLoop(const std::string & subscribedTopicsMsg)
	{
		ros::Duration r(5.0);
		while(!callbackCalled_)
		{
			r.sleep();
			if(!callbackCalled_)
			{
				ROS_WARN("%s: Did not receive data since 5 seconds! Make sure the input topics are "
						"published (\"$ rostopic hz my_topic\") and the timestamps in their "
						"header are set. %s",
						getName().c_str(),
						subscribedTopicsMsg.c_str());
			}
		}
	}

private:
	boost::thread * warningThread_;
	bool callbackCalled_;

	ros::Subscriber cloudSub_;
	ros::Publisher cloudPub_;

	typedef message_filters::sync_policies::ExactTime<sensor_msgs::PointCloud2, nav_msgs::Odometry> syncPolicy;
	typedef message_filters::sync_policies::ExactTime<sensor_msgs::PointCloud2, nav_msgs::Odometry, rtabmap_ros::OdomInfo> syncInfoPolicy;
	message_filters::Synchronizer<syncPolicy>* exactSync_;
	message_filters::Synchronizer<syncInfoPolicy>* exactInfoSync_;
	message_filters::Subscriber<sensor_msgs::PointCloud2> syncCloudSub_;
	message_filters::Subscriber<nav_msgs::Odometry> syncOdomSub_;
	message_filters::Subscriber<rtabmap_ros::OdomInfo> syncOdomInfoSub_;

	int maxClouds_;
	int skipClouds_;
	int cloudsSkipped_;
	bool circularBuffer_;
	double assemblingTime_;
	double waitForTransformDuration_;
	double rangeMin_;
	double rangeMax_;
	double voxelSize_;
	std::string fixedFrameId_;
	tf::TransformListener tfListener_;

	std::list<pcl::PCLPointCloud2::Ptr> clouds_;
};

PLUGINLIB_EXPORT_CLASS(rtabmap_ros::PointCloudAssembler, nodelet::Nodelet);
}

<|endoftext|>


<commit_before>/* Copyright (c) 2016, Dennis Wölfing
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* kernel/src/keyboard.cpp
 * Keyboard.
 */

#include <stddef.h>
#include <dennix/kernel/keyboard.h>

// German keyboard layout.
static const char KBLAYOUT_DE[] = {
    0, 0, 0, 0,
    0, 0, 0, 0, // Escape
    '1', '!', 0, 0,
    '2', '"', 0/*'²'*/, 0,
    '3', 0/*'§'*/, 0/*'³'*/, 0,
    '4', '$', 0, 0,
    '5', '%', 0, 0,
    '6', '&', 0, 0,
    '7', '/', '{', 0,
    '8', '(', '[', 0,
    '9', ')', ']', 0,
    '0', '=', '}', 0,
    0/*'ß'*/, '?', '\\', 0,
    0/*'´'*/, '`', 0, 0,
    '\b', '\b', '\b', '\b',
    '\t', '\t', '\t', '\t',
    'q', 'Q', '@', 0,
    'w', 'W', 0, 0,
    'e', 'E', 0/*'€'*/, 0,
    'r', 'R', 0, 0,
    't', 'T', 0, 0,
    'z', 'Z', 0, 0,
    'u', 'U', 0, 0,
    'i', 'I', 0, 0,
    'o', 'O', 0, 0,
    'p', 'P', 0, 0,
    0/*'ü'*/, 0/*'Ü'*/, 0, 0,
    '+', '*', '~', 0,
    '\n', '\n', '\n', '\n',
    0, 0, 0, 0, // left Control
    'a', 'A', 0, 0,
    's', 'S', 0, 0,
    'd', 'D', 0, 0,
    'f', 'F', 0, 0,
    'g', 'G', 0, 0,
    'h', 'H', 0, 0,
    'j', 'J', 0, 0,
    'k', 'K', 0, 0,
    'l', 'L', 0, 0,
    0/*'ö'*/, 0/*'Ö'*/, 0, 0,
    0/*'ä'*/, 0/*'Ä'*/, 0, 0,
    '^', 0/*'°'*/, 0, 0,
    0, 0, 0, 0, // left Shift
    '#', '\'', 0, 0,
    'y', 'Y', 0, 0,
    'x', 'X', 0, 0,
    'c', 'C', 0, 0,
    'v', 'V', 0, 0,
    'b', 'B', 0, 0,
    'n', 'N', 0, 0,
    'm', 'M', 0/*'µ'*/, 0,
    ',', ';', 0, 0,
    '.', ':', 0, 0,
    '-', '_', 0, 0,
    0, 0, 0, 0, // right Shift
    '*', '*', '*', '*',
    0, 0, 0, 0, // left Alt
    ' ', ' ', ' ', ' ',
    0, 0, 0, 0, // Caps Lock
    0, 0, 0, 0, // F1
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0, // F10
    0, 0, 0, 0, // Num Lock
    0, 0, 0, 0, // Scroll Lock
    '7', 0, '7', 0,
    '8', 0, '8', 0,
    '9', 0, '9', 0,
    '-', '-', '-', '-',
    '4', 0, '4', 0,
    '5', 0, '5', 0,
    '6', 0, '6', 0,
    '+', '+', '+', '+',
    '1', 0, '1', 0,
    '2', 0, '2', 0,
    '3', 0, '3', 0,
    '0', 0, '0', 0,
    ',', 0, ',', 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    '<', '>', '|', 0,
    0, 0, 0, 0, // F11
    0, 0, 0, 0, // F12
    // Most things below are not printable
};

char Keyboard::getCharFromKey(int key) {
    static bool leftShift = false;
    static bool rightShift = false;
    static bool capsLock = false;
    static bool altGr = false;

    if (key == 0x2A) {
        leftShift = true;
    } else if (key == 0x36) {
        rightShift = true;
    } else if (key == 0x3A) {
        capsLock = !capsLock;
    } else if (key == 0xB8) {
        altGr = true;
    } else if (key == -0x2A) {
        leftShift = false;
    } else if (key == -0x36) {
        rightShift = false;
    } else if (key == -0xB8) {
        altGr = false;
    }

    if (key < 0) return '\0';

    size_t index = key << 2 | altGr << 1 | ((leftShift || rightShift) ^ capsLock);
    if (index < sizeof(KBLAYOUT_DE)) {
        return KBLAYOUT_DE[index];
    }

    if (key == 0x9C) {
        return '\n';
    } else if (key == 0xB5) {
        return '/';
    }

    return '\0';
}
<commit_msg>Switch to US keyboard layout.<commit_after>/* Copyright (c) 2016, Dennis Wölfing
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* kernel/src/keyboard.cpp
 * Keyboard.
 */

#include <stddef.h>
#include <dennix/kernel/keyboard.h>

// US keyboard layout.
static const char KBLAYOUT_US[] = {
    // No modifiers, Shift, Caps, Shift + Caps,
    0, 0, 0, 0,
    0, 0, 0, 0, // Escape
    '1', '!', '1', '!',
    '2', '@', '2', '@',
    '3', '#', '3', '#',
    '4', '$', '4', '$',
    '5', '%', '5', '%',
    '6', '^', '6', '^',
    '7', '&', '7', '&',
    '8', '*', '8', '*',
    '9', '(', '9', '(',
    '0', ')', '0', ')',
    '-', '_', '-', '_',
    '=', '+', '=', '+',
    '\b', '\b', '\b', '\b',
    '\t', '\t', '\t', '\t',
    'q', 'Q', 'Q', 'q',
    'w', 'W', 'W', 'w',
    'e', 'E', 'E', 'e',
    'r', 'R', 'R', 'r',
    't', 'T', 'T', 't',
    'y', 'Y', 'Y', 'y',
    'u', 'U', 'U', 'u',
    'i', 'I', 'I', 'i',
    'o', 'O', 'O', 'o',
    'p', 'P', 'P', 'p',
    '[', '{', '[', '{',
    ']', '}', ']', '}',
    '\n', '\n', '\n', '\n',
    0, 0, 0, 0, // left Control
    'a', 'A', 'A', 'a',
    's', 'S', 'S', 's',
    'd', 'D', 'D', 'd',
    'f', 'F', 'F', 'f',
    'g', 'G', 'G', 'g',
    'h', 'H', 'H', 'h',
    'j', 'J', 'J', 'j',
    'k', 'K', 'K', 'k',
    'l', 'L', 'L', 'l',
    ';', ':', ';', ':',
    '\'', '"', '\'', '"',
    '`', '~', '`', '~',
    0, 0, 0, 0, // left Shift
    '\\', '|', '\\', '|',
    'z', 'Z', 'Z', 'z',
    'x', 'X', 'X', 'x',
    'c', 'C', 'C', 'c',
    'v', 'V', 'V', 'v',
    'b', 'B', 'B', 'b',
    'n', 'N', 'N', 'n',
    'm', 'M', 'M', 'm',
    ',', '<', ',', '<',
    '.', '>', '.', '>',
    '/', '?', '/', '?',
    0, 0, 0, 0, // right Shift
    '*', '*', '*', '*',
    0, 0, 0, 0, // left Alt
    ' ', ' ', ' ', ' ',
    0, 0, 0, 0, // Caps Lock
    0, 0, 0, 0, // F1
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0, // F10
    0, 0, 0, 0, // Num Lock
    0, 0, 0, 0, // Scroll Lock
    '7', 0, '7', 0,
    '8', 0, '8', 0,
    '9', 0, '9', 0,
    '-', '-', '-', '-',
    '4', 0, '4', 0,
    '5', 0, '5', 0,
    '6', 0, '6', 0,
    '+', '+', '+', '+',
    '1', 0, '1', 0,
    '2', 0, '2', 0,
    '3', 0, '3', 0,
    '0', 0, '0', 0,
    '.', 0, '.', 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0, // F11
    0, 0, 0, 0, // F12
    // Most things below are not printable
};

char Keyboard::getCharFromKey(int key) {
    static bool leftShift = false;
    static bool rightShift = false;
    static bool capsLock = false;

    if (key == 0x2A) {
        leftShift = true;
    } else if (key == 0x36) {
        rightShift = true;
    } else if (key == 0x3A) {
        capsLock = !capsLock;
    } else if (key == -0x2A) {
        leftShift = false;
    } else if (key == -0x36) {
        rightShift = false;
    }

    if (key < 0) return '\0';

    size_t index = key << 2 | (capsLock << 1) | (leftShift || rightShift);
    if (index < sizeof(KBLAYOUT_US)) {
        return KBLAYOUT_US[index];
    }

    if (key == 0x9C) {
        return '\n';
    } else if (key == 0xB5) {
        return '/';
    }

    return '\0';
}
<|endoftext|>


<commit_before>#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Verifier.h>
#include <vector>
#include <string>

struct LLVMCodeGen {
  using IRBuilder = llvm::IRBuilder<>;
  llvm::LLVMContext &Context;
  llvm::Module &M;
  IRBuilder &Builder;

  LLVMCodeGen(llvm::LLVMContext &context, llvm::Module &m,
              llvm::IRBuilder<> &builder)
      : Context(context), M(m), Builder(builder) {}
  void dump() const { M.dump(); }

  // -----------------------  Value -------------------------------------------
  struct Value {
    LLVMCodeGen &CG;
    llvm::Value &V;

    Value(LLVMCodeGen &cg, llvm::Value &value) : CG(cg), V(value) {}

    operator llvm::Value *() { return &V; }

    Value operator*(Value R) const {
      return Value{CG, *CG.Builder.CreateMul(&V, R, "mul")};
    }
  };

  //----------------------- Type ---------------------------------------------

  struct Type {
    enum Kind { int32, float32, float64 };

    LLVMCodeGen const &CG;
    Kind TypeKind;

    Type(LLVMCodeGen const &cg, Kind type_kind) : CG(cg), TypeKind(type_kind) {}

    operator llvm::Type *() const {
      switch (TypeKind) {
      case int32:
        return CG.Builder.getInt32Ty();
      case float32:
        return CG.Builder.getFloatTy();
      case float64:
        return CG.Builder.getDoubleTy();
      default:
        assert(0 && "Must not happen");
      }
    }

    size_t size() const {
      switch (TypeKind) {
      case int32:
      case float32:
        return 4;
      case float64:
        return 8;
      default:
        assert(0 && "Must not happen");
      }
      return 0;
    }
  };

  // --------------------- Global Variable -----------------------------------

  struct GlobalVar {
    LLVMCodeGen &CG;
    llvm::GlobalVariable &Var;
    GlobalVar(LLVMCodeGen &cg, llvm::GlobalVariable &var)
        : CG(cg), Var(var) {}
  };

  GlobalVar mkGlobalVar(std::string name, Type type) {
    M.getOrInsertGlobal(name, type);
    llvm::GlobalVariable *gvar = M.getNamedGlobal(name);
    gvar->setLinkage(llvm::GlobalValue::CommonLinkage);
    gvar->setAlignment(type.size());
    return GlobalVar{*this, *gvar};
  }

  //---------------------- Function -------------------------------------------

  struct Function {
    LLVMCodeGen &CG;
    llvm::Function &F;
    std::vector<llvm::Value*> Args;
    Function(LLVMCodeGen &cg, llvm::Function &f) : CG(cg), F(f) {
      Args.reserve(16);
      for (auto &arg : F.args()) {
        Args.push_back(&arg);
      }
    }
    void verify() const { llvm::verifyFunction(F); }

    operator llvm::Function *() { return &F; }

    Value arg(size_t num) const {
      assert(num < Args.size());
      return Value{CG, *Args[num]};
    }

  };

  Function mkFunction(std::string name, Type ret_type,
                      std::vector<std::pair<Type, std::string>> args = {}) {
    std::vector<llvm::Type*> args_type;
    args_type.reserve(args.size());
    for (auto arg : args) {
      args_type.push_back(arg.first);
    }
    llvm::FunctionType *funcType =
        llvm::FunctionType::get(ret_type, args_type, false);
    llvm::Function *func = llvm::Function::Create(
        funcType, llvm::Function::ExternalLinkage, name, &M);
    int count = 0;
    for (auto &arg : func->args()) {
      arg.setName(args[count++].second);
    }
    return Function{*this, *func};
  }

  //------------------- Basic Block -------------------------------------------

  struct BasicBlock {
    LLVMCodeGen &CG;
    llvm::BasicBlock &BB;
    BasicBlock(LLVMCodeGen &cg, llvm::BasicBlock &bb) : CG(cg), BB(bb) {}
    operator llvm::BasicBlock *() { return &BB; }
    void set() { CG.Builder.SetInsertPoint(&BB); }

  };

  BasicBlock mkBasicBlock(Function &func, std::string name) {
    llvm::BasicBlock *bb = llvm::BasicBlock::Create(Context, name, func);
    return BasicBlock{*this, *bb};
  }

  // ------------- type & vals

  Type mkInt() { return Type(*this, Type::int32); }
  Value mkInt(int val) { return {*this, *Builder.getInt32(val)}; }
  Type mkFloat() { return Type(*this, Type::float32); }
  Type mkDouble() { return Type(*this, Type::float64); }

  //-------------------- Ops

  void mkRet(Value val) { Builder.CreateRet(val); }
};

static llvm::LLVMContext &ContextRef = llvm::getGlobalContext();
static llvm::Module *ModuleOb = new llvm::Module("my compiler", ContextRef);

int main(int argc, char *argv[]) {
  static llvm::IRBuilder<> BuilderObj(ContextRef);
  LLVMCodeGen cg(ContextRef, *ModuleOb, BuilderObj);

  auto gvar = cg.mkGlobalVar("x", cg.mkFloat());

  auto f = cg.mkFunction("foo", cg.mkInt(),
                         {{cg.mkInt(), "a"}, {cg.mkFloat(), "b"}});
  auto entry = cg.mkBasicBlock(f, "entry");
  entry.set();

  auto constant = cg.mkInt(16);
  auto val      = constant * f.arg(0);
  cg.mkRet(val);

  f.verify();

  cg.dump();
  return 0;
}
<commit_msg>move basic block creation under function<commit_after>#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Verifier.h>
#include <vector>
#include <string>

struct LLVMCodeGen {
  using IRBuilder = llvm::IRBuilder<>;
  llvm::LLVMContext &Context;
  llvm::Module &M;
  IRBuilder &Builder;

  LLVMCodeGen(llvm::LLVMContext &context, llvm::Module &m,
              llvm::IRBuilder<> &builder)
      : Context(context), M(m), Builder(builder) {}
  void dump() const { M.dump(); }

  // -----------------------  Value -------------------------------------------
  struct Value {
    LLVMCodeGen &CG;
    llvm::Value &V;

    Value(LLVMCodeGen &cg, llvm::Value &value) : CG(cg), V(value) {}

    operator llvm::Value *() { return &V; }

    Value operator*(Value R) const {
      return Value{CG, *CG.Builder.CreateMul(&V, R, "mul")};
    }
  };

  //----------------------- Type ---------------------------------------------

  struct Type {
    enum Kind { int32, float32, float64 };

    LLVMCodeGen const &CG;
    Kind TypeKind;

    Type(LLVMCodeGen const &cg, Kind type_kind) : CG(cg), TypeKind(type_kind) {}

    operator llvm::Type *() const {
      switch (TypeKind) {
      case int32:
        return CG.Builder.getInt32Ty();
      case float32:
        return CG.Builder.getFloatTy();
      case float64:
        return CG.Builder.getDoubleTy();
      default:
        assert(0 && "Must not happen");
      }
    }

    size_t size() const {
      switch (TypeKind) {
      case int32:
      case float32:
        return 4;
      case float64:
        return 8;
      default:
        assert(0 && "Must not happen");
      }
      return 0;
    }
  };

  // --------------------- Global Variable -----------------------------------

  struct GlobalVar {
    LLVMCodeGen &CG;
    llvm::GlobalVariable &Var;
    GlobalVar(LLVMCodeGen &cg, llvm::GlobalVariable &var)
        : CG(cg), Var(var) {}
  };

  GlobalVar mkGlobalVar(std::string name, Type type) {
    M.getOrInsertGlobal(name, type);
    llvm::GlobalVariable *gvar = M.getNamedGlobal(name);
    gvar->setLinkage(llvm::GlobalValue::CommonLinkage);
    gvar->setAlignment(type.size());
    return GlobalVar{*this, *gvar};
  }

  //------------------- Basic Block -------------------------------------------

  struct BasicBlock {
    LLVMCodeGen &CG;
    llvm::BasicBlock &BB;
    BasicBlock(LLVMCodeGen &cg, llvm::BasicBlock &bb) : CG(cg), BB(bb) {}
    operator llvm::BasicBlock *() { return &BB; }
    void set() { CG.Builder.SetInsertPoint(&BB); }

  };

  //---------------------- Function -------------------------------------------

  struct Function {
    LLVMCodeGen &CG;
    llvm::Function &F;
    std::vector<llvm::Value*> Args;
    Function(LLVMCodeGen &cg, llvm::Function &f) : CG(cg), F(f) {
      Args.reserve(16);
      for (auto &arg : F.args()) {
        Args.push_back(&arg);
      }
    }
    void verify() const { llvm::verifyFunction(F); }

    operator llvm::Function *() { return &F; }

    Value arg(size_t num) const {
      assert(num < Args.size());
      return Value{CG, *Args[num]};
    }

    BasicBlock mkBasicBlock(std::string name) {
      llvm::BasicBlock *bb = llvm::BasicBlock::Create(CG.Context, name, &F);
      return {CG, *bb};
    }
  };

  Function mkFunction(std::string name, Type ret_type,
                      std::vector<std::pair<Type, std::string>> args = {}) {
    std::vector<llvm::Type*> args_type;
    args_type.reserve(args.size());
    for (auto arg : args) {
      args_type.push_back(arg.first);
    }
    llvm::FunctionType *funcType =
        llvm::FunctionType::get(ret_type, args_type, false);
    llvm::Function *func = llvm::Function::Create(
        funcType, llvm::Function::ExternalLinkage, name, &M);
    int count = 0;
    for (auto &arg : func->args()) {
      arg.setName(args[count++].second);
    }
    return Function{*this, *func};
  }

  // ------------- type & vals

  Type mkInt() { return Type(*this, Type::int32); }
  Value mkInt(int val) { return {*this, *Builder.getInt32(val)}; }
  Type mkFloat() { return Type(*this, Type::float32); }
  Type mkDouble() { return Type(*this, Type::float64); }

  //-------------------- Ops

  void mkRet(Value val) { Builder.CreateRet(val); }
};

static llvm::LLVMContext &ContextRef = llvm::getGlobalContext();
static llvm::Module *ModuleOb = new llvm::Module("my compiler", ContextRef);

int main(int argc, char *argv[]) {
  static llvm::IRBuilder<> BuilderObj(ContextRef);
  LLVMCodeGen cg(ContextRef, *ModuleOb, BuilderObj);

  auto gvar = cg.mkGlobalVar("x", cg.mkFloat());

  auto f = cg.mkFunction("foo", cg.mkInt(),
                         {{cg.mkInt(), "a"}, {cg.mkFloat(), "b"}});
  auto entry = f.mkBasicBlock("entry");
  entry.set();

  auto constant = cg.mkInt(16);
  auto val      = constant * f.arg(0);
  cg.mkRet(val);

  f.verify();

  cg.dump();
  return 0;
}
<|endoftext|>


<commit_before>/***************************************************************************
                          FilterPAB.cxx  -  description
                             -------------------
    begin                : Fri Jun 30 2000
    copyright            : (C) 2000 by Hans Dijkema
    email                : kmailcvt@hum.org
 ***************************************************************************/

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

#include "filter_pab.hxx"
#include "pablib.hxx"

#include <kfiledialog.h>

FilterPAB::FilterPAB() : Filter(i18n("Import MS Exchange Personal Address Book (.PAB)"),"Hans Dijkema")
{
}

FilterPAB::~FilterPAB()
{
}

void FilterPAB::import(FilterInfo *info)
{
  QString  file;
  QWidget *parent=info->parent();

  file=KFileDialog::getOpenFileName(QDir::homeDirPath(),"*.pab *.PAB *.Pab",parent);

  if (file.isEmpty()) {
    info->alert(i18n("No address book chosen"));
    return;
  }

  {
    pab PAB(QFile::encodeName(file),this,info);
    info->setFrom(file);
    info->setTo(i18n("KAddressBook"));
    info->setCurrent(i18n("Currently converting .PAB addresses to Kab"));
    PAB.convert();
    info->setCurrent(i18n("Finished converting .PAB addresses to Kab"));
  }
}

// vim: ts=2 sw=2 et
<commit_msg>Cleanup file filter code<commit_after>/***************************************************************************
                          FilterPAB.cxx  -  description
                             -------------------
    begin                : Fri Jun 30 2000
    copyright            : (C) 2000 by Hans Dijkema
    email                : kmailcvt@hum.org
 ***************************************************************************/

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

#include "filter_pab.hxx"
#include "pablib.hxx"

#include <kfiledialog.h>

FilterPAB::FilterPAB() : Filter(i18n("Import MS Exchange Personal Address Book (.PAB)"),"Hans Dijkema")
{
}

FilterPAB::~FilterPAB()
{
}

void FilterPAB::import(FilterInfo *info)
{
  QString file = KFileDialog::getOpenFileName(QDir::homeDirPath(),"*.[pP][aA][bB]|MS Personal Address Book Files (*.pab)", info->parent());

  if (file.isEmpty()) {
    info->alert(i18n("No address book chosen"));
    return;
  }

  {
    pab PAB(QFile::encodeName(file),this,info);
    info->setFrom(file);
    info->setTo(i18n("KAddressBook"));
    info->setCurrent(i18n("Currently converting .PAB addresses to Kab"));
    PAB.convert();
    info->setCurrent(i18n("Finished converting .PAB addresses to Kab"));
  }
}

// vim: ts=2 sw=2 et
<|endoftext|>


<commit_before>/********************************************************************
 *
 * Software License Agreement (BSD License)
 *
 * Copyright (c) 2012, Max-Planck-Gesellschaft
 * Copyright (c) 2012-2015, Inria
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of the copyright holder 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.
 *
 ********************************************************************/

#ifndef GENERICSUBSCRIBER_HPP_
#define GENERICSUBSCRIBER_HPP_

#include <boost/thread/mutex.hpp>

#include <semaphore.h>
//#include <sys/sem.h>
//#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <ros/node_handle.h>

#ifndef GENERATESEMAPHORENAME
#define GENERATESEMAPHORENAME

#endif

class GenericSubscriber_base {
public:
	static
	void resetSemaphore(sem_t* sem){
		int valp;
		sem_getvalue(sem, &valp);
		while ( valp > 0){
			sem_wait(sem);
			sem_getvalue(sem, &valp);
		}
	}

	static
	std::string generateSemaphoreName(std::string const & topicName) {
		std::string semName(topicName);
		if (topicName[0] == '/'){
			semName.erase(0,1);
		}
		std::replace(semName.begin(), semName.end(), '/', '_');
		semName = "slk." + semName;
		return semName;
	}
};

template <class T_>
class GenericSubscriber : public GenericSubscriber_base {
protected:
	boost::shared_ptr<T_ const> lastMsg;
	mutable boost::mutex lastMsgLock;
	const std::string semName;
	sem_t * newMsg;

	// Subscriber
	ros::Subscriber sub;

	void msgCallback(boost::shared_ptr<T_ const> msg) {
		boost::mutex::scoped_lock lock(lastMsgLock);
		lastMsg = msg;
		sem_post(newMsg);
	}

public:

	void resetSem(){
		boost::mutex::scoped_lock lock(lastMsgLock);
		resetSemaphore(newMsg);
	}

	int waitMsg(const double timeout=-1){
		if (timeout<0){
			return sem_wait(newMsg);
		} else {
			const int wait_sec = (int) timeout;
			const int wait_nsec = (int)((timeout - (int)timeout)*1e9);
			timespec waitSpec;
			clock_gettime(CLOCK_REALTIME, &waitSpec);
			waitSpec.tv_sec += wait_sec;
			waitSpec.tv_nsec += wait_nsec;
			return sem_timedwait(newMsg, &waitSpec);
		}
	}

	GenericSubscriber(ros::NodeHandle handle, const std::string& topicName, int queue_size) :
		semName(generateSemaphoreName(topicName)),
		newMsg(sem_open(semName.c_str(), O_CREAT, 0644, 0)),
		sub(handle.subscribe(topicName, queue_size, &GenericSubscriber<T_>::msgCallback, this)){
		//    	std::cout << "Opening semaphore in " << __func__ << " in file /dev/shm/sem." << semName << std::endl;

		if (newMsg == SEM_FAILED){
			//TODO: ssSetErrorStatus(S, strerror(errno));
			//    		std::cout << " returned SEM_FAILED with error: " << strerror(errno);
		}
	}

	virtual ~GenericSubscriber() {
		boost::mutex::scoped_lock lock(lastMsgLock);
		//        lastMsg = boost::shared_ptr<T_ const> (new T_);
		sem_close(newMsg);
		sem_unlink(semName.c_str());
	}

	boost::shared_ptr<T_ const> getLastMsg() const {
		boost::mutex::scoped_lock lock(lastMsgLock);
		return lastMsg;
	}

};

#endif /* GENERICSUBSCRIBER_HPP_ */
<commit_msg>get topic name from generic subscriber<commit_after>/********************************************************************
 *
 * Software License Agreement (BSD License)
 *
 * Copyright (c) 2012, Max-Planck-Gesellschaft
 * Copyright (c) 2012-2015, Inria
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of the copyright holder 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.
 *
 ********************************************************************/

#ifndef GENERICSUBSCRIBER_HPP_
#define GENERICSUBSCRIBER_HPP_

#include <boost/thread/mutex.hpp>

#include <semaphore.h>
//#include <sys/sem.h>
//#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <ros/node_handle.h>

#ifndef GENERATESEMAPHORENAME
#define GENERATESEMAPHORENAME

#endif

class GenericSubscriber_base {
public:
	static
	void resetSemaphore(sem_t* sem){
		int valp;
		sem_getvalue(sem, &valp);
		while ( valp > 0){
			sem_wait(sem);
			sem_getvalue(sem, &valp);
		}
	}

	static
	std::string generateSemaphoreName(std::string const & topicName) {
		std::string semName(topicName);
		if (topicName[0] == '/'){
			semName.erase(0,1);
		}
		std::replace(semName.begin(), semName.end(), '/', '_');
		semName = "slk." + semName;
		return semName;
	}
};

template <class T_>
class GenericSubscriber : public GenericSubscriber_base {
protected:
	boost::shared_ptr<T_ const> lastMsg;
	mutable boost::mutex lastMsgLock;
	const std::string semName;
	sem_t * newMsg;
	const std::string tName;

	// Subscriber
	ros::Subscriber sub;

	void msgCallback(boost::shared_ptr<T_ const> msg) {
		boost::mutex::scoped_lock lock(lastMsgLock);
		lastMsg = msg;
		sem_post(newMsg);
	}

public:

	std::string getTopicName(){return tName;};

	void resetSem(){
		boost::mutex::scoped_lock lock(lastMsgLock);
		resetSemaphore(newMsg);
	}

	int waitMsg(const double timeout=-1){
		if (timeout<0){
			return sem_wait(newMsg);
		} else {
			const int wait_sec = (int) timeout;
			const int wait_nsec = (int)((timeout - (int)timeout)*1e9);
			timespec waitSpec;
			clock_gettime(CLOCK_REALTIME, &waitSpec);
			waitSpec.tv_sec += wait_sec;
			waitSpec.tv_nsec += wait_nsec;
			return sem_timedwait(newMsg, &waitSpec);
		}
	}

	GenericSubscriber(ros::NodeHandle handle, const std::string& topicName, int queue_size) :
		semName(generateSemaphoreName(topicName)),
		newMsg(sem_open(semName.c_str(), O_CREAT, 0644, 0)),
		sub(handle.subscribe(topicName, queue_size, &GenericSubscriber<T_>::msgCallback, this)),
		tName(topicName){
		//    	std::cout << "Opening semaphore in " << __func__ << " in file /dev/shm/sem." << semName << std::endl;

		if (newMsg == SEM_FAILED){
			//TODO: ssSetErrorStatus(S, strerror(errno));
			//    		std::cout << " returned SEM_FAILED with error: " << strerror(errno);
		}
	}

	virtual ~GenericSubscriber() {
		boost::mutex::scoped_lock lock(lastMsgLock);
		//        lastMsg = boost::shared_ptr<T_ const> (new T_);
		sem_close(newMsg);
		sem_unlink(semName.c_str());
	}

	boost::shared_ptr<T_ const> getLastMsg() const {
		boost::mutex::scoped_lock lock(lastMsgLock);
		return lastMsg;
	}

};

#endif /* GENERICSUBSCRIBER_HPP_ */
<|endoftext|>


<commit_before>/*
    knrangefilter.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <qlabel.h>
#include <qlayout.h>
#include <qcheckbox.h>
#include <qcombobox.h>

#include <ksimpleconfig.h>
#include <knuminput.h>

#include "knrangefilter.h"

bool KNRangeFilter::doFilter(int a)
{
  bool ret=true;
  if(enabled) {
    switch (op1) {
      case gt:
      case gtoeq:
          if (op2 != dis)
            ret=( matchesOp(val1,op1,a) && matchesOp(a,op2,val2) );
          else
            ret = matchesOp(val1,op1,a);;
          break;
      case eq:
      case lt:
      case ltoeq:
          ret = matchesOp(val1,op1,a);
          break;
      default:
          ret = false;
    }
  }

  return ret;
}

bool KNRangeFilter::matchesOp(int v1, Op o, int v2)
{
  bool ret=false;

  switch(o) {
    case eq:      ret=(v1==v2);   break;
    case gt:      ret=(v1<v2);    break;
    case gtoeq:   ret=(v1<=v2);   break;
    case ltoeq:   ret=(v1>=v2);   break;
    case lt:      ret=(v1>v2);    break;
    default:      ret=false;      break;
  };

  return ret;
}

void KNRangeFilter::load(KSimpleConfig *conf)
{
  enabled=conf->readBoolEntry("enabled", false);
  val1=conf->readNumEntry("val1",0);
  op1=(Op) conf->readNumEntry("op1",0);
  val2=conf->readNumEntry("val2",0);
  op2=(Op) conf->readNumEntry("op2",0);
}

void KNRangeFilter::save(KSimpleConfig *conf)
{
  conf->writeEntry("enabled", enabled);
  conf->writeEntry("val1", val1);
  conf->writeEntry("op1", (int)op1);
  conf->writeEntry("op2", (int)op2);
  conf->writeEntry("val2", val2);
}

//=====================================================================================
//=====================================================================================

KNRangeFilterWidget::KNRangeFilterWidget(const QString& value, int min, int max, QWidget* parent, const QString &unit)
  : QGroupBox(value, parent)
{
  enabled=new QCheckBox(this);

  val1=new KIntSpinBox(min, max, 1, min, 10, this);
  val1->setSuffix(unit);
  val2=new KIntSpinBox(min, max, 1, min, 10, this);
  val2->setSuffix(unit);

  op1=new QComboBox(this);
  op1->insertItem("<");
  op1->insertItem("<=");
  op1->insertItem("=");
  op1->insertItem(">=");
  op1->insertItem(">");
  op2=new QComboBox(this);
  op2->insertItem("");
  op2->insertItem("<");
  op2->insertItem("<=");

  des=new QLabel(value, this);
  des->setAlignment(AlignCenter);

  QGridLayout *topL=new QGridLayout(this, 2,6, 8,5 );

  topL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
  topL->addWidget(enabled,1,0, Qt::AlignHCenter);
  topL->addColSpacing(0, 30);
  topL->addWidget(val1,1,1);
  topL->addWidget(op1,1,2);
  topL->addWidget(des,1,3);
  topL->addColSpacing(3, 45);
  topL->addWidget(op2,1,4);
  topL->addWidget(val2,1,5);
  topL->setColStretch(1,1);
  topL->setColStretch(5,1);

  connect(op1, SIGNAL(activated(int)), SLOT(slotOp1Changed(int)));
  connect(op2, SIGNAL(activated(int)), SLOT(slotOp2Changed(int)));
  connect(enabled, SIGNAL(toggled(bool)), SLOT(slotEnabled(bool)));

  slotEnabled(false);
}

KNRangeFilterWidget::~KNRangeFilterWidget()
{
}

KNRangeFilter KNRangeFilterWidget::filter()
{
  KNRangeFilter r;
  r.val1=val1->value();
  r.val2=val2->value();

  r.op1=(KNRangeFilter::Op) op1->currentItem();
  if (op2->currentText().isEmpty())
    r.op2=KNRangeFilter::dis;
  else if (op2->currentText()=="<")
    r.op2=KNRangeFilter::gt;
  else if (op2->currentText()=="<=")
    r.op2=KNRangeFilter::gtoeq;

  r.enabled=enabled->isChecked();

  return r;
}

void KNRangeFilterWidget::setFilter(KNRangeFilter &f)
{
  val1->setValue(f.val1);
  val2->setValue(f.val2);

  op1->setCurrentItem((int)f.op1);
  if (f.op2 == KNRangeFilter::dis)
    op2->setCurrentItem(0);
  else if (f.op2 == KNRangeFilter::gt)
    op2->setCurrentItem(1);
  else if (f.op2 == KNRangeFilter::gtoeq)
    op2->setCurrentItem(2);

  enabled->setChecked(f.enabled);
}

void KNRangeFilterWidget::clear()
{
  val1->setValue(val1->minValue());
  val2->setValue(val2->minValue());
  enabled->setChecked(false);
}

void KNRangeFilterWidget::slotOp1Changed(int id)
{
  op2->setEnabled(op1->isEnabled() && (id<2));
  slotOp2Changed(op2->currentItem());
}

void KNRangeFilterWidget::slotOp2Changed(int id)
{
  val2->setEnabled(op1->isEnabled() && (op1->currentItem()<2) && (id>0));
}

void KNRangeFilterWidget::slotEnabled(bool e)
{
  op1->setEnabled(e);
  val1->setEnabled(e);
  des->setEnabled(e);
  slotOp1Changed(op1->currentItem());
}

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

#include "knrangefilter.moc"

<commit_msg>Minor fix<commit_after>/*
    knrangefilter.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <qlabel.h>
#include <qlayout.h>
#include <qcheckbox.h>
#include <qcombobox.h>

#include <ksimpleconfig.h>
#include <knuminput.h>

#include "knrangefilter.h"

bool KNRangeFilter::doFilter(int a)
{
  bool ret=true;
  if(enabled) {
    switch (op1) {
      case gt:
      case gtoeq:
          if (op2 != dis)
            ret=( matchesOp(val1,op1,a) && matchesOp(a,op2,val2) );
          else
            ret = matchesOp(val1,op1,a);;
          break;
      case eq:
      case lt:
      case ltoeq:
          ret = matchesOp(val1,op1,a);
          break;
      default:
          ret = false;
    }
  }

  return ret;
}

bool KNRangeFilter::matchesOp(int v1, Op o, int v2)
{
  bool ret=false;

  switch(o) {
    case eq:      ret=(v1==v2);   break;
    case gt:      ret=(v1<v2);    break;
    case gtoeq:   ret=(v1<=v2);   break;
    case ltoeq:   ret=(v1>=v2);   break;
    case lt:      ret=(v1>v2);    break;
    default:      ret=false;      break;
  };

  return ret;
}

void KNRangeFilter::load(KSimpleConfig *conf)
{
  enabled=conf->readBoolEntry("enabled", false);
  val1=conf->readNumEntry("val1",0);
  op1=(Op) conf->readNumEntry("op1",0);
  val2=conf->readNumEntry("val2",0);
  op2=(Op) conf->readNumEntry("op2",0);
}

void KNRangeFilter::save(KSimpleConfig *conf)
{
  conf->writeEntry("enabled", enabled);
  conf->writeEntry("val1", val1);
  conf->writeEntry("op1", (int)op1);
  conf->writeEntry("op2", (int)op2);
  conf->writeEntry("val2", val2);
}

//=====================================================================================
//=====================================================================================

KNRangeFilterWidget::KNRangeFilterWidget(const QString& value, int min, int max, QWidget* parent, const QString &unit)
  : QGroupBox(value, parent)
{
  enabled=new QCheckBox(this);

  val1=new KIntSpinBox(min, max, 1, min, 10, this);
  val1->setSuffix(unit);
  val2=new KIntSpinBox(min, max, 1, min, 10, this);
  val2->setSuffix(unit);

  op1=new QComboBox(this);
  op1->insertItem("<");
  op1->insertItem("<=");
  op1->insertItem("=");
  op1->insertItem(">=");
  op1->insertItem(">");
  op2=new QComboBox(this);
  op2->insertItem("");
  op2->insertItem("<");
  op2->insertItem("<=");

  des=new QLabel(value, this);
  des->setAlignment(AlignCenter);

  QGridLayout *topL=new QGridLayout(this, 2,6, 8,5 );

  topL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
  topL->addWidget(enabled,1,0, Qt::AlignHCenter);
  topL->addColSpacing(0, 30);
  topL->addWidget(val1,1,1);
  topL->addWidget(op1,1,2);
  topL->addWidget(des,1,3);
  topL->addColSpacing(3, 45);
  topL->addWidget(op2,1,4);
  topL->addWidget(val2,1,5);
  topL->setColStretch(1,1);
  topL->setColStretch(5,1);

  connect(op1, SIGNAL(activated(int)), SLOT(slotOp1Changed(int)));
  connect(op2, SIGNAL(activated(int)), SLOT(slotOp2Changed(int)));
  connect(enabled, SIGNAL(toggled(bool)), SLOT(slotEnabled(bool)));

  slotEnabled(false);
}

KNRangeFilterWidget::~KNRangeFilterWidget()
{
}

KNRangeFilter KNRangeFilterWidget::filter()
{
  KNRangeFilter r;
  r.val1=val1->value();
  r.val2=val2->value();

  r.op1=(KNRangeFilter::Op) op1->currentItem();
  if (op2->currentText().isEmpty())
    r.op2=KNRangeFilter::dis;
  else if (op2->currentText()=="<")
    r.op2=KNRangeFilter::gt;
  else if (op2->currentText()=="<=")
    r.op2=KNRangeFilter::gtoeq;

  r.enabled=enabled->isChecked();

  return r;
}

void KNRangeFilterWidget::setFilter(KNRangeFilter &f)
{
  val1->setValue(f.val1);
  val2->setValue(f.val2);

  op1->setCurrentItem((int)f.op1);
  if (f.op2 == KNRangeFilter::dis)
    op2->setCurrentItem(0);
  else if (f.op2 == KNRangeFilter::gt)
    op2->setCurrentItem(1);
  else if (f.op2 == KNRangeFilter::gtoeq)
    op2->setCurrentItem(2);

  enabled->setChecked(f.enabled);
}

void KNRangeFilterWidget::clear()
{
  val1->setValue(val1->minValue());
  val2->setValue(val2->minValue());
  enabled->setChecked(false);
}

void KNRangeFilterWidget::slotOp1Changed(int id)
{
    bool state = (op1->isEnabled() && (id<2));
  op2->setEnabled(state);
  des->setEnabled(state);
  slotOp2Changed(op2->currentItem());
}

void KNRangeFilterWidget::slotOp2Changed(int id)
{
  val2->setEnabled(op1->isEnabled() && (op1->currentItem()<2) && (id>0));
}

void KNRangeFilterWidget::slotEnabled(bool e)
{
  op1->setEnabled(e);
  val1->setEnabled(e);
  des->setEnabled(e);
  slotOp1Changed(op1->currentItem());
}

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

#include "knrangefilter.moc"

<|endoftext|>