<commit_before>#include "objectfinder.h"

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

ObjectFinder::ObjectFinder()
{
	using boost::property_tree::ptree;
	try {

		ptree pt;
		read_ini("conf/camera.ini", pt);
		Vfov = pt.get<float>("Vfov");
		CamHeight = pt.get<float>("Height");
		CamAngleDev = pt.get<float>("AngleDev");
	}
	catch (...){
		ptree pt;
		pt.put("Height", CamHeight);
		pt.put("AngleDev", CamAngleDev);
		pt.put("Vfov", Vfov);

		write_ini("conf/camera.ini", pt);
	};
}
cv::Point3d ObjectFinder::Locate(const HSVColorRange &r, cv::Mat &frameHSV, cv::Mat &frameBGR) {
	cv::Point2f point = LocateOnScreen(r, frameHSV, frameBGR);
	cv::Point3d info = ConvertPixelToRealWorld(point, cv::Point2i(frameHSV.cols, frameHSV.rows));
	WriteInfoOnScreen(info);
	return info;
}

cv::Point2f ObjectFinder::LocateOnScreen(const HSVColorRange &r, cv::Mat &frameHSV, cv::Mat &frameBGR) {

	cv::Point2f center;
	//	cv::imshow("Thresholded Image 2", frameHSV); //show the thresholded image

	//	cv::imshow("Thresholded Image 3", imgHSV); //show the thresholded image
	cv::Mat imgThresholded;

	inRange(frameHSV, cv::Scalar(r.hue.low, r.sat.low, r.val.low), cv::Scalar(r.hue.high, r.sat.high, r.val.high), imgThresholded); //Threshold the image

	cv::Mat dst(imgThresholded.rows, imgThresholded.cols, CV_8U, cv::Scalar::all(0));

	//biggest area
	std::vector<std::vector<cv::Point> > contours; // Vector for storing contour
	std::vector<cv::Vec4i> hierarchy;
	int largest_area = 0;
	int largest_contour_index = 0;
	cv::Rect bounding_rect;

	findContours(imgThresholded, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // Find the contours in the image

	cv::Scalar color(255, 255, 255);
	cv::Scalar color2(0, 0, 255);

	for (int i = 0; i < contours.size(); i++) // iterate through each contour.
	{
		double a = cv::contourArea(contours[i], false);  //  Find the area of contour
		if (a > largest_area){
			largest_area = a;
			largest_contour_index = i;                //Store the index of largest contour
			bounding_rect = cv::boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
		}
		bounding_rect = cv::boundingRect(contours[i]);
		cv::rectangle(frameBGR, bounding_rect, color2);
		drawContours(frameBGR, contours, i, color, 1, 8, hierarchy); // Draw the largest contour using previously stored index.
	}

	//find center
	cv::Scalar colorCircle(133, 33, 55);

	if (contours.size() > largest_contour_index){
		cv::Moments M = cv::moments(contours[largest_contour_index]);
		center = cv::Point2f(M.m10 / M.m00, M.m01 / M.m00);
	}

	//Draw circle
	cv::circle(frameBGR, center, 10, colorCircle, 3);
//	cv::imshow("Original", imgOriginal);
//	cv::moveWindow("Original", 0, 0);
	return center;
}

void ObjectFinder::IsolateField(const HSVColorRange &inner, const HSVColorRange &outer, cv::Mat &frameHSV, cv::Mat &frameBGR) {

	//	cv::imshow("Thresholded Image 3", imgHSV); //show the thresholded image
	cv::Mat innerThresholded;
	inRange(frameHSV, cv::Scalar(inner.hue.low, inner.sat.low, inner.val.low), cv::Scalar(inner.hue.high, inner.sat.high, inner.val.high), innerThresholded); //Threshold the image
	cv::Mat outerThresholded;
	inRange(frameHSV, cv::Scalar(outer.hue.low, outer.sat.low, outer.val.low), cv::Scalar(outer.hue.high, outer.sat.high, outer.val.high), outerThresholded); //Threshold the image

	std::vector<std::vector<cv::Point> > contours; // Vector for storing contour
	std::vector<cv::Vec4i> hierarchy;
	std::vector<std::vector<cv::Point> > contours2; // Vector for storing contour
	std::vector<cv::Vec4i> hierarchy2;
#ifdef USE_CONTOURS
	innerThresholded = outerThresholded + innerThresholded;
	findContours(innerThresholded, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // Find the contours in the image
	//findContours(outerThresholded, contours2, hierarchy2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // Find the contours in the image

	cv::Scalar color(255, 255, 255);
	cv::Scalar color2(0, 0, 255);
	cv::Scalar color3(0, 0, 0);
	cv::Scalar color4(255, 0, 0);
	cv::RotatedRect bounding_rect;

	for (int i = 0; i < contours.size(); i++) // iterate through each contour.
	{
		double a = cv::contourArea(contours[i], false);  //  Find the area of contour
		bounding_rect = cv::minAreaRect(contours[i]);
		//cv::rectangle(frameBGR, bounding_rect, color2);
		// rotated rectangle
		cv::Point2f rect_points[4]; bounding_rect.points(rect_points);
		for (int j = 0; j < 4; j++)
			line(frameBGR, rect_points[j], rect_points[(j + 1) % 4], color2, 1, 8);

		drawContours(frameBGR, contours, i, color, -1, 8, hierarchy); // Draw the largest contour using previously stored index.
	}
	/*
	for (int i = 0; i < contours2.size(); i++) // iterate through each contour.
	{
		double a = cv::contourArea(contours2[i], false);  //  Find the area of contour
		bounding_rect = cv::minAreaRect(contours2[i]);
		//cv::rectangle(frameBGR, bounding_rect, color4);
		drawContours(frameBGR, contours2, i, color3, -1, 8, hierarchy2); // Draw the largest contour using previously stored index.
	}
	*/

		cv::imshow("i", innerThresholded);
		cv::imshow("o", outerThresholded);
#else
//	cv::Mat image;
//	frameBGR.copyTo(image);
//	image.copyTo(frameBGR, imgThresholded);
	for (int dir = 0; dir < 2; dir++) {
		int end = dir ? frameHSV.cols - 1 : 0;
		for (int y = 0; y < frameHSV.rows; y+=5) {
			int outer_start = -1;
			int outer_end = -1;
			int inner_start = -1;
			int inner_end = -1;

			for (int x = 0; x < frameHSV.cols; x++) {
				if (inner_end > 0 && inner_end - inner_start > 1) {
					for (int z = inner_end; z >= 0; z--) {
						outerThresholded.ptr<uchar>(y)[dir ? end -z : z] = (unsigned char)255;
						frameBGR.at<cv::Vec3b>(y, dir ? end -z : z) = cv::Vec3b(0, 255, 0);
						frameHSV.at<cv::Vec3b>(y, dir ? end - z : z) = cv::Vec3b(0, 255, 255);
					}
					for (int z = outer_end; z > outer_start; z--) {
						//outerThresholded.ptr<uchar>(y)[z] = (unsigned char)255;
						frameBGR.at<cv::Vec3b>(y, dir ? end - z : z) = cv::Vec3b(0, 255, 255);
					}
					break;
				}
				else if (inner_start > 0 && x - inner_start > 10 && innerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 0) {
					inner_end = x;
				}
				else if (outer_end > 0 && x - outer_end < 150 && inner_start < 0 && innerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 255) {
					inner_start = x;
				}
				else if (outer_end < 0 && outer_start > 0 && x - outer_start > 10 && outerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 0) {
					outer_end = x;
				}
				else if (outer_start < 0 && outerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 255) {
					outer_start = x;
				}
			}
		}
	}

//	cv::imshow("io", innerThresholded + outerThresholded);
//	cv::imshow("i", innerThresholded);
//	cv::imshow("o", outerThresholded);
#endif

}

cv::Point3d ObjectFinder::ConvertPixelToRealWorld(const cv::Point2f &point, const cv::Point2i &frame_size)
{
	if (point.y < 1 && point.x < 1 || (point.y != point.y) || (point.x != point.x)){ //If there is no object found
		return cv::Point3d(-1, -1, -1);
	}

	const cv::Point2d center (frame_size.x / 2.0, frame_size.y / 2.0);
	//Calculating distance
	double angle = (Vfov * (point.y - center.y) / center.y) + CamAngleDev;
	double distance = CamHeight / tan(angle * PI / 180);
	//Calculating horizontal deviation
	double hor_space = tan(Vfov)*distance;
	double HorizontalDev = (hor_space * (point.x - center.x) / center.x);
	double Hor_angle = atan(HorizontalDev / distance)* 180/PI;
	if (Hor_angle < 0){
		Hor_angle = 360 + Hor_angle;
	}
	return cv::Point3d(distance, HorizontalDev, Hor_angle);
}

void ObjectFinder::WriteInfoOnScreen(const cv::Point3d &info){
	cv::Mat infoWindow(100, 250, CV_8UC3, cv::Scalar::all(0));
	std::ostringstream oss;
	oss << "Distance :" << info.x;
	cv::putText(infoWindow, oss.str(), cv::Point(20, 20), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));
	oss.str("");
	oss << "Horizontal Dev :" << info.y;
	cv::putText(infoWindow, oss.str(), cv::Point(20, 50), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));
	oss.str("");
	oss << "Horizontal angle :" << info.z;
	cv::putText(infoWindow, oss.str(), cv::Point(20, 80), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));
	cv::namedWindow("Info Window");
	cv::imshow("Info Window", infoWindow);
	return;
}

<commit_msg>border detection<commit_after>#include "objectfinder.h"

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

ObjectFinder::ObjectFinder()
{
	using boost::property_tree::ptree;
	try {

		ptree pt;
		read_ini("conf/camera.ini", pt);
		Vfov = pt.get<float>("Vfov");
		CamHeight = pt.get<float>("Height");
		CamAngleDev = pt.get<float>("AngleDev");
	}
	catch (...){
		ptree pt;
		pt.put("Height", CamHeight);
		pt.put("AngleDev", CamAngleDev);
		pt.put("Vfov", Vfov);

		write_ini("conf/camera.ini", pt);
	};
}
cv::Point3d ObjectFinder::Locate(const HSVColorRange &r, cv::Mat &frameHSV, cv::Mat &frameBGR) {
	cv::Point2f point = LocateOnScreen(r, frameHSV, frameBGR);
	cv::Point3d info = ConvertPixelToRealWorld(point, cv::Point2i(frameHSV.cols, frameHSV.rows));
	WriteInfoOnScreen(info);
	return info;
}

