<commit_before>
#include "stdafx.h"
#include "resource.h"

#include "D2D_Graphics.h"

static const float c_JointThickness = 3.0f;
static const float c_TrackedBoneThickness = 6.0f;
static const float c_InferredBoneThickness = 1.0f;
static const float c_HandSize = 30.0f;

D2D_Graphics::D2D_Graphics():

m_pD2DFactory(NULL),
m_pRenderTarget(NULL),
m_pBrushJointTracked(NULL),
m_pBrushJointInferred(NULL),
m_pBrushBoneTracked(NULL),
m_pBrushBoneInferred(NULL),
m_pBrushHandClosed(NULL),
m_pBrushHandOpen(NULL),
m_pBrushHandLasso(NULL)

{

}

D2D_Graphics::~D2D_Graphics()
{
}

ID2D1HwndRenderTarget * D2D_Graphics::GetRenderTarget()
{
	return m_pRenderTarget;
}

void D2D_Graphics::SetRenderTarget(ID2D1HwndRenderTarget * renderTarget)
{
	m_pRenderTarget = renderTarget;
}

/// <summary>
/// Ensure necessary Direct2d resources are created
/// </summary>
/// <returns>S_OK if successful, otherwise an error code</returns>
HRESULT D2D_Graphics::EnsureDirect2DResources(HWND m_hWnd)
{
	HRESULT hr = S_OK;

	if (m_pD2DFactory && !m_pRenderTarget)
	{
		RECT rc;
		GetWindowRect(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), &rc);

		int width = rc.right - rc.left;
		int height = rc.bottom - rc.top;
		D2D1_SIZE_U size = D2D1::SizeU(width, height);
		D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties();
		rtProps.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
		rtProps.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;

		// Create a Hwnd render target, in order to render to the window set in initialize
		hr = m_pD2DFactory->CreateHwndRenderTarget(
			rtProps,
			D2D1::HwndRenderTargetProperties(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), size),
			&m_pRenderTarget
		);

		if (FAILED(hr))
		{
			//SetStatusMessage(L"Couldn't create Direct2D render target!", 10000, true);
			return hr;
		}

		// light green
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.27f, 0.75f, 0.27f), &m_pBrushJointTracked);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow, 1.0f), &m_pBrushJointInferred);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green, 1.0f), &m_pBrushBoneTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), &m_pBrushBoneInferred);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red, 0.5f), &m_pBrushHandClosed);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green, 0.5f), &m_pBrushHandOpen);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Blue, 0.5f), &m_pBrushHandLasso);
	}

	return hr;
}

/// <summary>
/// Dispose Direct2d resources
/// </summary>
void D2D_Graphics::DiscardDirect2DResources()
{
	SafeRelease(m_pRenderTarget);

	SafeRelease(m_pBrushJointTracked);
	SafeRelease(m_pBrushJointInferred);
	SafeRelease(m_pBrushBoneTracked);
	SafeRelease(m_pBrushBoneInferred);

	SafeRelease(m_pBrushHandClosed);
	SafeRelease(m_pBrushHandOpen);
	SafeRelease(m_pBrushHandLasso);
}

/// <summary>
/// Converts a body point to screen space
/// </summary>
/// <param name="bodyPoint">body point to tranform</param>
/// <param name="width">width (in pixels) of output buffer</param>
/// <param name="height">height (in pixels) of output buffer</param>
/// <returns>point in screen-space</returns>
D2D1_POINT_2F D2D_Graphics::BodyToScreen(const CameraSpacePoint& bodyPoint, int width, int height, ICoordinateMapper* m_pCoordinateMapper, int cDepthWidth, int cDepthHeight)
{
	// Calculate the body's position on the screen
	DepthSpacePoint depthPoint = { 0 };
	m_pCoordinateMapper->MapCameraPointToDepthSpace(bodyPoint, &depthPoint);

	float screenPointX = static_cast<float>(depthPoint.X * width) / cDepthWidth;
	float screenPointY = static_cast<float>(depthPoint.Y * height) / cDepthHeight;

	return D2D1::Point2F(screenPointX, screenPointY);
}

/// <summary>
/// Draws a body
/// </summary>
/// <param name="pJoints">joint data</param>
/// <param name="pJointPoints">joint positions converted to screen space</param>
void D2D_Graphics::DrawBody(const Joint* pJoints, const D2D1_POINT_2F* pJointPoints, const int colorID)
{
	// Draw the bones

	changeColor(colorID);

	// Torso
	DrawBone(pJoints, pJointPoints, JointType_Head, JointType_Neck);
	DrawBone(pJoints, pJointPoints, JointType_Neck, JointType_SpineShoulder);
	DrawBone(pJoints, pJointPoints, JointType_SpineShoulder, JointType_SpineMid);
	DrawBone(pJoints, pJointPoints, JointType_SpineMid, JointType_SpineBase);
	DrawBone(pJoints, pJointPoints, JointType_SpineShoulder, JointType_ShoulderRight);
	DrawBone(pJoints, pJointPoints, JointType_SpineShoulder, JointType_ShoulderLeft);
	DrawBone(pJoints, pJointPoints, JointType_SpineBase, JointType_HipRight);
	DrawBone(pJoints, pJointPoints, JointType_SpineBase, JointType_HipLeft);

	// Right Arm
	DrawBone(pJoints, pJointPoints, JointType_ShoulderRight, JointType_ElbowRight);
	DrawBone(pJoints, pJointPoints, JointType_ElbowRight, JointType_WristRight);
	DrawBone(pJoints, pJointPoints, JointType_WristRight, JointType_HandRight);
	DrawBone(pJoints, pJointPoints, JointType_HandRight, JointType_HandTipRight);
	DrawBone(pJoints, pJointPoints, JointType_WristRight, JointType_ThumbRight);

	// Left Arm
	DrawBone(pJoints, pJointPoints, JointType_ShoulderLeft, JointType_ElbowLeft);
	DrawBone(pJoints, pJointPoints, JointType_ElbowLeft, JointType_WristLeft);
	DrawBone(pJoints, pJointPoints, JointType_WristLeft, JointType_HandLeft);
	DrawBone(pJoints, pJointPoints, JointType_HandLeft, JointType_HandTipLeft);
	DrawBone(pJoints, pJointPoints, JointType_WristLeft, JointType_ThumbLeft);

	// Right Leg
	DrawBone(pJoints, pJointPoints, JointType_HipRight, JointType_KneeRight);
	DrawBone(pJoints, pJointPoints, JointType_KneeRight, JointType_AnkleRight);
	DrawBone(pJoints, pJointPoints, JointType_AnkleRight, JointType_FootRight);

	// Left Leg
	DrawBone(pJoints, pJointPoints, JointType_HipLeft, JointType_KneeLeft);
	DrawBone(pJoints, pJointPoints, JointType_KneeLeft, JointType_AnkleLeft);
	DrawBone(pJoints, pJointPoints, JointType_AnkleLeft, JointType_FootLeft);

	// Draw the joints
	for (int i = 0; i < JointType_Count; ++i)
	{
		D2D1_ELLIPSE ellipse = D2D1::Ellipse(pJointPoints[i], c_JointThickness, c_JointThickness);

		if (pJoints[i].TrackingState == TrackingState_Inferred)
		{
			m_pRenderTarget->FillEllipse(ellipse, m_pBrushJointInferred);
		}
		else if (pJoints[i].TrackingState == TrackingState_Tracked)
		{
			m_pRenderTarget->FillEllipse(ellipse, m_pBrushJointTracked);
		}
	}

	//SELFMADE CODE
	//simple button
	//D2D_RECT_F measureButton = D2D1::RectF(100, 0, 200, 200);
	//m_pRenderTarget->FillRectangle(measureButton, m_pBrushJointInferred);

	//END SELFMADE
}

/// <summary>
/// Draws one bone of a body (joint to joint)
/// </summary>
/// <param name="pJoints">joint data</param>
/// <param name="pJointPoints">joint positions converted to screen space</param>
/// <param name="pJointPoints">joint positions converted to screen space</param>
/// <param name="joint0">one joint of the bone to draw</param>
/// <param name="joint1">other joint of the bone to draw</param>
void D2D_Graphics::DrawBone(const Joint* pJoints, const D2D1_POINT_2F* pJointPoints, JointType joint0, JointType joint1)
{
	TrackingState joint0State = pJoints[joint0].TrackingState;
	TrackingState joint1State = pJoints[joint1].TrackingState;

	// If we can't find either of these joints, exit
	if ((joint0State == TrackingState_NotTracked) || (joint1State == TrackingState_NotTracked))
	{
		return;
	}

	// Don't draw if both points are inferred
	if ((joint0State == TrackingState_Inferred) && (joint1State == TrackingState_Inferred))
	{
		return;
	}

	// We assume all drawn bones are inferred unless BOTH joints are tracked
	if ((joint0State == TrackingState_Tracked) && (joint1State == TrackingState_Tracked))
	{
		m_pRenderTarget->DrawLine(pJointPoints[joint0], pJointPoints[joint1], m_pBrushBoneTracked, c_TrackedBoneThickness);
	}
	else
	{
		m_pRenderTarget->DrawLine(pJointPoints[joint0], pJointPoints[joint1], m_pBrushBoneInferred, c_InferredBoneThickness);
	}
}

/// <summary>
/// Draws a hand symbol if the hand is tracked: red circle = closed, green circle = opened; blue circle = lasso
/// </summary>
/// <param name="handState">state of the hand</param>
/// <param name="handPosition">position of the hand</param>
void D2D_Graphics::DrawHand(HandState handState, const D2D1_POINT_2F& handPosition)
{
	D2D1_ELLIPSE ellipse = D2D1::Ellipse(handPosition, c_HandSize, c_HandSize);

	switch (handState)
	{
	case HandState_Closed:
		m_pRenderTarget->FillEllipse(ellipse, m_pBrushHandClosed);
		break;

	case HandState_Open:
		m_pRenderTarget->FillEllipse(ellipse, m_pBrushHandOpen);
		break;

	case HandState_Lasso:
		m_pRenderTarget->FillEllipse(ellipse, m_pBrushHandLasso);
		break;
	}
}

void D2D_Graphics::InitD2D()
{
	// Init Direct2D
	D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
}

void D2D_Graphics::CleanD2D()
{
	DiscardDirect2DResources();
	SafeRelease(m_pD2DFactory);
}

//limited to 15 different color
void D2D_Graphics::changeColor(int colorID)
{
	/*
	switch (colorID)
	{
	case 0:
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f, 0.75f, 0.25f), &m_pBrushJointTracked);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 0.0f), &m_pBrushJointInferred);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f, 1.0f, 0.0f), &m_pBrushBoneTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), &m_pBrushBoneInferred);

		break;
	case 1:
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f, 0.75f, 0.25f), &m_pBrushJointTracked);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow, 1.0f), &m_pBrushJointInferred);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green, 1.0f), &m_pBrushBoneTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), &m_pBrushBoneInferred);

		break;
	}
	*/
	if (colorID < 15)
	{
		float c = colorID*0.05; //the change in the color from skelet to skelet

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f + c, 0.75f - c, 0.25f + c), &m_pBrushJointTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f + c, 1.0f - c, 0.0f + c), &m_pBrushBoneTracked);
	}
	else
	{
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f, 0.75f, 0.25f), &m_pBrushJointTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f, 1.0f, 0.0f), &m_pBrushBoneTracked);
	}

}

//SELFMADE FUNCTIONS<commit_msg>graphics?<commit_after>
#include "stdafx.h"
#include "resource.h"

#include "D2D_Graphics.h"

static const float c_JointThickness = 3.0f;
static const float c_TrackedBoneThickness = 6.0f;
static const float c_InferredBoneThickness = 1.0f;
static const float c_HandSize = 30.0f;

