<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2020)

#ifndef PYTHON_DUNE_GDT_SPACES_L2_DISCONTINUOUS_LAGRANGE_HH
#define PYTHON_DUNE_GDT_SPACES_L2_DISCONTINUOUS_LAGRANGE_HH

#include <dune/pybindxi/pybind11.h>
#include <dune/pybindxi/stl.h>

#include <dune/xt/grid/gridprovider/provider.hh>

#include <dune/gdt/spaces/l2/discontinuous-lagrange.hh>

#include <python/dune/xt/common/configuration.hh>
#include <python/dune/xt/common/fvector.hh>
#include <python/dune/xt/grid/grids.bindings.hh>
#include <python/dune/xt/grid/traits.hh>

namespace Dune {
namespace GDT {
namespace bindings {

/**
 * \note Assumes that GV is the leaf view!
 */
template <class GV, size_t r = 1, class R = double>
class DiscontinuousLagrangeSpace
{
  using G = typename GV::Grid;
  static const size_t d = G::dimension;

public:
  using type = GDT::DiscontinuousLagrangeSpace<GV, r, R>;
  using base_type = GDT::SpaceInterface<GV, r, 1, R>;
  using bound_type = pybind11::class_<type, base_type>;

  static bound_type
  bind(pybind11::module& m, const std::string& grid_id, const std::string& class_id = "discontinuous_lagrange_space")
  {
    namespace py = pybind11;
    using namespace pybind11::literals;

    std::string class_name = class_id + "_" + grid_id;
    if (r > 1)
      class_name += "_to_" + XT::Common::to_string(r) + "d";
    if (!std::is_same<R, double>::value)
      class_name += "_" + XT::Common::Typename<R>::value(/*fail_wo_typeid=*/true);
    const auto ClassName = XT::Common::to_camel_case(class_name);
    bound_type c(m, ClassName.c_str(), ClassName.c_str());
    c.def(py::init([](XT::Grid::GridProvider<G>& grid_provider, const int order) {
            return type(grid_provider.leaf_view(), order); // Otherwise we get an error here!
          }),
          "grid_provider"_a,
          "order"_a);
    c.def("__repr__", [](const type& self) {
      std::stringstream ss;
      ss << self;
      return ss.str();
    });

    std::string space_type_name = class_id;
    if (!std::is_same<R, double>::value)
      space_type_name += "_" + XT::Common::Typename<R>::value(/*fail_wo_typeid=*/true);
    m.def(XT::Common::to_camel_case(space_type_name).c_str(),
          [c](XT::Grid::GridProvider<G>& grid, const int order, const XT::Grid::bindings::Dimension<r>&) {
            return type(grid.leaf_view(), order); // Otherwise we get an error here!
          },
          "grid"_a,
          "order"_a,
          "dim_range"_a = XT::Grid::bindings::Dimension<r>());

    return c;
  } // ... bind(...)
}; // class DiscontinuousLagrangeSpace

} // namespace bindings
} // namespace GDT
} // namespace Dune

#endif // PYTHON_DUNE_GDT_SPACES_L2_DISCONTINUOUS_LAGRANGE_HH
<commit_msg>[P|spaces.l2.dg] fix default dim_range<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2020)

#ifndef PYTHON_DUNE_GDT_SPACES_L2_DISCONTINUOUS_LAGRANGE_HH
#define PYTHON_DUNE_GDT_SPACES_L2_DISCONTINUOUS_LAGRANGE_HH

#include <dune/pybindxi/pybind11.h>
#include <dune/pybindxi/stl.h>

#include <dune/xt/grid/gridprovider/provider.hh>

#include <dune/gdt/spaces/l2/discontinuous-lagrange.hh>

#include <python/dune/xt/common/configuration.hh>
#include <python/dune/xt/common/fvector.hh>
#include <python/dune/xt/grid/grids.bindings.hh>
#include <python/dune/xt/grid/traits.hh>

namespace Dune {
namespace GDT {
namespace bindings {

/**
 * \note Assumes that GV is the leaf view!
 */
template <class GV, size_t r = 1, class R = double>
class DiscontinuousLagrangeSpace
{
  using G = typename GV::Grid;
  static const size_t d = G::dimension;

public:
  using type = GDT::DiscontinuousLagrangeSpace<GV, r, R>;
  using base_type = GDT::SpaceInterface<GV, r, 1, R>;
  using bound_type = pybind11::class_<type, base_type>;

  static bound_type
  bind(pybind11::module& m, const std::string& grid_id, const std::string& class_id = "discontinuous_lagrange_space")
  {
    namespace py = pybind11;
    using namespace pybind11::literals;

    std::string class_name = class_id + "_" + grid_id;
    if (r > 1)
      class_name += "_to_" + XT::Common::to_string(r) + "d";
    if (!std::is_same<R, double>::value)
      class_name += "_" + XT::Common::Typename<R>::value(/*fail_wo_typeid=*/true);
    const auto ClassName = XT::Common::to_camel_case(class_name);
    bound_type c(m, ClassName.c_str(), ClassName.c_str());
    c.def(py::init([](XT::Grid::GridProvider<G>& grid_provider, const int order) {
            return type(grid_provider.leaf_view(), order); // Otherwise we get an error here!
          }),
          "grid_provider"_a,
          "order"_a);
    c.def("__repr__", [](const type& self) {
      std::stringstream ss;
      ss << self;
      return ss.str();
    });

    std::string space_type_name = class_id;
    if (!std::is_same<R, double>::value)
      space_type_name += "_" + XT::Common::Typename<R>::value(/*fail_wo_typeid=*/true);
    if (r == 1)
      m.def(
          XT::Common::to_camel_case(space_type_name).c_str(),
          [c](XT::Grid::GridProvider<G>& grid, const int order, const XT::Grid::bindings::Dimension<r>&) {
            return type(grid.leaf_view(), order); // Otherwise we get an error here!
          },
          "grid"_a,
          "order"_a,
          "dim_range"_a = XT::Grid::bindings::Dimension<r>());
    else
      m.def(
          XT::Common::to_camel_case(space_type_name).c_str(),
          [c](XT::Grid::GridProvider<G>& grid, const int order, const XT::Grid::bindings::Dimension<r>&) {
            return type(grid.leaf_view(), order); // Otherwise we get an error here!
          },
          "grid"_a,
          "order"_a,
          "dim_range"_a);

    return c;
  } // ... bind(...)
}; // class DiscontinuousLagrangeSpace

} // namespace bindings
} // namespace GDT
} // namespace Dune

#endif // PYTHON_DUNE_GDT_SPACES_L2_DISCONTINUOUS_LAGRANGE_HH
<|endoftext|>


<commit_before>#include "ofSoundStream.h"
#include "RtAudio.h"

//----------------------------------- static variables:
static ofBaseApp 	* 		OFSAptr;
RtAudio				*		audio;
int 						nInputChannels;
int 						nOutputChannels;
ofAudioEventArgs 			audioEventArgs;

int receiveAudioBufferAndCallSimpleApp(void *outputBuffer, void *inputBuffer, unsigned int bufferSize,
           double streamTime, RtAudioStreamStatus status, void *data);

//------------------------------------------------------------------------------
int receiveAudioBufferAndCallSimpleApp(void *outputBuffer, void *inputBuffer, unsigned int bufferSize,
           double streamTime, RtAudioStreamStatus status, void *data){

	if ( status ) std::cout << "Stream over/underflow detected." << std::endl;

	// 	rtAudio uses a system by which the audio
	// 	can be of different formats
	// 	char, float, etc.
	// 	we choose float
	float * fPtrOut = (float *)outputBuffer;
	float * fPtrIn = (float *)inputBuffer;
	// [zach] memset output to zero before output call
	// this is because of how rtAudio works: duplex w/ one callback
	// you need to cut in the middle. if the simpleApp
	// doesn't produce audio, we pass silence instead of duplex...

	if (nInputChannels > 0){
		OFSAptr->audioReceived(fPtrIn, bufferSize, nInputChannels);
		memset(fPtrIn, 0, bufferSize * nInputChannels * sizeof(float));
		#ifdef OF_USING_POCO
			audioEventArgs.buffer = fPtrIn;
			audioEventArgs.bufferSize = bufferSize;
			audioEventArgs.nChannels = nInputChannels;
			ofNotifyEvent( ofEvents.audioReceived, audioEventArgs );
		#endif
	}

	if (nOutputChannels > 0) {
		OFSAptr->audioRequested(fPtrOut, bufferSize, nOutputChannels);
		#ifdef OF_USING_POCO
			audioEventArgs.buffer = fPtrOut;
			audioEventArgs.bufferSize = bufferSize;
			audioEventArgs.nChannels = nOutputChannels;
			ofNotifyEvent( ofEvents.audioRequested, audioEventArgs );
		#endif
	}

	return 0;
}
//---------------------------------------------------------
void ofSoundStreamSetup(int nOutputs, int nInputs, ofBaseApp * OFSA){
	ofSoundStreamSetup(nOutputs, nInputs, OFSA, 44100, 256, 4);
}

//---------------------------------------------------------
void ofSoundStreamSetup(int nOutputs, int nInputs, int sampleRate, int bufferSize, int nBuffers){
	ofSoundStreamSetup(nOutputs, nInputs, NULL, sampleRate, bufferSize, nBuffers);
}