cv::Point2f ObjectFinder::LocateOnScreen(const HSVColorRange &r, cv::Mat &frameHSV, cv::Mat &frameBGR) {

	cv::Point2f center;
	//	cv::imshow("Thresholded Image 2", frameHSV); //show the thresholded image

	//	cv::imshow("Thresholded Image 3", imgHSV); //show the thresholded image
	cv::Mat imgThresholded;

	inRange(frameHSV, cv::Scalar(r.hue.low, r.sat.low, r.val.low), cv::Scalar(r.hue.high, r.sat.high, r.val.high), imgThresholded); //Threshold the image

	cv::Mat dst(imgThresholded.rows, imgThresholded.cols, CV_8U, cv::Scalar::all(0));

	//biggest area
	std::vector<std::vector<cv::Point> > contours; // Vector for storing contour
	std::vector<cv::Vec4i> hierarchy;
	int largest_area = 0;
	int largest_contour_index = 0;
	cv::Rect bounding_rect;

	findContours(imgThresholded, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // Find the contours in the image

	cv::Scalar color(255, 255, 255);
	cv::Scalar color2(0, 0, 255);

	for (int i = 0; i < contours.size(); i++) // iterate through each contour.
	{
		double a = cv::contourArea(contours[i], false);  //  Find the area of contour
		if (a > largest_area){
			largest_area = a;
			largest_contour_index = i;                //Store the index of largest contour
			bounding_rect = cv::boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
		}
		bounding_rect = cv::boundingRect(contours[i]);
		cv::rectangle(frameBGR, bounding_rect, color2);
		drawContours(frameBGR, contours, i, color, 1, 8, hierarchy); // Draw the largest contour using previously stored index.
	}

	//find center
	cv::Scalar colorCircle(133, 33, 55);

	if (contours.size() > largest_contour_index){
		cv::Moments M = cv::moments(contours[largest_contour_index]);
		center = cv::Point2f(M.m10 / M.m00, M.m01 / M.m00);
	}

	//Draw circle
	cv::circle(frameBGR, center, 10, colorCircle, 3);
//	cv::imshow("Original", imgOriginal);
//	cv::moveWindow("Original", 0, 0);
	return center;
}

void drawLine(cv::Mat & img, cv::Mat & img2, int dir, cv::Vec4f line, int thickness, CvScalar color)
{
	double theMult = std::max(img.cols, img.rows);
	// calculate start point
	cv::Point startPoint;
	startPoint.y = line[2] - theMult*line[0];// x0
	startPoint.x = line[3] - theMult*line[1];// y0
	// calculate end point
	cv::Point endPoint;
	endPoint.y = line[2] + theMult*line[0];//x[1]
	endPoint.x = line[3] + theMult*line[1];//y[1]

	// draw overlay of bottom lines on image
	cv::clipLine(cv::Size(img.cols, img.rows), startPoint, endPoint);
	std::vector <cv::Point2i> points;
	points.push_back(dir ? cv::Point2i(img.cols - 1, img.rows-1) : cv::Point2i(0, 0));
	points.push_back(cv::Point2i(img.cols - 1, 0));

	points.push_back(startPoint);
	points.push_back(endPoint);
	//cv::fillConvexPoly(img, points, cv::Scalar(0, 255, 0));
	cv::fillConvexPoly(img2, points, cv::Scalar(0, 255, 0));

	cv::line(img, startPoint, endPoint, color, thickness, 8, 0);

}

void ObjectFinder::IsolateField(const HSVColorRange &inner, const HSVColorRange &outer, const HSVColorRange &gate1, const HSVColorRange &gate2, cv::Mat &frameHSV, cv::Mat &frameBGR) {

	//	cv::imshow("Thresholded Image 3", imgHSV); //show the thresholded image
	cv::Mat innerThresholded;
	inRange(frameHSV, cv::Scalar(inner.hue.low, inner.sat.low, inner.val.low), cv::Scalar(inner.hue.high, inner.sat.high, inner.val.high), innerThresholded); //Threshold the image
	cv::Mat outerThresholded;
	inRange(frameHSV, cv::Scalar(outer.hue.low, outer.sat.low, outer.val.low), cv::Scalar(outer.hue.high, outer.sat.high, outer.val.high), outerThresholded); //Threshold the image

	cv::Mat gate1Thresholded;
	inRange(frameHSV, cv::Scalar(gate1.hue.low, gate1.sat.low, gate1.val.low), cv::Scalar(gate1.hue.high, gate1.sat.high, gate1.val.high), gate1Thresholded); //Threshold the image
	cv::Mat gate2Thresholded;
	inRange(frameHSV, cv::Scalar(gate2.hue.low, gate2.sat.low, gate2.val.low), cv::Scalar(gate2.hue.high, gate2.sat.high, gate2.val.high), gate2Thresholded); //Threshold the image

	std::vector<std::vector<cv::Point> > contours; // Vector for storing contour
	std::vector<cv::Vec4i> hierarchy;
	std::vector<std::vector<cv::Point> > contours2; // Vector for storing contour
	std::vector<cv::Vec4i> hierarchy2;

	/*
	cv::Point2d orgin(frameBGR.cols / 2, frameBGR.rows *0.9);
	cv::circle(frameBGR, orgin, 40, cv::Scalar(40, 20, 100), 10);
	for (float a = -PI; a < 0 ; a += PI/10) {
		bool was_border_start = false;
		for (float d = 0; d < frameBGR.cols ; d += 10) {
			float x = d * std::cos(a);
			float y = d * std::sin(a);
			if (abs(x) > orgin.x) break;
			if (y < -orgin.y) break;

			cv::Point2i point = orgin + cv::Point2d(x, y);
			bool border = abs(x) > orgin.x * 0.9 || y < -orgin.y*0.9;
			if (!border) {
				bool is_border_start = innerThresholded.ptr<uchar>(point.y)[point.x] == 255;
				bool is_border_end = outerThresholded.ptr<uchar>(point.y)[point.x] == 255;

				border = !is_border_start && is_border_end && was_border_start;
				was_border_start = is_border_start;
			}
			cv::circle(frameBGR, point, 4, border? cv::Scalar(d, 255, 100 * a)  : cv::Scalar(d, 20, 100 * a), 10);
			if (border) break;
		}
		//break;
	}
	*/

#ifdef USE_CONTOURS
	innerThresholded = outerThresholded + innerThresholded;
	findContours(innerThresholded, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // Find the contours in the image
	//findContours(outerThresholded, contours2, hierarchy2, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // Find the contours in the image

	cv::Scalar color(255, 255, 255);
	cv::Scalar color2(0, 0, 255);
	cv::Scalar color3(0, 0, 0);
	cv::Scalar color4(255, 0, 0);
	cv::RotatedRect bounding_rect;

	for (int i = 0; i < contours.size(); i++) // iterate through each contour.
	{
		double a = cv::contourArea(contours[i], false);  //  Find the area of contour
		bounding_rect = cv::minAreaRect(contours[i]);
		//cv::rectangle(frameBGR, bounding_rect, color2);
		// rotated rectangle
		cv::Point2f rect_points[4]; bounding_rect.points(rect_points);
		for (int j = 0; j < 4; j++)
			line(frameBGR, rect_points[j], rect_points[(j + 1) % 4], color2, 1, 8);

		drawContours(frameBGR, contours, i, color, -1, 8, hierarchy); // Draw the largest contour using previously stored index.
	}
	/*
	for (int i = 0; i < contours2.size(); i++) // iterate through each contour.
	{
		double a = cv::contourArea(contours2[i], false);  //  Find the area of contour
		bounding_rect = cv::minAreaRect(contours2[i]);
		//cv::rectangle(frameBGR, bounding_rect, color4);
		drawContours(frameBGR, contours2, i, color3, -1, 8, hierarchy2); // Draw the largest contour using previously stored index.
	}
	*/

		cv::imshow("i", innerThresholded);
		cv::imshow("o", outerThresholded);
#else

	outerThresholded = outerThresholded + gate1Thresholded + gate2Thresholded;
//	cv::Mat image;
//	frameBGR.copyTo(image);
//	image.copyTo(frameBGR, imgThresholded);
	//dir: left -> right, right -> left, top -> down
	for (int dir = 0; dir < 4; dir++) {
		std::vector<cv::Point2i> points;
		int end = dir ? frameHSV.cols - 1 : 0;
		//int last_y = -1;
		cv::Point2i last_point(-1, -1);
		cv::Point2i last_point2(-1, -1);
		for (int y = 0; y < frameHSV.rows; y += 5) {
			int outer_start = -1;
			int outer_end = -1;
			int inner_start = -1;
			int inner_end = -1;
			bool break2 = false;
			for (int x = 0; x < frameHSV.cols; x++) {
				if (inner_end > 0 && inner_end - inner_start > 1) {
					cv::Point2i new_point = cv::Point2i(y, dir ? end - inner_start : inner_start);
					// chekck the monotonicity
					if (last_point2.x != -1 &&  !(((last_point.x - new_point.x) >= 0) ^ ((last_point2.x - last_point.x) < 0))) { // direction change, not straight line
						break2 = true;
						break;
					}
					if (last_point.x != -1 && (new_point.x - last_point.x) > 30){ // to big gap, break
						break2 = true;
						break;
					}

					if (last_point.y != -1 && new_point.y - last_point.y < 20) {
						points.push_back(last_point);
						cv::circle(frameBGR, cv::Point2i(last_point.y, last_point.x), 4, dir ? cv::Scalar(255, 255, 100) : cv::Scalar(0, 20, 100), 10);
						for (int z = inner_end; z >= 0; z--) {
							outerThresholded.ptr<uchar>(y)[dir ? end - z : z] = (unsigned char)255;
							frameBGR.at<cv::Vec3b>(y, dir ? end - z : z) = cv::Vec3b(0, 255*dir, 0);
							frameHSV.at<cv::Vec3b>(y, dir ? end - z : z) = cv::Vec3b(0, 255, 255);
						}
						for (int z = outer_end; z > outer_start; z--) {
							//outerThresholded.ptr<uchar>(y)[z] = (unsigned char)255;
							frameBGR.at<cv::Vec3b>(y, dir ? end - z : z) = cv::Vec3b(0, 255 * dir, 255);
						}
					}
					last_point2 = last_point;
					last_point = new_point;
					break;
				}
				else if (inner_start > 0 && x - inner_start > 10 && innerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 0) {
					inner_end = x;
				}
				else if (outer_end > 0 && x - outer_end < 150 && inner_start < 0 && innerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 255) {
					inner_start = x;
				}
				else if (outer_end < 0 && outer_start > 0 && x - outer_start > 10 && outerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 0) {
					outer_end = x;
				}
				else if (outer_start < 0 && outerThresholded.ptr<uchar>(y)[dir ? end -x : x] == 255) {
					outer_start = x;
				}
			}
			if (break2) break;
		}
		if (points.size() > 2) {
			cv::Vec4f newLine;
			cv::fitLine(points, newLine, CV_DIST_L2, 0, 0.001, 0.001);
			drawLine(frameBGR, frameHSV, dir, newLine, 2+dir, cv::Scalar(255, 255*(dir+0.3), 0));
		}
		//break;
	}

	cv::imshow("io", innerThresholded + outerThresholded);
	cv::imshow("i", innerThresholded);
	cv::imshow("o", outerThresholded);
#endif

}

cv::Point3d ObjectFinder::ConvertPixelToRealWorld(const cv::Point2f &point, const cv::Point2i &frame_size)
{
	if (point.y < 1 && point.x < 1 || (point.y != point.y) || (point.x != point.x)){ //If there is no object found
		return cv::Point3d(-1, -1, -1);
	}

	const cv::Point2d center (frame_size.x / 2.0, frame_size.y / 2.0);
	//Calculating distance
	double angle = (Vfov * (point.y - center.y) / center.y) + CamAngleDev;
	double distance = CamHeight / tan(angle * PI / 180);
	//Calculating horizontal deviation
	double hor_space = tan(Vfov)*distance;
	double HorizontalDev = (hor_space * (point.x - center.x) / center.x);
	double Hor_angle = atan(HorizontalDev / distance)* 180/PI;
	if (Hor_angle < 0){
		Hor_angle = 360 + Hor_angle;
	}
	return cv::Point3d(distance, HorizontalDev, Hor_angle);
}

void ObjectFinder::WriteInfoOnScreen(const cv::Point3d &info){
	cv::Mat infoWindow(100, 250, CV_8UC3, cv::Scalar::all(0));
	std::ostringstream oss;
	oss << "Distance :" << info.x;
	cv::putText(infoWindow, oss.str(), cv::Point(20, 20), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));
	oss.str("");
	oss << "Horizontal Dev :" << info.y;
	cv::putText(infoWindow, oss.str(), cv::Point(20, 50), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));
	oss.str("");
	oss << "Horizontal angle :" << info.z;
	cv::putText(infoWindow, oss.str(), cv::Point(20, 80), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));
	cv::namedWindow("Info Window");
	cv::imshow("Info Window", infoWindow);
	return;
}

<|endoftext|>


<commit_before>#include "managesievescriptsdialog.h"
#include "managesievescriptsdialog_p.h"

#include "sieveconfig.h"
#include "kmacctmgr.h"
#include "imapaccountbase.h"
#include "sievejob.h"
#include "kmkernel.h"

#include <klocale.h>
#include <kiconloader.h>
#include <kwin.h>
#include <kapplication.h>
#include <kinputdialog.h>
#include <kglobalsettings.h>
#include <kmessagebox.h>

#include <qlayout.h>
#include <qlistview.h>
#include <qtextedit.h>
#include <qpopupmenu.h>

#include <cassert>

inline QCheckListItem * qcli_cast( QListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<QCheckListItem*>( lvi ) : 0 ;
}
inline const QCheckListItem * qcli_cast( const QListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<const QCheckListItem*>( lvi ) : 0 ;
}