D2D_Graphics::D2D_Graphics():

m_pD2DFactory(NULL),
m_pRenderTarget(NULL),
m_pBrushJointTracked(NULL),
m_pBrushJointInferred(NULL),
m_pBrushBoneTracked(NULL),
m_pBrushBoneInferred(NULL),
m_pBrushHandClosed(NULL),
m_pBrushHandOpen(NULL),
m_pBrushHandLasso(NULL)

{

}

D2D_Graphics::~D2D_Graphics()
{
}

ID2D1HwndRenderTarget * D2D_Graphics::GetRenderTarget()
{
	return m_pRenderTarget;
}

void D2D_Graphics::SetRenderTarget(ID2D1HwndRenderTarget * renderTarget)
{
	m_pRenderTarget = renderTarget;
}

/// <summary>
/// Ensure necessary Direct2d resources are created
/// </summary>
/// <returns>S_OK if successful, otherwise an error code</returns>
HRESULT D2D_Graphics::EnsureDirect2DResources(HWND m_hWnd)
{
	HRESULT hr = S_OK;

	if (m_pD2DFactory && !m_pRenderTarget)
	{
		RECT rc;
		GetWindowRect(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), &rc);

		int width = rc.right - rc.left;
		int height = rc.bottom - rc.top;
		D2D1_SIZE_U size = D2D1::SizeU(width, height);
		D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties();
		rtProps.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
		rtProps.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;

		// Create a Hwnd render target, in order to render to the window set in initialize
		hr = m_pD2DFactory->CreateHwndRenderTarget(
			rtProps,
			D2D1::HwndRenderTargetProperties(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), size),
			&m_pRenderTarget
		);

		if (FAILED(hr))
		{
			//SetStatusMessage(L"Couldn't create Direct2D render target!", 10000, true);
			return hr;
		}

		// light green
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.27f, 0.75f, 0.27f), &m_pBrushJointTracked);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow, 1.0f), &m_pBrushJointInferred);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green, 1.0f), &m_pBrushBoneTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), &m_pBrushBoneInferred);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red, 0.5f), &m_pBrushHandClosed);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green, 0.5f), &m_pBrushHandOpen);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Blue, 0.5f), &m_pBrushHandLasso);
	}

	return hr;
}

/// <summary>
/// Dispose Direct2d resources
/// </summary>
void D2D_Graphics::DiscardDirect2DResources()
{
	SafeRelease(m_pRenderTarget);

	SafeRelease(m_pBrushJointTracked);
	SafeRelease(m_pBrushJointInferred);
	SafeRelease(m_pBrushBoneTracked);
	SafeRelease(m_pBrushBoneInferred);

	SafeRelease(m_pBrushHandClosed);
	SafeRelease(m_pBrushHandOpen);
	SafeRelease(m_pBrushHandLasso);
}

/// <summary>
/// Converts a body point to screen space
/// </summary>
/// <param name="bodyPoint">body point to tranform</param>
/// <param name="width">width (in pixels) of output buffer</param>
/// <param name="height">height (in pixels) of output buffer</param>
/// <returns>point in screen-space</returns>
D2D1_POINT_2F D2D_Graphics::BodyToScreen(const CameraSpacePoint& bodyPoint, int width, int height, ICoordinateMapper* m_pCoordinateMapper, int cDepthWidth, int cDepthHeight)
{
	// Calculate the body's position on the screen
	DepthSpacePoint depthPoint = { 0 };
	m_pCoordinateMapper->MapCameraPointToDepthSpace(bodyPoint, &depthPoint);

	float screenPointX = static_cast<float>(depthPoint.X * width) / cDepthWidth;
	float screenPointY = static_cast<float>(depthPoint.Y * height) / cDepthHeight;

	return D2D1::Point2F(screenPointX, screenPointY);
}

/// <summary>
/// Draws a body
/// </summary>
/// <param name="pJoints">joint data</param>
/// <param name="pJointPoints">joint positions converted to screen space</param>
void D2D_Graphics::DrawBody(const Joint* pJoints, const D2D1_POINT_2F* pJointPoints, const int colorID)
{
	// Draw the bones

	changeColor(colorID);

	// Torso
	DrawBone(pJoints, pJointPoints, JointType_Head, JointType_Neck);
	DrawBone(pJoints, pJointPoints, JointType_Neck, JointType_SpineShoulder);
	DrawBone(pJoints, pJointPoints, JointType_SpineShoulder, JointType_SpineMid);
	DrawBone(pJoints, pJointPoints, JointType_SpineMid, JointType_SpineBase);
	DrawBone(pJoints, pJointPoints, JointType_SpineShoulder, JointType_ShoulderRight);
	DrawBone(pJoints, pJointPoints, JointType_SpineShoulder, JointType_ShoulderLeft);
	DrawBone(pJoints, pJointPoints, JointType_SpineBase, JointType_HipRight);
	DrawBone(pJoints, pJointPoints, JointType_SpineBase, JointType_HipLeft);

	// Right Arm
	DrawBone(pJoints, pJointPoints, JointType_ShoulderRight, JointType_ElbowRight);
	DrawBone(pJoints, pJointPoints, JointType_ElbowRight, JointType_WristRight);
	DrawBone(pJoints, pJointPoints, JointType_WristRight, JointType_HandRight);
	DrawBone(pJoints, pJointPoints, JointType_HandRight, JointType_HandTipRight);
	DrawBone(pJoints, pJointPoints, JointType_WristRight, JointType_ThumbRight);

	// Left Arm
	DrawBone(pJoints, pJointPoints, JointType_ShoulderLeft, JointType_ElbowLeft);
	DrawBone(pJoints, pJointPoints, JointType_ElbowLeft, JointType_WristLeft);
	DrawBone(pJoints, pJointPoints, JointType_WristLeft, JointType_HandLeft);
	DrawBone(pJoints, pJointPoints, JointType_HandLeft, JointType_HandTipLeft);
	DrawBone(pJoints, pJointPoints, JointType_WristLeft, JointType_ThumbLeft);

	// Right Leg
	DrawBone(pJoints, pJointPoints, JointType_HipRight, JointType_KneeRight);
	DrawBone(pJoints, pJointPoints, JointType_KneeRight, JointType_AnkleRight);
	DrawBone(pJoints, pJointPoints, JointType_AnkleRight, JointType_FootRight);

	// Left Leg
	DrawBone(pJoints, pJointPoints, JointType_HipLeft, JointType_KneeLeft);
	DrawBone(pJoints, pJointPoints, JointType_KneeLeft, JointType_AnkleLeft);
	DrawBone(pJoints, pJointPoints, JointType_AnkleLeft, JointType_FootLeft);

	// Draw the joints
	for (int i = 0; i < JointType_Count; ++i)
	{
		D2D1_ELLIPSE ellipse = D2D1::Ellipse(pJointPoints[i], c_JointThickness, c_JointThickness);

		if (pJoints[i].TrackingState == TrackingState_Inferred)
		{
			m_pRenderTarget->FillEllipse(ellipse, m_pBrushJointInferred);
		}
		else if (pJoints[i].TrackingState == TrackingState_Tracked)
		{
			m_pRenderTarget->FillEllipse(ellipse, m_pBrushJointTracked);
		}
	}

	//SELFMADE CODE
	//simple button
	//D2D_RECT_F measureButton = D2D1::RectF(1000, 1000, 1200, 1200);
	D2D_RECT_F up = D2D1::RectF(100, 550, 150, 600);
	D2D_RECT_F  = D2D1::RectF(50, 600, 100, 650);
	D2D_RECT_F up = D2D1::RectF(100, 550, 150, 600);
	D2D_RECT_F up = D2D1::RectF(100, 550, 150, 600);

	m_pRenderTarget->FillRectangle(measureButton, m_pBrushJointInferred);

	//END SELFMADE
}

/// <summary>
/// Draws one bone of a body (joint to joint)
/// </summary>
/// <param name="pJoints">joint data</param>
/// <param name="pJointPoints">joint positions converted to screen space</param>
/// <param name="pJointPoints">joint positions converted to screen space</param>
/// <param name="joint0">one joint of the bone to draw</param>
/// <param name="joint1">other joint of the bone to draw</param>
void D2D_Graphics::DrawBone(const Joint* pJoints, const D2D1_POINT_2F* pJointPoints, JointType joint0, JointType joint1)
{
	TrackingState joint0State = pJoints[joint0].TrackingState;
	TrackingState joint1State = pJoints[joint1].TrackingState;

	// If we can't find either of these joints, exit
	if ((joint0State == TrackingState_NotTracked) || (joint1State == TrackingState_NotTracked))
	{
		return;
	}

	// Don't draw if both points are inferred
	if ((joint0State == TrackingState_Inferred) && (joint1State == TrackingState_Inferred))
	{
		return;
	}

	// We assume all drawn bones are inferred unless BOTH joints are tracked
	if ((joint0State == TrackingState_Tracked) && (joint1State == TrackingState_Tracked))
	{
		m_pRenderTarget->DrawLine(pJointPoints[joint0], pJointPoints[joint1], m_pBrushBoneTracked, c_TrackedBoneThickness);
	}
	else
	{
		m_pRenderTarget->DrawLine(pJointPoints[joint0], pJointPoints[joint1], m_pBrushBoneInferred, c_InferredBoneThickness);
	}
}

/// <summary>
/// Draws a hand symbol if the hand is tracked: red circle = closed, green circle = opened; blue circle = lasso
/// </summary>
/// <param name="handState">state of the hand</param>
/// <param name="handPosition">position of the hand</param>
void D2D_Graphics::DrawHand(HandState handState, const D2D1_POINT_2F& handPosition)
{
	D2D1_ELLIPSE ellipse = D2D1::Ellipse(handPosition, c_HandSize, c_HandSize);

	switch (handState)
	{
	case HandState_Closed:
		m_pRenderTarget->FillEllipse(ellipse, m_pBrushHandClosed);
		break;

	case HandState_Open:
		m_pRenderTarget->FillEllipse(ellipse, m_pBrushHandOpen);
		break;

	case HandState_Lasso:
		m_pRenderTarget->FillEllipse(ellipse, m_pBrushHandLasso);
		break;
	}
}

void D2D_Graphics::InitD2D()
{
	// Init Direct2D
	D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
}

void D2D_Graphics::CleanD2D()
{
	DiscardDirect2DResources();
	SafeRelease(m_pD2DFactory);
}

//limited to 15 different color
void D2D_Graphics::changeColor(int colorID)
{
	/*
	switch (colorID)
	{
	case 0:
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f, 0.75f, 0.25f), &m_pBrushJointTracked);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 0.0f), &m_pBrushJointInferred);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f, 1.0f, 0.0f), &m_pBrushBoneTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), &m_pBrushBoneInferred);

		break;
	case 1:
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f, 0.75f, 0.25f), &m_pBrushJointTracked);

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow, 1.0f), &m_pBrushJointInferred);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green, 1.0f), &m_pBrushBoneTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), &m_pBrushBoneInferred);

		break;
	}
	*/
	if (colorID < 15)
	{
		float c = colorID*0.05; //the change in the color from skelet to skelet

		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f + c, 0.75f - c, 0.25f + c), &m_pBrushJointTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f + c, 1.0f - c, 0.0f + c), &m_pBrushBoneTracked);
	}
	else
	{
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.25f, 0.75f, 0.25f), &m_pBrushJointTracked);
		m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0.0f, 1.0f, 0.0f), &m_pBrushBoneTracked);
	}

}

//SELFMADE FUNCTIONS<|endoftext|>


