<commit_before>// include LiteSQL's header file and generated header file
#include <iostream>
#include "litesql.hpp"
#include "exampledatabase.hpp"
// provide implementation for Person::sayHello
void example::Person::sayHello() {
    std::cout << "Hi! My name is " << name
        << " and I am " << age << " years old." << std::endl;
}

// no name collisions expected
using namespace litesql;
using namespace example;

int main(int argc, char **argv) {
    try {
        // using SQLite3 as backend
        ExampleDatabase db("sqlite3", "database=example.db");
        // create tables, sequences and indexes
        db.create();
        char buf[100];
        gets(buf);
        db.query("select * from Person_");

        // create couple of Person-objects
        Person jeff(db);
        jeff.name = "Jeff";
        jeff.sex = Person::Sex::Male;
        jeff.age = 32;
        // store Jeff to database
        jeff.update();
        Person jill(db);
        jill.name = "Jill";
        jill.sex = Person::Sex::Female;
        jill.age = 33;
        jill.update();
        Person jack(db);
        jack.name = "Jack";
        jack.sex = Person::Sex::Male;
        jack.update();
        Person jess(db);
        jess.name = "Jess";
        jess.sex = Person::Sex::Female;
        jess.update();
        // build up relationships between Persons
        jeff.children().link(jack);
        jill.children().link(jack);
        jill.children().link(jess);
        jack.father().link(jeff);
        jack.mother().link(jill);
        jill.mother().link(jill);
        jack.siblings().link(jill);
        // select all Persons and order them by age
        vector<Person> family = select<Person>(db).orderBy(Person::age_).all();
        // show results
        for (vector<Person>::iterator i = family.begin(); i != family.end(); i++)
            cout << toString(*i) << endl;

        // select intersection of Jeff's and Jill's children and
        // iterate results with cursor
        family = jeff.children().get().all();
        for (vector<Person>::iterator i = family.begin(); i != family.end(); i++)
            cout << toString(*i) << endl;

        Cursor<Person> cursor = intersect(jeff.children().get(),
                                          jill.children().get()).cursor();
        // Jack should say hello
        for (;cursor.rowsLeft();cursor++)
            (*cursor).sayHello();

        // select a non-existing Person
        try {
            select<Person>(db, Person::id_ == 100).one();
        } catch (NotFound e) {
            cout << "No Person with id 100" << endl;
        }
        // clean up
        db.drop();
    } catch (Except e) {
        cerr << e << endl;
        return -1;
    }
    return 0;
}
<commit_msg>debug-stuff removed<commit_after>// include LiteSQL's header file and generated header file
#include <iostream>
#include "litesql.hpp"
#include "exampledatabase.hpp"
// provide implementation for Person::sayHello
void example::Person::sayHello() {
    std::cout << "Hi! My name is " << name
        << " and I am " << age << " years old." << std::endl;
}

// no name collisions expected
using namespace litesql;
using namespace example;

int main(int argc, char **argv) {
    try {
        // using SQLite3 as backend
        ExampleDatabase db("sqlite3", "database=example.db");
        // create tables, sequences and indexes
        db.create();

        // create couple of Person-objects
        Person jeff(db);
        jeff.name = "Jeff";
        jeff.sex = Person::Sex::Male;
        jeff.age = 32;
        // store Jeff to database
        jeff.update();
        Person jill(db);
        jill.name = "Jill";
        jill.sex = Person::Sex::Female;
        jill.age = 33;
        jill.update();
        Person jack(db);
        jack.name = "Jack";
        jack.sex = Person::Sex::Male;
        jack.update();
        Person jess(db);
        jess.name = "Jess";
        jess.sex = Person::Sex::Female;
        jess.update();
        // build up relationships between Persons
        jeff.children().link(jack);
        jill.children().link(jack);
        jill.children().link(jess);
        jack.father().link(jeff);
        jack.mother().link(jill);
        jill.mother().link(jill);
        jack.siblings().link(jill);
        // select all Persons and order them by age
        vector<Person> family = select<Person>(db).orderBy(Person::age_).all();
        // show results
        for (vector<Person>::iterator i = family.begin(); i != family.end(); i++)
            cout << toString(*i) << endl;

        // select intersection of Jeff's and Jill's children and
        // iterate results with cursor
        family = jeff.children().get().all();
        for (vector<Person>::iterator i = family.begin(); i != family.end(); i++)
            cout << toString(*i) << endl;

        Cursor<Person> cursor = intersect(jeff.children().get(),
                                          jill.children().get()).cursor();
        // Jack should say hello
        for (;cursor.rowsLeft();cursor++)
            (*cursor).sayHello();

        // select a non-existing Person
        try {
            select<Person>(db, Person::id_ == 100).one();
        } catch (NotFound e) {
            cout << "No Person with id 100" << endl;
        }
        // clean up
        db.drop();
    } catch (Except e) {
        cerr << e << endl;
        return -1;
    }
    return 0;
}
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2015-2019, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <fg/defines.h>
#include <fg/exception.h>
#include <err_common.hpp>
#include <vector>

static const float GRAY[]  = {0.0f   , 0.0f   , 0.0f   , 1.0f};
static const float WHITE[] = {1.0f   , 1.0f   , 1.0f   , 1.0f};
static const float BLUE[]  = {0.0588f, 0.1137f, 0.2745f, 1.0f};
static const float RED[]   = {1.0f   , 0.0f   , 0.0f   , 1.0f};

namespace internal
{

/* Basic renderable class
 *
 * Any object that is renderable to a window should inherit from this
 * class.
 */
class AbstractRenderable {
    public:
        /* render is a pure virtual function.
         * @pX X coordinate at which the currently bound viewport begins.
         * @pX Y coordinate at which the currently bound viewport begins.
         * @pViewPortWidth Width of the currently bound viewport.
         * @pViewPortHeight Height of the currently bound viewport.
         *
         * Any concrete class that inherits AbstractRenderable class needs to
         * implement this method to render their OpenGL objects to
         * the currently bound viewport.
         *
         * @return nothing.
         */
        virtual void render(int pWindowId,
                int pX, int pY, int pViewPortWidth, int pViewPortHeight) = 0;

        /* virtual function to set colormap, a derviced class might
         * use it or ignore it if it doesnt have a need for color maps */
        virtual void setColorMapUBOParams(GLuint ubo, GLuint size) {
        }
};

}

GLenum gl_dtype(fg::dtype val);

GLenum gl_ctype(fg::ChannelFormat mode);

GLenum gl_ictype(fg::ChannelFormat mode);

char* loadFile(const char *fname, GLint &fSize);

GLuint initShaders(const char* vshader_code, const char* fshader_code);

template<typename T>
GLuint createBuffer(GLenum target, size_t size, const T* data, GLenum usage)
{
    GLuint ret_val = 0;
    glGenBuffers(1, &ret_val);
    glBindBuffer(target, ret_val);
    glBufferData(target, size*sizeof(T), data, usage);
    glBindBuffer(target, 0);
    return ret_val;
}

int next_p2(int value);

float clampTo01(float a);

#ifdef OS_WIN
void getFontFilePaths(std::vector<std::string>& pFiles, std::string pDir, std::string pExt);
#endif

std::string toString(float pVal, const int n = 2);
<commit_msg>Forcing usage of radians for angle measure in glm<commit_after>/*******************************************************
 * Copyright (c) 2015-2019, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#define GLM_FORCE_RADIANS
#include <fg/defines.h>
#include <fg/exception.h>
#include <err_common.hpp>
#include <vector>

static const float GRAY[]  = {0.0f   , 0.0f   , 0.0f   , 1.0f};
static const float WHITE[] = {1.0f   , 1.0f   , 1.0f   , 1.0f};
static const float BLUE[]  = {0.0588f, 0.1137f, 0.2745f, 1.0f};
static const float RED[]   = {1.0f   , 0.0f   , 0.0f   , 1.0f};

namespace internal
{

/* Basic renderable class
 *
 * Any object that is renderable to a window should inherit from this
 * class.
 */
class AbstractRenderable {
    public:
        /* render is a pure virtual function.
         * @pX X coordinate at which the currently bound viewport begins.
         * @pX Y coordinate at which the currently bound viewport begins.
         * @pViewPortWidth Width of the currently bound viewport.
         * @pViewPortHeight Height of the currently bound viewport.
         *
         * Any concrete class that inherits AbstractRenderable class needs to
         * implement this method to render their OpenGL objects to
         * the currently bound viewport.
         *
         * @return nothing.
         */
        virtual void render(int pWindowId,
                int pX, int pY, int pViewPortWidth, int pViewPortHeight) = 0;

        /* virtual function to set colormap, a derviced class might
         * use it or ignore it if it doesnt have a need for color maps */
        virtual void setColorMapUBOParams(GLuint ubo, GLuint size) {
        }
};

}

GLenum gl_dtype(fg::dtype val);

GLenum gl_ctype(fg::ChannelFormat mode);

GLenum gl_ictype(fg::ChannelFormat mode);

char* loadFile(const char *fname, GLint &fSize);

GLuint initShaders(const char* vshader_code, const char* fshader_code);

template<typename T>
GLuint createBuffer(GLenum target, size_t size, const T* data, GLenum usage)
{
    GLuint ret_val = 0;
    glGenBuffers(1, &ret_val);
    glBindBuffer(target, ret_val);
    glBufferData(target, size*sizeof(T), data, usage);
    glBindBuffer(target, 0);
    return ret_val;
}

int next_p2(int value);

float clampTo01(float a);