//---------------------------------------------------------
void ofSoundStreamSetup(int nOutputs, int nInputs, ofBaseApp * OFSA, int sampleRate, int bufferSize, int nBuffers){

	nInputChannels 		=  nInputs;
	nOutputChannels 	=  nOutputs;
	OFSAptr 			=  OFSA;
	bufferSize = ofNextPow2(bufferSize);	// must be pow2

	try {
		audio = new RtAudio();
	}	catch (RtError &error) {
		error.printMessage();
		//std::exit(EXIT_FAILURE); // need case here
	}

	RtAudio::StreamParameters * outputParameters=NULL;
	if(nOutputChannels >0){
		outputParameters = new RtAudio::StreamParameters();
		outputParameters->deviceId = audio->getDefaultOutputDevice();
		outputParameters->nChannels = nOutputChannels;
	}

	RtAudio::StreamParameters * inputParameters = NULL;
	if(nInputChannels>0){
		inputParameters = new RtAudio::StreamParameters;
		inputParameters->deviceId = audio->getDefaultInputDevice();
		inputParameters->nChannels = nInputChannels;
	}

	unsigned int bufferFrames = (unsigned int)bufferSize; // 256 sample frames

	RtAudio::StreamOptions options;
	options.flags = RTAUDIO_SCHEDULE_REALTIME;
	options.numberOfBuffers = nBuffers;
	options.priority = 1;

	try {

		audio ->openStream( outputParameters, inputParameters, RTAUDIO_FLOAT32,
							sampleRate, &bufferFrames, &receiveAudioBufferAndCallSimpleApp, &options);
		audio->startStream();
	} catch (RtError &error) {
		error.printMessage();
	}

}

//---------------------------------------------------------
void ofSoundStreamStop(){
	try {
    	audio->stopStream();
  	} catch (RtError &error) {
   		error.printMessage();
 	}
}

//---------------------------------------------------------
void ofSoundStreamStart(){
	try{
		audio->startStream();
	} catch (RtError &error) {
		error.printMessage();
	}
}

//---------------------------------------------------------
void ofSoundStreamClose(){
	try {
    	audio->stopStream();
    	audio->closeStream();
  	} catch (RtError &error) {
   		error.printMessage();
 	}
	delete audio;
}

//---------------------------------------------------------
void ofSoundStreamListDevices(){
	RtAudio *audioTemp = 0;
	try {
		audioTemp = new RtAudio();
	} catch (RtError &error) {
		error.printMessage();
	}
 	int devices = audioTemp->getDeviceCount();
	RtAudio::DeviceInfo info;
	for (int i=0; i< devices; i++) {
		try {
			info = audioTemp->getDeviceInfo(i);
		} catch (RtError &error) {
			error.printMessage();
			break;
		}
		std::cout << "device = " << i << " (" << info.name << ")\n";
		if (info.isDefaultInput) std::cout << "----* default ----* \n";
		std::cout << "maximum output channels = " << info.outputChannels << "\n";
		std::cout << "maximum input channels = " << info.inputChannels << "\n";
		std::cout << "-----------------------------------------\n";

	}
	delete audioTemp;
}
<commit_msg>sound/ofSoundStream.cpp: change order of sound events buffer clean. Closes #130<commit_after>#include "ofSoundStream.h"
#include "RtAudio.h"

//----------------------------------- static variables:
static ofBaseApp 	* 		OFSAptr;
RtAudio				*		audio;
int 						nInputChannels;
int 						nOutputChannels;
ofAudioEventArgs 			audioEventArgs;

int receiveAudioBufferAndCallSimpleApp(void *outputBuffer, void *inputBuffer, unsigned int bufferSize,
           double streamTime, RtAudioStreamStatus status, void *data);

//------------------------------------------------------------------------------
int receiveAudioBufferAndCallSimpleApp(void *outputBuffer, void *inputBuffer, unsigned int bufferSize,
           double streamTime, RtAudioStreamStatus status, void *data){

	if ( status ) std::cout << "Stream over/underflow detected." << std::endl;

	// 	rtAudio uses a system by which the audio
	// 	can be of different formats
	// 	char, float, etc.
	// 	we choose float
	float * fPtrOut = (float *)outputBuffer;
	float * fPtrIn = (float *)inputBuffer;
	// [zach] memset output to zero before output call
	// this is because of how rtAudio works: duplex w/ one callback
	// you need to cut in the middle. if the simpleApp
	// doesn't produce audio, we pass silence instead of duplex...

	if (nInputChannels > 0){
		OFSAptr->audioReceived(fPtrIn, bufferSize, nInputChannels);
		#ifdef OF_USING_POCO
			audioEventArgs.buffer = fPtrIn;
			audioEventArgs.bufferSize = bufferSize;
			audioEventArgs.nChannels = nInputChannels;
			ofNotifyEvent( ofEvents.audioReceived, audioEventArgs );
		#endif
		memset(fPtrIn, 0, bufferSize * nInputChannels * sizeof(float));
	}

	if (nOutputChannels > 0) {
		OFSAptr->audioRequested(fPtrOut, bufferSize, nOutputChannels);
		#ifdef OF_USING_POCO
			audioEventArgs.buffer = fPtrOut;
			audioEventArgs.bufferSize = bufferSize;
			audioEventArgs.nChannels = nOutputChannels;
			ofNotifyEvent( ofEvents.audioRequested, audioEventArgs );
		#endif
	}

	return 0;
}
//---------------------------------------------------------
void ofSoundStreamSetup(int nOutputs, int nInputs, ofBaseApp * OFSA){
	ofSoundStreamSetup(nOutputs, nInputs, OFSA, 44100, 256, 4);
}

//---------------------------------------------------------
void ofSoundStreamSetup(int nOutputs, int nInputs, int sampleRate, int bufferSize, int nBuffers){
	ofSoundStreamSetup(nOutputs, nInputs, NULL, sampleRate, bufferSize, nBuffers);
}

//---------------------------------------------------------
void ofSoundStreamSetup(int nOutputs, int nInputs, ofBaseApp * OFSA, int sampleRate, int bufferSize, int nBuffers){

	nInputChannels 		=  nInputs;
	nOutputChannels 	=  nOutputs;
	OFSAptr 			=  OFSA;
	bufferSize = ofNextPow2(bufferSize);	// must be pow2

	try {
		audio = new RtAudio();
	}	catch (RtError &error) {
		error.printMessage();
		//std::exit(EXIT_FAILURE); // need case here
	}

	RtAudio::StreamParameters * outputParameters=NULL;
	if(nOutputChannels >0){
		outputParameters = new RtAudio::StreamParameters();
		outputParameters->deviceId = audio->getDefaultOutputDevice();
		outputParameters->nChannels = nOutputChannels;
	}

	RtAudio::StreamParameters * inputParameters = NULL;
	if(nInputChannels>0){
		inputParameters = new RtAudio::StreamParameters;
		inputParameters->deviceId = audio->getDefaultInputDevice();
		inputParameters->nChannels = nInputChannels;
	}

	unsigned int bufferFrames = (unsigned int)bufferSize; // 256 sample frames

	RtAudio::StreamOptions options;
	options.flags = RTAUDIO_SCHEDULE_REALTIME;
	options.numberOfBuffers = nBuffers;
	options.priority = 1;

	try {

		audio ->openStream( outputParameters, inputParameters, RTAUDIO_FLOAT32,
							sampleRate, &bufferFrames, &receiveAudioBufferAndCallSimpleApp, &options);
		audio->startStream();
	} catch (RtError &error) {
		error.printMessage();
	}

}

//---------------------------------------------------------
void ofSoundStreamStop(){
	try {
    	audio->stopStream();
  	} catch (RtError &error) {
   		error.printMessage();
 	}
}

//---------------------------------------------------------
void ofSoundStreamStart(){
	try{
		audio->startStream();
	} catch (RtError &error) {
		error.printMessage();
	}
}

//---------------------------------------------------------
void ofSoundStreamClose(){
	try {
    	audio->stopStream();
    	audio->closeStream();
  	} catch (RtError &error) {
   		error.printMessage();
 	}
	delete audio;
}