<commit_before>/*
 * DesktopMainWindow.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopMainWindow.hpp"

#include <algorithm>

#include <QtGui>
#include <QtWebKit>
#include <QToolBar>
#include <QWebFrame>

#include <boost/bind.hpp>
#include <boost/format.hpp>

#include <core/FilePath.hpp>
#include <core/system/System.hpp>

#include "DesktopGwtCallback.hpp"
#include "DesktopMenuCallback.hpp"
#include "DesktopWebView.hpp"
#include "DesktopOptions.hpp"
#include "DesktopSlotBinders.hpp"
#include "DesktopUtils.hpp"
#include "DesktopSessionLauncher.hpp"

using namespace rstudio::core;

namespace rstudio {
namespace desktop {

MainWindow::MainWindow(QUrl url) :
      GwtWindow(false, false, QString(), url, NULL),
      menuCallback_(this),
      gwtCallback_(this, this),
      pSessionLauncher_(NULL),
      pCurrentSessionProcess_(NULL)
{
   quitConfirmed_ = false;
   pToolbar_->setVisible(false);

   // Dummy menu bar to deal with the fact that
   // the real menu bar isn't ready until well
   // after startup.
   QMenuBar* pMainMenuStub = new QMenuBar(this);
   pMainMenuStub->addMenu(QString::fromUtf8("File"));
   pMainMenuStub->addMenu(QString::fromUtf8("Edit"));
   pMainMenuStub->addMenu(QString::fromUtf8("Code"));
   pMainMenuStub->addMenu(QString::fromUtf8("View"));
   pMainMenuStub->addMenu(QString::fromUtf8("Plots"));
   pMainMenuStub->addMenu(QString::fromUtf8("Session"));
   pMainMenuStub->addMenu(QString::fromUtf8("Build"));
   pMainMenuStub->addMenu(QString::fromUtf8("Debug"));
   pMainMenuStub->addMenu(QString::fromUtf8("Profile"));
   pMainMenuStub->addMenu(QString::fromUtf8("Tools"));
   pMainMenuStub->addMenu(QString::fromUtf8("Help"));
   setMenuBar(pMainMenuStub);

   connect(&menuCallback_, SIGNAL(menuBarCompleted(QMenuBar*)),
           this, SLOT(setMenuBar(QMenuBar*)));
   connect(&menuCallback_, SIGNAL(commandInvoked(QString)),
           this, SLOT(invokeCommand(QString)));
   connect(&menuCallback_, SIGNAL(manageCommand(QString,QAction*)),
           this, SLOT(manageCommand(QString,QAction*)));
   connect(&menuCallback_, SIGNAL(manageCommandVisibility(QString,QAction*)),
           this, SLOT(manageCommandVisibility(QString,QAction*)));

   connect(&menuCallback_, SIGNAL(zoomIn()), this, SLOT(zoomIn()));
   connect(&menuCallback_, SIGNAL(zoomOut()), this, SLOT(zoomOut()));

   connect(&gwtCallback_, SIGNAL(workbenchInitialized()),
           this, SIGNAL(firstWorkbenchInitialized()));
   connect(&gwtCallback_, SIGNAL(workbenchInitialized()),
           this, SLOT(onWorkbenchInitialized()));

   connect(webView(), SIGNAL(onCloseWindowShortcut()),
           this, SLOT(onCloseWindowShortcut()));

   connect(qApp, SIGNAL(commitDataRequest(QSessionManager&)),
           this, SLOT(commitDataRequest(QSessionManager&)),
           Qt::DirectConnection);

   setWindowIcon(QIcon(QString::fromUtf8(":/icons/RStudio.ico")));

   setWindowTitle(QString::fromUtf8("RStudio"));

#ifdef Q_OS_MAC
   QMenuBar* pDefaultMenu = new QMenuBar();
   pDefaultMenu->addMenu(new WindowMenu());
#endif

   desktop::enableFullscreenMode(this, true);

   //setContentsMargins(10000, 0, -10000, 0);
   setStyleSheet(QString::fromUtf8("QMainWindow { background: #e1e2e5; }"));
}

QString MainWindow::getSumatraPdfExePath()
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   QString sumatraPath = pMainFrame->evaluateJavaScript(QString::fromUtf8(
                    "window.desktopHooks.getSumatraPdfExePath()")).toString();
   return sumatraPath;
}

void MainWindow::launchSession(bool reload)
{
   Error error = pSessionLauncher_->launchNextSession(reload);
   if (error)
   {
      LOG_ERROR(error);

      showMessageBox(QMessageBox::Critical,
                     this,
                     QString::fromUtf8("RStudio"),
                     QString::fromUtf8("The R session failed to start."));

      quit();
   }
}

void MainWindow::onCloseWindowShortcut()
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();

   bool closeSourceDocEnabled = pMainFrame->evaluateJavaScript(
      QString::fromUtf8(
         "window.desktopHooks.isCommandEnabled('closeSourceDoc')")).toBool();

   if (!closeSourceDocEnabled)
      close();
}

void MainWindow::onWorkbenchInitialized()
{
   //QTimer::singleShot(300, this, SLOT(resetMargins()));

   // reset state (in case this occurred in response to a manual reload
   // or reload for a new project context)
   quitConfirmed_ = false;

   // see if there is a project dir to display in the titlebar
   // if there are unsaved changes then resolve them before exiting
   QVariant vProjectDir = webView()->page()->mainFrame()->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.getActiveProjectDir()"));
   QString projectDir = vProjectDir.toString();
   if (projectDir.length() > 0)
      setWindowTitle(projectDir + QString::fromUtf8(" - RStudio"));
   else
      setWindowTitle(QString::fromUtf8("RStudio"));

   avoidMoveCursorIfNecessary();
}

void MainWindow::resetMargins()
{
   setContentsMargins(0, 0, 0, 0);
}

// this notification occurs when windows or X11 is shutting
// down -- in this case we want to be a good citizen and just
// exit right away so we notify the gwt callback that a legit
// quit and exit is on the way and we set the quitConfirmed_
// flag so no prompting occurs (note that source documents
// have already been auto-saved so will be restored next time
// the current project context is opened)
void MainWindow::commitDataRequest(QSessionManager &manager)
{
   gwtCallback_.setPendingQuit(PendingQuitAndExit);
   quitConfirmed_ = true;
}

void MainWindow::loadUrl(const QUrl& url)
{
   webView()->setBaseUrl(url);
   webView()->load(url);
}

void MainWindow::quit()
{
   quitConfirmed_ = true;
   close();
}

void MainWindow::onJavaScriptWindowObjectCleared()
{
   GwtWindow::onJavaScriptWindowObjectCleared();

   webView()->page()->mainFrame()->addToJavaScriptWindowObject(
         QString::fromUtf8("desktop"),
         &gwtCallback_,
         QWebFrame::QtOwnership);
   webView()->page()->mainFrame()->addToJavaScriptWindowObject(
         QString::fromUtf8("desktopMenuCallback"),
         &menuCallback_,
         QWebFrame::QtOwnership);
}

void MainWindow::invokeCommand(QString commandId)
{
   webView()->page()->mainFrame()->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.invokeCommand('") + commandId + QString::fromUtf8("');"));
}

void MainWindow::manageCommand(QString cmdId, QAction* action)
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   action->setVisible(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandVisible('") + cmdId + QString::fromUtf8("')")).toBool());
   action->setEnabled(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandEnabled('") + cmdId + QString::fromUtf8("')")).toBool());
   action->setText(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.getCommandLabel('") + cmdId + QString::fromUtf8("')")).toString());
   if (action->isCheckable())
   {
      action->setChecked(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandChecked('") + cmdId + QString::fromUtf8("')")).toBool());
   }
}

// a faster version of the above that just checks and sets the command's
// visibility state (to trigger visibility of menus containing the command)
void MainWindow::manageCommandVisibility(QString cmdId, QAction* action)
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   action->setVisible(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandVisible('") + cmdId + QString::fromUtf8("')")).toBool());
}

void MainWindow::evaluateJavaScript(QString jsCode)
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   pMainFrame->evaluateJavaScript(jsCode);
}

void MainWindow::closeEvent(QCloseEvent* pEvent)
{
   QWebFrame* pFrame = webView()->page()->mainFrame();
   if (!pFrame)
   {
       pEvent->accept();
       return;
   }

   QVariant hasQuitR = pFrame->evaluateJavaScript(QString::fromUtf8("!!window.desktopHooks"));

   if (quitConfirmed_
       || !hasQuitR.toBool()
       || pCurrentSessionProcess_ == NULL
       || pCurrentSessionProcess_->state() != QProcess::Running)
   {
      pEvent->accept();
   }
   else
   {
      pFrame->evaluateJavaScript(QString::fromUtf8("window.desktopHooks.quitR()"));
      pEvent->ignore();
   }
}

double MainWindow::getZoomLevel()
{
   return options().zoomLevel();
}

void MainWindow::setZoomLevel(double zoomLevel)
{
   options().setZoomLevel(zoomLevel);
}

void MainWindow::setMenuBar(QMenuBar *pMenubar)
{
   delete menuBar();
   this->QMainWindow::setMenuBar(pMenubar);
}

void MainWindow::openFileInRStudio(QString path)
{
   QFileInfo fileInfo(path);
   if (!fileInfo.isAbsolute() || !fileInfo.exists() || !fileInfo.isFile())
      return;

   path = path.replace(QString::fromUtf8("\\"), QString::fromUtf8("\\\\"))
          .replace(QString::fromUtf8("\""), QString::fromUtf8("\\\""))
          .replace(QString::fromUtf8("\n"), QString::fromUtf8("\\n"));

   webView()->page()->mainFrame()->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.openFile(\"") + path + QString::fromUtf8("\")"));
}

void MainWindow::onPdfViewerClosed(QString pdfPath)
{
   webView()->page()->mainFrame()->evaluateJavaScript(
            QString::fromUtf8("window.synctexNotifyPdfViewerClosed(\"") +
                                         pdfPath + QString::fromUtf8("\")"));
}

void MainWindow::onPdfViewerSyncSource(QString srcFile, int line, int column)
{
   boost::format fmt("window.desktopSynctexInverseSearch(\"%1%\", %2%, %3%)");
   std::string js = boost::str(fmt % srcFile.toStdString() % line % column);

   webView()->page()->mainFrame()->evaluateJavaScript(
                                                   QString::fromStdString(js));
}

// private interface for SessionLauncher

void MainWindow::setSessionLauncher(SessionLauncher* pSessionLauncher)
{
   pSessionLauncher_ = pSessionLauncher;
}

void MainWindow::setSessionProcess(QProcess* pSessionProcess)
{
   pCurrentSessionProcess_ = pSessionProcess;
}

// allow SessionLauncher to collect restart requests from GwtCallback
int MainWindow::collectPendingQuitRequest()
{
   return gwtCallback_.collectPendingQuitRequest();
}

bool MainWindow::desktopHooksAvailable()
{
   return webView()->page()->mainFrame()->evaluateJavaScript(
                        QString::fromUtf8("!!window.desktopHooks")).toBool();
}

void MainWindow::onActivated()
{
   if (desktopHooksAvailable())
      invokeCommand(QString::fromUtf8("vcsRefreshNoError"));
}

} // namespace desktop
} // namespace rstudio
<commit_msg>Fixed contrast for light-on-dark color themes<commit_after>/*
 * DesktopMainWindow.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopMainWindow.hpp"

#include <algorithm>

#include <QtGui>
#include <QtWebKit>
#include <QToolBar>
#include <QWebFrame>

#include <boost/bind.hpp>
#include <boost/format.hpp>

#include <core/FilePath.hpp>
#include <core/system/System.hpp>

#include "DesktopGwtCallback.hpp"
#include "DesktopMenuCallback.hpp"
#include "DesktopWebView.hpp"
#include "DesktopOptions.hpp"
#include "DesktopSlotBinders.hpp"
#include "DesktopUtils.hpp"
#include "DesktopSessionLauncher.hpp"

using namespace rstudio::core;

namespace rstudio {
namespace desktop {

MainWindow::MainWindow(QUrl url) :
      GwtWindow(false, false, QString(), url, NULL),
      menuCallback_(this),
      gwtCallback_(this, this),
      pSessionLauncher_(NULL),
      pCurrentSessionProcess_(NULL)
{
   quitConfirmed_ = false;
   pToolbar_->setVisible(false);

   // Dummy menu bar to deal with the fact that
   // the real menu bar isn't ready until well
   // after startup.
   QMenuBar* pMainMenuStub = new QMenuBar(this);
   pMainMenuStub->addMenu(QString::fromUtf8("File"));
   pMainMenuStub->addMenu(QString::fromUtf8("Edit"));
   pMainMenuStub->addMenu(QString::fromUtf8("Code"));
   pMainMenuStub->addMenu(QString::fromUtf8("View"));
   pMainMenuStub->addMenu(QString::fromUtf8("Plots"));
   pMainMenuStub->addMenu(QString::fromUtf8("Session"));
   pMainMenuStub->addMenu(QString::fromUtf8("Build"));
   pMainMenuStub->addMenu(QString::fromUtf8("Debug"));
   pMainMenuStub->addMenu(QString::fromUtf8("Profile"));
   pMainMenuStub->addMenu(QString::fromUtf8("Tools"));
   pMainMenuStub->addMenu(QString::fromUtf8("Help"));
   setMenuBar(pMainMenuStub);

   connect(&menuCallback_, SIGNAL(menuBarCompleted(QMenuBar*)),
           this, SLOT(setMenuBar(QMenuBar*)));
   connect(&menuCallback_, SIGNAL(commandInvoked(QString)),
           this, SLOT(invokeCommand(QString)));
   connect(&menuCallback_, SIGNAL(manageCommand(QString,QAction*)),
           this, SLOT(manageCommand(QString,QAction*)));
   connect(&menuCallback_, SIGNAL(manageCommandVisibility(QString,QAction*)),
           this, SLOT(manageCommandVisibility(QString,QAction*)));

   connect(&menuCallback_, SIGNAL(zoomIn()), this, SLOT(zoomIn()));
   connect(&menuCallback_, SIGNAL(zoomOut()), this, SLOT(zoomOut()));

   connect(&gwtCallback_, SIGNAL(workbenchInitialized()),
           this, SIGNAL(firstWorkbenchInitialized()));
   connect(&gwtCallback_, SIGNAL(workbenchInitialized()),
           this, SLOT(onWorkbenchInitialized()));

   connect(webView(), SIGNAL(onCloseWindowShortcut()),
           this, SLOT(onCloseWindowShortcut()));

   connect(qApp, SIGNAL(commitDataRequest(QSessionManager&)),
           this, SLOT(commitDataRequest(QSessionManager&)),
           Qt::DirectConnection);

   setWindowIcon(QIcon(QString::fromUtf8(":/icons/RStudio.ico")));

   setWindowTitle(QString::fromUtf8("RStudio"));

#ifdef Q_OS_MAC
   QMenuBar* pDefaultMenu = new QMenuBar();
   pDefaultMenu->addMenu(new WindowMenu());
#endif

   desktop::enableFullscreenMode(this, true);

   //setContentsMargins(10000, 0, -10000, 0);
   setStyleSheet(QString::fromUtf8("QMainWindow { background: #e1e2e5; } QMenuBar { color: #000000; }"));
}

QString MainWindow::getSumatraPdfExePath()
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   QString sumatraPath = pMainFrame->evaluateJavaScript(QString::fromUtf8(
                    "window.desktopHooks.getSumatraPdfExePath()")).toString();
   return sumatraPath;
}

void MainWindow::launchSession(bool reload)
{
   Error error = pSessionLauncher_->launchNextSession(reload);
   if (error)
   {
      LOG_ERROR(error);

      showMessageBox(QMessageBox::Critical,
                     this,
                     QString::fromUtf8("RStudio"),
                     QString::fromUtf8("The R session failed to start."));

      quit();
   }
}

void MainWindow::onCloseWindowShortcut()
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();

   bool closeSourceDocEnabled = pMainFrame->evaluateJavaScript(
      QString::fromUtf8(
         "window.desktopHooks.isCommandEnabled('closeSourceDoc')")).toBool();

   if (!closeSourceDocEnabled)
      close();
}

void MainWindow::onWorkbenchInitialized()
{
   //QTimer::singleShot(300, this, SLOT(resetMargins()));

   // reset state (in case this occurred in response to a manual reload
   // or reload for a new project context)
   quitConfirmed_ = false;

   // see if there is a project dir to display in the titlebar
   // if there are unsaved changes then resolve them before exiting
   QVariant vProjectDir = webView()->page()->mainFrame()->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.getActiveProjectDir()"));
   QString projectDir = vProjectDir.toString();
   if (projectDir.length() > 0)
      setWindowTitle(projectDir + QString::fromUtf8(" - RStudio"));
   else
      setWindowTitle(QString::fromUtf8("RStudio"));

   avoidMoveCursorIfNecessary();
}

void MainWindow::resetMargins()
{
   setContentsMargins(0, 0, 0, 0);
}

// this notification occurs when windows or X11 is shutting
// down -- in this case we want to be a good citizen and just
// exit right away so we notify the gwt callback that a legit
// quit and exit is on the way and we set the quitConfirmed_
// flag so no prompting occurs (note that source documents
// have already been auto-saved so will be restored next time
// the current project context is opened)
void MainWindow::commitDataRequest(QSessionManager &manager)
{
   gwtCallback_.setPendingQuit(PendingQuitAndExit);
   quitConfirmed_ = true;
}

void MainWindow::loadUrl(const QUrl& url)
{
   webView()->setBaseUrl(url);
   webView()->load(url);
}

void MainWindow::quit()
{
   quitConfirmed_ = true;
   close();
}

void MainWindow::onJavaScriptWindowObjectCleared()
{
   GwtWindow::onJavaScriptWindowObjectCleared();

   webView()->page()->mainFrame()->addToJavaScriptWindowObject(
         QString::fromUtf8("desktop"),
         &gwtCallback_,
         QWebFrame::QtOwnership);
   webView()->page()->mainFrame()->addToJavaScriptWindowObject(
         QString::fromUtf8("desktopMenuCallback"),
         &menuCallback_,
         QWebFrame::QtOwnership);
}

void MainWindow::invokeCommand(QString commandId)
{
   webView()->page()->mainFrame()->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.invokeCommand('") + commandId + QString::fromUtf8("');"));
}

void MainWindow::manageCommand(QString cmdId, QAction* action)
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   action->setVisible(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandVisible('") + cmdId + QString::fromUtf8("')")).toBool());
   action->setEnabled(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandEnabled('") + cmdId + QString::fromUtf8("')")).toBool());
   action->setText(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.getCommandLabel('") + cmdId + QString::fromUtf8("')")).toString());
   if (action->isCheckable())
   {
      action->setChecked(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandChecked('") + cmdId + QString::fromUtf8("')")).toBool());
   }
}

// a faster version of the above that just checks and sets the command's
// visibility state (to trigger visibility of menus containing the command)
void MainWindow::manageCommandVisibility(QString cmdId, QAction* action)
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   action->setVisible(pMainFrame->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.isCommandVisible('") + cmdId + QString::fromUtf8("')")).toBool());
}

void MainWindow::evaluateJavaScript(QString jsCode)
{
   QWebFrame* pMainFrame = webView()->page()->mainFrame();
   pMainFrame->evaluateJavaScript(jsCode);
}

void MainWindow::closeEvent(QCloseEvent* pEvent)
{
   QWebFrame* pFrame = webView()->page()->mainFrame();
   if (!pFrame)
   {
       pEvent->accept();
       return;
   }

   QVariant hasQuitR = pFrame->evaluateJavaScript(QString::fromUtf8("!!window.desktopHooks"));

   if (quitConfirmed_
       || !hasQuitR.toBool()
       || pCurrentSessionProcess_ == NULL
       || pCurrentSessionProcess_->state() != QProcess::Running)
   {
      pEvent->accept();
   }
   else
   {
      pFrame->evaluateJavaScript(QString::fromUtf8("window.desktopHooks.quitR()"));
      pEvent->ignore();
   }
}

double MainWindow::getZoomLevel()
{
   return options().zoomLevel();
}

void MainWindow::setZoomLevel(double zoomLevel)
{
   options().setZoomLevel(zoomLevel);
}

void MainWindow::setMenuBar(QMenuBar *pMenubar)
{
   delete menuBar();
   this->QMainWindow::setMenuBar(pMenubar);
}

void MainWindow::openFileInRStudio(QString path)
{
   QFileInfo fileInfo(path);
   if (!fileInfo.isAbsolute() || !fileInfo.exists() || !fileInfo.isFile())
      return;

   path = path.replace(QString::fromUtf8("\\"), QString::fromUtf8("\\\\"))
          .replace(QString::fromUtf8("\""), QString::fromUtf8("\\\""))
          .replace(QString::fromUtf8("\n"), QString::fromUtf8("\\n"));

   webView()->page()->mainFrame()->evaluateJavaScript(
         QString::fromUtf8("window.desktopHooks.openFile(\"") + path + QString::fromUtf8("\")"));
}

void MainWindow::onPdfViewerClosed(QString pdfPath)
{
   webView()->page()->mainFrame()->evaluateJavaScript(
            QString::fromUtf8("window.synctexNotifyPdfViewerClosed(\"") +
                                         pdfPath + QString::fromUtf8("\")"));
}

void MainWindow::onPdfViewerSyncSource(QString srcFile, int line, int column)
{
   boost::format fmt("window.desktopSynctexInverseSearch(\"%1%\", %2%, %3%)");
   std::string js = boost::str(fmt % srcFile.toStdString() % line % column);

   webView()->page()->mainFrame()->evaluateJavaScript(
                                                   QString::fromStdString(js));
}

// private interface for SessionLauncher

void MainWindow::setSessionLauncher(SessionLauncher* pSessionLauncher)
{
   pSessionLauncher_ = pSessionLauncher;
}

void MainWindow::setSessionProcess(QProcess* pSessionProcess)
{
   pCurrentSessionProcess_ = pSessionProcess;
}

// allow SessionLauncher to collect restart requests from GwtCallback
int MainWindow::collectPendingQuitRequest()
{
   return gwtCallback_.collectPendingQuitRequest();
}

bool MainWindow::desktopHooksAvailable()
{
   return webView()->page()->mainFrame()->evaluateJavaScript(
                        QString::fromUtf8("!!window.desktopHooks")).toBool();
}

void MainWindow::onActivated()
{
   if (desktopHooksAvailable())
      invokeCommand(QString::fromUtf8("vcsRefreshNoError"));
}

} // namespace desktop
} // namespace rstudio
<|endoftext|>


<commit_before>#ifndef BOOST_CLBL_TRTS_DETAIL_FORWARD_DECLARATIONS
#define BOOST_CLBL_TRTS_DETAIL_FORWARD_DECLARATIONS
#include <boost/callable_traits/detail/config.hpp>
#include <boost/callable_traits/detail/default_callable_traits.hpp>

namespace boost { namespace callable_traits { namespace detail {

template<typename T>
struct function;

template<typename T>
struct has_normal_call_operator
{
    template<typename N, N Value>
    struct check { check(std::nullptr_t) {} };

    template<typename U>
    static std::int8_t test(
        check<decltype(&U::operator()), &U::operator()>);

    template<typename>
    static std::int16_t test(...);

    static constexpr bool value =
        sizeof(test<T>(nullptr)) == sizeof(std::int8_t);
};

struct callable_dummy {
    void operator()() {}
};

template<typename T>
using default_to_function_object = typename std::conditional<
    has_normal_call_operator<T>::value,
    T, callable_dummy>::type;

template<typename T>
struct pmf;

template<typename T>
struct pmd;

template<typename F, typename T = typename std::remove_reference<F>::type>
using function_object_base = typename std::conditional<
    has_normal_call_operator<T>::value,
    pmf<decltype(&default_to_function_object<T>::operator())>,
    default_callable_traits<T>>::type;

template<typename T, typename Base = function_object_base<T>>
struct function_object;

}}} // namespace boost::callable_traits::detail

#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_FORWARD_DECLARATIONS
<commit_msg>Delete forward_declarations.hpp<commit_after><|endoftext|>


<commit_before>
#include "function.h"
#include "value.h"

using namespace v8;

namespace GINode {

static Handle<Value> FunctionInvoker(const Arguments &args) {
    HandleScope scope;
    GIBaseInfo *info = (GIBaseInfo *) External::Unwrap (args.Data ());
    GIFunctionInfo *function_info = (GIFunctionInfo *) info;
    GError *error = NULL;

    /* XXX: For now, only work on functions without any OUT args at all.
     * Just assume everything is an in arg. */
    int n_in_args = g_callable_info_get_n_args ((GICallableInfo *) info);
    GIArgument in_args[n_in_args];

    if (args.Length() < n_in_args) {
        ThrowException (Exception::TypeError (String::New ("Not enough arguments.")));
        return scope.Close (Undefined ());
    }

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        V8ToGIArgument (&type_info, &in_args[i], args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    GIArgument return_value;
    g_function_info_invoke (function_info,
                            in_args, n_in_args,
                            NULL, 0,
                            &return_value,
                            &error);

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        FreeGIArgument (&type_info, &in_args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    if (error) {
        ThrowException (Exception::TypeError (String::New (error->message)));
        return scope.Close (Undefined ());
    }

    GITypeInfo return_value_type;
    g_callable_info_load_return_type ((GICallableInfo *) info, &return_value_type);
    return scope.Close (GIArgumentToV8 (&return_value_type, &return_value));
}

static void FunctionDestroyed (Persistent<Value> object, void *data) {
    GIBaseInfo *info = (GIBaseInfo *) data;
    g_base_info_unref (info);
}

Handle<Function> MakeFunction(GIBaseInfo *info) {
    HandleScope scope;

    Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New (FunctionInvoker));
    tpl.MakeWeak (g_base_info_ref (info), FunctionDestroyed);

    tpl->SetCallHandler (FunctionInvoker, External::New (info));
    Local<Function> fn = tpl->GetFunction ();

    const char *function_name = g_base_info_get_name (info);
    fn->SetName (String::NewSymbol (function_name));

    return scope.Close (fn);
}

};
<commit_msg>function: Clean up a bit<commit_after>
#include "function.h"
#include "value.h"