#ifdef OS_WIN
void getFontFilePaths(std::vector<std::string>& pFiles, std::string pDir, std::string pExt);
#endif

std::string toString(float pVal, const int n = 2);
<|endoftext|>


<commit_before>#include "FlightTask.hpp"
#include <mathlib/mathlib.h>
#include <lib/ecl/geo/geo.h>

constexpr uint64_t FlightTask::_timeout;
// First index of empty_setpoint corresponds to time-stamp and requires a finite number.
const vehicle_local_position_setpoint_s FlightTask::empty_setpoint = {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, {NAN, NAN, NAN}};

const vehicle_constraints_s FlightTask::empty_constraints = {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, {}};
const landing_gear_s FlightTask::landing_gear_default_keep = {0, landing_gear_s::GEAR_KEEP, {}};
const vehicle_trajectory_waypoint_s FlightTask::empty_trajectory_waypoint = {0, 0, {0, 0, 0, 0, 0, 0, 0},
	{	{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}}
	}
};

bool FlightTask::initializeSubscriptions(SubscriptionArray &subscription_array)
{
	if (!subscription_array.get(ORB_ID(vehicle_local_position), _sub_vehicle_local_position)) {
		return false;
	}

	if (!subscription_array.get(ORB_ID(vehicle_attitude), _sub_attitude)) {
		return false;
	}

	return true;
}

bool FlightTask::activate()
{
	_resetSetpoints();
	_setDefaultConstraints();
	_time_stamp_activate = hrt_absolute_time();
	_heading_reset_counter = _sub_attitude->get().quat_reset_counter;
	return true;
}

void FlightTask::reActivate()
{
	activate();
}

bool FlightTask::updateInitialize()
{
	_time_stamp_current = hrt_absolute_time();
	_time = (_time_stamp_current - _time_stamp_activate) / 1e6f;
	_deltatime  = math::min((_time_stamp_current - _time_stamp_last), _timeout) / 1e6f;
	_time_stamp_last = _time_stamp_current;
	_evaluateVehicleLocalPosition();
	return true;
}

const vehicle_local_position_setpoint_s FlightTask::getPositionSetpoint()
{
	/* fill position setpoint message */
	vehicle_local_position_setpoint_s vehicle_local_position_setpoint;
	vehicle_local_position_setpoint.timestamp = hrt_absolute_time();

	vehicle_local_position_setpoint.x = _position_setpoint(0);
	vehicle_local_position_setpoint.y = _position_setpoint(1);
	vehicle_local_position_setpoint.z = _position_setpoint(2);

	vehicle_local_position_setpoint.vx = _velocity_setpoint(0);
	vehicle_local_position_setpoint.vy = _velocity_setpoint(1);
	vehicle_local_position_setpoint.vz = _velocity_setpoint(2);

	vehicle_local_position_setpoint.acc_x = _acceleration_setpoint(0);
	vehicle_local_position_setpoint.acc_y = _acceleration_setpoint(1);
	vehicle_local_position_setpoint.acc_z = _acceleration_setpoint(2);

	vehicle_local_position_setpoint.jerk_x = _jerk_setpoint(0);
	vehicle_local_position_setpoint.jerk_y = _jerk_setpoint(1);
	vehicle_local_position_setpoint.jerk_z = _jerk_setpoint(2);

	_thrust_setpoint.copyTo(vehicle_local_position_setpoint.thrust);
	vehicle_local_position_setpoint.yaw = _yaw_setpoint;
	vehicle_local_position_setpoint.yawspeed = _yawspeed_setpoint;

	return vehicle_local_position_setpoint;
}

void FlightTask::_resetSetpoints()
{
	_position_setpoint.setAll(NAN);
	_velocity_setpoint.setAll(NAN);
	_acceleration_setpoint.setAll(NAN);
	_jerk_setpoint.setAll(NAN);
	_thrust_setpoint.setAll(NAN);
	_yaw_setpoint = _yawspeed_setpoint = NAN;
	_desired_waypoint = FlightTask::empty_trajectory_waypoint;
}

void FlightTask::_evaluateVehicleLocalPosition()
{
	_position.setAll(NAN);
	_velocity.setAll(NAN);
	_yaw = NAN;
	_dist_to_bottom = NAN;

	if ((_time_stamp_current - _sub_attitude->get().timestamp) < _timeout) {
		// yaw
		_yaw = matrix::Eulerf(matrix::Quatf(_sub_attitude->get().q)).psi();
	}

	// Only use vehicle-local-position topic fields if the topic is received within a certain timestamp
	if ((_time_stamp_current - _sub_vehicle_local_position->get().timestamp) < _timeout) {

		// position
		if (_sub_vehicle_local_position->get().xy_valid) {
			_position(0) = _sub_vehicle_local_position->get().x;
			_position(1) = _sub_vehicle_local_position->get().y;
		}

		if (_sub_vehicle_local_position->get().z_valid) {
			_position(2) = _sub_vehicle_local_position->get().z;
		}

		// velocity
		if (_sub_vehicle_local_position->get().v_xy_valid) {
			_velocity(0) = _sub_vehicle_local_position->get().vx;
			_velocity(1) = _sub_vehicle_local_position->get().vy;
		}

		if (_sub_vehicle_local_position->get().v_z_valid) {
			_velocity(2) = _sub_vehicle_local_position->get().vz;
		}

		// distance to bottom
		if (_sub_vehicle_local_position->get().dist_bottom_valid
		    && PX4_ISFINITE(_sub_vehicle_local_position->get().dist_bottom)) {
			_dist_to_bottom =  _sub_vehicle_local_position->get().dist_bottom;
		}

		// global frame reference coordinates to enable conversions
		if (_sub_vehicle_local_position->get().xy_global && _sub_vehicle_local_position->get().z_global) {
			globallocalconverter_init(_sub_vehicle_local_position->get().ref_lat, _sub_vehicle_local_position->get().ref_lon,
						  _sub_vehicle_local_position->get().ref_alt, _sub_vehicle_local_position->get().ref_timestamp);
		}
	}
}

void FlightTask::_setDefaultConstraints()
{
	_constraints.speed_xy = MPC_XY_VEL_MAX.get();
	_constraints.speed_up = MPC_Z_VEL_MAX_UP.get();
	_constraints.speed_down = MPC_Z_VEL_MAX_DN.get();
	_constraints.tilt = math::radians(MPC_TILTMAX_AIR.get());
	_constraints.min_distance_to_ground = NAN;
	_constraints.max_distance_to_ground = NAN;
}
<commit_msg>FlightTask: Add initialisation of the landing gear<commit_after>#include "FlightTask.hpp"
#include <mathlib/mathlib.h>
#include <lib/ecl/geo/geo.h>

constexpr uint64_t FlightTask::_timeout;
// First index of empty_setpoint corresponds to time-stamp and requires a finite number.
const vehicle_local_position_setpoint_s FlightTask::empty_setpoint = {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, {NAN, NAN, NAN}};

const vehicle_constraints_s FlightTask::empty_constraints = {0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, {}};
const landing_gear_s FlightTask::landing_gear_default_keep = {0, landing_gear_s::GEAR_KEEP, {}};
const vehicle_trajectory_waypoint_s FlightTask::empty_trajectory_waypoint = {0, 0, {0, 0, 0, 0, 0, 0, 0},
	{	{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}},
		{0, {NAN, NAN, NAN}, {NAN, NAN, NAN}, {NAN, NAN, NAN}, NAN, NAN, false, {0, 0, 0}}
	}
};

bool FlightTask::initializeSubscriptions(SubscriptionArray &subscription_array)
{
	if (!subscription_array.get(ORB_ID(vehicle_local_position), _sub_vehicle_local_position)) {
		return false;
	}

	if (!subscription_array.get(ORB_ID(vehicle_attitude), _sub_attitude)) {
		return false;
	}

	return true;
}

bool FlightTask::activate()
{
	_resetSetpoints();
	_setDefaultConstraints();
	_time_stamp_activate = hrt_absolute_time();
	_heading_reset_counter = _sub_attitude->get().quat_reset_counter;
	_gear = landing_gear_default_keep;
	return true;
}

void FlightTask::reActivate()
{
	activate();
}

bool FlightTask::updateInitialize()
{
	_time_stamp_current = hrt_absolute_time();
	_time = (_time_stamp_current - _time_stamp_activate) / 1e6f;
	_deltatime  = math::min((_time_stamp_current - _time_stamp_last), _timeout) / 1e6f;
	_time_stamp_last = _time_stamp_current;
	_evaluateVehicleLocalPosition();
	return true;
}

const vehicle_local_position_setpoint_s FlightTask::getPositionSetpoint()
{
	/* fill position setpoint message */
	vehicle_local_position_setpoint_s vehicle_local_position_setpoint;
	vehicle_local_position_setpoint.timestamp = hrt_absolute_time();

	vehicle_local_position_setpoint.x = _position_setpoint(0);
	vehicle_local_position_setpoint.y = _position_setpoint(1);
	vehicle_local_position_setpoint.z = _position_setpoint(2);

	vehicle_local_position_setpoint.vx = _velocity_setpoint(0);
	vehicle_local_position_setpoint.vy = _velocity_setpoint(1);
	vehicle_local_position_setpoint.vz = _velocity_setpoint(2);

	vehicle_local_position_setpoint.acc_x = _acceleration_setpoint(0);
	vehicle_local_position_setpoint.acc_y = _acceleration_setpoint(1);
	vehicle_local_position_setpoint.acc_z = _acceleration_setpoint(2);

	vehicle_local_position_setpoint.jerk_x = _jerk_setpoint(0);
	vehicle_local_position_setpoint.jerk_y = _jerk_setpoint(1);
	vehicle_local_position_setpoint.jerk_z = _jerk_setpoint(2);

	_thrust_setpoint.copyTo(vehicle_local_position_setpoint.thrust);
	vehicle_local_position_setpoint.yaw = _yaw_setpoint;
	vehicle_local_position_setpoint.yawspeed = _yawspeed_setpoint;

	return vehicle_local_position_setpoint;
}