KMail::ManageSieveScriptsDialog::ManageSieveScriptsDialog( QWidget * parent, const char * name )
  : KDialogBase( Plain, i18n( "Manage Sieve Scripts" ), Ok|Close, Ok, parent, name, false ),
    mSieveEditor( 0 ),
    mContextMenuItem( 0 ),
    mWasActive( false )
{
  setWFlags( WGroupLeader|WDestructiveClose );
  KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );

  QVBoxLayout * vlay = new QVBoxLayout( plainPage(), 0, 0 );

  mListView = new QListView( plainPage() );
  mListView->addColumn( i18n( "Available Scripts" ) );
  mListView->setResizeMode( QListView::LastColumn );
  mListView->setRootIsDecorated( true );
  mListView->setSelectionMode( QListView::Single );
  connect( mListView, SIGNAL(contextMenuRequested(QListViewItem*,const QPoint&,int)),
           this, SLOT(slotContextMenuRequested(QListViewItem*, const QPoint&)) );
  connect( mListView, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)),
           this, SLOT(slotDoubleClicked(QListViewItem*)) );
  connect( mListView, SIGNAL(selectionChanged(QListViewItem*)),
           this, SLOT(slotSelectionChanged(QListViewItem*)) );
  vlay->addWidget( mListView );

  resize( 2 * sizeHint().width(), sizeHint().height() );

  slotRefresh();
}

KMail::ManageSieveScriptsDialog::~ManageSieveScriptsDialog() {
  killAllJobs();
}

void KMail::ManageSieveScriptsDialog::killAllJobs() {
  for ( QMap<SieveJob*,QCheckListItem*>::const_iterator it = mJobs.constBegin(), end = mJobs.constEnd() ; it != end ; ++it )
    it.key()->kill();
  mJobs.clear();
}

static KURL findUrlForAccount( const KMail::ImapAccountBase * a ) {
  assert( a );
  const KMail::SieveConfig sieve = a->sieveConfig();
  if ( !sieve.managesieveSupported() )
    return KURL();
  if ( sieve.reuseConfig() ) {
    // assemble Sieve url from the settings of the account:
    KURL u;
    u.setProtocol( "sieve" );
    u.setHost( a->host() );
    u.setUser( a->login() );
    u.setPass( a->passwd() );
    u.setPort( sieve.port() );
    return u;
  } else {
    return sieve.alternateURL();
  }
}

void KMail::ManageSieveScriptsDialog::slotRefresh() {
  killAllJobs();
  mUrls.clear();
  mListView->clear();

  KMAcctMgr * am = kmkernel->acctMgr();
  assert( am );
  QCheckListItem * last = 0;
  for ( KMAccount * a = am->first() ; a ; a = am->next() ) {
    last = new QCheckListItem( mListView, last, a->name(), QCheckListItem::Controller );
    last->setPixmap( 0, SmallIcon( "server" ) );
    if ( ImapAccountBase * iab = dynamic_cast<ImapAccountBase*>( a ) ) {
      const KURL u = findUrlForAccount( iab );
      if ( u.isEmpty() )
        continue;
      SieveJob * job = SieveJob::list( u );
      connect( job, SIGNAL(item(KMail::SieveJob*,const QString&,bool)),
               this, SLOT(slotItem(KMail::SieveJob*,const QString&,bool)) );
      connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
               this, SLOT(slotResult(KMail::SieveJob*,bool,const QString&,bool)) );
      mJobs.insert( job, last );
      mUrls.insert( last, u );
    } else {
      QListViewItem * item = new QListViewItem( last, i18n( "No Sieve URL configured" ) );
      item->setEnabled( false );
      last->setOpen( true );
    }
  }
}

void KMail::ManageSieveScriptsDialog::slotResult( KMail::SieveJob * job, bool success, const QString &, bool ) {
  QCheckListItem * parent = mJobs[job];
  if ( !parent )
    return;

  mJobs.remove( job );

  parent->setOpen( true );

  if ( success )
    return;

  QListViewItem * item = new QListViewItem( parent, i18n( "Failed to fetch the list of scripts" ) );
  item->setEnabled( false );
}

void KMail::ManageSieveScriptsDialog::slotItem( KMail::SieveJob * job, const QString & filename, bool isActive ) {
  QCheckListItem * parent = mJobs[job];
  if ( !parent )
    return;
  QCheckListItem * item = new QCheckListItem( parent, filename, QCheckListItem::RadioButton );
  if ( isActive ) {
    item->setOn( true );
    mSelectedItems[parent] = item;
  }
}

void KMail::ManageSieveScriptsDialog::slotContextMenuRequested( QListViewItem * i, const QPoint & p ) {
  QCheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() && !mUrls.count( item ) )
    return;
  QPopupMenu menu;
  mContextMenuItem = item;
  if ( item->depth() ) {
    // script items:
    menu.insertItem( i18n( "Delete Script" ), this, SLOT(slotDeleteScript()) );
    menu.insertItem( i18n( "Edit Script..." ), this, SLOT(slotEditScript()) );
  } else {
    // top-levels:
    menu.insertItem( i18n( "New Script..." ), this, SLOT(slotNewScript()) );
  }
  menu.exec( p );
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotSelectionChanged( QListViewItem * i ) {
  QCheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  QCheckListItem * parent = qcli_cast( item->parent() );
  if ( !parent )
    return;
  if ( item->isOn() && mSelectedItems[parent] != item ) {
    mSelectedItems[parent] = item;
    changeActiveScript( parent );
  }
}

void KMail::ManageSieveScriptsDialog::changeActiveScript( QCheckListItem * item ) {
  if ( !item )
    return;
  if ( !mUrls.count( item ) )
    return;
  if ( !mSelectedItems.count( item ) )
    return;
  KURL u = mUrls[item];
  if ( u.isEmpty() )
    return;
  QCheckListItem * selected = mSelectedItems[item];
  if ( !selected )
    return;
  u.setFileName( selected->text( 0 ) );

  SieveJob * job = SieveJob::activate( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotDoubleClicked( QListViewItem * i ) {
  QCheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() )
    return;
  mContextMenuItem = item;
  slotEditScript();
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotDeleteScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;

  QCheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !parent )
    return;

  if ( !mUrls.count( parent ) )
    return;

  KURL u = mUrls[parent];
  if ( u.isEmpty() )
    return;

  u.setFileName( mContextMenuItem->text( 0 ) );

  if ( KMessageBox::questionYesNo( this, i18n( "Really delete script \"%1\" from the server?" ).arg( u.fileName() ),
                                   i18n( "Delete Sieve Script Confirmation" ),
                                   i18n( "Delete" ) )
       != KMessageBox::Yes )
    return;

  SieveJob * job = SieveJob::del( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotEditScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;
  QCheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !mUrls.count( parent ) )
    return;
  KURL url = mUrls[parent];
  if ( url.isEmpty() )
    return;
  url.setFileName( mContextMenuItem->text( 0 ) );
  mCurrentURL = url;
  SieveJob * job = SieveJob::get( url );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotNewScript() {
  if ( !mContextMenuItem )
    return;
  if ( mContextMenuItem->depth() )
    mContextMenuItem = qcli_cast( mContextMenuItem->parent() );
  if ( !mContextMenuItem )
    return;

  if ( !mUrls.count( mContextMenuItem ) )
    return;

  KURL u = mUrls[mContextMenuItem];
  if ( u.isEmpty() )
    return;

  bool ok = false;
  const QString name = KInputDialog::getText( i18n( "New Sieve Script" ),
                                              i18n( "Please enter a name for the new Sieve script:" ),
                                              i18n( "unnamed" ), &ok, this );
  if ( !ok || name.isEmpty() )
    return;

  u.setFileName( name );

  (void) new QCheckListItem( mContextMenuItem, name, QCheckListItem::RadioButton );

  mCurrentURL = u;
  slotGetResult( 0, true, QString::null, false );
}

KMail::SieveEditor::SieveEditor( QWidget * parent, const char * name )
  : KDialogBase( Plain, i18n( "Edit Sieve Script" ), Ok|Cancel, Ok, parent, name )
{
  QVBoxLayout * vlay = new QVBoxLayout( plainPage(), 0, spacingHint() );
  mTextEdit = new QTextEdit( plainPage() );
  vlay->addWidget( mTextEdit );
  mTextEdit->setTextFormat( QTextEdit::PlainText );
  mTextEdit->setWordWrap( QTextEdit::NoWrap );
  mTextEdit->setFont( KGlobalSettings::fixedFont() );

  resize( 3 * sizeHint() );
}

KMail::SieveEditor::~SieveEditor() {}

void KMail::ManageSieveScriptsDialog::slotGetResult( KMail::SieveJob *, bool success, const QString & script, bool isActive ) {
  if ( !success )
    return;

  if ( mSieveEditor )
    return;

  mSieveEditor = new SieveEditor( this );
  mSieveEditor->setScript( script );
  connect( mSieveEditor, SIGNAL(okClicked()), this, SLOT(slotSieveEditorOkClicked()) );
  connect( mSieveEditor, SIGNAL(cancelClicked()), this, SLOT(slotSieveEditorCancelClicked()) );
  mSieveEditor->show();
  mWasActive = isActive;
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorOkClicked() {
  if ( !mSieveEditor )
    return;
  SieveJob * job = SieveJob::put( mCurrentURL, mSieveEditor->script(), mWasActive, mWasActive );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotPutResult(KMail::SieveJob*,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorCancelClicked() {
  mSieveEditor->deleteLater(); mSieveEditor = 0;
  mCurrentURL = KURL();
}

void KMail::ManageSieveScriptsDialog::slotPutResult( KMail::SieveJob *, bool success ) {
  if ( success ) {
    KMessageBox::information( this, i18n( "The Sieve script was successfully uploaded." ),
                              i18n( "Sieve Script Upload" ) );
    mSieveEditor->deleteLater(); mSieveEditor = 0;
    mCurrentURL = KURL();
  } else {
    mSieveEditor->show();
  }
}

#include "managesievescriptsdialog.moc"
#include "managesievescriptsdialog_p.moc"
<commit_msg>Disambiguate for --enable-final<commit_after>#include "managesievescriptsdialog.h"
#include "managesievescriptsdialog_p.h"

#include "sieveconfig.h"
#include "kmacctmgr.h"
#include "imapaccountbase.h"
#include "sievejob.h"
#include "kmkernel.h"

#include <klocale.h>
#include <kiconloader.h>
#include <kwin.h>
#include <kapplication.h>
#include <kinputdialog.h>
#include <kglobalsettings.h>
#include <kmessagebox.h>

#include <qlayout.h>
#include <qlistview.h>
#include <qtextedit.h>
#include <qpopupmenu.h>

#include <cassert>

inline QCheckListItem * qcli_cast( QListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<QCheckListItem*>( lvi ) : 0 ;
}
inline const QCheckListItem * qcli_cast( const QListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<const QCheckListItem*>( lvi ) : 0 ;
}

KMail::ManageSieveScriptsDialog::ManageSieveScriptsDialog( QWidget * parent, const char * name )
  : KDialogBase( Plain, i18n( "Manage Sieve Scripts" ), Ok|Close, Ok, parent, name, false ),
    mSieveEditor( 0 ),
    mContextMenuItem( 0 ),
    mWasActive( false )
{
  setWFlags( WGroupLeader|WDestructiveClose );
  KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );

  QVBoxLayout * vlay = new QVBoxLayout( plainPage(), 0, 0 );

  mListView = new QListView( plainPage() );
  mListView->addColumn( i18n( "Available Scripts" ) );
  mListView->setResizeMode( QListView::LastColumn );
  mListView->setRootIsDecorated( true );
  mListView->setSelectionMode( QListView::Single );
  connect( mListView, SIGNAL(contextMenuRequested(QListViewItem*,const QPoint&,int)),
           this, SLOT(slotContextMenuRequested(QListViewItem*, const QPoint&)) );
  connect( mListView, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)),
           this, SLOT(slotDoubleClicked(QListViewItem*)) );
  connect( mListView, SIGNAL(selectionChanged(QListViewItem*)),
           this, SLOT(slotSelectionChanged(QListViewItem*)) );
  vlay->addWidget( mListView );

  resize( 2 * sizeHint().width(), sizeHint().height() );

  slotRefresh();
}

KMail::ManageSieveScriptsDialog::~ManageSieveScriptsDialog() {
  killAllJobs();
}

void KMail::ManageSieveScriptsDialog::killAllJobs() {
  for ( QMap<SieveJob*,QCheckListItem*>::const_iterator it = mJobs.constBegin(), end = mJobs.constEnd() ; it != end ; ++it )
    it.key()->kill();
  mJobs.clear();
}

static KURL findUrlForAccount( const KMail::ImapAccountBase * a ) {
  assert( a );
  const KMail::SieveConfig sieve = a->sieveConfig();
  if ( !sieve.managesieveSupported() )
    return KURL();
  if ( sieve.reuseConfig() ) {
    // assemble Sieve url from the settings of the account:
    KURL u;
    u.setProtocol( "sieve" );
    u.setHost( a->host() );
    u.setUser( a->login() );
    u.setPass( a->passwd() );
    u.setPort( sieve.port() );
    return u;
  } else {
    return sieve.alternateURL();
  }
}

void KMail::ManageSieveScriptsDialog::slotRefresh() {
  killAllJobs();
  mUrls.clear();
  mListView->clear();

  KMAcctMgr * am = kmkernel->acctMgr();
  assert( am );
  QCheckListItem * last = 0;
  for ( KMAccount * a = am->first() ; a ; a = am->next() ) {
    last = new QCheckListItem( mListView, last, a->name(), QCheckListItem::Controller );
    last->setPixmap( 0, SmallIcon( "server" ) );
    if ( ImapAccountBase * iab = dynamic_cast<ImapAccountBase*>( a ) ) {
      const KURL u = ::findUrlForAccount( iab );
      if ( u.isEmpty() )
        continue;
      SieveJob * job = SieveJob::list( u );
      connect( job, SIGNAL(item(KMail::SieveJob*,const QString&,bool)),
               this, SLOT(slotItem(KMail::SieveJob*,const QString&,bool)) );
      connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
               this, SLOT(slotResult(KMail::SieveJob*,bool,const QString&,bool)) );
      mJobs.insert( job, last );
      mUrls.insert( last, u );
    } else {
      QListViewItem * item = new QListViewItem( last, i18n( "No Sieve URL configured" ) );
      item->setEnabled( false );
      last->setOpen( true );
    }
  }
}

