<commit_before>// janssonxx - C++ wrapper for jansson, implementation file
//
// author: Sean Middleditch <sean@middleditch.us>
//
// janssonxx is free software; you can redistribute it and/or modify
// it under the terms of the MIT license. See LICENSE for details.

#if !defined(IN_JANSSON_HPP)
#	error "jansson-impl.hpp may only by included from jansson.hpp"
#endif

namespace json {
	namespace _private {
		// assignment operator
		template <typename _Base>
		ValueBase<_Base>& ValueBase<_Base>::operator=(const Value& value) {
			_Base::operator=(value);
			return *this;
		}

		// check value type
		template <typename _Base>
		bool ValueBase<_Base>::is_undefined() const {
			return _Base::as_json() == 0;
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_object() const {
			return json_is_object(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_array() const {
			return json_is_array(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_string() const {
			return json_is_string(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_integer() const {
			return json_is_integer(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_real() const {
			return json_is_real(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_number() const {
			return json_is_number(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_true() const {
			return json_is_true(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_false() const {
			return json_is_false(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_boolean() const {
			return json_is_boolean(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_null() const {
			return json_is_null(_Base::as_json());
		}

		// get size of array or object
		template <typename _Base>
		unsigned int ValueBase<_Base>::size() const {
			if (is_object())
				return json_object_size(_Base::as_json());
			else
				return json_array_size(_Base::as_json());
		}

		// get value at array index (const version)
		template <typename _Base>
		const Value ValueBase<_Base>::at(unsigned int index) const {
			return Value(json_array_get(_Base::as_json(), index));
		}

		template <typename _Base>
		const Value ValueBase<_Base>::operator[](signed int index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](unsigned int index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](signed short index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](unsigned short index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](signed long index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](unsigned long index) const { return at(index); }

		// get value at array index (non-const version)
		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::at(unsigned int index) {
			return ElementProxy(_Base::as_json(), index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed int index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned int index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed short index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned short index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed long index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned long index) {
			return at(index);
		}

		// get object property (const version)
		template <typename _Base>
		const Value ValueBase<_Base>::get(const char* key) const {
			return Value(json_object_get(_Base::as_json(), key));
		}

		template <typename _Base>
		const Value ValueBase<_Base>::get(const std::string& key) const {
			return get(key.c_str());
		}

		template <typename _Base>
		const Value ValueBase<_Base>::operator[](const char* key) const {
			return get(key);
		}

		template <typename _Base>
		const Value ValueBase<_Base>::operator[](const std::string& key) const {
			return get(key.c_str());
		}

		// get object property (non-const version)
		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::get(const char* key) {
			return PropertyProxy(_Base::as_json(), key);
		}

		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::get(const std::string& key) {
			return get(key.c_str());
		}

		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const char* key) {
			return get(key);
		}

		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const std::string& key) {
			return get(key.c_str());
		}

		// clear all array/object values
		template <typename _Base>
		void ValueBase<_Base>::clear() {
			if (is_object())
				json_object_clear(_Base::as_json());
			else
				json_array_clear(_Base::as_json());
		}

		// get value cast to specified type
		template <typename _Base>
		const char* ValueBase<_Base>::as_cstring() const {
			return json_string_value(_Base::as_json());
		}

		template <typename _Base>
		std::string ValueBase<_Base>::as_string() const {
			const char* tmp = as_cstring();
			return tmp == 0 ? "" : tmp;
		}

		template <typename _Base>
		int ValueBase<_Base>::as_integer() const {
			return json_integer_value(_Base::as_json());
		}

		template <typename _Base>
		double ValueBase<_Base>::as_real() const {
			return json_real_value(_Base::as_json());
		}

		template <typename _Base>
		double ValueBase<_Base>::as_number() const {
			return json_number_value(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::as_boolean() const {
			return is_true();
		}

		// set an object property (converts value to object is not one already)
		template <typename _Base>
		_Base& ValueBase<_Base>::set_key(const char* key, const Value& value) {
			json_object_set(_Base::as_json(), key, value._Base::as_json());
			return *this;
		}

		template <typename _Base>
		_Base& ValueBase<_Base>::set_key(const std::string& key, const Value& value) {
			return set_key(key.c_str(), value);
		}

		// set an array index (converts value to object is not one already)
		template <typename _Base>
		_Base& ValueBase<_Base>::set_at(unsigned int index, const Value& value) {
			if (index == size())
				json_array_append(_Base::as_json(), value._Base::as_json());
			else
				json_array_set(_Base::as_json(), index, value._Base::as_json());
			return *this;
		}

		// delete an object key
		template <typename _Base>
		_Base& ValueBase<_Base>::del_key(const char* key) {
			json_object_del(_Base::as_json(), key);
			return *this;
		}

		template <typename _Base>
		_Base& ValueBase<_Base>::del_key(const std::string& key) {
			return del_key(key.c_str());
		}

		// delete an item from an array by index
		template <typename _Base>
		_Base& ValueBase<_Base>::del_at(unsigned int index) {
			json_array_remove(_Base::as_json(), index);
			return *this;
		}

		// insert an item into an array at a given index
		template <typename _Base>
		_Base& ValueBase<_Base>::insert_at(unsigned int index, const Value& value) {
			json_array_insert(_Base::as_json(), index, value._Base::as_json());
			return *this;
		}

		// write the value to a file
		template <typename _Base>
		int ValueBase<_Base>::save_file(const char* path, int flags) const {
			return json_dump_file(_Base::as_json(), path, flags);
		}

		// write the value to a string (caller must deallocate with free()!)
		template <typename _Base>
		char* ValueBase<_Base>::save_string(int flags) const {
			return json_dumps(_Base::as_json(), flags);
		}

		Basic::~Basic() {
			json_decref(_value);
		}

		// copy an existing Value
		Basic& Basic::operator=(const Basic& e) {
			if (&e != this) {
				json_decref(_value);
				_value = json_incref(e._value);
			}
			return *this;
		}

		// get the underlying json_t
		json_t* Basic::as_json() const {
			return _value;
		}

		// take ownership of a json_t (does not increase reference count)
		Basic Basic::take_ownership(json_t* json) {
			Basic v;
			v._value = json;
			return v;
		}

		// assign value to proxied array element
		ElementProxy& ElementProxy::operator=(const Value& value) {
			json_array_set(_array, _index, value.as_json());
			return *this;
		}

		// get the proxied element
		json_t* ElementProxy::as_json() const {
			return json_array_get(_array, _index);
		}

		// assign value to proxied object property
		PropertyProxy& PropertyProxy::operator=(const Value& value) {
			json_object_set(_object, _key, value.as_json());
			return *this;
		}

		json_t* PropertyProxy::as_json() const {
			return json_object_get(_object, _key);
		}

	} // namespace json::_private

	// construct Value::Value input
	Value::Value(const char* value) {
		_value = json_string(value);
	}

	Value::Value(const std::string& value) {
		_value = json_string(value.c_str());
	}

	Value::Value(bool value) {
		_value = value ? json_true() : json_false();
	}

	Value::Value(signed int value) {
		_value = json_integer(value);
	}

	Value::Value(unsigned int value) {
		_value = json_integer(value);
	}

	Value::Value(signed short value) {
		_value = json_integer(value);
	}

	Value::Value(unsigned short value) {
		_value = json_integer(value);
	}

	Value::Value(signed long value) {
		_value = json_integer(value);
	}

	Value::Value(unsigned long value) {
		_value = json_integer(value);
	}

	Value::Value(float value) {
		_value = json_real(value);
	}

	Value::Value(double value) {
		_value = json_real(value);
	}

	// construct a new iterator for a given object
	Iterator::Iterator(const Value& value) : _object(value), _iter(0) {
		_iter = json_object_iter(_object.as_json());
	}

	// construct a new iterator for a given object
	Iterator::Iterator(const _private::ValueBase<_private::PropertyProxy>& value) :
			_object(value.as_json()), _iter(0) {
		_iter = json_object_iter(_object.as_json());
	}

	// increment iterator
	void Iterator::next() {
		_iter = json_object_iter_next(_object.as_json(), _iter);
	}

	Iterator& Iterator::operator++() { next(); return *this; }

	// test if iterator is still valid
	bool Iterator::valid() const {
		return _iter != 0;
	}

	Iterator::operator bool() const {
		return valid();
	}

	// get key
	const char* Iterator::ckey() const {
		return json_object_iter_key(_iter);
	}

	std::string Iterator::key() const {
		return ckey();
	}

	// get value
	const Value Iterator::value() const {
		return Value(json_object_iter_value(_iter));
	}

	// dereference value
	const Value Iterator::operator*() const {
		return value();
	}

	// create a new empty object
	Value object() {
		return Value::take_ownership(json_object());
	}

	// create a new empty array
	Value array() {
		return Value::take_ownership(json_array());
	}

	// create a new null value
	Value null() {
		return Value::take_ownership(json_null());
	}

	// load a file as a JSON value
	Value load_file(const char* path, json_error_t* error) {
		return Value::take_ownership(json_load_file(path, error));
	}

	// load a string as a JSON value
	Value load_string(const char* string, json_error_t* error) {
		return Value::take_ownership(json_loads(string, error));
	}

} // namespace json

// stream JSON value out
std::ostream& operator<<(std::ostream& os, const json::Value& value) {
	// get the temporary serialize string
	char* tmp = value.save_string();
	if (tmp != 0) {
		// stream temp string out and release it
		os << tmp;
		free(tmp);
	}
	return os;
}

// read JSON value
std::istream& operator>>(std::istream& is, json::Value& value) {
	// buffer the remaining bytes into a single string for Jansson
	std::stringstream tmp;
	while (is)
		tmp << static_cast<char>(is.get());
	// parse the buffered string
	value = json::load_string(tmp.str().c_str());
	return is;
}
<commit_msg>add meaningful copyright to jansson-impl.hpp too<commit_after>// Copyright (c) 2010 Sean Middleditch <sean@middleditch.us>
//
// Jansson is free software; you can redistribute it and/or modify
// it under the terms of the MIT license. See LICENSE for details.

#if !defined(IN_JANSSON_HPP)
#	error "jansson-impl.hpp may only by included from jansson.hpp"
#endif

namespace json {
	namespace _private {
		// assignment operator
		template <typename _Base>
		ValueBase<_Base>& ValueBase<_Base>::operator=(const Value& value) {
			_Base::operator=(value);
			return *this;
		}

		// check value type
		template <typename _Base>
		bool ValueBase<_Base>::is_undefined() const {
			return _Base::as_json() == 0;
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_object() const {
			return json_is_object(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_array() const {
			return json_is_array(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_string() const {
			return json_is_string(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_integer() const {
			return json_is_integer(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_real() const {
			return json_is_real(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_number() const {
			return json_is_number(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_true() const {
			return json_is_true(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_false() const {
			return json_is_false(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_boolean() const {
			return json_is_boolean(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::is_null() const {
			return json_is_null(_Base::as_json());
		}

		// get size of array or object
		template <typename _Base>
		unsigned int ValueBase<_Base>::size() const {
			if (is_object())
				return json_object_size(_Base::as_json());
			else
				return json_array_size(_Base::as_json());
		}

		// get value at array index (const version)
		template <typename _Base>
		const Value ValueBase<_Base>::at(unsigned int index) const {
			return Value(json_array_get(_Base::as_json(), index));
		}

		template <typename _Base>
		const Value ValueBase<_Base>::operator[](signed int index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](unsigned int index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](signed short index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](unsigned short index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](signed long index) const { return at(index); }
		template <typename _Base>
		const Value ValueBase<_Base>::operator[](unsigned long index) const { return at(index); }

		// get value at array index (non-const version)
		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::at(unsigned int index) {
			return ElementProxy(_Base::as_json(), index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed int index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned int index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed short index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned short index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](signed long index) {
			return at(index);
		}

		template <typename _Base>
		ValueBase<ElementProxy> ValueBase<_Base>::operator[](unsigned long index) {
			return at(index);
		}

		// get object property (const version)
		template <typename _Base>
		const Value ValueBase<_Base>::get(const char* key) const {
			return Value(json_object_get(_Base::as_json(), key));
		}

		template <typename _Base>
		const Value ValueBase<_Base>::get(const std::string& key) const {
			return get(key.c_str());
		}

		template <typename _Base>
		const Value ValueBase<_Base>::operator[](const char* key) const {
			return get(key);
		}

		template <typename _Base>
		const Value ValueBase<_Base>::operator[](const std::string& key) const {
			return get(key.c_str());
		}

		// get object property (non-const version)
		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::get(const char* key) {
			return PropertyProxy(_Base::as_json(), key);
		}

		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::get(const std::string& key) {
			return get(key.c_str());
		}

		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const char* key) {
			return get(key);
		}

		template <typename _Base>
		ValueBase<PropertyProxy> ValueBase<_Base>::operator[](const std::string& key) {
			return get(key.c_str());
		}

		// clear all array/object values
		template <typename _Base>
		void ValueBase<_Base>::clear() {
			if (is_object())
				json_object_clear(_Base::as_json());
			else
				json_array_clear(_Base::as_json());
		}

		// get value cast to specified type
		template <typename _Base>
		const char* ValueBase<_Base>::as_cstring() const {
			return json_string_value(_Base::as_json());
		}

		template <typename _Base>
		std::string ValueBase<_Base>::as_string() const {
			const char* tmp = as_cstring();
			return tmp == 0 ? "" : tmp;
		}

		template <typename _Base>
		int ValueBase<_Base>::as_integer() const {
			return json_integer_value(_Base::as_json());
		}

		template <typename _Base>
		double ValueBase<_Base>::as_real() const {
			return json_real_value(_Base::as_json());
		}

		template <typename _Base>
		double ValueBase<_Base>::as_number() const {
			return json_number_value(_Base::as_json());
		}

		template <typename _Base>
		bool ValueBase<_Base>::as_boolean() const {
			return is_true();
		}

		// set an object property (converts value to object is not one already)
		template <typename _Base>
		_Base& ValueBase<_Base>::set_key(const char* key, const Value& value) {
			json_object_set(_Base::as_json(), key, value._Base::as_json());
			return *this;
		}

		template <typename _Base>
		_Base& ValueBase<_Base>::set_key(const std::string& key, const Value& value) {
			return set_key(key.c_str(), value);
		}

		// set an array index (converts value to object is not one already)
		template <typename _Base>
		_Base& ValueBase<_Base>::set_at(unsigned int index, const Value& value) {
			if (index == size())
				json_array_append(_Base::as_json(), value._Base::as_json());
			else
				json_array_set(_Base::as_json(), index, value._Base::as_json());
			return *this;
		}

		// delete an object key
		template <typename _Base>
		_Base& ValueBase<_Base>::del_key(const char* key) {
			json_object_del(_Base::as_json(), key);
			return *this;
		}

		template <typename _Base>
		_Base& ValueBase<_Base>::del_key(const std::string& key) {
			return del_key(key.c_str());
		}

		// delete an item from an array by index
		template <typename _Base>
		_Base& ValueBase<_Base>::del_at(unsigned int index) {
			json_array_remove(_Base::as_json(), index);
			return *this;
		}

		// insert an item into an array at a given index
		template <typename _Base>
		_Base& ValueBase<_Base>::insert_at(unsigned int index, const Value& value) {
			json_array_insert(_Base::as_json(), index, value._Base::as_json());
			return *this;
		}

		// write the value to a file
		template <typename _Base>
		int ValueBase<_Base>::save_file(const char* path, int flags) const {
			return json_dump_file(_Base::as_json(), path, flags);
		}

		// write the value to a string (caller must deallocate with free()!)
		template <typename _Base>
		char* ValueBase<_Base>::save_string(int flags) const {
			return json_dumps(_Base::as_json(), flags);
		}

		Basic::~Basic() {
			json_decref(_value);
		}

		// copy an existing Value
		Basic& Basic::operator=(const Basic& e) {
			if (&e != this) {
				json_decref(_value);
				_value = json_incref(e._value);
			}
			return *this;
		}

		// get the underlying json_t
		json_t* Basic::as_json() const {
			return _value;
		}

		// take ownership of a json_t (does not increase reference count)
		Basic Basic::take_ownership(json_t* json) {
			Basic v;
			v._value = json;
			return v;
		}

		// assign value to proxied array element
		ElementProxy& ElementProxy::operator=(const Value& value) {
			json_array_set(_array, _index, value.as_json());
			return *this;
		}

		// get the proxied element
		json_t* ElementProxy::as_json() const {
			return json_array_get(_array, _index);
		}

		// assign value to proxied object property
		PropertyProxy& PropertyProxy::operator=(const Value& value) {
			json_object_set(_object, _key, value.as_json());
			return *this;
		}

		json_t* PropertyProxy::as_json() const {
			return json_object_get(_object, _key);
		}

	} // namespace json::_private

	// construct Value::Value input
	Value::Value(const char* value) {
		_value = json_string(value);
	}

	Value::Value(const std::string& value) {
		_value = json_string(value.c_str());
	}

	Value::Value(bool value) {
		_value = value ? json_true() : json_false();
	}

	Value::Value(signed int value) {
		_value = json_integer(value);
	}

	Value::Value(unsigned int value) {
		_value = json_integer(value);
	}

	Value::Value(signed short value) {
		_value = json_integer(value);
	}

	Value::Value(unsigned short value) {
		_value = json_integer(value);
	}

	Value::Value(signed long value) {
		_value = json_integer(value);
	}

	Value::Value(unsigned long value) {
		_value = json_integer(value);
	}

	Value::Value(float value) {
		_value = json_real(value);
	}

	Value::Value(double value) {
		_value = json_real(value);
	}

	// construct a new iterator for a given object
	Iterator::Iterator(const Value& value) : _object(value), _iter(0) {
		_iter = json_object_iter(_object.as_json());
	}

	// construct a new iterator for a given object
	Iterator::Iterator(const _private::ValueBase<_private::PropertyProxy>& value) :
			_object(value.as_json()), _iter(0) {
		_iter = json_object_iter(_object.as_json());
	}

	// increment iterator
	void Iterator::next() {
		_iter = json_object_iter_next(_object.as_json(), _iter);
	}

	Iterator& Iterator::operator++() { next(); return *this; }

	// test if iterator is still valid
	bool Iterator::valid() const {
		return _iter != 0;
	}

	Iterator::operator bool() const {
		return valid();
	}

	// get key
	const char* Iterator::ckey() const {
		return json_object_iter_key(_iter);
	}

	std::string Iterator::key() const {
		return ckey();
	}

	// get value
	const Value Iterator::value() const {
		return Value(json_object_iter_value(_iter));
	}

	// dereference value
	const Value Iterator::operator*() const {
		return value();
	}

	// create a new empty object
	Value object() {
		return Value::take_ownership(json_object());
	}

	// create a new empty array
	Value array() {
		return Value::take_ownership(json_array());
	}

	// create a new null value
	Value null() {
		return Value::take_ownership(json_null());
	}

	// load a file as a JSON value
	Value load_file(const char* path, json_error_t* error) {
		return Value::take_ownership(json_load_file(path, error));
	}

	// load a string as a JSON value
	Value load_string(const char* string, json_error_t* error) {
		return Value::take_ownership(json_loads(string, error));
	}

} // namespace json

// stream JSON value out
std::ostream& operator<<(std::ostream& os, const json::Value& value) {
	// get the temporary serialize string
	char* tmp = value.save_string();
	if (tmp != 0) {
		// stream temp string out and release it
		os << tmp;
		free(tmp);
	}
	return os;
}

// read JSON value
std::istream& operator>>(std::istream& is, json::Value& value) {
	// buffer the remaining bytes into a single string for Jansson
	std::stringstream tmp;
	while (is)
		tmp << static_cast<char>(is.get());
	// parse the buffered string
	value = json::load_string(tmp.str().c_str());
	return is;
}
<|endoftext|>


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

#include "kaa/log/LogCollector.hpp"

#include "kaa/gen/EndpointGen.hpp"
#include "kaa/common/UuidGenerator.hpp"
#include "kaa/logging/Log.hpp"
#include "kaa/log/LoggingTransport.hpp"
#include "kaa/log/MemoryLogStorage.hpp"
#include "kaa/log/DefaultLogUploadStrategy.hpp"
#include "kaa/common/exception/TransportNotFoundException.hpp"
#include "kaa/log/LogRecord.hpp"

namespace kaa {

LogCollector::LogCollector(IKaaChannelManagerPtr manager)
    : requestId_(0), transport_(nullptr)
{
    storage_.reset(new MemoryLogStorage());
    uploadStrategy_.reset(new DefaultLogUploadStrategy(manager));
}

void LogCollector::addLogRecord(const KaaUserLogRecord& record)
{
    LogRecordPtr serializedRecord(new LogRecord(record));

    {
        KAA_MUTEX_LOCKING("storageGuard_");
        KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
        KAA_MUTEX_LOCKED("storageGuard_");

        storage_->addLogRecord(serializedRecord);
    }

    if (isDeliveryTimeout()) {
        return;
    }

    processLogUploadDecision(uploadStrategy_->isUploadNeeded(storage_->getStatus()));

}

void LogCollector::processLogUploadDecision(LogUploadStrategyDecision decision)
{
    switch (decision) {
    case LogUploadStrategyDecision::UPLOAD: {
        KAA_LOG_DEBUG("Going to upload logs");
        doSync();
        break;
    }
    case LogUploadStrategyDecision::NOOP:
        KAA_LOG_TRACE("Nothing to do now");
        break;
    default:
        KAA_LOG_WARN("Unknown log upload decision");
        break;
    }
}

void LogCollector::setStorage(ILogStoragePtr storage)
{
    if (!storage) {
        KAA_LOG_ERROR("Failed to set log storage: bad data");
        throw KaaException("Bad log storage");
    }

    KAA_MUTEX_LOCKING("storageGuard_");
    KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
    KAA_MUTEX_LOCKED("storageGuard_");

    KAA_LOG_INFO("New log storage was set");
    storage_ = storage;
}

void LogCollector::setUploadStrategy(ILogUploadStrategyPtr strategy)
{
    if (!strategy) {
        KAA_LOG_ERROR("Failed to set log upload strategy: bad data");
        throw KaaException("Bad log upload strategy");
    }

    KAA_MUTEX_LOCKING("storageGuard_");
    KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
    KAA_MUTEX_LOCKED("storageGuard_");

    KAA_LOG_INFO("New log upload strategy was set");
    uploadStrategy_ = strategy;
}

void LogCollector::doSync()
{
    if (transport_) {
        transport_->sync();
    } else {
        KAA_LOG_ERROR("Failed to upload logs: log transport isn't initialized");
        throw TransportNotFoundException("Log transport isn't set");
    }
}

bool LogCollector::isDeliveryTimeout()
{
    bool isTimeout = false;
    const auto& now = clock_t::now();

    for (const auto& request : timeoutsMap_) {
        if (now >= request.second) {
            isTimeout = true;
            break;
        }
    }

    if (isTimeout) {
        KAA_LOG_INFO("Log delivery timeout detected");

        for (const auto& request : timeoutsMap_) {
            storage_->notifyUploadFailed(request.first);
        }

        timeoutsMap_.clear();
        uploadStrategy_->onTimeout();
    }

    return isTimeout;
}

std::shared_ptr<LogSyncRequest> LogCollector::getLogUploadRequest()
{
    ILogStorage::RecordPack recordPack;
    std::shared_ptr<LogSyncRequest> request;

    {
        KAA_MUTEX_LOCKING("storageGuard_");
        KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
        KAA_MUTEX_LOCKED("storageGuard_");

        recordPack = storage_->getRecordBlock(uploadStrategy_->getBatchSize());
    }

    if (!recordPack.second.empty()) {
        request.reset(new LogSyncRequest);
        request->requestId = recordPack.first;

        std::vector<LogEntry> logs;
        logs.reserve(recordPack.second.size());
        for (const auto& log : recordPack.second) {
            logs.push_back(log->getLogEntry());
        }

        request->logEntries.set_array(std::move(logs));
        timeoutsMap_.insert(std::make_pair(request->requestId,
                                           clock_t::now() + std::chrono::seconds(uploadStrategy_->getTimeout())));
    }

    return request;
}

void LogCollector::onLogUploadResponse(const LogSyncResponse& response)
{
    KAA_MUTEX_LOCKING("storageGuard_");
    KAA_MUTEX_UNIQUE_DECLARE(storageLock, storageGuard_);
    KAA_MUTEX_LOCKED("storageGuard_");

    if (!response.deliveryStatuses.is_null()) {
        const auto& deliveryStatuses = response.deliveryStatuses.get_array();
        for (const auto& status : deliveryStatuses) {
            if (!timeoutsMap_.erase(status.requestId)) {
                continue;
            }

            if (status.result == SyncResponseResultType::SUCCESS) {
                KAA_LOG_INFO(boost::format("Logs (requestId %1%) successfully delivered") % status.requestId);
                storage_->removeRecordBlock(status.requestId);
            } else {
                KAA_LOG_WARN(boost::format("Logs (requestId %1%) failed to deliver") % status.requestId);
                storage_->notifyUploadFailed(status.requestId);

                KAA_MUTEX_UNLOCKING("storageGuard_");
                KAA_UNLOCK(storageLock);
                KAA_MUTEX_UNLOCKED("storageGuard_");

                if (!status.errorCode.is_null()) {
                    uploadStrategy_->onFailure(status.errorCode.get_LogDeliveryErrorCode());
                } else {
                    KAA_LOG_ERROR("Log delivery failed, but no error code received");
                }

                KAA_MUTEX_LOCKING("storageGuard_");
                KAA_LOCK(storageLock);
                KAA_MUTEX_LOCKED("storageGuard_");
            }
        }
    }

    processLogUploadDecision(uploadStrategy_->isUploadNeeded(storage_->getStatus()));
}

void LogCollector::setTransport(LoggingTransport* transport)
{
    transport_ = transport;
}

}  // namespace kaa

<commit_msg>KAA-529: Fix race condition in C++ SDK log colletor.<commit_after>/*
 * Copyright 2014 CyberVision, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License") {}
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "kaa/log/LogCollector.hpp"

#include "kaa/gen/EndpointGen.hpp"
#include "kaa/common/UuidGenerator.hpp"
#include "kaa/logging/Log.hpp"
#include "kaa/log/LoggingTransport.hpp"
#include "kaa/log/MemoryLogStorage.hpp"
#include "kaa/log/DefaultLogUploadStrategy.hpp"
#include "kaa/common/exception/TransportNotFoundException.hpp"
#include "kaa/log/LogRecord.hpp"

namespace kaa {

LogCollector::LogCollector(IKaaChannelManagerPtr manager)
    : requestId_(0), transport_(nullptr)
{
    storage_.reset(new MemoryLogStorage());
    uploadStrategy_.reset(new DefaultLogUploadStrategy(manager));
}

void LogCollector::addLogRecord(const KaaUserLogRecord& record)
{
    LogRecordPtr serializedRecord(new LogRecord(record));

    {
        KAA_MUTEX_LOCKING("storageGuard_");
        KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
        KAA_MUTEX_LOCKED("storageGuard_");

        storage_->addLogRecord(serializedRecord);

        if (isDeliveryTimeout()) {
            return;
        }
    }

    processLogUploadDecision(uploadStrategy_->isUploadNeeded(storage_->getStatus()));

}

void LogCollector::processLogUploadDecision(LogUploadStrategyDecision decision)
{
    switch (decision) {
    case LogUploadStrategyDecision::UPLOAD: {
        KAA_LOG_DEBUG("Going to upload logs");
        doSync();
        break;
    }
    case LogUploadStrategyDecision::NOOP:
        KAA_LOG_TRACE("Nothing to do now");
        break;
    default:
        KAA_LOG_WARN("Unknown log upload decision");
        break;
    }
}

void LogCollector::setStorage(ILogStoragePtr storage)
{
    if (!storage) {
        KAA_LOG_ERROR("Failed to set log storage: bad data");
        throw KaaException("Bad log storage");
    }

    KAA_MUTEX_LOCKING("storageGuard_");
    KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
    KAA_MUTEX_LOCKED("storageGuard_");

    KAA_LOG_INFO("New log storage was set");
    storage_ = storage;
}

void LogCollector::setUploadStrategy(ILogUploadStrategyPtr strategy)
{
    if (!strategy) {
        KAA_LOG_ERROR("Failed to set log upload strategy: bad data");
        throw KaaException("Bad log upload strategy");
    }

    KAA_MUTEX_LOCKING("storageGuard_");
    KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
    KAA_MUTEX_LOCKED("storageGuard_");

    KAA_LOG_INFO("New log upload strategy was set");
    uploadStrategy_ = strategy;
}

void LogCollector::doSync()
{
    if (transport_) {
        transport_->sync();
    } else {
        KAA_LOG_ERROR("Failed to upload logs: log transport isn't initialized");
        throw TransportNotFoundException("Log transport isn't set");
    }
}

bool LogCollector::isDeliveryTimeout()
{
    bool isTimeout = false;
    const auto& now = clock_t::now();

    for (const auto& request : timeoutsMap_) {
        if (now >= request.second) {
            KAA_LOG_INFO(boost::format("Log delivery timeout detected, bucket id %li") % request.first);
            isTimeout = true;
            break;
        }
    }

    if (isTimeout) {
        for (const auto& request : timeoutsMap_) {
            storage_->notifyUploadFailed(request.first);
        }

        timeoutsMap_.clear();
        uploadStrategy_->onTimeout();
    }

    return isTimeout;
}

std::shared_ptr<LogSyncRequest> LogCollector::getLogUploadRequest()
{
    ILogStorage::RecordPack recordPack;
    std::shared_ptr<LogSyncRequest> request;

    {
        KAA_MUTEX_LOCKING("storageGuard_");
        KAA_MUTEX_UNIQUE_DECLARE(lock, storageGuard_);
        KAA_MUTEX_LOCKED("storageGuard_");

        recordPack = storage_->getRecordBlock(uploadStrategy_->getBatchSize());
    }

    if (!recordPack.second.empty()) {
        request.reset(new LogSyncRequest);
        request->requestId = recordPack.first;

        std::vector<LogEntry> logs;
        logs.reserve(recordPack.second.size());
        for (const auto& log : recordPack.second) {
            logs.push_back(log->getLogEntry());
        }

        request->logEntries.set_array(std::move(logs));
        timeoutsMap_.insert(std::make_pair(request->requestId,
                                           clock_t::now() + std::chrono::seconds(uploadStrategy_->getTimeout())));
    }

    return request;
}

void LogCollector::onLogUploadResponse(const LogSyncResponse& response)
{
    KAA_MUTEX_LOCKING("storageGuard_");
    KAA_MUTEX_UNIQUE_DECLARE(storageLock, storageGuard_);
    KAA_MUTEX_LOCKED("storageGuard_");

    if (!response.deliveryStatuses.is_null()) {
        const auto& deliveryStatuses = response.deliveryStatuses.get_array();
        for (const auto& status : deliveryStatuses) {
            if (!timeoutsMap_.erase(status.requestId)) {
                continue;
            }

            if (status.result == SyncResponseResultType::SUCCESS) {
                KAA_LOG_INFO(boost::format("Logs (requestId %1%) successfully delivered") % status.requestId);
                storage_->removeRecordBlock(status.requestId);
            } else {
                KAA_LOG_WARN(boost::format("Logs (requestId %1%) failed to deliver") % status.requestId);
                storage_->notifyUploadFailed(status.requestId);

                KAA_MUTEX_UNLOCKING("storageGuard_");
                KAA_UNLOCK(storageLock);
                KAA_MUTEX_UNLOCKED("storageGuard_");

                if (!status.errorCode.is_null()) {
                    uploadStrategy_->onFailure(status.errorCode.get_LogDeliveryErrorCode());
                } else {
                    KAA_LOG_ERROR("Log delivery failed, but no error code received");
                }

                KAA_MUTEX_LOCKING("storageGuard_");
                KAA_LOCK(storageLock);
                KAA_MUTEX_LOCKED("storageGuard_");
            }
        }
    }

    processLogUploadDecision(uploadStrategy_->isUploadNeeded(storage_->getStatus()));
}

void LogCollector::setTransport(LoggingTransport* transport)
{
    transport_ = transport;
}

}  // namespace kaa

<|endoftext|>


<commit_before>/**
 * \file qibla.cpp
 */
#include <math.h>

double get_qibla_angle(double longitude, double latitude)
{
    double m = sin(longitude - 39.8230);
    double n = cos(latitude) * tan(21.42330) - sin(latitude) * cos(longitude - 39.8230);
    double q = atan(m/n);
    return q;
}
<commit_msg>use constants while calculating qibla<commit_after>/**
 * \file qibla.cpp
 */
#include <math.h>

static const double DEG2RAD = 0.017453292519943295769236907684886;
static const double MECCA_LONGITUDE = 39.8230*DEG2RAD; // 39.8230E
static const double MECCA_LATITUDE = 21.42330*DEG2RAD; // 21.42330N
double get_qibla_angle(double longitude, double latitude)
{
    double m = sin(longitude*DEG2RAD - MECCA_LONGITUDE);
    double n = cos(latitude*DEG2RAD) * tan(MECCA_LATITUDE) - sin(latitude*DEG2RAD) * cos(longitude*DEG2RAD - MECCA_LONGITUDE);
    double q = atan(m/n) / DEG2RAD;
    return q;
}
<|endoftext|>


<commit_before>#include "Audio.hpp"
#include <AL/al.h>
#include <AL/alext.h>
#include "Game.hpp"
#include "Sound.hpp"
#include "GlobalProperties.hpp"

#define AUDIO_GC_DEBUG 0

namespace Diggler {

Audio::Audio(Game* G) : G(G), sounds(m_sounds) {
	if (!GlobalProperties::IsSoundEnabled)
		return;

	int alMajor, alMinor;
	alcGetIntegerv(nullptr, ALC_MAJOR_VERSION, 1, &alMajor);
	alcGetIntegerv(nullptr, ALC_MINOR_VERSION, 1, &alMinor);
	getDebugStream() << "OpenAL v" << alMajor << '.' << alMinor << std::endl;

	ALboolean enumeration = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
	if (enumeration == AL_FALSE)
		; // enumeration not supported
	else {
		const ALCchar *devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
		const ALCchar *device = devices, *next = devices + 1;
		size_t len = 0;
		while (device && *device != '\0' && next && *next != '\0') {
			len = strlen(device);
			device += (len + 1);
			next += (len + 2);
		}
	}
	const ALCchar *deviceName = nullptr;
	m_audioDevice = alcOpenDevice(deviceName);
	if (!m_audioDevice) {
		getDebugStream() << "Failed opening AL device '" << deviceName << "': " << alcGetError(m_audioDevice) << std::endl;
		GlobalProperties::IsSoundEnabled = false;
	}
	deviceName = alcGetString(m_audioDevice, ALC_DEVICE_SPECIFIER);
	getDebugStream() << "Using device '" << deviceName << '\'' << std::endl;

	ALCint attrs[] = {
		0, 0
	};

	m_audioContext = alcCreateContext(m_audioDevice, attrs);
	if (!alcMakeContextCurrent(m_audioContext)) {
		getDebugStream() << "Failed setting context on AL device '" << deviceName << "': " << alcGetError(m_audioDevice) << std::endl;
		alcCloseDevice(m_audioDevice);
		GlobalProperties::IsSoundEnabled = false;
	}
}

Audio::~Audio() {
	if (!GlobalProperties::IsSoundEnabled)
		return;

	alcMakeContextCurrent(nullptr);
	alcDestroyContext(m_audioContext);
	alcCloseDevice(m_audioDevice);
}

static ALfloat float3data[3], plrOrient[6];

void Audio::updateAngle() {
	const glm::vec3 &at = G->LP->camera.getLookAt(),
					&up = G->LP->camera.getUp();
	plrOrient[0] = at.x;
	plrOrient[1] = at.y;
	plrOrient[2] = at.z;
	plrOrient[3] = up.x;
	plrOrient[4] = up.y;
	plrOrient[5] = up.z;
	alListenerfv(AL_ORIENTATION, plrOrient);
}

void Audio::updatePos() {
	const glm::vec3 &pos = G->LP->position,
					&vel = G->LP->velocity;
	float3data[0] = pos.x;
	float3data[1] = pos.y;
	float3data[2] = pos.z;
	alListenerfv(AL_POSITION, float3data);
	float3data[0] = vel.x;
	float3data[1] = vel.y;
	float3data[2] = vel.z;
	alListenerfv(AL_VELOCITY, float3data);
}

void Audio::update() {
	updatePos();
	updateAngle();
}

void Audio::loadSoundAssets() {
	std::string soundsDir = getAssetsDirectory() + "sounds/";
	for (const std::string &fn : fs::getFiles(soundsDir)) {
		if (fn.length() >= 4 && fn.substr(fn.length()-4) == ".ogg") {
			addSound(fn.substr(0, fn.length()-4), soundsDir+fn);
		}
	}
}

void Audio::addSound(const std::string& name, const std::string& path) {
	m_sounds.emplace(std::piecewise_construct,
			std::forward_as_tuple(name), std::forward_as_tuple()).first->second.loadOgg(path);
}

void Audio::playSound(const std::string &name) {
	playSound(m_sounds.at(name));
}

void Audio::playSound(const SoundBuffer &buf) {
	m_playing.emplace_back(&buf);
	m_playing.back().play();
	gc();
}

void Audio::playSound(const std::string &name, const glm::vec3 &pos) {
	playSound(m_sounds.at(name), pos);
}

void Audio::playSound(const SoundBuffer &buf, const glm::vec3& pos) {
	m_playing.emplace_back(&buf, false, pos);
	m_playing.back().play();
	gc();
}

/// Garbage Collects the sound sources
void Audio::gc() {
#if AUDIO_GC_DEBUG
	uint freed = 0;
#endif
	std::list<Sound>::const_iterator it = m_playing.begin();
	while (it != m_playing.end()) {
		if (!it->isPlaying()) {
			it = m_playing.erase(it);
#if AUDIO_GC_DEBUG
			freed++;
#endif
		} else {
			++it;
		}
	}
#if AUDIO_GC_DEBUG
	getDebugStream() << "GC'd " << freed << " sources" << std::endl;
#endif
}

}<commit_msg>Fix bad sound paths leading to crash by std::out_of_range<commit_after>#include "Audio.hpp"
#include <AL/al.h>
#include <AL/alext.h>
#include "Game.hpp"
#include "Sound.hpp"
#include "GlobalProperties.hpp"

#define AUDIO_GC_DEBUG 0

namespace Diggler {

Audio::Audio(Game* G) : G(G), sounds(m_sounds) {
	if (!GlobalProperties::IsSoundEnabled)
		return;

	int alMajor, alMinor;
	alcGetIntegerv(nullptr, ALC_MAJOR_VERSION, 1, &alMajor);
	alcGetIntegerv(nullptr, ALC_MINOR_VERSION, 1, &alMinor);
	getDebugStream() << "OpenAL v" << alMajor << '.' << alMinor << std::endl;

	ALboolean enumeration = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
	if (enumeration == AL_FALSE)
		; // enumeration not supported
	else {
		const ALCchar *devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
		const ALCchar *device = devices, *next = devices + 1;
		size_t len = 0;
		while (device && *device != '\0' && next && *next != '\0') {
			len = strlen(device);
			device += (len + 1);
			next += (len + 2);
		}
	}
	const ALCchar *deviceName = nullptr;
	m_audioDevice = alcOpenDevice(deviceName);
	if (!m_audioDevice) {
		getDebugStream() << "Failed opening AL device '" << deviceName << "': " << alcGetError(m_audioDevice) << std::endl;
		GlobalProperties::IsSoundEnabled = false;
	}
	deviceName = alcGetString(m_audioDevice, ALC_DEVICE_SPECIFIER);
	getDebugStream() << "Using device '" << deviceName << '\'' << std::endl;

	ALCint attrs[] = {
		0, 0
	};

	m_audioContext = alcCreateContext(m_audioDevice, attrs);
	if (!alcMakeContextCurrent(m_audioContext)) {
		getDebugStream() << "Failed setting context on AL device '" << deviceName << "': " << alcGetError(m_audioDevice) << std::endl;
		alcCloseDevice(m_audioDevice);
		GlobalProperties::IsSoundEnabled = false;
	}
}

Audio::~Audio() {
	if (!GlobalProperties::IsSoundEnabled)
		return;

	alcMakeContextCurrent(nullptr);
	alcDestroyContext(m_audioContext);
	alcCloseDevice(m_audioDevice);
}

static ALfloat float3data[3], plrOrient[6];

void Audio::updateAngle() {
	const glm::vec3 &at = G->LP->camera.getLookAt(),
					&up = G->LP->camera.getUp();
	plrOrient[0] = at.x;
	plrOrient[1] = at.y;
	plrOrient[2] = at.z;
	plrOrient[3] = up.x;
	plrOrient[4] = up.y;
	plrOrient[5] = up.z;
	alListenerfv(AL_ORIENTATION, plrOrient);
}

void Audio::updatePos() {
	const glm::vec3 &pos = G->LP->position,
					&vel = G->LP->velocity;
	float3data[0] = pos.x;
	float3data[1] = pos.y;
	float3data[2] = pos.z;
	alListenerfv(AL_POSITION, float3data);
	float3data[0] = vel.x;
	float3data[1] = vel.y;
	float3data[2] = vel.z;
	alListenerfv(AL_VELOCITY, float3data);
}

void Audio::update() {
	updatePos();
	updateAngle();
}

void Audio::loadSoundAssets() {
	std::string soundsDir = getAssetsDirectory() + "/sounds/";
	for (const std::string &fn : fs::getFiles(soundsDir)) {
		if (fn.length() >= 4 && fn.substr(fn.length()-4) == ".ogg") {
			addSound(fn.substr(0, fn.length()-4), soundsDir+fn);
		}
	}
}

void Audio::addSound(const std::string& name, const std::string& path) {
	m_sounds.emplace(std::piecewise_construct,
			std::forward_as_tuple(name), std::forward_as_tuple()).first->second.loadOgg(path);
}

void Audio::playSound(const std::string &name) {
	playSound(m_sounds.at(name));
}

void Audio::playSound(const SoundBuffer &buf) {
	m_playing.emplace_back(&buf);
	m_playing.back().play();
	gc();
}

void Audio::playSound(const std::string &name, const glm::vec3 &pos) {
	playSound(m_sounds.at(name), pos);
}

void Audio::playSound(const SoundBuffer &buf, const glm::vec3& pos) {
	m_playing.emplace_back(&buf, false, pos);
	m_playing.back().play();
	gc();
}

/// Garbage Collects the sound sources
void Audio::gc() {
#if AUDIO_GC_DEBUG
	uint freed = 0;
#endif
	std::list<Sound>::const_iterator it = m_playing.begin();
	while (it != m_playing.end()) {
		if (!it->isPlaying()) {
			it = m_playing.erase(it);
#if AUDIO_GC_DEBUG
			freed++;
#endif
		} else {
			++it;
		}
	}
#if AUDIO_GC_DEBUG
	getDebugStream() << "GC'd " << freed << " sources" << std::endl;
#endif
}

}<|endoftext|>


<commit_before>// Uses ITK to convert any image format ITK understands to any format ITK understands.
// If necessary e.g. for custom/proprietory file formats, can write an ImageIO subclass
// and register it with the IO factory.

#include <boost/program_options.hpp>

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
// #include "itkVoxImageIO.h"
#include "itkVoxImageIOFactory.h"

using namespace std;

namespace po = boost::program_options;

int main(int argc, char * argv[])
{
  // PARSE COMMAND LINE OPTIONS
  po::positional_options_description pd;
  pd.add("input", 1).add("output", 1);

  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "Display this help message.")
    ("input", po::value<std::string>(), "Name of input file.  Alternative syntax to first positional parameter.")
    ("output", po::value<std::string>(), "name of output file. Alternative syntax to second positional parameter.")
  ;

  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).
            options(desc).positional(pd).run(), vm);
  po::notify(vm);

  // if --help is specified, or the usage is wrong
  if ( vm.count("help") || !vm.count("input") || !vm.count("output") ) {
    cout << "\nUsage: " << argv[0] << " input output\n\n";
    cout << desc << "\n";
    return EXIT_FAILURE;
  }

  // Register vox IO library
  itk::ObjectFactoryBase::RegisterFactory( itk::VoxImageIOFactory::New() );

  // ITK STUFF
  typedef float PixelType;
  const unsigned int Dimension = 3;
  typedef itk::Image< PixelType, Dimension > ImageType;

  typedef itk::ImageFileReader< ImageType > ReaderType;
  typedef itk::ImageFileWriter< ImageType > WriterType;

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  const char * inputFilename  = argv[1];
  const char * outputFilename = argv[2];

  reader->SetFileName( inputFilename  );
  writer->SetFileName( outputFilename );

  writer->SetInput( reader->GetOutput() );

  try
    {
    cout << "Reading...";
    reader->Update();
    cout << "done\n";
    }
  catch( itk::ExceptionObject & err )
    {
      std::cerr << "ExceptionObject caught !" << std::endl;
      std::cerr << err << std::endl;
      return EXIT_FAILURE;
    }

  try
    {
    cout << "Writing...";
    writer->Update();
    cout << "done\n";
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;

}
<commit_msg>Fixed input arguments bug.<commit_after>// Uses ITK to convert any image format ITK understands to any format ITK understands.
// If necessary e.g. for custom/proprietory file formats, can write an ImageIO subclass
// and register it with the IO factory.

#include <boost/program_options.hpp>

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
// #include "itkVoxImageIO.h"
#include "itkVoxImageIOFactory.h"

using namespace std;

namespace po = boost::program_options;

int main(int argc, char * argv[])
{
  // PARSE COMMAND LINE OPTIONS
  po::positional_options_description pd;
  pd.add("input", 1).add("output", 1);

  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "Display this help message.")
    ("input", po::value<std::string>(), "Name of input file.  Alternative syntax to first positional parameter.")
    ("output", po::value<std::string>(), "name of output file. Alternative syntax to second positional parameter.")
  ;

  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).
            options(desc).positional(pd).run(), vm);
  po::notify(vm);

  // if --help is specified, or the usage is wrong
  if ( vm.count("help") || !vm.count("input") || !vm.count("output") ) {
    cout << "\nUsage: " << argv[0] << " input output\n\n";
    cout << desc << "\n";
    return EXIT_FAILURE;
  }

  // Register vox IO library
  itk::ObjectFactoryBase::RegisterFactory( itk::VoxImageIOFactory::New() );

  // ITK STUFF
  typedef float PixelType;
  const unsigned int Dimension = 3;
  typedef itk::Image< PixelType, Dimension > ImageType;

  typedef itk::ImageFileReader< ImageType > ReaderType;
  typedef itk::ImageFileWriter< ImageType > WriterType;

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName( vm["input"].as<std::string>()  );
  writer->SetFileName( vm["output"].as<std::string>() );

  writer->SetInput( reader->GetOutput() );

  try
    {
    cout << "Reading...";
    reader->Update();
    cout << "done\n";
    }
  catch( itk::ExceptionObject & err )
    {
      std::cerr << "ExceptionObject caught !" << std::endl;
      std::cerr << err << std::endl;
      return EXIT_FAILURE;
    }

  try
    {
    cout << "Writing...";
    writer->Update();
    cout << "done\n";
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before><commit_msg>Add steering function<commit_after><|endoftext|>


<commit_before>#include "RTSContainableComponent.h"

#include "GameFramework/Actor.h"
#include "Net/UnrealNetwork.h"

#include "RTSContainerComponent.h"
#include "RTSLog.h"
#include "Combat/RTSHealthComponent.h"

URTSContainableComponent::URTSContainableComponent(const FObjectInitializer& ObjectInitializer /*= FObjectInitializer::Get()*/)
    : Super(ObjectInitializer)
{
    SetIsReplicated(true);
}

void URTSContainableComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(URTSContainableComponent, Container);
}

void URTSContainableComponent::BeginPlay()
{
    Super::BeginPlay();

    AActor* Owner = GetOwner();

    if (!IsValid(Owner))
    {
        return;
    }

    URTSHealthComponent* HealthComponent = Owner->FindComponentByClass<URTSHealthComponent>();

    if (!IsValid(HealthComponent))
    {
        return;
    }

    HealthComponent->OnKilled.AddDynamic(this, &URTSContainableComponent::OnKilled);
}

AActor* URTSContainableComponent::GetContainer() const
{
    return Container;
}

void URTSContainableComponent::SetContainer(AActor* NewContainer)
{
    if (Container == NewContainer)
    {
        return;
    }

    Container = NewContainer;

    // Notify listeners.
    OnContainerChanged.Broadcast(GetOwner(), NewContainer);
}

void URTSContainableComponent::ReceivedContainer()
{
    // Notify listeners.
    OnContainerChanged.Broadcast(GetOwner(), Container);
}

void URTSContainableComponent::OnKilled(AActor* Actor, AController* PreviousOwner, AActor* DamageCauser)
{
    if (!IsValid(Container))
    {
        return;
    }

    AActor* Owner = GetOwner();

    if (!IsValid(Owner))
    {
        return;
    }

    // Unload from all containers.
    TArray<URTSContainerComponent*> ContainerComponents;
    Container->GetComponents(ContainerComponents);

    for (URTSContainerComponent* ContainerComponent : ContainerComponents)
    {
        if (ContainerComponent->ContainsActor(Owner))
        {
            UE_LOG(LogRTS, Log, TEXT("Unloading actor %s from container %s because it was killed while being inside."),
                *Owner->GetName(), *Container->GetName());

            ContainerComponent->UnloadActor(Owner);
        }
    }
}
<commit_msg>Use SetIsReplicatedByDefault for RTSContainableComponent.<commit_after>#include "RTSContainableComponent.h"

#include "GameFramework/Actor.h"
#include "Net/UnrealNetwork.h"

#include "RTSContainerComponent.h"
#include "RTSLog.h"
#include "Combat/RTSHealthComponent.h"

URTSContainableComponent::URTSContainableComponent(const FObjectInitializer& ObjectInitializer /*= FObjectInitializer::Get()*/)
    : Super(ObjectInitializer)
{
    SetIsReplicatedByDefault(true);
}

void URTSContainableComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(URTSContainableComponent, Container);
}

void URTSContainableComponent::BeginPlay()
{
    Super::BeginPlay();

    AActor* Owner = GetOwner();

    if (!IsValid(Owner))
    {
        return;
    }

    URTSHealthComponent* HealthComponent = Owner->FindComponentByClass<URTSHealthComponent>();

    if (!IsValid(HealthComponent))
    {
        return;
    }

    HealthComponent->OnKilled.AddDynamic(this, &URTSContainableComponent::OnKilled);
}

AActor* URTSContainableComponent::GetContainer() const
{
    return Container;
}

void URTSContainableComponent::SetContainer(AActor* NewContainer)
{
    if (Container == NewContainer)
    {
        return;
    }

    Container = NewContainer;

    // Notify listeners.
    OnContainerChanged.Broadcast(GetOwner(), NewContainer);
}

void URTSContainableComponent::ReceivedContainer()
{
    // Notify listeners.
    OnContainerChanged.Broadcast(GetOwner(), Container);
}

void URTSContainableComponent::OnKilled(AActor* Actor, AController* PreviousOwner, AActor* DamageCauser)
{
    if (!IsValid(Container))
    {
        return;
    }

    AActor* Owner = GetOwner();

    if (!IsValid(Owner))
    {
        return;
    }

    // Unload from all containers.
    TArray<URTSContainerComponent*> ContainerComponents;
    Container->GetComponents(ContainerComponents);

    for (URTSContainerComponent* ContainerComponent : ContainerComponents)
    {
        if (ContainerComponent->ContainsActor(Owner))
        {
            UE_LOG(LogRTS, Log, TEXT("Unloading actor %s from container %s because it was killed while being inside."),
                *Owner->GetName(), *Container->GetName());

            ContainerComponent->UnloadActor(Owner);
        }
    }
}
<|endoftext|>


<commit_before>#include "GUINode.h"

wxIMPLEMENT_DYNAMIC_CLASS(GUINode, wxControl);

void GUINode::Init()
{
	// Compute the best width
	m_bestSize.SetWidth(200); // Must be computed depending on the lengths of the inputs and outputs parameters
	// Compute the best height
	int nbInputs = m_node.GetInputs().size();
	int nbOutputs = m_node.GetOutputs().size();
	m_maxParamsPerColumn = nbInputs > nbOutputs ? nbInputs : nbOutputs;
	m_bestSize.SetHeight((1 + m_maxParamsPerColumn) * 50); // MAGIC NUMBER here : we say 50 pixels per param and 50 pixels for the node's name

	// Defines the size of the widget
	SetSize(m_bestSize);

	// Add a sizer to manage the space inside the node
	wxSizer* verticalSizer = new wxBoxSizer(wxVERTICAL);
	wxStaticText* titleText = new wxStaticText(this, wxID_ANY, "Title");
	verticalSizer->Add(titleText, 1, wxALL | wxALIGN_CENTER);

	// TODO Add horizontal sizers to distribute the space for each input/output

	SetSizer(verticalSizer);
	Layout();
	SetBackgroundColour(*wxGREEN);

	titleText->Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
	titleText->Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
	titleText->Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);

	Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
	Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);
	Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
	Bind(wxEVT_PAINT, &GUINode::OnPaint, this);
}

wxSize GUINode::DoGetBestSize() const
{
	return m_bestSize;
}

void GUINode::OnPaint(wxPaintEvent &event)
{
	wxPaintDC dc(this);
	wxGraphicsContext *gc = wxGraphicsContext::Create(dc);
	wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);

	int height = GetSize().GetHeight() - 1;
	int width = GetSize().GetWidth() - 1;
	int i = 0;
	if (gc)
	{
		// Draw the body
		gc->SetBrush(*wxRED_BRUSH);
		gc->SetPen(wxPen(*wxBLACK, 1));
		gc->DrawRoundedRectangle(0, 0, m_bestSize.GetWidth() - 1, m_bestSize.GetHeight() - 1, 10);

		gc->SetBrush(*wxBLUE_BRUSH);
		gc->SetFont(font, *wxBLACK);
		i = 0;
		// Draw the inputs
		for (InputParam p : m_node.GetInputs()) {
			gc->DrawEllipse(10, (i+0.5f)*height / m_maxParamsPerColumn, 25, 25);
			gc->DrawText(p.GetName(), 50, (i + 0.5f)*height / m_maxParamsPerColumn);
			i++;
		}
		i = 0;
		// Draw the outputs
		for (OutputParam p : m_node.GetOutputs()) {
			gc->DrawEllipse(width-50, (i+0.5f)*height / m_maxParamsPerColumn, 25, 25);
			gc->DrawText(p.GetName(), width-100, (i + 0.5f)*height / m_maxParamsPerColumn);
			i++;
		}

		delete gc;
	}

	event.Skip();
}

void GUINode::OnLeftMouseDown(wxMouseEvent& event)
{
	m_isDragging = true;
	m_firstDraggingPoint = ScreenToClient(ClientToScreen(event.GetPosition()));
}

void GUINode::OnLeftMouseUp(wxMouseEvent& event)
{
	m_isDragging = false;
}

void GUINode::OnMouseMotion(wxMouseEvent& event)
{
	if (m_isDragging && event.LeftIsDown())
		SetPosition(m_parent->ScreenToClient(ClientToScreen(event.GetPosition())) - m_firstDraggingPoint);
}<commit_msg>Added the new GUI of the GUINode : only wxWidgets widgets and sizers.<commit_after>#include "GUINode.h"

wxIMPLEMENT_DYNAMIC_CLASS(GUINode, wxControl);

void GUINode::Init()
{
	// Compute the best width
	m_bestSize.SetWidth(200); // Must be computed depending on the lengths of the inputs and outputs parameters
	// Compute the best height
	int nbInputs = m_node.GetInputs().size();
	int nbOutputs = m_node.GetOutputs().size();
	m_maxParamsPerColumn = nbInputs > nbOutputs ? nbInputs : nbOutputs;
	m_bestSize.SetHeight((1 + m_maxParamsPerColumn) * 50); // MAGIC NUMBER here : we say 50 pixels per param and 50 pixels for the node's name

	// Defines the size of the widget
	SetSize(m_bestSize);

	// Add a sizer to manage the space inside the node
	wxSizer* verticalSizer = new wxBoxSizer(wxVERTICAL);
	wxStaticText* titleText = new wxStaticText(this, wxID_ANY, "Title", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
	verticalSizer->Add(titleText, 1, wxALL | wxEXPAND);

	// TODO Add horizontal sizers to distribute the space for each input/output
	for (int i = 0; i < m_maxParamsPerColumn; i++) {
		wxSizer* horizontalSizer = new wxBoxSizer(wxHORIZONTAL);
		// TODO change this text to a specific class GUINodeInput
		wxStaticText* guiNodeInput = new wxStaticText(this, wxID_ANY, "I", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
		wxStaticText* guiNodeOutput = new wxStaticText(this, wxID_ANY, "O", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
		wxStaticText* intputText = new wxStaticText(this, wxID_ANY, i<nbInputs ? m_node.GetInputs()[i].GetName() : "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
		wxStaticText* outputText = new wxStaticText(this, wxID_ANY, i<nbOutputs ? m_node.GetOutputs()[i].GetName() : "", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);

		horizontalSizer->Add(guiNodeInput, 1, wxALL | wxALIGN_CENTRE_VERTICAL);
		horizontalSizer->Add(intputText, 1, wxALL | wxALIGN_CENTRE_VERTICAL);
		horizontalSizer->Add(outputText, 1, wxALL | wxALIGN_CENTRE_VERTICAL);
		horizontalSizer->Add(guiNodeOutput, 1, wxALL | wxALIGN_CENTRE_VERTICAL);

		verticalSizer->Add(horizontalSizer, 1, wxALL | wxEXPAND);

		guiNodeInput->Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
		guiNodeInput->Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
		guiNodeInput->Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);
		guiNodeOutput->Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
		guiNodeOutput->Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
		guiNodeOutput->Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);
		intputText->Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
		intputText->Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
		intputText->Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);
		outputText->Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
		outputText->Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
		outputText->Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);
	}

	SetSizer(verticalSizer);
	Layout();
	SetBackgroundColour(*wxGREEN);

	titleText->Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
	titleText->Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
	titleText->Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);

	Bind(wxEVT_LEFT_DOWN, &GUINode::OnLeftMouseDown, this);
	Bind(wxEVT_LEFT_UP, &GUINode::OnLeftMouseUp, this);
	Bind(wxEVT_MOTION, &GUINode::OnMouseMotion, this);
	Bind(wxEVT_PAINT, &GUINode::OnPaint, this);
}

wxSize GUINode::DoGetBestSize() const
{
	return m_bestSize;
}

void GUINode::OnPaint(wxPaintEvent &event)
{
	wxPaintDC dc(this);
	wxGraphicsContext *gc = wxGraphicsContext::Create(dc);
	wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);

	int height = GetSize().GetHeight() - 1;
	int width = GetSize().GetWidth() - 1;
	int i = 0;
	if (gc)
	{
		// Draw the body
		gc->SetBrush(*wxRED_BRUSH);
		gc->SetPen(wxPen(*wxBLACK, 1));
		gc->DrawRoundedRectangle(0, 0, m_bestSize.GetWidth() - 1, m_bestSize.GetHeight() - 1, 10);

		gc->SetBrush(*wxBLUE_BRUSH);
		gc->SetFont(font, *wxBLACK);
		i = 0;
		// Draw the inputs
		for (InputParam p : m_node.GetInputs()) {
			gc->DrawEllipse(10, (i+0.5f)*height / m_maxParamsPerColumn, 25, 25);
			gc->DrawText(p.GetName(), 50, (i + 0.5f)*height / m_maxParamsPerColumn);
			i++;
		}
		i = 0;
		// Draw the outputs
		for (OutputParam p : m_node.GetOutputs()) {
			gc->DrawEllipse(width-50, (i+0.5f)*height / m_maxParamsPerColumn, 25, 25);
			gc->DrawText(p.GetName(), width-100, (i + 0.5f)*height / m_maxParamsPerColumn);
			i++;
		}

		delete gc;
	}

	event.Skip();
}

void GUINode::OnLeftMouseDown(wxMouseEvent& event)
{
	m_isDragging = true;
	m_firstDraggingPoint = ScreenToClient(ClientToScreen(event.GetPosition()));
}

void GUINode::OnLeftMouseUp(wxMouseEvent& event)
{
	m_isDragging = false;
}

void GUINode::OnMouseMotion(wxMouseEvent& event)
{
	if (m_isDragging)
		SetPosition(m_parent->ScreenToClient(ClientToScreen(event.GetPosition())) - m_firstDraggingPoint);
}<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <math.h>
#include <igvc_msgs/velocity_pair.h>
#include "Odometer.h"

/**
 * Coneverts wheel velocities to odometry message using trigonometry for calculations
 * In the ros coordinate convention x is forward, y is leftward, and z is upward relative to the robot
 * The position is published in an absolute reference frame relative to the initial position
 * The velocities (twist) is in a reference frame relative to the robot
*/
void Odometer::enc_callback(const igvc_msgs::velocity_pair& msg) {
    float leftVelocity = msg.left_velocity;
    float rightVelocity = msg.right_velocity;
    float deltaT = msg.duration;

    float angularVelocity = (rightVelocity - leftVelocity) / WHEEL_SEPARATION;
    float deltaTheta = angularVelocity * deltaT;
    float velocity = (rightVelocity + leftVelocity) / 2;

    geometry_msgs::Vector3 linearVelocities;
    linearVelocities.z = 0;

    if (abs(rightVelocity - leftVelocity) > 1e-4) {  // 1e-4 is the point where less of a difference is straight
        linearVelocities.y = velocity * sin(deltaTheta);
        linearVelocities.x = velocity * cos(deltaTheta);
    } else {
        // limit where turn radius is infinite (ie. straight line)
        linearVelocities.y = 0;
        linearVelocities.x = velocity;
    }

    // set angular velocities - assuming 2D operation
    geometry_msgs::Vector3 angularVelocities;
    angularVelocities.x = 0.0;
    angularVelocities.y = 0.0;
    angularVelocities.z = angularVelocity;

    nav_msgs::Odometry odom;
    odom.twist.twist.linear = linearVelocities;
    odom.twist.twist.angular = angularVelocities;

    // update global positions
    // note x and y velocities are local reference frame - convert to global then increment poition
    float dx = linearVelocities.x * deltaT;
    float dy = linearVelocities.y * deltaT;
    x += dx * cos(yaw) - dy * sin(yaw);
    y += dx * sin(yaw) + dy * cos(yaw);
    yaw += deltaTheta;

    // enter message info for global position
    odom.pose.pose.position.x = x;
    odom.pose.pose.position.y = y;
    odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(yaw);

    // Row-major representation of the 6x6 covariance matrix
    // The orientation parameters use a fixed-axis representation.
    // In order, the parameters are:
    // (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis)
    // TODO replace with calculated values
    odom.twist.covariance = {
            .01, .01, .01, .01, .01, .01,
            .01, .01, .01, .01, .01, .01,
            .01, .01, .01, .01, .01, .01,
            .01, .01, .01, .01, .01, .01,
            .01, .01, .01, .01, .01, .01,
            .01, .01, .01, .01, .01, .01
    };
    // the position covariance takes same form as twist covariance above
    // this grows without bounds as error accumulates - disregard exact reading with high variance
    odom.pose.covariance = {
             1e6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6,
            1e-6,  1e6, 1e-6, 1e-6, 1e-6, 1e-6,
            1e-6, 1e-6,  1e6, 1e-6, 1e-6, 1e-6,
            1e-6, 1e-6, 1e-6,  1e6, 1e-6, 1e-6,
            1e-6, 1e-6, 1e-6, 1e-6,  1e6, 1e-6,
            1e-6, 1e-6, 1e-6, 1e-6, 1e-6,  1e6
    };

    // setting sequence of message
    odom.header.seq = seq++;

    // setting reference frames
    odom.header.frame_id = "wheel_odom";
    odom.child_frame_id = "base_link";

    // set time then publish
    odom.header.stamp = ros::Time::now();
    pub.publish(odom);

    // publish the tf using the published odom message
    geometry_msgs::TransformStamped odom_tf;
    odom_tf.header.stamp = ros::Time::now();
    odom_tf.transform.translation.x = odom.pose.pose.position.x;
    odom_tf.transform.translation.y = odom.pose.pose.position.y;
    odom_tf.transform.translation.z = 0;
    odom_tf.transform.rotation = odom.pose.pose.orientation;

    // initializing default odom tf
    odom_tf.header.frame_id = "wheel_odom";
    odom_tf.child_frame_id = "base_link";

    odom_broadcaster.sendTransform(odom_tf);
}

Odometer::Odometer(ros::NodeHandle& nh) {
    sub = nh.subscribe("/encoders", 10, &Odometer::enc_callback, this);
    pub = nh.advertise<nav_msgs::Odometry>("/wheel_odometry", 10);

    // initializing sequence number for messages
    seq = 0;

    // initialize position - map published is relative to position at time t=0
    x = 0;
    y = 0;
    yaw = 0;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "wheel_odom");
    ros::NodeHandle nh;

    Odometer odom(nh);

    ROS_INFO_STREAM("wheel odometry node has started");

    ros::spin();
}
<commit_msg>added linear velocity covariances - will need tuning on new robot<commit_after>#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <math.h>
#include <igvc_msgs/velocity_pair.h>
#include "Odometer.h"

/**
 * Coneverts wheel velocities to odometry message using trigonometry for calculations
 * In the ros coordinate convention x is forward, y is leftward, and z is upward relative to the robot
 * The position is published in an absolute reference frame relative to the initial position
 * The velocities (twist) is in a reference frame relative to the robot
*/
void Odometer::enc_callback(const igvc_msgs::velocity_pair& msg) {
    float leftVelocity = msg.left_velocity;
    float rightVelocity = msg.right_velocity;
    float deltaT = msg.duration;

    float angularVelocity = (rightVelocity - leftVelocity) / WHEEL_SEPARATION;
    float deltaTheta = angularVelocity * deltaT;
    float velocity = (rightVelocity + leftVelocity) / 2;

    geometry_msgs::Vector3 linearVelocities;
    linearVelocities.z = 0;

    if (abs(rightVelocity - leftVelocity) > 1e-4) {  // 1e-4 is the point where less of a difference is straight
        linearVelocities.y = velocity * sin(deltaTheta);
        linearVelocities.x = velocity * cos(deltaTheta);
    } else {
        // limit where turn radius is infinite (ie. straight line)
        linearVelocities.y = 0;
        linearVelocities.x = velocity;
    }

    // set angular velocities - assuming 2D operation
    geometry_msgs::Vector3 angularVelocities;
    angularVelocities.x = 0.0;
    angularVelocities.y = 0.0;
    angularVelocities.z = angularVelocity;

    nav_msgs::Odometry odom;
    odom.twist.twist.linear = linearVelocities;
    odom.twist.twist.angular = angularVelocities;

    // update global positions
    // note x and y velocities are local reference frame - convert to global then increment poition
    float dx = linearVelocities.x * deltaT;
    float dy = linearVelocities.y * deltaT;
    x += dx * cos(yaw) - dy * sin(yaw);
    y += dx * sin(yaw) + dy * cos(yaw);
    yaw += deltaTheta;

    // enter message info for global position
    odom.pose.pose.position.x = x;
    odom.pose.pose.position.y = y;
    odom.pose.pose.orientation = tf::createQuaternionMsgFromYaw(yaw);

    // Row-major representation of the 6x6 covariance matrix
    // The orientation parameters use a fixed-axis representation.
    // In order, the parameters are:
    // (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis)
    odom.twist.covariance = {
            0.02, 1e-4, 1e-4, 1e-4, 1e-4, 1e-4,
            1e-4, 0.05, 1e-4, 1e-4, 1e-4, 1e-4,
            1e-4, 1e-4,  1e6, 1e-4, 1e-4, 1e-4,
            1e-4, 1e-4, 1e-4,  1e6, 1e-4, 1e-4,
            1e-4, 1e-4, 1e-4, 1e-4,  1e6, 1e-4,
            1e-4, 1e-4, 1e-4, 1e-4, 1e-4, 0.02,
    };
    // the position covariance takes same form as twist covariance above
    // this grows without bounds as error accumulates - disregard exact reading with high variance
    odom.pose.covariance = {
             1e6, 1e-6, 1e-6, 1e-6, 1e-6, 1e-6,
            1e-6,  1e6, 1e-6, 1e-6, 1e-6, 1e-6,
            1e-6, 1e-6,  1e6, 1e-6, 1e-6, 1e-6,
            1e-6, 1e-6, 1e-6,  1e6, 1e-6, 1e-6,
            1e-6, 1e-6, 1e-6, 1e-6,  1e6, 1e-6,
            1e-6, 1e-6, 1e-6, 1e-6, 1e-6,  1e6
    };

    // setting sequence of message
    odom.header.seq = seq++;

    // setting reference frames
    odom.header.frame_id = "wheel_odom";
    odom.child_frame_id = "base_link";

    // set time then publish
    odom.header.stamp = ros::Time::now();
    pub.publish(odom);

    // publish the tf using the published odom message
    geometry_msgs::TransformStamped odom_tf;
    odom_tf.header.stamp = ros::Time::now();
    odom_tf.transform.translation.x = odom.pose.pose.position.x;
    odom_tf.transform.translation.y = odom.pose.pose.position.y;
    odom_tf.transform.translation.z = 0;
    odom_tf.transform.rotation = odom.pose.pose.orientation;

    // initializing default odom tf
    odom_tf.header.frame_id = "wheel_odom";
    odom_tf.child_frame_id = "base_link";

    odom_broadcaster.sendTransform(odom_tf);
}

Odometer::Odometer(ros::NodeHandle& nh) {
    sub = nh.subscribe("/encoders", 10, &Odometer::enc_callback, this);
    pub = nh.advertise<nav_msgs::Odometry>("/wheel_odometry", 10);

    // initializing sequence number for messages
    seq = 0;

    // initialize position - map published is relative to position at time t=0
    x = 0;
    y = 0;
    yaw = 0;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "wheel_odom");
    ros::NodeHandle nh;

    Odometer odom(nh);

    ROS_INFO_STREAM("wheel odometry node has started");

    ros::spin();
}
<|endoftext|>


<commit_before>#include "../base/SRC_FIRST.hpp"

#include "mainwindow.hpp"
#include "draw_widget.hpp"
#include "update_dialog.hpp"
#include "searchwindow.hpp"
#include "classificator_tree.hpp"
#include "slider_ctrl.hpp"
#include "about.hpp"
#include "preferences_dialog.hpp"
#include "info_dialog.hpp"
#include "guide_page.hpp"

#include "../defines.hpp"

#include "../map/settings.hpp"

#include "../indexer/classificator.hpp"

#include <QtGui/QDockWidget>
#include <QtGui/QToolBar>
#include <QtGui/QAction>
#include <QtGui/QMenuBar>
#include <QtGui/QMenu>

#include <QtCore/QFile>

#include "../base/start_mem_debug.hpp"

#define IDM_ABOUT_DIALOG        1001
#define IDM_PREFERENCES_DIALOG  1002

namespace qt
{

MainWindow::MainWindow() : m_updateDialog(0)
{
  m_pDrawWidget = new DrawWidget(this, m_storage);

  CreateNavigationBar();

  CreateClassifPanel();
  CreateGuidePanel();

  setCentralWidget(m_pDrawWidget);

  setWindowTitle(tr("MapsWithMe"));
  setWindowIcon(QIcon(":logo.png"));

#ifndef OMIM_OS_WINDOWS
  QMenu * helpMenu = new QMenu(tr("Help"), this);
  menuBar()->addMenu(helpMenu);
  helpMenu->addAction(tr("About"), this, SLOT(OnAbout()));
  helpMenu->addAction(tr("Preferences"), this, SLOT(OnPreferences()));
#else
  {
    // create items in the system menu
    QByteArray const aboutStr = tr("About MapsWithMe...").toLocal8Bit();
    QByteArray const prefsStr = tr("Preferences...").toLocal8Bit();
    // we use system menu for our items
    HMENU menu = ::GetSystemMenu(winId(), FALSE);
    MENUITEMINFOA item;
    item.cbSize = sizeof(MENUITEMINFOA);
    item.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
    item.fType = MFT_STRING;
    item.wID = IDM_PREFERENCES_DIALOG;
    item.dwTypeData = const_cast<char *>(prefsStr.data());
    item.cch = prefsStr.size();
    ::InsertMenuItemA(menu, ::GetMenuItemCount(menu) - 1, TRUE, &item);
    item.wID = IDM_ABOUT_DIALOG;
    item.dwTypeData = const_cast<char *>(aboutStr.data());
    item.cch = aboutStr.size();
    ::InsertMenuItemA(menu, ::GetMenuItemCount(menu) - 1, TRUE, &item);
    item.fType = MFT_SEPARATOR;
    ::InsertMenuItemA(menu, ::GetMenuItemCount(menu) - 1, TRUE, &item);
  }
#endif

  LoadState();

  // Show intro dialog if necessary
  bool bShow = true;
  (void)Settings::Get("ShowWelcome", bShow);

  if (bShow)
  {
    QFile welcomeTextFile(GetPlatform().ReadPathForFile("welcome.html").c_str());

    bool bShowUpdateDialog = true;

    if (welcomeTextFile.open(QIODevice::ReadOnly))
    {
      QByteArray text = welcomeTextFile.readAll();
      welcomeTextFile.close();

      InfoDialog welcomeDlg(tr("Welcome to MapsWithMe!"), text, this, QStringList(tr("Download Maps")));
      if (welcomeDlg.exec() == QDialog::Rejected)
        bShowUpdateDialog = false;
    }
    Settings::Set("ShowWelcome", false);

    if (bShowUpdateDialog)
      ShowUpdateDialog();
  }
}

#if defined(Q_WS_WIN)
bool MainWindow::winEvent(MSG * msg, long * result)
{
  if (msg->message == WM_SYSCOMMAND)
  {
    if (msg->wParam == IDM_PREFERENCES_DIALOG)
    {
      OnPreferences();
      *result = 0;
      return true;
    }
    else if (msg->wParam == IDM_ABOUT_DIALOG)
    {
      OnAbout();
      *result = 0;
      return true;
    }
  }
  return false;
}
#endif

MainWindow::~MainWindow()
{
  SaveState();

  GetDownloadManager().CancelAllDownloads();
}

void MainWindow::SaveState()
{
  pair<uint32_t, uint32_t> xAndY(x(), y());
  pair<uint32_t, uint32_t> widthAndHeight(width(), height());
  Settings::Set("MainWindowXY", xAndY);
  Settings::Set("MainWindowSize", widthAndHeight);

  m_pDrawWidget->SaveState();
}

void MainWindow::LoadState()
{
  pair<uint32_t, uint32_t> xAndY;
  pair<uint32_t, uint32_t> widthAndHeight;
  bool loaded = Settings::Get("MainWindowXY", xAndY) &&
                Settings::Get("MainWindowSize", widthAndHeight);
  if (loaded)
  {
    move(xAndY.first, xAndY.second);
    resize(widthAndHeight.first, widthAndHeight.second);

    loaded = m_pDrawWidget->LoadState();
  }

  if (!loaded)
  {
    showMaximized();
    m_pDrawWidget->ShowAll();
  }
  else
    m_pDrawWidget->UpdateNow();
}

void MainWindow::CreateClassifPanel()
{
  CreatePanelImpl(0, tr("Classificator Bar"),
                  QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), SLOT(ShowClassifPanel()));

  ClassifTreeHolder * pCTree = new ClassifTreeHolder(m_Docks[0], m_pDrawWidget, SLOT(Repaint()));
  pCTree->SetRoot(classif().GetMutableRoot());

  m_Docks[0]->setWidget(pCTree);
}

void MainWindow::CreateGuidePanel()
{
  CreatePanelImpl(1, tr("Guide Bar"),
                  QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_G), SLOT(ShowGuidePanel()));

  qt::GuidePageHolder * pGPage = new qt::GuidePageHolder(m_Docks[1]);

  m_Docks[1]->setWidget(pGPage);
}

void MainWindow::CreatePanelImpl(size_t i, QString const & name,
                                 QKeySequence const & hotkey, char const * slot)
{
  m_Docks[i] = new QDockWidget(name, this);

  addDockWidget(Qt::LeftDockWidgetArea, m_Docks[i]);

  // hide by default
  m_Docks[i]->hide();

  // register a hotkey to show classificator panel
  QAction * pAct = new QAction(this);
  pAct->setShortcut(hotkey);
  connect(pAct, SIGNAL(triggered()), this, slot);
  addAction(pAct);
}

namespace
{
  struct button_t
  {
    QString name;
    char const * icon;
    char const * slot;
  };

  void add_buttons(QToolBar * pBar, button_t buttons[], size_t count, QWidget * pReceiver)
  {
    for (size_t i = 0; i < count; ++i)
    {
      if (buttons[i].icon)
        pBar->addAction(QIcon(buttons[i].icon), buttons[i].name, pReceiver, buttons[i].slot);
      else
        pBar->addSeparator();
    }
  }
}

void MainWindow::CreateNavigationBar()
{
  QToolBar * pBar = new QToolBar(tr("Navigation Bar"), this);
  pBar->setOrientation(Qt::Vertical);
  pBar->setIconSize(QSize(32, 32));

  {
    // add my position button with "checked" behavior
    m_pMyPosition = pBar->addAction(QIcon(":/navig64/location.png"),
                                           tr("My Position"),
                                           this,
                                           SLOT(OnMyPosition()));
    m_pMyPosition->setCheckable(true);

    // add view actions 1
    button_t arr[] = {
      { tr("Left"), ":/navig64/left.png", SLOT(MoveLeft()) },
      { tr("Right"), ":/navig64/right.png", SLOT(MoveRight()) },
      { tr("Up"), ":/navig64/up.png", SLOT(MoveUp()) },
      { tr("Down"), ":/navig64/down.png", SLOT(MoveDown()) },
      { tr("Show all"), ":/navig64/world.png", SLOT(ShowAll()) },
      { QString(), 0, 0 },
      { tr("Scale +"), ":/navig64/plus.png", SLOT(ScalePlus()) }
    };
    add_buttons(pBar, arr, ARRAY_SIZE(arr), m_pDrawWidget);
  }

  // add scale slider
  QClickSlider * pScale = new QClickSlider(Qt::Vertical, this);
  pScale->setRange(0, scales::GetUpperScale());
  pScale->setTickPosition(QSlider::TicksRight);

  pBar->addWidget(pScale);
  m_pDrawWidget->SetScaleControl(pScale);

  {
    // add view actions 2
    button_t arr[] = {
      { tr("Scale -"), ":/navig64/minus.png", SLOT(ScaleMinus()) },
      { QString(), 0, 0 }
    };
    add_buttons(pBar, arr, ARRAY_SIZE(arr), m_pDrawWidget);
  }

  {
    // add mainframe actions
    button_t arr[] = {
      { tr("Download Maps"), ":/navig64/download.png", SLOT(ShowUpdateDialog()) }
    };
    add_buttons(pBar, arr, ARRAY_SIZE(arr), this);
  }

  addToolBar(Qt::RightToolBarArea, pBar);
}

//void MainWindow::CreateFindTable(QLayout * pLayout)
//{
//  // find widget
//  FindEditorWnd * pEditor = new FindEditorWnd(0);
//  pLayout->addWidget(pEditor);
//
//  // find table result
//  m_pFindTable = new FindTableWnd(0, pEditor, m_pDrawWidget->GetModel());
//  pLayout->addWidget(m_pFindTable);
//  connect(m_pFindTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnFeatureClicked(int, int)));
//  connect(m_pFindTable, SIGNAL(cellEntered(int, int)), this, SLOT(OnFeatureEntered(int, int)));
//}
//
//void MainWindow::OnFeatureEntered(int /*row*/, int /*col*/)
//{
//  //Feature const & p = m_pFindTable->GetFeature(row);
//
//  /// @todo highlight the feature
//}
//
//void MainWindow::OnFeatureClicked(int row, int /*col*/)
//{
//  Feature const & p = m_pFindTable->GetFeature(row);
//  m_pDrawWidget->ShowFeature(p);
//}

void MainWindow::ShowUpdateDialog()
{
  if (!m_updateDialog)
    m_updateDialog = new UpdateDialog(this, m_storage);
  m_updateDialog->ShowDialog();
}

void MainWindow::ShowClassifPanel()
{
  m_Docks[0]->show();
}

void MainWindow::ShowGuidePanel()
{
  m_Docks[1]->show();
}

void MainWindow::OnAbout()
{
  AboutDialog dlg(this);
  dlg.exec();
}

void MainWindow::OnPreferences()
{
  bool autoUpdatesEnabled = DEFAULT_AUTO_UPDATES_ENABLED;
  Settings::Get("AutomaticUpdateCheck", autoUpdatesEnabled);

  PreferencesDialog dlg(this, autoUpdatesEnabled);
  dlg.exec();

  Settings::Set("AutomaticUpdateCheck", autoUpdatesEnabled);
}

void MainWindow::OnLocationFound()
{
  m_pMyPosition->setIcon(QIcon(":/navig64/location.png"));
}

void MainWindow::OnMyPosition()
{
  if (m_pMyPosition->isChecked())
  {
    m_pMyPosition->setIcon(QIcon(":/navig64/location-search.png"));
    m_pDrawWidget->OnEnableMyPosition(boost::bind(&MainWindow::OnLocationFound, this));
  }
  else
  {
    m_pMyPosition->setIcon(QIcon(":/navig64/location.png"));
    m_pDrawWidget->OnDisableMyPosition();
  }
}

}
<commit_msg>[qt] Added tooltips for my position<commit_after>#include "../base/SRC_FIRST.hpp"

#include "mainwindow.hpp"
#include "draw_widget.hpp"
#include "update_dialog.hpp"
#include "searchwindow.hpp"
#include "classificator_tree.hpp"
#include "slider_ctrl.hpp"
#include "about.hpp"
#include "preferences_dialog.hpp"
#include "info_dialog.hpp"
#include "guide_page.hpp"

#include "../defines.hpp"

#include "../map/settings.hpp"

#include "../indexer/classificator.hpp"

#include <QtGui/QDockWidget>
#include <QtGui/QToolBar>
#include <QtGui/QAction>
#include <QtGui/QMenuBar>
#include <QtGui/QMenu>

#include <QtCore/QFile>

#include "../base/start_mem_debug.hpp"

#define IDM_ABOUT_DIALOG        1001
#define IDM_PREFERENCES_DIALOG  1002

namespace qt
{

MainWindow::MainWindow() : m_updateDialog(0)
{
  m_pDrawWidget = new DrawWidget(this, m_storage);

  CreateNavigationBar();

  CreateClassifPanel();
  CreateGuidePanel();

  setCentralWidget(m_pDrawWidget);

  setWindowTitle(tr("MapsWithMe"));
  setWindowIcon(QIcon(":logo.png"));

#ifndef OMIM_OS_WINDOWS
  QMenu * helpMenu = new QMenu(tr("Help"), this);
  menuBar()->addMenu(helpMenu);
  helpMenu->addAction(tr("About"), this, SLOT(OnAbout()));
  helpMenu->addAction(tr("Preferences"), this, SLOT(OnPreferences()));
#else
  {
    // create items in the system menu
    QByteArray const aboutStr = tr("About MapsWithMe...").toLocal8Bit();
    QByteArray const prefsStr = tr("Preferences...").toLocal8Bit();
    // we use system menu for our items
    HMENU menu = ::GetSystemMenu(winId(), FALSE);
    MENUITEMINFOA item;
    item.cbSize = sizeof(MENUITEMINFOA);
    item.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
    item.fType = MFT_STRING;
    item.wID = IDM_PREFERENCES_DIALOG;
    item.dwTypeData = const_cast<char *>(prefsStr.data());
    item.cch = prefsStr.size();
    ::InsertMenuItemA(menu, ::GetMenuItemCount(menu) - 1, TRUE, &item);
    item.wID = IDM_ABOUT_DIALOG;
    item.dwTypeData = const_cast<char *>(aboutStr.data());
    item.cch = aboutStr.size();
    ::InsertMenuItemA(menu, ::GetMenuItemCount(menu) - 1, TRUE, &item);
    item.fType = MFT_SEPARATOR;
    ::InsertMenuItemA(menu, ::GetMenuItemCount(menu) - 1, TRUE, &item);
  }
#endif

  LoadState();

  // Show intro dialog if necessary
  bool bShow = true;
  (void)Settings::Get("ShowWelcome", bShow);

  if (bShow)
  {
    QFile welcomeTextFile(GetPlatform().ReadPathForFile("welcome.html").c_str());

    bool bShowUpdateDialog = true;

    if (welcomeTextFile.open(QIODevice::ReadOnly))
    {
      QByteArray text = welcomeTextFile.readAll();
      welcomeTextFile.close();

      InfoDialog welcomeDlg(tr("Welcome to MapsWithMe!"), text, this, QStringList(tr("Download Maps")));
      if (welcomeDlg.exec() == QDialog::Rejected)
        bShowUpdateDialog = false;
    }
    Settings::Set("ShowWelcome", false);

    if (bShowUpdateDialog)
      ShowUpdateDialog();
  }
}

#if defined(Q_WS_WIN)
bool MainWindow::winEvent(MSG * msg, long * result)
{
  if (msg->message == WM_SYSCOMMAND)
  {
    if (msg->wParam == IDM_PREFERENCES_DIALOG)
    {
      OnPreferences();
      *result = 0;
      return true;
    }
    else if (msg->wParam == IDM_ABOUT_DIALOG)
    {
      OnAbout();
      *result = 0;
      return true;
    }
  }
  return false;
}
#endif

MainWindow::~MainWindow()
{
  SaveState();

  GetDownloadManager().CancelAllDownloads();
}

void MainWindow::SaveState()
{
  pair<uint32_t, uint32_t> xAndY(x(), y());
  pair<uint32_t, uint32_t> widthAndHeight(width(), height());
  Settings::Set("MainWindowXY", xAndY);
  Settings::Set("MainWindowSize", widthAndHeight);

  m_pDrawWidget->SaveState();
}

void MainWindow::LoadState()
{
  pair<uint32_t, uint32_t> xAndY;
  pair<uint32_t, uint32_t> widthAndHeight;
  bool loaded = Settings::Get("MainWindowXY", xAndY) &&
                Settings::Get("MainWindowSize", widthAndHeight);
  if (loaded)
  {
    move(xAndY.first, xAndY.second);
    resize(widthAndHeight.first, widthAndHeight.second);

    loaded = m_pDrawWidget->LoadState();
  }

  if (!loaded)
  {
    showMaximized();
    m_pDrawWidget->ShowAll();
  }
  else
    m_pDrawWidget->UpdateNow();
}

void MainWindow::CreateClassifPanel()
{
  CreatePanelImpl(0, tr("Classificator Bar"),
                  QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), SLOT(ShowClassifPanel()));

  ClassifTreeHolder * pCTree = new ClassifTreeHolder(m_Docks[0], m_pDrawWidget, SLOT(Repaint()));
  pCTree->SetRoot(classif().GetMutableRoot());

  m_Docks[0]->setWidget(pCTree);
}

void MainWindow::CreateGuidePanel()
{
  CreatePanelImpl(1, tr("Guide Bar"),
                  QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_G), SLOT(ShowGuidePanel()));

  qt::GuidePageHolder * pGPage = new qt::GuidePageHolder(m_Docks[1]);

  m_Docks[1]->setWidget(pGPage);
}

void MainWindow::CreatePanelImpl(size_t i, QString const & name,
                                 QKeySequence const & hotkey, char const * slot)
{
  m_Docks[i] = new QDockWidget(name, this);

  addDockWidget(Qt::LeftDockWidgetArea, m_Docks[i]);

  // hide by default
  m_Docks[i]->hide();

  // register a hotkey to show classificator panel
  QAction * pAct = new QAction(this);
  pAct->setShortcut(hotkey);
  connect(pAct, SIGNAL(triggered()), this, slot);
  addAction(pAct);
}

namespace
{
  struct button_t
  {
    QString name;
    char const * icon;
    char const * slot;
  };

  void add_buttons(QToolBar * pBar, button_t buttons[], size_t count, QWidget * pReceiver)
  {
    for (size_t i = 0; i < count; ++i)
    {
      if (buttons[i].icon)
        pBar->addAction(QIcon(buttons[i].icon), buttons[i].name, pReceiver, buttons[i].slot);
      else
        pBar->addSeparator();
    }
  }
}

void MainWindow::CreateNavigationBar()
{
  QToolBar * pBar = new QToolBar(tr("Navigation Bar"), this);
  pBar->setOrientation(Qt::Vertical);
  pBar->setIconSize(QSize(32, 32));

  {
    // add my position button with "checked" behavior
    m_pMyPosition = pBar->addAction(QIcon(":/navig64/location.png"),
                                           tr("My Position"),
                                           this,
                                           SLOT(OnMyPosition()));
    m_pMyPosition->setCheckable(true);
    m_pMyPosition->setToolTip(tr("My Position"));

    // add view actions 1
    button_t arr[] = {
      { tr("Left"), ":/navig64/left.png", SLOT(MoveLeft()) },
      { tr("Right"), ":/navig64/right.png", SLOT(MoveRight()) },
      { tr("Up"), ":/navig64/up.png", SLOT(MoveUp()) },
      { tr("Down"), ":/navig64/down.png", SLOT(MoveDown()) },
      { tr("Show all"), ":/navig64/world.png", SLOT(ShowAll()) },
      { QString(), 0, 0 },
      { tr("Scale +"), ":/navig64/plus.png", SLOT(ScalePlus()) }
    };
    add_buttons(pBar, arr, ARRAY_SIZE(arr), m_pDrawWidget);
  }

  // add scale slider
  QClickSlider * pScale = new QClickSlider(Qt::Vertical, this);
  pScale->setRange(0, scales::GetUpperScale());
  pScale->setTickPosition(QSlider::TicksRight);

  pBar->addWidget(pScale);
  m_pDrawWidget->SetScaleControl(pScale);

  {
    // add view actions 2
    button_t arr[] = {
      { tr("Scale -"), ":/navig64/minus.png", SLOT(ScaleMinus()) },
      { QString(), 0, 0 }
    };
    add_buttons(pBar, arr, ARRAY_SIZE(arr), m_pDrawWidget);
  }

  {
    // add mainframe actions
    button_t arr[] = {
      { tr("Download Maps"), ":/navig64/download.png", SLOT(ShowUpdateDialog()) }
    };
    add_buttons(pBar, arr, ARRAY_SIZE(arr), this);
  }

  addToolBar(Qt::RightToolBarArea, pBar);
}

//void MainWindow::CreateFindTable(QLayout * pLayout)
//{
//  // find widget
//  FindEditorWnd * pEditor = new FindEditorWnd(0);
//  pLayout->addWidget(pEditor);
//
//  // find table result
//  m_pFindTable = new FindTableWnd(0, pEditor, m_pDrawWidget->GetModel());
//  pLayout->addWidget(m_pFindTable);
//  connect(m_pFindTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnFeatureClicked(int, int)));
//  connect(m_pFindTable, SIGNAL(cellEntered(int, int)), this, SLOT(OnFeatureEntered(int, int)));
//}
//
//void MainWindow::OnFeatureEntered(int /*row*/, int /*col*/)
//{
//  //Feature const & p = m_pFindTable->GetFeature(row);
//
//  /// @todo highlight the feature
//}
//
//void MainWindow::OnFeatureClicked(int row, int /*col*/)
//{
//  Feature const & p = m_pFindTable->GetFeature(row);
//  m_pDrawWidget->ShowFeature(p);
//}

void MainWindow::ShowUpdateDialog()
{
  if (!m_updateDialog)
    m_updateDialog = new UpdateDialog(this, m_storage);
  m_updateDialog->ShowDialog();
}

void MainWindow::ShowClassifPanel()
{
  m_Docks[0]->show();
}

void MainWindow::ShowGuidePanel()
{
  m_Docks[1]->show();
}

void MainWindow::OnAbout()
{
  AboutDialog dlg(this);
  dlg.exec();
}

void MainWindow::OnPreferences()
{
  bool autoUpdatesEnabled = DEFAULT_AUTO_UPDATES_ENABLED;
  Settings::Get("AutomaticUpdateCheck", autoUpdatesEnabled);

  PreferencesDialog dlg(this, autoUpdatesEnabled);
  dlg.exec();

  Settings::Set("AutomaticUpdateCheck", autoUpdatesEnabled);
}

void MainWindow::OnLocationFound()
{
  m_pMyPosition->setIcon(QIcon(":/navig64/location.png"));
  m_pMyPosition->setToolTip(tr("My Position"));
}

void MainWindow::OnMyPosition()
{
  if (m_pMyPosition->isChecked())
  {
    m_pMyPosition->setIcon(QIcon(":/navig64/location-search.png"));
    m_pMyPosition->setToolTip(tr("Looking for position..."));
    m_pDrawWidget->OnEnableMyPosition(boost::bind(&MainWindow::OnLocationFound, this));
  }
  else
  {
    m_pMyPosition->setIcon(QIcon(":/navig64/location.png"));
    m_pMyPosition->setToolTip(tr("My Position"));
    m_pDrawWidget->OnDisableMyPosition();
  }
}

}
<|endoftext|>


<commit_before>/*
gpe_game_master_itenary.cpp
This file is part of:
GAME PENCIL ENGINE
https://create.pawbyte.com
Copyright (c) 2014-2020 Nathan Hurde, Chase Lee.

Copyright (c) 2014-2020 PawByte LLC.
Copyright (c) 2014-2020 Game Pencil Engine contributors ( Contributors Page )

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

-Game Pencil Engine <https://create.pawbyte.com>

 ____                ____        _
|  _ \ __ ___      _| __ ) _   _| |_ ___
| |_) / _` \ \ /\ / /  _ \| | | | __/ _ \
|  __/ (_| |\ V  V /| |_) | |_| | ||  __/
|_|   \__,_| \_/\_/ |____/ \__, |\__\___|
                           |___/
Created By PawByte
Attribution required at start of program and in credits.
SDL 2.0.9 used for this version...
*/

#include "gpe_game_master_itenary.h"

bool GPE_Init_Master_Itenary( int argc, char* args[] )
{
    if( GPE_Editor_Init(argc, args) == false)
    {
        return false;
    }

    return true;
}

bool GPE_Quit_Master_Itenary()
{
    GPE_Report("Deleting Editor....");
    GPE_Editor_Quit();

    GPE_Report("Deleting Gui...");
    PAW_GUI_END();

    return true;
}
<commit_msg>Delete gpe_game_master_itenary.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>printerpullpages: #i106879# use document printer as default<commit_after><|endoftext|>