//---------------------------------------------------------
void ofSoundStreamListDevices(){
	RtAudio *audioTemp = 0;
	try {
		audioTemp = new RtAudio();
	} catch (RtError &error) {
		error.printMessage();
	}
 	int devices = audioTemp->getDeviceCount();
	RtAudio::DeviceInfo info;
	for (int i=0; i< devices; i++) {
		try {
			info = audioTemp->getDeviceInfo(i);
		} catch (RtError &error) {
			error.printMessage();
			break;
		}
		std::cout << "device = " << i << " (" << info.name << ")\n";
		if (info.isDefaultInput) std::cout << "----* default ----* \n";
		std::cout << "maximum output channels = " << info.outputChannels << "\n";
		std::cout << "maximum input channels = " << info.inputChannels << "\n";
		std::cout << "-----------------------------------------\n";

	}
	delete audioTemp;
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2009-2016, MAV'RIC Development Team
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/

/*******************************************************************************
 * \file gimbal_controller.hpp
 *
 * \author MAV'RIC Team
 * \author Alexandre Cherpillod
 *
 * \brief   Gimbal control management
 *
 ******************************************************************************/

#ifndef GIMBAL_CONTROLLER_H_
#define GIMBAL_CONTROLLER_H_

#include "control/control_command.h"
#include "control/pid_controller.h"
#include "drivers/servo.hpp"

/**
 * \brief Gimbal controller configuration
 */
typedef struct
{
	attitude_command_t   		attitude_command_desired_config;	///< Initial desired attitude command
	attitude_command_t   		attitude_command_range_config[2];  	///< Allowed [min;max] range of the gimbal
	attitude_command_t   		attitude_output_config;  			///< Initial output commands
} gimbal_controller_conf_t;

class Gimbal_controller
{

//------------------------------------------------------------------------------
// VARIABLES
//------------------------------------------------------------------------------
private:
	enum RANGE_GIMBAL
	{
	    MIN_RANGE_GIMBAL = 0,              ///< Range of the minimum allowed gimbal angles
	    MAX_RANGE_GIMBAL = 1               ///< Range of the maximum allowed gimabl angles
	};

	attitude_command_t			attitude_command_range[2];	///< Range [min; max] of the attitude commands
	attitude_command_t			attitude_output;			///< Output to PWM (output)
	Servo*						servo_pitch;				///< Gimbal pitch servo
	Servo*						servo_yaw;					///< Gimbal yaw servo

public:
	attitude_command_t			attitude_command_desired;	///< Attitude command (input from head-tracker)

//------------------------------------------------------------------------------
// FUNCTIONS
//------------------------------------------------------------------------------
private:
	/**
	 * \brief                   Sends the output to the servos
	 *
	 * \param   output			Outputs to send
	 * \param	servos			pointer to the servo structure
	 */
	void gimbal_controller_mix_to_servos();

public:
	/**
	 * \brief                       Initializes the gimbal controller structure
	 *
	 * \param   controller          Pointer to data structure
	 * \param   config              Pointer to configuration
	 */
	void gimbal_controller_init(const gimbal_controller_conf_t config,Servo *servo_4,Servo *servo_5);

	/**
	 * \brief                   Main update function - sends gimbal command to two PWM outputs (for pitch and yaw)
	 *
	 * \param   controller      Pointer to data structure
	 */
	bool gimbal_controller_update(Gimbal_controller *not_used);

};

#endif /* GIMBAL_CONTROLLER_H_ */
<commit_msg>Reorder public and private members<commit_after>/*******************************************************************************
 * Copyright (c) 2009-2016, MAV'RIC Development Team
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/

/*******************************************************************************
 * \file gimbal_controller.hpp
 *
 * \author MAV'RIC Team
 * \author Alexandre Cherpillod
 *
 * \brief   Gimbal control management
 *
 ******************************************************************************/

#ifndef GIMBAL_CONTROLLER_H_
#define GIMBAL_CONTROLLER_H_

#include "control/control_command.h"
#include "control/pid_controller.h"
#include "drivers/servo.hpp"

/**
 * \brief Gimbal controller configuration
 */
typedef struct
{
	attitude_command_t   		attitude_command_desired_config;	///< Initial desired attitude command
	attitude_command_t   		attitude_command_range_config[2];  	///< Allowed [min;max] range of the gimbal
	attitude_command_t   		attitude_output_config;  			///< Initial output commands
} gimbal_controller_conf_t;

class Gimbal_controller
{
public:
	/**
	 * \brief                       Initializes the gimbal controller structure
	 *
	 * \param   controller          Pointer to data structure
	 * \param   config              Pointer to configuration
	 */
	void gimbal_controller_init(const gimbal_controller_conf_t config,Servo *servo_4,Servo *servo_5);

	/**
	 * \brief                   Main update function - sends gimbal command to two PWM outputs (for pitch and yaw)
	 *
	 * \param   controller      Pointer to data structure
	 */
	bool gimbal_controller_update(Gimbal_controller *not_used);

	attitude_command_t			attitude_command_desired;	///< Attitude command (input from head-tracker)

private:
	/**
	 * \brief                   Sends the output to the servos
	 *
	 * \param   output			Outputs to send
	 * \param	servos			pointer to the servo structure
	 */
	void gimbal_controller_mix_to_servos();

	enum RANGE_GIMBAL
	{
	    MIN_RANGE_GIMBAL = 0,              ///< Range of the minimum allowed gimbal angles
	    MAX_RANGE_GIMBAL = 1               ///< Range of the maximum allowed gimabl angles
	};

	attitude_command_t			attitude_command_range[2];	///< Range [min; max] of the attitude commands
	attitude_command_t			attitude_output;			///< Output to PWM (output)
	Servo*						servo_pitch;				///< Gimbal pitch servo
	Servo*						servo_yaw;					///< Gimbal yaw servo
};

#endif /* GIMBAL_CONTROLLER_H_ */
<|endoftext|>


<commit_before>#include "XsdType.hpp"
#include "XsdChecker.hpp"
#include <sstream>
#include "../Utils.hpp"

namespace Xsd
{

    const std::string TYPE_SUFFIX = "TYPE";
    const std::string UNBOUNDED = "unbounded";
    const std::string UNBOUNDED_EXP_REG = "*";

    Type::Type(const Xml::Element * const xmlElement, const std::string & name)
    {
        mRegex = parseComplexType(xmlElement, "", false);
        Checker::getInstance()->addType(name, this);
    }

    Type::Type(const std::string & name, const std::string & regex, std::list<Attribute *> attrs):
        mRegex(regex),
        mAttributes(attrs)
    {
        Checker::getInstance()->addType(name, this);
    }

    Type::~Type()
    {
    }

    bool
    Type::isValid(const std::string & str)
    {
        return RE2::FullMatch(str, mRegex);
    }

    void
    Type::checkValidity(const Xml::Element & element)
    {
        //TODO: add function attributes() which returns the mAttributes map in Xml::Element
        for (auto iterAttr = element.attributesValue().begin(); iterAttr != element.attributesValue().end(); ++iterAttr)
        {
            //pour chaque attibut d'un element
            //  obtenir l'attribut xsd avec une map depuis le type (map attribut de type)
            //  xsdAttribute->checkValidity(iterAttr->second)
            // mAttributes.find(iterAttr->first)
            // iterAttr->checkValidity(iterAttr->second);
        }

        if(!RE2::FullMatch(childrenToString(element.elements()), mRegex))
        {
            throw new XSDValidationException("Invalid element: " + element.name());
        }

        for (auto iter = element.elements().begin(); iter != element.elements().end(); ++iter)
        {
            Checker::getInstance()->getElementType(*iter->name())->checkValidity(*iter);
        }
    }

    std::string
    Type::childrenToString(std::vector<Xml::Element const *> childrenElt)
    {
        std::string str = "";
        for (auto iter = childrenElt.begin(); iter != childrenElt.end(); ++iter)
        {
            str += "<" + (*iter)->name() + ">";
        }
        return str;
    }

    //Should work, still have to check the algorithm for choice or sequence inside choice or sequence
    std::string
    Type::parseComplexType(const Xml::Element * const xmlElement, std::string separator, bool eltSeqChoice)
    {
        bool eltParsed = false;
        std::string regex = "(";

        if(xmlElement->attribute(Checker::MIXED_ATTR).compare("true") == 0)
        {
            separator += ".*";
        }

        for (auto ci = xmlElement->elements().begin(); ci != xmlElement->elements().end(); ++ci)
        {
            if((*ci)->name().compare(Checker::SEQUENCE_ELT) == 0)
            {
                regex += getRegexFromOccurs(*ci, parseComplexType(ci, "", true)) + separator;
            }
            else if((*ci)->name().compare(Checker::CHOICE_ELT) == 0)
            {
                regex += getRegexFromOccurs(*ci, parseComplexType(ci, "|", true)) + separator;
            }
            else if((*ci)->name().compare(Checker::ELEMENT_ELT) == 0)
            {
                if(eltSeqChoice || !eltParsed)
                {
                    eltParsed = true;
                    regex += parseElement(*ci) + separator;
                }
                else
                {
                    Checker::throwInvalidElementException(Checker::ELEMENT_ELT, getNameOrRef(*(*ci)));
                }
            }
            else if((*ci)->name().compare(Checker::ATTRIBUTE_ELT) == 0)
            {
                mAttributes.push_back(Xsd::Attribute::parseAttribute(*(*ci)));
            }
            else
            {
                Checker::throwInvalidElementException(Checker::COMPLEX_TYP_ELT, (*ci)->name());
            }
        }

        if(regex.back() == '|')
        {
            regex = regex.substr(0, regex.size()-1);
        }

        return regex + ")";
    }

    bool
    Type::isSimpleType(const std::string & type)
    {
        throw new NotImplementedException("Not implemented yet");
        return (type.compare(Checker::STRING_TYPE) == 0)
            || (type.compare(Checker::DATE_TYPE) == 0);
    }

    std::string
    Type::getOccursFromElement(const Xml::Element & xmlElement, const std::string & occursAttrName, const std::string & occursAttrValue)
    {
        if(occursAttrValue.compare(UNBOUNDED) == 0)
        {
            return UNBOUNDED_EXP_REG;
        }

        try
        {
            if(std::stoi(occursAttrValue) < 0)
            {
                throw new Exception();
            }
        }
        catch(const std::exception& e)
        {
            Checker::throwInvalidAttributeValueException(Checker::ELEMENT_ELT, occursAttrName, occursAttrValue);
        }

        return occursAttrValue;
    }

    std::string
    Type::getNameOrRef(const Xml::Element & xmlElement)
    {
        if(isReference(xmlElement))
        {
            return xmlElement.attribute(Checker::REF_ATTR);
        }
        return xmlElement.attribute(Checker::NAME_ATTR);
    }

    bool
    Type::isReference(const Xml::Element & xmlElement)
    {
        std::string notFound = "";
        std::string name = xmlElement.attribute(Checker::NAME_ATTR);
        std::string ref = xmlElement.attribute(Checker::REF_ATTR);

        // Name and ref attributes
        if((name.compare(notFound) == 0) && (ref.compare(notFound) != 0))
        {
            return true;
        }
        else
        {
            Checker::throwMissingAttributeException(Checker::ELEMENT_ELT, Checker::NAME_ATTR);
        }

        return false;
    }

    /**
     * Returns the regex of an element, adds its type and type relation to the maps if it's not a ref
     * The regex does not contain the validation for the element children, it's only about the element name or ref itself
     */
    std::string
    Type::parseElement(const Xml::Element & xmlElement)
    {
        bool ref = false;
        std::string regex, name;

        // Name and ref attributes
        if(isReference(xmlElement))
        {
            name = xmlElement.attribute(Checker::REF_ATTR);
            ref = true;
        }
        else
        {
            name = xmlElement.attribute(Checker::NAME_ATTR);
        }

        regex = getRegexFromOccurs(xmlElement, name);

        if(!ref)
        {
            //Type manaement
            std::string type = xmlElement.attribute(Checker::TYPE_ATTR);
            if(!type.compare("") && isSimpleType(type))
            {
                std::vector<std::string> tokens;
                throw new NotImplementedException("Not implemented yet"); tokens = NULL; //todo remove
                //tokens = Utils::split(type, ':'));
                Checker::getInstance()->addTypedElement(name, tokens.back());

            }
            else if(xmlElement.elements().size() > 0)
            {
                Xml::Element & typeElement = xmlElement.elements().front();
                if(typeElement.name().compare(Checker::COMPLEX_TYP_ELT) == 0)
                {
                    parseComplexType(ci, "", true);
                }
                else
                {
                    throw new XSDConstructionException("Error: type attribute or element cannot be found for " + Checker::ELEMENT_ELT + " element");
                }
            }
            else
            {
                throw new XSDConstructionException("Error: type attribute or element cannot be found for " + Checker::ELEMENT_ELT + " element");
            }
        }

        return regex;
    }

    /**
     * Modify and returns the element regex given in parameter in order to add
     * regex expression for the occurs attributes values
     */
    std::string
    Type::getRegexFromOccurs(const Xml::Element & xmlElement, const std::string & eltRegex)
    {
        std::string notFound = "", regex;
        std::string name = xmlElement.attribute(Xsd::Checker::NAME_ATTR);
        std::string ref = xmlElement.attribute(Xsd::Checker::REF_ATTR);
        std::string minOccurs = xmlElement.attribute(Checker::MIN_OCC_ATTR);
        std::string supOccurs = xmlElement.attribute(Checker::MAX_OCC_ATTR);

        // Min and max occurs attributes
        if(!(minOccurs.compare(notFound) == 0))
        {
            minOccurs = getOccursFromElement(xmlElement, Checker::MIN_OCC_ATTR, minOccurs);
        }
        else
        {
            minOccurs = "1";
        }

        if(!(supOccurs.compare(notFound) == 0))
        {
            supOccurs = getOccursFromElement(xmlElement, Checker::MAX_OCC_ATTR, supOccurs);
        }
        else
        {
            supOccurs = "0";
        }

        if((minOccurs.compare(UNBOUNDED_EXP_REG) == 0) && !(supOccurs.compare(UNBOUNDED_EXP_REG) == 0)
            || (!(supOccurs.compare(UNBOUNDED_EXP_REG) ==0) && std::stoi(supOccurs) < std::stoi(minOccurs)))
        {
            throw new XSDConstructionException("Error: " + Checker::MIN_OCC_ATTR + " attribute value is higher than " + Checker::MAX_OCC_ATTR + " value");
        }
        if((minOccurs.compare(UNBOUNDED_EXP_REG) == 0) && (supOccurs.compare(UNBOUNDED_EXP_REG) == 0))
        {
            std::stringstream out;
            out << (std::stoi(supOccurs) - std::stoi(minOccurs));
            supOccurs = out.str();
        }

        // Name and ref attributes
        if(isReference(xmlElement))
        {
            name = ref;
        }

        // Create the regex
        regex = "(<" + eltRegex + ">){" + minOccurs + "}";
        if(!(supOccurs.compare("0") == 0))
        {
            regex += "((<" + eltRegex + ">?){" + supOccurs + "})";
        }

        return regex;
    }

    std::list<Attribute *>
    Type::attributes() const
    {
        return mAttributes;
    }
}
<commit_msg>fixed error<commit_after>#include "XsdType.hpp"
#include "XsdChecker.hpp"
#include <sstream>
#include "../Utils.hpp"

namespace Xsd
{

    const std::string TYPE_SUFFIX = "TYPE";
    const std::string UNBOUNDED = "unbounded";
    const std::string UNBOUNDED_EXP_REG = "*";

    Type::Type(const Xml::Element * const xmlElement, const std::string & name)
    {
        mRegex = parseComplexType(xmlElement, "", false);
        Checker::getInstance()->addType(name, this);
    }

    Type::Type(const std::string & name, const std::string & regex, std::list<Attribute *> attrs):
        mRegex(regex),
        mAttributes(attrs)
    {
        Checker::getInstance()->addType(name, this);
    }

    Type::~Type()
    {
    }

    bool
    Type::isValid(const std::string & str)
    {
        return RE2::FullMatch(str, mRegex);
    }

    void
    Type::checkValidity(const Xml::Element & element)
    {
        //TODO: add function attributes() which returns the mAttributes map in Xml::Element
        for (auto iterAttr = element.attributesValue().begin(); iterAttr != element.attributesValue().end(); ++iterAttr)
        {
            //pour chaque attibut d'un element
            //  obtenir l'attribut xsd avec une map depuis le type (map attribut de type)
            //  xsdAttribute->checkValidity(iterAttr->second)
            // mAttributes.find(iterAttr->first)
            // iterAttr->checkValidity(iterAttr->second);
        }

        if(!RE2::FullMatch(childrenToString(element.elements()), mRegex))
        {
            throw new XSDValidationException("Invalid element: " + element.name());
        }

        for (auto iter = element.elements().begin(); iter != element.elements().end(); ++iter)
        {
            Checker::getInstance()->getElementType(*iter->name())->checkValidity(*iter);
        }
    }

    std::string
    Type::childrenToString(std::vector<Xml::Element const *> childrenElt)
    {
        std::string str = "";
        for (auto iter = childrenElt.begin(); iter != childrenElt.end(); ++iter)
        {
            str += "<" + (*iter)->name() + ">";
        }
        return str;
    }

    //Should work, still have to check the algorithm for choice or sequence inside choice or sequence
    std::string
    Type::parseComplexType(const Xml::Element * const xmlElement, std::string separator, bool eltSeqChoice)
    {
        bool eltParsed = false;
        std::string regex = "(";

        if(xmlElement->attribute(Checker::MIXED_ATTR).compare("true") == 0)
        {
            separator += ".*";
        }

        for (auto ci = xmlElement->elements().begin(); ci != xmlElement->elements().end(); ++ci)
        {
            if((*ci)->name().compare(Checker::SEQUENCE_ELT) == 0)
            {
                regex += getRegexFromOccurs(*ci, parseComplexType(ci, "", true)) + separator;
            }
            else if((*ci)->name().compare(Checker::CHOICE_ELT) == 0)
            {
                regex += getRegexFromOccurs(*ci, parseComplexType(ci, "|", true)) + separator;
            }
            else if((*ci)->name().compare(Checker::ELEMENT_ELT) == 0)
            {
                if(eltSeqChoice || !eltParsed)
                {
                    eltParsed = true;
                    regex += parseElement(*ci) + separator;
                }
                else
                {
                    Checker::throwInvalidElementException(Checker::ELEMENT_ELT, getNameOrRef(*(*ci)));
                }
            }
            else if((*ci)->name().compare(Checker::ATTRIBUTE_ELT) == 0)
            {
                mAttributes.push_back(Xsd::Attribute::parseAttribute(*(*ci)));
            }
            else
            {
                Checker::throwInvalidElementException(Checker::COMPLEX_TYP_ELT, (*ci)->name());
            }
        }

        if(regex.back() == '|')
        {
            regex = regex.substr(0, regex.size()-1);
        }

        return regex + ")";
    }

    bool
    Type::isSimpleType(const std::string & type)
    {
        throw new NotImplementedException("Not implemented yet");
        return (type.compare(Checker::STRING_TYPE) == 0)
            || (type.compare(Checker::DATE_TYPE) == 0);
    }

    std::string
    Type::getOccursFromElement(const Xml::Element & xmlElement, const std::string & occursAttrName, const std::string & occursAttrValue)
    {
        if(occursAttrValue.compare(UNBOUNDED) == 0)
        {
            return UNBOUNDED_EXP_REG;
        }

        try
        {
            if(std::stoi(occursAttrValue) < 0)
            {
                throw new Exception();
            }
        }
        catch(const std::exception& e)
        {
            Checker::throwInvalidAttributeValueException(Checker::ELEMENT_ELT, occursAttrName, occursAttrValue);
        }

        return occursAttrValue;
    }

    std::string
    Type::getNameOrRef(const Xml::Element & xmlElement)
    {
        if(isReference(xmlElement))
        {
            return xmlElement.attribute(Checker::REF_ATTR);
        }
        return xmlElement.attribute(Checker::NAME_ATTR);
    }

    bool
    Type::isReference(const Xml::Element & xmlElement)
    {
        std::string notFound = "";
        std::string name = xmlElement.attribute(Checker::NAME_ATTR);
        std::string ref = xmlElement.attribute(Checker::REF_ATTR);

        // Name and ref attributes
        if((name.compare(notFound) == 0) && (ref.compare(notFound) != 0))
        {
            return true;
        }
        else
        {
            Checker::throwMissingAttributeException(Checker::ELEMENT_ELT, Checker::NAME_ATTR);
        }

        return false;
    }

    /**
     * Returns the regex of an element, adds its type and type relation to the maps if it's not a ref
     * The regex does not contain the validation for the element children, it's only about the element name or ref itself
     */
    std::string
    Type::parseElement(const Xml::Element & xmlElement)
    {
        bool ref = false;
        std::string regex, name;

        // Name and ref attributes
        if(isReference(xmlElement))
        {
            name = xmlElement.attribute(Checker::REF_ATTR);
            ref = true;
        }
        else
        {
            name = xmlElement.attribute(Checker::NAME_ATTR);
        }

        regex = getRegexFromOccurs(xmlElement, name);

        if(!ref)
        {
            //Type manaement
            std::string type = xmlElement.attribute(Checker::TYPE_ATTR);
            if(!type.compare("") && isSimpleType(type))
            {
                std::vector<std::string> tokens;
                throw new NotImplementedException("Not implemented yet"); tokens = NULL; //todo remove
                //tokens = Utils::split(type, ':'));
                Checker::getInstance()->addTypedElement(name, tokens.back());

            }
            else if(xmlElement.elements().size() > 0)
            {
                Xml::Element * typeElement = xmlElement.elements().front();
                if(typeElement->name().compare(Checker::COMPLEX_TYP_ELT) == 0)
                {
                    parseComplexType(typeElement, "", true);
                }
                else
                {
                    throw new XSDConstructionException("Error: type attribute or element cannot be found for " + Checker::ELEMENT_ELT + " element");
                }
            }
            else
            {
                throw new XSDConstructionException("Error: type attribute or element cannot be found for " + Checker::ELEMENT_ELT + " element");
            }
        }

        return regex;
    }

    /**
     * Modify and returns the element regex given in parameter in order to add
     * regex expression for the occurs attributes values
     */
    std::string
    Type::getRegexFromOccurs(const Xml::Element & xmlElement, const std::string & eltRegex)
    {
        std::string notFound = "", regex;
        std::string name = xmlElement.attribute(Xsd::Checker::NAME_ATTR);
        std::string ref = xmlElement.attribute(Xsd::Checker::REF_ATTR);
        std::string minOccurs = xmlElement.attribute(Checker::MIN_OCC_ATTR);
        std::string supOccurs = xmlElement.attribute(Checker::MAX_OCC_ATTR);

        // Min and max occurs attributes
        if(!(minOccurs.compare(notFound) == 0))
        {
            minOccurs = getOccursFromElement(xmlElement, Checker::MIN_OCC_ATTR, minOccurs);
        }
        else
        {
            minOccurs = "1";
        }

        if(!(supOccurs.compare(notFound) == 0))
        {
            supOccurs = getOccursFromElement(xmlElement, Checker::MAX_OCC_ATTR, supOccurs);
        }
        else
        {
            supOccurs = "0";
        }

        if((minOccurs.compare(UNBOUNDED_EXP_REG) == 0) && !(supOccurs.compare(UNBOUNDED_EXP_REG) == 0)
            || (!(supOccurs.compare(UNBOUNDED_EXP_REG) ==0) && std::stoi(supOccurs) < std::stoi(minOccurs)))
        {
            throw new XSDConstructionException("Error: " + Checker::MIN_OCC_ATTR + " attribute value is higher than " + Checker::MAX_OCC_ATTR + " value");
        }
        if((minOccurs.compare(UNBOUNDED_EXP_REG) == 0) && (supOccurs.compare(UNBOUNDED_EXP_REG) == 0))
        {
            std::stringstream out;
            out << (std::stoi(supOccurs) - std::stoi(minOccurs));
            supOccurs = out.str();
        }

        // Name and ref attributes
        if(isReference(xmlElement))
        {
            name = ref;
        }

        // Create the regex
        regex = "(<" + eltRegex + ">){" + minOccurs + "}";
        if(!(supOccurs.compare("0") == 0))
        {
            regex += "((<" + eltRegex + ">?){" + supOccurs + "})";
        }

        return regex;
    }

    std::list<Attribute *>
    Type::attributes() const
    {
        return mAttributes;
    }
}
<|endoftext|>


<commit_before>#include
#include <string_view>
#include "net/connector.hpp"
#include "xson/json.hpp"
#include "http/headers.hpp"

using namespace std;
using namespace string_view_literals;
using namespace ext;
using namespace net;
using namespace xson;

const auto usage = R"(usage: yarsh [--help] [URL])";

const auto help = R"(
Currently supported shell commands are:
POST /collection         aka Create
JSON
PUT /collection/id       aka Replace
JSON
PATCH /collection/id     aka Update/Upsert
JSON
GET /collection/{id}     aka Read
DELETE /collection/id    aka Delete
HELP                     i.e. This text
EXIT                     i.e. Exit the shell
GET /                    i.e. Returns all the collections
GET /_reindex            i.e. Reindex all the collections
)";

