<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
long long f(long long c,long long d){
	if(c<(2*d)) return 4*d;
	else return 4*(c-d);
}
long long mx(long c,long d){
	return 4*(c+d);
}
int main(int argc, char const *argv[]) {
	long long int t;
	cin>>t;
	while(t--){
		long long c,d,l;
		cin>>c>>d>>l;
		if(l%4!=0){cout<<"no\n";continue;}
		if(l<f(c,d))cout<<"no\n";
		else if(l>mx(c,d))cout<<"no\n";
		else cout<<"yes\n";
	}
	 return 0;
}
<commit_msg>small bug. done :)<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
long long f(long long c,long long d){
	if(c<(2*d)) return 4*d;
	else return 4*(c-d);
}
long long mx(long long c,long long d){
	return 4*(c+d);
}
int main(int argc, char const *argv[]) {
	long long int t;
	cin>>t;
	while(t--){
		long long c,d,l;
		cin>>c>>d>>l;
		if(l%4!=0){cout<<"no\n";continue;}
		if(l<f(c,d))cout<<"no\n";
		else if(l>mx(c,d))cout<<"no\n";
		else cout<<"yes\n";
	}
	 return 0;
}
<|endoftext|>


<commit_before>#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <sstream>

int const MIN_AREA = 30*30;

std::string const intToString(int n){
	std::stringstream ss;
	ss << n;
	return ss.str();
}

void const drawObject(cv::Point const &center, cv::Mat &frame, bool showCoords = false){
	cv::Scalar color(0, 255, 0);
	cv::circle(frame, center, 15, color, 2);
	if(showCoords){
		std::string coords = "x" + intToString(center.x) + " y" + intToString(center.y);
		cv::putText(frame, coords, cv::Point(center.x + 20, center.y), 1, 1, color, 1);
	}
}

cv::Point const findObject(cv::Mat const &imgThresholed){
	int posX = 0, posY = 0;
	cv::Moments mom = moments(imgThresholed);
	if(mom.m00 > MIN_AREA){
		posX = mom.m10 / mom.m00;
		posY = mom.m01 / mom.m00;
	}
	return cv::Point(posX, posY);
}

void const morphOps(cv::Mat &img, cv::Mat const &structuringElement){
	//morphological opening (remove small objects from the foreground)
	cv::erode(img, img, structuringElement);
	cv::dilate(img, img, structuringElement);
	//morphological closing (fill small holes in the foreground)
	cv::dilate(img, img, structuringElement);
	cv::erode(img, img, structuringElement);
}

void const intro(){
	using namespace std;
	cout << "ECS: Quit" << endl;
	cout << "SPACEBAR: toggle tracking" << endl;
	cout << "c: toggle coords" << endl;
}

int main(){
	using namespace cv;
	intro();

	VideoCapture cap(0);
	if(!cap.isOpened()){
		std::cerr << "could not open webcam!" << std::endl;
		return EXIT_FAILURE;
	}

	namedWindow("Control", CV_WINDOW_AUTOSIZE);
	int lowH = 0, highH = 179;
	int lowS = 0, highS = 255;
	int lowV = 0, highV = 255;

	cvCreateTrackbar("LowH", "Control", &lowH, 179);
	cvCreateTrackbar("HighH", "Control", &highH, 179);

	cvCreateTrackbar("LowS", "Control", &lowS, 255);
	cvCreateTrackbar("HighS", "Control", &highS, 255);

	cvCreateTrackbar("LowV", "Control", &lowV, 255);
	cvCreateTrackbar("HighV", "Control", &highV, 255);

	Mat imgOrginal, imgHSV, imgThresholded;
	Mat se = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
	bool tracking = false, showCoords = false;
	while(true){
		if(!cap.read(imgOrginal)){
			std::cerr << "could not read frame from video stream!" << std::endl;
			return EXIT_FAILURE;
		}

		cvtColor(imgOrginal, imgHSV, COLOR_BGR2HSV);
		inRange(imgHSV, Scalar(lowH, lowS, lowV), Scalar(highH, highS, highV), imgThresholded);

		morphOps(imgThresholded, se);
		imshow("Thresholded Image", imgThresholded);
		if(tracking){
			Point p = findObject(imgThresholded);
			if(p.x != 0 && p.y != 0){
				drawObject(p, imgOrginal, showCoords);
			}
		}
		imshow("Orginal", imgOrginal);

		int keyCode = waitKey(30);
		switch(keyCode){
			case 27: //ESC
				return EXIT_SUCCESS;
			break;
			case 32: //SPACEBAR
				tracking = !tracking;
			break;
			case 99: // c key
				showCoords = !showCoords;
			break;
			default:
				if(keyCode >= 0){
					std::cout << "keyCode: " << keyCode << std::endl;
				}
			break;
		}
	}

	return EXIT_SUCCESS;
}
<commit_msg>added possibility to input videofile<commit_after>#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <sstream>

int const MIN_AREA = 30*30;

std::string const intToString(int n){
	std::stringstream ss;
	ss << n;
	return ss.str();
}

void const drawObject(cv::Point const &center, cv::Mat &frame, bool showCoords = false){
	cv::Scalar color(0, 255, 0);
	cv::circle(frame, center, 15, color, 2);
	if(showCoords){
		std::string coords = "x" + intToString(center.x) + " y" + intToString(center.y);
		cv::putText(frame, coords, cv::Point(center.x + 20, center.y), 1, 1, color, 1);
	}
}

cv::Point const findObject(cv::Mat const &imgThresholed){
	int posX = 0, posY = 0;
	cv::Moments mom = moments(imgThresholed);
	if(mom.m00 > MIN_AREA){
		posX = mom.m10 / mom.m00;
		posY = mom.m01 / mom.m00;
	}
	return cv::Point(posX, posY);
}

void const morphOps(cv::Mat &img, cv::Mat const &structuringElement){
	//morphological opening (remove small objects from the foreground)
	cv::erode(img, img, structuringElement);
	cv::dilate(img, img, structuringElement);
	//morphological closing (fill small holes in the foreground)
	cv::dilate(img, img, structuringElement);
	cv::erode(img, img, structuringElement);
}

void const intro(){
	using namespace std;
	cout << "ECS: Quit" << endl;
	cout << "SPACEBAR: toggle tracking" << endl;
	cout << "c: toggle coords" << endl;
}