using namespace v8;

namespace GINode {

static Handle<Value> FunctionInvoker(const Arguments &args) {
    HandleScope scope;
    GIBaseInfo *info = (GIBaseInfo *) External::Unwrap (args.Data ());
    GIFunctionInfo *function_info = (GIFunctionInfo *) info;
    GError *error = NULL;

    /* XXX: For now, only work on functions without any OUT args at all.
     * Just assume everything is an in arg. */
    int n_in_args = g_callable_info_get_n_args ((GICallableInfo *) info);
    GIArgument in_args[n_in_args];

    if (args.Length() < n_in_args) {
        ThrowException (Exception::TypeError (String::New ("Not enough arguments.")));
        return scope.Close (Undefined ());
    }

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        V8ToGIArgument (&type_info, &in_args[i], args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    GIArgument return_value;
    g_function_info_invoke (function_info,
                            in_args, n_in_args,
                            NULL, 0,
                            &return_value,
                            &error);

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        FreeGIArgument (&type_info, &in_args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    if (error) {
        ThrowException (Exception::TypeError (String::New (error->message)));
        return scope.Close (Undefined ());
    }

    GITypeInfo return_value_type;
    g_callable_info_load_return_type ((GICallableInfo *) info, &return_value_type);
    return scope.Close (GIArgumentToV8 (&return_value_type, &return_value));
}

static void FunctionDestroyed (Persistent<Value> object, void *data) {
    GIBaseInfo *info = (GIBaseInfo *) data;
    g_base_info_unref (info);
}

Handle<Function> MakeFunction(GIBaseInfo *info) {
    HandleScope scope;

    Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New (FunctionInvoker, External::New (info)));
    tpl.MakeWeak (g_base_info_ref (info), FunctionDestroyed);
    Local<Function> fn = tpl->GetFunction ();

    const char *function_name = g_base_info_get_name (info);
    fn->SetName (String::NewSymbol (function_name));

    return scope.Close (fn);
}

};
<|endoftext|>


<commit_before><commit_msg>Layout was entirely the wrong place to be updating the button - it gets called too early. This moves it near the other user of the color values.<commit_after><|endoftext|>


<commit_before>#include "Repair.h"
#include "UndoRepair.h"
#include "Partitioning.h"
#include "Util.h"
using namespace std;

/*
We must be able to re-extract for the algorithm to be correct
Associations must be monotonically decreasing for the algorithm to be optimal
*/
bool checkOutput(vector<Association> associations, vector<unsigned> wordIDs)
{
	//Check to see whether it's correct
	vector<unsigned> extractedWordIDs = undoRepair(associations);
	for (size_t i = 0; i < extractedWordIDs.size(); i++)
	{
		//cerr << "Orig: " << wordIDs[i] << ", compare: " << extractedWordIDs[i] << endl;
		if (extractedWordIDs[i] != wordIDs[i])
		{
			return false;
		}
	}

	cerr << "Passed correctness check..." << endl;

	//If it's correct, check to see whether it's optimal
	for (size_t i = 0; i < associations.size() - 1; i++)
	{
		// cerr << "i: " << i << " freq[i]: " << associations[i].freq << ", freq[i+1]: " << associations[i+1].freq << endl;
		// system("pause");
		if (associations[i].freq < associations[i+1].freq)
		{
			return false;
		}
	}

	cerr << "Passed optimal check..." << endl;

	return true;
}

double getScore(unordered_map<string, FragInfo>& uniqueFrags, ostream& os = cerr)
{
	double term;
	double sum(0);
	for (unordered_map<string, FragInfo>::iterator it = uniqueFrags.begin(); it != uniqueFrags.end(); it++)
	{
		term = it->second.count * it->second.fragSize;
		sum += term;
	}
	return sum / uniqueFrags.size();
}

void writeAssociations(const vector<Association>& associations, ostream& os = cerr)
{
	for (size_t i = 0; i < associations.size(); i++)
	{
		os << associations[i];
	}
}

void writeResults(const vector<vector<unsigned> >& versions, unsigned* offsetsAllVersions, unsigned* versionPartitionSizes, const vector<Association>& associations, unordered_map<unsigned, string>& IDsToWords, const string& outFilename, bool printFragments = false, bool printAssociations = false)
{
	ofstream os(outFilename.c_str());

	os << "Results of re-pair partitioning..." << endl << endl;
	os << "*** Fragment boundaries ***" << endl;

	unsigned totalCountFragments(0);
	unsigned diff(0);
	unsigned numVersions = versions.size();
	for (unsigned v = 0; v < numVersions; v++)
	{
		unsigned numFragsInVersion = versionPartitionSizes[v];

		if (numFragsInVersion < 1)
		{
			continue;
		}
		os << "Version " << v << endl;
		for (unsigned i = 0; i < numFragsInVersion - 1; i++)
		{
			if (i < versionPartitionSizes[v] - 1)
			{
				unsigned currOffset = offsetsAllVersions[totalCountFragments + i];
				unsigned nextOffset = offsetsAllVersions[totalCountFragments + i + 1];
				diff = nextOffset - currOffset;
			}
			else
			{
				diff = 0;
			}

			os << "Fragment " << i << ": " << offsetsAllVersions[totalCountFragments + i] << "-" <<
				offsetsAllVersions[totalCountFragments + i + 1] << " (frag size: " << diff << ")" << endl;
		}
		totalCountFragments += numFragsInVersion;
		os << endl;
	}

	// os << "Number of fragment boundaries: " << starts.size() << endl;
	// os << "Number of fragments: " << (starts.size() - 1) << endl << endl;

	vector<vector<FragInfo > > fragmentHashes;
	os << "*** Fragments ***" << endl;
	fragmentHashes = getFragmentHashes(versions, offsetsAllVersions, versionPartitionSizes, IDsToWords, os, printFragments);

	// Assign fragment IDs and stick them in a hashmap
	unordered_map<string, FragInfo> uniqueFrags;
	updateFragmentHashMap(fragmentHashes, uniqueFrags);

	// Now decide on the score for this partitioning
	double score = getScore(uniqueFrags, os);
	os << "Score: " << score << endl;

	if (printAssociations)
	{
		os << "*** Associations (symbol -> pair) ***" << endl;
		writeAssociations(associations, os);
	}
}

void printIDtoWordMapping(unordered_map<unsigned, string>& IDsToWords, ostream& os = cerr)
{
	for (unordered_map<unsigned, string>::iterator it = IDsToWords.begin(); it != IDsToWords.end(); it++)
	{
		os << it->first << ": " << it->second << endl;
	}
}

double runRepairPartitioning(vector<vector<unsigned> > versions, unordered_map<unsigned, string>& IDsToWords,
	unsigned*& offsetsAllVersions, unsigned*& versionPartitionSizes, vector<Association>& associations,
	unsigned minFragSize, unsigned repairStoppingPoint, bool printFragments = false)
{
	//Allocate the heap, hash table, array of associations, and list of pointers to neighbor structures

	RandomHeap myHeap;

	unordered_map<unsigned long long, HashTableEntry*> hashTable = unordered_map<unsigned long long, HashTableEntry*> ();

	associations = vector<Association>();

	vector<VersionDataItem> versionData = vector<VersionDataItem>();

	extractPairs(versions, myHeap, hashTable, versionData);

	int numPairs = hashTable.size();

	doRepair(myHeap, hashTable, associations, repairStoppingPoint, versionData);

	versionPartitionSizes = new unsigned[versions.size()];

	offsetsAllVersions = getPartitioningsAllVersions(myHeap, minFragSize, versionData, versionPartitionSizes);

	if (!offsetsAllVersions)
	{
		// Maybe repairStoppingPoint was too low
		return 0.0;
	}

	vector<vector<FragInfo > > fragmentHashes;
	fragmentHashes = getFragmentHashes(versions, offsetsAllVersions, versionPartitionSizes, IDsToWords, cerr, printFragments);

	// Assign fragment IDs and stick them in a hashmap
	unordered_map<string, FragInfo> uniqueFrags;
	updateFragmentHashMap(fragmentHashes, uniqueFrags);

	// Now decide on the score for this partitioning
	double score = getScore(uniqueFrags, cerr);
	if (printFragments)
		cerr << "Score: " << score << endl;

	return score;

	// stringstream outFilenameStream;
	// outFilenameStream << "Output/results" << stripDot(inputFilepath);
	// string outputFilename = outFilenameStream.str();

	// outputFilename = "Output/results.txt";

	// bool printFragments = true;
	// bool printAssociations = false;
	// writeResults(versions, offsetsAllVersions, versionPartitionSizes, associations, IDsToWords, outputFilename, printFragments, printAssociations);

	// stringstream command;
	// command << "start " << outputFilename.c_str();
	// system(command.str().c_str());

	// stringstream ss;
	// ss << "Filename: " << inputFilepath << endl;
	// ss << "Size: " << fileSize << " bytes" << endl;
	// ss << "Word Count: " << wordIDs.size() << endl;
	// ss << "Unique Pair Count (in original file): " << numPairs << endl;

	// cerr << "Checking output... " << endl;
	// if (checkOutput(associations, wordIDs))
	// 	cerr << "Output ok!";
	// else
	// 	cerr << "Check failed!";
	// cerr << endl;

	// Profiler::getInstance().end("all");
	// Profiler::getInstance().setInputSpec(ss.str());
	// Profiler::getInstance().writeResults("Output/profile-functions.txt");

	// cleanup(hashTable);
	// system("pause");
}

unsigned currentFragID = 0;
unsigned currentID = 0;

int main(int argc, char* argv[])
{
	//createOutputDir();

	//heap, repair
	string test = "repair";

	if (test == "heap")
	{
		RandomHeapTest test = RandomHeapTest(1000);
		exit(0);
	}

	if (test == "repair")
	{
		Profiler::getInstance().start("all");
		string inputFilepath = "./Input/ints/";

		// Default param values
		/*
		Initial test show that minFragSize should be proportional to document size
		*/
		unsigned minFragSize = 2; //in words

		/*
		Initial tests show that repairStoppingPoint shouldn't be too small (repair goes too far for our purposes in this case)
		And it shouldn't be larger than the number of versions (this is trivial, we expect to get repetition
		at most numVersions times for inter-version repetitions)
		*/
		unsigned repairStoppingPoint = 2; //pairs that occur less than this amount of times will not be replaced

		if (argc == 2 && (string) argv[1] == "help")
		{
			cerr << "Usage:" << endl;
			cerr << "\t" << argv[0] << " <directory> <minFragSize> <repairStoppingPoint>" << endl;
			cerr << "\t" << argv[0] << " <directory> <minFragSize>" << endl;
			cerr << "\t" << argv[0] << " <directory>" << endl;
			cerr << "\t" << argv[0] << "" << endl << endl;
			cerr << "Defaults: " << endl;
			cerr << "\tdirectory: " << inputFilepath << endl;
			cerr << "\tminFragSize: " << minFragSize << endl;
			cerr << "\trepairStoppingPoint: " << repairStoppingPoint << endl;
			exit(0);
		}

		if (argc > 1)
			inputFilepath = (string)argv[1];

		if (argc > 2)
			minFragSize = atoi(argv[2]);

		if (argc > 3)
			repairStoppingPoint = atoi(argv[3]);

		vector<string> inputFilenames = vector<string>();
		if (getFileNames(inputFilepath, inputFilenames))
			return errno;

		char* text;

		int fileSize;

		vector<vector<unsigned> > versions = vector<vector<unsigned> >(); //each inner vector is the wordIDs for one version

		vector<unsigned> wordIDs;

		unordered_map<unsigned, string> IDsToWords = unordered_map<unsigned, string>();

		unordered_map<unsigned, unsigned> uniqueWordIDs = unordered_map<unsigned, unsigned>();

		for (unsigned i = 0; i < inputFilenames.size(); i++)
		{
			stringstream filenameSS;
			filenameSS << inputFilepath << inputFilenames[i];
			string filename = filenameSS.str();
			text = getText(filename, fileSize);
			if (!text)
				continue;
			wordIDs = stringToWordIDs(text, IDsToWords, uniqueWordIDs);
			versions.push_back(wordIDs);
			delete text;
			text = NULL;
		}

		// By this time, IDsToWords should contain the mappings of IDs to words in all versions
		// printIDtoWordMapping(IDsToWords);
		// system("pause");

		vector<Association> associations;

		unsigned* offsetsAllVersions(NULL);
		unsigned* versionPartitionSizes(NULL);

		unsigned* bestOffsetsAllVersions(NULL);
		unsigned* bestVersionPartitionSizes(NULL);

		unsigned bestMinFragSize;
		unsigned bestRepairStoppingPoint;

		double score(0.0);
		double max(0.0);
		// This crashes after 4 lines of output
		for ( minFragSize = 10; minFragSize < 30; minFragSize += 10 )
		{
			for ( repairStoppingPoint = 2; repairStoppingPoint < 20; repairStoppingPoint += 2 )
			{
				score = runRepairPartitioning(versions, IDsToWords, offsetsAllVersions, versionPartitionSizes, associations, minFragSize, repairStoppingPoint, false);
				cerr << "minFragSize: " << minFragSize << ", repairStoppingPoint: " << repairStoppingPoint << ", score: " << score << endl;

				if (score > max)
				{
					max = score;
					bestMinFragSize = minFragSize;
					bestRepairStoppingPoint = repairStoppingPoint;

					bestOffsetsAllVersions = offsetsAllVersions;
					bestVersionPartitionSizes = versionPartitionSizes;
				}
				else
				{
					delete offsetsAllVersions;
					offsetsAllVersions = NULL;

					delete versionPartitionSizes;
					versionPartitionSizes = NULL;
				}
			}
		}

		cerr << "Best partitioning happened with" << endl;
		cerr << "minFragSize: " << bestMinFragSize << ", repairStoppingPoint: " << bestRepairStoppingPoint << endl;

		string outputFilename = "Output/results.txt";

		bool printFragments = true;
		bool printAssociations = false;
		writeResults(versions, bestOffsetsAllVersions, bestVersionPartitionSizes, associations, IDsToWords, outputFilename, printFragments, printAssociations);

		stringstream command;
		command << "start " << outputFilename.c_str();
		system(command.str().c_str());
	}
}<commit_msg>cleaned up protoype.cpp<commit_after>#include "Repair.h"
#include "UndoRepair.h"
#include "Partitioning.h"
#include "Util.h"
using namespace std;

/*
We must be able to re-extract for the algorithm to be correct
Associations must be monotonically decreasing for the algorithm to be optimal
*/
bool checkOutput(vector<Association> associations, vector<unsigned> wordIDs)
{
	//Check to see whether it's correct
	vector<unsigned> extractedWordIDs = undoRepair(associations);
	for (size_t i = 0; i < extractedWordIDs.size(); i++)
	{
		//cerr << "Orig: " << wordIDs[i] << ", compare: " << extractedWordIDs[i] << endl;
		if (extractedWordIDs[i] != wordIDs[i])
		{
			return false;
		}
	}

	cerr << "Passed correctness check..." << endl;

	//If it's correct, check to see whether it's optimal
	for (size_t i = 0; i < associations.size() - 1; i++)
	{
		// cerr << "i: " << i << " freq[i]: " << associations[i].freq << ", freq[i+1]: " << associations[i+1].freq << endl;
		// system("pause");
		if (associations[i].freq < associations[i+1].freq)
		{
			return false;
		}
	}

	cerr << "Passed optimal check..." << endl;

	return true;
}

double getScore(unordered_map<string, FragInfo>& uniqueFrags, ostream& os = cerr)
{
	double term;
	double sum(0);
	for (unordered_map<string, FragInfo>::iterator it = uniqueFrags.begin(); it != uniqueFrags.end(); it++)
	{
		term = it->second.count * it->second.fragSize;
		sum += term;
	}
	return sum / uniqueFrags.size();
}

void writeAssociations(const vector<Association>& associations, ostream& os = cerr)
{
	for (size_t i = 0; i < associations.size(); i++)
	{
		os << associations[i];
	}
}

void writeResults(const vector<vector<unsigned> >& versions, unsigned* offsetsAllVersions, unsigned* versionPartitionSizes, const vector<Association>& associations, unordered_map<unsigned, string>& IDsToWords, const string& outFilename, bool printFragments = false, bool printAssociations = false)
{
	ofstream os(outFilename.c_str());

	os << "Results of re-pair partitioning..." << endl << endl;
	os << "*** Fragment boundaries ***" << endl;

	unsigned totalCountFragments(0);
	unsigned diff(0);
	unsigned numVersions = versions.size();
	for (unsigned v = 0; v < numVersions; v++)
	{
		unsigned numFragsInVersion = versionPartitionSizes[v];

		if (numFragsInVersion < 1)
		{
			continue;
		}
		os << "Version " << v << endl;
		for (unsigned i = 0; i < numFragsInVersion - 1; i++)
		{
			if (i < versionPartitionSizes[v] - 1)
			{
				unsigned currOffset = offsetsAllVersions[totalCountFragments + i];
				unsigned nextOffset = offsetsAllVersions[totalCountFragments + i + 1];
				diff = nextOffset - currOffset;
			}
			else
			{
				diff = 0;
			}

			os << "Fragment " << i << ": " << offsetsAllVersions[totalCountFragments + i] << "-" <<
				offsetsAllVersions[totalCountFragments + i + 1] << " (frag size: " << diff << ")" << endl;
		}
		totalCountFragments += numFragsInVersion;
		os << endl;
	}

	// os << "Number of fragment boundaries: " << starts.size() << endl;
	// os << "Number of fragments: " << (starts.size() - 1) << endl << endl;

	vector<vector<FragInfo > > fragmentHashes;
	os << "*** Fragments ***" << endl;
	fragmentHashes = getFragmentHashes(versions, offsetsAllVersions, versionPartitionSizes, IDsToWords, os, printFragments);

	// Assign fragment IDs and stick them in a hashmap
	unordered_map<string, FragInfo> uniqueFrags;
	updateFragmentHashMap(fragmentHashes, uniqueFrags);

	// Now decide on the score for this partitioning
	double score = getScore(uniqueFrags, os);
	os << "Score: " << score << endl;

	if (printAssociations)
	{
		os << "*** Associations (symbol -> pair) ***" << endl;
		writeAssociations(associations, os);
	}
}

void printIDtoWordMapping(unordered_map<unsigned, string>& IDsToWords, ostream& os = cerr)
{
	for (unordered_map<unsigned, string>::iterator it = IDsToWords.begin(); it != IDsToWords.end(); it++)
	{
		os << it->first << ": " << it->second << endl;
	}
}

double runRepairPartitioning(vector<vector<unsigned> > versions, unordered_map<unsigned, string>& IDsToWords,
	unsigned*& offsetsAllVersions, unsigned*& versionPartitionSizes, vector<Association>& associations,
	unsigned minFragSize, unsigned repairStoppingPoint, bool printFragments = false)
{
	//Allocate the heap, hash table, array of associations, and list of pointers to neighbor structures

	RandomHeap myHeap;

	unordered_map<unsigned long long, HashTableEntry*> hashTable = unordered_map<unsigned long long, HashTableEntry*> ();

	associations = vector<Association>();

	vector<VersionDataItem> versionData = vector<VersionDataItem>();

	extractPairs(versions, myHeap, hashTable, versionData);

	int numPairs = hashTable.size();

	doRepair(myHeap, hashTable, associations, repairStoppingPoint, versionData);

	versionPartitionSizes = new unsigned[versions.size()];

	offsetsAllVersions = getPartitioningsAllVersions(myHeap, minFragSize, versionData, versionPartitionSizes);

	if (!offsetsAllVersions)
	{
		// Maybe repairStoppingPoint was too low
		return 0.0;
	}

	vector<vector<FragInfo > > fragmentHashes;
	fragmentHashes = getFragmentHashes(versions, offsetsAllVersions, versionPartitionSizes, IDsToWords, cerr, printFragments);

	// Assign fragment IDs and stick them in a hashmap
	unordered_map<string, FragInfo> uniqueFrags;
	updateFragmentHashMap(fragmentHashes, uniqueFrags);

	// Now decide on the score for this partitioning
	double score = getScore(uniqueFrags, cerr);
	if (printFragments)
		cerr << "Score: " << score << endl;

	return score;
}

unsigned currentFragID = 0;
unsigned currentID = 0;

int main(int argc, char* argv[])
{
	//createOutputDir();

	//heap, repair
	string test = "repair";

	if (test == "heap")
	{
		RandomHeapTest test = RandomHeapTest(1000);
		exit(0);
	}

	if (test == "repair")
	{
		Profiler::getInstance().start("all");
		string inputFilepath = "./Input/ints/";

		// Default param values
		/*
		Initial test show that minFragSize should be proportional to document size
		*/
		unsigned minFragSize = 2; //in words

		/*
		Initial tests show that repairStoppingPoint shouldn't be too small (repair goes too far for our purposes in this case)
		And it shouldn't be larger than the number of versions (this is trivial, we expect to get repetition
		at most numVersions times for inter-version repetitions)
		*/
		unsigned repairStoppingPoint = 2; //pairs that occur less than this amount of times will not be replaced

		if (argc == 2 && (string) argv[1] == "help")
		{
			cerr << "Usage:" << endl;
			cerr << "\t" << argv[0] << " <directory> <minFragSize> <repairStoppingPoint>" << endl;
			cerr << "\t" << argv[0] << " <directory> <minFragSize>" << endl;
			cerr << "\t" << argv[0] << " <directory>" << endl;
			cerr << "\t" << argv[0] << "" << endl << endl;
			cerr << "Defaults: " << endl;
			cerr << "\tdirectory: " << inputFilepath << endl;
			cerr << "\tminFragSize: " << minFragSize << endl;
			cerr << "\trepairStoppingPoint: " << repairStoppingPoint << endl;
			exit(0);
		}

		if (argc > 1)
			inputFilepath = (string)argv[1];

		if (argc > 2)
			minFragSize = atoi(argv[2]);

		if (argc > 3)
			repairStoppingPoint = atoi(argv[3]);

		vector<string> inputFilenames = vector<string>();
		if (getFileNames(inputFilepath, inputFilenames))
			return errno;

		char* text;

		int fileSize;

		vector<vector<unsigned> > versions = vector<vector<unsigned> >(); //each inner vector is the wordIDs for one version

		vector<unsigned> wordIDs;

		unordered_map<unsigned, string> IDsToWords = unordered_map<unsigned, string>();

		unordered_map<unsigned, unsigned> uniqueWordIDs = unordered_map<unsigned, unsigned>();

		for (unsigned i = 0; i < inputFilenames.size(); i++)
		{
			stringstream filenameSS;
			filenameSS << inputFilepath << inputFilenames[i];
			string filename = filenameSS.str();
			text = getText(filename, fileSize);
			if (!text)
				continue;
			wordIDs = stringToWordIDs(text, IDsToWords, uniqueWordIDs);
			versions.push_back(wordIDs);
			delete text;
			text = NULL;
		}

		// By this time, IDsToWords should contain the mappings of IDs to words in all versions
		// printIDtoWordMapping(IDsToWords);
		// system("pause");

		vector<Association> associations;

		unsigned* offsetsAllVersions(NULL);
		unsigned* versionPartitionSizes(NULL);

		unsigned* bestOffsetsAllVersions(NULL);
		unsigned* bestVersionPartitionSizes(NULL);

		unsigned bestMinFragSize;
		unsigned bestRepairStoppingPoint;

		double score(0.0);
		double max(0.0);
		// This crashes after 4 lines of output
		for ( minFragSize = 10; minFragSize < 30; minFragSize += 10 )
		{
			for ( repairStoppingPoint = 2; repairStoppingPoint < 20; repairStoppingPoint += 2 )
			{
				score = runRepairPartitioning(versions, IDsToWords, offsetsAllVersions, versionPartitionSizes, associations, minFragSize, repairStoppingPoint, false);
				cerr << "minFragSize: " << minFragSize << ", repairStoppingPoint: " << repairStoppingPoint << ", score: " << score << endl;

				if (score > max)
				{
					max = score;
					bestMinFragSize = minFragSize;
					bestRepairStoppingPoint = repairStoppingPoint;

					bestOffsetsAllVersions = offsetsAllVersions;
					bestVersionPartitionSizes = versionPartitionSizes;
				}
				else
				{
					delete offsetsAllVersions;
					offsetsAllVersions = NULL;

					delete versionPartitionSizes;
					versionPartitionSizes = NULL;
				}
			}
		}

		cerr << "Best partitioning happened with" << endl;
		cerr << "minFragSize: " << bestMinFragSize << ", repairStoppingPoint: " << bestRepairStoppingPoint << endl;

		// stringstream outFilenameStream;
		// outFilenameStream << "Output/results" << stripDot(inputFilepath);
		// string outputFilename = outFilenameStream.str();

		string outputFilename = "Output/results.txt";

		bool printFragments = true;
		bool printAssociations = false;
		writeResults(versions, bestOffsetsAllVersions, bestVersionPartitionSizes, associations, IDsToWords, outputFilename, printFragments, printAssociations);

		stringstream command;
		command << "start " << outputFilename.c_str();
		system(command.str().c_str());

		// stringstream ss;
		// ss << "Filename: " << inputFilepath << endl;
		// ss << "Size: " << fileSize << " bytes" << endl;
		// ss << "Word Count: " << wordIDs.size() << endl;
		// ss << "Unique Pair Count (in original file): " << numPairs << endl;

		// cerr << "Checking output... " << endl;
		// if (checkOutput(associations, wordIDs))
		// 	cerr << "Output ok!";
		// else
		// 	cerr << "Check failed!";
		// cerr << endl;

		// Profiler::getInstance().end("all");
		// Profiler::getInstance().setInputSpec(ss.str());
		// Profiler::getInstance().writeResults("Output/profile-functions.txt");

		// cleanup(hashTable);
		// system("pause");
	}
}<|endoftext|>


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

#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/main_function_params.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"

// TODO(port): Bring up this test this on other platforms.
#if defined(OS_POSIX)

using base::ProcessHandle;

const char kRendererTestChannelName[] = "test";

extern int RendererMain(const MainFunctionParams& parameters);

// TODO(port): The IPC Channel tests have a class with extremely similar
// functionality, we should combine them.
class RendererMainTest : public base::MultiProcessTest {
 protected:
  RendererMainTest() {}