void FlightTask::_resetSetpoints()
{
	_position_setpoint.setAll(NAN);
	_velocity_setpoint.setAll(NAN);
	_acceleration_setpoint.setAll(NAN);
	_jerk_setpoint.setAll(NAN);
	_thrust_setpoint.setAll(NAN);
	_yaw_setpoint = _yawspeed_setpoint = NAN;
	_desired_waypoint = FlightTask::empty_trajectory_waypoint;
}

void FlightTask::_evaluateVehicleLocalPosition()
{
	_position.setAll(NAN);
	_velocity.setAll(NAN);
	_yaw = NAN;
	_dist_to_bottom = NAN;

	if ((_time_stamp_current - _sub_attitude->get().timestamp) < _timeout) {
		// yaw
		_yaw = matrix::Eulerf(matrix::Quatf(_sub_attitude->get().q)).psi();
	}

	// Only use vehicle-local-position topic fields if the topic is received within a certain timestamp
	if ((_time_stamp_current - _sub_vehicle_local_position->get().timestamp) < _timeout) {

		// position
		if (_sub_vehicle_local_position->get().xy_valid) {
			_position(0) = _sub_vehicle_local_position->get().x;
			_position(1) = _sub_vehicle_local_position->get().y;
		}

		if (_sub_vehicle_local_position->get().z_valid) {
			_position(2) = _sub_vehicle_local_position->get().z;
		}

		// velocity
		if (_sub_vehicle_local_position->get().v_xy_valid) {
			_velocity(0) = _sub_vehicle_local_position->get().vx;
			_velocity(1) = _sub_vehicle_local_position->get().vy;
		}

		if (_sub_vehicle_local_position->get().v_z_valid) {
			_velocity(2) = _sub_vehicle_local_position->get().vz;
		}

		// distance to bottom
		if (_sub_vehicle_local_position->get().dist_bottom_valid
		    && PX4_ISFINITE(_sub_vehicle_local_position->get().dist_bottom)) {
			_dist_to_bottom =  _sub_vehicle_local_position->get().dist_bottom;
		}

		// global frame reference coordinates to enable conversions
		if (_sub_vehicle_local_position->get().xy_global && _sub_vehicle_local_position->get().z_global) {
			globallocalconverter_init(_sub_vehicle_local_position->get().ref_lat, _sub_vehicle_local_position->get().ref_lon,
						  _sub_vehicle_local_position->get().ref_alt, _sub_vehicle_local_position->get().ref_timestamp);
		}
	}
}

void FlightTask::_setDefaultConstraints()
{
	_constraints.speed_xy = MPC_XY_VEL_MAX.get();
	_constraints.speed_up = MPC_Z_VEL_MAX_UP.get();
	_constraints.speed_down = MPC_Z_VEL_MAX_DN.get();
	_constraints.tilt = math::radians(MPC_TILTMAX_AIR.get());
	_constraints.min_distance_to_ground = NAN;
	_constraints.max_distance_to_ground = NAN;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stylepool.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2007-04-11 18:58:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef INCLUDED_SVTOOLS_STYLEPOOL_HXX
#define INCLUDED_SVTOOLS_STYLEPOOL_HXX

#include <boost/shared_ptr.hpp>
#include <rtl/ustring.hxx>

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

class StylePoolImpl;
class StylePoolIterImpl;
class IStylePoolIteratorAccess;

class SVL_DLLPUBLIC StylePool
{
private:
    StylePoolImpl *pImpl;
public:
    typedef boost::shared_ptr<SfxItemSet> SfxItemSet_Pointer_t;

    StylePool();

    /** Insert a SfxItemSet into the style pool.

        The pool makes a copy of the provided SfxItemSet.

        @param SfxItemSet
        the SfxItemSet to insert

        @return a shared pointer to the SfxItemSet
    */
    virtual SfxItemSet_Pointer_t insertItemSet( const SfxItemSet& rSet );

    /** Create an iterator

        The iterator walks through the StylePool

        @attention every change, e.g. destruction, of the StylePool could cause undefined effects.

        @postcond the iterator "points before the first" SfxItemSet of the pool.
        The first StylePoolIterator::getNext() call will deliver the first SfxItemSet.
    */
    virtual IStylePoolIteratorAccess* createIterator();

    /** Returns the number of styles
    */
    virtual sal_Int32 getCount() const;

    virtual ~StylePool();

    static ::rtl::OUString nameOf( SfxItemSet_Pointer_t pSet );
};

class SVL_DLLPUBLIC IStylePoolIteratorAccess
{
public:
    /** Delivers a shared pointer to the next SfxItemSet of the pool
        If there is no more SfxItemSet, the delivered share_pointer is empty.
    */
    virtual StylePool::SfxItemSet_Pointer_t getNext() = 0;
    virtual ::rtl::OUString getName() = 0;
    virtual ~IStylePoolIteratorAccess() {};
};

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.3.320); FILE MERGED 2008/04/01 12:43:09 thb 1.3.320.2: #i85898# Stripping all external header guards 2008/03/31 13:00:56 rt 1.3.320.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: stylepool.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef INCLUDED_SVTOOLS_STYLEPOOL_HXX
#define INCLUDED_SVTOOLS_STYLEPOOL_HXX

#include <boost/shared_ptr.hpp>
#include <rtl/ustring.hxx>
#include <svtools/itemset.hxx>

class StylePoolImpl;
class StylePoolIterImpl;
class IStylePoolIteratorAccess;

class SVL_DLLPUBLIC StylePool
{
private:
    StylePoolImpl *pImpl;
public:
    typedef boost::shared_ptr<SfxItemSet> SfxItemSet_Pointer_t;

    StylePool();

    /** Insert a SfxItemSet into the style pool.

        The pool makes a copy of the provided SfxItemSet.

        @param SfxItemSet
        the SfxItemSet to insert

        @return a shared pointer to the SfxItemSet
    */
    virtual SfxItemSet_Pointer_t insertItemSet( const SfxItemSet& rSet );

    /** Create an iterator

        The iterator walks through the StylePool

        @attention every change, e.g. destruction, of the StylePool could cause undefined effects.

        @postcond the iterator "points before the first" SfxItemSet of the pool.
        The first StylePoolIterator::getNext() call will deliver the first SfxItemSet.
    */
    virtual IStylePoolIteratorAccess* createIterator();

    /** Returns the number of styles
    */
    virtual sal_Int32 getCount() const;

    virtual ~StylePool();

    static ::rtl::OUString nameOf( SfxItemSet_Pointer_t pSet );
};

class SVL_DLLPUBLIC IStylePoolIteratorAccess
{
public:
    /** Delivers a shared pointer to the next SfxItemSet of the pool
        If there is no more SfxItemSet, the delivered share_pointer is empty.
    */
    virtual StylePool::SfxItemSet_Pointer_t getNext() = 0;
    virtual ::rtl::OUString getName() = 0;
    virtual ~IStylePoolIteratorAccess() {};
};

#endif
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "shortcutsettings.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/id.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/command_p.h>
#include <coreplugin/actionmanager/commandsfile.h>

#include <QKeyEvent>
#include <QFileDialog>
#include <QLineEdit>
#include <QTreeWidgetItem>
#include <QCoreApplication>
#include <QDebug>

Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*)

using namespace Core;
using namespace Core::Internal;

ShortcutSettings::ShortcutSettings(QObject *parent)
    : CommandMappings(parent), m_initialized(false)
{
    connect(ActionManager::instance(), SIGNAL(commandListChanged()), this, SLOT(initialize()));

    setId(Core::Constants::SETTINGS_ID_SHORTCUTS);
    setDisplayName(tr("Keyboard"));
    setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
    setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE));
    setCategoryIcon(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE_ICON));
}

QWidget *ShortcutSettings::createPage(QWidget *parent)
{
    m_initialized = true;
    m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;

    QWidget *w = CommandMappings::createPage(parent);

    const QString pageTitle = tr("Keyboard Shortcuts");
    const QString targetLabelText = tr("Key sequence:");
    const QString editTitle = tr("Shortcut");

    setPageTitle(pageTitle);
    setTargetLabelText(targetLabelText);
    setTargetEditTitle(editTitle);
    setTargetHeader(editTitle);
    targetEdit()->setPlaceholderText(tr("Type to set shortcut"));

    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords) << ' ' << pageTitle
                << ' ' << targetLabelText
                << ' ' << editTitle;
    }

    return w;
}

void ShortcutSettings::apply()
{
    foreach (ShortcutItem *item, m_scitems)
        item->m_cmd->setKeySequence(item->m_key);
}

void ShortcutSettings::finish()
{
    qDeleteAll(m_scitems);
    m_scitems.clear();

    CommandMappings::finish();
    m_initialized = false;
}

bool ShortcutSettings::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

bool ShortcutSettings::eventFilter(QObject *o, QEvent *e)
{
    Q_UNUSED(o)

    if ( e->type() == QEvent::KeyPress ) {
        QKeyEvent *k = static_cast<QKeyEvent*>(e);
        handleKeyEvent(k);
        return true;
    }

    if ( e->type() == QEvent::Shortcut ||
         e->type() == QEvent::KeyRelease ) {
        return true;
    }

    if (e->type() == QEvent::ShortcutOverride) {
        // for shortcut overrides, we need to accept as well
        e->accept();
        return true;
    }

    return false;
}