int main(int argc, char* argv[]){
	using namespace cv;
	intro();

	VideoCapture cap;
	if(argc == 2){
		cap.open(argv[1]);
	} else {
		cap.open(0);
	}

	if(!cap.isOpened()){
		std::cerr << "could not open webcam!" << std::endl;
		return EXIT_FAILURE;
	}

	//Control window
	namedWindow("Control", CV_WINDOW_AUTOSIZE);
	int lowH = 0, highH = 179;
	int lowS = 0, highS = 255;
	int lowV = 0, highV = 255;

	cvCreateTrackbar("LowH", "Control", &lowH, 179);
	cvCreateTrackbar("HighH", "Control", &highH, 179);

	cvCreateTrackbar("LowS", "Control", &lowS, 255);
	cvCreateTrackbar("HighS", "Control", &highS, 255);

	cvCreateTrackbar("LowV", "Control", &lowV, 255);
	cvCreateTrackbar("HighV", "Control", &highV, 255);
	////

	namedWindow("Orginal", CV_WINDOW_KEEPRATIO);
	namedWindow("Thresholded Image", CV_WINDOW_KEEPRATIO);

	Mat imgOrginal, imgHSV, imgThresholded;
	Mat se = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
	bool tracking = false, showCoords = false;
	while(true){
		if(!cap.read(imgOrginal)){
			std::cerr << "could not read frame from video stream!" << std::endl;
			return EXIT_FAILURE;
		}

		cvtColor(imgOrginal, imgHSV, COLOR_BGR2HSV);
		inRange(imgHSV, Scalar(lowH, lowS, lowV), Scalar(highH, highS, highV), imgThresholded);

		morphOps(imgThresholded, se);
		imshow("Thresholded Image", imgThresholded);
		if(tracking){
			Point p = findObject(imgThresholded);
			if(p.x != 0 && p.y != 0){
				drawObject(p, imgOrginal, showCoords);
			}
		}
		imshow("Orginal", imgOrginal);

		int keyCode = waitKey(30);
		switch(keyCode){
			case 27: //ESC
				return EXIT_SUCCESS;
				break;
			case 32: //SPACEBAR
				tracking = !tracking;
				break;
			case 99: // c key
				showCoords = !showCoords;
				break;
			default:
				if(keyCode >= 0){
					std::cout << "keyCode: " << keyCode << std::endl;
				}
				break;
		}
	}

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//
// Created by czfshine on 2017/10/20.
//

#include "gtest/gtest.h"
#include <vector>
#include "nstl_ttraits.h"
namespace {

    /**
     * 编写一个函数，接受一个vector对象，返回一个指针，指向vector的第三个元素，没有就为NULL
     * @return
     */
    template <class T >
     typename  NSTLSPACE::iterator_traits<typename T::iterator>::value_type * a(T& xs){
        if(xs.size()>=3){
            return &(xs[2]);
        }else{
            return nullptr;
        }
    }

    TEST(SAMPLE,TRAITS){
        std::vector<int> xs={1,2,3,5,6};
        auto b=a(xs);
        EXPECT_EQ(* b,3);
    }
}<commit_msg>修复拼写错误<commit_after>//
// Created by czfshine on 2017/10/20.
//

#include "gtest/gtest.h"
#include <vector>
#include "nstl_type_traits.h"
namespace {

    /**
     * 编写一个函数，接受一个vector对象，返回一个指针，指向vector的第三个元素，没有就为NULL
     * @return
     */
    template <class T >
     typename  NSTLSPACE::iterator_traits<typename T::iterator>::value_type * a(T& xs){
        if(xs.size()>=3){
            return &(xs[2]);
        }else{
            return nullptr;
        }
    }

    TEST(SAMPLE,TRAITS){
        std::vector<int> xs={1,2,3,5,6};
        auto b=a(xs);
        EXPECT_EQ(* b,3);
    }
}<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 */

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/parse.h>
#include <pcl/console/print.h>
#include <pcl/common/convolution.h>
#include <pcl/visualization/pcl_visualizer.h>

void
usage (char ** argv)
{
  pcl::console::print_info ("usage: %s <filename> <-r|-c|-s> [-p <borders policy>] [-t <number of threads>] [-d <distance>]\n\n", argv[0]);
  pcl::console::print_info ("Where options are:\n");
  pcl::console::print_info ("\t\t\t-r convolve rows\n");
  pcl::console::print_info ("\t\t\t-c convolve columns\n");
  pcl::console::print_info ("\t\t\t-s convolve separate\n");
  pcl::console::print_info ("\t\t\t-p borders policy\n");
  pcl::console::print_info ("\t\t\t\t Z zero padding, default\n");
  pcl::console::print_info ("\t\t\t\t D duplicate borders\n");
  pcl::console::print_info ("\t\t\t\t M mirror borders\n");
  pcl::console::print_info ("\t\t\t-t optional, number of threads, default 1\n");
  pcl::console::print_info ("\t\t\t-d optional, distance threshold, default 0.001\n");
}

int
main (int argc, char ** argv)
{
  int viewport_source, viewport_convolved = 0;
  int direction = -1;
  int nb_threads = 0;
  char border_policy = 'Z';
  double threshold = 0.001;
	pcl::common::Convolution<pcl::PointXYZRGB> convolution;
	Eigen::ArrayXf gaussian_kernel(5);
	gaussian_kernel << 1.f/16, 1.f/4, 3.f/8, 1.f/4, 1.f/16;
  pcl::console::print_info ("convolution kernel:");
  for (int i = 0; i < gaussian_kernel.size (); ++i)
    pcl::console::print_info (" %f", gaussian_kernel[i]);
  pcl::console::print_info ("\n");

  if (argc < 3)
  {
    usage (argv);
    return 1;
  }

  // check if user is requesting help
  std::string arg (argv[1]);

  if (arg == "--help" || arg == "-h")
  {
    usage (argv);
    return 1;
  }

  // user don't need help find convolving direction
  // convolve row
  if (pcl::console::find_switch (argc, argv, "-r"))
    direction = 0;
  else
  {
    // convolve column
    if (pcl::console::find_switch (argc, argv, "-c"))
      direction = 1;
    else
      // convolve both
      if (pcl::console::find_switch (argc, argv, "-s"))
        direction = 2;
      else
      {
        // wrong direction given print usage
        usage (argv);
        return 1;
      }
  }

  // number of threads if any
  if (pcl::console::parse_argument (argc, argv, "-t", nb_threads) != -1 )
  {
    if (nb_threads <= 0)
      nb_threads = 1;
  }
  convolution.setNumberOfThreads (nb_threads);

  // borders policy if any
  if (pcl::console::parse_argument (argc, argv, "-p", border_policy) != -1 )
  {
    switch (border_policy)
    {
      case 'Z' : convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::IGNORE);
        break;
      case 'M' : convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::MIRROR);
        break;
      case 'D' : convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::DUPLICATE);
        break;
      default :
      {
        usage (argv);
        return (1);
      }
    }
  }
  else
    convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::IGNORE);

  // distance threshold if any
  if (pcl::console::parse_argument (argc, argv, "-d", threshold) == -1 )
  {
    threshold = 0.001;
  }
  convolution.setDistanceThreshold (static_cast<float> (threshold));

  // all set
  // we have file name and convolving direction
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB> ());
	if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
  {
    pcl::console::print_error ("Couldn't read file %s \n", argv[1]);
    return (-1);
  }
	cloud->is_dense = false;
	convolution.setInputCloud (cloud);
	convolution.setKernel (gaussian_kernel);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr convolved (new pcl::PointCloud<pcl::PointXYZRGB> ());

  double t0;
  pcl::console::print_info ("convolving %s along \n", argv[1]);
  std::ostringstream convolved_label;
  convolved_label << "convolved along ";
  switch (direction)
  {
    case 0:
    {
      convolved_label << "rows... ";
      t0 = pcl::getTime ();
      convolution.convolveRows (*convolved);
      break;
    }
    case 1:
    {
      convolved_label << "columns... ";
      t0 = pcl::getTime ();
      convolution.convolveCols (*convolved);
      break;
    }
    case 2:
    {
      convolved_label << "rows and columns... ";
      t0 = pcl::getTime ();
      convolution.convolve (*convolved);
      break;
    }
  }
  convolved_label << pcl::getTime () - t0 << "s";
  // Display
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("Convolution"));
  // viewport stuff
  viewer->createViewPort (0, 0, 0.5, 1, viewport_source);
  viewer->createViewPort (0.5, 0, 1, 1, viewport_convolved);
  viewer->setBackgroundColor (0, 0, 0);

  // Source
  pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_source (cloud);
  viewer->addPointCloud<pcl::PointXYZRGB> (cloud, color_handler_source, "source", viewport_source);
  viewer->addText ("source", 10, 10, "source_label", viewport_source);

  // Convolved
	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_convolved (convolved);
  viewer->addPointCloud<pcl::PointXYZRGB> (convolved, color_handler_convolved, "convolved", viewport_convolved);
  viewer->addText (convolved_label.str (), 10, 10, "convolved_label", viewport_convolved);
	viewer->spin ();
}
<commit_msg>Update to fit new headers<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 */

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/parse.h>
#include <pcl/console/print.h>
#include <pcl/filters/convolution.h>
#include <pcl/visualization/pcl_visualizer.h>

void
usage (char ** argv)
{
  pcl::console::print_info ("usage: %s <filename> <-r|-c|-s> [-p <borders policy>] [-t <number of threads>] [-d <distance>]\n\n", argv[0]);
  pcl::console::print_info ("Where options are:\n");
  pcl::console::print_info ("\t\t\t-r convolve rows\n");
  pcl::console::print_info ("\t\t\t-c convolve columns\n");
  pcl::console::print_info ("\t\t\t-s convolve separate\n");
  pcl::console::print_info ("\t\t\t-p borders policy\n");
  pcl::console::print_info ("\t\t\t\t Z zero padding, default\n");
  pcl::console::print_info ("\t\t\t\t D duplicate borders\n");
  pcl::console::print_info ("\t\t\t\t M mirror borders\n");
  pcl::console::print_info ("\t\t\t-t optional, number of threads, default 1\n");
  pcl::console::print_info ("\t\t\t-d optional, distance threshold, default 0.001\n");
}

int
main (int argc, char ** argv)
{
  int viewport_source, viewport_convolved = 0;
  int direction = -1;
  int nb_threads = 0;
  char border_policy = 'Z';
  double threshold = 0.001;
  pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB> convolution;
  Eigen::ArrayXf gaussian_kernel(5);
  gaussian_kernel << 1.f/16, 1.f/4, 3.f/8, 1.f/4, 1.f/16;
  pcl::console::print_info ("convolution kernel:");
  for (int i = 0; i < gaussian_kernel.size (); ++i)
    pcl::console::print_info (" %f", gaussian_kernel[i]);
  pcl::console::print_info ("\n");

  if (argc < 3)
  {
    usage (argv);
    return 1;
  }

  // check if user is requesting help
  std::string arg (argv[1]);

  if (arg == "--help" || arg == "-h")
  {
    usage (argv);
    return 1;
  }

  // user don't need help find convolving direction
  // convolve row
  if (pcl::console::find_switch (argc, argv, "-r"))
    direction = 0;
  else
  {
    // convolve column
    if (pcl::console::find_switch (argc, argv, "-c"))
      direction = 1;
    else
      // convolve both
      if (pcl::console::find_switch (argc, argv, "-s"))
        direction = 2;
      else
      {
        // wrong direction given print usage
        usage (argv);
        return 1;
      }
  }

  // number of threads if any
  if (pcl::console::parse_argument (argc, argv, "-t", nb_threads) != -1 )
  {
    if (nb_threads <= 0)
      nb_threads = 1;
  }
  convolution.setNumberOfThreads (nb_threads);

  // borders policy if any
  if (pcl::console::parse_argument (argc, argv, "-p", border_policy) != -1 )
  {
    switch (border_policy)
    {
      case 'Z' : convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_IGNORE);
        break;
      case 'M' : convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_MIRROR);
        break;
      case 'D' : convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_DUPLICATE);
        break;
      default :
      {
        usage (argv);
        return (1);
      }
    }
  }
  else
    convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_IGNORE);

  // distance threshold if any
  if (pcl::console::parse_argument (argc, argv, "-d", threshold) == -1 )
  {
    threshold = 0.01;
  }
  convolution.setDistanceThreshold (static_cast<float> (threshold));

  // all set
  // we have file name and convolving direction
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB> ());
  if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
  {
    pcl::console::print_error ("Couldn't read file %s \n", argv[1]);
    return (-1);
  }
  cloud->is_dense = false;
  convolution.setInputCloud (cloud);
  convolution.setKernel (gaussian_kernel);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr convolved (new pcl::PointCloud<pcl::PointXYZRGB> ());
  double t0;
  pcl::console::print_info ("convolving %s along \n", argv[1]);
  std::ostringstream convolved_label;
  convolved_label << "convolved along ";
  switch (direction)
  {
    case 0:
    {
      convolved_label << "rows... ";
      t0 = pcl::getTime ();
      convolution.convolveRows (*convolved);
      break;
    }
    case 1:
    {
      convolved_label << "columns... ";
      t0 = pcl::getTime ();
      convolution.convolveCols (*convolved);
      break;
    }
    case 2:
    {
      convolved_label << "rows and columns... ";
      t0 = pcl::getTime ();
      convolution.convolve (*convolved);
      break;
    }
  }
  convolved_label << pcl::getTime () - t0 << "s";
  // Display
  boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("Convolution"));
  // viewport stuff
  viewer->createViewPort (0, 0, 0.5, 1, viewport_source);
  viewer->createViewPort (0.5, 0, 1, 1, viewport_convolved);
  viewer->setBackgroundColor (0, 0, 0);

  // Source
  pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_source (cloud);
  viewer->addPointCloud<pcl::PointXYZRGB> (cloud, color_handler_source, "source", viewport_source);
  viewer->addText ("source", 10, 10, "source_label", viewport_source);

  // Convolved
  pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_convolved (convolved);
  viewer->addPointCloud<pcl::PointXYZRGB> (convolved, color_handler_convolved, "convolved", viewport_convolved);
  viewer->addText (convolved_label.str (), 10, 10, "convolved_label", viewport_convolved);
  viewer->spin ();
  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZRGB> ("convolved.pcd", *convolved, false);
}
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2014 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// 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

#include "word_splitter.hpp"

#include <vector>

namespace jubatus {
namespace core {
namespace fv_converter {

void word_splitter::extract(
    const std::string& text,
    std::vector<string_feature_element>& result) const {
  std::vector<std::pair<size_t, size_t> > boundaries;
  split(text, boundaries);

  std::vector<string_feature_element> elements;
  for (size_t i = 0; i < boundaries.size(); ++i) {
    size_t begin = boundaries[i].first;
    size_t length = boundaries[i].second;
    elements.push_back(
        string_feature_element(
            begin,
            length,
            text.substr(begin, length),
            1.0));
  }
  elements.swap(result);
}

}  // namespace fv_converter
}  // namespace core
}  // namespace jubatus
<commit_msg>Add missing includes<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2014 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// 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

#include "word_splitter.hpp"

#include <string>
#include <utility>
#include <vector>