  // Create a new MessageLoopForIO For each test.
  virtual void SetUp();
  virtual void TearDown();

  // Spawns a child process of the specified type
  base::ProcessHandle SpawnChild(const std::string& procname,
                                 IPC::Channel* channel);

  // Created around each test instantiation.
  MessageLoopForIO *message_loop_;
};

void RendererMainTest::SetUp() {
  MultiProcessTest::SetUp();

  // Construct a fresh IO Message loop for the duration of each test.
  message_loop_ = new MessageLoopForIO();
}

void RendererMainTest::TearDown() {
  delete message_loop_;
  message_loop_ = NULL;

  MultiProcessTest::TearDown();
}

ProcessHandle RendererMainTest::SpawnChild(const std::string& procname,
                                           IPC::Channel* channel) {
  base::file_handle_mapping_vector fds_to_map;
  const int ipcfd = channel->GetClientFileDescriptor();
  if (ipcfd > -1) {
    fds_to_map.push_back(std::pair<int,int>(ipcfd, 3));
  }

  return MultiProcessTest::SpawnChild(procname, fds_to_map, false);
}

// Listener class that kills the message loop when it connects.
class SuicidalListener : public IPC::Channel::Listener {
 public:
  explicit SuicidalListener(bool* suicide_success)
      : suicide_success_(suicide_success) {}