void ShortcutSettings::commandChanged(QTreeWidgetItem *current)
{
    CommandMappings::commandChanged(current);
    if (!current || !current->data(0, Qt::UserRole).isValid())
        return;
    ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(current->data(0, Qt::UserRole));
    setKeySequence(scitem->m_key);
}

void ShortcutSettings::targetIdentifierChanged()
{
    QTreeWidgetItem *current = commandList()->currentItem();
    if (current && current->data(0, Qt::UserRole).isValid()) {
        ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(current->data(0, Qt::UserRole));
        scitem->m_key = QKeySequence(m_key[0], m_key[1], m_key[2], m_key[3]);
        if (scitem->m_cmd->defaultKeySequence() != scitem->m_key)
            setModified(current, true);
        else
            setModified(current, false);
        current->setText(2, scitem->m_key.toString(QKeySequence::NativeText));
        resetCollisionMarker(scitem);
        markPossibleCollisions(scitem);
    }
}

void ShortcutSettings::setKeySequence(const QKeySequence &key)
{
    m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
    m_keyNum = key.count();
    for (int i = 0; i < m_keyNum; ++i) {
        m_key[i] = key[i];
    }
    targetEdit()->setText(key.toString(QKeySequence::NativeText));
}

void ShortcutSettings::resetTargetIdentifier()
{
    QTreeWidgetItem *current = commandList()->currentItem();
    if (current && current->data(0, Qt::UserRole).isValid()) {
        ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(current->data(0, Qt::UserRole));
        setKeySequence(scitem->m_cmd->defaultKeySequence());
    }
}

void ShortcutSettings::removeTargetIdentifier()
{
    m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
    targetEdit()->clear();
}

void ShortcutSettings::importAction()
{
    QString fileName = QFileDialog::getOpenFileName(0, tr("Import Keyboard Mapping Scheme"),
        ICore::resourcePath() + QLatin1String("/schemes/"),
        tr("Keyboard Mapping Scheme (*.kms)"));
    if (!fileName.isEmpty()) {

        CommandsFile cf(fileName);
        QMap<QString, QKeySequence> mapping = cf.importCommands();

        foreach (ShortcutItem *item, m_scitems) {
            QString sid = item->m_cmd->id().toString();
            if (mapping.contains(sid)) {
                item->m_key = mapping.value(sid);
                item->m_item->setText(2, item->m_key.toString(QKeySequence::NativeText));
                if (item->m_item == commandList()->currentItem())
                    commandChanged(item->m_item);

                if (item->m_cmd->defaultKeySequence() != item->m_key)
                    setModified(item->m_item, true);
                else
                    setModified(item->m_item, false);
            }
        }

        foreach (ShortcutItem *item, m_scitems) {
            resetCollisionMarker(item);
            markPossibleCollisions(item);
        }
    }
}

void ShortcutSettings::defaultAction()
{
    foreach (ShortcutItem *item, m_scitems) {
        item->m_key = item->m_cmd->defaultKeySequence();
        item->m_item->setText(2, item->m_key.toString(QKeySequence::NativeText));
        setModified(item->m_item, false);
        if (item->m_item == commandList()->currentItem())
            commandChanged(item->m_item);
    }

    foreach (ShortcutItem *item, m_scitems) {
        resetCollisionMarker(item);
        markPossibleCollisions(item);
    }
}

void ShortcutSettings::exportAction()
{
    QString fileName = DocumentManager::getSaveFileNameWithExtension(
        tr("Export Keyboard Mapping Scheme"),
        ICore::resourcePath() + QLatin1String("/schemes/"),
        tr("Keyboard Mapping Scheme (*.kms)"));
    if (!fileName.isEmpty()) {
        CommandsFile cf(fileName);
        cf.exportCommands(m_scitems);
    }
}

void ShortcutSettings::clear()
{
    QTreeWidget *tree = commandList();
    for (int i = tree->topLevelItemCount()-1; i >= 0 ; --i) {
        delete tree->takeTopLevelItem(i);
    }
    qDeleteAll(m_scitems);
    m_scitems.clear();
}

void ShortcutSettings::initialize()
{
    if (!m_initialized)
        return;
    clear();
    QMap<QString, QTreeWidgetItem *> sections;

    foreach (Command *c, ActionManager::instance()->commands()) {
        if (c->hasAttribute(Command::CA_NonConfigurable))
            continue;
        if (c->action() && c->action()->isSeparator())
            continue;

        QTreeWidgetItem *item = 0;
        ShortcutItem *s = new ShortcutItem;
        m_scitems << s;
        item = new QTreeWidgetItem;
        s->m_cmd = c;
        s->m_item = item;

        const QString identifier = c->id().toString();
        int pos = identifier.indexOf(QLatin1Char('.'));
        const QString section = identifier.left(pos);
        const QString subId = identifier.mid(pos + 1);
        if (!sections.contains(section)) {
            QTreeWidgetItem *categoryItem = new QTreeWidgetItem(commandList(), QStringList() << section);
            QFont f = categoryItem->font(0);
            f.setBold(true);
            categoryItem->setFont(0, f);
            sections.insert(section, categoryItem);
            commandList()->expandItem(categoryItem);
        }
        sections[section]->addChild(item);

        s->m_key = c->keySequence();
        item->setText(0, subId);
        item->setText(1, c->description());
        item->setText(2, s->m_key.toString(QKeySequence::NativeText));
        if (s->m_cmd->defaultKeySequence() != s->m_key)
            setModified(item, true);

        item->setData(0, Qt::UserRole, qVariantFromValue(s));

        markPossibleCollisions(s);
    }
    filterChanged(filterText());
}

void ShortcutSettings::handleKeyEvent(QKeyEvent *e)
{
    int nextKey = e->key();
    if ( m_keyNum > 3 ||
         nextKey == Qt::Key_Control ||
         nextKey == Qt::Key_Shift ||
         nextKey == Qt::Key_Meta ||
         nextKey == Qt::Key_Alt )
         return;

    nextKey |= translateModifiers(e->modifiers(), e->text());
    switch (m_keyNum) {
        case 0:
            m_key[0] = nextKey;
            break;
        case 1:
            m_key[1] = nextKey;
            break;
        case 2:
            m_key[2] = nextKey;
            break;
        case 3:
            m_key[3] = nextKey;
            break;
        default:
            break;
    }
    m_keyNum++;
    QKeySequence ks(m_key[0], m_key[1], m_key[2], m_key[3]);
    targetEdit()->setText(ks.toString(QKeySequence::NativeText));
    e->accept();
}

int ShortcutSettings::translateModifiers(Qt::KeyboardModifiers state,
                                         const QString &text)
{
    int result = 0;
    // The shift modifier only counts when it is not used to type a symbol
    // that is only reachable using the shift key anyway
    if ((state & Qt::ShiftModifier) && (text.size() == 0
                                        || !text.at(0).isPrint()
                                        || text.at(0).isLetterOrNumber()
                                        || text.at(0).isSpace()))
        result |= Qt::SHIFT;
    if (state & Qt::ControlModifier)
        result |= Qt::CTRL;
    if (state & Qt::MetaModifier)
        result |= Qt::META;
    if (state & Qt::AltModifier)
        result |= Qt::ALT;
    return result;
}

void ShortcutSettings::markPossibleCollisions(ShortcutItem *item)
{
    if (item->m_key.isEmpty())
        return;

    Id globalId = Context(Constants::C_GLOBAL).at(0);

    foreach (ShortcutItem *currentItem, m_scitems) {

        if (currentItem->m_key.isEmpty() || item == currentItem ||
            item->m_key != currentItem->m_key) {
            continue;
        }

        foreach (Id id, currentItem->m_cmd->context()) {
            // conflict if context is identical, OR if one
            // of the contexts is the global context
            if (item->m_cmd->context().contains(id) ||
               (item->m_cmd->context().contains(globalId) &&
                !currentItem->m_cmd->context().isEmpty()) ||
                (currentItem->m_cmd->context().contains(globalId) &&
                !item->m_cmd->context().isEmpty())) {
                currentItem->m_item->setForeground(2, Qt::red);
                item->m_item->setForeground(2, Qt::red);

            }
        }
    }
}

void ShortcutSettings::resetCollisionMarker(ShortcutItem *item)
{
    item->m_item->setForeground(2, commandList()->palette().foreground());
}

void ShortcutSettings::resetCollisionMarkers()
{
    foreach (ShortcutItem *item, m_scitems)
        resetCollisionMarker(item);
}
<commit_msg>ShortCutSettings: Remove a couple of letters of useless code<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "shortcutsettings.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/id.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/command_p.h>
#include <coreplugin/actionmanager/commandsfile.h>

#include <QKeyEvent>
#include <QFileDialog>
#include <QLineEdit>
#include <QTreeWidgetItem>
#include <QCoreApplication>
#include <QDebug>

Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*)

using namespace Core;
using namespace Core::Internal;

ShortcutSettings::ShortcutSettings(QObject *parent)
    : CommandMappings(parent), m_initialized(false)
{
    connect(ActionManager::instance(), SIGNAL(commandListChanged()), this, SLOT(initialize()));

    setId(Core::Constants::SETTINGS_ID_SHORTCUTS);
    setDisplayName(tr("Keyboard"));
    setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
    setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE));
    setCategoryIcon(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE_ICON));
}