namespace jubatus {
namespace core {
namespace fv_converter {

void word_splitter::extract(
    const std::string& text,
    std::vector<string_feature_element>& result) const {
  std::vector<std::pair<size_t, size_t> > boundaries;
  split(text, boundaries);

  std::vector<string_feature_element> elements;
  for (size_t i = 0; i < boundaries.size(); ++i) {
    size_t begin = boundaries[i].first;
    size_t length = boundaries[i].second;
    elements.push_back(
        string_feature_element(
            begin,
            length,
            text.substr(begin, length),
            1.0));
  }
  elements.swap(result);
}

}  // namespace fv_converter
}  // namespace core
}  // namespace jubatus
<|endoftext|>


<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.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.

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

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QGroupBox>
#include <QLabel>
#include <QLayout>
#include <QListWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QGridLayout>

#include <KDialogButtonBox>
#include <kcombobox.h>
#include <kconfig.h>
#include <kdialog.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <klineedit.h>
#include <QDBusMessage>
#include <QDBusConnection>
#include "addresseewidget.h"

NamePartWidget::NamePartWidget( const QString &title, const QString &label,
                                QWidget *parent, const char *name )
  : QWidget( parent ), mTitle( title ), mLabel( label )
{
  setObjectName( name );
  QHBoxLayout *layout = new QHBoxLayout( this );
  layout->setSpacing( KDialog::spacingHint() );
  layout->setMargin( 0 );

  QGroupBox *group = new QGroupBox( title, this );
  QGridLayout *groupLayout = new QGridLayout();
  groupLayout->setSpacing( KDialog::spacingHint() );
  groupLayout->setMargin( KDialog::marginHint() );
  group->setLayout( groupLayout );

  mBox = new QListWidget( group );
  connect( mBox,
           SIGNAL( currentItemChanged( QListWidgetItem *, QListWidgetItem * ) ),
           SLOT( selectionChanged( QListWidgetItem * ) ) );
  groupLayout->addWidget( mBox, 0, 0 );

  KDialogButtonBox *bbox = new KDialogButtonBox( group, Qt::Vertical );
  mAddButton = bbox->addButton( i18n( "Add..." ), QDialogButtonBox::ActionRole, this,  SLOT( add() ) );
  mEditButton = bbox->addButton( i18n( "Edit..." ), QDialogButtonBox::ActionRole, this,  SLOT( edit() ) );
  mEditButton->setEnabled( false );
  mRemoveButton = bbox->addButton( i18n( "Remove" ), QDialogButtonBox::ActionRole, this,  SLOT( remove() ) );
  mRemoveButton->setEnabled( false );
  bbox->layout();
  groupLayout->addWidget( bbox, 0, 1 );

  layout->addWidget( group );
}

NamePartWidget::~NamePartWidget()
{
}

void NamePartWidget::setNameParts( const QStringList &list )
{
  mBox->clear();
  mBox->addItems( list );
}

QStringList NamePartWidget::nameParts() const
{
  QStringList parts;
  for ( int i = 0; i < mBox->count(); ++i )
    parts.append( mBox->item( i )->text() );

  return parts;
}

void NamePartWidget::add()
{
  bool ok;

  QString namePart = KInputDialog::getText( i18n( "New" ), mLabel,
                                            QString(), &ok );
  if ( ok && !namePart.isEmpty() ) {
    mBox->addItem( namePart );
    emit modified();
  }
}

void NamePartWidget::edit()
{
  bool ok;

  QListWidgetItem *item = mBox->currentItem();
  if ( !item )
    return;

  QString namePart = KInputDialog::getText( i18n( "Edit" ), mLabel,
                                            item->text(), &ok );
  if ( ok && !namePart.isEmpty() ) {
    item->setText( namePart );
    emit modified();
  }
}

void NamePartWidget::remove()
{
  mBox->takeItem( mBox->currentRow() );
  if ( mBox->count() == 0 )
    selectionChanged( 0 );

  emit modified();
}

void NamePartWidget::selectionChanged( QListWidgetItem *item )
{
  mEditButton->setEnabled( item );
  mRemoveButton->setEnabled( item );
}

AddresseeWidget::AddresseeWidget( QWidget *parent, const char *name )
  : QWidget( parent )
{
  setObjectName( name );
  QGridLayout *layout = new QGridLayout( this );
  layout->setSpacing( KDialog::spacingHint() );
  layout->setMargin( KDialog::marginHint() );

  mPrefix = new NamePartWidget( i18n( "Prefixes"), i18n( "Enter prefix:" ), this );
  layout->addWidget( mPrefix, 0, 0 );

  mInclusion = new NamePartWidget( i18n( "Inclusions"), i18n( "Enter inclusion:" ), this );
  layout->addWidget( mInclusion, 0, 1 );

  mSuffix = new NamePartWidget( i18n( "Suffixes" ), i18n( "Enter suffix:" ), this );
  layout->addWidget( mSuffix, 0, 2 );

  QLabel *label = new QLabel( i18n( "Default formatted name:" ), this );
  layout->addWidget( label, 1, 0 );

  mFormattedNameCombo = new KComboBox( this );
  mFormattedNameCombo->addItem( i18n( "Empty" ) );
  mFormattedNameCombo->addItem( i18n( "Simple Name" ) );
  mFormattedNameCombo->addItem( i18n( "Full Name" ) );
  mFormattedNameCombo->addItem( i18n( "Reverse Name with Comma" ) );
  mFormattedNameCombo->addItem( i18n( "Reverse Name" ) );
  layout->addWidget( mFormattedNameCombo, 1, 1, 1, 2 );

  connect( mPrefix, SIGNAL( modified() ), SIGNAL( modified() ) );
  connect( mInclusion, SIGNAL( modified() ), SIGNAL( modified() ) );
  connect( mSuffix, SIGNAL( modified() ), SIGNAL( modified() ) );
  connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SIGNAL( modified() ) );
}

AddresseeWidget::~AddresseeWidget()
{
}

void AddresseeWidget::restoreSettings()
{
  KConfig _config( "kabcrc" );
  KConfigGroup config(&_config, "General" );

  mPrefix->setNameParts( config.readEntry( "Prefixes" , QStringList() ) );
  mInclusion->setNameParts( config.readEntry( "Inclusions" , QStringList() ) );
  mSuffix->setNameParts( config.readEntry( "Suffixes" , QStringList() ) );

  KConfig _cfg( "kaddressbookrc" );
  KConfigGroup cfg(&_cfg, "General" );
  mFormattedNameCombo->setCurrentIndex( cfg.readEntry( "FormattedNameType", 1 ) );
}

void AddresseeWidget::saveSettings()
{
  KConfig _config( "kabcrc" );
  KConfigGroup config(&_config, "General" );

  config.writeEntry( "Prefixes", mPrefix->nameParts() );
  config.writeEntry( "Inclusions", mInclusion->nameParts() );
  config.writeEntry( "Suffixes", mSuffix->nameParts() );

  KConfig _cfg( "kaddressbookrc" );
  KConfigGroup cfg(&_cfg, "General" );
  cfg.writeEntry( "FormattedNameType", mFormattedNameCombo->currentIndex() );

   QDBusMessage message =
       QDBusMessage::createSignal(QString(), "org.kde.kabc.AddressBookConfig", "changed");
   QDBusConnection::sessionBus().send(message);

}

#include "addresseewidget.moc"
<commit_msg>* "Uncommented" crash b/c of successless dbus call<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.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.

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

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QGroupBox>
#include <QLabel>
#include <QLayout>
#include <QListWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QGridLayout>

#include <KDialogButtonBox>
#include <kcombobox.h>
#include <kconfig.h>
#include <kdialog.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <klineedit.h>
#include <QDBusMessage>
#include <QDBusConnection>
#include "addresseewidget.h"

NamePartWidget::NamePartWidget( const QString &title, const QString &label,
                                QWidget *parent, const char *name )
  : QWidget( parent ), mTitle( title ), mLabel( label )
{
  setObjectName( name );
  QHBoxLayout *layout = new QHBoxLayout( this );
  layout->setSpacing( KDialog::spacingHint() );
  layout->setMargin( 0 );

  QGroupBox *group = new QGroupBox( title, this );
  QGridLayout *groupLayout = new QGridLayout();
  groupLayout->setSpacing( KDialog::spacingHint() );
  groupLayout->setMargin( KDialog::marginHint() );
  group->setLayout( groupLayout );

  mBox = new QListWidget( group );
  connect( mBox,
           SIGNAL( currentItemChanged( QListWidgetItem *, QListWidgetItem * ) ),
           SLOT( selectionChanged( QListWidgetItem * ) ) );
  groupLayout->addWidget( mBox, 0, 0 );

  KDialogButtonBox *bbox = new KDialogButtonBox( group, Qt::Vertical );
  mAddButton = bbox->addButton( i18n( "Add..." ), QDialogButtonBox::ActionRole, this,  SLOT( add() ) );
  mEditButton = bbox->addButton( i18n( "Edit..." ), QDialogButtonBox::ActionRole, this,  SLOT( edit() ) );
  mEditButton->setEnabled( false );
  mRemoveButton = bbox->addButton( i18n( "Remove" ), QDialogButtonBox::ActionRole, this,  SLOT( remove() ) );
  mRemoveButton->setEnabled( false );
  bbox->layout();
  groupLayout->addWidget( bbox, 0, 1 );

  layout->addWidget( group );
}

NamePartWidget::~NamePartWidget()
{
}

void NamePartWidget::setNameParts( const QStringList &list )
{
  mBox->clear();
  mBox->addItems( list );
}

QStringList NamePartWidget::nameParts() const
{
  QStringList parts;
  for ( int i = 0; i < mBox->count(); ++i )
    parts.append( mBox->item( i )->text() );

  return parts;
}

void NamePartWidget::add()
{
  bool ok;

  QString namePart = KInputDialog::getText( i18n( "New" ), mLabel,
                                            QString(), &ok );
  if ( ok && !namePart.isEmpty() ) {
    mBox->addItem( namePart );
    emit modified();
  }
}

void NamePartWidget::edit()
{
  bool ok;

  QListWidgetItem *item = mBox->currentItem();
  if ( !item )
    return;

  QString namePart = KInputDialog::getText( i18n( "Edit" ), mLabel,
                                            item->text(), &ok );
  if ( ok && !namePart.isEmpty() ) {
    item->setText( namePart );
    emit modified();
  }
}

void NamePartWidget::remove()
{
  mBox->takeItem( mBox->currentRow() );
  if ( mBox->count() == 0 )
    selectionChanged( 0 );

  emit modified();
}

void NamePartWidget::selectionChanged( QListWidgetItem *item )
{
  mEditButton->setEnabled( item );
  mRemoveButton->setEnabled( item );
}