  void OnChannelConnected(int32 peer_pid) {
    *suicide_success_ = true;
    MessageLoop::current()->Quit();
  }

  void OnMessageReceived(const IPC::Message& message) {
    // We shouldn't receive any messages
    ASSERT_TRUE(false);
  }

  // A flag that we set when we have successfully suicided.
  bool* suicide_success_;
};

MULTIPROCESS_TEST_MAIN(SimpleRenderer) {
  SandboxInitWrapper dummy_sandbox_init;
  CommandLine cl(*CommandLine::ForCurrentProcess());
  cl.AppendSwitchASCII(switches::kProcessChannelID, kRendererTestChannelName);

  MainFunctionParams dummy_params(cl, dummy_sandbox_init, NULL);
  return RendererMain(dummy_params);
}

TEST_F(RendererMainTest, CreateDestroy) {
  bool suicide_success = false;
  SuicidalListener listener(&suicide_success);
  IPC::Channel control_channel(kRendererTestChannelName,
                               IPC::Channel::MODE_SERVER,
                               &listener);
  base::ProcessHandle renderer_pid = SpawnChild("SimpleRenderer",
                                                &control_channel);

  ASSERT_TRUE(control_channel.Connect());

  // The SuicidalListener *should* cause the following MessageLoop run
  // to quit, but just in case it doesn't, insert a QuitTask at the back
  // of the queue.
  MessageLoop::current()->PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask,
                                          TestTimeouts::action_timeout_ms());
  MessageLoop::current()->Run();
  ASSERT_TRUE(suicide_success);