void KMail::ManageSieveScriptsDialog::slotResult( KMail::SieveJob * job, bool success, const QString &, bool ) {
  QCheckListItem * parent = mJobs[job];
  if ( !parent )
    return;

  mJobs.remove( job );

  parent->setOpen( true );

  if ( success )
    return;

  QListViewItem * item = new QListViewItem( parent, i18n( "Failed to fetch the list of scripts" ) );
  item->setEnabled( false );
}

void KMail::ManageSieveScriptsDialog::slotItem( KMail::SieveJob * job, const QString & filename, bool isActive ) {
  QCheckListItem * parent = mJobs[job];
  if ( !parent )
    return;
  QCheckListItem * item = new QCheckListItem( parent, filename, QCheckListItem::RadioButton );
  if ( isActive ) {
    item->setOn( true );
    mSelectedItems[parent] = item;
  }
}

void KMail::ManageSieveScriptsDialog::slotContextMenuRequested( QListViewItem * i, const QPoint & p ) {
  QCheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() && !mUrls.count( item ) )
    return;
  QPopupMenu menu;
  mContextMenuItem = item;
  if ( item->depth() ) {
    // script items:
    menu.insertItem( i18n( "Delete Script" ), this, SLOT(slotDeleteScript()) );
    menu.insertItem( i18n( "Edit Script..." ), this, SLOT(slotEditScript()) );
  } else {
    // top-levels:
    menu.insertItem( i18n( "New Script..." ), this, SLOT(slotNewScript()) );
  }
  menu.exec( p );
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotSelectionChanged( QListViewItem * i ) {
  QCheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  QCheckListItem * parent = qcli_cast( item->parent() );
  if ( !parent )
    return;
  if ( item->isOn() && mSelectedItems[parent] != item ) {
    mSelectedItems[parent] = item;
    changeActiveScript( parent );
  }
}