int main(int argc, char** argv)
try
{
    const auto arguments = span(argv,argc).subspan(1);
    auto url = "http://localhost:2112"sv;

    for(const string_view option : arguments)
    {
        if(option.starts_with("--help"))
        {
            clog << usage << endl;
            return 0;
        }
        else if(option.starts_with("-"))
        {
            clog << usage << endl;
            return 1;
        }
        else
        {
            url = option;
        }
    }

    auto server = connect(url);

    clog << help << endl;

    while(cin && server)
    {
        auto method = ""s, uri = ""s, version = "HTTP/1.1"s, content = ""s, reason = ""s;
        auto headers = http::headers{};
        auto status = 0u;

        clog << "Enter restful request: ";
        cin >> method;

        ext::to_upper(method);

        if (method == "HELP")
        {
            clog << help << endl;
            continue;
        }

        if (method == "EXIT")
        {
            clog << "Closing connection..." << endl;
            break;
        }

        cin >> uri;

        if(method == "POST" || method == "PUT" || method == "PATCH")
            content = json::stringify(json::parse(cin),0);

        clog << newl;

        clog << method << sp << uri << sp << version     << newl
               << "Host: localhost:2112 "                << newl
               << "Accept: application/json"             << newl
               << "Content-Type: application/json"       << newl
               << "Content-Length: " << content.length() << newl
               << newl
               << content
               << newl;

        clog << endl;

        server << method << sp << uri << sp << version   << crlf
               << "Host: localhost:2112 "                << crlf
               << "Accept: application/json"             << crlf
               << "Content-Type: application/json"       << crlf
               << "Content-Length: " << content.length() << crlf
               << crlf
               << content
               << flush;

        server >> version >> status;
        getline(server,reason,'\r') >> ws >> headers >> crlf;

        clog << version << sp << status << sp << reason << newl;

        auto content_length = headers.contains("content-length") ? std::stoll(headers["content-length"]) : 0ull;

        clog << newl;

        // only {} and [] are valid, complete JSON strings in parsers and stringifiers
        if(content_length > 1)
            clog << json::stringify(json::parse(server)) << newl;

        clog << endl;
    }
    clog << "See you latter - bye!" << newl;
    return 0;
}
catch(const system_error& e)
{
    cerr << "System error with code: \"" << e.code() << "\" \"" << e.what() << "\"" << endl;
    return 1;
}
catch(const std::exception& e)
{
    cerr << "Exception: \"" << e.what() << "\"" << endl;
    return 1;
}
catch(...)
{
    cerr << "Shit hit the fan!" << endl;
    return 1;
}
<commit_msg>Code refactoring<commit_after>#include
#include <string_view>
#include "net/connector.hpp"
#include "xson/json.hpp"
#include "http/headers.hpp"