  // The renderer should exit when we close the channel.
  control_channel.Close();

  EXPECT_TRUE(base::WaitForSingleProcess(renderer_pid,
                                         TestTimeouts::action_timeout_ms()));
}
#endif  // defined(OS_POSIX)
<commit_msg>Revert most of my recent changes to RendererMainTest.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/main_function_params.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"

// TODO(port): Bring up this test this on other platforms.
#if defined(OS_POSIX)

using base::ProcessHandle;

const char kRendererTestChannelName[] = "test";

extern int RendererMain(const MainFunctionParams& parameters);

// TODO(port): The IPC Channel tests have a class with extremely similar
// functionality, we should combine them.
class RendererMainTest : public base::MultiProcessTest {
 protected:
  RendererMainTest() {}

  // Create a new MessageLoopForIO For each test.
  virtual void SetUp();
  virtual void TearDown();

  // Spawns a child process of the specified type
  base::ProcessHandle SpawnChild(const std::string& procname,
                                 IPC::Channel* channel);

  // Created around each test instantiation.
  MessageLoopForIO *message_loop_;
};

void RendererMainTest::SetUp() {
  MultiProcessTest::SetUp();

  // Construct a fresh IO Message loop for the duration of each test.
  message_loop_ = new MessageLoopForIO();
}

void RendererMainTest::TearDown() {
  delete message_loop_;
  message_loop_ = NULL;

  MultiProcessTest::TearDown();
}

ProcessHandle RendererMainTest::SpawnChild(const std::string& procname,
                                           IPC::Channel* channel) {
  base::file_handle_mapping_vector fds_to_map;
  const int ipcfd = channel->GetClientFileDescriptor();
  if (ipcfd > -1) {
    fds_to_map.push_back(std::pair<int,int>(ipcfd, 3));
  }

  return MultiProcessTest::SpawnChild(procname, fds_to_map, false);
}

// Listener class that kills the message loop when it connects.
class SuicidalListener : public IPC::Channel::Listener {
 public:
  void OnChannelConnected(int32 peer_pid) {
    MessageLoop::current()->Quit();
  }

  void OnMessageReceived(const IPC::Message& message) {
    // We shouldn't receive any messages
    ASSERT_TRUE(false);
  }
};

MULTIPROCESS_TEST_MAIN(SimpleRenderer) {
  SandboxInitWrapper dummy_sandbox_init;
  CommandLine cl(*CommandLine::ForCurrentProcess());
  cl.AppendSwitchASCII(switches::kProcessChannelID, kRendererTestChannelName);

  MainFunctionParams dummy_params(cl, dummy_sandbox_init, NULL);
  return RendererMain(dummy_params);
}

TEST_F(RendererMainTest, CreateDestroy) {
  SuicidalListener listener;
  IPC::Channel control_channel(kRendererTestChannelName,
                               IPC::Channel::MODE_SERVER,
                               &listener);
  base::ProcessHandle renderer_pid = SpawnChild("SimpleRenderer",
                                                &control_channel);

  ASSERT_TRUE(control_channel.Connect());

  MessageLoop::current()->PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask,
                                          TestTimeouts::action_timeout_ms());
  MessageLoop::current()->Run();

  // The renderer should exit when we close the channel.
  control_channel.Close();

  EXPECT_TRUE(base::WaitForSingleProcess(renderer_pid,
                                         TestTimeouts::action_timeout_ms()));
}
#endif  // defined(OS_POSIX)
<|endoftext|>