void KMail::ManageSieveScriptsDialog::changeActiveScript( QCheckListItem * item ) {
  if ( !item )
    return;
  if ( !mUrls.count( item ) )
    return;
  if ( !mSelectedItems.count( item ) )
    return;
  KURL u = mUrls[item];
  if ( u.isEmpty() )
    return;
  QCheckListItem * selected = mSelectedItems[item];
  if ( !selected )
    return;
  u.setFileName( selected->text( 0 ) );

  SieveJob * job = SieveJob::activate( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotDoubleClicked( QListViewItem * i ) {
  QCheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() )
    return;
  mContextMenuItem = item;
  slotEditScript();
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotDeleteScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;

  QCheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !parent )
    return;

  if ( !mUrls.count( parent ) )
    return;

  KURL u = mUrls[parent];
  if ( u.isEmpty() )
    return;

  u.setFileName( mContextMenuItem->text( 0 ) );

  if ( KMessageBox::questionYesNo( this, i18n( "Really delete script \"%1\" from the server?" ).arg( u.fileName() ),
                                   i18n( "Delete Sieve Script Confirmation" ),
                                   i18n( "Delete" ) )
       != KMessageBox::Yes )
    return;

  SieveJob * job = SieveJob::del( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotEditScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;
  QCheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !mUrls.count( parent ) )
    return;
  KURL url = mUrls[parent];
  if ( url.isEmpty() )
    return;
  url.setFileName( mContextMenuItem->text( 0 ) );
  mCurrentURL = url;
  SieveJob * job = SieveJob::get( url );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotNewScript() {
  if ( !mContextMenuItem )
    return;
  if ( mContextMenuItem->depth() )
    mContextMenuItem = qcli_cast( mContextMenuItem->parent() );
  if ( !mContextMenuItem )
    return;

  if ( !mUrls.count( mContextMenuItem ) )
    return;

  KURL u = mUrls[mContextMenuItem];
  if ( u.isEmpty() )
    return;

  bool ok = false;
  const QString name = KInputDialog::getText( i18n( "New Sieve Script" ),
                                              i18n( "Please enter a name for the new Sieve script:" ),
                                              i18n( "unnamed" ), &ok, this );
  if ( !ok || name.isEmpty() )
    return;

  u.setFileName( name );

  (void) new QCheckListItem( mContextMenuItem, name, QCheckListItem::RadioButton );

  mCurrentURL = u;
  slotGetResult( 0, true, QString::null, false );
}

KMail::SieveEditor::SieveEditor( QWidget * parent, const char * name )
  : KDialogBase( Plain, i18n( "Edit Sieve Script" ), Ok|Cancel, Ok, parent, name )
{
  QVBoxLayout * vlay = new QVBoxLayout( plainPage(), 0, spacingHint() );
  mTextEdit = new QTextEdit( plainPage() );
  vlay->addWidget( mTextEdit );
  mTextEdit->setTextFormat( QTextEdit::PlainText );
  mTextEdit->setWordWrap( QTextEdit::NoWrap );
  mTextEdit->setFont( KGlobalSettings::fixedFont() );

  resize( 3 * sizeHint() );
}

KMail::SieveEditor::~SieveEditor() {}

void KMail::ManageSieveScriptsDialog::slotGetResult( KMail::SieveJob *, bool success, const QString & script, bool isActive ) {
  if ( !success )
    return;

  if ( mSieveEditor )
    return;

  mSieveEditor = new SieveEditor( this );
  mSieveEditor->setScript( script );
  connect( mSieveEditor, SIGNAL(okClicked()), this, SLOT(slotSieveEditorOkClicked()) );
  connect( mSieveEditor, SIGNAL(cancelClicked()), this, SLOT(slotSieveEditorCancelClicked()) );
  mSieveEditor->show();
  mWasActive = isActive;
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorOkClicked() {
  if ( !mSieveEditor )
    return;
  SieveJob * job = SieveJob::put( mCurrentURL, mSieveEditor->script(), mWasActive, mWasActive );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotPutResult(KMail::SieveJob*,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorCancelClicked() {
  mSieveEditor->deleteLater(); mSieveEditor = 0;
  mCurrentURL = KURL();
}

void KMail::ManageSieveScriptsDialog::slotPutResult( KMail::SieveJob *, bool success ) {
  if ( success ) {
    KMessageBox::information( this, i18n( "The Sieve script was successfully uploaded." ),
                              i18n( "Sieve Script Upload" ) );
    mSieveEditor->deleteLater(); mSieveEditor = 0;
    mCurrentURL = KURL();
  } else {
    mSieveEditor->show();
  }
}

#include "managesievescriptsdialog.moc"
#include "managesievescriptsdialog_p.moc"
<|endoftext|>


<commit_before>#pragma once

#include "events.hpp"
#include "render_policy.hpp"
#include "information_display.hpp"
#include "window_handle.hpp"
#include "location_state.hpp"
#include "navigator.hpp"
#include "animator.hpp"
#include "feature_vec_model.hpp"
#include "scales_processor.hpp"

#include "bookmark.hpp"
#include "bookmark_manager.hpp"
#include "balloon_manager.hpp"

#include "mwm_url.hpp"

#include "../defines.hpp"

#include "../search/search_engine.hpp"

#include "../storage/storage.hpp"

#include "../platform/location.hpp"

#include "../graphics/defines.hpp"
#include "../graphics/screen.hpp"
#include "../graphics/color.hpp"

#include "../geometry/rect2d.hpp"
#include "../geometry/screenbase.hpp"

#include "../base/logging.hpp"
#include "../base/strings_bundle.hpp"

#include "../std/vector.hpp"
#include "../std/shared_ptr.hpp"
#include "../std/scoped_ptr.hpp"
#include "../std/target_os.hpp"

//#define DRAW_TOUCH_POINTS

namespace search
{
  class Result;
  struct AddressInfo;
}

namespace gui { class Controller; }
namespace anim { class Controller; }

class CountryStatusDisplay;
class BenchmarkEngine;

/// Uncomment line to make fixed position settings and
/// build version for screenshots.
//#define FIXED_LOCATION

class Framework
{
#ifdef FIXED_LOCATION
  class FixedPosition
  {
    pair<double, double> m_latlon;
    double m_dirFromNorth;
    bool m_fixedLatLon, m_fixedDir;

  public:
    FixedPosition();

    void GetLat(double & l) const { if (m_fixedLatLon) l = m_latlon.first; }
    void GetLon(double & l) const { if (m_fixedLatLon) l = m_latlon.second; }

    void GetNorth(double & n) const { if (m_fixedDir) n = m_dirFromNorth; }
    bool HasNorth() const { return m_fixedDir; }

  } m_fixedPos;
#endif

protected:
  friend class BenchmarkEngine;

  StringsBundle m_stringsBundle;

  mutable scoped_ptr<search::Engine> m_pSearchEngine;
  model::FeaturesFetcher m_model;
  ScalesProcessor m_scales;
  Navigator m_navigator;
  Animator m_animator;

  typedef vector<BookmarkCategory *>::iterator CategoryIter;

  scoped_ptr<RenderPolicy> m_renderPolicy;

  double m_StartForegroundTime;

  bool m_queryMaxScaleMode;

  double const m_metresMinWidth;
  double const m_metresMaxWidth;
  int const m_minRulerWidth;

  int m_width;
  int m_height;

  location::ECompassProcessMode m_dragCompassProcessMode;
  location::ELocationProcessMode m_dragLocationProcessMode;

  void StopLocationFollow();

  //mutable threads::Mutex m_modelSyn;

  storage::Storage m_storage;
  scoped_ptr<gui::Controller> m_guiController;
  scoped_ptr<anim::Controller> m_animController;
  InformationDisplay m_informationDisplay;

  /// This function is called by m_storage to notify that country downloading is finished.
  /// @param[in] file Country file name (without extensions).
  void UpdateAfterDownload(string const & file);

  //my::Timer m_timer;
  inline double ElapsedSeconds() const
  {
    //return m_timer.ElapsedSeconds();
    return 0.0;
  }

  /// Stores lowest loaded map version or MAX_INT if no maps added.
  /// @see feature::DataHeader::Version
  int m_lowestMapVersion;

  void DrawAdditionalInfo(shared_ptr<PaintEvent> const & e);

  BenchmarkEngine * m_benchmarkEngine;

  BookmarkManager m_bmManager;
  BalloonManager m_balloonManager;

  void ClearAllCaches();

  void RemoveMap(string const & file);

public:
  Framework();
  virtual ~Framework();

  /// @name Process storage connecting/disconnecting.
  //@{
  void AddLocalMaps();
  void RemoveLocalMaps();

  void AddMap(string const & file);
  //@}

  /// @return File names without path.
  void GetLocalMaps(vector<string> & outMaps) const;

  /// @name This functions is used by Downloader UI.
  //@{
  void DeleteCountry(storage::TIndex const & index);

  storage::TStatus GetCountryStatus(storage::TIndex const & index) const;
  string GetCountryName(storage::TIndex const & index) const;

  /// Get country rect from borders (not from mwm file).
  /// @param[in] file Pass country file name without extension as an id.
  m2::RectD GetCountryBounds(string const & file) const;
  m2::RectD GetCountryBounds(storage::TIndex const & index) const;

  void ShowCountry(storage::TIndex const & index);
  //@}

  /// Scans and loads all kml files with bookmarks in WritableDir.
  void LoadBookmarks();

  /// @return Created bookmark index in category.
  size_t AddBookmark(size_t categoryIndex, Bookmark & bm);
  /// @return Created bookmark category index.
  size_t AddCategory(string const & categoryName);

  inline size_t GetBmCategoriesCount() const { return m_bmManager.GetBmCategoriesCount(); }
  /// @returns 0 if category is not found
  BookmarkCategory * GetBmCategory(size_t index) const;

  size_t LastEditedCategory();

  /// Delete bookmarks category with all bookmarks.
  /// @return true if category was deleted
  bool DeleteBmCategory(size_t index);

  /// @name Get bookmark by touch.
  /// @param[in]  pixPt   Coordinates of touch point in pixels.
  /// @return     NULL    If there is no bookmark found
  //@{
  BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint) const;
  BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint, double visualScale) const;
  //@}

  void ShowBookmark(BookmarkAndCategory bnc);

  void ClearBookmarks();

  bool AddBookmarksFile(string const & filePath);

  //Additional Layer methods
  void AdditionalPoiLayerSetInvisible();
  void AdditionalPoiLayerSetVisible();
  void AdditionalPoiLayerAddPoi(Bookmark const & bm);
  Bookmark const * AdditionalPoiLayerGetBookmark(size_t index) const;
  Bookmark * AdditionalPoiLayerGetBookmark(size_t index);
  void AdditionalPoiLayerDeleteBookmark(int index);
  void AdditionalPoiLayerClear();
  bool IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const;
  bool AdditionalLayerIsVisible();
  size_t AdditionalLayerNumberOfPoi();

  inline m2::PointD PtoG(m2::PointD const & p) const { return m_navigator.PtoG(p); }
  inline m2::PointD GtoP(m2::PointD const & p) const { return m_navigator.GtoP(p); }

  storage::Storage & Storage() { return m_storage; }

  /// @name GPS location updates routine.
  //@{

  void StartLocation();
  void StopLocation();

  void OnLocationError(location::TLocationError error);
  void OnLocationUpdate(location::GpsInfo const & info);
  void OnCompassUpdate(location::CompassInfo const & info);
  //@}

  void SetRenderPolicy(RenderPolicy * renderPolicy);
  RenderPolicy * GetRenderPolicy() const;

  InformationDisplay & GetInformationDisplay();
  CountryStatusDisplay * GetCountryStatusDisplay() const;

  /// Safe function to get current visual scale.
  /// Call it when you need do calculate pixel rect (not matter if m_renderPolicy == 0).
  /// @return 1.0 if m_renderPolicy == 0 (possible for Android).
  double GetVisualScale() const;

  void PrepareToShutdown();

  void SetupMeasurementSystem();

  RenderPolicy::TRenderFn DrawModelFn();

  void DrawModel(shared_ptr<PaintEvent> const & e,
                 ScreenBase const & screen,
                 m2::RectD const & renderRect,
                 int baseScale);

private:
  search::Engine * GetSearchEngine() const;
  void AddBookmarkAndSetViewport(Bookmark & bm, m2::RectD const & viewPort);

public:
  m2::RectD GetCurrentViewport() const;

  /// Call this function before entering search GUI.
  /// While it's loading, we can cache features near user's position.
  /// @param[in] hasPt Are (lat, lon) valid
  /// @param[in] (lat, lon) Current user's position
  void PrepareSearch(bool hasPt, double lat = 0.0, double lon = 0.0);
  bool Search(search::SearchParams const & params);
  bool GetCurrentPosition(double & lat, double & lon) const;
  void ShowSearchResult(search::Result const & res);

  /// Calculate distance and direction to POI for the given position.
  /// @param[in]  point             POI's position;
  /// @param[in]  lat, lon, north   Current position and heading from north;
  /// @param[out] distance          Formatted distance string;
  /// @param[out] azimut            Azimut to point from (lat, lon);
  /// @return true  If the POI is near the current position (distance < 25 km);
  bool GetDistanceAndAzimut(m2::PointD const & point,
                            double lat, double lon, double north,
                            string & distance, double & azimut);

 //@{
  storage::TIndex GetCountryIndex(m2::PointD const & pt) const;

  string GetCountryName(m2::PointD const & pt) const;
  /// @param[in] id Country file name without an extension.
  string GetCountryName(string const & id) const;

  /// @return country code in ISO 3166-1 alpha-2 format (two small letters) or empty string
  string GetCountryCode(m2::PointD const & pt) const;
  //@}

  void SetMaxWorldRect();

  void Invalidate(bool doForceUpdate = false);
  void InvalidateRect(m2::RectD const & rect, bool doForceUpdate = false);

  void SaveState();
  bool LoadState();

  /// Resize event from window.
  virtual void OnSize(int w, int h);

  bool SetUpdatesEnabled(bool doEnable);

  int GetDrawScale() const;

  m2::PointD GetViewportCenter() const;
  void SetViewportCenter(m2::PointD const & pt);

  /// @param[out] outPoint is a point in url, where we need to show balloon
  bool SetViewportByURL(string const & url, url_scheme::ApiPoint & balloonPoint);

  bool NeedRedraw() const;
  void SetNeedRedraw(bool flag);

  inline void XorQueryMaxScaleMode()
  {
    m_queryMaxScaleMode = !m_queryMaxScaleMode;
    Invalidate(true);
  }

  /// Get classificator types for nearest features.
  /// @param[in] pixPt Current touch point in device pixel coordinates.
  void GetFeatureTypes(m2::PointD pixPt, vector<string> & types) const;

  /// Get address information for point on map.
  inline void GetAddressInfoForPixelPoint(m2::PointD const & pxPoint, search::AddressInfo & info) const
  {
    GetAddressInfoForGlobalPoint(PtoG(pxPoint), info);
  }
  void GetAddressInfoForGlobalPoint(m2::PointD const & pt, search::AddressInfo & info) const;

private:
  void GetAddressInfo(FeatureType const & ft, m2::PointD const & pt, search::AddressInfo & info) const;
  void GetLocality(m2::PointD const & pt, search::AddressInfo & info) const;

public:
  bool GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, search::AddressInfo & info) const;

  enum BookmarkOrPoi
  {
    NOTHING_FOUND = 0,
    BOOKMARK = 1,
    POI = 2
  };

  BookmarkOrPoi GetBookmarkOrPoi(m2::PointD const & pxPoint, m2::PointD & pxPivot,
                                 search::AddressInfo & info, BookmarkAndCategory & bmCat);

  virtual void BeginPaint(shared_ptr<PaintEvent> const & e);
  /// Function for calling from platform dependent-paint function.
  virtual void DoPaint(shared_ptr<PaintEvent> const & e);

  virtual void EndPaint(shared_ptr<PaintEvent> const & e);

private:
  m2::AnyRectD ToRotated(m2::RectD const & rect) const;
  void CheckMinGlobalRect(m2::AnyRectD & rect) const;
  /// @return true if rect was fixed to display downloaded zoom level (world map)
  bool CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale = -1) const;
  void ShowRectFixed(m2::AnyRectD const & rect);

public:
  /// Set navigator viewport by rect as-is.
  void ShowRect(m2::RectD const & rect);
  /// - Use navigator rotate angle.
  /// - Check for fixed scales from navigator.
  void ShowRectEx(m2::RectD const & rect);
  /// - Check minimal visible scale according to downloaded countries.
  void ShowRectExVisibleScale(m2::RectD rect, int maxScale = -1);

  void MemoryWarning();
  void EnterBackground();
  void EnterForeground();

  /// Show all model by it's world rect.
  void ShowAll();

  /// @name Drag implementation.
  //@{
private:
  m2::PointD GetPixelCenter() const;
public:
  void StartDrag(DragEvent const & e);
  void DoDrag(DragEvent const & e);
  void StopDrag(DragEvent const & e);
  void Move(double azDir, double factor);
  //@}

  /// @name Rotation implementation
  //@{
  void StartRotate(RotateEvent const & e);
  void DoRotate(RotateEvent const & e);
  void StopRotate(RotateEvent const & e);
  //@}

  /// @name Scaling.
  //@{
  void ScaleToPoint(ScaleToPointEvent const & e);
  void ScaleDefault(bool enlarge);
  void Scale(double scale);

private:
  void CalcScalePoints(ScaleEvent const & e, m2::PointD & pt1, m2::PointD & pt2) const;
public:
  void StartScale(ScaleEvent const & e);
  void DoScale(ScaleEvent const & e);
  void StopScale(ScaleEvent const & e);
  //@}

  gui::Controller * GetGuiController() const;
  anim::Controller * GetAnimController() const;

  Animator & GetAnimator();
  Navigator & GetNavigator();

  /// Set the localized strings bundle
  inline void AddString(string const & name, string const & value)
  {
    m_stringsBundle.SetString(name, value);
  }

  bool IsBenchmarking() const;

  StringsBundle const & GetStringsBundle();

  BalloonManager & GetBalloonManager() { return m_balloonManager; }

  /// Checks, whether the country which contains
  /// the specified point is loaded
  bool IsCountryLoaded(m2::PointD const & pt) const;

  shared_ptr<location::State> const & GetLocationState() const;

public:
  string CodeGe0url(Bookmark const * bmk, bool const addName);
  string CodeGe0url(double const lat, double const lon, double const zoomLevel, string const & name);

private:
  url_scheme::ParsedMapApi m_ParsedMapApi;
  void DrawMapApiPoints(shared_ptr<PaintEvent> const & e);
  void SetViewPortASync(m2::RectD const & rect);

public:
  /// @name Api
  //@{
  void MapApiSetUriAndParse(string const & url);
  bool GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ApiPoint & point);
  vector<url_scheme::ApiPoint> const & GetMapApiPoints() { return m_ParsedMapApi.GetPoints(); }
  void ClearMapApiPoints() { m_ParsedMapApi.Reset(); }
  int GetMapApiVersion() const { return m_ParsedMapApi.GetApiVersion(); }
  string const & GetMapApiAppTitle() const { return m_ParsedMapApi.GetAppTitle(); }
  string const & GetMapApiBackUrl() const { return m_ParsedMapApi.GetGlobalBackUrl(); }
  m2::RectD GetMapApiLatLonRect() const { return m_ParsedMapApi.GetLatLonRect(); }
  bool IsValidMapApi() const { return m_ParsedMapApi.IsValid(); }
  string GenerateApiBackUrl(url_scheme::ApiPoint const & point);
  //@}

  /// @name Map updates
  //@{
  bool IsDataVersionChanged();
  void UpdateSavedDataVersion();
  //@}
};
<commit_msg>[framework] set queryMaxScaleMode from parameter<commit_after>#pragma once

#include "events.hpp"
#include "render_policy.hpp"
#include "information_display.hpp"
#include "window_handle.hpp"
#include "location_state.hpp"
#include "navigator.hpp"
#include "animator.hpp"
#include "feature_vec_model.hpp"
#include "scales_processor.hpp"

#include "bookmark.hpp"
#include "bookmark_manager.hpp"
#include "balloon_manager.hpp"

#include "mwm_url.hpp"

#include "../defines.hpp"

#include "../search/search_engine.hpp"

#include "../storage/storage.hpp"

#include "../platform/location.hpp"

#include "../graphics/defines.hpp"
#include "../graphics/screen.hpp"
#include "../graphics/color.hpp"

#include "../geometry/rect2d.hpp"
#include "../geometry/screenbase.hpp"

#include "../base/logging.hpp"
#include "../base/strings_bundle.hpp"

#include "../std/vector.hpp"
#include "../std/shared_ptr.hpp"
#include "../std/scoped_ptr.hpp"
#include "../std/target_os.hpp"

//#define DRAW_TOUCH_POINTS

namespace search
{
  class Result;
  struct AddressInfo;
}

namespace gui { class Controller; }
namespace anim { class Controller; }

class CountryStatusDisplay;
class BenchmarkEngine;

/// Uncomment line to make fixed position settings and
/// build version for screenshots.
//#define FIXED_LOCATION

class Framework
{
#ifdef FIXED_LOCATION
  class FixedPosition
  {
    pair<double, double> m_latlon;
    double m_dirFromNorth;
    bool m_fixedLatLon, m_fixedDir;

  public:
    FixedPosition();

    void GetLat(double & l) const { if (m_fixedLatLon) l = m_latlon.first; }
    void GetLon(double & l) const { if (m_fixedLatLon) l = m_latlon.second; }