QWidget *ShortcutSettings::createPage(QWidget *parent)
{
    m_initialized = true;
    m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;

    QWidget *w = CommandMappings::createPage(parent);

    const QString pageTitle = tr("Keyboard Shortcuts");
    const QString targetLabelText = tr("Key sequence:");
    const QString editTitle = tr("Shortcut");

    setPageTitle(pageTitle);
    setTargetLabelText(targetLabelText);
    setTargetEditTitle(editTitle);
    setTargetHeader(editTitle);
    targetEdit()->setPlaceholderText(tr("Type to set shortcut"));

    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords) << ' ' << pageTitle
                << ' ' << targetLabelText
                << ' ' << editTitle;
    }

    return w;
}

void ShortcutSettings::apply()
{
    foreach (ShortcutItem *item, m_scitems)
        item->m_cmd->setKeySequence(item->m_key);
}

void ShortcutSettings::finish()
{
    qDeleteAll(m_scitems);
    m_scitems.clear();

    CommandMappings::finish();
    m_initialized = false;
}

bool ShortcutSettings::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

bool ShortcutSettings::eventFilter(QObject *o, QEvent *e)
{
    Q_UNUSED(o)

    if ( e->type() == QEvent::KeyPress ) {
        QKeyEvent *k = static_cast<QKeyEvent*>(e);
        handleKeyEvent(k);
        return true;
    }

    if ( e->type() == QEvent::Shortcut ||
         e->type() == QEvent::KeyRelease ) {
        return true;
    }

    if (e->type() == QEvent::ShortcutOverride) {
        // for shortcut overrides, we need to accept as well
        e->accept();
        return true;
    }

    return false;
}

void ShortcutSettings::commandChanged(QTreeWidgetItem *current)
{
    CommandMappings::commandChanged(current);
    if (!current || !current->data(0, Qt::UserRole).isValid())
        return;
    ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(current->data(0, Qt::UserRole));
    setKeySequence(scitem->m_key);
}

void ShortcutSettings::targetIdentifierChanged()
{
    QTreeWidgetItem *current = commandList()->currentItem();
    if (current && current->data(0, Qt::UserRole).isValid()) {
        ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(current->data(0, Qt::UserRole));
        scitem->m_key = QKeySequence(m_key[0], m_key[1], m_key[2], m_key[3]);
        if (scitem->m_cmd->defaultKeySequence() != scitem->m_key)
            setModified(current, true);
        else
            setModified(current, false);
        current->setText(2, scitem->m_key.toString(QKeySequence::NativeText));
        resetCollisionMarker(scitem);
        markPossibleCollisions(scitem);
    }
}

void ShortcutSettings::setKeySequence(const QKeySequence &key)
{
    m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
    m_keyNum = key.count();
    for (int i = 0; i < m_keyNum; ++i) {
        m_key[i] = key[i];
    }
    targetEdit()->setText(key.toString(QKeySequence::NativeText));
}

void ShortcutSettings::resetTargetIdentifier()
{
    QTreeWidgetItem *current = commandList()->currentItem();
    if (current && current->data(0, Qt::UserRole).isValid()) {
        ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(current->data(0, Qt::UserRole));
        setKeySequence(scitem->m_cmd->defaultKeySequence());
    }
}

void ShortcutSettings::removeTargetIdentifier()
{
    m_keyNum = m_key[0] = m_key[1] = m_key[2] = m_key[3] = 0;
    targetEdit()->clear();
}

void ShortcutSettings::importAction()
{
    QString fileName = QFileDialog::getOpenFileName(0, tr("Import Keyboard Mapping Scheme"),
        ICore::resourcePath() + QLatin1String("/schemes/"),
        tr("Keyboard Mapping Scheme (*.kms)"));
    if (!fileName.isEmpty()) {

        CommandsFile cf(fileName);
        QMap<QString, QKeySequence> mapping = cf.importCommands();

        foreach (ShortcutItem *item, m_scitems) {
            QString sid = item->m_cmd->id().toString();
            if (mapping.contains(sid)) {
                item->m_key = mapping.value(sid);
                item->m_item->setText(2, item->m_key.toString(QKeySequence::NativeText));
                if (item->m_item == commandList()->currentItem())
                    commandChanged(item->m_item);

                if (item->m_cmd->defaultKeySequence() != item->m_key)
                    setModified(item->m_item, true);
                else
                    setModified(item->m_item, false);
            }
        }

        foreach (ShortcutItem *item, m_scitems) {
            resetCollisionMarker(item);
            markPossibleCollisions(item);
        }
    }
}

void ShortcutSettings::defaultAction()
{
    foreach (ShortcutItem *item, m_scitems) {
        item->m_key = item->m_cmd->defaultKeySequence();
        item->m_item->setText(2, item->m_key.toString(QKeySequence::NativeText));
        setModified(item->m_item, false);
        if (item->m_item == commandList()->currentItem())
            commandChanged(item->m_item);
    }

    foreach (ShortcutItem *item, m_scitems) {
        resetCollisionMarker(item);
        markPossibleCollisions(item);
    }
}

void ShortcutSettings::exportAction()
{
    QString fileName = DocumentManager::getSaveFileNameWithExtension(
        tr("Export Keyboard Mapping Scheme"),
        ICore::resourcePath() + QLatin1String("/schemes/"),
        tr("Keyboard Mapping Scheme (*.kms)"));
    if (!fileName.isEmpty()) {
        CommandsFile cf(fileName);
        cf.exportCommands(m_scitems);
    }
}

void ShortcutSettings::clear()
{
    QTreeWidget *tree = commandList();
    for (int i = tree->topLevelItemCount()-1; i >= 0 ; --i) {
        delete tree->takeTopLevelItem(i);
    }
    qDeleteAll(m_scitems);
    m_scitems.clear();
}

void ShortcutSettings::initialize()
{
    if (!m_initialized)
        return;
    clear();
    QMap<QString, QTreeWidgetItem *> sections;

    foreach (Command *c, ActionManager::instance()->commands()) {
        if (c->hasAttribute(Command::CA_NonConfigurable))
            continue;
        if (c->action() && c->action()->isSeparator())
            continue;

        QTreeWidgetItem *item = 0;
        ShortcutItem *s = new ShortcutItem;
        m_scitems << s;
        item = new QTreeWidgetItem;
        s->m_cmd = c;
        s->m_item = item;

        const QString identifier = c->id().toString();
        int pos = identifier.indexOf(QLatin1Char('.'));
        const QString section = identifier.left(pos);
        const QString subId = identifier.mid(pos + 1);
        if (!sections.contains(section)) {
            QTreeWidgetItem *categoryItem = new QTreeWidgetItem(commandList(), QStringList() << section);
            QFont f = categoryItem->font(0);
            f.setBold(true);
            categoryItem->setFont(0, f);
            sections.insert(section, categoryItem);
            commandList()->expandItem(categoryItem);
        }
        sections[section]->addChild(item);

        s->m_key = c->keySequence();
        item->setText(0, subId);
        item->setText(1, c->description());
        item->setText(2, s->m_key.toString(QKeySequence::NativeText));
        if (s->m_cmd->defaultKeySequence() != s->m_key)
            setModified(item, true);

        item->setData(0, Qt::UserRole, qVariantFromValue(s));

        markPossibleCollisions(s);
    }
    filterChanged(filterText());
}

void ShortcutSettings::handleKeyEvent(QKeyEvent *e)
{
    int nextKey = e->key();
    if ( m_keyNum > 3 ||
         nextKey == Qt::Key_Control ||
         nextKey == Qt::Key_Shift ||
         nextKey == Qt::Key_Meta ||
         nextKey == Qt::Key_Alt )
         return;

    nextKey |= translateModifiers(e->modifiers(), e->text());
    switch (m_keyNum) {
        case 0:
            m_key[0] = nextKey;
            break;
        case 1:
            m_key[1] = nextKey;
            break;
        case 2:
            m_key[2] = nextKey;
            break;
        case 3:
            m_key[3] = nextKey;
            break;
        default:
            break;
    }
    m_keyNum++;
    QKeySequence ks(m_key[0], m_key[1], m_key[2], m_key[3]);
    targetEdit()->setText(ks.toString(QKeySequence::NativeText));
    e->accept();
}

int ShortcutSettings::translateModifiers(Qt::KeyboardModifiers state,
                                         const QString &text)
{
    int result = 0;
    // The shift modifier only counts when it is not used to type a symbol
    // that is only reachable using the shift key anyway
    if ((state & Qt::ShiftModifier) && (text.size() == 0
                                        || !text.at(0).isPrint()
                                        || text.at(0).isLetterOrNumber()
                                        || text.at(0).isSpace()))
        result |= Qt::SHIFT;
    if (state & Qt::ControlModifier)
        result |= Qt::CTRL;
    if (state & Qt::MetaModifier)
        result |= Qt::META;
    if (state & Qt::AltModifier)
        result |= Qt::ALT;
    return result;
}

void ShortcutSettings::markPossibleCollisions(ShortcutItem *item)
{
    if (item->m_key.isEmpty())
        return;

    Id globalId = Context(Constants::C_GLOBAL).at(0);

    foreach (ShortcutItem *currentItem, m_scitems) {

        if (currentItem->m_key.isEmpty() || item == currentItem ||
            item->m_key != currentItem->m_key) {
            continue;
        }

        foreach (Id id, currentItem->m_cmd->context()) {
            // conflict if context is identical, OR if one
            // of the contexts is the global context
            if (item->m_cmd->context().contains(id) ||
               (item->m_cmd->context().contains(globalId) &&
                !currentItem->m_cmd->context().isEmpty()) ||
                (currentItem->m_cmd->context().contains(globalId) &&
                !item->m_cmd->context().isEmpty())) {
                currentItem->m_item->setForeground(2, Qt::red);
                item->m_item->setForeground(2, Qt::red);

            }
        }
    }
}