AddresseeWidget::AddresseeWidget( QWidget *parent, const char *name )
  : QWidget( parent )
{
  setObjectName( name );
  QGridLayout *layout = new QGridLayout( this );
  layout->setSpacing( KDialog::spacingHint() );
  layout->setMargin( KDialog::marginHint() );

  mPrefix = new NamePartWidget( i18n( "Prefixes"), i18n( "Enter prefix:" ), this );
  layout->addWidget( mPrefix, 0, 0 );

  mInclusion = new NamePartWidget( i18n( "Inclusions"), i18n( "Enter inclusion:" ), this );
  layout->addWidget( mInclusion, 0, 1 );

  mSuffix = new NamePartWidget( i18n( "Suffixes" ), i18n( "Enter suffix:" ), this );
  layout->addWidget( mSuffix, 0, 2 );

  QLabel *label = new QLabel( i18n( "Default formatted name:" ), this );
  layout->addWidget( label, 1, 0 );

  mFormattedNameCombo = new KComboBox( this );
  mFormattedNameCombo->addItem( i18n( "Empty" ) );
  mFormattedNameCombo->addItem( i18n( "Simple Name" ) );
  mFormattedNameCombo->addItem( i18n( "Full Name" ) );
  mFormattedNameCombo->addItem( i18n( "Reverse Name with Comma" ) );
  mFormattedNameCombo->addItem( i18n( "Reverse Name" ) );
  layout->addWidget( mFormattedNameCombo, 1, 1, 1, 2 );

  connect( mPrefix, SIGNAL( modified() ), SIGNAL( modified() ) );
  connect( mInclusion, SIGNAL( modified() ), SIGNAL( modified() ) );
  connect( mSuffix, SIGNAL( modified() ), SIGNAL( modified() ) );
  connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SIGNAL( modified() ) );
}

AddresseeWidget::~AddresseeWidget()
{
}

void AddresseeWidget::restoreSettings()
{
  KConfig _config( "kabcrc" );
  KConfigGroup config(&_config, "General" );

  mPrefix->setNameParts( config.readEntry( "Prefixes" , QStringList() ) );
  mInclusion->setNameParts( config.readEntry( "Inclusions" , QStringList() ) );
  mSuffix->setNameParts( config.readEntry( "Suffixes" , QStringList() ) );

  KConfig _cfg( "kaddressbookrc" );
  KConfigGroup cfg(&_cfg, "General" );
  mFormattedNameCombo->setCurrentIndex( cfg.readEntry( "FormattedNameType", 1 ) );
}

void AddresseeWidget::saveSettings()
{
  KConfig _config( "kabcrc" );
  KConfigGroup config(&_config, "General" );

  config.writeEntry( "Prefixes", mPrefix->nameParts() );
  config.writeEntry( "Inclusions", mInclusion->nameParts() );
  config.writeEntry( "Suffixes", mSuffix->nameParts() );

  KConfig _cfg( "kaddressbookrc" );
  KConfigGroup cfg(&_cfg, "General" );
  cfg.writeEntry( "FormattedNameType", mFormattedNameCombo->currentIndex() );

#ifdef __GNUC__
#warning Is this necessary? I could not find this dbus namespace
#endif
  /* This causes a crash */
  /*QDBusMessage message =
      QDBusMessage::createSignal( QString(), "org.kde.kabc.AddressBookConfig",
                                  "changed" );
   QDBusConnection::sessionBus().send( message );*/
}

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


<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.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.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qcheckbox.h>
#include <qframe.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qtabwidget.h>
#include <qtooltip.h>
#include <qcombobox.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kdialog.h>
#include <klistview.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <ktrader.h>

#include "addresseewidget.h"
#include "extensionconfigdialog.h"
#include "extensionwidget.h"
#include "kabprefs.h"

#include "kabconfigwidget.h"

class ExtensionItem : public QCheckListItem
{
  public:
    ExtensionItem( QListView *parent, const QString &text );

    void setService( const KService::Ptr &ptr );
    bool configWidgetAvailable() const;
    KAB::ExtensionFactory *factory() const;

    virtual QString text( int column ) const;

  private:
    KService::Ptr mPtr;
};

KABConfigWidget::KABConfigWidget( QWidget *parent, const char *name )
  : QWidget( parent, name )
{
  QVBoxLayout *topLayout = new QVBoxLayout( this, 0,
                                            KDialog::spacingHint() );

  QTabWidget *tabWidget = new QTabWidget( this );
  topLayout->addWidget( tabWidget );

  // General page
  QWidget *generalPage = new QWidget( this );
  QVBoxLayout *layout = new QVBoxLayout( generalPage, KDialog::marginHint(),
                                            KDialog::spacingHint() );

  QGroupBox *groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "General" ), generalPage );
  QBoxLayout *boxLayout = new QVBoxLayout( groupBox->layout() );
  boxLayout->setAlignment( Qt::AlignTop );

  mViewsSingleClickBox = new QCheckBox( i18n( "Honor KDE single click" ), groupBox, "msingle" );
  boxLayout->addWidget( mViewsSingleClickBox );

  mNameParsing = new QCheckBox( i18n( "Automatic name parsing for new addressees" ), groupBox, "mparse" );
  boxLayout->addWidget( mNameParsing );

  mTradeAsFamilyName = new QCheckBox( i18n( "Trade single name component as family name" ), groupBox, "mtrade" );
  boxLayout->addWidget( mTradeAsFamilyName );