using namespace std;
using namespace string_view_literals;
using namespace ext;
using namespace net;
using namespace xson;

const auto usage = R"(usage: yarsh [--help] [URL])";

const auto help = R"(
Currently supported shell commands are:
POST /collection         aka Create
JSON
PUT /collection/id       aka Replace
JSON
PATCH /collection/id     aka Update/Upsert
JSON
GET /collection/{id}     aka Read
DELETE /collection/id    aka Delete
HELP                     i.e. This text
EXIT                     i.e. Exit the shell
GET /                    i.e. Returns all the collections
GET /_reindex            i.e. Reindex all the collections
)";

int main(int argc, char** argv)
try
{
    const auto arguments = span(argv,argc).subspan(1);
    auto url = "http://localhost:2112"sv;

    for(const string_view option : arguments)
    {
        if(option.starts_with("--help"))
        {
            clog << usage << endl;
            return 0;
        }
        else if(option.starts_with("-"))
        {
            clog << usage << endl;
            return 1;
        }
        else
        {
            url = option;
        }
    }

    auto server = connect(url);

    clog << help << endl;

    while(cin && server)
    {
        auto method = ""s, uri = ""s, version = "HTTP/1.1"s, content = ""s, reason = ""s;
        auto headers = http::headers{};
        auto status = 0u;

        clog << "Enter restful request: ";
        cin >> method;

        ext::to_upper(method);

        if (method == "HELP")
        {
            clog << help << endl;
            continue;
        }

        if (method == "EXIT")
        {
            clog << "Closing connection..." << endl;
            break;
        }

        cin >> uri;

        if(method == "POST" || method == "PUT" || method == "PATCH")
            content = json::stringify(json::parse(cin),0);

        clog << newl;

        clog << method << sp << uri << sp << version     << newl
               << "Host: localhost:2112 "                << newl
               << "Accept: application/json"             << newl
               << "Content-Type: application/json"       << newl
               << "Content-Length: " << content.length() << newl
               << newl
               << content
               << newl;

        clog << endl;

        server << method << sp << uri << sp << version   << crlf
               << "Host: localhost:2112 "                << crlf
               << "Accept: application/json"             << crlf
               << "Content-Type: application/json"       << crlf
               << "Content-Length: " << content.length() << crlf
               << crlf
               << content
               << flush;

        server >> version >> status >> ws;
        getline(server,reason,'\r') >> ws >> headers >> crlf;

        clog << version << sp << status << sp << reason << newl;

        auto content_length = headers.contains("content-length") ? std::stoll(headers["content-length"]) : 0ull;

        clog << newl;

        // only {} and [] are valid, complete JSON strings in parsers and stringifiers
        if(content_length > 1)
            clog << json::stringify(json::parse(server)) << newl;

        clog << endl;
    }
    clog << "See you latter - bye!" << newl;
    return 0;
}
catch(const system_error& e)
{
    cerr << "System error with code: \"" << e.code() << "\" \"" << e.what() << "\"" << endl;
    return 1;
}
catch(const std::exception& e)
{
    cerr << "Exception: \"" << e.what() << "\"" << endl;
    return 1;
}
catch(...)
{
    cerr << "Shit hit the fan!" << endl;
    return 1;
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>

#if ABC_HOST_API_POSIX
   #include <unistd.h> // close()
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::filedesc

namespace abc {
namespace io {

filedesc_t const filedesc::smc_fdNull =
#if ABC_HOST_API_POSIX
   -1;
#elif ABC_HOST_API_WIN32
   INVALID_HANDLE_VALUE;
#else
   #error "TODO: HOST_API"
#endif

filedesc::filedesc(filedesc && fd) :
   m_fd(fd.m_fd),
   m_bOwn(fd.m_bOwn) {
   ABC_TRACE_FUNC(this);

   fd.m_fd = smc_fdNull;
   fd.m_bOwn = false;
}

filedesc::~filedesc() {
   ABC_TRACE_FUNC(this);

   if (m_bOwn && m_fd != smc_fdNull) {
#if ABC_HOST_API_POSIX
      ::close(m_fd);
#elif ABC_HOST_API_WIN32
      ::CloseHandle(m_fd);
#else
   #error "TODO: HOST_API"
#endif
   }
}

filedesc & filedesc::operator=(filedesc_t fd) {
   ABC_TRACE_FUNC(this, fd);

   if (fd != m_fd) {
      this->~filedesc();
   }
   m_fd = fd;
   m_bOwn = true;
   return *this;
}
filedesc & filedesc::operator=(filedesc && fd) {
   ABC_TRACE_FUNC(this);

   if (fd.m_fd != m_fd) {
      this->~filedesc();
      m_fd = fd.m_fd;
      m_bOwn = fd.m_bOwn;
      fd.m_fd = smc_fdNull;
   }
   return *this;
}

} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
<commit_msg>Comment on why abc::io::filedesc::~filedesc() does not check for close(2) errors<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>

#if ABC_HOST_API_POSIX
   #include <unistd.h> // close()
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::filedesc

namespace abc {
namespace io {

filedesc_t const filedesc::smc_fdNull =
#if ABC_HOST_API_POSIX
   -1;
#elif ABC_HOST_API_WIN32
   INVALID_HANDLE_VALUE;
#else
   #error "TODO: HOST_API"
#endif

filedesc::filedesc(filedesc && fd) :
   m_fd(fd.m_fd),
   m_bOwn(fd.m_bOwn) {
   ABC_TRACE_FUNC(this);

   fd.m_fd = smc_fdNull;
   fd.m_bOwn = false;
}

filedesc::~filedesc() {
   ABC_TRACE_FUNC(this);

   if (m_bOwn && m_fd != smc_fdNull) {
#if ABC_HOST_API_POSIX
      /* The man page for close(2) says:

         “Not checking the return value of close() is a common but nevertheless serious programming
         error. It is quite possible that errors on a previous write(2) operation are first reported
         at the final close(). Not checking the return value when closing the file may lead to
         silent loss of data. This can especially be observed with NFS and with disk quota. Note
         that the return value should only be used for diagnostics. In particular close() should not
         be retried after an EINTR since this may cause a reused descriptor from another thread to
         be closed.”

      For these reasons, this destructor does not check for errno because of the possible values
      that close(2) would set,
      •  EINTR is ignored here since there’s nothing this destructor can do;
      •  EIO is expected to never happen because this destructor relies on abc::io::binary::file* to
         have ensured that any outstanding I/O operations complete before this destructor is called;
      •  EBADF either can’t happen, or if it happens there’s nothing this destructor can do. */
      ::close(m_fd);
#elif ABC_HOST_API_WIN32
      ::CloseHandle(m_fd);
#else
   #error "TODO: HOST_API"
#endif
   }
}

filedesc & filedesc::operator=(filedesc_t fd) {
   ABC_TRACE_FUNC(this, fd);

   if (fd != m_fd) {
      this->~filedesc();
   }
   m_fd = fd;
   m_bOwn = true;
   return *this;
}
filedesc & filedesc::operator=(filedesc && fd) {
   ABC_TRACE_FUNC(this);

   if (fd.m_fd != m_fd) {
      this->~filedesc();
      m_fd = fd.m_fd;
      m_bOwn = fd.m_bOwn;
      fd.m_fd = smc_fdNull;
   }
   return *this;
}

} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/UI/CQLayoutsWidget.cpp,v $
//   $Revision: 1.16 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2011/10/13 17:24:27 $
// End CVS Header

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

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

#include "CQLayoutsWidget.h"

#include <iostream>

#include "CQMessageBox.h"
#include "CQLayoutsDM.h"
#include "CQSortFilterProxyModel.h"
#include "CQPushButtonDelegate.h"

#include "listviews.h"
#include "qtUtilities.h"
#include "copasi/layout/CLayout.h"
#include "copasi/layout/CListOfLayouts.h"
#include "copasi/model/CModel.h"
#include "copasi/report/CKeyFactory.h"
#include "copasi/CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"

#ifdef USE_CRENDER_EXTENSION
# include "copasi/layoutUI/CQNewMainWindow.h"
#else
# include "copasi/layoutUI/CQLayoutMainWindow.h"
#endif // USE_CRENDER_EXTENSION

#ifdef COPASI_AUTOLAYOUT
# include "copasi/layoutUI/CQAutolayoutWizard.h"
#endif // COPASI_AUTOLAYOUT

CQLayoutsWidget::CQLayoutsWidget(QWidget* parent)
    : CopasiWidget(parent)
{
  setupUi(this);

#ifndef COPASI_AUTOLAYOUT
  mpBtnNew->hide();
#endif

  // Create Source Data Model.
  mpLayoutsDM = new CQLayoutsDM(this);

  // Create the Proxy Model for sorting/filtering and set its properties.
  mpProxyModel = new CQSortFilterProxyModel();
  mpProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
  mpProxyModel->setFilterKeyColumn(-1);
  mpProxyModel->setSourceModel(mpLayoutsDM);

  mpTblLayouts->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
  mpTblLayouts->verticalHeader()->hide();
  mpTblLayouts->sortByColumn(COL_ROW_NUMBER, Qt::AscendingOrder);
  mpTblLayouts->setModel(mpProxyModel);

  mpPushButtonDelegate = new CQPushButtonDelegate(QIcon(), QString(), CQPushButtonDelegate::PushButton, this);

  mpTblLayouts->setItemDelegateForColumn(COL_SHOW, mpPushButtonDelegate);

  // Connect the table widget
  connect(mpLayoutsDM, SIGNAL(notifyGUI(ListViews::ObjectType, ListViews::Action, const std::string)),
          this, SLOT(protectedNotify(ListViews::ObjectType, ListViews::Action, const std::string)));
  connect(mpLayoutsDM, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
          this, SLOT(dataChanged(const QModelIndex&, const QModelIndex&)));
  connect(mpLEFilter, SIGNAL(textChanged(const QString &)),
          this, SLOT(slotFilterChanged()));
  connect(mpPushButtonDelegate, SIGNAL(clicked(int)), this, SLOT(slotShowLayout(int)));
}

// virtual
CQLayoutsWidget::~CQLayoutsWidget()
{}

// virtual
bool CQLayoutsWidget::update(ListViews::ObjectType /* objectType */, ListViews::Action /* action */, const std::string & /* key */)
{
  if (!mIgnoreUpdates)
    {
      enterProtected();
    }

  return true;
}

// virtual
bool CQLayoutsWidget::leave()
{
  return true;
}

void CQLayoutsWidget::deleteLayoutWindows()
{
  LayoutWindowMap::iterator it = mLayoutWindowMap.begin(), endit = mLayoutWindowMap.end();

  while (it != endit)
    {
      delete it->second;
      ++it;
    }

  mLayoutWindowMap.clear();
}

void CQLayoutsWidget::deleteSelectedLayouts()
{
  const QItemSelectionModel * pSelectionModel = mpTblLayouts->selectionModel();

  QModelIndexList mappedSelRows;
  size_t i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; i++)
    {
      if (pSelectionModel->isRowSelected((int) i, QModelIndex()))
        {
          mappedSelRows.append(mpProxyModel->mapToSource(mpProxyModel->index((int) i, 0)));
        }
    }

  if (mappedSelRows.empty()) return;

  // We need to make sure that we remove the window mapped for each layout
  QModelIndexList::const_iterator it = mappedSelRows.begin();
  QModelIndexList::const_iterator end = mappedSelRows.end();

  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CListOfLayouts * pListOfLayouts = (*CCopasiRootContainer::getDatamodelList())[0]->getListOfLayouts();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator itWindow = mLayoutWindowMap.find((*pListOfLayouts)[it->row()]->getKey());

      if (itWindow != mLayoutWindowMap.end())
        {
          mLayoutWindowMap.erase(itWindow);
          delete itWindow->second;
        }
    }

  mpLayoutsDM->removeRows(mappedSelRows);
}

void CQLayoutsWidget::updateDeleteBtns()
{
  mpBtnDelete->setEnabled(mpTblLayouts->selectionModel()->selectedRows().size() > 0);
  mpBtnClear->setEnabled(mpProxyModel->rowCount() > 0);
}

// virtual
bool CQLayoutsWidget::enterProtected()
{
  if (mpTblLayouts->selectionModel() != NULL)
    {
      disconnect(mpTblLayouts->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
                 this, SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
    }

  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CListOfLayouts * pListOfLayouts = (*CCopasiRootContainer::getDatamodelList())[0]->getListOfLayouts();
  mpLayoutsDM->setListOfLayouts(pListOfLayouts);

  // check if we have at least a compartment
  // that we can lay out.
  CCopasiDataModel* pDataModel = (*CCopasiRootContainer::getDatamodelList())[0];

  if (pDataModel != NULL &&
      pDataModel->getModel() != NULL &&
      pDataModel->getModel()->getCompartments().size() > 0)
    {
      mpBtnNew->setEnabled(true);
    }
  else
    {
      mpBtnNew->setEnabled(false);
    }

  // We need to make sure that we have a window mapped for each layout
  CListOfLayouts::const_iterator it = pListOfLayouts->begin();
  CListOfLayouts::const_iterator end = pListOfLayouts->end();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator pos = mLayoutWindowMap.find((*it)->getKey());

      // if this layout does not have an entry in the layout window map, add one
      if (pos == mLayoutWindowMap.end())
        {
          mLayoutWindowMap.insert(std::pair<std::string, LayoutWindow*>((*it)->getKey(), NULL));
        }

    }

  connect(mpTblLayouts->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
          this, SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));

  dataChanged(QModelIndex(), QModelIndex());

  return true;
}