    void GetNorth(double & n) const { if (m_fixedDir) n = m_dirFromNorth; }
    bool HasNorth() const { return m_fixedDir; }

  } m_fixedPos;
#endif

protected:
  friend class BenchmarkEngine;

  StringsBundle m_stringsBundle;

  mutable scoped_ptr<search::Engine> m_pSearchEngine;
  model::FeaturesFetcher m_model;
  ScalesProcessor m_scales;
  Navigator m_navigator;
  Animator m_animator;

  typedef vector<BookmarkCategory *>::iterator CategoryIter;

  scoped_ptr<RenderPolicy> m_renderPolicy;

  double m_StartForegroundTime;

  bool m_queryMaxScaleMode;

  double const m_metresMinWidth;
  double const m_metresMaxWidth;
  int const m_minRulerWidth;

  int m_width;
  int m_height;

  location::ECompassProcessMode m_dragCompassProcessMode;
  location::ELocationProcessMode m_dragLocationProcessMode;

  void StopLocationFollow();

  //mutable threads::Mutex m_modelSyn;

  storage::Storage m_storage;
  scoped_ptr<gui::Controller> m_guiController;
  scoped_ptr<anim::Controller> m_animController;
  InformationDisplay m_informationDisplay;

  /// This function is called by m_storage to notify that country downloading is finished.
  /// @param[in] file Country file name (without extensions).
  void UpdateAfterDownload(string const & file);

  //my::Timer m_timer;
  inline double ElapsedSeconds() const
  {
    //return m_timer.ElapsedSeconds();
    return 0.0;
  }

  /// Stores lowest loaded map version or MAX_INT if no maps added.
  /// @see feature::DataHeader::Version
  int m_lowestMapVersion;

  void DrawAdditionalInfo(shared_ptr<PaintEvent> const & e);

  BenchmarkEngine * m_benchmarkEngine;

  BookmarkManager m_bmManager;
  BalloonManager m_balloonManager;

  void ClearAllCaches();

  void RemoveMap(string const & file);

public:
  Framework();
  virtual ~Framework();

  /// @name Process storage connecting/disconnecting.
  //@{
  void AddLocalMaps();
  void RemoveLocalMaps();

  void AddMap(string const & file);
  //@}

  /// @return File names without path.
  void GetLocalMaps(vector<string> & outMaps) const;

  /// @name This functions is used by Downloader UI.
  //@{
  void DeleteCountry(storage::TIndex const & index);

  storage::TStatus GetCountryStatus(storage::TIndex const & index) const;
  string GetCountryName(storage::TIndex const & index) const;

  /// Get country rect from borders (not from mwm file).
  /// @param[in] file Pass country file name without extension as an id.
  m2::RectD GetCountryBounds(string const & file) const;
  m2::RectD GetCountryBounds(storage::TIndex const & index) const;

  void ShowCountry(storage::TIndex const & index);
  //@}

  /// Scans and loads all kml files with bookmarks in WritableDir.
  void LoadBookmarks();

  /// @return Created bookmark index in category.
  size_t AddBookmark(size_t categoryIndex, Bookmark & bm);
  /// @return Created bookmark category index.
  size_t AddCategory(string const & categoryName);

  inline size_t GetBmCategoriesCount() const { return m_bmManager.GetBmCategoriesCount(); }
  /// @returns 0 if category is not found
  BookmarkCategory * GetBmCategory(size_t index) const;

  size_t LastEditedCategory();

  /// Delete bookmarks category with all bookmarks.
  /// @return true if category was deleted
  bool DeleteBmCategory(size_t index);

  /// @name Get bookmark by touch.
  /// @param[in]  pixPt   Coordinates of touch point in pixels.
  /// @return     NULL    If there is no bookmark found
  //@{
  BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint) const;
  BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint, double visualScale) const;
  //@}

  void ShowBookmark(BookmarkAndCategory bnc);

  void ClearBookmarks();

  bool AddBookmarksFile(string const & filePath);

  //Additional Layer methods
  void AdditionalPoiLayerSetInvisible();
  void AdditionalPoiLayerSetVisible();
  void AdditionalPoiLayerAddPoi(Bookmark const & bm);
  Bookmark const * AdditionalPoiLayerGetBookmark(size_t index) const;
  Bookmark * AdditionalPoiLayerGetBookmark(size_t index);
  void AdditionalPoiLayerDeleteBookmark(int index);
  void AdditionalPoiLayerClear();
  bool IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const;
  bool AdditionalLayerIsVisible();
  size_t AdditionalLayerNumberOfPoi();

  inline m2::PointD PtoG(m2::PointD const & p) const { return m_navigator.PtoG(p); }
  inline m2::PointD GtoP(m2::PointD const & p) const { return m_navigator.GtoP(p); }

  storage::Storage & Storage() { return m_storage; }

  /// @name GPS location updates routine.
  //@{

  void StartLocation();
  void StopLocation();

  void OnLocationError(location::TLocationError error);
  void OnLocationUpdate(location::GpsInfo const & info);
  void OnCompassUpdate(location::CompassInfo const & info);
  //@}

  void SetRenderPolicy(RenderPolicy * renderPolicy);
  RenderPolicy * GetRenderPolicy() const;

  InformationDisplay & GetInformationDisplay();
  CountryStatusDisplay * GetCountryStatusDisplay() const;

  /// Safe function to get current visual scale.
  /// Call it when you need do calculate pixel rect (not matter if m_renderPolicy == 0).
  /// @return 1.0 if m_renderPolicy == 0 (possible for Android).
  double GetVisualScale() const;

  void PrepareToShutdown();

  void SetupMeasurementSystem();

  RenderPolicy::TRenderFn DrawModelFn();

  void DrawModel(shared_ptr<PaintEvent> const & e,
                 ScreenBase const & screen,
                 m2::RectD const & renderRect,
                 int baseScale);

private:
  search::Engine * GetSearchEngine() const;
  void AddBookmarkAndSetViewport(Bookmark & bm, m2::RectD const & viewPort);

public:
  m2::RectD GetCurrentViewport() const;

  /// Call this function before entering search GUI.
  /// While it's loading, we can cache features near user's position.
  /// @param[in] hasPt Are (lat, lon) valid
  /// @param[in] (lat, lon) Current user's position
  void PrepareSearch(bool hasPt, double lat = 0.0, double lon = 0.0);
  bool Search(search::SearchParams const & params);
  bool GetCurrentPosition(double & lat, double & lon) const;
  void ShowSearchResult(search::Result const & res);

  /// Calculate distance and direction to POI for the given position.
  /// @param[in]  point             POI's position;
  /// @param[in]  lat, lon, north   Current position and heading from north;
  /// @param[out] distance          Formatted distance string;
  /// @param[out] azimut            Azimut to point from (lat, lon);
  /// @return true  If the POI is near the current position (distance < 25 km);
  bool GetDistanceAndAzimut(m2::PointD const & point,
                            double lat, double lon, double north,
                            string & distance, double & azimut);

 //@{
  storage::TIndex GetCountryIndex(m2::PointD const & pt) const;

  string GetCountryName(m2::PointD const & pt) const;
  /// @param[in] id Country file name without an extension.
  string GetCountryName(string const & id) const;

  /// @return country code in ISO 3166-1 alpha-2 format (two small letters) or empty string
  string GetCountryCode(m2::PointD const & pt) const;
  //@}

  void SetMaxWorldRect();

  void Invalidate(bool doForceUpdate = false);
  void InvalidateRect(m2::RectD const & rect, bool doForceUpdate = false);

  void SaveState();
  bool LoadState();

  /// Resize event from window.
  virtual void OnSize(int w, int h);

  bool SetUpdatesEnabled(bool doEnable);

  int GetDrawScale() const;

  m2::PointD GetViewportCenter() const;
  void SetViewportCenter(m2::PointD const & pt);

  /// @param[out] outPoint is a point in url, where we need to show balloon
  bool SetViewportByURL(string const & url, url_scheme::ApiPoint & balloonPoint);

  bool NeedRedraw() const;
  void SetNeedRedraw(bool flag);

  inline void XorQueryMaxScaleMode()
  {
    m_queryMaxScaleMode = !m_queryMaxScaleMode;
    Invalidate(true);
  }

  inline void SetQueryMaxScaleMode(bool mode)
  {
    m_queryMaxScaleMode = mode;
    Invalidate(true);
  }

  /// Get classificator types for nearest features.
  /// @param[in] pixPt Current touch point in device pixel coordinates.
  void GetFeatureTypes(m2::PointD pixPt, vector<string> & types) const;

  /// Get address information for point on map.
  inline void GetAddressInfoForPixelPoint(m2::PointD const & pxPoint, search::AddressInfo & info) const
  {
    GetAddressInfoForGlobalPoint(PtoG(pxPoint), info);
  }
  void GetAddressInfoForGlobalPoint(m2::PointD const & pt, search::AddressInfo & info) const;

private:
  void GetAddressInfo(FeatureType const & ft, m2::PointD const & pt, search::AddressInfo & info) const;
  void GetLocality(m2::PointD const & pt, search::AddressInfo & info) const;

public:
  bool GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, search::AddressInfo & info) const;

  enum BookmarkOrPoi
  {
    NOTHING_FOUND = 0,
    BOOKMARK = 1,
    POI = 2
  };

  BookmarkOrPoi GetBookmarkOrPoi(m2::PointD const & pxPoint, m2::PointD & pxPivot,
                                 search::AddressInfo & info, BookmarkAndCategory & bmCat);

  virtual void BeginPaint(shared_ptr<PaintEvent> const & e);
  /// Function for calling from platform dependent-paint function.
  virtual void DoPaint(shared_ptr<PaintEvent> const & e);

  virtual void EndPaint(shared_ptr<PaintEvent> const & e);

private:
  m2::AnyRectD ToRotated(m2::RectD const & rect) const;
  void CheckMinGlobalRect(m2::AnyRectD & rect) const;
  /// @return true if rect was fixed to display downloaded zoom level (world map)
  bool CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale = -1) const;
  void ShowRectFixed(m2::AnyRectD const & rect);

public:
  /// Set navigator viewport by rect as-is.
  void ShowRect(m2::RectD const & rect);
  /// - Use navigator rotate angle.
  /// - Check for fixed scales from navigator.
  void ShowRectEx(m2::RectD const & rect);
  /// - Check minimal visible scale according to downloaded countries.
  void ShowRectExVisibleScale(m2::RectD rect, int maxScale = -1);

  void MemoryWarning();
  void EnterBackground();
  void EnterForeground();

  /// Show all model by it's world rect.
  void ShowAll();

  /// @name Drag implementation.
  //@{
private:
  m2::PointD GetPixelCenter() const;
public:
  void StartDrag(DragEvent const & e);
  void DoDrag(DragEvent const & e);
  void StopDrag(DragEvent const & e);
  void Move(double azDir, double factor);
  //@}

  /// @name Rotation implementation
  //@{
  void StartRotate(RotateEvent const & e);
  void DoRotate(RotateEvent const & e);
  void StopRotate(RotateEvent const & e);
  //@}

  /// @name Scaling.
  //@{
  void ScaleToPoint(ScaleToPointEvent const & e);
  void ScaleDefault(bool enlarge);
  void Scale(double scale);

private:
  void CalcScalePoints(ScaleEvent const & e, m2::PointD & pt1, m2::PointD & pt2) const;
public:
  void StartScale(ScaleEvent const & e);
  void DoScale(ScaleEvent const & e);
  void StopScale(ScaleEvent const & e);
  //@}

  gui::Controller * GetGuiController() const;
  anim::Controller * GetAnimController() const;

  Animator & GetAnimator();
  Navigator & GetNavigator();

  /// Set the localized strings bundle
  inline void AddString(string const & name, string const & value)
  {
    m_stringsBundle.SetString(name, value);
  }

  bool IsBenchmarking() const;

  StringsBundle const & GetStringsBundle();

  BalloonManager & GetBalloonManager() { return m_balloonManager; }

  /// Checks, whether the country which contains
  /// the specified point is loaded
  bool IsCountryLoaded(m2::PointD const & pt) const;

  shared_ptr<location::State> const & GetLocationState() const;

public:
  string CodeGe0url(Bookmark const * bmk, bool const addName);
  string CodeGe0url(double const lat, double const lon, double const zoomLevel, string const & name);

private:
  url_scheme::ParsedMapApi m_ParsedMapApi;
  void DrawMapApiPoints(shared_ptr<PaintEvent> const & e);
  void SetViewPortASync(m2::RectD const & rect);