/**
  TODO: show the checkbox when we can compile agains kdelibs from HEAD, atm it
        doesn't work and would just confuse the users ;)
*/
  mTradeAsFamilyName->hide();

  mLimitContactDisplay = new QCheckBox( i18n( "Limit unfiltered display to 100 contacts" ), groupBox, "mlimit" );
  boxLayout->addWidget( mLimitContactDisplay );

  QBoxLayout *editorLayout = new QHBoxLayout( boxLayout, KDialog::spacingHint() );

  QLabel *label = new QLabel( i18n( "Addressee editor type:" ), groupBox );
  editorLayout->addWidget( label );

  mEditorCombo = new QComboBox( groupBox );
  mEditorCombo->insertItem( i18n( "Full Editor" ) );
  mEditorCombo->insertItem( i18n( "Simple Editor" ) );
  label->setBuddy( mEditorCombo );
  editorLayout->addWidget( mEditorCombo );

  editorLayout->addStretch( 1 );

  layout->addWidget( groupBox );

  groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Script-Hooks" ), generalPage );
  QGridLayout *grid = new QGridLayout( groupBox->layout(), 2, 2,
                                       KDialog::spacingHint() );
  label = new QLabel( i18n( "Phone:" ), groupBox );
  grid->addWidget( label, 0, 0 );

  mPhoneHook = new QLineEdit( groupBox );
  QToolTip::add( mPhoneHook, i18n( "

%N: Phone Number

" ) );
  grid->addWidget( mPhoneHook, 0, 1 );

  label = new QLabel( i18n( "Fax:" ), groupBox );
  grid->addWidget( label, 1, 0 );

  mFaxHook = new QLineEdit( groupBox );
  QToolTip::add( mFaxHook, i18n( "

%N: Fax Number

" ) );
  grid->addWidget( mFaxHook, 1, 1 );
  grid->setColStretch( 1, 1 );

  layout->addWidget( groupBox );

  groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Location Map" ), generalPage );
  boxLayout = new QVBoxLayout( groupBox->layout(), KDialog::spacingHint() );
  boxLayout->setAlignment( Qt::AlignTop );

  mLocationMapURL = new QComboBox( true, groupBox );
  QToolTip::add( mLocationMapURL, i18n( "

%s: Street
"
                                 "
%r: Region
"
                                 "
%l: Location
"
                                 "
%z: Zip Code
"
                                 "
%c: Country ISO Code

" ) );
  mLocationMapURL->insertStringList( KABPrefs::instance()->mLocationMapURLs );
  boxLayout->addWidget( mLocationMapURL );
  layout->addWidget( groupBox );

  groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Extensions" ), generalPage );
  boxLayout = new QVBoxLayout( groupBox->layout(), KDialog::spacingHint() );
  boxLayout->setAlignment( Qt::AlignTop );

  mExtensionView = new KListView( groupBox );
  mExtensionView->setAllColumnsShowFocus( true );
  mExtensionView->setFullWidth( true );
  mExtensionView->addColumn( i18n( "Name" ) );
  mExtensionView->addColumn( i18n( "Description" ) );
  boxLayout->addWidget( mExtensionView );
  connect( mExtensionView, SIGNAL( doubleClicked ( QListViewItem* ) ),
           this, SLOT( configureExtension( QListViewItem* ) ) );
  QHBoxLayout *hboxLayout = new QHBoxLayout( boxLayout, KDialog::spacingHint() );
  hboxLayout->addStretch( 1 );
  mConfigureButton = new QPushButton( i18n( "Configure..." ), groupBox );
  mConfigureButton->setEnabled( false );
  hboxLayout->addWidget( mConfigureButton );

  layout->addWidget( groupBox );

  connect( mNameParsing, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mViewsSingleClickBox, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mTradeAsFamilyName, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mLimitContactDisplay, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mPhoneHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) );
  connect( mFaxHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) );
  connect( mLocationMapURL, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) );
  connect( mExtensionView, SIGNAL( selectionChanged( QListViewItem* ) ),
           SLOT( selectionChanged( QListViewItem* ) ) );
  connect( mExtensionView, SIGNAL( clicked( QListViewItem* ) ),
           SLOT( itemClicked( QListViewItem* ) ) );
  connect( mConfigureButton, SIGNAL( clicked() ),
           SLOT( configureExtension() ) );
  connect( mEditorCombo, SIGNAL( activated( int ) ), SLOT( modified() ) );

  tabWidget->addTab( generalPage, i18n( "General" ) );

  // Addressee page
  mAddresseeWidget = new AddresseeWidget( this );
  tabWidget->addTab( mAddresseeWidget, i18n( "Contact" ) );
  connect( mAddresseeWidget, SIGNAL( modified() ), SLOT( modified() ) );
}

void KABConfigWidget::configureExtension(QListViewItem *i)
{
    ExtensionItem *item = static_cast<ExtensionItem*>( i );
    if ( !item )
        return;
    if ( item->configWidgetAvailable() )
        configureExtension();
}

void KABConfigWidget::restoreSettings()
{
  bool blocked = signalsBlocked();
  blockSignals( true );

  mNameParsing->setChecked( KABPrefs::instance()->mAutomaticNameParsing );
  mViewsSingleClickBox->setChecked( KABPrefs::instance()->mHonorSingleClick );
  mPhoneHook->setText( KABPrefs::instance()->mPhoneHookApplication );
  mFaxHook->setText( KABPrefs::instance()->mFaxHookApplication );
  mAddresseeWidget->restoreSettings();
  mEditorCombo->setCurrentItem( KABPrefs::instance()->mEditorType );
  mLocationMapURL->setCurrentText( KABPrefs::instance()->mLocationMapURL.arg( KGlobal::locale()->country() ) );
  mLocationMapURL->lineEdit()->setCursorPosition( 0 );

  restoreExtensionSettings();

  KConfig config( "kabcrc", false, false );
  config.setGroup( "General" );
  mTradeAsFamilyName->setChecked( config.readBoolEntry( "TradeAsFamilyName", true ) );
  mLimitContactDisplay->setChecked( config.readBoolEntry( "LimitContactDisplay", true ) );

  blockSignals( blocked );

  emit changed( false );
}

void KABConfigWidget::saveSettings()
{
  KABPrefs::instance()->mAutomaticNameParsing = mNameParsing->isChecked();
  KABPrefs::instance()->mHonorSingleClick = mViewsSingleClickBox->isChecked();
  KABPrefs::instance()->mPhoneHookApplication = mPhoneHook->text();
  KABPrefs::instance()->mFaxHookApplication = mFaxHook->text();
  KABPrefs::instance()->mEditorType = mEditorCombo->currentItem();
  KABPrefs::instance()->mLocationMapURL = mLocationMapURL->currentText();
  mAddresseeWidget->saveSettings();

  saveExtensionSettings();
  KABPrefs::instance()->writeConfig();

  KConfig config( "kabcrc", false, false );
  config.setGroup( "General" );
  config.writeEntry( "TradeAsFamilyName", mTradeAsFamilyName->isChecked() );
  config.writeEntry( "LimitContactDisplay", mLimitContactDisplay->isChecked() );

  emit changed( false );
}

void KABConfigWidget::defaults()
{
  mNameParsing->setChecked( true );
  mViewsSingleClickBox->setChecked( false );
  mEditorCombo->setCurrentItem( 0 );
  mLimitContactDisplay->setChecked( true );

  emit changed( true );
}

void KABConfigWidget::modified()
{
  emit changed( true );
}

void KABConfigWidget::restoreExtensionSettings()
{
  QStringList activeExtensions = KABPrefs::instance()->mActiveExtensions;

  mExtensionView->clear();

  KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/Extension" );
  KTrader::OfferList::ConstIterator it;
  for ( it = plugins.begin(); it != plugins.end(); ++it ) {
    if ( !(*it)->hasServiceType( "KAddressBook/Extension" ) )
      continue;

    ExtensionItem *item = new ExtensionItem( mExtensionView, (*it)->name() );
    item->setService( *it );
    if ( activeExtensions.contains( item->factory()->identifier() ) )
      item->setOn( true );
  }
}

void KABConfigWidget::saveExtensionSettings()
{
  QStringList activeExtensions;

  QPtrList<QListViewItem> list;
  QListViewItemIterator it( mExtensionView );
  while ( it.current() ) {
    ExtensionItem *item = static_cast<ExtensionItem*>( it.current() );
    if ( item ) {
      if ( item->isOn() )
        activeExtensions.append( item->factory()->identifier() );
    }
    ++it;
  }

  KABPrefs::instance()->mActiveExtensions = activeExtensions;
}

void KABConfigWidget::configureExtension()
{
  ExtensionItem *item = static_cast<ExtensionItem*>( mExtensionView->currentItem() );
  if ( !item )
    return;

  KConfig config( "kaddressbookrc" );
  config.setGroup( QString( "Extensions_%1" ).arg( item->factory()->identifier() ) );

  ExtensionConfigDialog dlg( item->factory(), &config, this );
  dlg.exec();

  config.sync();
}

void KABConfigWidget::selectionChanged( QListViewItem *i )
{
  ExtensionItem *item = static_cast<ExtensionItem*>( i );
  if ( !item )
    return;

  mConfigureButton->setEnabled( item->configWidgetAvailable() );
}

void KABConfigWidget::itemClicked( QListViewItem *item )
{
  if ( item != 0 )
    modified();
}

ExtensionItem::ExtensionItem( QListView *parent, const QString &text )
  : QCheckListItem( parent, text, CheckBox )
{
}

void ExtensionItem::setService( const KService::Ptr &ptr )
{
  mPtr = ptr;
}

bool ExtensionItem::configWidgetAvailable() const
{
  KLibFactory *factory = KLibLoader::self()->factory( mPtr->library().latin1() );
  if ( !factory )
    return false;

  KAB::ExtensionFactory *extensionFactory = static_cast<KAB::ExtensionFactory*>( factory );
  if ( !extensionFactory )
    return false;

  return extensionFactory->configureWidgetAvailable();
}

KAB::ExtensionFactory *ExtensionItem::factory() const
{
  KLibFactory *factory = KLibLoader::self()->factory( mPtr->library().latin1() );
  if ( !factory )
    return 0;

  return static_cast<KAB::ExtensionFactory*>( factory );
}

QString ExtensionItem::text( int column ) const
{
  if ( column == 0 )
    return mPtr->name();
  else if ( column == 1 )
    return mPtr->comment();
  else
    return QString::null;
}

#include "kabconfigwidget.moc"
<commit_msg>Changed size policy, otherwise the combobox would increase the width of the dialog dramatically.<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.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.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qcheckbox.h>
#include <qframe.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qtabwidget.h>
#include <qtooltip.h>
#include <qcombobox.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kdialog.h>
#include <klistview.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <ktrader.h>

#include "addresseewidget.h"
#include "extensionconfigdialog.h"
#include "extensionwidget.h"
#include "kabprefs.h"

#include "kabconfigwidget.h"

class ExtensionItem : public QCheckListItem
{
  public:
    ExtensionItem( QListView *parent, const QString &text );

    void setService( const KService::Ptr &ptr );
    bool configWidgetAvailable() const;
    KAB::ExtensionFactory *factory() const;

    virtual QString text( int column ) const;

  private:
    KService::Ptr mPtr;
};

KABConfigWidget::KABConfigWidget( QWidget *parent, const char *name )
  : QWidget( parent, name )
{
  QVBoxLayout *topLayout = new QVBoxLayout( this, 0,
                                            KDialog::spacingHint() );

  QTabWidget *tabWidget = new QTabWidget( this );
  topLayout->addWidget( tabWidget );

  // General page
  QWidget *generalPage = new QWidget( this );
  QVBoxLayout *layout = new QVBoxLayout( generalPage, KDialog::marginHint(),
                                            KDialog::spacingHint() );

  QGroupBox *groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "General" ), generalPage );
  QBoxLayout *boxLayout = new QVBoxLayout( groupBox->layout() );
  boxLayout->setAlignment( Qt::AlignTop );

  mViewsSingleClickBox = new QCheckBox( i18n( "Honor KDE single click" ), groupBox, "msingle" );
  boxLayout->addWidget( mViewsSingleClickBox );

  mNameParsing = new QCheckBox( i18n( "Automatic name parsing for new addressees" ), groupBox, "mparse" );
  boxLayout->addWidget( mNameParsing );

  mTradeAsFamilyName = new QCheckBox( i18n( "Trade single name component as family name" ), groupBox, "mtrade" );
  boxLayout->addWidget( mTradeAsFamilyName );
/**
  TODO: show the checkbox when we can compile agains kdelibs from HEAD, atm it
        doesn't work and would just confuse the users ;)
*/
  mTradeAsFamilyName->hide();

  mLimitContactDisplay = new QCheckBox( i18n( "Limit unfiltered display to 100 contacts" ), groupBox, "mlimit" );
  boxLayout->addWidget( mLimitContactDisplay );

  QBoxLayout *editorLayout = new QHBoxLayout( boxLayout, KDialog::spacingHint() );

  QLabel *label = new QLabel( i18n( "Addressee editor type:" ), groupBox );
  editorLayout->addWidget( label );

  mEditorCombo = new QComboBox( groupBox );
  mEditorCombo->insertItem( i18n( "Full Editor" ) );
  mEditorCombo->insertItem( i18n( "Simple Editor" ) );
  label->setBuddy( mEditorCombo );
  editorLayout->addWidget( mEditorCombo );

  editorLayout->addStretch( 1 );

  layout->addWidget( groupBox );

  groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Script-Hooks" ), generalPage );
  QGridLayout *grid = new QGridLayout( groupBox->layout(), 2, 2,
                                       KDialog::spacingHint() );
  label = new QLabel( i18n( "Phone:" ), groupBox );
  grid->addWidget( label, 0, 0 );

  mPhoneHook = new QLineEdit( groupBox );
  QToolTip::add( mPhoneHook, i18n( "

%N: Phone Number

" ) );
  grid->addWidget( mPhoneHook, 0, 1 );

  label = new QLabel( i18n( "Fax:" ), groupBox );
  grid->addWidget( label, 1, 0 );

  mFaxHook = new QLineEdit( groupBox );
  QToolTip::add( mFaxHook, i18n( "

%N: Fax Number

" ) );
  grid->addWidget( mFaxHook, 1, 1 );
  grid->setColStretch( 1, 1 );

  layout->addWidget( groupBox );

  groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Location Map" ), generalPage );
  boxLayout = new QVBoxLayout( groupBox->layout(), KDialog::spacingHint() );
  boxLayout->setAlignment( Qt::AlignTop );

  mLocationMapURL = new QComboBox( true, groupBox );
  mLocationMapURL->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
  QToolTip::add( mLocationMapURL, i18n( "

%s: Street
"
                                 "
%r: Region
"
                                 "
%l: Location
"
                                 "
%z: Zip Code
"
                                 "
%c: Country ISO Code

" ) );
  mLocationMapURL->insertStringList( KABPrefs::instance()->mLocationMapURLs );
  boxLayout->addWidget( mLocationMapURL );
  layout->addWidget( groupBox );

  groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Extensions" ), generalPage );
  boxLayout = new QVBoxLayout( groupBox->layout(), KDialog::spacingHint() );
  boxLayout->setAlignment( Qt::AlignTop );

  mExtensionView = new KListView( groupBox );
  mExtensionView->setAllColumnsShowFocus( true );
  mExtensionView->setFullWidth( true );
  mExtensionView->addColumn( i18n( "Name" ) );
  mExtensionView->addColumn( i18n( "Description" ) );
  boxLayout->addWidget( mExtensionView );
  connect( mExtensionView, SIGNAL( doubleClicked ( QListViewItem* ) ),
           this, SLOT( configureExtension( QListViewItem* ) ) );
  QHBoxLayout *hboxLayout = new QHBoxLayout( boxLayout, KDialog::spacingHint() );
  hboxLayout->addStretch( 1 );
  mConfigureButton = new QPushButton( i18n( "Configure..." ), groupBox );
  mConfigureButton->setEnabled( false );
  hboxLayout->addWidget( mConfigureButton );

  layout->addWidget( groupBox );

  connect( mNameParsing, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mViewsSingleClickBox, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mTradeAsFamilyName, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mLimitContactDisplay, SIGNAL( toggled( bool ) ), SLOT( modified() ) );
  connect( mPhoneHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) );
  connect( mFaxHook, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) );
  connect( mLocationMapURL, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) );
  connect( mExtensionView, SIGNAL( selectionChanged( QListViewItem* ) ),
           SLOT( selectionChanged( QListViewItem* ) ) );
  connect( mExtensionView, SIGNAL( clicked( QListViewItem* ) ),
           SLOT( itemClicked( QListViewItem* ) ) );
  connect( mConfigureButton, SIGNAL( clicked() ),
           SLOT( configureExtension() ) );
  connect( mEditorCombo, SIGNAL( activated( int ) ), SLOT( modified() ) );

  tabWidget->addTab( generalPage, i18n( "General" ) );

  // Addressee page
  mAddresseeWidget = new AddresseeWidget( this );
  tabWidget->addTab( mAddresseeWidget, i18n( "Contact" ) );
  connect( mAddresseeWidget, SIGNAL( modified() ), SLOT( modified() ) );
}

void KABConfigWidget::configureExtension(QListViewItem *i)
{
    ExtensionItem *item = static_cast<ExtensionItem*>( i );
    if ( !item )
        return;
    if ( item->configWidgetAvailable() )
        configureExtension();
}

void KABConfigWidget::restoreSettings()
{
  bool blocked = signalsBlocked();
  blockSignals( true );

  mNameParsing->setChecked( KABPrefs::instance()->mAutomaticNameParsing );
  mViewsSingleClickBox->setChecked( KABPrefs::instance()->mHonorSingleClick );
  mPhoneHook->setText( KABPrefs::instance()->mPhoneHookApplication );
  mFaxHook->setText( KABPrefs::instance()->mFaxHookApplication );
  mAddresseeWidget->restoreSettings();
  mEditorCombo->setCurrentItem( KABPrefs::instance()->mEditorType );
  mLocationMapURL->setCurrentText( KABPrefs::instance()->mLocationMapURL.arg( KGlobal::locale()->country() ) );
  mLocationMapURL->lineEdit()->setCursorPosition( 0 );

  restoreExtensionSettings();

  KConfig config( "kabcrc", false, false );
  config.setGroup( "General" );
  mTradeAsFamilyName->setChecked( config.readBoolEntry( "TradeAsFamilyName", true ) );
  mLimitContactDisplay->setChecked( config.readBoolEntry( "LimitContactDisplay", true ) );

  blockSignals( blocked );

  emit changed( false );
}

void KABConfigWidget::saveSettings()
{
  KABPrefs::instance()->mAutomaticNameParsing = mNameParsing->isChecked();
  KABPrefs::instance()->mHonorSingleClick = mViewsSingleClickBox->isChecked();
  KABPrefs::instance()->mPhoneHookApplication = mPhoneHook->text();
  KABPrefs::instance()->mFaxHookApplication = mFaxHook->text();
  KABPrefs::instance()->mEditorType = mEditorCombo->currentItem();
  KABPrefs::instance()->mLocationMapURL = mLocationMapURL->currentText();
  mAddresseeWidget->saveSettings();

  saveExtensionSettings();
  KABPrefs::instance()->writeConfig();

  KConfig config( "kabcrc", false, false );
  config.setGroup( "General" );
  config.writeEntry( "TradeAsFamilyName", mTradeAsFamilyName->isChecked() );
  config.writeEntry( "LimitContactDisplay", mLimitContactDisplay->isChecked() );

  emit changed( false );
}

void KABConfigWidget::defaults()
{
  mNameParsing->setChecked( true );
  mViewsSingleClickBox->setChecked( false );
  mEditorCombo->setCurrentItem( 0 );
  mLimitContactDisplay->setChecked( true );

  emit changed( true );
}

void KABConfigWidget::modified()
{
  emit changed( true );
}

void KABConfigWidget::restoreExtensionSettings()
{
  QStringList activeExtensions = KABPrefs::instance()->mActiveExtensions;

  mExtensionView->clear();

  KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/Extension" );
  KTrader::OfferList::ConstIterator it;
  for ( it = plugins.begin(); it != plugins.end(); ++it ) {
    if ( !(*it)->hasServiceType( "KAddressBook/Extension" ) )
      continue;

    ExtensionItem *item = new ExtensionItem( mExtensionView, (*it)->name() );
    item->setService( *it );
    if ( activeExtensions.contains( item->factory()->identifier() ) )
      item->setOn( true );
  }
}

void KABConfigWidget::saveExtensionSettings()
{
  QStringList activeExtensions;

  QPtrList<QListViewItem> list;
  QListViewItemIterator it( mExtensionView );
  while ( it.current() ) {
    ExtensionItem *item = static_cast<ExtensionItem*>( it.current() );
    if ( item ) {
      if ( item->isOn() )
        activeExtensions.append( item->factory()->identifier() );
    }
    ++it;
  }

  KABPrefs::instance()->mActiveExtensions = activeExtensions;
}

void KABConfigWidget::configureExtension()
{
  ExtensionItem *item = static_cast<ExtensionItem*>( mExtensionView->currentItem() );
  if ( !item )
    return;

  KConfig config( "kaddressbookrc" );
  config.setGroup( QString( "Extensions_%1" ).arg( item->factory()->identifier() ) );

  ExtensionConfigDialog dlg( item->factory(), &config, this );
  dlg.exec();

  config.sync();
}

void KABConfigWidget::selectionChanged( QListViewItem *i )
{
  ExtensionItem *item = static_cast<ExtensionItem*>( i );
  if ( !item )
    return;

  mConfigureButton->setEnabled( item->configWidgetAvailable() );
}

void KABConfigWidget::itemClicked( QListViewItem *item )
{
  if ( item != 0 )
    modified();
}

ExtensionItem::ExtensionItem( QListView *parent, const QString &text )
  : QCheckListItem( parent, text, CheckBox )
{
}

void ExtensionItem::setService( const KService::Ptr &ptr )
{
  mPtr = ptr;
}

bool ExtensionItem::configWidgetAvailable() const
{
  KLibFactory *factory = KLibLoader::self()->factory( mPtr->library().latin1() );
  if ( !factory )
    return false;

  KAB::ExtensionFactory *extensionFactory = static_cast<KAB::ExtensionFactory*>( factory );
  if ( !extensionFactory )
    return false;

  return extensionFactory->configureWidgetAvailable();
}

KAB::ExtensionFactory *ExtensionItem::factory() const
{
  KLibFactory *factory = KLibLoader::self()->factory( mPtr->library().latin1() );
  if ( !factory )
    return 0;

  return static_cast<KAB::ExtensionFactory*>( factory );
}

QString ExtensionItem::text( int column ) const
{
  if ( column == 0 )
    return mPtr->name();
  else if ( column == 1 )
    return mPtr->comment();
  else
    return QString::null;
}

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


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/debug/debugger.h"
#include "build/build_config.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#if !defined(OS_ANDROID) && !defined(OS_NACL)
#include <execinfo.h>
#endif

#if defined(__GLIBCXX__)
#include <cxxabi.h>
#endif

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

#if defined(OS_MACOSX) || defined(OS_BSD)
#include <sys/sysctl.h>
#endif

#if defined(OS_FREEBSD)
#include <sys/user.h>
#endif

#include <ostream>

#include "base/basictypes.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "base/string_piece.h"
#include "base/stringprintf.h"

#if defined(USE_SYMBOLIZE)
#include "base/third_party/symbolize/symbolize.h"
#endif

#if defined(OS_ANDROID)
#include "base/threading/platform_thread.h"
#endif

namespace base {
namespace debug {

bool SpawnDebuggerOnProcess(unsigned process_id) {
#if OS_ANDROID
  NOTIMPLEMENTED();
  return false;
#else
  const std::string debug_cmd =
      StringPrintf("xterm -e 'gdb --pid=%u' &", process_id);
  LOG(WARNING) << "Starting debugger on pid " << process_id
               << " with command `" << debug_cmd << "`";
  int ret = system(debug_cmd.c_str());
  if (ret == -1)
    return false;
  return true;
#endif
}

#if defined(OS_MACOSX) || defined(OS_BSD)

// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
bool BeingDebugged() {
  // If the process is sandboxed then we can't use the sysctl, so cache the
  // value.
  static bool is_set = false;
  static bool being_debugged = false;

  if (is_set) {
    return being_debugged;
  }

  // Initialize mib, which tells sysctl what info we want.  In this case,
  // we're looking for information about a specific process ID.
  int mib[] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid()
#if defined(OS_OPENBSD)
    , sizeof(struct kinfo_proc),
    0
#endif
  };

  // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE.  The source and
  // binary interfaces may change.
  struct kinfo_proc info;
  size_t info_size = sizeof(info);

#if defined(OS_OPENBSD)
  if (sysctl(mib, arraysize(mib), NULL, &info_size, NULL, 0) < 0)
    return -1;

  mib[5] = (info_size / sizeof(struct kinfo_proc));
#endif

  int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
  DCHECK_EQ(sysctl_result, 0);
  if (sysctl_result != 0) {
    is_set = true;
    being_debugged = false;
    return being_debugged;
  }

  // This process is being debugged if the P_TRACED flag is set.
  is_set = true;
#if defined(OS_FREEBSD)
  being_debugged = (info.ki_flag & P_TRACED) != 0;
#elif defined(OS_BSD)
  being_debugged = (info.p_flag & P_TRACED) != 0;
#else
  being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
#endif
  return being_debugged;
}

#elif defined(OS_LINUX) || defined(OS_ANDROID)

// We can look in /proc/self/status for TracerPid.  We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
// Another option that is common is to try to ptrace yourself, but then we
// can't detach without forking(), and that's not so great.
// static
bool BeingDebugged() {
  int status_fd = open("/proc/self/status", O_RDONLY);
  if (status_fd == -1)
    return false;

  // We assume our line will be in the first 1024 characters and that we can
  // read this much all at once.  In practice this will generally be true.
  // This simplifies and speeds up things considerably.
  char buf[1024];

  ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
  if (HANDLE_EINTR(close(status_fd)) < 0)
    return false;

  if (num_read <= 0)
    return false;

  StringPiece status(buf, num_read);
  StringPiece tracer("TracerPid:\t");

  StringPiece::size_type pid_index = status.find(tracer);
  if (pid_index == StringPiece::npos)
    return false;

  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
  pid_index += tracer.size();
  return pid_index < status.size() && status[pid_index] != '0';
}

#else

bool BeingDebugged() {
  NOTIMPLEMENTED();
  return false;
}

#endif

// We want to break into the debugger in Debug mode, and cause a crash dump in
// Release mode. Breakpad behaves as follows:
//
// +-------+-----------------+-----------------+
// | OS    | Dump on SIGTRAP | Dump on SIGABRT |
// +-------+-----------------+-----------------+
// | Linux |       N         |        Y        |
// | Mac   |       Y         |        N        |
// +-------+-----------------+-----------------+
//
// Thus we do the following:
// Linux: Debug mode, send SIGTRAP; Release mode, send SIGABRT.
// Mac: Always send SIGTRAP.

#if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#define DEBUG_BREAK() abort()
#elif defined(OS_NACL)
// The NaCl verifier doesn't let use use int3.  For now, we call abort().  We
// should ask for advice from some NaCl experts about the optimum thing here.
// http://code.google.com/p/nativeclient/issues/detail?id=645
#define DEBUG_BREAK() abort()
#elif defined(ARCH_CPU_ARM_FAMILY)
#if defined(OS_ANDROID)
// Though Android has a "helpful" process called debuggerd to catch native
// signals on the general assumption that they are fatal errors, we've had great
// difficulty continuing in a debugger once we stop from SIGINT triggered by
// native code.
//
// Use GDB to set |go| to 1 to resume execution.
#define DEBUG_BREAK() do { \
  volatile int go = 0;             \
  while (!go) { \
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); \
  } \
} while (0)
#else
// ARM && !ANDROID
#define DEBUG_BREAK() asm("bkpt 0")
#endif
#else
#define DEBUG_BREAK() asm("int3")
#endif

void BreakDebugger() {
  DEBUG_BREAK();
#if defined(NDEBUG)
  _exit(1);
#endif
}

}  // namespace debug
}  // namespace base
<commit_msg>PPAPI/NaCl: Remove call of system() from NaCl build<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/debug/debugger.h"
#include "build/build_config.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#if !defined(OS_ANDROID) && !defined(OS_NACL)
#include <execinfo.h>
#endif