void CQLayoutsWidget::showButtons()
{
  int i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; ++i)
    {
      this->mpTblLayouts->openPersistentEditor(mpProxyModel->index(i, COL_SHOW, QModelIndex()));
    }
}

// virtual
void CQLayoutsWidget::slotBtnNewClicked()
{
#ifdef COPASI_AUTOLAYOUT
  CLayout* pLayout = new CLayout("COPASI autolayout");
  CCopasiDataModel* pDataModel = (*CCopasiRootContainer::getDatamodelList())[0];
  const CModel* pModel = pDataModel->getModel();
  assert(pModel != NULL);
  CQAutolayoutWizard* pWizard = new CQAutolayoutWizard(*pModel);

  if (pWizard->exec() == QDialog::Accepted)
    {
      // add the layout to the datamodel
      std::map<std::string, std::string> m;

      CListOfLayouts * pListOfLayouts = pDataModel->getListOfLayouts();
      pListOfLayouts->addLayout(pLayout, m);

      // update the table
      mpLayoutsDM->insertRows(pListOfLayouts->size() - 1, 1);
      dataChanged(QModelIndex(), QModelIndex());

      CQNewMainWindow* pWin = createLayoutWindow(pListOfLayouts->size() - 1, pLayout);
      assert(pWin != NULL);

      if (pWin != NULL)
        {
          // create the random layout
          pWin->createRandomLayout(pWizard->getSelectedCompartments(), pWizard->getSelectedReactions(), pWizard->getSelectedMetabolites(), pWizard->getSideMetabolites());
          pWin->updateRenderer();
          // show the new layout
          pWin->show();
          pWin->redrawNow();
          // now we create the spring layout
          pWin->createSpringLayout(1000, 1);
        }

    }
  else
    {
      delete pLayout;
    }

#endif // COPASI_AUTOLAYOUT
}