<commit_before>/*
 * This file is part of buteo-syncfw package
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: Sateesh Kavuri <sateesh.kavuri@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "Logger.h"
#include <QMutexLocker>
#include <iostream>
#include <QFile>
#include <QFileInfo>
#include <QDir>

#include <syslog.h>

using namespace Buteo;

void logMessageHandler(QtMsgType aType, const char *aMsg)
{
     Logger::instance()->write(aType, aMsg);
}

const int Logger::DEFAULT_INDENT_SIZE = 4;

Logger *Logger::sInstance = NULL;

Logger *Logger::instance()
{
    if (NULL == sInstance)
    {
        createInstance();
    }
    return sInstance;
}

void Logger::createInstance(const QString &aLogFileName, bool aUseStdOut,
                            int aIndentSize)
{
    deleteInstance();
    sInstance = new Logger(aLogFileName, aUseStdOut, aIndentSize);
}

void Logger::deleteInstance()
{
    delete sInstance;
    sInstance = NULL;
}

Logger::Logger(const QString &aLogFileName, bool aUseStdOut, int aIndentSize)
:   iEnabledLevels(NUM_LEVELS),
    iIndentLevel(0),
    iIndentSize(aIndentSize),
    iFileStream(0),
    iStdOutStream(0),
    iStdErrStream(0),
    iEnabled(false)
{
    if (aUseStdOut)
    {
        // Create a stream for writing log messages to standard output.
        iStdOutStream = new QTextStream(stdout);
    } // no else

    iStdErrStream = new QTextStream(stderr);

    if (!aLogFileName.isEmpty())
    {
        // Create stream for writing log messages to a file.
        iFile.setFileName(aLogFileName);
        QFileInfo fileInfo(iFile);
        QDir dir;
        dir.mkpath(fileInfo.absolutePath());
        if (iFile.open(QIODevice::WriteOnly | QIODevice::Append))
        {
            iFileStream = new QTextStream(&iFile);
        } // no else
    } // no else

    // Install our own message handler.
    qInstallMsgHandler(logMessageHandler);

}

Logger::~Logger()
{
    // Restore default message handler.
    qInstallMsgHandler(0);

    delete iFileStream;
    iFileStream = 0;

    delete iStdOutStream;
    iStdOutStream = 0;

    delete iStdErrStream;
    iStdErrStream = 0;
}

bool  Logger::setLogLevel(int aLevel)
{
    bool retVal = false;
    if ((aLevel > 0)  && (aLevel <= NUM_LEVELS))
    {
	disable(iEnabledLevels);
        QBitArray iLevels(NUM_LEVELS, false);
        for(int i = aLevel; i > 0; i--)
        {
            iLevels.setBit(NUM_LEVELS - i);
        }
        enable(iLevels);
        retVal = true;
    } // no else
    return retVal;
}

QBitArray Logger::getLogLevelArray()
{
	return iEnabledLevels;
}

void Logger::enable(const QBitArray &aLevels)
{
    QMutexLocker lock(&iMutex);
    iEnabledLevels |= aLevels;
    iEnabled = true;
}

void Logger::disable(const QBitArray &aLevels)
{
    QMutexLocker lock(&iMutex);
    iEnabledLevels &= ~(aLevels);
    iEnabled = false;
}

void Logger::push()
{
    QMutexLocker lock(&iMutex);
    iIndentLevel += iIndentSize;
}

void Logger::pop()
{
    QMutexLocker lock(&iMutex);
    iIndentLevel -= iIndentSize;
    if (iIndentLevel < 0)
        iIndentLevel = 0;
}

void Logger::write(int aLevel, const char *aMsg)
{
    static const char* levelTexts[NUM_LEVELS] = {
        "Debug: ",
        "Warning: ",
        "Critical: ",
        "Fatal: ",
    };

    int syslogLevel[NUM_LEVELS] = {
	    LOG_DEBUG,
	    LOG_WARNING,
	    LOG_CRIT,
	    LOG_CRIT,
    } ;

    QMutexLocker lock(&iMutex);

    // Verify that the log message can and should be written.
    if (aLevel < QtDebugMsg || aLevel > QtFatalMsg )
    {
        return;
    }

    // We don't make use of format specifiers in our logs, but syslog (vprintf) might interpret any % as part of
    // a format specifier and might fail (crash) when it doesn't find values corresponding to the format, prevent that.
    QString sysLogMsg = QString::fromLocal8Bit(aMsg);
    sysLogMsg = sysLogMsg.remove("%");

    if(!iEnabledLevels.count(true))
    {
        if(aLevel >= QtCriticalMsg)
        {
            syslog(LOG_CRIT, sysLogMsg.toLocal8Bit().data());
        }
        return;
    }

    // Verify that the log message can and should be written.
    if (!iEnabledLevels.testBit(aLevel))
    {
        return;
    }

    syslog(syslogLevel[aLevel], sysLogMsg.toLocal8Bit().data());

    if (iFileStream != 0)
    {
        *iFileStream << QString(iIndentLevel, ' ') << levelTexts[aLevel] <<
           aMsg << "\n";
        iFileStream->flush();
    }

    if (aLevel != QtDebugMsg)
    {
        if (iStdErrStream != 0)
        {
            *iStdErrStream << QString(iIndentLevel, ' ') << levelTexts[aLevel] <<
                   aMsg << "\n";
            iStdErrStream->flush();
        }
    }
    else if (iStdOutStream != 0)
    {
        *iStdOutStream << QString(iIndentLevel, ' ') << levelTexts[aLevel] <<
           aMsg << "\n";
        iStdOutStream->flush();
    }

    if (QtFatalMsg == aLevel)
    {
        // Exit on fatal message.
        abort();
    } // no else
}

<commit_msg>[qt5] Port logger to Qt5<commit_after>/*
 * This file is part of buteo-syncfw package
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: Sateesh Kavuri <sateesh.kavuri@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "Logger.h"
#include <QMutexLocker>
#include <iostream>
#include <QFile>
#include <QFileInfo>
#include <QDir>

#include <syslog.h>

using namespace Buteo;

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
void logMessageHandler(QtMsgType aType, const QMessageLogContext&, const QString& aMsg)
#else
void logMessageHandler(QtMsgType aType, const char *aMsg)
#endif
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
  Logger::instance()->write(aType, qPrintable(aMsg));
#else
  Logger::instance()->write(aType, aMsg);
#endif
}

const int Logger::DEFAULT_INDENT_SIZE = 4;

Logger *Logger::sInstance = NULL;

Logger *Logger::instance()
{
    if (NULL == sInstance)
    {
        createInstance();
    }
    return sInstance;
}

void Logger::createInstance(const QString &aLogFileName, bool aUseStdOut,
                            int aIndentSize)
{
    deleteInstance();
    sInstance = new Logger(aLogFileName, aUseStdOut, aIndentSize);
}

void Logger::deleteInstance()
{
    delete sInstance;
    sInstance = NULL;
}

Logger::Logger(const QString &aLogFileName, bool aUseStdOut, int aIndentSize)
:   iEnabledLevels(NUM_LEVELS),
    iIndentLevel(0),
    iIndentSize(aIndentSize),
    iFileStream(0),
    iStdOutStream(0),
    iStdErrStream(0),
    iEnabled(false)
{
    if (aUseStdOut)
    {
        // Create a stream for writing log messages to standard output.
        iStdOutStream = new QTextStream(stdout);
    } // no else

    iStdErrStream = new QTextStream(stderr);

    if (!aLogFileName.isEmpty())
    {
        // Create stream for writing log messages to a file.
        iFile.setFileName(aLogFileName);
        QFileInfo fileInfo(iFile);
        QDir dir;
        dir.mkpath(fileInfo.absolutePath());
        if (iFile.open(QIODevice::WriteOnly | QIODevice::Append))
        {
            iFileStream = new QTextStream(&iFile);
        } // no else
    } // no else

    // Install our own message handler.
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    qInstallMessageHandler(logMessageHandler);
#else
    qInstallMsgHandler(logMessageHandler);
#endif
}

Logger::~Logger()
{
    // Restore default message handler.
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    qInstallMessageHandler(0);
#else
    qInstallMsgHandler(0);
#endif

    delete iFileStream;
    iFileStream = 0;

    delete iStdOutStream;
    iStdOutStream = 0;

    delete iStdErrStream;
    iStdErrStream = 0;
}

bool  Logger::setLogLevel(int aLevel)
{
    bool retVal = false;
    if ((aLevel > 0)  && (aLevel <= NUM_LEVELS))
    {
        disable(iEnabledLevels);
        QBitArray iLevels(NUM_LEVELS, false);
        for(int i = aLevel; i > 0; i--)
        {
            iLevels.setBit(NUM_LEVELS - i);
        }
        enable(iLevels);
        retVal = true;
    } // no else
    return retVal;
}

QBitArray Logger::getLogLevelArray()
{
        return iEnabledLevels;
}

void Logger::enable(const QBitArray &aLevels)
{
    QMutexLocker lock(&iMutex);
    iEnabledLevels |= aLevels;
    iEnabled = true;
}

void Logger::disable(const QBitArray &aLevels)
{
    QMutexLocker lock(&iMutex);
    iEnabledLevels &= ~(aLevels);
    iEnabled = false;
}

void Logger::push()
{
    QMutexLocker lock(&iMutex);
    iIndentLevel += iIndentSize;
}

void Logger::pop()
{
    QMutexLocker lock(&iMutex);
    iIndentLevel -= iIndentSize;
    if (iIndentLevel < 0)
        iIndentLevel = 0;
}

void Logger::write(int aLevel, const char *aMsg)
{
    static const char* levelTexts[NUM_LEVELS] = {
        "Debug: ",
        "Warning: ",
        "Critical: ",
        "Fatal: ",
    };

    int syslogLevel[NUM_LEVELS] = {
            LOG_DEBUG,
            LOG_WARNING,
            LOG_CRIT,
            LOG_CRIT,
    } ;

    QMutexLocker lock(&iMutex);

    // Verify that the log message can and should be written.
    if (aLevel < QtDebugMsg || aLevel > QtFatalMsg )
    {
        return;
    }

    // We don't make use of format specifiers in our logs, but syslog (vprintf) might interpret any % as part of
    // a format specifier and might fail (crash) when it doesn't find values corresponding to the format, prevent that.
    QString sysLogMsg = QString::fromLocal8Bit(aMsg);
    sysLogMsg = sysLogMsg.remove("%");

    if(!iEnabledLevels.count(true))
    {
        if(aLevel >= QtCriticalMsg)
        {
            syslog(LOG_CRIT, sysLogMsg.toLocal8Bit().data());
        }
        return;
    }

    // Verify that the log message can and should be written.
    if (!iEnabledLevels.testBit(aLevel))
    {
        return;
    }

    syslog(syslogLevel[aLevel], sysLogMsg.toLocal8Bit().data());

    if (iFileStream != 0)
    {
        *iFileStream << QString(iIndentLevel, ' ') << levelTexts[aLevel] <<
           aMsg << "\n";
        iFileStream->flush();
    }

    if (aLevel != QtDebugMsg)
    {
        if (iStdErrStream != 0)
        {
            *iStdErrStream << QString(iIndentLevel, ' ') << levelTexts[aLevel] <<
                   aMsg << "\n";
            iStdErrStream->flush();
        }
    }
    else if (iStdOutStream != 0)
    {
        *iStdOutStream << QString(iIndentLevel, ' ') << levelTexts[aLevel] <<
           aMsg << "\n";
        iStdOutStream->flush();
    }

    if (QtFatalMsg == aLevel)
    {
        // Exit on fatal message.
        abort();
    } // no else
}
<|endoftext|>