<commit_before>//=====================================================================//
/*! @file
    @brief  RX24T CNC ドライバー @n
			・ステッピングモーターパルス出力 @n
			・リミットスイッチによる制御 @n
			・P00(4) ピンに赤色LED（VF:1.9V）を吸い込みで接続する
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/cmt_io.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"

#include "cnc_pulse.hpp"

namespace {

	static const uint16_t VERSION = 10;

	typedef device::PORT<device::PORT0, device::bitpos::B0> LED;

	device::cmt_io<device::CMT0, utils::null_task>  cmt_;

	typedef utils::fixed_fifo<char, 1024> RBF;
	typedef utils::fixed_fifo<char,  128> SBF;
	typedef device::sci_io<device::SCI1, RBF, SBF> SCI;
	SCI		sci_;

	typedef utils::command<256> COMMAND;
	COMMAND command_;

	typedef cnc::pulse<COMMAND>	CNC;
	CNC		cnc_(command_);

}

extern "C" {

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}

}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MEMWAIT = 0b10; // 80MHz 動作 wait 設定

	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");
	device::SYSTEM::OPCCR = 0;  // 高速モード選択
	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");

	// clock osc 10MHz
	device::SYSTEM::MOSCWTCR = 9;	// 4ms wait
	// メインクロック・ドライブ能力設定、内部発信
	device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV21.b(1);
	device::SYSTEM::MOSCCR.MOSTP = 0;  // メインクロック発振器動作
	while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) asm("nop");

	device::SYSTEM::PLLCR.STC = 0b001111;		// PLL input: 1, PLL 8 倍(80MHz)
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) asm("nop");

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(2)		// 1/4 (80/4=20)
						  | device::SYSTEM::SCKCR.ICK.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKA.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKB.b(1)		// 1/2 (80/2=40)
						  | device::SYSTEM::SCKCR.PCKD.b(1);	// 1/2 (80/2=40)
	device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

	// タイマー設定（１００Ｈｚ）
	{
		uint8_t intr = 3;
		cmt_.start(100, intr);
	}

	// SCI 設定
	static const uint8_t sci_level = 2;
	sci_.start(115200, sci_level);

	utils::format("CNC Driver Version %1d.%02d\n") % (VERSION / 100) % (VERSION % 100);

	cnc_.start();

	command_.set_prompt("# ");

	LED::DIR = 1;

	uint32_t cnt = 0;
	while(1) {
		cmt_.sync();

		cnc_.update();

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			auto f = cnc_.service_command();
			if(!f) {
				utils::format("Error: '%s'\n") % command_.get_command();
			}
		}

		++cnt;
		if(cnt >= 30) {
			cnt = 0;
		}
		LED::P = (cnt < 10) ? 0 : 1;
	}
}
<commit_msg>update: version 0.40 CNC<commit_after>//=====================================================================//
/*! @file
    @brief  RX24T CNC ドライバー @n
			・ステッピングモーターパルス出力 @n
			・リミットスイッチによる制御 @n
			・P00(4) ピンに赤色LED（VF:1.9V）を吸い込みで接続する
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/cmt_io.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"

#include "cnc_pulse.hpp"

namespace {

	static const uint16_t VERSION = 40;

	typedef device::PORT<device::PORT0, device::bitpos::B0> LED;

	device::cmt_io<device::CMT0, utils::null_task>  cmt_;

	typedef utils::fixed_fifo<char, 1024> RBF;
	typedef utils::fixed_fifo<char,  128> SBF;
	typedef device::sci_io<device::SCI1, RBF, SBF> SCI;
	SCI		sci_;

	typedef utils::command<256> COMMAND;
	COMMAND command_;

	typedef cnc::pulse<COMMAND>	CNC;
	CNC		cnc_(command_);

}

extern "C" {

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}

}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

	device::SYSTEM::MEMWAIT = 0b10; // 80MHz 動作 wait 設定

	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");
	device::SYSTEM::OPCCR = 0;  // 高速モード選択
	while(device::SYSTEM::OPCCR.OPCMTSF() != 0) asm("nop");

	// clock osc 10MHz
	device::SYSTEM::MOSCWTCR = 9;	// 4ms wait
	// メインクロック・ドライブ能力設定、内部発信
	device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV21.b(1);
	device::SYSTEM::MOSCCR.MOSTP = 0;  // メインクロック発振器動作
	while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) asm("nop");

	device::SYSTEM::PLLCR.STC = 0b001111;		// PLL input: 1, PLL 8 倍(80MHz)
	device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
	while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) asm("nop");

	device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(2)		// 1/4 (80/4=20)
						  | device::SYSTEM::SCKCR.ICK.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKA.b(0)		// 1/1 (80/1=80)
						  | device::SYSTEM::SCKCR.PCKB.b(1)		// 1/2 (80/2=40)
						  | device::SYSTEM::SCKCR.PCKD.b(1);	// 1/2 (80/2=40)
	device::SYSTEM::SCKCR3.CKSEL = 0b100;	///< PLL 選択

	// タイマー設定（１００Ｈｚ）
	{
		uint8_t intr = 3;
		cmt_.start(100, intr);
	}

	// SCI 設定
	static const uint8_t sci_level = 2;
	sci_.start(115200, sci_level);

	utils::format("CNC Driver Version %1d.%02d\n") % (VERSION / 100) % (VERSION % 100);

	cnc_.start();

	command_.set_prompt("# ");

	LED::DIR = 1;

	uint32_t cnt = 0;
	while(1) {
		cmt_.sync();

		cnc_.update();

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			auto f = cnc_.service_command();
			if(!f) {
				utils::format("Error: '%s'\n") % command_.get_command();
			}
		}

		++cnt;
		if(cnt >= 30) {
			cnt = 0;
		}
		LED::P = (cnt < 10) ? 0 : 1;
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp

#include <NDK/Widgets/TextAreaWidget.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/World.hpp>
#include <limits>

namespace Ndk
{
	TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
	BaseWidget(parent),
	m_cursorPosition(0U),
	m_multiLineEnabled(false),
	m_readOnly(false)
	{
		m_cursorSprite = Nz::Sprite::New();
		m_cursorSprite->SetColor(Nz::Color(192, 192, 192));
		m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));

		m_cursorEntity = CreateEntity();
		m_cursorEntity->AddComponent<GraphicsComponent>().Attach(m_cursorSprite, 10);
		m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
		m_cursorEntity->Enable(false);

		m_textSprite = Nz::TextSprite::New();

		m_textEntity = CreateEntity();
		m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
		m_textEntity->AddComponent<NodeComponent>().SetParent(this);

		SetCursor(Nz::SystemCursor_Text);

		Layout();
	}

	void TextAreaWidget::AppendText(const Nz::String& text)
	{
		m_drawer.AppendText(text);

		m_textSprite->Update(m_drawer);
	}

	std::size_t TextAreaWidget::GetHoveredGlyph(float x, float y) const
	{
		std::size_t glyphCount = m_drawer.GetGlyphCount();
		if (glyphCount > 0)
		{
			std::size_t lineCount = m_drawer.GetLineCount();
			std::size_t line = 0U;
			for (; line < lineCount - 1; ++line)
			{
				Nz::Rectf lineBounds = m_drawer.GetLine(line).bounds;
				if (lineBounds.GetMaximum().y > y)
					break;
			}

			std::size_t upperLimit = (line != lineCount - 1) ? m_drawer.GetLine(line + 1).glyphIndex : glyphCount + 1;

			std::size_t i = m_drawer.GetLine(line).glyphIndex;
			for (; i < upperLimit - 1; ++i)
			{
				Nz::Rectf bounds = m_drawer.GetGlyph(i).bounds;
				if (x < bounds.x + bounds.width * 0.75f)
					break;
			}

			return i;
		}

		return 0;
	}

	void TextAreaWidget::ResizeToContent()
	{
		SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
	}

	void TextAreaWidget::Write(const Nz::String& text)
	{
		if (m_cursorPosition >= m_drawer.GetGlyphCount())
		{
			AppendText(text);
			SetCursorPosition(m_drawer.GetGlyphCount());
		}
		else
		{
			Nz::String currentText = m_drawer.GetText();
			currentText.Insert(currentText.GetCharacterPosition(m_cursorPosition), text);
			SetText(currentText);

			SetCursorPosition(m_cursorPosition + text.GetLength());
		}
	}

	void TextAreaWidget::Layout()
	{
		BaseWidget::Layout();

		m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());

		RefreshCursor();
	}

	void TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
	{
		switch (key.code)
		{
			case Nz::Keyboard::Delete:
			{
				const Nz::String& text = m_drawer.GetText();

				Nz::String newText;
				if (m_cursorPosition > 0)
					newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition) - 1));

				if (m_cursorPosition < m_drawer.GetGlyphCount())
					newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition + 1)));

				m_drawer.SetText(newText);
				m_textSprite->Update(m_drawer);
				break;
			}

			case Nz::Keyboard::Down:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyDown(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				//TODO
				break;
			}

			case Nz::Keyboard::Left:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyLeft(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				MoveCursor(-1);
				break;
			}

			case Nz::Keyboard::Right:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyRight(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				MoveCursor(1);
				break;
			}

			case Nz::Keyboard::Up:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyUp(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				//TODO
				break;
			}
		}
	}

	void TextAreaWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& key)
	{
	}

	void TextAreaWidget::OnMouseEnter()
	{
		m_cursorEntity->Enable(true);
	}

	void TextAreaWidget::OnMouseButtonPress(int x, int y, Nz::Mouse::Button button)
	{
		if (button == Nz::Mouse::Left)
		{
			GrabKeyboard();

			SetCursorPosition(GetHoveredGlyph(float(x), float(y)));
		}
	}

	void TextAreaWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY)
	{
	}

	void TextAreaWidget::OnMouseExit()
	{
		m_cursorEntity->Enable(false);
	}

	void TextAreaWidget::OnTextEntered(char32_t character, bool /*repeated*/)
	{
		if (m_readOnly)
			return;

		switch (character)
		{
			case '\b':
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyBackspace(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				const Nz::String& text = m_drawer.GetText();

				Nz::String newText;
				if (m_cursorPosition > 1)
					newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition - 1) - 1));

				if (m_cursorPosition < m_drawer.GetGlyphCount())
					newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition)));

				MoveCursor(-1);
				SetText(newText);
				break;
			}

			case '\r':
			case '\n':
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyReturn(this, &ignoreDefaultAction);

				if (ignoreDefaultAction || !m_multiLineEnabled)
					break;

				Write(Nz::String('\n'));
				break;
			}

			default:
			{
				if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control)
					break;

				Write(Nz::String::Unicode(character));
				break;
			}
		}
	}

	void TextAreaWidget::RefreshCursor()
	{
		std::size_t lineCount = m_drawer.GetLineCount();
		std::size_t line = 0U;
		for (std::size_t i = line + 1; i < lineCount; ++i)
		{
			if (m_drawer.GetLine(i).glyphIndex > m_cursorPosition)
				break;

			line = i;
		}

		const auto& lineInfo = m_drawer.GetLine(line);

		std::size_t glyphCount = m_drawer.GetGlyphCount();
		float position;
		if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorPosition)
		{
			const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorPosition, glyphCount - 1));
			position = glyph.bounds.x;
			if (m_cursorPosition >= glyphCount)
				position += glyph.bounds.width;
		}
		else
			position = 0.f;

		Nz::Vector2f contentOrigin = GetContentOrigin();

		m_cursorEntity->GetComponent<NodeComponent>().SetPosition(contentOrigin.x + position, contentOrigin.y + lineInfo.bounds.y);
	}
}
<commit_msg>Sdk/TextAreaWidget: Make cursor sprite black<commit_after>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp

#include <NDK/Widgets/TextAreaWidget.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/World.hpp>
#include <limits>

namespace Ndk
{
	TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
	BaseWidget(parent),
	m_cursorPosition(0U),
	m_multiLineEnabled(false),
	m_readOnly(false)
	{
		m_cursorSprite = Nz::Sprite::New();
		m_cursorSprite->SetColor(Nz::Color::Black);
		m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));

		m_cursorEntity = CreateEntity();
		m_cursorEntity->AddComponent<GraphicsComponent>().Attach(m_cursorSprite, 10);
		m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
		m_cursorEntity->Enable(false);

		m_textSprite = Nz::TextSprite::New();

		m_textEntity = CreateEntity();
		m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
		m_textEntity->AddComponent<NodeComponent>().SetParent(this);

		SetCursor(Nz::SystemCursor_Text);

		Layout();
	}

	void TextAreaWidget::AppendText(const Nz::String& text)
	{
		m_drawer.AppendText(text);

		m_textSprite->Update(m_drawer);
	}

	std::size_t TextAreaWidget::GetHoveredGlyph(float x, float y) const
	{
		std::size_t glyphCount = m_drawer.GetGlyphCount();
		if (glyphCount > 0)
		{
			std::size_t lineCount = m_drawer.GetLineCount();
			std::size_t line = 0U;
			for (; line < lineCount - 1; ++line)
			{
				Nz::Rectf lineBounds = m_drawer.GetLine(line).bounds;
				if (lineBounds.GetMaximum().y > y)
					break;
			}

			std::size_t upperLimit = (line != lineCount - 1) ? m_drawer.GetLine(line + 1).glyphIndex : glyphCount + 1;

			std::size_t i = m_drawer.GetLine(line).glyphIndex;
			for (; i < upperLimit - 1; ++i)
			{
				Nz::Rectf bounds = m_drawer.GetGlyph(i).bounds;
				if (x < bounds.x + bounds.width * 0.75f)
					break;
			}

			return i;
		}

		return 0;
	}

	void TextAreaWidget::ResizeToContent()
	{
		SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
	}

	void TextAreaWidget::Write(const Nz::String& text)
	{
		if (m_cursorPosition >= m_drawer.GetGlyphCount())
		{
			AppendText(text);
			SetCursorPosition(m_drawer.GetGlyphCount());
		}
		else
		{
			Nz::String currentText = m_drawer.GetText();
			currentText.Insert(currentText.GetCharacterPosition(m_cursorPosition), text);
			SetText(currentText);

			SetCursorPosition(m_cursorPosition + text.GetLength());
		}
	}

	void TextAreaWidget::Layout()
	{
		BaseWidget::Layout();

		m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());

		RefreshCursor();
	}

	void TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
	{
		switch (key.code)
		{
			case Nz::Keyboard::Delete:
			{
				const Nz::String& text = m_drawer.GetText();

				Nz::String newText;
				if (m_cursorPosition > 0)
					newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition) - 1));

				if (m_cursorPosition < m_drawer.GetGlyphCount())
					newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition + 1)));

				m_drawer.SetText(newText);
				m_textSprite->Update(m_drawer);
				break;
			}

			case Nz::Keyboard::Down:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyDown(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				//TODO
				break;
			}

			case Nz::Keyboard::Left:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyLeft(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				MoveCursor(-1);
				break;
			}

			case Nz::Keyboard::Right:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyRight(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				MoveCursor(1);
				break;
			}

			case Nz::Keyboard::Up:
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyUp(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				//TODO
				break;
			}
		}
	}

	void TextAreaWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& key)
	{
	}

	void TextAreaWidget::OnMouseEnter()
	{
		m_cursorEntity->Enable(true);
	}

	void TextAreaWidget::OnMouseButtonPress(int x, int y, Nz::Mouse::Button button)
	{
		if (button == Nz::Mouse::Left)
		{
			GrabKeyboard();

			SetCursorPosition(GetHoveredGlyph(float(x), float(y)));
		}
	}

	void TextAreaWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY)
	{
	}

	void TextAreaWidget::OnMouseExit()
	{
		m_cursorEntity->Enable(false);
	}

	void TextAreaWidget::OnTextEntered(char32_t character, bool /*repeated*/)
	{
		if (m_readOnly)
			return;

		switch (character)
		{
			case '\b':
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyBackspace(this, &ignoreDefaultAction);

				if (ignoreDefaultAction)
					break;

				const Nz::String& text = m_drawer.GetText();

				Nz::String newText;
				if (m_cursorPosition > 1)
					newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition - 1) - 1));

				if (m_cursorPosition < m_drawer.GetGlyphCount())
					newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition)));

				MoveCursor(-1);
				SetText(newText);
				break;
			}

			case '\r':
			case '\n':
			{
				bool ignoreDefaultAction = false;
				OnTextAreaKeyReturn(this, &ignoreDefaultAction);

				if (ignoreDefaultAction || !m_multiLineEnabled)
					break;

				Write(Nz::String('\n'));
				break;
			}

			default:
			{
				if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control)
					break;

				Write(Nz::String::Unicode(character));
				break;
			}
		}
	}

	void TextAreaWidget::RefreshCursor()
	{
		std::size_t lineCount = m_drawer.GetLineCount();
		std::size_t line = 0U;
		for (std::size_t i = line + 1; i < lineCount; ++i)
		{
			if (m_drawer.GetLine(i).glyphIndex > m_cursorPosition)
				break;

			line = i;
		}

		const auto& lineInfo = m_drawer.GetLine(line);

		std::size_t glyphCount = m_drawer.GetGlyphCount();
		float position;
		if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorPosition)
		{
			const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorPosition, glyphCount - 1));
			position = glyph.bounds.x;
			if (m_cursorPosition >= glyphCount)
				position += glyph.bounds.width;
		}
		else
			position = 0.f;

		Nz::Vector2f contentOrigin = GetContentOrigin();

		m_cursorEntity->GetComponent<NodeComponent>().SetPosition(contentOrigin.x + position, contentOrigin.y + lineInfo.bounds.y);
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and University of
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <QtCore/QtDebug>
#include <QtGui/QFrame>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QComboBox>
#include <QtGui/QApplication>

#include "TaskWidget.h"
#include "qtUtilities.h"

#include "listviews.h"
#include "DataModelGUI.h"
#include "CQMessageBox.h"
#include "MyLineEdit.h"
#include "CProgressBar.h"
#include "copasiui3window.h"
#include "CQReportDefinitionSelect.h"
#include "DefaultplotDialog.h"
#include "CQTaskHeaderWidget.h"
#include "CQTaskMethodWidget.h"
#include "CQTaskBtnWidget.h"
#include "utilities/CCopasiTask.h"
#include "utilities/CCopasiMethod.h"
#include "utilities/CCopasiException.h"
#include "utilities/COutputHandler.h"
#include "utilities/CDirEntry.h"
#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "model/CModel.h"
#include "math/CMathContainer.h"
#include "report/CKeyFactory.h"
#include "UI/CQTaskThread.h"
#include "plotUI/CopasiPlot.h"
#include "plotUI/plotwindow.h"

/*
 *  Constructs a TaskWidget which is a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
TaskWidget::TaskWidget(QWidget* parent, const char* name, Qt::WFlags fl):
  CopasiWidget(parent, name, fl),
  mProgressBar(NULL),
  mpHeaderWidget(NULL),
  mpMethodWidget(NULL),
  mpBtnWidget(NULL),
  mpMethodLayout(NULL),
  mpSpacer1(NULL),
  mpSpacer2(NULL),
  mpTask(NULL),
  mpMethod(NULL),
  mChanged(false)
{
  if (!name)
    setObjectName("TaskWidget");

  setWindowTitle(trUtf8("TaskWidget"));

  mpTaskThread = new CQTaskThread(this);

  mpHeaderWidget = new CQTaskHeaderWidget(this);
  mpMethodWidget = new CQTaskMethodWidget(this);
  mpBtnWidget = new CQTaskBtnWidget(this);

  connect(mpBtnWidget->mpBtnRun, SIGNAL(clicked()), this, SLOT(runBtnClicked()));
  connect(mpBtnWidget->mpBtnRevert, SIGNAL(clicked()), this, SLOT(revertBtnClicked()));
  connect(mpBtnWidget->mpBtnReport, SIGNAL(clicked()), this, SLOT(reportBtnClicked()));
  connect(mpBtnWidget->mpBtnAssistant, SIGNAL(clicked()), this, SLOT(assistantBtnClicked()));

  connect(mpTaskThread, SIGNAL(finished()), this, SLOT(slotFinishThread()));
}

TaskWidget::~TaskWidget()
{
  pdelete(mpTaskThread);
}

void TaskWidget::revertBtnClicked()
{
  if (!mpTask) return;

  CCopasiMethod* pMethod = mpTask->getMethod();

  if (pMethod != mpMethod)
    {
      pdelete(mpMethod);
      mpMethod = pMethod;
    }

  loadTask();
}

void TaskWidget::runBtnClicked()
{
  // Assure that all edits to the current widget are committed.
  mpBtnWidget->mpBtnRun->setFocus();

  runTask();
}

void TaskWidget::reportBtnClicked()
{
  if (!mpTask) return;

  CQReportDefinitionSelect * pSelectDlg = new CQReportDefinitionSelect(mpListView);
  pSelectDlg->setReport(&mpTask->getReport());
  pSelectDlg->loadReportDefinitionVector();
  pSelectDlg->exec();

  delete pSelectDlg;
}

void TaskWidget::assistantBtnClicked()
{
  if (!mpTask) return;

  saveTask(); //this is necessary since the output may use information from the problem

  DefaultPlotDialog * pDlg = new DefaultPlotDialog(this);
  pDlg->setTask(mpTask);

  if (pDlg->exec() == QDialog::Accepted)
    {
      protectedNotify(ListViews::PLOT, ListViews::ADD, "");
    }

  if (pDlg)delete pDlg;
}

//************  executable button *******************

bool TaskWidget::loadCommon()
{
  if (!mpTask) return false;

  mpHeaderWidget->mpBoxExecutable->setChecked(mpTask->isScheduled());
  mpHeaderWidget->mpUpdateModel->setChecked(mpTask->isUpdateModel());

  mpHeaderWidget->saved();
  return true;
}

bool TaskWidget::saveCommon()
{
  if (!mpTask) return false;

  bool Value = mpHeaderWidget->mpBoxExecutable->isChecked();

  if (mpTask->isScheduled() != Value)
    {
      mpTask->setScheduled(Value);
      mChanged = true;
    }

  Value = mpHeaderWidget->mpUpdateModel->isChecked();

  if (mpTask->isUpdateModel() != Value)
    {
      mpTask->setUpdateModel(Value);
      mChanged = true;
    }

  mpHeaderWidget->saved();
  return true;
}

//************* parameter table ***********************

bool TaskWidget::loadMethod()
{
  if (!mpTask) return false;

  mpMethodWidget->setTask(mpTask);

  return mpMethodWidget->loadMethod();
}

void TaskWidget::adjustTable()
{
#ifdef DEBUG_UI
  qDebug() << "--> TaskWidget::adjustTable <--";
#endif

  // mpTblParameter->resizeColumnsToContents();
  // mpTblParameter->resizeRowsToContents();

  /*
  mpTblParameter->setFixedSize(mpTblParameter->columnWidth(0) + mpTblParameter->verticalHeader()->sizeHint().width() + 5,
                               mpTblParameter->verticalHeader()->sizeHint().height() * mpTblParameter->rowCount() + 5);
                               */
}