// virtual
void CQLayoutsWidget::slotBtnDeleteClicked()
{
  if (mpTblLayouts->hasFocus())
    {deleteSelectedLayouts();}
}

// virtual
void CQLayoutsWidget::slotBtnClearClicked()
{
  int ret = QMessageBox::question(this, tr("Confirm Delete"), "Delete all Layouts?",
                                  QMessageBox::Yes | QMessageBox::No, QMessageBox::No);

  if (ret == QMessageBox::Yes)
    {
      mpLayoutsDM->clear();
      deleteLayoutWindows();
    }
}

// virtual
void CQLayoutsWidget::slotSelectionChanged(const QItemSelection & /* selected */,
    const QItemSelection & /* deselected */)
{
  updateDeleteBtns();
}

// virtual
void CQLayoutsWidget::slotDoubleClicked(const QModelIndex proxyIndex)
{
  QModelIndex index = mpProxyModel->mapToSource(proxyIndex);

  int row = index.row();

  if (row >= mpLayoutsDM->rowCount() || row < 0) return;

  slotShowLayout(row);
}

// virtual
void CQLayoutsWidget::dataChanged(const QModelIndex & /* topLeft */,
                                  const QModelIndex & /* bottomRight */)
{
  mpTblLayouts->resizeColumnsToContents();
  updateDeleteBtns();
  showButtons();
}

// virtual
void CQLayoutsWidget::slotFilterChanged()
{
  QRegExp regExp(mpLEFilter->text(), Qt::CaseInsensitive, QRegExp::RegExp);
  mpProxyModel->setFilterRegExp(regExp);
}

/**
 * This creates a new layout window and return a pointer to it.
 * In case of an error, NULL is returned.
 */
CQLayoutsWidget::LayoutWindow * CQLayoutsWidget::createLayoutWindow(int row, CLayout* pLayout)
{
  if (pLayout == NULL || row < 0) return NULL;

#ifdef USE_CRENDER_EXTENSION
  LayoutWindow * pWin = new CQNewMainWindow((*CCopasiRootContainer::getDatamodelList())[0]);
  pWin->slotLayoutChanged(row);
#else
  LayoutWindow * pWin = new CQLayoutMainWindow(pLayout);
#endif // USE_CRENDER_EXTENSION

  pWin->setWindowTitle(pLayout->getObjectName().c_str());
  pWin->resize(900, 600);
  mLayoutWindowMap[pLayout->getKey()] = pWin;

  return pWin;
}

void CQLayoutsWidget::slotShowLayout(int row)
{
  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CListOfLayouts* pListOfLayouts = (*CCopasiRootContainer::getDatamodelList())[0]->getListOfLayouts();

  CLayout* pLayout = (* pListOfLayouts)[row];
  std::string Key = pLayout->getKey();

  if (pLayout != NULL)
    {
      // check if we already have a widget for the layout
      // if yes, open it, else create one and add it to the map
      LayoutWindow * pLayoutWindow = NULL;

      LayoutWindowMap::iterator pos = mLayoutWindowMap.find(Key);

      if (pos != mLayoutWindowMap.end())
        {
          pLayoutWindow = pos->second;
        }

      if (pLayoutWindow == NULL)
        {
          pLayoutWindow = createLayoutWindow(row, pLayout);
        }

      if (pLayoutWindow != NULL)
        {
#ifdef USE_CRENDER_EXTENSION
          pLayoutWindow->slotLayoutChanged(row);
#endif // USE_CRENDER_EXTENSION
          pLayoutWindow->show();
          pLayoutWindow->showNormal();
          pLayoutWindow->setActiveWindow();
        }
    }
  else
    {
      //std::cerr << "Could not find layout." << std::endl;
    }
}

<commit_msg>Fixed crash.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/UI/CQLayoutsWidget.cpp,v $
//   $Revision: 1.17 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2012/03/15 19:07:26 $
// End CVS Header

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

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

#include "CQLayoutsWidget.h"

#include <iostream>

#include "CQMessageBox.h"
#include "CQLayoutsDM.h"
#include "CQSortFilterProxyModel.h"
#include "CQPushButtonDelegate.h"

#include "listviews.h"
#include "qtUtilities.h"
#include "resourcesUI/CQIconResource.h"

#include "copasi/layout/CLayout.h"
#include "copasi/layout/CListOfLayouts.h"
#include "copasi/model/CModel.h"
#include "copasi/report/CKeyFactory.h"
#include "copasi/CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"

#ifdef USE_CRENDER_EXTENSION
# include "copasi/layoutUI/CQNewMainWindow.h"
#else
# include "copasi/layoutUI/CQLayoutMainWindow.h"
#endif // USE_CRENDER_EXTENSION

#ifdef COPASI_AUTOLAYOUT
# include "copasi/layoutUI/CQAutolayoutWizard.h"
#endif // COPASI_AUTOLAYOUT

CQLayoutsWidget::CQLayoutsWidget(QWidget* parent)
    : CopasiWidget(parent)
{
  setupUi(this);

#ifndef COPASI_AUTOLAYOUT
  mpBtnNew->hide();
#endif

  // Create Source Data Model.
  mpLayoutsDM = new CQLayoutsDM(this);

  // Create the Proxy Model for sorting/filtering and set its properties.
  mpProxyModel = new CQSortFilterProxyModel();
  mpProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
  mpProxyModel->setFilterKeyColumn(-1);
  mpProxyModel->setSourceModel(mpLayoutsDM);

  mpTblLayouts->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
  mpTblLayouts->verticalHeader()->hide();
  mpTblLayouts->sortByColumn(COL_ROW_NUMBER, Qt::AscendingOrder);
  mpTblLayouts->setModel(mpProxyModel);

  mpPushButtonDelegate = new CQPushButtonDelegate(CQIconResource::icon(CQIconResource::unknown), QString(), CQPushButtonDelegate::PushButton, this);

  mpTblLayouts->setItemDelegateForColumn(COL_SHOW, mpPushButtonDelegate);

  // Connect the table widget
  connect(mpLayoutsDM, SIGNAL(notifyGUI(ListViews::ObjectType, ListViews::Action, const std::string)),
          this, SLOT(protectedNotify(ListViews::ObjectType, ListViews::Action, const std::string)));
  connect(mpLayoutsDM, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
          this, SLOT(dataChanged(const QModelIndex&, const QModelIndex&)));
  connect(mpLEFilter, SIGNAL(textChanged(const QString &)),
          this, SLOT(slotFilterChanged()));
  connect(mpPushButtonDelegate, SIGNAL(clicked(int)), this, SLOT(slotShowLayout(int)));
}