#if defined(__GLIBCXX__)
#include <cxxabi.h>
#endif

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

#if defined(OS_MACOSX) || defined(OS_BSD)
#include <sys/sysctl.h>
#endif

#if defined(OS_FREEBSD)
#include <sys/user.h>
#endif

#include <ostream>

#include "base/basictypes.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "base/string_piece.h"
#include "base/stringprintf.h"

#if defined(USE_SYMBOLIZE)
#include "base/third_party/symbolize/symbolize.h"
#endif

#if defined(OS_ANDROID)
#include "base/threading/platform_thread.h"
#endif

namespace base {
namespace debug {

bool SpawnDebuggerOnProcess(unsigned process_id) {
#if OS_ANDROID || OS_NACL
  NOTIMPLEMENTED();
  return false;
#else
  const std::string debug_cmd =
      StringPrintf("xterm -e 'gdb --pid=%u' &", process_id);
  LOG(WARNING) << "Starting debugger on pid " << process_id
               << " with command `" << debug_cmd << "`";
  int ret = system(debug_cmd.c_str());
  if (ret == -1)
    return false;
  return true;
#endif
}

#if defined(OS_MACOSX) || defined(OS_BSD)

// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
bool BeingDebugged() {
  // If the process is sandboxed then we can't use the sysctl, so cache the
  // value.
  static bool is_set = false;
  static bool being_debugged = false;

  if (is_set) {
    return being_debugged;
  }

  // Initialize mib, which tells sysctl what info we want.  In this case,
  // we're looking for information about a specific process ID.
  int mib[] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid()
#if defined(OS_OPENBSD)
    , sizeof(struct kinfo_proc),
    0
#endif
  };

  // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE.  The source and
  // binary interfaces may change.
  struct kinfo_proc info;
  size_t info_size = sizeof(info);

#if defined(OS_OPENBSD)
  if (sysctl(mib, arraysize(mib), NULL, &info_size, NULL, 0) < 0)
    return -1;

  mib[5] = (info_size / sizeof(struct kinfo_proc));
#endif

  int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
  DCHECK_EQ(sysctl_result, 0);
  if (sysctl_result != 0) {
    is_set = true;
    being_debugged = false;
    return being_debugged;
  }

  // This process is being debugged if the P_TRACED flag is set.
  is_set = true;
#if defined(OS_FREEBSD)
  being_debugged = (info.ki_flag & P_TRACED) != 0;
#elif defined(OS_BSD)
  being_debugged = (info.p_flag & P_TRACED) != 0;
#else
  being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
#endif
  return being_debugged;
}

#elif defined(OS_LINUX) || defined(OS_ANDROID)

// We can look in /proc/self/status for TracerPid.  We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
// Another option that is common is to try to ptrace yourself, but then we
// can't detach without forking(), and that's not so great.
// static
bool BeingDebugged() {
  int status_fd = open("/proc/self/status", O_RDONLY);
  if (status_fd == -1)
    return false;

  // We assume our line will be in the first 1024 characters and that we can
  // read this much all at once.  In practice this will generally be true.
  // This simplifies and speeds up things considerably.
  char buf[1024];

  ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
  if (HANDLE_EINTR(close(status_fd)) < 0)
    return false;

  if (num_read <= 0)
    return false;

  StringPiece status(buf, num_read);
  StringPiece tracer("TracerPid:\t");

  StringPiece::size_type pid_index = status.find(tracer);
  if (pid_index == StringPiece::npos)
    return false;

  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
  pid_index += tracer.size();
  return pid_index < status.size() && status[pid_index] != '0';
}

#else

bool BeingDebugged() {
  NOTIMPLEMENTED();
  return false;
}

#endif

// We want to break into the debugger in Debug mode, and cause a crash dump in
// Release mode. Breakpad behaves as follows:
//
// +-------+-----------------+-----------------+
// | OS    | Dump on SIGTRAP | Dump on SIGABRT |
// +-------+-----------------+-----------------+
// | Linux |       N         |        Y        |
// | Mac   |       Y         |        N        |
// +-------+-----------------+-----------------+
//
// Thus we do the following:
// Linux: Debug mode, send SIGTRAP; Release mode, send SIGABRT.
// Mac: Always send SIGTRAP.

#if defined(NDEBUG) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#define DEBUG_BREAK() abort()
#elif defined(OS_NACL)
// The NaCl verifier doesn't let use use int3.  For now, we call abort().  We
// should ask for advice from some NaCl experts about the optimum thing here.
// http://code.google.com/p/nativeclient/issues/detail?id=645
#define DEBUG_BREAK() abort()
#elif defined(ARCH_CPU_ARM_FAMILY)
#if defined(OS_ANDROID)
// Though Android has a "helpful" process called debuggerd to catch native
// signals on the general assumption that they are fatal errors, we've had great
// difficulty continuing in a debugger once we stop from SIGINT triggered by
// native code.
//
// Use GDB to set |go| to 1 to resume execution.
#define DEBUG_BREAK() do { \
  volatile int go = 0;             \
  while (!go) { \
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); \
  } \
} while (0)
#else
// ARM && !ANDROID
#define DEBUG_BREAK() asm("bkpt 0")
#endif
#else
#define DEBUG_BREAK() asm("int3")
#endif

void BreakDebugger() {
  DEBUG_BREAK();
#if defined(NDEBUG)
  _exit(1);
#endif
}

}  // namespace debug
}  // namespace base
<|endoftext|>


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

#include "bvh4_builder_twolevel.h"
#include "bvh4_statistics.h"
#include "../builders/bvh_builder_sah.h"

#define PROFILE 0
#define MAX_OPEN_SIZE 10000

namespace embree
{
  namespace isa
  {
    BVH4BuilderTwoLevel::BVH4BuilderTwoLevel (BVH4* bvh, Scene* scene, const createTriangleMeshAccelTy createTriangleMeshAccel)
      : bvh(bvh), objects(bvh->objects), scene(scene), createTriangleMeshAccel(createTriangleMeshAccel) {}

    BVH4BuilderTwoLevel::~BVH4BuilderTwoLevel ()
    {
      for (size_t i=0; i<builders.size(); i++)
	delete builders[i];
    }

    void BVH4BuilderTwoLevel::build(size_t threadIndex, size_t threadCount)
    {
      /* delete some objects */
      size_t N = scene->size();
      if (N < objects.size()) {
        parallel_for(N, objects.size(), [&] (const range<size_t>& r) {
            for (size_t i=r.begin(); i<r.end(); i++) {
              delete builders[i]; builders[i] = nullptr;
              delete objects[i]; objects[i] = nullptr;
            }
          });
      }

      /* skip build for empty scene */
      const size_t numPrimitives = scene->getNumPrimitives<TriangleMesh,1>();
      if (numPrimitives == 0) {
        prims.resize(0);
        bvh->set(BVH4::emptyNode,empty,0);
        return;
      }

      double t0 = bvh->preBuild(TOSTRING(isa) "::BVH4BuilderTwoLevel");

#if PROFILE
	profile(2,20,numPrimitives,[&] (ProfileTimer& timer)
        {
#endif

      /* resize object array if scene got larger */
      if (objects.size()  < N) objects.resize(N);
      if (builders.size() < N) builders.resize(N);
      if (refs.size()     < N) refs.resize(N);
      nextRef = 0;

      /* create of acceleration structures */
      parallel_for(size_t(0), N, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          TriangleMesh* mesh = scene->getTriangleMeshSafe(objectID);

          /* verify meshes got deleted properly */
          if (mesh == nullptr || mesh->numTimeSteps != 1) {
            assert(objectID < objects.size () && objects[objectID] == nullptr);
            assert(objectID < builders.size() && builders[objectID] == nullptr);
            continue;
          }

          /* delete BVH and builder for meshes that are scheduled for deletion */
          if (mesh->isErasing()) {
            delete builders[objectID]; builders[objectID] = nullptr;
            delete objects [objectID]; objects [objectID] = nullptr;
            continue;
          }

          /* create BVH and builder for new meshes */
          if (objects[objectID] == nullptr)
            createTriangleMeshAccel(mesh,(AccelData*&)objects[objectID],builders[objectID]);
        }
      });

      /* parallel build of acceleration structures */
      parallel_for(size_t(0), N, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          /* ignore if no triangle mesh or not enabled */
          TriangleMesh* mesh = scene->getTriangleMeshSafe(objectID);
          if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
            continue;

          BVH4*    object  = objects [objectID]; assert(object);
          Builder* builder = builders[objectID]; assert(builder);

          /* build object if it got modified */
#if !PROFILE
          if (mesh->isModified())
#endif
            builder->build(0,0);

          /* create build primitive */
          if (!object->bounds.empty())
            refs[nextRef++] = BVH4BuilderTwoLevel::BuildRef(object->bounds,object->root);
        }
      });

      /* fast path for single geometry scenes */
      if (nextRef == 1) {
        bvh->set(refs[0].node,refs[0].bounds(),numPrimitives);
        return;
      }

      /* open all large nodes */
      refs.resize(nextRef);
      open_sequential(numPrimitives);

      /* fast path for small geometries */
      if (refs.size() == 1) {
        bvh->set(refs[0].node,refs[0].bounds(),numPrimitives);
        return;
      }