void ShortcutSettings::resetCollisionMarker(ShortcutItem *item)
{
    item->m_item->setForeground(2, commandList()->palette().foreground());
}

void ShortcutSettings::resetCollisionMarkers()
{
    foreach (ShortcutItem *item, m_scitems)
        resetCollisionMarker(item);
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "debuggerprofileinformation.h"

#include "debuggerprofileconfigwidget.h"

#include <projectexplorer/abi.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>

#include <utils/environment.h>

#include <QDir>
#include <QPair>

using namespace ProjectExplorer;
using namespace Utils;

// --------------------------------------------------------------------------
// Helpers:
// --------------------------------------------------------------------------

static QPair<QString, QString> autoDetectCdbDebugger()
{
    QPair<QString, QString> result;
    QList<FileName> cdbs;

    QStringList programDirs;
    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles")));
    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)")));
    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432")));

    foreach (const QString &dirName, programDirs) {
        if (dirName.isEmpty())
            continue;
        QDir dir(dirName);
        // Windows SDK's starting from version 8 live in
        // "ProgramDir\Windows Kits\<version>"
        const QString windowsKitsFolderName = QLatin1String("Windows Kits");
        if (dir.exists(windowsKitsFolderName)) {
            QDir windowKitsFolder = dir;
            if (windowKitsFolder.cd(windowsKitsFolderName)) {
                // Check in reverse order (latest first)
                const QFileInfoList kitFolders =
                    windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
                                                   QDir::Time | QDir::Reversed);
                foreach (const QFileInfo &kitFolderFi, kitFolders) {
                    const QString path = kitFolderFi.absoluteFilePath();
                    const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe"));
                    if (cdb32.isExecutable())
                        cdbs.push_back(FileName::fromString(cdb32.absoluteFilePath()));
                    const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe"));
                    if (cdb64.isExecutable())
                        cdbs.push_back(FileName::fromString(cdb64.absoluteFilePath()));
                } // for Kits
            } // can cd to "Windows Kits"
        } // "Windows Kits" exists

        // Pre Windows SDK 8: Check 'Debugging Tools for Windows'
        foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")),
                                                        QDir::Dirs | QDir::NoDotAndDotDot)) {
            FileName filePath(fi);
            filePath.appendPath(QLatin1String("cdb.exe"));
            if (!cdbs.contains(filePath))
                cdbs.append(filePath);
        }
    }

    foreach (const FileName &cdb, cdbs) {
        QList<Abi> abis = Abi::abisOfBinary(cdb);
        if (abis.isEmpty())
            continue;
        if (abis.first().wordWidth() == 32)
            result.first = cdb.toString();
        else if (abis.first().wordWidth() == 64)
            result.second = cdb.toString();
    }

    // prefer 64bit debugger, even for 32bit binaries:
    if (!result.second.isEmpty())
        result.first = result.second;

    return result;
}

namespace Debugger {

// --------------------------------------------------------------------------
// DebuggerProfileInformation:
// --------------------------------------------------------------------------

static const char DEBUGGER_INFORMATION[] = "Debugger.Information";

DebuggerProfileInformation::DebuggerProfileInformation()
{
    setObjectName(QLatin1String("DebuggerProfileInformation"));
}

Core::Id DebuggerProfileInformation::dataId() const
{
    static Core::Id id = Core::Id(DEBUGGER_INFORMATION);
    return id;
}

unsigned int DebuggerProfileInformation::priority() const
{
    return 28000;
}

QVariant DebuggerProfileInformation::defaultValue(Profile *p) const
{
    ToolChain *tc = ToolChainProfileInformation::toolChain(p);
    Abi abi = Abi::hostAbi();
    if (tc)
        abi = tc->targetAbi();

    // CDB for windows:
    if (abi.os() == Abi::WindowsOS && abi.osFlavor() != Abi::WindowsMSysFlavor) {
        QPair<QString, QString> cdbs = autoDetectCdbDebugger();
        return (abi.wordWidth() == 32) ? cdbs.first : cdbs.second;
    }

    // fall back to system GDB:
    QString debugger = QLatin1String("gdb");
    if (tc) {
        // Check suggestions from the SDK:
        const QString path = tc->suggestedDebugger().toString();
        if (!path.isEmpty()) {
            QFileInfo fi(path);
            if (fi.isAbsolute())
                return path;
            debugger = path;
        }
    }

    Environment env = Environment::systemEnvironment();
    return env.searchInPath(debugger);
}

QList<Task> DebuggerProfileInformation::validate(Profile *p) const
{
    QList<Task> result;
    FileName dbg = debuggerCommand(p);
    if (dbg.isEmpty()) {
        result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1,
                                        Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
        return result;
    }

    QFileInfo fi = dbg.toFileInfo();
    if (!fi.exists() || fi.isDir())
        result << Task(Task::Error, tr("Debugger not found."), FileName(), -1,
                                        Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
    else if (!fi.isExecutable())
        result << Task(Task::Error, tr("Debugger not exectutable."), FileName(), -1,
                                        Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));

    return result;
}

ProfileConfigWidget *DebuggerProfileInformation::createConfigWidget(Profile *p) const
{
    return new Internal::DebuggerProfileConfigWidget(p, this);
}

ProfileInformation::ItemList DebuggerProfileInformation::toUserOutput(Profile *p) const
{
    return ItemList() << qMakePair(tr("Debugger"), debuggerCommand(p).toUserOutput());
}

FileName DebuggerProfileInformation::debuggerCommand(const Profile *p)
{
    return FileName::fromString(p->value(Core::Id(DEBUGGER_INFORMATION)).toString());
}

void DebuggerProfileInformation::setDebuggerCommand(Profile *p, const FileName &command)
{
    p->setValue(Core::Id(DEBUGGER_INFORMATION), command.toString());
}

} // namespace Debugger
<commit_msg>debugger: require absolute paths to debugger binary on windows<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "debuggerprofileinformation.h"

#include "debuggerprofileconfigwidget.h"

#include <projectexplorer/abi.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>

#include <utils/environment.h>

#include <QDir>
#include <QPair>

using namespace ProjectExplorer;
using namespace Utils;

// --------------------------------------------------------------------------
// Helpers:
// --------------------------------------------------------------------------

static QPair<QString, QString> autoDetectCdbDebugger()
{
    QPair<QString, QString> result;
    QList<FileName> cdbs;

    QStringList programDirs;
    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles")));
    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)")));
    programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432")));

    foreach (const QString &dirName, programDirs) {
        if (dirName.isEmpty())
            continue;
        QDir dir(dirName);
        // Windows SDK's starting from version 8 live in
        // "ProgramDir\Windows Kits\<version>"
        const QString windowsKitsFolderName = QLatin1String("Windows Kits");
        if (dir.exists(windowsKitsFolderName)) {
            QDir windowKitsFolder = dir;
            if (windowKitsFolder.cd(windowsKitsFolderName)) {
                // Check in reverse order (latest first)
                const QFileInfoList kitFolders =
                    windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
                                                   QDir::Time | QDir::Reversed);
                foreach (const QFileInfo &kitFolderFi, kitFolders) {
                    const QString path = kitFolderFi.absoluteFilePath();
                    const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe"));
                    if (cdb32.isExecutable())
                        cdbs.push_back(FileName::fromString(cdb32.absoluteFilePath()));
                    const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe"));
                    if (cdb64.isExecutable())
                        cdbs.push_back(FileName::fromString(cdb64.absoluteFilePath()));
                } // for Kits
            } // can cd to "Windows Kits"
        } // "Windows Kits" exists

        // Pre Windows SDK 8: Check 'Debugging Tools for Windows'
        foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")),
                                                        QDir::Dirs | QDir::NoDotAndDotDot)) {
            FileName filePath(fi);
            filePath.appendPath(QLatin1String("cdb.exe"));
            if (!cdbs.contains(filePath))
                cdbs.append(filePath);
        }
    }

    foreach (const FileName &cdb, cdbs) {
        QList<Abi> abis = Abi::abisOfBinary(cdb);
        if (abis.isEmpty())
            continue;
        if (abis.first().wordWidth() == 32)
            result.first = cdb.toString();
        else if (abis.first().wordWidth() == 64)
            result.second = cdb.toString();
    }

    // prefer 64bit debugger, even for 32bit binaries:
    if (!result.second.isEmpty())
        result.first = result.second;

    return result;
}