// virtual
CQLayoutsWidget::~CQLayoutsWidget()
{}

// virtual
bool CQLayoutsWidget::update(ListViews::ObjectType /* objectType */, ListViews::Action /* action */, const std::string & /* key */)
{
  if (!mIgnoreUpdates)
    {
      enterProtected();
    }

  return true;
}

// virtual
bool CQLayoutsWidget::leave()
{
  return true;
}

void CQLayoutsWidget::deleteLayoutWindows()
{
  LayoutWindowMap::iterator it = mLayoutWindowMap.begin(), endit = mLayoutWindowMap.end();

  while (it != endit)
    {
      delete it->second;
      ++it;
    }

  mLayoutWindowMap.clear();
}

void CQLayoutsWidget::deleteSelectedLayouts()
{
  const QItemSelectionModel * pSelectionModel = mpTblLayouts->selectionModel();

  QModelIndexList mappedSelRows;
  size_t i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; i++)
    {
      if (pSelectionModel->isRowSelected((int) i, QModelIndex()))
        {
          mappedSelRows.append(mpProxyModel->mapToSource(mpProxyModel->index((int) i, 0)));
        }
    }

  if (mappedSelRows.empty()) return;

  // We need to make sure that we remove the window mapped for each layout
  QModelIndexList::const_iterator it = mappedSelRows.begin();
  QModelIndexList::const_iterator end = mappedSelRows.end();

  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CListOfLayouts * pListOfLayouts = (*CCopasiRootContainer::getDatamodelList())[0]->getListOfLayouts();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator itWindow = mLayoutWindowMap.find((*pListOfLayouts)[it->row()]->getKey());

      if (itWindow != mLayoutWindowMap.end())
        {
          mLayoutWindowMap.erase(itWindow);
          delete itWindow->second;
        }
    }

  mpLayoutsDM->removeRows(mappedSelRows);
}

void CQLayoutsWidget::updateDeleteBtns()
{
  mpBtnDelete->setEnabled(mpTblLayouts->selectionModel()->selectedRows().size() > 0);
  mpBtnClear->setEnabled(mpProxyModel->rowCount() > 0);
}

// virtual
bool CQLayoutsWidget::enterProtected()
{
  if (mpTblLayouts->selectionModel() != NULL)
    {
      disconnect(mpTblLayouts->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
                 this, SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));
    }

  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CListOfLayouts * pListOfLayouts = (*CCopasiRootContainer::getDatamodelList())[0]->getListOfLayouts();
  mpLayoutsDM->setListOfLayouts(pListOfLayouts);

  // check if we have at least a compartment
  // that we can lay out.
  CCopasiDataModel* pDataModel = (*CCopasiRootContainer::getDatamodelList())[0];

  if (pDataModel != NULL &&
      pDataModel->getModel() != NULL &&
      pDataModel->getModel()->getCompartments().size() > 0)
    {
      mpBtnNew->setEnabled(true);
    }
  else
    {
      mpBtnNew->setEnabled(false);
    }

  // We need to make sure that we have a window mapped for each layout
  CListOfLayouts::const_iterator it = pListOfLayouts->begin();
  CListOfLayouts::const_iterator end = pListOfLayouts->end();

  for (; it != end; ++it)
    {
      LayoutWindowMap::iterator pos = mLayoutWindowMap.find((*it)->getKey());

      // if this layout does not have an entry in the layout window map, add one
      if (pos == mLayoutWindowMap.end())
        {
          mLayoutWindowMap.insert(std::pair<std::string, LayoutWindow*>((*it)->getKey(), NULL));
        }

    }

  connect(mpTblLayouts->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
          this, SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection&)));

  dataChanged(QModelIndex(), QModelIndex());

  return true;
}

void CQLayoutsWidget::showButtons()
{
  int i, imax = mpLayoutsDM->rowCount();

  for (i = 0; i < imax; ++i)
    {
      this->mpTblLayouts->openPersistentEditor(mpProxyModel->index(i, COL_SHOW, QModelIndex()));
    }
}

// virtual
void CQLayoutsWidget::slotBtnNewClicked()
{
#ifdef COPASI_AUTOLAYOUT
  CLayout* pLayout = new CLayout("COPASI autolayout");
  CCopasiDataModel* pDataModel = (*CCopasiRootContainer::getDatamodelList())[0];
  const CModel* pModel = pDataModel->getModel();
  assert(pModel != NULL);
  CQAutolayoutWizard* pWizard = new CQAutolayoutWizard(*pModel);

  if (pWizard->exec() == QDialog::Accepted)
    {
      // add the layout to the datamodel
      std::map<std::string, std::string> m;

      CListOfLayouts * pListOfLayouts = pDataModel->getListOfLayouts();
      pListOfLayouts->addLayout(pLayout, m);

      // update the table
      mpLayoutsDM->insertRows(pListOfLayouts->size() - 1, 1);
      dataChanged(QModelIndex(), QModelIndex());

      CQNewMainWindow* pWin = createLayoutWindow(pListOfLayouts->size() - 1, pLayout);
      assert(pWin != NULL);

      if (pWin != NULL)
        {
          // create the random layout
          pWin->createRandomLayout(pWizard->getSelectedCompartments(), pWizard->getSelectedReactions(), pWizard->getSelectedMetabolites(), pWizard->getSideMetabolites());
          pWin->updateRenderer();
          // show the new layout
          pWin->show();
          pWin->redrawNow();
          // now we create the spring layout
          pWin->createSpringLayout(1000, 1);
        }

    }
  else
    {
      delete pLayout;
    }

#endif // COPASI_AUTOLAYOUT
}

// virtual
void CQLayoutsWidget::slotBtnDeleteClicked()
{
  if (mpTblLayouts->hasFocus())
    {deleteSelectedLayouts();}
}

// virtual
void CQLayoutsWidget::slotBtnClearClicked()
{
  int ret = QMessageBox::question(this, tr("Confirm Delete"), "Delete all Layouts?",
                                  QMessageBox::Yes | QMessageBox::No, QMessageBox::No);

  if (ret == QMessageBox::Yes)
    {
      mpLayoutsDM->clear();
      deleteLayoutWindows();
    }
}

// virtual
void CQLayoutsWidget::slotSelectionChanged(const QItemSelection & /* selected */,
    const QItemSelection & /* deselected */)
{
  updateDeleteBtns();
}

// virtual
void CQLayoutsWidget::slotDoubleClicked(const QModelIndex proxyIndex)
{
  QModelIndex index = mpProxyModel->mapToSource(proxyIndex);

  int row = index.row();

  if (row >= mpLayoutsDM->rowCount() || row < 0) return;

  slotShowLayout(row);
}

// virtual
void CQLayoutsWidget::dataChanged(const QModelIndex & /* topLeft */,
                                  const QModelIndex & /* bottomRight */)
{
  mpTblLayouts->resizeColumnsToContents();
  updateDeleteBtns();
  showButtons();
}

// virtual
void CQLayoutsWidget::slotFilterChanged()
{
  QRegExp regExp(mpLEFilter->text(), Qt::CaseInsensitive, QRegExp::RegExp);
  mpProxyModel->setFilterRegExp(regExp);
}

/**
 * This creates a new layout window and return a pointer to it.
 * In case of an error, NULL is returned.
 */
CQLayoutsWidget::LayoutWindow * CQLayoutsWidget::createLayoutWindow(int row, CLayout* pLayout)
{
  if (pLayout == NULL || row < 0) return NULL;

#ifdef USE_CRENDER_EXTENSION
  LayoutWindow * pWin = new CQNewMainWindow((*CCopasiRootContainer::getDatamodelList())[0]);
  pWin->slotLayoutChanged(row);
#else
  LayoutWindow * pWin = new CQLayoutMainWindow(pLayout);
#endif // USE_CRENDER_EXTENSION

  pWin->setWindowTitle(pLayout->getObjectName().c_str());
  pWin->resize(900, 600);
  mLayoutWindowMap[pLayout->getKey()] = pWin;

  return pWin;
}

void CQLayoutsWidget::slotShowLayout(int row)
{
  assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
  CListOfLayouts* pListOfLayouts = (*CCopasiRootContainer::getDatamodelList())[0]->getListOfLayouts();

  CLayout* pLayout = (* pListOfLayouts)[row];
  std::string Key = pLayout->getKey();

  if (pLayout != NULL)
    {
      // check if we already have a widget for the layout
      // if yes, open it, else create one and add it to the map
      LayoutWindow * pLayoutWindow = NULL;

      LayoutWindowMap::iterator pos = mLayoutWindowMap.find(Key);

      if (pos != mLayoutWindowMap.end())
        {
          pLayoutWindow = pos->second;
        }

      if (pLayoutWindow == NULL)
        {
          pLayoutWindow = createLayoutWindow(row, pLayout);
        }

      if (pLayoutWindow != NULL)
        {
#ifdef USE_CRENDER_EXTENSION
          pLayoutWindow->slotLayoutChanged(row);
#endif // USE_CRENDER_EXTENSION
          pLayoutWindow->show();
          pLayoutWindow->showNormal();
          pLayoutWindow->setActiveWindow();
        }
    }
  else
    {
      //std::cerr << "Could not find layout." << std::endl;
    }
}

<|endoftext|>