      /* compute PrimRefs */
      prims.resize(refs.size());
      const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), size_t(1024), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo
      {
        PrimInfo pinfo(empty);
        for (size_t i=r.begin(); i<r.end(); i++) {
          pinfo.add(refs[i].bounds());
          prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
        }
        return pinfo;
      }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });

      /* skip if all objects where empty */
      if (pinfo.size() == 0)
        bvh->set(BVH4::emptyNode,empty,0);

      /* otherwise build toplevel hierarchy */
      else
      {
        BVH4::NodeRef root;
        BVHBuilderBinnedSAH::build<BVH4::NodeRef>
          (root,
           [&] { return bvh->alloc.threadLocal2(); },
           [&] (const isa::BVHBuilderBinnedSAH::BuildRecord& current, BVHBuilderBinnedSAH::BuildRecord* children, const size_t N, FastAllocator::ThreadLocal2* alloc) -> int
           {
             BVH4::Node* node = (BVH4::Node*) alloc->alloc0.malloc(sizeof(BVH4::Node)); node->clear();
             for (size_t i=0; i<N; i++) {
               node->set(i,children[i].pinfo.geomBounds);
               children[i].parent = (size_t*)&node->child(i);
             }
             *current.parent = bvh->encodeNode(node);
             return 0;
           },
           [&] (const BVHBuilderBinnedSAH::BuildRecord& current, FastAllocator::ThreadLocal2* alloc) -> int
           {
             assert(current.prims.size() == 1);
             *current.parent = (BVH4::NodeRef) prims[current.prims.begin()].ID();
             return 1;
           },
           [&] (size_t dn) { bvh->scene->progressMonitor(0); },
           prims.data(),pinfo,BVH4::N,BVH4::maxBuildDepthLeaf,1,1,1,1.0f,1.0f);

        bvh->set(root,pinfo.geomBounds,numPrimitives);
      }

#if PROFILE
      });
#endif

      bvh->alloc.cleanup();
      bvh->postBuild(t0);
    }

    void BVH4BuilderTwoLevel::clear()
    {
      for (size_t i=0; i<objects.size(); i++)
        if (objects[i]) objects[i]->clear();

      for (size_t i=0; i<builders.size(); i++)
	if (builders[i]) builders[i]->clear();

      refs.clear();
    }

    void BVH4BuilderTwoLevel::open_sequential(size_t numPrimitives)
    {
      if (refs.size() == 0)
	return;

      size_t N = min(numPrimitives/200,size_t(MAX_OPEN_SIZE));
      refs.reserve(N);

      std::make_heap(refs.begin(),refs.end());
      while (refs.size()+3 <= N)
      {
        std::pop_heap (refs.begin(),refs.end());
        BVH4::NodeRef ref = refs.back().node;
        if (ref.isLeaf()) break;
        refs.pop_back();

        BVH4::Node* node = ref.node();
        for (size_t i=0; i<4; i++) {
          if (node->child(i) == BVH4::emptyNode) continue;
          refs.push_back(BuildRef(node->bounds(i),node->child(i)));
          std::push_heap (refs.begin(),refs.end());
        }
      }
    }

    Builder* BVH4BuilderTwoLevelSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createTriangleMeshAccel) {
      return new BVH4BuilderTwoLevel((BVH4*)bvh,scene,createTriangleMeshAccel);
    }
  }
}
<commit_msg>fixed memory leak in two-level BVH4 builder<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "bvh4_builder_twolevel.h"
#include "bvh4_statistics.h"
#include "../builders/bvh_builder_sah.h"

#define PROFILE 0
#define MAX_OPEN_SIZE 10000

namespace embree
{
  namespace isa
  {
    BVH4BuilderTwoLevel::BVH4BuilderTwoLevel (BVH4* bvh, Scene* scene, const createTriangleMeshAccelTy createTriangleMeshAccel)
      : bvh(bvh), objects(bvh->objects), scene(scene), createTriangleMeshAccel(createTriangleMeshAccel) {}

    BVH4BuilderTwoLevel::~BVH4BuilderTwoLevel ()
    {
      for (size_t i=0; i<builders.size(); i++)
	delete builders[i];
    }

    void BVH4BuilderTwoLevel::build(size_t threadIndex, size_t threadCount)
    {
      /* delete some objects */
      size_t N = scene->size();
      if (N < objects.size()) {
        parallel_for(N, objects.size(), [&] (const range<size_t>& r) {
            for (size_t i=r.begin(); i<r.end(); i++) {
              delete builders[i]; builders[i] = nullptr;
              delete objects[i]; objects[i] = nullptr;
            }
          });
      }

      /* reset memory allocator */
      bvh->alloc.clear();

      /* skip build for empty scene */
      const size_t numPrimitives = scene->getNumPrimitives<TriangleMesh,1>();
      if (numPrimitives == 0) {
        prims.resize(0);
        bvh->set(BVH4::emptyNode,empty,0);
        return;
      }

      double t0 = bvh->preBuild(TOSTRING(isa) "::BVH4BuilderTwoLevel");

#if PROFILE
	profile(2,20,numPrimitives,[&] (ProfileTimer& timer)
        {
#endif

      /* resize object array if scene got larger */
      if (objects.size()  < N) objects.resize(N);
      if (builders.size() < N) builders.resize(N);
      if (refs.size()     < N) refs.resize(N);
      nextRef = 0;

      /* create of acceleration structures */
      parallel_for(size_t(0), N, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          TriangleMesh* mesh = scene->getTriangleMeshSafe(objectID);

          /* verify meshes got deleted properly */
          if (mesh == nullptr || mesh->numTimeSteps != 1) {
            assert(objectID < objects.size () && objects[objectID] == nullptr);
            assert(objectID < builders.size() && builders[objectID] == nullptr);
            continue;
          }

          /* delete BVH and builder for meshes that are scheduled for deletion */
          if (mesh->isErasing()) {
            delete builders[objectID]; builders[objectID] = nullptr;
            delete objects [objectID]; objects [objectID] = nullptr;
            continue;
          }

          /* create BVH and builder for new meshes */
          if (objects[objectID] == nullptr)
            createTriangleMeshAccel(mesh,(AccelData*&)objects[objectID],builders[objectID]);
        }
      });

      /* parallel build of acceleration structures */
      parallel_for(size_t(0), N, [&] (const range<size_t>& r)
      {
        for (size_t objectID=r.begin(); objectID<r.end(); objectID++)
        {
          /* ignore if no triangle mesh or not enabled */
          TriangleMesh* mesh = scene->getTriangleMeshSafe(objectID);
          if (mesh == nullptr || !mesh->isEnabled() || mesh->numTimeSteps != 1)
            continue;

          BVH4*    object  = objects [objectID]; assert(object);
          Builder* builder = builders[objectID]; assert(builder);

          /* build object if it got modified */
#if !PROFILE
          if (mesh->isModified())
#endif
            builder->build(0,0);

          /* create build primitive */
          if (!object->bounds.empty())
            refs[nextRef++] = BVH4BuilderTwoLevel::BuildRef(object->bounds,object->root);
        }
      });

      /* fast path for single geometry scenes */
      if (nextRef == 1) {
        bvh->set(refs[0].node,refs[0].bounds(),numPrimitives);
        return;
      }

      /* open all large nodes */
      refs.resize(nextRef);
      open_sequential(numPrimitives);

      /* fast path for small geometries */
      if (refs.size() == 1) {
        bvh->set(refs[0].node,refs[0].bounds(),numPrimitives);
        return;
      }

      /* compute PrimRefs */
      prims.resize(refs.size());
      const PrimInfo pinfo = parallel_reduce(size_t(0), refs.size(), size_t(1024), PrimInfo(empty), [&] (const range<size_t>& r) -> PrimInfo
      {
        PrimInfo pinfo(empty);
        for (size_t i=r.begin(); i<r.end(); i++) {
          pinfo.add(refs[i].bounds());
          prims[i] = PrimRef(refs[i].bounds(),(size_t)refs[i].node);
        }
        return pinfo;
      }, [] (const PrimInfo& a, const PrimInfo& b) { return PrimInfo::merge(a,b); });

      /* skip if all objects where empty */
      if (pinfo.size() == 0)
        bvh->set(BVH4::emptyNode,empty,0);

      /* otherwise build toplevel hierarchy */
      else
      {
        BVH4::NodeRef root;
        BVHBuilderBinnedSAH::build<BVH4::NodeRef>
          (root,
           [&] { return bvh->alloc.threadLocal2(); },
           [&] (const isa::BVHBuilderBinnedSAH::BuildRecord& current, BVHBuilderBinnedSAH::BuildRecord* children, const size_t N, FastAllocator::ThreadLocal2* alloc) -> int
           {
             BVH4::Node* node = (BVH4::Node*) alloc->alloc0.malloc(sizeof(BVH4::Node)); node->clear();
             for (size_t i=0; i<N; i++) {
               node->set(i,children[i].pinfo.geomBounds);
               children[i].parent = (size_t*)&node->child(i);
             }
             *current.parent = bvh->encodeNode(node);
             return 0;
           },
           [&] (const BVHBuilderBinnedSAH::BuildRecord& current, FastAllocator::ThreadLocal2* alloc) -> int
           {
             assert(current.prims.size() == 1);
             *current.parent = (BVH4::NodeRef) prims[current.prims.begin()].ID();
             return 1;
           },
           [&] (size_t dn) { bvh->scene->progressMonitor(0); },
           prims.data(),pinfo,BVH4::N,BVH4::maxBuildDepthLeaf,1,1,1,1.0f,1.0f);

        bvh->set(root,pinfo.geomBounds,numPrimitives);
      }

#if PROFILE
      });
#endif

      bvh->alloc.cleanup();
      bvh->postBuild(t0);
    }

    void BVH4BuilderTwoLevel::clear()
    {
      for (size_t i=0; i<objects.size(); i++)
        if (objects[i]) objects[i]->clear();

      for (size_t i=0; i<builders.size(); i++)
	if (builders[i]) builders[i]->clear();

      refs.clear();
    }

    void BVH4BuilderTwoLevel::open_sequential(size_t numPrimitives)
    {
      if (refs.size() == 0)
	return;

      size_t N = min(numPrimitives/200,size_t(MAX_OPEN_SIZE));
      refs.reserve(N);

      std::make_heap(refs.begin(),refs.end());
      while (refs.size()+3 <= N)
      {
        std::pop_heap (refs.begin(),refs.end());
        BVH4::NodeRef ref = refs.back().node;
        if (ref.isLeaf()) break;
        refs.pop_back();

        BVH4::Node* node = ref.node();
        for (size_t i=0; i<4; i++) {
          if (node->child(i) == BVH4::emptyNode) continue;
          refs.push_back(BuildRef(node->bounds(i),node->child(i)));
          std::push_heap (refs.begin(),refs.end());
        }
      }
    }

    Builder* BVH4BuilderTwoLevelSAH (void* bvh, Scene* scene, const createTriangleMeshAccelTy createTriangleMeshAccel) {
      return new BVH4BuilderTwoLevel((BVH4*)bvh,scene,createTriangleMeshAccel);
    }
  }
}
<|endoftext|>