bool TaskWidget::saveMethod()
{
  if (!mpTask) return false;

  mChanged &= mpMethodWidget->saveMethod();

  return true;
}

bool TaskWidget::commonBeforeRunTask()
{
  // save the state of the widget
  if (!saveTask())
    {
      CQMessageBox::critical(this, "Simulation Error",
                             CCopasiMessage::getAllMessageText().c_str(),
                             QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
      return false;
    }

  if (!mpTask) return false;

  if (mProgressBar != NULL)
    {
      //CQMessageBox::critical(this, "Task in Progress",
      //                       "A task is currently running, another cannot be started before the current task ended.",
      //                       QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
      return false;
    }

  // if overwrite is enabled and the file exists, then ask
  if (!mpTask->getReport().getTarget().empty() &&
      mpTask->getReport().confirmOverwrite())
    {
      // The target might be a relative path
      std::string Target = mpTask->getReport().getTarget();

      if (CDirEntry::isRelativePath(Target) &&
          !CDirEntry::makePathAbsolute(Target, mpDataModel->getReferenceDirectory()))
        Target = CDirEntry::fileName(Target);

      if (CDirEntry::exist(Target) &&
          QMessageBox::question(this,
                                QString("Confirm Overwrite"),
                                QString("The report file already exists. Would you like to overwrite it? \n\n(You can disable this dialog by clicking the 'Report' button.)"),
                                QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
        return false;
    }

  //set mouse cursor
  setCursor(Qt::WaitCursor);

  //handle autosave feature
  CopasiUI3Window::getMainWindow()->autoSave();
  CopasiUI3Window::getMainWindow()->suspendAutoSave(true);

  //create progress bar
  mProgressBar = CProgressBar::create();
  mpTask->setCallBack(mProgressBar);

  CCopasiMessage::clearDeque();
  return true;
}

bool TaskWidget::commonAfterRunTask()
{
  if (!mpTask) return false;

  if (mProgressBar != NULL)
    {
      mProgressBar->finish();
      mProgressBar->deleteLater();
      mProgressBar = NULL;
    }

  mpTask->setCallBack(NULL);

  CCopasiMessage::clearDeque();

  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CCopasiRootContainer::getDatamodelList()->operator[](0).finish();

  // Update all values shown in the GUI
  CMathContainer * pContainer = mpTask->getMathContainer();

  pContainer->updateSimulatedValues(false);
  pContainer->updateTransientDataValues();
  pContainer->pushAllTransientValues();

  protectedNotify(ListViews::STATE, ListViews::CHANGE, pContainer->getModel().getKey());

  unsetCursor();
  CopasiUI3Window::getMainWindow()->suspendAutoSave(false);

  return loadTask();
}

bool TaskWidget::commonRunTask()
{
  // Initialize the task
  try
    {
      assert(CCopasiRootContainer::getDatamodelList()->size() > 0);

      if (!mpTask->initialize(CCopasiTask::OUTPUT_UI, &CCopasiRootContainer::getDatamodelList()->operator[](0), NULL))
        throw CCopasiException(CCopasiMessage::peekLastMessage());
    }

  catch (CCopasiException & /*Exception*/)
    {
      if (CCopasiMessage::peekLastMessage().getNumber() != MCCopasiMessage + 1)
        {
          if (mProgressBar != NULL) mProgressBar->finish();

          CQMessageBox::critical(this, "Initialization Error",
                                 CCopasiMessage::getAllMessageText().c_str(),
                                 QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);

          finishTask();
          return false;
        }
    }

  if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::ERROR)
    {
      if (mProgressBar != NULL) mProgressBar->finish();

      CQMessageBox::critical(this, "Initialization Error",
                             CCopasiMessage::getAllMessageText().c_str(),
                             QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);

      finishTask();
      return false;
    }

  if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::COMMANDLINE)
    {
      C_INT Result =
        CQMessageBox::question(this, "Initialization Warning",
                               CCopasiMessage::getAllMessageText().c_str(),
                               QMessageBox::Ignore | QMessageBox::Abort, QMessageBox::Ignore);

      if (Result == QMessageBox::Abort)
        {
          finishTask();
          return false;
        }
    }

  CCopasiMessage::clearDeque();

  // Execute the task
  mpTaskThread->start();

  return true;
}

void TaskWidget::slotFinishThread()
{
  if (!mpTaskThread->success() &&
      CCopasiMessage::size() != 0)
    {
      CQMessageBox::critical(this, "Calculation Error",
                             CCopasiMessage::getAllMessageText().c_str(),
                             QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
    }
  else if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::COMMANDLINE)
    {
      CQMessageBox::information(this, "Calculation Warning",
                                CCopasiMessage::getAllMessageText().c_str(),
                                QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
    }

  finishTask();
}

void TaskWidget::finishTask()
{
  CCopasiMessage::clearDeque();

  try {mpTask->restore();}

  catch (CCopasiException & /*Exception*/)
    {
      if (CCopasiMessage::peekLastMessage().getNumber() != MCCopasiMessage + 1)
        {
          if (mProgressBar != NULL) mProgressBar->finish();

          CQMessageBox::critical(this, "Calculation Error", CCopasiMessage::getAllMessageText().c_str(),
                                 QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
          CCopasiMessage::clearDeque();
        }
    }

  catch (...) {}

  if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::COMMANDLINE)
    {
      CQMessageBox::information(this, "Calculation Warning",
                                CCopasiMessage::getAllMessageText().c_str(),
                                QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
    }

  CCopasiMessage::clearDeque();

  commonAfterRunTask();

  taskFinishedEvent();
}

bool TaskWidget::taskFinishedEvent()
{
  return true;
}

CCopasiTask* TaskWidget::getTask()
{
  return mpTask;
}
//*********************************************************************

bool TaskWidget::update(ListViews::ObjectType objectType, ListViews::Action action, const std::string & C_UNUSED(key))
{
  if (mIgnoreUpdates || !isVisible())
    {
      return true;
    }

  switch (objectType)
    {
      case ListViews::MODEL:

        if (action == ListViews::ADD &&
            mpMethodWidget != NULL)
          {
            mpMethodWidget->clearHistory();
          }

        break;

      default:
        break;
    }

  return true;
}

bool TaskWidget::leave()
{
  return saveTask();
}

bool TaskWidget::enterProtected()
{
  mpTask = dynamic_cast< CCopasiTask * >(mpObject);

  // :TODO: We need a message here.
  if (!mpTask) return false;

  mpMethod = mpTask->getMethod();

  return loadTask();
}

CCopasiMethod * TaskWidget::createMethod(const CTaskEnum::Method & type)
{
  CCopasiMethod * pMethod = NULL;

  if (mpTask != NULL)
    {
      pMethod = mpTask->createMethod(type);
    }

  return pMethod;
}
<commit_msg>Bug 2495: The method history is  cleared when a new model is loaded.<commit_after>// Copyright (C) 2017 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and University of
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <QtCore/QtDebug>
#include <QtGui/QFrame>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QComboBox>
#include <QtGui/QApplication>

#include "TaskWidget.h"
#include "qtUtilities.h"

#include "listviews.h"
#include "DataModelGUI.h"
#include "CQMessageBox.h"
#include "MyLineEdit.h"
#include "CProgressBar.h"
#include "copasiui3window.h"
#include "CQReportDefinitionSelect.h"
#include "DefaultplotDialog.h"
#include "CQTaskHeaderWidget.h"
#include "CQTaskMethodWidget.h"
#include "CQTaskBtnWidget.h"
#include "utilities/CCopasiTask.h"
#include "utilities/CCopasiMethod.h"
#include "utilities/CCopasiException.h"
#include "utilities/COutputHandler.h"
#include "utilities/CDirEntry.h"
#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "model/CModel.h"
#include "math/CMathContainer.h"
#include "report/CKeyFactory.h"
#include "UI/CQTaskThread.h"
#include "plotUI/CopasiPlot.h"
#include "plotUI/plotwindow.h"

/*
 *  Constructs a TaskWidget which is a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
TaskWidget::TaskWidget(QWidget* parent, const char* name, Qt::WFlags fl):
  CopasiWidget(parent, name, fl),
  mProgressBar(NULL),
  mpHeaderWidget(NULL),
  mpMethodWidget(NULL),
  mpBtnWidget(NULL),
  mpMethodLayout(NULL),
  mpSpacer1(NULL),
  mpSpacer2(NULL),
  mpTask(NULL),
  mpMethod(NULL),
  mChanged(false)
{
  if (!name)
    setObjectName("TaskWidget");

  setWindowTitle(trUtf8("TaskWidget"));

  mpTaskThread = new CQTaskThread(this);

  mpHeaderWidget = new CQTaskHeaderWidget(this);
  mpMethodWidget = new CQTaskMethodWidget(this);
  mpBtnWidget = new CQTaskBtnWidget(this);

  connect(mpBtnWidget->mpBtnRun, SIGNAL(clicked()), this, SLOT(runBtnClicked()));
  connect(mpBtnWidget->mpBtnRevert, SIGNAL(clicked()), this, SLOT(revertBtnClicked()));
  connect(mpBtnWidget->mpBtnReport, SIGNAL(clicked()), this, SLOT(reportBtnClicked()));
  connect(mpBtnWidget->mpBtnAssistant, SIGNAL(clicked()), this, SLOT(assistantBtnClicked()));

  connect(mpTaskThread, SIGNAL(finished()), this, SLOT(slotFinishThread()));
}

TaskWidget::~TaskWidget()
{
  pdelete(mpTaskThread);
}

void TaskWidget::revertBtnClicked()
{
  if (!mpTask) return;

  CCopasiMethod* pMethod = mpTask->getMethod();

  if (pMethod != mpMethod)
    {
      pdelete(mpMethod);
      mpMethod = pMethod;
    }

  loadTask();
}

void TaskWidget::runBtnClicked()
{
  // Assure that all edits to the current widget are committed.
  mpBtnWidget->mpBtnRun->setFocus();

  runTask();
}

void TaskWidget::reportBtnClicked()
{
  if (!mpTask) return;

  CQReportDefinitionSelect * pSelectDlg = new CQReportDefinitionSelect(mpListView);
  pSelectDlg->setReport(&mpTask->getReport());
  pSelectDlg->loadReportDefinitionVector();
  pSelectDlg->exec();

  delete pSelectDlg;
}

void TaskWidget::assistantBtnClicked()
{
  if (!mpTask) return;

  saveTask(); //this is necessary since the output may use information from the problem

  DefaultPlotDialog * pDlg = new DefaultPlotDialog(this);
  pDlg->setTask(mpTask);

  if (pDlg->exec() == QDialog::Accepted)
    {
      protectedNotify(ListViews::PLOT, ListViews::ADD, "");
    }

  if (pDlg)delete pDlg;
}

//************  executable button *******************

bool TaskWidget::loadCommon()
{
  if (!mpTask) return false;

  mpHeaderWidget->mpBoxExecutable->setChecked(mpTask->isScheduled());
  mpHeaderWidget->mpUpdateModel->setChecked(mpTask->isUpdateModel());

  mpHeaderWidget->saved();
  return true;
}

bool TaskWidget::saveCommon()
{
  if (!mpTask) return false;

  bool Value = mpHeaderWidget->mpBoxExecutable->isChecked();

  if (mpTask->isScheduled() != Value)
    {
      mpTask->setScheduled(Value);
      mChanged = true;
    }

  Value = mpHeaderWidget->mpUpdateModel->isChecked();

  if (mpTask->isUpdateModel() != Value)
    {
      mpTask->setUpdateModel(Value);
      mChanged = true;
    }

  mpHeaderWidget->saved();
  return true;
}

//************* parameter table ***********************

bool TaskWidget::loadMethod()
{
  if (!mpTask) return false;

  mpMethodWidget->setTask(mpTask);

  return mpMethodWidget->loadMethod();
}

void TaskWidget::adjustTable()
{
#ifdef DEBUG_UI
  qDebug() << "--> TaskWidget::adjustTable <--";
#endif

  // mpTblParameter->resizeColumnsToContents();
  // mpTblParameter->resizeRowsToContents();

  /*
  mpTblParameter->setFixedSize(mpTblParameter->columnWidth(0) + mpTblParameter->verticalHeader()->sizeHint().width() + 5,
                               mpTblParameter->verticalHeader()->sizeHint().height() * mpTblParameter->rowCount() + 5);
                               */
}

bool TaskWidget::saveMethod()
{
  if (!mpTask) return false;

  mChanged &= mpMethodWidget->saveMethod();

  return true;
}

bool TaskWidget::commonBeforeRunTask()
{
  // save the state of the widget
  if (!saveTask())
    {
      CQMessageBox::critical(this, "Simulation Error",
                             CCopasiMessage::getAllMessageText().c_str(),
                             QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
      return false;
    }

  if (!mpTask) return false;

  if (mProgressBar != NULL)
    {
      //CQMessageBox::critical(this, "Task in Progress",
      //                       "A task is currently running, another cannot be started before the current task ended.",
      //                       QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
      return false;
    }

  // if overwrite is enabled and the file exists, then ask
  if (!mpTask->getReport().getTarget().empty() &&
      mpTask->getReport().confirmOverwrite())
    {
      // The target might be a relative path
      std::string Target = mpTask->getReport().getTarget();

      if (CDirEntry::isRelativePath(Target) &&
          !CDirEntry::makePathAbsolute(Target, mpDataModel->getReferenceDirectory()))
        Target = CDirEntry::fileName(Target);

      if (CDirEntry::exist(Target) &&
          QMessageBox::question(this,
                                QString("Confirm Overwrite"),
                                QString("The report file already exists. Would you like to overwrite it? \n\n(You can disable this dialog by clicking the 'Report' button.)"),
                                QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
        return false;
    }

  //set mouse cursor
  setCursor(Qt::WaitCursor);

  //handle autosave feature
  CopasiUI3Window::getMainWindow()->autoSave();
  CopasiUI3Window::getMainWindow()->suspendAutoSave(true);

  //create progress bar
  mProgressBar = CProgressBar::create();
  mpTask->setCallBack(mProgressBar);

  CCopasiMessage::clearDeque();
  return true;
}

bool TaskWidget::commonAfterRunTask()
{
  if (!mpTask) return false;

  if (mProgressBar != NULL)
    {
      mProgressBar->finish();
      mProgressBar->deleteLater();
      mProgressBar = NULL;
    }

  mpTask->setCallBack(NULL);

  CCopasiMessage::clearDeque();

  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CCopasiRootContainer::getDatamodelList()->operator[](0).finish();

  // Update all values shown in the GUI
  CMathContainer * pContainer = mpTask->getMathContainer();

  pContainer->updateSimulatedValues(false);
  pContainer->updateTransientDataValues();
  pContainer->pushAllTransientValues();

  protectedNotify(ListViews::STATE, ListViews::CHANGE, pContainer->getModel().getKey());

  unsetCursor();
  CopasiUI3Window::getMainWindow()->suspendAutoSave(false);

  return loadTask();
}

bool TaskWidget::commonRunTask()
{
  // Initialize the task
  try
    {
      assert(CCopasiRootContainer::getDatamodelList()->size() > 0);

      if (!mpTask->initialize(CCopasiTask::OUTPUT_UI, &CCopasiRootContainer::getDatamodelList()->operator[](0), NULL))
        throw CCopasiException(CCopasiMessage::peekLastMessage());
    }

  catch (CCopasiException & /*Exception*/)
    {
      if (CCopasiMessage::peekLastMessage().getNumber() != MCCopasiMessage + 1)
        {
          if (mProgressBar != NULL) mProgressBar->finish();

          CQMessageBox::critical(this, "Initialization Error",
                                 CCopasiMessage::getAllMessageText().c_str(),
                                 QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);

          finishTask();
          return false;
        }
    }

  if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::ERROR)
    {
      if (mProgressBar != NULL) mProgressBar->finish();

      CQMessageBox::critical(this, "Initialization Error",
                             CCopasiMessage::getAllMessageText().c_str(),
                             QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);

      finishTask();
      return false;
    }

  if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::COMMANDLINE)
    {
      C_INT Result =
        CQMessageBox::question(this, "Initialization Warning",
                               CCopasiMessage::getAllMessageText().c_str(),
                               QMessageBox::Ignore | QMessageBox::Abort, QMessageBox::Ignore);

      if (Result == QMessageBox::Abort)
        {
          finishTask();
          return false;
        }
    }

  CCopasiMessage::clearDeque();

  // Execute the task
  mpTaskThread->start();

  return true;
}

void TaskWidget::slotFinishThread()
{
  if (!mpTaskThread->success() &&
      CCopasiMessage::size() != 0)
    {
      CQMessageBox::critical(this, "Calculation Error",
                             CCopasiMessage::getAllMessageText().c_str(),
                             QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
    }
  else if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::COMMANDLINE)
    {
      CQMessageBox::information(this, "Calculation Warning",
                                CCopasiMessage::getAllMessageText().c_str(),
                                QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
    }

  finishTask();
}

void TaskWidget::finishTask()
{
  CCopasiMessage::clearDeque();

  try {mpTask->restore();}

  catch (CCopasiException & /*Exception*/)
    {
      if (CCopasiMessage::peekLastMessage().getNumber() != MCCopasiMessage + 1)
        {
          if (mProgressBar != NULL) mProgressBar->finish();

          CQMessageBox::critical(this, "Calculation Error", CCopasiMessage::getAllMessageText().c_str(),
                                 QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
          CCopasiMessage::clearDeque();
        }
    }

  catch (...) {}

  if (CCopasiMessage::getHighestSeverity() > CCopasiMessage::COMMANDLINE)
    {
      CQMessageBox::information(this, "Calculation Warning",
                                CCopasiMessage::getAllMessageText().c_str(),
                                QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
    }

  CCopasiMessage::clearDeque();

  commonAfterRunTask();

  taskFinishedEvent();
}

bool TaskWidget::taskFinishedEvent()
{
  return true;
}

CCopasiTask* TaskWidget::getTask()
{
  return mpTask;
}
//*********************************************************************

bool TaskWidget::update(ListViews::ObjectType objectType, ListViews::Action action, const std::string & C_UNUSED(key))
{
  if (mIgnoreUpdates)
    {
      return true;
    }

  switch (objectType)
    {
      case ListViews::MODEL:

        if (action == ListViews::ADD &&
            mpMethodWidget != NULL)
          {
            mpMethodWidget->clearHistory();
          }

        break;

      default:
        break;
    }

  return true;
}

bool TaskWidget::leave()
{
  return saveTask();
}

bool TaskWidget::enterProtected()
{
  mpTask = dynamic_cast< CCopasiTask * >(mpObject);

  // :TODO: We need a message here.
  if (!mpTask) return false;

  mpMethod = mpTask->getMethod();

  return loadTask();
}

CCopasiMethod * TaskWidget::createMethod(const CTaskEnum::Method & type)
{
  CCopasiMethod * pMethod = NULL;

  if (mpTask != NULL)
    {
      pMethod = mpTask->createMethod(type);
    }

  return pMethod;
}
<|endoftext|>


<commit_before>/*
    This file is part of KXForms.

    Copyright (c) 2005,2006 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "guihandlerdialogs.h"

#include "manager.h"

#include <kdebug.h>
#include <kmessagebox.h>
#include <klocale.h>

#include <QLabel>
#include <QVBoxLayout>
#include <QFrame>

using namespace KXForms;

FormDialog::FormDialog( QWidget *parent, const QString &title, Manager *m )
  : KDialog( parent, title, Ok ),
    mFormGui( 0 ), mManager( m )
{
  QFrame *topFrame = new QFrame( this );
  setMainWidget( topFrame );
  mTopLayout = new QVBoxLayout( topFrame );

  connect( this, SIGNAL( okClicked() ), SLOT( slotOk() ) );
}

void FormDialog::setGui( FormGui *gui )
{
  mTopLayout->addWidget( gui );
  mFormGui = gui;
}

void FormDialog::slotOk()
{
  kDebug() << "FormDialog::slotOk()" << endl;

  mFormGui->saveData();

  mManager->unregisterGui( mFormGui );

  accept();
}

GuiHandlerDialogs::GuiHandlerDialogs( Manager *m )
  : GuiHandler( m )
{
}

QWidget *GuiHandlerDialogs::createRootGui( QWidget *parent )
{
  kDebug() << "GuiHandlerDialogs::createRootGui()" << endl;

  Form *f = manager()->rootForm();

  if ( !f ) {
    KMessageBox::sorry( parent, i18n("Root form not found.") );
    return 0;
  }

  FormGui *gui = createGui( f, parent );

  gui->setRef( "/" + f->ref() );
  gui->parseElement( f->element() );

  if ( manager()->hasData() ) {
    kDebug() << "Manager::createGui() Load data on creation" << endl;
    manager()->loadData( gui );
  }

  return gui;
}

void GuiHandlerDialogs::createGui( const Reference &ref, QWidget *parent )
{
  kDebug() << "GuiHandlerDialogs::createGui() ref: '" << ref.toString() << "'" << endl;

  if ( ref.isEmpty() ) {
    KMessageBox::sorry( parent, i18n("No reference.") );
    return;
  }

  QString r = ref.segments().last().name();

  Form *f = manager()->form( r );

  if ( !f ) {
    KMessageBox::sorry( parent, i18n("Form '%1' not found.", ref.toString() ) );
    return;
  }

  FormDialog dlg( parent, i18n("Edit %1", ref.toString() ), manager() );

  FormGui *gui = createGui( f, dlg.mainWidget() );
  gui->setRef( ref );
  gui->parseElement( f->element() );

  if ( !gui ) {
    KMessageBox::sorry( parent, i18n("Unable to create GUI for '%1'.",
        ref.toString() ) );
    return;
  }

  dlg.setGui( gui );

  if ( manager()->hasData() ) {
    kDebug() << "Manager::createGui() Load data on creation" << endl;
    manager()->loadData( gui );
  }

  dlg.exec();
}

FormGui *GuiHandlerDialogs::createGui( Form *form, QWidget *parent )
{
  kDebug() << "Manager::createGui() form: '" << form->ref() << "'" << endl;

  if ( !form ) {
    kError() << "KXForms::Manager::createGui(): form is null." << endl;
    return 0;
  }

  FormGui *gui = new FormGui( form->label(), manager(), parent );
  if ( gui ) manager()->registerGui( gui );

  return gui;
}

#include "guihandlerdialogs.moc"
<commit_msg>fix crash (CID 1514)<commit_after>/*
    This file is part of KXForms.

    Copyright (c) 2005,2006 Cornelius Schumacher <schumacher@kde.org>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "guihandlerdialogs.h"

#include "manager.h"

#include <kdebug.h>
#include <kmessagebox.h>
#include <klocale.h>

#include <QLabel>
#include <QVBoxLayout>
#include <QFrame>

using namespace KXForms;

FormDialog::FormDialog( QWidget *parent, const QString &title, Manager *m )
  : KDialog( parent, title, Ok ),
    mFormGui( 0 ), mManager( m )
{
  QFrame *topFrame = new QFrame( this );
  setMainWidget( topFrame );
  mTopLayout = new QVBoxLayout( topFrame );

  connect( this, SIGNAL( okClicked() ), SLOT( slotOk() ) );
}

void FormDialog::setGui( FormGui *gui )
{
  mTopLayout->addWidget( gui );
  mFormGui = gui;
}

void FormDialog::slotOk()
{
  kDebug() << "FormDialog::slotOk()" << endl;

  mFormGui->saveData();

  mManager->unregisterGui( mFormGui );

  accept();
}

GuiHandlerDialogs::GuiHandlerDialogs( Manager *m )
  : GuiHandler( m )
{
}

QWidget *GuiHandlerDialogs::createRootGui( QWidget *parent )
{
  kDebug() << "GuiHandlerDialogs::createRootGui()" << endl;

  Form *f = manager()->rootForm();

  if ( !f ) {
    KMessageBox::sorry( parent, i18n("Root form not found.") );
    return 0;
  }

  FormGui *gui = createGui( f, parent );

  gui->setRef( "/" + f->ref() );
  gui->parseElement( f->element() );

  if ( manager()->hasData() ) {
    kDebug() << "Manager::createGui() Load data on creation" << endl;
    manager()->loadData( gui );
  }

  return gui;
}

void GuiHandlerDialogs::createGui( const Reference &ref, QWidget *parent )
{
  kDebug() << "GuiHandlerDialogs::createGui() ref: '" << ref.toString() << "'" << endl;

  if ( ref.isEmpty() ) {
    KMessageBox::sorry( parent, i18n("No reference.") );
    return;
  }

  QString r = ref.segments().last().name();

  Form *f = manager()->form( r );

  if ( !f ) {
    KMessageBox::sorry( parent, i18n("Form '%1' not found.", ref.toString() ) );
    return;
  }

  FormDialog dlg( parent, i18n("Edit %1", ref.toString() ), manager() );

  FormGui *gui = createGui( f, dlg.mainWidget() );
  if ( !gui ) {
    KMessageBox::sorry( parent, i18n("Unable to create GUI for '%1'.",
        ref.toString() ) );
    return;
  }

  gui->setRef( ref );
  gui->parseElement( f->element() );

  dlg.setGui( gui );

  if ( manager()->hasData() ) {
    kDebug() << "Manager::createGui() Load data on creation" << endl;
    manager()->loadData( gui );
  }

  dlg.exec();
}

FormGui *GuiHandlerDialogs::createGui( Form *form, QWidget *parent )
{
  kDebug() << "Manager::createGui() form: '" << form->ref() << "'" << endl;

  if ( !form ) {
    kError() << "KXForms::Manager::createGui(): form is null." << endl;
    return 0;
  }

  FormGui *gui = new FormGui( form->label(), manager(), parent );
  if ( gui ) manager()->registerGui( gui );

  return gui;
}

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


<commit_before>#pragma once

#include "../result_wrapper.hpp"
#include "../tags/Logic.hpp"

#include <cuddObj.hh>

namespace metaSMT {
  namespace solver {
    #ifndef _CPPCUDD
    typedef std::vector<BDD> BDDvector;
    #endif

    namespace predtags = ::metaSMT::logic::tag;

    class CUDD_Context
    {
      struct CUDDAssertion : public std::runtime_error {
        CUDDAssertion(const char* what)
          : std::runtime_error(what) {}
      };

      static void _cudd_error(std::string what) {
        throw CUDDAssertion(what.c_str());
      }

      public:

        CUDD_Context ()
        {
          _manager.setHandler(&CUDD_Context::_cudd_error);
          _manager.AutodynEnable(CUDD_REORDER_SIFT);
          _assertions  = _manager.bddOne();
          _assumptions = _manager.bddOne();
        }

        typedef BDD result_type;

        void assertion( result_type e ) {
          _assertions &= e;
        }

        void assumption( result_type e ) {
          _assumptions &= e;
        }

        void writeDotFile(std::string const & filename)
        {
#ifdef _CPPCUDD
          BDDvector bvec (3, &_manager, NULL);
          bvec[0] = _assertions & _assumptions;
          bvec[1] = _assertions;
          bvec[2] = _assumptions;
#else
          BDDvector bvec;
          bvec.push_back(_assertions & _assumptions);
          bvec.push_back(_assertions);
          bvec.push_back(_assumptions);
#endif
          char comple[] = "complete";
          char assert[] = "assertions";
          char assume[] = "assumptions";
          char *names[]={ comple, assert, assume };
          FILE* fp = fopen(filename.c_str(), "w");
#ifdef _CPPCUDD
          bvec.DumpDot(0, names, fp);
#else
          _manager.DumpDot(bvec, 0, names, fp);
#endif
          fclose(fp);
        }

        bool solve() {
          _solution.clear();
          BDD complete =_assertions & _assumptions;
          bool  ret =  complete != _manager.bddZero();
          _assumptions = _manager.bddOne();
          if(ret) {
            unsigned size = _manager.ReadSize();
            char *buf = new char[size];
            complete.PickOneCube(buf);
            _solution.resize(size);
            for (unsigned i = 0; i < size; ++i) {
              if( buf[i] == 2) {
                _solution[i] = boost::logic::indeterminate;
              } else {
                _solution[i] =  buf[i];
              }
            }
            delete[] buf;
          }
          return ret;
        }

        result_wrapper read_value(result_type var)
        {
          assert( var.NodeReadIndex() < _solution.size() );
          return result_wrapper( _solution[var.NodeReadIndex()] );
        }

        result_type operator() (predtags::var_tag const & , boost::any )
        {
          return _manager.bddVar();
        }

        result_type operator() (predtags::false_tag , boost::any ) {
          return _manager.bddZero();
        }

        result_type operator() (predtags::true_tag , boost::any ) {
          return _manager.bddOne();
        }

        result_type operator() (predtags::not_tag , result_type a) {
          return !a ;
        }

        result_type operator() (predtags::equal_tag , result_type a, result_type b) {
          return !(a ^ b);
        }

        result_type operator() (predtags::nequal_tag , result_type a, result_type b) {
          return a ^ b;
        }

        result_type operator() (predtags::and_tag , result_type a, result_type b) {
          return a & b;
        }

        result_type operator() (predtags::nand_tag , result_type a, result_type b) {
          return !(a & b);
        }

        result_type operator() (predtags::xor_tag , result_type a, result_type b) {
          return a ^ b;
        }

        result_type operator() (predtags::xnor_tag , result_type a, result_type b) {
         return  !(a ^ b);
        }

        result_type operator() (predtags::implies_tag , result_type a, result_type b) {
          return !a | b;
        }

        result_type operator() (predtags::or_tag , result_type a, result_type b) {
          return a | b;
        }

        result_type operator() (predtags::nor_tag , result_type a, result_type b) {
          return !(a | b);
        }

        result_type operator() (predtags::distinct_tag , result_type a, result_type b) {
          return a ^ b;
        }

        result_type operator() (predtags::ite_tag
            , result_type a, result_type b, result_type c
        ) {
          return a.Ite(b,c);
        }

        ////////////////////////
        // Fallback operators //
        ////////////////////////

        template <typename TagT>
        result_type operator() (TagT , boost::any ) {
          assert(false && "fallback op0 called");
          return _manager.bddZero();
        }

        template <typename TagT>
        result_type operator() (TagT , result_type ) {
          assert(false && "fallback op1 called");
          return _manager.bddZero();
        }

        template <typename TagT, typename T1, typename T2>
        result_type operator() (TagT , T1 , T2 ) {
          assert(false && "fallback op2 called");
          return _manager.bddZero();
        }

        template <typename TagT, typename T1, typename T2, typename T3>
        result_type operator() (TagT , T1 , T2 , T3 ) {
          assert(false && "fallback op3 called");
          return _manager.bddZero();
        }

      /* pseudo command */
      void command ( CUDD_Context const & ) { };

      protected:
        Cudd _manager;
        BDD _assertions;
        BDD _assumptions;
        std::vector< boost::logic::tribool> _solution;
    };

  } // namespace solver
} // namespace metaSMT

//  vim: ft=cpp:ts=2:sw=2:expandtab
<commit_msg>small improvement CUDD_Context::writeDotFile<commit_after>#pragma once

#include "../result_wrapper.hpp"
#include "../tags/Logic.hpp"

#include <cuddObj.hh>

namespace metaSMT {
  namespace solver {
    namespace predtags = ::metaSMT::logic::tag;

    class CUDD_Context
    {
      struct CUDDAssertion : public std::runtime_error {
        CUDDAssertion(const char* what)
          : std::runtime_error(what) {}
      };

      static void _cudd_error(std::string what) {
        throw CUDDAssertion(what.c_str());
      }

      public:

        CUDD_Context ()
        {
          _manager.setHandler(&CUDD_Context::_cudd_error);
          _manager.AutodynEnable(CUDD_REORDER_SIFT);
          _assertions  = _manager.bddOne();
          _assumptions = _manager.bddOne();
        }

        typedef BDD result_type;

        void assertion( result_type e ) {
          _assertions &= e;
        }

        void assumption( result_type e ) {
          _assumptions &= e;
        }

        void writeDotFile(std::string const & filename)
        {
#ifdef _CPPCUDD // this is defined in CUDD 2.4.x but not in 3.0.0
          BDDvector bvec (3, &_manager, NULL);
#else
          std::vector<BDD> bvec (3, _manager.bddOne());
#endif
          bvec[0] = _assertions & _assumptions;
          bvec[1] = _assertions;
          bvec[2] = _assumptions;
          char comple[] = "complete";
          char assert[] = "assertions";
          char assume[] = "assumptions";
          char *names[]={ comple, assert, assume };
          FILE* fp = fopen(filename.c_str(), "w");
#ifdef _CPPCUDD
          bvec.DumpDot(0, names, fp);
#else
          _manager.DumpDot(bvec, 0, names, fp);
#endif
          fclose(fp);
        }

        bool solve() {
          _solution.clear();
          BDD complete =_assertions & _assumptions;
          bool  ret =  complete != _manager.bddZero();
          _assumptions = _manager.bddOne();
          if(ret) {
            unsigned size = _manager.ReadSize();
            char *buf = new char[size];
            complete.PickOneCube(buf);
            _solution.resize(size);
            for (unsigned i = 0; i < size; ++i) {
              if( buf[i] == 2) {
                _solution[i] = boost::logic::indeterminate;
              } else {
                _solution[i] =  buf[i];
              }
            }
            delete[] buf;
          }
          return ret;
        }

        result_wrapper read_value(result_type var)
        {
          assert( var.NodeReadIndex() < _solution.size() );
          return result_wrapper( _solution[var.NodeReadIndex()] );
        }

        result_type operator() (predtags::var_tag const & , boost::any )
        {
          return _manager.bddVar();
        }

        result_type operator() (predtags::false_tag , boost::any ) {
          return _manager.bddZero();
        }

        result_type operator() (predtags::true_tag , boost::any ) {
          return _manager.bddOne();
        }

        result_type operator() (predtags::not_tag , result_type a) {
          return !a ;
        }

        result_type operator() (predtags::equal_tag , result_type a, result_type b) {
          return !(a ^ b);
        }

        result_type operator() (predtags::nequal_tag , result_type a, result_type b) {
          return a ^ b;
        }

        result_type operator() (predtags::and_tag , result_type a, result_type b) {
          return a & b;
        }

        result_type operator() (predtags::nand_tag , result_type a, result_type b) {
          return !(a & b);
        }

        result_type operator() (predtags::xor_tag , result_type a, result_type b) {
          return a ^ b;
        }

        result_type operator() (predtags::xnor_tag , result_type a, result_type b) {
         return  !(a ^ b);
        }

        result_type operator() (predtags::implies_tag , result_type a, result_type b) {
          return !a | b;
        }

        result_type operator() (predtags::or_tag , result_type a, result_type b) {
          return a | b;
        }

        result_type operator() (predtags::nor_tag , result_type a, result_type b) {
          return !(a | b);
        }

        result_type operator() (predtags::distinct_tag , result_type a, result_type b) {
          return a ^ b;
        }

        result_type operator() (predtags::ite_tag
            , result_type a, result_type b, result_type c
        ) {
          return a.Ite(b,c);
        }

        ////////////////////////
        // Fallback operators //
        ////////////////////////

        template <typename TagT>
        result_type operator() (TagT , boost::any ) {
          assert(false && "fallback op0 called");
          return _manager.bddZero();
        }

        template <typename TagT>
        result_type operator() (TagT , result_type ) {
          assert(false && "fallback op1 called");
          return _manager.bddZero();
        }

        template <typename TagT, typename T1, typename T2>
        result_type operator() (TagT , T1 , T2 ) {
          assert(false && "fallback op2 called");
          return _manager.bddZero();
        }

        template <typename TagT, typename T1, typename T2, typename T3>
        result_type operator() (TagT , T1 , T2 , T3 ) {
          assert(false && "fallback op3 called");
          return _manager.bddZero();
        }

      /* pseudo command */
      void command ( CUDD_Context const & ) { };

      protected:
        Cudd _manager;
        BDD _assertions;
        BDD _assumptions;
        std::vector< boost::logic::tribool> _solution;
    };

  } // namespace solver
} // namespace metaSMT

//  vim: ft=cpp:ts=2:sw=2:expandtab
<|endoftext|>


<commit_before>/* Copyright 2010 Jukka Jylnki

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

/** @file FileTransfer.cpp
	@brief Implements a file transfer application. The server acts as a receiver waiting for a
	       client to connect and send a file. */

#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
#include <utility>

#include "kNet.h"
#include "kNet/DebugMemoryLeakCheck.h"

// If enabled, this sample is used for network transfer profiling and all disk operations are ignored.
//#define NULLTRANSFER

using namespace std;
using namespace kNet;

const unsigned long cFileTransferStartMessage = 30;
const unsigned long cFileTransferFragment = 31;

#ifdef LINUX
#define _stricmp strcasecmp
#endif

struct Fragment
{
	std::vector<char> data;
	size_t fragmentIndex;
};

class NetworkApp : public IMessageHandler, public INetworkServerListener
{
	Network network;

	// Used by the receiver to store partial received data.
	std::map<size_t, Fragment> fragments;

	size_t nextFragment;
	size_t totalFragments;
	size_t bytesReceived;
	std::ofstream out;
	tick_t transferStartTick;

	PolledTimer statsPrintTimer;
	static const int printIntervalMSecs = 4000;
public:

	/// Called to notify the listener that a new connection has been established.
	void NewConnectionEstablished(MessageConnection *connection)
	{
		connection->RegisterInboundMessageHandler(this);
	}

	void HandleMessage(MessageConnection *source, message_id_t id, const char *data, size_t numBytes)
	{
		switch(id)
		{
		case cFileTransferStartMessage:
		{
			DataDeserializer dd(data, numBytes);
			std::string filename = dd.ReadString();
			size_t fileSize = dd.Read<u32>();
			totalFragments = dd.Read<u32>();
			nextFragment = 0;
			bytesReceived = 0;
			statsPrintTimer.StartMSecs(printIntervalMSecs);
			cout << "Starting receive of file \"" << filename << "\". File size: " << fileSize << "B, which is split into "
				<< totalFragments << " fragments." << endl;
			char str[256];
			sprintf(str, "received_%s", filename.c_str());
			out.open(str, ios::binary | ios::trunc);
			transferStartTick = Clock::Tick();
			break;
		}
		case cFileTransferFragment:
		{
			DataDeserializer dd(data, numBytes);
			size_t fragmentIndex = dd.Read<u32>();
			if (nextFragment == fragmentIndex)
			{
				++nextFragment;
				size_t numDataBytes = dd.BytesLeft();
#ifndef NULLTRANSFER
				out.write(data + dd.BytePos(), numDataBytes);
#endif
				bytesReceived += numDataBytes;
				WriteFinishedFragments();

				LOG(LogVerbose, "Received fragment %d.", fragmentIndex);

				if (statsPrintTimer.Test())
				{
					const tick_t sendFinishTick = Clock::Tick();
					double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
					LOG(LogUser, "Received fragment %d. Elapsed: %.2f seconds. Bytes received: %d. Transfer rate: %s/sec.",
						nextFragment-1, (float)timespan, bytesReceived, FormatBytes((size_t)(bytesReceived/timespan)).c_str());
					statsPrintTimer.StartMSecs(printIntervalMSecs);
				}

			}
			else // Queue up this fragment.
			{
//				cout << "Queued up received fragment " << fragmentIndex << endl;
				Fragment f;
				size_t numDataBytes = dd.BytesLeft();
#ifndef NULLTRANSFER
				f.data.insert(f.data.end(), data + dd.BytePos(), data + numBytes);
#endif
				f.fragmentIndex = fragmentIndex;
				fragments[fragmentIndex] = f;
				bytesReceived += numDataBytes;
			}
			break;
		}
		default:
			cout << "Received an unknown message with ID 0x" << std::hex << id << "!" << endl;
			break;
		}
	}

	void WriteFinishedFragments()
	{
		std::map<size_t, Fragment>::iterator iter = fragments.find(nextFragment);
		while(iter != fragments.end())
		{
#ifndef NULLTRANSFER
			out.write(&iter->second.data[0], iter->second.data.size());
#endif
			fragments.erase(nextFragment);
			++nextFragment;
			iter = fragments.find(nextFragment);
		}
	}

	void RunReceiver(unsigned short port, SocketTransportLayer transport)
	{
		nextFragment = 0;
		totalFragments = 0xFFFFFFFF;

		// Start the server either in TCP or UDP mode.
		NetworkServer *server = network.StartServer(port, transport, this);
		if (!server)
		{
			cout << "Unable to start server in port " << port << "!" << endl;
			return;
		}

		cout << "Server waiting for connection in port " << port << "." << endl;

		while(server->GetConnections().size() == 0)
		{
			server->Process();
			Clock::Sleep(2000);
		}

		Ptr(MessageConnection) clientConnection = server->GetConnections().begin()->second;

		// Stop accepting any further connections.
		server->SetAcceptNewConnections(false);

		clientConnection->WaitToEstablishConnection(10000);

		statsPrintTimer.StartMSecs(printIntervalMSecs);

		transferStartTick = Clock::Tick();

		LOG(LogUser, "Waiting for file receive.");
		while(clientConnection->IsReadOpen())
		{
			server->Process();

			Clock::Sleep(1);
			if (statsPrintTimer.Test())
			{
				const tick_t sendFinishTick = Clock::Tick();
				double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
				LOG(LogUser, "Have received fragment %d. Elapsed: %.2f seconds. Bytes received: %d. Transfer rate: %s/sec.",
					nextFragment-1, (float)timespan, bytesReceived, FormatBytes((size_t)(bytesReceived/timespan)).c_str());
				clientConnection->DumpStatus();
				statsPrintTimer.StartMSecs(printIntervalMSecs);
			}
		}
		LOG(LogUser, "Finished file receive. Closing connection.");
		clientConnection->Close(15000);
	}

	void RunSender(const char *address, unsigned short port, SocketTransportLayer transport, const char *filename)
	{
		FILE *handle = fopen(filename, "rb");
		if (!handle)
		{
			LOG(LogUser, "Failed to open file %s!", filename);
			return;
		}
		fseek(handle, 0, SEEK_END);
		long fileSize = ftell(handle);
		if (fileSize <= 0)
		{
			fclose(handle);
			LOG(LogUser, "File %s has zero size!", filename);
			return;
		}

		fseek(handle, 0, SEEK_SET);
		std::vector<char> tempData;

		Ptr(MessageConnection) connection = network.Connect(address, port, transport, this);
		if (!connection)
		{
			cout << "Unable to connect to " << address << ":" << port << "." << endl;
			return;
		}

		// We have nothing better to do while waiting for the connection to build up, so wait modally.
		if (!connection->WaitToEstablishConnection(10000))
		{
			cout << "Failed to connect to server!" << endl;
			return;
		}

		cout << "Connected to " << connection->GetSocket()->ToString() << "." << endl;

		transferStartTick = Clock::Tick();

		NetworkMessage *msg = connection->StartNewMessage(cFileTransferStartMessage, 2048);
		DataSerializer ds(msg->data, 2048);
		const size_t fragmentSize = 450;
		const size_t numFragments = (fileSize + fragmentSize - 1) / fragmentSize;
		ds.AddString(filename);
		ds.Add<u32>(fileSize);
		ds.Add<u32>(numFragments);
		msg->priority = 100;
		msg->reliable = true;
		msg->inOrder = true;
		connection->EndAndQueueMessage(msg, ds.BytesFilled());

		size_t nextFragment = 0;
		size_t bytesSent = 0;

		LOG(LogUser, "Starting file transfer. File size: %dB, number of fragments: %d.",
			fileSize, numFragments);
		statsPrintTimer.StartMSecs(printIntervalMSecs);

		while(connection->IsWriteOpen())
		{
			connection->Process();

			// Add new data fragments into the queue.
			const int outboundMsgQueueSize = 200;
			int i = 100;
			while(i-- > 0 && connection->IsWriteOpen() && connection->NumOutboundMessagesPending() < outboundMsgQueueSize && bytesSent < fileSize)
			{
				// File payload data bytes in this message.
				const size_t bytesInThisFragment = min((int)fragmentSize, (int)(fileSize - bytesSent));

				NetworkMessage *msg = connection->StartNewMessage(cFileTransferFragment, bytesInThisFragment+4);
				msg->priority = 100;
				msg->reliable = true;
				msg->inOrder = true;

				DataSerializer ds(msg->data, msg->Size());
				ds.Add<u32>(nextFragment++);

#ifndef NULLTRANSFER
				size_t read = fread(ds.GetData() + ds.BytesFilled(), sizeof(char), bytesInThisFragment, handle);
#else
				size_t read = bytesInThisFragment;
#endif
				if (read < bytesInThisFragment)
				{
					LOG(LogUser, "Failed to read file!");
					connection->Close(0);
				}

				connection->EndAndQueueMessage(msg);
				bytesSent += bytesInThisFragment;
			}

			// If we've put out all file fragments to the network, close the connection down.
			if (connection->IsWriteOpen() && bytesSent >= fileSize && connection->NumOutboundMessagesPending() == 0)
			{
				LOG(LogUser, "All data sent. Disconnecting.");
				connection->Disconnect(15000);
			}

			if (statsPrintTimer.Test())
			{
				const tick_t sendFinishTick = Clock::Tick();
				double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
				LOG(LogUser, "Sending fragment %d. Elapsed: %.2f seconds. Bytes sent: %d. Transfer rate: %s/sec.",
					nextFragment-1, (float)timespan, bytesSent, FormatBytes((size_t)(bytesSent/timespan)).c_str());
				connection->DumpStatus();
				statsPrintTimer.StartMSecs(printIntervalMSecs);
			}
		}

		LOG(LogUser, "Waiting for peer to acknowledge all received data.");
		while((connection->NumOutboundMessagesPending() > 0 && connection->IsWriteOpen()) || connection->IsReadOpen())
		{
			connection->Process();
			Clock::Sleep(1);

			if (statsPrintTimer.TriggeredOrNotRunning())
			{
				connection->DumpStatus();
				statsPrintTimer.StartMSecs(printIntervalMSecs);
			}
		}

		const tick_t sendFinishTick = Clock::Tick();
		double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
		connection->DumpStatus();
		LOG(LogUser, "File transfer finished in %.2f seconds. Bytes sent: %d. Transfer rate: %s/sec. Closing connection.",
			(float)timespan, bytesSent, FormatBytes((size_t)(bytesSent/timespan)).c_str());

		connection->Close(15000);
		fclose(handle);
	}
};

void PrintUsage()
{
	cout << "Usage: " << endl;
	cout << "       receive tcp|udp <port>" << endl;
	cout << "       send tcp|udp <hostname> <port> <filename>" << endl;
}

int main(int argc, char **argv)
{
	if (argc < 4)
	{
		PrintUsage();
		return 0;
	}

	EnableMemoryLeakLoggingAtExit();

//	kNet::SetLogChannels((LogChannel)(-1) & ~(LogObjectAlloc | LogVerbose)); // Enable all log channels.
	kNet::SetLogChannels(LogUser | LogInfo | LogError);

	SocketTransportLayer transport = SocketOverUDP;
	if (!_stricmp(argv[2], "tcp"))
		transport = SocketOverTCP;
	else if (!!_stricmp(argv[2], "udp"))
	{
		cout << "The second parameter is either 'tcp' or 'udp'!" << endl;
		return 0;
	}
	NetworkApp app;
	if (!_stricmp(argv[1], "receive"))
	{
		unsigned short port = atoi(argv[3]);

		app.RunReceiver(port, transport);
	}
	else if (!_stricmp(argv[1], "send"))
	{
		if (argc < 6)
		{
			PrintUsage();
			return 0;
		}

		unsigned short port = atoi(argv[4]);
		app.RunSender(argv[3], port, transport, argv[5]);
	}
	else
	{
		cout << "The second parameter is either 'send' or 'receive'!" << endl;
		return 0;
	}
}
<commit_msg>Tuned the FileTransfer sample.<commit_after>/* Copyright 2010 Jukka Jylnki

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

/** @file FileTransfer.cpp
	@brief Implements a file transfer application. The server acts as a receiver waiting for a
	       client to connect and send a file. */

#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
#include <utility>

#include "kNet.h"
#include "kNet/DebugMemoryLeakCheck.h"

// If enabled, this sample is used for network transfer profiling and all disk operations are ignored.
//#define NULLTRANSFER

using namespace std;
using namespace kNet;

const unsigned long cFileTransferStartMessage = 30;
const unsigned long cFileTransferFragment = 31;

#ifdef LINUX
#define _stricmp strcasecmp
#endif

struct Fragment
{
	std::vector<char> data;
	size_t fragmentIndex;
};

class NetworkApp : public IMessageHandler, public INetworkServerListener
{
	Network network;

	// Used by the receiver to store partial received data.
	std::map<size_t, Fragment> fragments;

	size_t nextFragment;
	size_t totalFragments;
	size_t bytesReceived;
	std::string filename;
	std::ofstream out;
	tick_t transferStartTick;

	PolledTimer statsPrintTimer;
	static const int printIntervalMSecs = 4000;
public:

	NetworkApp()
	:nextFragment(0),
	totalFragments(0),
	bytesReceived(0)
	{
	}
	/// Called to notify the listener that a new connection has been established.
	void NewConnectionEstablished(MessageConnection *connection)
	{
		connection->RegisterInboundMessageHandler(this);
	}

	void HandleMessage(MessageConnection *source, message_id_t id, const char *data, size_t numBytes)
	{
		switch(id)
		{
		case cFileTransferStartMessage:
		{
			DataDeserializer dd(data, numBytes);
			filename = dd.ReadString();
			size_t fileSize = dd.Read<u32>();
			totalFragments = dd.Read<u32>();
			nextFragment = 0;
			bytesReceived = 0;
			statsPrintTimer.StartMSecs(printIntervalMSecs);
			cout << "Starting receive of file \"" << filename << "\". File size: " << fileSize << "B bytes, which is split into "
				<< totalFragments << " fragments." << endl;
			char str[256];
			sprintf(str, "received_%s", filename.c_str());
			out.open(str, ios::binary | ios::trunc);
			transferStartTick = Clock::Tick();
			break;
		}
		case cFileTransferFragment:
		{
			DataDeserializer dd(data, numBytes);
			size_t fragmentIndex = dd.Read<u32>();
			if (nextFragment == fragmentIndex)
			{
				++nextFragment;
				size_t numDataBytes = dd.BytesLeft();
#ifndef NULLTRANSFER
				out.write(data + dd.BytePos(), numDataBytes);
#endif
				bytesReceived += numDataBytes;
				WriteFinishedFragments();

				LOG(LogVerbose, "Received fragment %d.", fragmentIndex);

				if (statsPrintTimer.Test())
				{
					const tick_t sendFinishTick = Clock::Tick();
					double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
					LOG(LogUser, "Received fragment %d. Elapsed: %.2f seconds. Bytes received: %d. Transfer rate: %s/sec.",
						nextFragment-1, (float)timespan, bytesReceived, FormatBytes((size_t)(bytesReceived/timespan)).c_str());
					statsPrintTimer.StartMSecs(printIntervalMSecs);
				}

			}
			else // Queue up this fragment.
			{
//				cout << "Queued up received fragment " << fragmentIndex << endl;
				Fragment f;
				size_t numDataBytes = dd.BytesLeft();
#ifndef NULLTRANSFER
				f.data.insert(f.data.end(), data + dd.BytePos(), data + numBytes);
#endif
				f.fragmentIndex = fragmentIndex;
				fragments[fragmentIndex] = f;
				bytesReceived += numDataBytes;
			}
			break;
		}
		default:
			cout << "Received an unknown message with ID 0x" << std::hex << id << "!" << endl;
			break;
		}
	}

	void WriteFinishedFragments()
	{
		std::map<size_t, Fragment>::iterator iter = fragments.find(nextFragment);
		while(iter != fragments.end())
		{
#ifndef NULLTRANSFER
			out.write(&iter->second.data[0], iter->second.data.size());
#endif
			fragments.erase(nextFragment);
			++nextFragment;
			iter = fragments.find(nextFragment);
		}
	}

	void RunReceiver(unsigned short port, SocketTransportLayer transport)
	{
		nextFragment = 0;
		totalFragments = 0xFFFFFFFF;

		// Start the server either in TCP or UDP mode.
		NetworkServer *server = network.StartServer(port, transport, this);
		if (!server)
		{
			cout << "Unable to start server in port " << port << "!" << endl;
			return;
		}

		cout << "Server waiting for connection in port " << port << "." << endl;

		while(server->GetConnections().size() == 0)
		{
			server->Process();
			Clock::Sleep(1);
		}

		Ptr(MessageConnection) clientConnection = server->GetConnections().begin()->second;

		// Stop accepting any further connections.
		server->SetAcceptNewConnections(false);

		clientConnection->WaitToEstablishConnection(10000);

		statsPrintTimer.StartMSecs(printIntervalMSecs);

		transferStartTick = Clock::Tick();

		LOG(LogUser, "Waiting for file receive.");
		while(clientConnection->IsReadOpen())
		{
			server->Process();

			Clock::Sleep(1);
			if (statsPrintTimer.Test())
			{
				const tick_t sendFinishTick = Clock::Tick();
				double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
				LOG(LogUser, "Have received %d fragments (+%d out-of-order) (%.2f%%). Elapsed: %.2f seconds. Bytes received: %d. Transfer rate: %s/sec.",
					nextFragment, fragments.size(), (nextFragment + fragments.size()) * 100.f / totalFragments,
					(float)timespan, bytesReceived, FormatBytes((size_t)(bytesReceived/timespan)).c_str());
				clientConnection->DumpStatus();
				statsPrintTimer.StartMSecs(printIntervalMSecs);
			}
		}
		if (nextFragment == totalFragments)
		{
			LOG(LogUser, "Finished receiving all fragments. File '%s' saved to disk, size: %d bytes. Closing connection.",
				filename.c_str(), bytesReceived);
		}
		else
		{
			LOG(LogUser, "Error: Sender specified the file '%s' to contain %d fragments, but the connection was closed after "
				"receiving %d fragments. Received a partial file of %d bytes.", filename.c_str(), totalFragments, nextFragment);
		}
		clientConnection->Close(15000);
	}

	void RunSender(const char *address, unsigned short port, SocketTransportLayer transport, const char *filename)
	{
		FILE *handle = fopen(filename, "rb");
		if (!handle)
		{
			LOG(LogUser, "Failed to open file %s!", filename);
			return;
		}
		fseek(handle, 0, SEEK_END);
		long fileSize = ftell(handle);
		if (fileSize <= 0)
		{
			fclose(handle);
			LOG(LogUser, "File %s has zero size!", filename);
			return;
		}

		fseek(handle, 0, SEEK_SET);
		std::vector<char> tempData;

		Ptr(MessageConnection) connection = network.Connect(address, port, transport, this);
		if (!connection)
		{
			cout << "Unable to connect to " << address << ":" << port << "." << endl;
			return;
		}

		// We have nothing better to do while waiting for the connection to build up, so wait modally.
		if (!connection->WaitToEstablishConnection(10000))
		{
			cout << "Failed to connect to server!" << endl;
			return;
		}

		cout << "Connected to " << connection->GetSocket()->ToString() << "." << endl;

		transferStartTick = Clock::Tick();

		NetworkMessage *msg = connection->StartNewMessage(cFileTransferStartMessage, 2048);
		DataSerializer ds(msg->data, 2048);
		const size_t fragmentSize = 450;
		const size_t numFragments = (fileSize + fragmentSize - 1) / fragmentSize;
		ds.AddString(filename);
		ds.Add<u32>(fileSize);
		ds.Add<u32>(numFragments);
		msg->priority = 100;
		msg->reliable = true;
		msg->inOrder = true;
		connection->EndAndQueueMessage(msg, ds.BytesFilled());

		size_t nextFragment = 0;
		size_t bytesSent = 0;

		LOG(LogUser, "Starting file transfer. File size: %dB, number of fragments: %d.",
			fileSize, numFragments);
		statsPrintTimer.StartMSecs(printIntervalMSecs);

		while(connection->IsWriteOpen())
		{
			connection->Process();
			Clock::Sleep(1); // A simple throttle on the send loop to avoid using 100% CPU.

			// Add new data fragments into the queue.
			const int outboundMsgQueueSize = 200;
			int i = 100;
			while(i-- > 0 && connection->IsWriteOpen() && connection->NumOutboundMessagesPending() < outboundMsgQueueSize && bytesSent < fileSize)
			{
				// File payload data bytes in this message.
				const size_t bytesInThisFragment = min((int)fragmentSize, (int)(fileSize - bytesSent));

				NetworkMessage *msg = connection->StartNewMessage(cFileTransferFragment, bytesInThisFragment+4);
				msg->priority = 100;
				msg->reliable = true;
				msg->inOrder = true;

				DataSerializer ds(msg->data, msg->Size());
				ds.Add<u32>(nextFragment++);

#ifndef NULLTRANSFER
				size_t read = fread(ds.GetData() + ds.BytesFilled(), sizeof(char), bytesInThisFragment, handle);
#else
				size_t read = bytesInThisFragment;
#endif
				if (read < bytesInThisFragment)
				{
					LOG(LogUser, "Failed to read file!");
					connection->Close(0);
				}

				connection->EndAndQueueMessage(msg);
				bytesSent += bytesInThisFragment;
			}

			// If we've put out all file fragments to the network, close the connection down.
			if (connection->IsWriteOpen() && bytesSent >= fileSize && connection->NumOutboundMessagesPending() == 0)
			{
				LOG(LogUser, "All data sent. Disconnecting.");
				connection->Disconnect(15000);
			}

			if (statsPrintTimer.Test())
			{
				const tick_t sendFinishTick = Clock::Tick();
				double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
				LOG(LogUser, "Sending fragment %d. Elapsed: %.2f seconds. Bytes sent: %d. Transfer rate: %s/sec.",
					nextFragment-1, (float)timespan, bytesSent, FormatBytes((size_t)(bytesSent/timespan)).c_str());
				connection->DumpStatus();
				statsPrintTimer.StartMSecs(printIntervalMSecs);
			}
		}

		LOG(LogUser, "Waiting for peer to acknowledge all received data.");
		while((connection->NumOutboundMessagesPending() > 0 && connection->IsWriteOpen()) || connection->IsReadOpen())
		{
			connection->Process();
			Clock::Sleep(1);

			if (statsPrintTimer.TriggeredOrNotRunning())
			{
				connection->DumpStatus();
				statsPrintTimer.StartMSecs(printIntervalMSecs);
			}
		}

		const tick_t sendFinishTick = Clock::Tick();
		double timespan = (float)Clock::TimespanToSecondsD(transferStartTick, sendFinishTick);
		connection->DumpStatus();
		LOG(LogUser, "File transfer finished in %.2f seconds. Bytes sent: %d. Transfer rate: %s/sec. Closing connection.",
			(float)timespan, bytesSent, FormatBytes((size_t)(bytesSent/timespan)).c_str());

		connection->Close(15000);
		fclose(handle);
	}
};

void PrintUsage()
{
	cout << "Usage: " << endl;
	cout << "       receive tcp|udp <port>" << endl;
	cout << "       send tcp|udp <hostname> <port> <filename>" << endl;
}

int main(int argc, char **argv)
{
	if (argc < 4)
	{
		PrintUsage();
		return 0;
	}

	EnableMemoryLeakLoggingAtExit();

//	kNet::SetLogChannels((LogChannel)(-1) & ~(LogObjectAlloc | LogVerbose)); // Enable all log channels.
	kNet::SetLogChannels(LogUser);

	SocketTransportLayer transport = SocketOverUDP;
	if (!_stricmp(argv[2], "tcp"))
		transport = SocketOverTCP;
	else if (!!_stricmp(argv[2], "udp"))
	{
		cout << "The second parameter is either 'tcp' or 'udp'!" << endl;
		return 0;
	}
	NetworkApp app;
	if (!_stricmp(argv[1], "receive"))
	{
		unsigned short port = atoi(argv[3]);

		app.RunReceiver(port, transport);
	}
	else if (!_stricmp(argv[1], "send"))
	{
		if (argc < 6)
		{
			PrintUsage();
			return 0;
		}

		unsigned short port = atoi(argv[4]);
		app.RunSender(argv[3], port, transport, argv[5]);
	}
	else
	{
		cout << "The second parameter is either 'send' or 'receive'!" << endl;
		return 0;
	}
}
<|endoftext|>


<commit_before><commit_msg>Fix coverity report: 63273 Uninitialized scalar field<commit_after><|endoftext|>