public:
  /// @name Api
  //@{
  void MapApiSetUriAndParse(string const & url);
  bool GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ApiPoint & point);
  vector<url_scheme::ApiPoint> const & GetMapApiPoints() { return m_ParsedMapApi.GetPoints(); }
  void ClearMapApiPoints() { m_ParsedMapApi.Reset(); }
  int GetMapApiVersion() const { return m_ParsedMapApi.GetApiVersion(); }
  string const & GetMapApiAppTitle() const { return m_ParsedMapApi.GetAppTitle(); }
  string const & GetMapApiBackUrl() const { return m_ParsedMapApi.GetGlobalBackUrl(); }
  m2::RectD GetMapApiLatLonRect() const { return m_ParsedMapApi.GetLatLonRect(); }
  bool IsValidMapApi() const { return m_ParsedMapApi.IsValid(); }
  string GenerateApiBackUrl(url_scheme::ApiPoint const & point);
  //@}

  /// @name Map updates
  //@{
  bool IsDataVersionChanged();
  void UpdateSavedDataVersion();
  //@}
};
<|endoftext|>


<commit_before>/*
 *     Copyright (C) 2007 by Mathias Soeken <msoeken@tzi.de>
 *                   2007 the ktimetracker developers
 *
 *   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.
 *
 */

#include "timetrackerwidget.h"

#include <QFileInfo>
#include <QHBoxLayout>
#include <QTimer>
#include <QVBoxLayout>
#include <QVector>

#include <KDebug>
#include <KFileDialog>
#include <KIcon>
#include <KLocale>
#include <KMessageBox>
#include <KTabWidget>
#include <KTemporaryFile>
#include <KTreeWidgetSearchLine>
#include <KIO/Job>

#include "task.h"
#include "taskview.h"
#include "version.h"

//@cond PRIVATE
class TimetrackerWidget::Private {
  public:
    Private() :
      mLastView( 0 ) {}

    QWidget *mSearchLine;
    KTabWidget *mTabWidget;
    KTreeWidgetSearchLine *mSearchWidget;
    TaskView *mLastView;
    QVector<TaskView*> mIsNewVector;
};
//@endcond

TimetrackerWidget::TimetrackerWidget( QWidget *parent ) : QWidget( parent ),
  d( new TimetrackerWidget::Private() )
{
  QLayout *layout = new QVBoxLayout;
  layout->setMargin( 0 );
  layout->setSpacing( 0 );

  QLayout *innerLayout = new QHBoxLayout;
  d->mSearchLine = new QWidget( this );
  innerLayout->setMargin( KDialog::marginHint() );
  innerLayout->setSpacing( KDialog::spacingHint() );
  d->mSearchWidget = new KTreeWidgetSearchLine( d->mSearchLine );
  d->mSearchWidget->setClickMessage( i18n( "Search or add task" ) );
  innerLayout->addWidget( d->mSearchWidget );
  d->mSearchLine->setLayout( innerLayout );

  d->mTabWidget = new KTabWidget( this );
  layout->addWidget( d->mSearchLine );
  layout->addWidget( d->mTabWidget );
  setLayout( layout );

  d->mTabWidget->setFocus( Qt::OtherFocusReason );

  connect( d->mSearchWidget, SIGNAL( returnPressed( const QString& ) ),
           this, SLOT( slotAddTask( const QString& ) ) );
  connect( d->mTabWidget, SIGNAL( currentChanged( int ) ),
           this, SIGNAL( currentTaskViewChanged() ) );
  connect( d->mTabWidget, SIGNAL( currentChanged( int ) ),
           this, SLOT( slotCurrentChanged() ) );
}

TimetrackerWidget::~TimetrackerWidget()
{
  delete d;
}

void TimetrackerWidget::addTaskView( const QString &fileName )
{
  bool isNew = fileName.isEmpty();
  QString lFileName = fileName;

  if ( isNew ) {
    KTemporaryFile tempFile;
    tempFile.setAutoRemove( false );
    if ( tempFile.open() ) {
      lFileName = tempFile.fileName();
      tempFile.close();
    } else {
      KMessageBox::error( this, i18n( "Cannot create new file." ) );
      return;
    }
  }

  TaskView *taskView = new TaskView( this );
  taskView->setContextMenuPolicy( Qt::CustomContextMenu );
  connect( taskView, SIGNAL( customContextMenuRequested( const QPoint& ) ),
           this, SIGNAL( contextMenuRequested( const QPoint& ) ) );
  connect( taskView, SIGNAL( tasksChanged( const QList< Task* >& ) ),
           this, SLOT( updateTabs() ) );

  d->mTabWidget->addTab( taskView,
          isNew ? KIcon( "document-save" ) : KIcon( "karm" ),
          isNew ? i18n( "Untitled" ) : QFileInfo( lFileName ).fileName() );
  d->mTabWidget->setCurrentWidget( taskView );
  taskView->load( lFileName );
  d->mSearchWidget->addTreeWidget( taskView );

  if ( isNew ) {
    d->mIsNewVector.append( taskView );
  } else {
    // FIXME does not work for the startup page
    d->mTabWidget->setTabToolTip( d->mTabWidget->currentIndex(), lFileName );
  }

  // When adding the first tab currentChanged is not emitted, so...
  if ( !d->mLastView ) {
    emit currentTaskViewChanged();
    slotCurrentChanged();
  }
}

bool TimetrackerWidget::saveCurrentTaskView()
{
  QString fileName = KFileDialog::getSaveFileName( QString(), QString(), this );
  if ( !fileName.isEmpty() ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
    taskView->stopAllTimers();
    taskView->save();
    taskView->closeStorage();

    QString currentFilename = taskView->storage()->icalfile();
    KIO::file_move( currentFilename, fileName, -1, true, false, false );
    d->mIsNewVector.remove( d->mIsNewVector.indexOf( taskView ) );

    taskView->load( fileName );
    KIO::file_delete( currentFilename, false );

    d->mTabWidget->setTabIcon( d->mTabWidget->currentIndex(), KIcon( "karm" ) );
    d->mTabWidget->setTabText( d->mTabWidget->currentIndex(), QFileInfo( fileName ).fileName() );
    d->mTabWidget->setTabToolTip( d->mTabWidget->currentIndex(), fileName );

    return true;
  }

  return false;
}

TaskView* TimetrackerWidget::currentTaskView()
{
  return qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
}

Task* TimetrackerWidget::currentTask()
{
  TaskView *taskView = 0;
  if ( ( taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() ) ) ) {
    return taskView->current_item();
  } else {
    return 0;
  }
}

void TimetrackerWidget::newFile()
{
  addTaskView();
}

void TimetrackerWidget::openFile( const QString &fileName )
{
  addTaskView( fileName );
}

bool TimetrackerWidget::closeFile()
{
  TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  // is it an unsaved file?
  if ( d->mIsNewVector.contains( taskView ) ) {
    QString message = i18n( "This document has not been saved yet. Do you want to save it?" );
    QString caption = i18n( "Untitled" );

    int result = KMessageBox::questionYesNoCancel( this, message, caption );

    if ( result == KMessageBox::Cancel ) {
      return false;
    }

    if ( result == KMessageBox::Yes ) {
      if ( !saveCurrentTaskView() ) {
        return false;
      }
    } else { // result == No
      d->mIsNewVector.remove( d->mIsNewVector.indexOf( taskView ) );
    }

    taskView->stopAllTimers();
    taskView->save();
    taskView->closeStorage();
  }

  d->mTabWidget->removeTab( d->mTabWidget->currentIndex() );
  d->mSearchWidget->removeTreeWidget( taskView );

  /* emit signals and call slots since currentChanged is not emitted if
   * we close the last tab
   */
  if ( d->mTabWidget->count() == 0 ) {
    emit currentTaskViewChanged();
    slotCurrentChanged();
  }

  delete taskView; // removeTab does not delete its widget.
  return true;
}

QString TimetrackerWidget::saveFile()
{
  TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  // is it an unsaved file?
  if ( d->mIsNewVector.contains( taskView ) ) {
    saveCurrentTaskView();
  }

  return taskView->save();
}

void TimetrackerWidget::reconfigureFiles()
{
  TaskView *taskView;
  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    taskView->reconfigure();
  }
}

void TimetrackerWidget::showSearchBar( bool visible )
{
  d->mSearchLine->setVisible( visible );
}

bool TimetrackerWidget::closeAllFiles()
{
  while ( d->mTabWidget->count() > 0 ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( 0 ) );

    d->mTabWidget->setCurrentWidget( taskView );
    if ( !( closeFile() ) )
      return false;
  }

  return true;
}

void TimetrackerWidget::slotCurrentChanged()
{
  kDebug() << "entering KTimetrackerWidget::slotCurrentChanged";

  if ( d->mLastView ) {
    disconnect( d->mLastView, SIGNAL( totalTimesChanged( long, long ) ) );
    disconnect( d->mLastView, SIGNAL( itemSelectionChanged() ) );
    disconnect( d->mLastView, SIGNAL( updateButtons() ) );
    disconnect( d->mLastView, SIGNAL( setStatusBarText( QString ) ) );
    disconnect( d->mLastView, SIGNAL( timersActive() ) );
    disconnect( d->mLastView, SIGNAL( timersInactive() ) );
    disconnect( d->mLastView, SIGNAL( tasksChanged( const QList< Task* >& ) ),
                this, SIGNAL( tasksChanged( const QList< Task* > & ) ) );
  }

  d->mLastView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  if ( d->mLastView ) {
    connect( d->mLastView, SIGNAL( totalTimesChanged( long, long ) ),
            this, SIGNAL( totalTimesChanged( long, long ) ) );
    connect( d->mLastView, SIGNAL( itemSelectionChanged() ),
            this, SIGNAL( currentTaskChanged() ) );
    connect( d->mLastView, SIGNAL( updateButtons() ),
            this, SIGNAL( updateButtons() ) );
    connect( d->mLastView, SIGNAL( setStatusBarText( QString ) ), // FIXME signature
            this, SIGNAL( statusBarTextChangeRequested( const QString & ) ) );
    connect( d->mLastView, SIGNAL( timersActive() ),
            this, SIGNAL( timersActive() ) );
    connect( d->mLastView, SIGNAL( timersInactive() ),
            this, SIGNAL( timersInactive() ) );
    connect( d->mLastView, SIGNAL( tasksChanged( QList< Task* > ) ), // FIXME signature
            this, SIGNAL( tasksChanged( const QList< Task* > &) ) );
  }

  d->mSearchWidget->setEnabled( d->mLastView );
}

void TimetrackerWidget::updateTabs()
{
  TaskView *taskView;
  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    if ( taskView->activeTasks().count() == 0 ) {
      d->mTabWidget->setTabTextColor( i, palette().color( QPalette::Foreground ) );
    } else {
      d->mTabWidget->setTabTextColor( i, Qt::darkGreen );
    }
  }
}

void TimetrackerWidget::slotAddTask( const QString &taskName )
{
  TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  taskView->addTask( taskName, 0, 0, DesktopList(), 0 );

  d->mSearchWidget->clear();
}

//BEGIN wrapper slots
void TimetrackerWidget::startCurrentTimer()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->startCurrentTimer();
  }
}

void TimetrackerWidget::stopCurrentTimer()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->stopCurrentTimer();
  }
}

void TimetrackerWidget::stopAllTimers( const QDateTime &when )
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->stopAllTimers( when );
  }
}

void TimetrackerWidget::newTask()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->newTask();
  }
}

void TimetrackerWidget::newSubTask()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->newSubTask();
  }
}

void TimetrackerWidget::editTask()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->editTask();
  }
}

void TimetrackerWidget::deleteTask( bool markingascomplete )
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->deleteTask( markingascomplete );
  }
}

void TimetrackerWidget::markTaskAsComplete()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->markTaskAsComplete();
  }
}

void TimetrackerWidget::markTaskAsIncomplete()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->markTaskAsIncomplete();
  }
}

void TimetrackerWidget::exportcsvFile()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->exportcsvFile();
  }
}

void TimetrackerWidget::importPlanner( const QString &fileName )
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->importPlanner( fileName );
  }
}
//END

//BEGIN dbus slots
QString TimetrackerWidget::version() const
{
  return KTIMETRACKER_VERSION;
}

QStringList TimetrackerWidget::tasks() const
{
  QStringList result;

  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    if ( !taskView ) continue;

    for ( int j = 0; j < taskView->count(); ++j ) {
      result << taskView->item_at_index( j )->name();
    }
  }

  return result;
}