namespace Debugger {

// --------------------------------------------------------------------------
// DebuggerProfileInformation:
// --------------------------------------------------------------------------

static const char DEBUGGER_INFORMATION[] = "Debugger.Information";

DebuggerProfileInformation::DebuggerProfileInformation()
{
    setObjectName(QLatin1String("DebuggerProfileInformation"));
}

Core::Id DebuggerProfileInformation::dataId() const
{
    static Core::Id id = Core::Id(DEBUGGER_INFORMATION);
    return id;
}

unsigned int DebuggerProfileInformation::priority() const
{
    return 28000;
}

QVariant DebuggerProfileInformation::defaultValue(Profile *p) const
{
    ToolChain *tc = ToolChainProfileInformation::toolChain(p);
    Abi abi = Abi::hostAbi();
    if (tc)
        abi = tc->targetAbi();

    // CDB for windows:
    if (abi.os() == Abi::WindowsOS && abi.osFlavor() != Abi::WindowsMSysFlavor) {
        QPair<QString, QString> cdbs = autoDetectCdbDebugger();
        return (abi.wordWidth() == 32) ? cdbs.first : cdbs.second;
    }

    // fall back to system GDB:
    QString debugger = QLatin1String("gdb");
    if (tc) {
        // Check suggestions from the SDK:
        const QString path = tc->suggestedDebugger().toString();
        if (!path.isEmpty()) {
            QFileInfo fi(path);
            if (fi.isAbsolute())
                return path;
            debugger = path;
        }
    }

    Environment env = Environment::systemEnvironment();
    return env.searchInPath(debugger);
}

QList<Task> DebuggerProfileInformation::validate(Profile *p) const
{
    const Core::Id id(Constants::TASK_CATEGORY_BUILDSYSTEM);
    QList<Task> result;
    FileName dbg = debuggerCommand(p);
    if (dbg.isEmpty()) {
        result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id);
        return result;
    }

    QFileInfo fi = dbg.toFileInfo();
    if (!fi.exists() || fi.isDir())
        result << Task(Task::Error, tr("Debugger not found."), FileName(), -1, id);
    else if (!fi.isExecutable())
        result << Task(Task::Error, tr("Debugger not exectutable."), FileName(), -1, id);

    if (ToolChain *tc = ToolChainProfileInformation::toolChain(p)) {
        // We need an absolute path to be able to locate Python on Windows.
        const Abi abi = tc->targetAbi();
        if (abi.os() == Abi::WindowsOS && !fi.isAbsolute()) {
            result << Task(Task::Error, tr("The debugger location must be given as an "
                   "absolute path (%1).").arg(dbg.toString()), FileName(), -1, id);
        }
        // FIXME: Make sure debugger matches toolchain.
        // if (isCdb()) {
        //    if (abi.binaryFormat() != Abi::PEFormat || abi.os() != Abi::WindowsOS) {
        //        result << Task(Tas->errorDetails.push_back(CdbEngine::tr("The CDB debug engine does not support the %1 ABI.").
        //                                      arg(abi.toString()));
        //        return false;
        //    }
        // }
    }

    return result;
}

ProfileConfigWidget *DebuggerProfileInformation::createConfigWidget(Profile *p) const
{
    return new Internal::DebuggerProfileConfigWidget(p, this);
}

ProfileInformation::ItemList DebuggerProfileInformation::toUserOutput(Profile *p) const
{
    return ItemList() << qMakePair(tr("Debugger"), debuggerCommand(p).toUserOutput());
}

FileName DebuggerProfileInformation::debuggerCommand(const Profile *p)
{
    return FileName::fromString(p->value(Core::Id(DEBUGGER_INFORMATION)).toString());
}

void DebuggerProfileInformation::setDebuggerCommand(Profile *p, const FileName &command)
{
    p->setValue(Core::Id(DEBUGGER_INFORMATION), command.toString());
}

} // namespace Debugger
<|endoftext|>


<commit_before>#include "acmacs-base/rjson-v3-helper.hh"
#include "acmacs-map-draw/mapi-settings.hh"
#include "acmacs-map-draw/draw.hh"
#include "acmacs-map-draw/map-elements-v1.hh"

// ----------------------------------------------------------------------

map_elements::v1::LegendPointLabel& acmacs::mapi::v1::Settings::legend()
{
    return chart_draw().map_elements().find_or_add<map_elements::v1::LegendPointLabel>("legend-point-label");

} // acmacs::mapi::v1::Settings::legend

// ----------------------------------------------------------------------

bool acmacs::mapi::v1::Settings::apply_legend()
{
    using namespace std::string_view_literals;

    if (rjson::v3::read_bool(getenv("show"sv), true)) { // show by default
        if (const auto legend_type = rjson::v3::read_string(getenv("type"sv), ""sv); legend_type == "continent-map"sv || legend_type == "continent_map"sv) {
            add_legend_continent_map();
        }
        else {
            auto& legend_element = legend();
            rjson::v3::call_if_not_null<acmacs::PointCoordinates>(getenv("offset"sv), [&legend_element](const acmacs::PointCoordinates& val) { legend_element.offset(val); });
            rjson::v3::call_if_not_null<Pixels>(getenv("label_size"sv), [&legend_element](Pixels val) { legend_element.label_size(val); });
            rjson::v3::call_if_not_null<Pixels>(getenv("point_size"sv), [&legend_element](Pixels val) { legend_element.point_size(val); });

            getenv("title"sv).visit([&legend_element]<typename Val>(const Val& title) {
                auto insertion_point{legend_element.lines().begin()};
                if constexpr (std::is_same_v<Val, rjson::v3::detail::array>) {
                    for (const auto& line : title)
                        insertion_point = std::next(legend_element.lines().emplace(insertion_point, line.template to<std::string_view>()));
                }
                else if constexpr (std::is_same_v<Val, rjson::v3::detail::string>)
                    legend_element.lines().insert(insertion_point, title.template to<std::string_view>());
                else if constexpr (!std::is_same_v<Val, rjson::v3::detail::null>)
                    throw error{fmt::format("unrecognized: {} (expected array of strings or a string)", title)};
            });

            getenv("lines"sv).visit([&legend_element]<typename Val>(const Val& lines) {
                if constexpr (std::is_same_v<Val, rjson::v3::detail::array>) {
                    for (const auto& line : lines) {
                        legend_element.lines().emplace_back(rjson::v3::read_color(line["outline"sv], TRANSPARENT), rjson::v3::read_number(line["outline_width"sv], Pixels{1}),
                                                            rjson::v3::read_color(line["fill"sv], TRANSPARENT), rjson::v3::read_string(line["text"sv], "\"text\""sv));
                    }
                }
                else if constexpr (!std::is_same_v<Val, rjson::v3::detail::null>)
                    throw error{fmt::format("unrecognized: {} (expected array of objects)", lines)};
            });
        }
    }
    else {
        // AD_DEBUG("remove_legend");
        chart_draw().remove_legend();
    }

    return true;

} // acmacs::mapi::v1::Settings::apply_legend

// ----------------------------------------------------------------------

void acmacs::mapi::v1::Settings::add_legend(const acmacs::chart::PointIndexList& indexes, const acmacs::PointStyleModified& style, const rjson::v3::value& legend_data)
{
    using namespace std::string_view_literals;

    const auto label{fmt::format(fmt::runtime(rjson::v3::get_or(legend_data["label"sv], "use \"label\" in \"legend\""sv)),
                                 fmt::arg("count", indexes.size()))};
    if (rjson::v3::read_bool(legend_data["replace"sv], false))
        legend().remove_line(label);

    add_legend(indexes, style, label, legend_data);

} // acmacs::mapi::v1::Settings::add_legend

// ----------------------------------------------------------------------

void acmacs::mapi::v1::Settings::add_legend(const acmacs::chart::PointIndexList& indexes, const acmacs::PointStyleModified& style, std::string_view label, const rjson::v3::value& legend_data)
{
    using namespace std::string_view_literals;
    if (rjson::v3::read_bool(legend_data["show"sv], true) && (!indexes->empty() || rjson::v3::read_bool(legend_data["show_if_none_selected"sv], false))) { // show is true by default
        legend().add_line(acmacs::color::Modifier{style.fill()}, acmacs::color::Modifier{style.outline()}, style.outline_width(), label);
    }

} // acmacs::mapi::v1::Settings::add_legend

// ----------------------------------------------------------------------

void acmacs::mapi::v1::Settings::add_legend_continent_map()
{
    using namespace std::string_view_literals;
    if (const auto offset = rjson::v3::read_point_coordinates(getenv("offset"sv)); offset.has_value())
        chart_draw().continent_map(*offset, rjson::v3::read_number(getenv("size"sv), Pixels{100.0}));
    else
        chart_draw().continent_map();

} // acmacs::mapi::v1::Settings::add_legend_continent_map

// ----------------------------------------------------------------------

map_elements::v1::Title& acmacs::mapi::v1::Settings::title()
{
    return chart_draw().map_elements().find_or_add<map_elements::v1::Title>("title");

} // acmacs::mapi::v1::Settings::title

// ----------------------------------------------------------------------