QStringList TimetrackerWidget::activeTasks() const
{
  QStringList result;

  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    if ( !taskView ) continue;

    for ( int j = 0; j < taskView->count(); ++j ) {
      if ( taskView->item_at_index( j )->isRunning() ) {
        result << taskView->item_at_index( j )->name();
      }
    }
  }

  return result;
}
//END

#include "timetrackerwidget.moc"
<commit_msg>Set focus to the taskView after adding a new task by search line<commit_after>/*
 *     Copyright (C) 2007 by Mathias Soeken <msoeken@tzi.de>
 *                   2007 the ktimetracker developers
 *
 *   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.
 *
 */

#include "timetrackerwidget.h"

#include <QFileInfo>
#include <QHBoxLayout>
#include <QTimer>
#include <QVBoxLayout>
#include <QVector>

#include <KDebug>
#include <KFileDialog>
#include <KIcon>
#include <KLocale>
#include <KMessageBox>
#include <KTabWidget>
#include <KTemporaryFile>
#include <KTreeWidgetSearchLine>
#include <KIO/Job>

#include "task.h"
#include "taskview.h"
#include "version.h"

//@cond PRIVATE
class TimetrackerWidget::Private {
  public:
    Private() :
      mLastView( 0 ) {}

    QWidget *mSearchLine;
    KTabWidget *mTabWidget;
    KTreeWidgetSearchLine *mSearchWidget;
    TaskView *mLastView;
    QVector<TaskView*> mIsNewVector;
};
//@endcond

TimetrackerWidget::TimetrackerWidget( QWidget *parent ) : QWidget( parent ),
  d( new TimetrackerWidget::Private() )
{
  QLayout *layout = new QVBoxLayout;
  layout->setMargin( 0 );
  layout->setSpacing( 0 );

  QLayout *innerLayout = new QHBoxLayout;
  d->mSearchLine = new QWidget( this );
  innerLayout->setMargin( KDialog::marginHint() );
  innerLayout->setSpacing( KDialog::spacingHint() );
  d->mSearchWidget = new KTreeWidgetSearchLine( d->mSearchLine );
  d->mSearchWidget->setClickMessage( i18n( "Search or add task" ) );
  innerLayout->addWidget( d->mSearchWidget );
  d->mSearchLine->setLayout( innerLayout );

  d->mTabWidget = new KTabWidget( this );
  layout->addWidget( d->mSearchLine );
  layout->addWidget( d->mTabWidget );
  setLayout( layout );

  d->mTabWidget->setFocus( Qt::OtherFocusReason );

  connect( d->mSearchWidget, SIGNAL( returnPressed( const QString& ) ),
           this, SLOT( slotAddTask( const QString& ) ) );
  connect( d->mTabWidget, SIGNAL( currentChanged( int ) ),
           this, SIGNAL( currentTaskViewChanged() ) );
  connect( d->mTabWidget, SIGNAL( currentChanged( int ) ),
           this, SLOT( slotCurrentChanged() ) );
}

TimetrackerWidget::~TimetrackerWidget()
{
  delete d;
}

void TimetrackerWidget::addTaskView( const QString &fileName )
{
  bool isNew = fileName.isEmpty();
  QString lFileName = fileName;

  if ( isNew ) {
    KTemporaryFile tempFile;
    tempFile.setAutoRemove( false );
    if ( tempFile.open() ) {
      lFileName = tempFile.fileName();
      tempFile.close();
    } else {
      KMessageBox::error( this, i18n( "Cannot create new file." ) );
      return;
    }
  }

  TaskView *taskView = new TaskView( this );
  taskView->setContextMenuPolicy( Qt::CustomContextMenu );
  connect( taskView, SIGNAL( customContextMenuRequested( const QPoint& ) ),
           this, SIGNAL( contextMenuRequested( const QPoint& ) ) );
  connect( taskView, SIGNAL( tasksChanged( const QList< Task* >& ) ),
           this, SLOT( updateTabs() ) );

  d->mTabWidget->addTab( taskView,
          isNew ? KIcon( "document-save" ) : KIcon( "karm" ),
          isNew ? i18n( "Untitled" ) : QFileInfo( lFileName ).fileName() );
  d->mTabWidget->setCurrentWidget( taskView );
  taskView->load( lFileName );
  d->mSearchWidget->addTreeWidget( taskView );

  if ( isNew ) {
    d->mIsNewVector.append( taskView );
  } else {
    // FIXME does not work for the startup page
    d->mTabWidget->setTabToolTip( d->mTabWidget->currentIndex(), lFileName );
  }

  // When adding the first tab currentChanged is not emitted, so...
  if ( !d->mLastView ) {
    emit currentTaskViewChanged();
    slotCurrentChanged();
  }
}

bool TimetrackerWidget::saveCurrentTaskView()
{
  QString fileName = KFileDialog::getSaveFileName( QString(), QString(), this );
  if ( !fileName.isEmpty() ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
    taskView->stopAllTimers();
    taskView->save();
    taskView->closeStorage();

    QString currentFilename = taskView->storage()->icalfile();
    KIO::file_move( currentFilename, fileName, -1, true, false, false );
    d->mIsNewVector.remove( d->mIsNewVector.indexOf( taskView ) );

    taskView->load( fileName );
    KIO::file_delete( currentFilename, false );

    d->mTabWidget->setTabIcon( d->mTabWidget->currentIndex(), KIcon( "karm" ) );
    d->mTabWidget->setTabText( d->mTabWidget->currentIndex(), QFileInfo( fileName ).fileName() );
    d->mTabWidget->setTabToolTip( d->mTabWidget->currentIndex(), fileName );

    return true;
  }

  return false;
}

TaskView* TimetrackerWidget::currentTaskView()
{
  return qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );
}

Task* TimetrackerWidget::currentTask()
{
  TaskView *taskView = 0;
  if ( ( taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() ) ) ) {
    return taskView->current_item();
  } else {
    return 0;
  }
}

void TimetrackerWidget::newFile()
{
  addTaskView();
}

void TimetrackerWidget::openFile( const QString &fileName )
{
  addTaskView( fileName );
}

bool TimetrackerWidget::closeFile()
{
  TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  // is it an unsaved file?
  if ( d->mIsNewVector.contains( taskView ) ) {
    QString message = i18n( "This document has not been saved yet. Do you want to save it?" );
    QString caption = i18n( "Untitled" );

    int result = KMessageBox::questionYesNoCancel( this, message, caption );

    if ( result == KMessageBox::Cancel ) {
      return false;
    }

    if ( result == KMessageBox::Yes ) {
      if ( !saveCurrentTaskView() ) {
        return false;
      }
    } else { // result == No
      d->mIsNewVector.remove( d->mIsNewVector.indexOf( taskView ) );
    }

    taskView->stopAllTimers();
    taskView->save();
    taskView->closeStorage();
  }

  d->mTabWidget->removeTab( d->mTabWidget->currentIndex() );
  d->mSearchWidget->removeTreeWidget( taskView );

  /* emit signals and call slots since currentChanged is not emitted if
   * we close the last tab
   */
  if ( d->mTabWidget->count() == 0 ) {
    emit currentTaskViewChanged();
    slotCurrentChanged();
  }

  delete taskView; // removeTab does not delete its widget.
  return true;
}

QString TimetrackerWidget::saveFile()
{
  TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  // is it an unsaved file?
  if ( d->mIsNewVector.contains( taskView ) ) {
    saveCurrentTaskView();
  }

  return taskView->save();
}

void TimetrackerWidget::reconfigureFiles()
{
  TaskView *taskView;
  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    taskView->reconfigure();
  }
}

void TimetrackerWidget::showSearchBar( bool visible )
{
  d->mSearchLine->setVisible( visible );
}

bool TimetrackerWidget::closeAllFiles()
{
  while ( d->mTabWidget->count() > 0 ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( 0 ) );

    d->mTabWidget->setCurrentWidget( taskView );
    if ( !( closeFile() ) )
      return false;
  }

  return true;
}

void TimetrackerWidget::slotCurrentChanged()
{
  kDebug() << "entering KTimetrackerWidget::slotCurrentChanged";

  if ( d->mLastView ) {
    disconnect( d->mLastView, SIGNAL( totalTimesChanged( long, long ) ) );
    disconnect( d->mLastView, SIGNAL( itemSelectionChanged() ) );
    disconnect( d->mLastView, SIGNAL( updateButtons() ) );
    disconnect( d->mLastView, SIGNAL( setStatusBarText( QString ) ) );
    disconnect( d->mLastView, SIGNAL( timersActive() ) );
    disconnect( d->mLastView, SIGNAL( timersInactive() ) );
    disconnect( d->mLastView, SIGNAL( tasksChanged( const QList< Task* >& ) ),
                this, SIGNAL( tasksChanged( const QList< Task* > & ) ) );
  }

  d->mLastView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  if ( d->mLastView ) {
    connect( d->mLastView, SIGNAL( totalTimesChanged( long, long ) ),
            this, SIGNAL( totalTimesChanged( long, long ) ) );
    connect( d->mLastView, SIGNAL( itemSelectionChanged() ),
            this, SIGNAL( currentTaskChanged() ) );
    connect( d->mLastView, SIGNAL( updateButtons() ),
            this, SIGNAL( updateButtons() ) );
    connect( d->mLastView, SIGNAL( setStatusBarText( QString ) ), // FIXME signature
            this, SIGNAL( statusBarTextChangeRequested( const QString & ) ) );
    connect( d->mLastView, SIGNAL( timersActive() ),
            this, SIGNAL( timersActive() ) );
    connect( d->mLastView, SIGNAL( timersInactive() ),
            this, SIGNAL( timersInactive() ) );
    connect( d->mLastView, SIGNAL( tasksChanged( QList< Task* > ) ), // FIXME signature
            this, SIGNAL( tasksChanged( const QList< Task* > &) ) );
  }

  d->mSearchWidget->setEnabled( d->mLastView );
}

void TimetrackerWidget::updateTabs()
{
  TaskView *taskView;
  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    if ( taskView->activeTasks().count() == 0 ) {
      d->mTabWidget->setTabTextColor( i, palette().color( QPalette::Foreground ) );
    } else {
      d->mTabWidget->setTabTextColor( i, Qt::darkGreen );
    }
  }
}

void TimetrackerWidget::slotAddTask( const QString &taskName )
{
  TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->currentWidget() );

  taskView->addTask( taskName, 0, 0, DesktopList(), 0 );

  d->mSearchWidget->clear();
  d->mTabWidget->setFocus( Qt::OtherFocusReason );
}

//BEGIN wrapper slots
void TimetrackerWidget::startCurrentTimer()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->startCurrentTimer();
  }
}

void TimetrackerWidget::stopCurrentTimer()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->stopCurrentTimer();
  }
}

void TimetrackerWidget::stopAllTimers( const QDateTime &when )
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->stopAllTimers( when );
  }
}

void TimetrackerWidget::newTask()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->newTask();
  }
}

void TimetrackerWidget::newSubTask()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->newSubTask();
  }
}

void TimetrackerWidget::editTask()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->editTask();
  }
}

void TimetrackerWidget::deleteTask( bool markingascomplete )
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->deleteTask( markingascomplete );
  }
}

void TimetrackerWidget::markTaskAsComplete()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->markTaskAsComplete();
  }
}

void TimetrackerWidget::markTaskAsIncomplete()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->markTaskAsIncomplete();
  }
}

void TimetrackerWidget::exportcsvFile()
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->exportcsvFile();
  }
}

void TimetrackerWidget::importPlanner( const QString &fileName )
{
  if ( d->mTabWidget->currentWidget() ) {
    qobject_cast< TaskView* >( d->mTabWidget->currentWidget() )->importPlanner( fileName );
  }
}
//END

//BEGIN dbus slots
QString TimetrackerWidget::version() const
{
  return KTIMETRACKER_VERSION;
}

QStringList TimetrackerWidget::tasks() const
{
  QStringList result;

  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    if ( !taskView ) continue;

    for ( int j = 0; j < taskView->count(); ++j ) {
      result << taskView->item_at_index( j )->name();
    }
  }

  return result;
}

QStringList TimetrackerWidget::activeTasks() const
{
  QStringList result;

  for ( int i = 0; i < d->mTabWidget->count(); ++i ) {
    TaskView *taskView = qobject_cast< TaskView* >( d->mTabWidget->widget( i ) );

    if ( !taskView ) continue;

    for ( int j = 0; j < taskView->count(); ++j ) {
      if ( taskView->item_at_index( j )->isRunning() ) {
        result << taskView->item_at_index( j )->name();
      }
    }
  }

  return result;
}
//END

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