bool acmacs::mapi::v1::Settings::apply_title()
{
    using namespace std::string_view_literals;

    auto& title_element = title();
    rjson::v3::call_if_not_null<bool>(getenv("show"sv), [&title_element](bool val) { title_element.show(val); });
    rjson::v3::call_if_not_null<Pixels>(getenv("padding"sv), [&title_element](Pixels val) { title_element.padding(val); });
    rjson::v3::call_if_not_null<double>(getenv("interline"sv), [&title_element](double val) { title_element.interline(val); });
    rjson::v3::call_if_not_null<Pixels>(getenv("text_size"sv), [&title_element](Pixels val) { title_element.text_size(val); });
    rjson::v3::call_if_not_null<Pixels>(getenv("border_width"sv), [&title_element](Pixels val) { title_element.border_width(val); });
    rjson::v3::call_if_not_null<acmacs::PointCoordinates>(getenv("offset"sv), [&title_element](const acmacs::PointCoordinates& val) { title_element.offset(val); });
    rjson::v3::call_if_not_null<acmacs::color::Modifier>(getenv("text_color"sv), [&title_element](const acmacs::color::Modifier& val) { title_element.text_color(val); });
    rjson::v3::call_if_not_null<acmacs::color::Modifier>(getenv("background"sv), [&title_element](const acmacs::color::Modifier& val) { title_element.background(val); });
    rjson::v3::call_if_not_null<acmacs::color::Modifier>(getenv("border_color"sv), [&title_element](const acmacs::color::Modifier& val) { title_element.border_color(val); });
    rjson::v3::call_if_not_null<std::string_view>(getenv("font_weight"sv), [&title_element](std::string_view val) { title_element.weight(val); });
    rjson::v3::call_if_not_null<std::string_view>(getenv("font_slant"sv), [&title_element](std::string_view val) { title_element.slant(val); });
    rjson::v3::call_if_not_null<std::string_view>(getenv("font_family"sv), [&title_element](std::string_view val) { title_element.font_family(val); });

    if (rjson::v3::read_bool(getenv("remove-lines"sv), false))
        title_element.remove_all_lines();

    getenv("lines"sv).visit([&title_element, this]<typename Val>(const Val& lines) {
        if constexpr (std::is_same_v<Val, rjson::v3::detail::array>) {
            for (const auto& line : lines) {
                // title_element.add_line(line.template to<std::string_view>());
                title_element.add_line(substitute(line).template to<std::string_view>());
            }
        }
        else if constexpr (!std::is_same_v<Val, rjson::v3::detail::null>)
            throw error{fmt::format("unrecognized: {} (expected array of strings)", lines)};
    });

    // AD_DEBUG("title: {}", title_element.lines());

    return true;

} // acmacs::mapi::v1::Settings::apply_title

// ----------------------------------------------------------------------

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>allow var substitution in antigen legend settings<commit_after>#include "acmacs-base/rjson-v3-helper.hh"
#include "acmacs-map-draw/mapi-settings.hh"
#include "acmacs-map-draw/draw.hh"
#include "acmacs-map-draw/map-elements-v1.hh"

// ----------------------------------------------------------------------

map_elements::v1::LegendPointLabel& acmacs::mapi::v1::Settings::legend()
{
    return chart_draw().map_elements().find_or_add<map_elements::v1::LegendPointLabel>("legend-point-label");

} // acmacs::mapi::v1::Settings::legend

// ----------------------------------------------------------------------

bool acmacs::mapi::v1::Settings::apply_legend()
{
    using namespace std::string_view_literals;

    if (rjson::v3::read_bool(getenv("show"sv), true)) { // show by default
        if (const auto legend_type = rjson::v3::read_string(getenv("type"sv), ""sv); legend_type == "continent-map"sv || legend_type == "continent_map"sv) {
            add_legend_continent_map();
        }
        else {
            auto& legend_element = legend();
            rjson::v3::call_if_not_null<acmacs::PointCoordinates>(getenv("offset"sv), [&legend_element](const acmacs::PointCoordinates& val) { legend_element.offset(val); });
            rjson::v3::call_if_not_null<Pixels>(getenv("label_size"sv), [&legend_element](Pixels val) { legend_element.label_size(val); });
            rjson::v3::call_if_not_null<Pixels>(getenv("point_size"sv), [&legend_element](Pixels val) { legend_element.point_size(val); });

            getenv("title"sv).visit([&legend_element]<typename Val>(const Val& title) {
                auto insertion_point{legend_element.lines().begin()};
                if constexpr (std::is_same_v<Val, rjson::v3::detail::array>) {
                    for (const auto& line : title)
                        insertion_point = std::next(legend_element.lines().emplace(insertion_point, line.template to<std::string_view>()));
                }
                else if constexpr (std::is_same_v<Val, rjson::v3::detail::string>)
                    legend_element.lines().insert(insertion_point, title.template to<std::string_view>());
                else if constexpr (!std::is_same_v<Val, rjson::v3::detail::null>)
                    throw error{fmt::format("unrecognized: {} (expected array of strings or a string)", title)};
            });

            getenv("lines"sv).visit([&legend_element]<typename Val>(const Val& lines) {
                if constexpr (std::is_same_v<Val, rjson::v3::detail::array>) {
                    for (const auto& line : lines) {
                        legend_element.lines().emplace_back(rjson::v3::read_color(line["outline"sv], TRANSPARENT), rjson::v3::read_number(line["outline_width"sv], Pixels{1}),
                                                            rjson::v3::read_color(line["fill"sv], TRANSPARENT), rjson::v3::read_string(line["text"sv], "\"text\""sv));
                    }
                }
                else if constexpr (!std::is_same_v<Val, rjson::v3::detail::null>)
                    throw error{fmt::format("unrecognized: {} (expected array of objects)", lines)};
            });
        }
    }
    else {
        // AD_DEBUG("remove_legend");
        chart_draw().remove_legend();
    }

    return true;

} // acmacs::mapi::v1::Settings::apply_legend

// ----------------------------------------------------------------------

void acmacs::mapi::v1::Settings::add_legend(const acmacs::chart::PointIndexList& indexes, const acmacs::PointStyleModified& style, const rjson::v3::value& legend_data)
{
    using namespace std::string_view_literals;

    const auto label{fmt::format(fmt::runtime(rjson::v3::get_or(substitute(legend_data["label"sv]), "use \"label\" in \"legend\""sv)),
                                 fmt::arg("count", indexes.size()))};
    if (rjson::v3::read_bool(substitute(legend_data["replace"sv]), false))
        legend().remove_line(label);

    add_legend(indexes, style, label, legend_data);

} // acmacs::mapi::v1::Settings::add_legend

// ----------------------------------------------------------------------

void acmacs::mapi::v1::Settings::add_legend(const acmacs::chart::PointIndexList& indexes, const acmacs::PointStyleModified& style, std::string_view label, const rjson::v3::value& legend_data)
{
    using namespace std::string_view_literals;
    if (rjson::v3::read_bool(substitute(legend_data["show"sv]), true) && (!indexes->empty() || rjson::v3::read_bool(substitute(legend_data["show_if_none_selected"sv]), false))) { // show is true by default
        legend().add_line(acmacs::color::Modifier{style.fill()}, acmacs::color::Modifier{style.outline()}, style.outline_width(), label);
    }

} // acmacs::mapi::v1::Settings::add_legend

// ----------------------------------------------------------------------

void acmacs::mapi::v1::Settings::add_legend_continent_map()
{
    using namespace std::string_view_literals;
    if (const auto offset = rjson::v3::read_point_coordinates(getenv("offset"sv)); offset.has_value())
        chart_draw().continent_map(*offset, rjson::v3::read_number(getenv("size"sv), Pixels{100.0}));
    else
        chart_draw().continent_map();

} // acmacs::mapi::v1::Settings::add_legend_continent_map

// ----------------------------------------------------------------------

map_elements::v1::Title& acmacs::mapi::v1::Settings::title()
{
    return chart_draw().map_elements().find_or_add<map_elements::v1::Title>("title");

} // acmacs::mapi::v1::Settings::title

// ----------------------------------------------------------------------

bool acmacs::mapi::v1::Settings::apply_title()
{
    using namespace std::string_view_literals;

    auto& title_element = title();
    rjson::v3::call_if_not_null<bool>(getenv("show"sv), [&title_element](bool val) { title_element.show(val); });
    rjson::v3::call_if_not_null<Pixels>(getenv("padding"sv), [&title_element](Pixels val) { title_element.padding(val); });
    rjson::v3::call_if_not_null<double>(getenv("interline"sv), [&title_element](double val) { title_element.interline(val); });
    rjson::v3::call_if_not_null<Pixels>(getenv("text_size"sv), [&title_element](Pixels val) { title_element.text_size(val); });
    rjson::v3::call_if_not_null<Pixels>(getenv("border_width"sv), [&title_element](Pixels val) { title_element.border_width(val); });
    rjson::v3::call_if_not_null<acmacs::PointCoordinates>(getenv("offset"sv), [&title_element](const acmacs::PointCoordinates& val) { title_element.offset(val); });
    rjson::v3::call_if_not_null<acmacs::color::Modifier>(getenv("text_color"sv), [&title_element](const acmacs::color::Modifier& val) { title_element.text_color(val); });
    rjson::v3::call_if_not_null<acmacs::color::Modifier>(getenv("background"sv), [&title_element](const acmacs::color::Modifier& val) { title_element.background(val); });
    rjson::v3::call_if_not_null<acmacs::color::Modifier>(getenv("border_color"sv), [&title_element](const acmacs::color::Modifier& val) { title_element.border_color(val); });
    rjson::v3::call_if_not_null<std::string_view>(getenv("font_weight"sv), [&title_element](std::string_view val) { title_element.weight(val); });
    rjson::v3::call_if_not_null<std::string_view>(getenv("font_slant"sv), [&title_element](std::string_view val) { title_element.slant(val); });
    rjson::v3::call_if_not_null<std::string_view>(getenv("font_family"sv), [&title_element](std::string_view val) { title_element.font_family(val); });

    if (rjson::v3::read_bool(getenv("remove-lines"sv), false))
        title_element.remove_all_lines();

    getenv("lines"sv).visit([&title_element, this]<typename Val>(const Val& lines) {
        if constexpr (std::is_same_v<Val, rjson::v3::detail::array>) {
            for (const auto& line : lines) {
                // title_element.add_line(line.template to<std::string_view>());
                title_element.add_line(substitute(line).template to<std::string_view>());
            }
        }
        else if constexpr (!std::is_same_v<Val, rjson::v3::detail::null>)
            throw error{fmt::format("unrecognized: {} (expected array of strings)", lines)};
    });

    // AD_DEBUG("title: {}", title_element.lines());

    return true;

} // acmacs::mapi::v1::Settings::apply_title

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