<commit_before>//
//  Exponent.cpp
//  Calculator
//
//  Created by Gavin Scheele on 3/27/14.
//  Copyright (c) 2014 Gavin Scheele. All rights reserved.
//

#include "Exponential.h"

Exponential::Exponential(Expression* base, Rational* exponent){
    this->type = "exponential";
    this->base = base;
    this->exponent = exponent;
    this->exde = new Integer(exponent->getDenominator());
    if (exde->getValue() != 1) {
    	//if the denominator of the exponent is not 1, make the base a root of the denominator, then setting the denominator equal to 1
    	Integer* baseAsInteger = (Integer *) base;
        base = new nthRoot(exde->getValue(), baseAsInteger->getValue(), 1);
        Integer* one = new Integer(1);
        exponent->setDenominator(one);
    }
    this->exnu = new Integer(exponent->getNumerator());
    if (canExponentiate()) {
    	exponentiate();
    }
}
Exponential::~Exponential(){

}

bool Exponential::canExponentiate() {
    if(base->type == "euler"){
        return false;

    }else if(base->type == "exponential"){
	Exponential* ex = (Exponential *) base;
	this->exponent->multiply(ex->getExponent());
	Integer* numSum = new Integer (1);
	ex->getExponent()->setNumerator(numSum);
        return false;
        // false is returned because the base itself would have already been exponentiated if it were possible

    }else if(base->type == "integer"){
        return true;

    }else if(base->type == "logarithm"){
        return false;

    }else if(base->type == "nthRoot"){
	nthRoot* nr = (nthRoot *) base;
	Rational* r = new Rational(this->exponent->getNumerator(), nr->getRoot()*this->exponent->getDenominator());
	//makes a new exponent, multiplying the denominator by the root, allowing the root to be simplified to one
	this->exponent = r;
	nr->setRoot(1);
	return false;

    }else if(base->type == "pi"){
        return false;

    }else if(base->type == "rational"){
        Rational* r = (Rational *) base;
        if (r->geteNumerator()->type == "integer" && r->geteDenominator()->type == "integer") {
          Exponential* nu = new Exponential(r->geteNumerator(), this->exponent);
          r->setNumerator(nu);
          Exponential* de = new Exponential(r->geteDenominator(), this->exponent);
          r->setDenominator(de);
        }

    }else{
        cout << "type not recognized" << endl;
    }
    return false;
}

void Exponential::exponentiate(){
	Integer* one = new Integer(1);
        Rational* oneRat = new Rational(1, 1);
	if (this->base->type == "rational") {
		Rational* ratBase = (Rational *) this->base;
		Exponential* numAsExponential = new Exponential ((ratBase->geteNumerator()), (this->exponent));  //no matching constructor for exponential
		Exponential* denAsExponential = new Exponential ((ratBase->geteDenominator()), (this->exponent));    //same error
		Rational* newRatBase = new Rational(numAsExponential, denAsExponential);
		this->base = newRatBase;
		this->exponent = oneRat;
	}
	else {

    if (this->exponent->getNumerator()==0) {

       this->exponent=oneRat;
       this->base=one;

    }
    bool toFlip = false;
    if (exnu->getValue()<0) {
	    exnu->setValue(exnu->getValue()*-1);
            toFlip = true;
            //handles negative exponents
    }
    Expression* constantBase = 0;
    if (base->type == "integer") {              //fixed the problem for integers but nothing else
        Integer *a = (Integer *)base;
        constantBase = new Integer(a->getValue());
    }

    while (exponent->getNumerator()>1)
    	{
        base->multiply(constantBase);
        exponent->setNumerator(exponent->geteNumerator()->subtract(one));
    }
    if (toFlip) {
        Integer* one = new Integer(1);
        Rational* mouse = new Rational(one, base);
    	base = mouse;
    }

	}

}

Expression* Exponential::add(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (ex->getBase()==this->base) {
		if (ex->getExponent()==this->exponent) {
			Integer* two = new Integer(2);
			this->multiply(two);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::subtract(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (ex->getBase()==this->base) {
		if (ex->getExponent()==this->exponent) {
			Integer* zero = new Integer(0);
			this->multiply(zero);
		}
	}
    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::multiply(Expression* a){
	if(a->type == "euler"){
    		if (this->base->type == "euler") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);

    	}

    }else if(a->type == "exponential"){
		Exponential* ex = (Exponential *) a;
	//if (this->base == ex->getBase()) {
	//	this->exponent->add(ex->getExponent());
	//}
	if (ex->base->type == this->base->type) {
		if ((ex->base->type == "euler") || (ex->base->type == "pi")) {
			this->exponent->add(ex->exponent);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);
    	}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	Expression* numToSet = r->geteNumerator();
	numToSet->multiply(this);
	r->setNumerator(numToSet);
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::divide(Expression* a){
	if(a->type == "euler"){
		if (this->base->type == "euler") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	//if (this->base == ex->getBase()) {
	//	this->exponent->subtract(ex->getExponent());
	//}
	if (ex->base->type == this->base->type) {
		if ((ex->base->type == "euler") || (ex->base->type == "pi")) {
			this->exponent->subtract(ex->exponent);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	Expression* denToSet = r->geteDenominator();
	denToSet->multiply(this);
	r->setDenominator(denToSet);
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}

Rational* Exponential::getExponent() {
    return exponent;
}

Expression* Exponential::getBase() {
    return base;
}

Integer* Exponential::getExnu() {
	return exnu;
}

Integer* Exponential::getExde() {
	return exde;
}

void Exponential::setExnu(Integer* n) {
	exnu = n;
}

void Exponential::setExde(Integer* n) {
	exde = n;
}

void Exponential::setExponent(Rational* e) {
    exponent = e;
}

void Exponential::setBase(Expression* e) {
    base = e;
}

string Exponential::toString() {
    stringstream str;
    if(exponent->getNumerator() == 1 && exponent->getDenominator() == 1){
        str << *base;
    }
    else if(exponent->getDenominator() == 1){
        str << *base << "^" << *exponent->geteNumerator();
    }else{
        str << *base << "^" << *exponent;
    }
    return str.str();
}

ostream& Exponential::print(std::ostream& output) const{
    Exponential *a = (Exponential *)this;
    output << a->toString();
    return output;
}

bool Exponential::canAdd(Expression* b){     //use "this" as comparison. Solver will call someExpression.canAdd(&someOtherExpression)

    if (this->type == b->type && this->type != "logarithm") {
        if (this->type == "nthRoot") {
        }
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canSubtract(Expression* b){
    if (this->type == b->type) {
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canMultiply(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if (this->base->type == b->type) {
    	return true;
    }
    else if(this->type == "integer" && b->type == "rational") return true;
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;

}
bool Exponential::canDivide(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if (this->base->type == b->type) {
    	return true;
    }
    else if(this->type == "integer"){
        if( b->type == "rational") return true;
    }
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
<commit_msg>Fixed add and subtract<commit_after>//
//  Exponent.cpp
//  Calculator
//
//  Created by Gavin Scheele on 3/27/14.
//  Copyright (c) 2014 Gavin Scheele. All rights reserved.
//

#include "Exponential.h"

Exponential::Exponential(Expression* base, Rational* exponent){
    this->type = "exponential";
    this->base = base;
    this->exponent = exponent;
    this->exde = new Integer(exponent->getDenominator());
    if (exde->getValue() != 1) {
    	//if the denominator of the exponent is not 1, make the base a root of the denominator, then setting the denominator equal to 1
    	Integer* baseAsInteger = (Integer *) base;
        base = new nthRoot(exde->getValue(), baseAsInteger->getValue(), 1);
        Integer* one = new Integer(1);
        exponent->setDenominator(one);
    }
    this->exnu = new Integer(exponent->getNumerator());
    if (canExponentiate()) {
    	exponentiate();
    }
}
Exponential::~Exponential(){

}

bool Exponential::canExponentiate() {
    if(base->type == "euler"){
        return false;

    }else if(base->type == "exponential"){
	Exponential* ex = (Exponential *) base;
	this->exponent->multiply(ex->getExponent());
	Integer* numSum = new Integer (1);
	ex->getExponent()->setNumerator(numSum);
        return false;
        // false is returned because the base itself would have already been exponentiated if it were possible

    }else if(base->type == "integer"){
        return true;

    }else if(base->type == "logarithm"){
        return false;

    }else if(base->type == "nthRoot"){
	nthRoot* nr = (nthRoot *) base;
	Rational* r = new Rational(this->exponent->getNumerator(), nr->getRoot()*this->exponent->getDenominator());
	//makes a new exponent, multiplying the denominator by the root, allowing the root to be simplified to one
	this->exponent = r;
	nr->setRoot(1);
	return false;

    }else if(base->type == "pi"){
        return false;

    }else if(base->type == "rational"){
        Rational* r = (Rational *) base;
        if (r->geteNumerator()->type == "integer" && r->geteDenominator()->type == "integer") {
          Exponential* nu = new Exponential(r->geteNumerator(), this->exponent);
          r->setNumerator(nu);
          Exponential* de = new Exponential(r->geteDenominator(), this->exponent);
          r->setDenominator(de);
        }

    }else{
        cout << "type not recognized" << endl;
    }
    return false;
}

void Exponential::exponentiate(){
	Integer* one = new Integer(1);
        Rational* oneRat = new Rational(1, 1);
	if (this->base->type == "rational") {
		Rational* ratBase = (Rational *) this->base;
		Exponential* numAsExponential = new Exponential ((ratBase->geteNumerator()), (this->exponent));  //no matching constructor for exponential
		Exponential* denAsExponential = new Exponential ((ratBase->geteDenominator()), (this->exponent));    //same error
		Rational* newRatBase = new Rational(numAsExponential, denAsExponential);
		this->base = newRatBase;
		this->exponent = oneRat;
	}
	else {

    if (this->exponent->getNumerator()==0) {

       this->exponent=oneRat;
       this->base=one;

    }
    bool toFlip = false;
    if (exnu->getValue()<0) {
	    exnu->setValue(exnu->getValue()*-1);
            toFlip = true;
            //handles negative exponents
    }
    Expression* constantBase = 0;
    if (base->type == "integer") {              //fixed the problem for integers but nothing else
        Integer *a = (Integer *)base;
        constantBase = new Integer(a->getValue());
    }

    while (exponent->getNumerator()>1)
    	{
        base->multiply(constantBase);
        exponent->setNumerator(exponent->geteNumerator()->subtract(one));
    }
    if (toFlip) {
        Integer* one = new Integer(1);
        Rational* mouse = new Rational(one, base);
    	base = mouse;
    }

	}

}

Expression* Exponential::add(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if ((ex->getBase()->type == this->base->type) && ((this->base->type == "euler") || (this->base->type == "pi"))) {
		if (ex->getExponent()==this->exponent) {
			Integer* two = new Integer(2);
			this->multiply(two);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::subtract(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if ((ex->getBase()->type == this->base->type) && ((this->base->type == "euler") || (this->base->type == "pi"))) {
		if (ex->getExponent()==this->exponent) {
			Integer* zero = new Integer(0);
			this->multiply(zero);
		}
	}
    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::multiply(Expression* a){
	if(a->type == "euler"){
    		if (this->base->type == "euler") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);

    	}

    }else if(a->type == "exponential"){
		Exponential* ex = (Exponential *) a;
	//if (this->base == ex->getBase()) {
	//	this->exponent->add(ex->getExponent());
	//}
	if (ex->base->type == this->base->type) {
		if ((ex->base->type == "euler") || (ex->base->type == "pi")) {
			this->exponent->add(ex->exponent);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);
    	}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	Expression* numToSet = r->geteNumerator();
	numToSet->multiply(this);
	r->setNumerator(numToSet);
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::divide(Expression* a){
	if(a->type == "euler"){
		if (this->base->type == "euler") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	//if (this->base == ex->getBase()) {
	//	this->exponent->subtract(ex->getExponent());
	//}
	if (ex->base->type == this->base->type) {
		if ((ex->base->type == "euler") || (ex->base->type == "pi")) {
			this->exponent->subtract(ex->exponent);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	Expression* denToSet = r->geteDenominator();
	denToSet->multiply(this);
	r->setDenominator(denToSet);
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}

Rational* Exponential::getExponent() {
    return exponent;
}

Expression* Exponential::getBase() {
    return base;
}

Integer* Exponential::getExnu() {
	return exnu;
}

Integer* Exponential::getExde() {
	return exde;
}

void Exponential::setExnu(Integer* n) {
	exnu = n;
}

void Exponential::setExde(Integer* n) {
	exde = n;
}

void Exponential::setExponent(Rational* e) {
    exponent = e;
}

void Exponential::setBase(Expression* e) {
    base = e;
}

string Exponential::toString() {
    stringstream str;
    if(exponent->getNumerator() == 1 && exponent->getDenominator() == 1){
        str << *base;
    }
    else if(exponent->getDenominator() == 1){
        str << *base << "^" << *exponent->geteNumerator();
    }else{
        str << *base << "^" << *exponent;
    }
    return str.str();
}

ostream& Exponential::print(std::ostream& output) const{
    Exponential *a = (Exponential *)this;
    output << a->toString();
    return output;
}

bool Exponential::canAdd(Expression* b){     //use "this" as comparison. Solver will call someExpression.canAdd(&someOtherExpression)

    if (this->type == b->type && this->type != "logarithm") {
        if (this->type == "nthRoot") {
        }
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canSubtract(Expression* b){
    if (this->type == b->type) {
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canMultiply(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if (this->base->type == b->type) {
    	return true;
    }
    else if(this->type == "integer" && b->type == "rational") return true;
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;

}
bool Exponential::canDivide(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if (this->base->type == b->type) {
    	return true;
    }
    else if(this->type == "integer"){
        if( b->type == "rational") return true;
    }
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
<|endoftext|>


<commit_before>/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

#include "scenemodel.h"
#include <gluon/gameobject.h>
#include <gluon/component.h>
#include <typeinfo>
#include <objectmanager.h>

#include <debughelper.h>
#include <qmimedata.h>
#include <KLocalizedString>

using namespace Gluon;
using namespace Gluon::Creator;

SceneModel::SceneModel(QObject* parent): QAbstractItemModel(parent)
{
    m_root = 0;
    connect(ObjectManager::instance(), SIGNAL(newObject(Gluon::GameObject*)), SIGNAL(layoutChanged()));
}

GameObject* SceneModel::rootGameObject()
{
    if(m_root) return m_root->childGameObject(0);
    return 0;
}

void SceneModel::setRootGameObject(GameObject* obj)
{
    if(obj)
    {
        /*if(!m_root)
            m_root = new GameObject(this);

        if(m_root->childCount() > 0)
            m_root->removeChild(m_root->childGameObject(0));

        m_root->addChild(obj);*/
        m_root = obj;

        reset();
    }
}

QVariant SceneModel::data(const QModelIndex& index, int role) const
{
    if (index.isValid() && role == Qt::DisplayRole)
    {
        GameObject *item = static_cast<GameObject*>(index.internalPointer());

        if(item)
            return item->name();
    }

    return QVariant();
}

int SceneModel::columnCount(const QModelIndex&) const
{
    return 1;
}

int SceneModel::rowCount(const QModelIndex& parent) const
{
    GameObject *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    if(parentItem) return parentItem->childCount();
    return 0;
}

QModelIndex SceneModel::parent(const QModelIndex& child) const
{
    if (!child.isValid())
        return QModelIndex();

    GameObject *childItem = static_cast<GameObject*>(child.internalPointer());

    if(!childItem)
        return QModelIndex();

    GameObject *parentItem = childItem->parentGameObject();

    if (parentItem == m_root)
        return QModelIndex();

    return createIndex(rowIndex(parentItem), 0, parentItem);
}

QModelIndex SceneModel::index(int row, int column, const QModelIndex& parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    GameObject *parentItem;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    GameObject *childItem = parentItem->childGameObject(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QVariant SceneModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section)
    Q_UNUSED(orientation)
    Q_UNUSED(role)

    return QVariant();
}

int SceneModel::rowIndex(GameObject* object) const
{
    if(object)
    {
        if(object->parentGameObject())
        {
            return object->parentGameObject()->childIndex(object);
        }
    }
    return 0;
}

Qt::DropActions SceneModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

Qt::ItemFlags SceneModel::flags(const QModelIndex& index) const
{
    if (index.isValid())
        return QAbstractItemModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
        return QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
}

QStringList
SceneModel::mimeTypes() const
{
    QStringList types;
    types << "application/gluon.text.componentclass";
    return types;
}

bool SceneModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
    DEBUG_FUNC_NAME

    if(action == Qt::IgnoreAction)
        return false;

    if(!parent.isValid())
        return false;

    GameObject *gobj = qobject_cast<GameObject*>((QObject*)parent.internalPointer());

    if(!gobj)
        return false;

    foreach(QString something, data->formats())
    {
        DEBUG_TEXT(QString("Dropped mimetype %1 on object %2").arg(something).arg(gobj->fullyQualifiedName()));
    }

    QByteArray encodedData = data->data("application/gluon.text.componentclass");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;
    int rows = 0;

    while (!stream.atEnd())
    {
        QString text;
        stream >> text;
        newItems << text;
        ++rows;
    }
    foreach(QString text, newItems)
    {
        DEBUG_TEXT(QString("Adding component of class %1").arg(text));
        GluonObject *component = Gluon::GluonObjectFactory::instance()->instantiateObjectByName(text);
        if(!component)
        {
            DEBUG_TEXT("Returned component instance was null, something's fishy");
        }
        else
        {
            DEBUG_TEXT(QString("Adding component of class name %1").arg(component->metaObject()->className()));
            gobj->addComponent(qobject_cast<Gluon::Component*>(component));
        }
    }

    return true;
}

bool SceneModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        static_cast<GluonObject*>(index.internalPointer())->setName(value.toString());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

bool SceneModel::insertRows(int row, int count, const QModelIndex& parent)
{
    beginInsertRows(parent, row, row + count - 1);

    GameObject* obj = static_cast<GameObject*>(parent.internalPointer());
    for (int i = 0; i < count; ++i) {
        obj->addChild(new GameObject());
    }

    endInsertRows();
    return true;
}

bool SceneModel::removeRows(int row, int count, const QModelIndex& parent)
{

}

#include "scenemodel.moc"

<commit_msg>Ewewewew! God-mode casting is so ugly... But qobject_cast fails me. Anybody who want to explain to me why that is the case?<commit_after>/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

#include "scenemodel.h"
#include <gluon/gameobject.h>
#include <gluon/component.h>
#include <typeinfo>
#include <objectmanager.h>

#include <debughelper.h>
#include <qmimedata.h>
#include <KLocalizedString>

using namespace Gluon;
using namespace Gluon::Creator;

SceneModel::SceneModel(QObject* parent): QAbstractItemModel(parent)
{
    m_root = 0;
    connect(ObjectManager::instance(), SIGNAL(newObject(Gluon::GameObject*)), SIGNAL(layoutChanged()));
}

GameObject* SceneModel::rootGameObject()
{
    if(m_root) return m_root->childGameObject(0);
    return 0;
}

void SceneModel::setRootGameObject(GameObject* obj)
{
    if(obj)
    {
        /*if(!m_root)
            m_root = new GameObject(this);

        if(m_root->childCount() > 0)
            m_root->removeChild(m_root->childGameObject(0));

        m_root->addChild(obj);*/
        m_root = obj;

        reset();
    }
}

QVariant SceneModel::data(const QModelIndex& index, int role) const
{
    if (index.isValid() && role == Qt::DisplayRole)
    {
        GameObject *item = static_cast<GameObject*>(index.internalPointer());

        if(item)
            return item->name();
    }

    return QVariant();
}

int SceneModel::columnCount(const QModelIndex&) const
{
    return 1;
}

int SceneModel::rowCount(const QModelIndex& parent) const
{
    GameObject *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    if(parentItem) return parentItem->childCount();
    return 0;
}

QModelIndex SceneModel::parent(const QModelIndex& child) const
{
    if (!child.isValid())
        return QModelIndex();

    GameObject *childItem = static_cast<GameObject*>(child.internalPointer());

    if(!childItem)
        return QModelIndex();

    GameObject *parentItem = childItem->parentGameObject();

    if (parentItem == m_root)
        return QModelIndex();

    return createIndex(rowIndex(parentItem), 0, parentItem);
}

QModelIndex SceneModel::index(int row, int column, const QModelIndex& parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    GameObject *parentItem;

    if (!parent.isValid())
        parentItem = m_root;
    else
        parentItem = static_cast<GameObject*>(parent.internalPointer());

    GameObject *childItem = parentItem->childGameObject(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QVariant SceneModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section)
    Q_UNUSED(orientation)
    Q_UNUSED(role)

    return QVariant();
}

int SceneModel::rowIndex(GameObject* object) const
{
    if(object)
    {
        if(object->parentGameObject())
        {
            return object->parentGameObject()->childIndex(object);
        }
    }
    return 0;
}

Qt::DropActions SceneModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

Qt::ItemFlags SceneModel::flags(const QModelIndex& index) const
{
    if (index.isValid())
        return QAbstractItemModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
        return QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
}

QStringList
SceneModel::mimeTypes() const
{
    QStringList types;
    types << "application/gluon.text.componentclass";
    return types;
}

bool SceneModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
    DEBUG_FUNC_NAME

    if(action == Qt::IgnoreAction)
        return false;

    if(!parent.isValid())
        return false;

    GameObject *gobj = qobject_cast<GameObject*>((QObject*)parent.internalPointer());

    if(!gobj)
        return false;

    foreach(QString something, data->formats())
    {
        DEBUG_TEXT(QString("Dropped mimetype %1 on object %2").arg(something).arg(gobj->fullyQualifiedName()));
    }

    QByteArray encodedData = data->data("application/gluon.text.componentclass");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;
    int rows = 0;

    while (!stream.atEnd())
    {
        QString text;
        stream >> text;
        newItems << text;
        ++rows;
    }
    foreach(QString text, newItems)
    {
        DEBUG_TEXT(QString("Adding component of class %1").arg(text));
        GluonObject *component = Gluon::GluonObjectFactory::instance()->instantiateObjectByName(text);
        if(!component)
        {
            DEBUG_TEXT("Returned component instance was null, something's fishy");
        }
        else
        {
            DEBUG_TEXT(QString("Adding component of class name %1").arg(component->metaObject()->className()));
            gobj->addComponent((Gluon::Component*)component);
        }
    }

    return true;
}

bool SceneModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        static_cast<GluonObject*>(index.internalPointer())->setName(value.toString());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

bool SceneModel::insertRows(int row, int count, const QModelIndex& parent)
{
    beginInsertRows(parent, row, row + count - 1);

    GameObject* obj = static_cast<GameObject*>(parent.internalPointer());
    for (int i = 0; i < count; ++i) {
        obj->addChild(new GameObject());
    }

    endInsertRows();
    return true;
}

bool SceneModel::removeRows(int row, int count, const QModelIndex& parent)
{

}

#include "scenemodel.moc"

<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  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
//
//  Current versions can be found at www.libavg.de
//

#include "TextEngine.h"

#include "../base/Logger.h"
#include "../base/OSHelper.h"
#include "../base/Exception.h"
#include "../base/FileHelper.h"
#include "../base/StringHelper.h"

#include <fontconfig/fontconfig.h>
#include <algorithm>

namespace avg {

using namespace std;

TextEngine& TextEngine::get(bool bHint)
{
    if (bHint) {
        static TextEngine s_Instance(true);
        return s_Instance;
    } else {
        static TextEngine s_Instance(false);
        return s_Instance;
    }
}

TextEngine::TextEngine(bool bHint)
    : m_bHint(bHint)
{
    m_sFontDirs.push_back("fonts/");
    init();
}

TextEngine::~TextEngine()
{
    deinit();
}

void TextEngine::init()
{
    g_type_init();
    m_pFontMap = PANGO_CAIRO_FONT_MAP(pango_cairo_font_map_new_for_font_type(
            CAIRO_FONT_TYPE_FT));
    pango_cairo_font_map_set_resolution(m_pFontMap, 72);

    m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
    m_pCairo = cairo_create(m_pCairoSurface);
    m_pPangoContext = pango_cairo_create_context(m_pCairo);

    pango_context_set_language(m_pPangoContext,
            pango_language_from_string ("en_US"));
    pango_context_set_base_dir(m_pPangoContext, PANGO_DIRECTION_LTR);

    initFonts();

    string sOldLang = "";
    getEnv("LC_CTYPE", sOldLang);
    setEnv("LC_CTYPE", "en-us");
    pango_font_map_list_families(PANGO_FONT_MAP(m_pFontMap), &m_ppFontFamilies,
            &m_NumFontFamilies);
    setEnv("LC_CTYPE", sOldLang);
    for (int i = 0; i < m_NumFontFamilies; ++i) {
        m_sFonts.push_back(pango_font_family_get_name(m_ppFontFamilies[i]));
    }
    sort(m_sFonts.begin(), m_sFonts.end());
}

void TextEngine::deinit()
{
    g_object_unref(m_pPangoContext);
    m_sFonts.clear();
    g_free(m_ppFontFamilies);
    cairo_surface_destroy(m_pCairoSurface);
    cairo_destroy(m_pCairo);
    g_object_unref(m_pFontMap);
}

void TextEngine::addFontDir(const std::string& sDir)
{
    deinit();
    m_sFontDirs.push_back(sDir);
    init();
}

PangoContext * TextEngine::getPangoContext()
{
    return m_pPangoContext;
}

const vector<string>& TextEngine::getFontFamilies()
{
    return m_sFonts;
}

const vector<string>& TextEngine::getFontVariants(const string& sFontName)
{
    PangoFontFamily * pCurFamily = getFontFamily(sFontName);
    PangoFontFace ** ppFaces;
    int numFaces;
    pango_font_family_list_faces (pCurFamily, &ppFaces, &numFaces);
    static vector<string> sVariants;
    for (int i = 0; i < numFaces; ++i) {
        sVariants.push_back(pango_font_face_get_face_name(ppFaces[i]));
    }
    g_free(ppFaces);
    return sVariants;
}

PangoFontDescription * TextEngine::getFontDescription(const string& sFamily,
        const string& sVariant)
{
    PangoFontDescription* pDescription;
    FontDescriptionCache::iterator it;
    it = m_FontDescriptionCache.find(pair<string, string>(sFamily, sVariant));
    if (it == m_FontDescriptionCache.end()) {
        PangoFontFamily * pFamily;
        bool bFamilyFound = true;
        try {
            pFamily = getFontFamily(sFamily);
        } catch (Exception&) {
            if (m_sFontsNotFound.find(sFamily) == m_sFontsNotFound.end()) {
                AVG_TRACE(Logger::WARNING, "Could not find font face " << sFamily <<
                        ". Using sans instead.");
                m_sFontsNotFound.insert(sFamily);
            }
            bFamilyFound = false;
            pFamily = getFontFamily("sans");
        }
        PangoFontFace ** ppFaces;
        int numFaces;
        pango_font_family_list_faces(pFamily, &ppFaces, &numFaces);
        PangoFontFace * pFace = 0;
        if (sVariant == "") {
            pFace = ppFaces[0];
        } else {
            for (int i = 0; i < numFaces; ++i) {
                if (equalIgnoreCase(pango_font_face_get_face_name(ppFaces[i]), sVariant))
                {
                    pFace = ppFaces[i];
                }
            }
        }
        if (!pFace) {
            pFace = ppFaces[0];
            if (bFamilyFound) {
                pair<string, string> variant(sFamily, sVariant);
                if (m_VariantsNotFound.find(variant) == m_VariantsNotFound.end()) {
                    m_VariantsNotFound.insert(variant);
                    AVG_TRACE(Logger::WARNING, "Could not find font variant "
                            << sFamily << ":" << sVariant << ". Using " <<
                            pango_font_face_get_face_name(pFace) << " instead.");
                }
            }
        }
        g_free(ppFaces);
        pDescription = pango_font_face_describe(pFace);
        m_FontDescriptionCache[pair<string, string>(sFamily, sVariant)] =
                pDescription;
    } else {
        pDescription = it->second;
    }
    return pango_font_description_copy(pDescription);
}

void GLibLogFunc(const gchar *log_domain, GLogLevelFlags log_level,
        const gchar *message, gpointer unused_data)
{
#ifndef WIN32
    string s = "Pango ";
    if (log_level & G_LOG_LEVEL_ERROR) {
        s += "error: ";
    } else if (log_level & G_LOG_LEVEL_CRITICAL) {
        s += string("critical: ")+message;
        AVG_TRACE(Logger::ERROR, s);
        return;
    } else if (log_level & G_LOG_LEVEL_WARNING) {
        s += "warning: ";
    } else if (log_level & G_LOG_LEVEL_MESSAGE) {
        s += "message: ";
    } else if (log_level & G_LOG_LEVEL_INFO) {
        s += "info: ";
    } else if (log_level & G_LOG_LEVEL_DEBUG) {
        s += "debug: ";
    }
    s += message;
    AVG_TRACE(Logger::WARNING, s);
#endif
}

void TextEngine::initFonts()
{
    g_type_init();

    std::vector<std::string> fontConfPathPrefixList;
#ifndef WIN32
    fontConfPathPrefixList.push_back("/");
    fontConfPathPrefixList.push_back("/usr/local/");
    fontConfPathPrefixList.push_back("/opt/local/");
#endif
    fontConfPathPrefixList.push_back(getAvgLibPath());

    std::string sFontConfPath;
    for (size_t i = 0; i < fontConfPathPrefixList.size(); ++i) {
        sFontConfPath = fontConfPathPrefixList[i] + "etc/fonts/fonts.conf";
        if (fileExists(sFontConfPath)) {
            break;
        }
    }

    FcConfig * pConfig = FcConfigCreate();
    int ok = (int)FcConfigParseAndLoad(pConfig,
            (const FcChar8 *)(sFontConfPath.c_str()), true);
    checkFontError(ok, string("Font error: could not load config file ")+sFontConfPath);
    ok = (int)FcConfigBuildFonts(pConfig);
    checkFontError(ok, string("Font error: FcConfigBuildFonts failed."));
    ok = (int)FcConfigSetCurrent(pConfig);
    checkFontError(ok, string("Font error: FcConfigSetCurrent failed."));
    for(std::vector<std::string>::const_iterator it = m_sFontDirs.begin();
            it != m_sFontDirs.end(); ++it)
    {
        ok = (int)FcConfigAppFontAddDir(pConfig, (const FcChar8 *)it->c_str());
        checkFontError(ok, string("Font error: FcConfigAppFontAddDir("
                    + *it + ") failed."));
    }

    /*
       FcStrList * pCacheDirs = FcConfigGetCacheDirs(pConfig);
       FcChar8 * pDir;
       do {
       pDir = FcStrListNext(pCacheDirs);
       if (pDir) {
       cerr << pDir << endl;
       }
       } while (pDir);
     */
    g_log_set_default_handler(GLibLogFunc, 0);
}

PangoFontFamily * TextEngine::getFontFamily(const string& sFamily)
{
    PangoFontFamily * pFamily = 0;
    AVG_ASSERT(m_NumFontFamilies != 0);
    for (int i=0; i<m_NumFontFamilies; ++i) {
        if (equalIgnoreCase(pango_font_family_get_name(m_ppFontFamilies[i]), sFamily)) {
            pFamily = m_ppFontFamilies[i];
        }
    }
    if (!pFamily) {
        throw(Exception(AVG_ERR_INVALID_ARGS,
                "getFontFamily: Font family "+sFamily+" not found."));
    }
    return pFamily;
}

void TextEngine::checkFontError(int ok, const string& sMsg)
{
    if (ok == 0) {
        throw Exception(AVG_ERR_FONT_INIT_FAILED, sMsg);
    }
}

}
<commit_msg>Added default font options.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  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
//
//  Current versions can be found at www.libavg.de
//

#include "TextEngine.h"

#include "../base/Logger.h"
#include "../base/OSHelper.h"
#include "../base/Exception.h"
#include "../base/FileHelper.h"
#include "../base/StringHelper.h"

#include <fontconfig/fontconfig.h>
#include <algorithm>

namespace avg {

using namespace std;

TextEngine& TextEngine::get(bool bHint)
{
    if (bHint) {
        static TextEngine s_Instance(true);
        return s_Instance;
    } else {
        static TextEngine s_Instance(false);
        return s_Instance;
    }
}

TextEngine::TextEngine(bool bHint)
    : m_bHint(bHint)
{
    m_sFontDirs.push_back("fonts/");
    init();
}

TextEngine::~TextEngine()
{
    deinit();
}

void TextEngine::init()
{
    g_type_init();
    m_pFontMap = PANGO_CAIRO_FONT_MAP(pango_cairo_font_map_new_for_font_type(
            CAIRO_FONT_TYPE_FT));
    pango_cairo_font_map_set_resolution(m_pFontMap, 72);

    m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
    m_pCairo = cairo_create(m_pCairoSurface);
    m_pPangoContext = pango_cairo_create_context(m_pCairo);

    pango_context_set_language(m_pPangoContext,
            pango_language_from_string ("en_US"));
    pango_context_set_base_dir(m_pPangoContext, PANGO_DIRECTION_LTR);

    cairo_font_options_t*  pFontOptions = cairo_font_options_create();
//    cairo_font_options_set_antialias(pFontOptions, CAIRO_ANTIALIAS_GRAY);
    cairo_font_options_set_hint_style(pFontOptions, CAIRO_HINT_STYLE_SLIGHT);
    cairo_font_options_set_hint_metrics(pFontOptions, CAIRO_HINT_METRICS_OFF);
    pango_cairo_context_set_font_options(m_pPangoContext, pFontOptions);

    cairo_font_options_destroy(pFontOptions);

    initFonts();

    string sOldLang = "";
    getEnv("LC_CTYPE", sOldLang);
    setEnv("LC_CTYPE", "en-us");
    pango_font_map_list_families(PANGO_FONT_MAP(m_pFontMap), &m_ppFontFamilies,
            &m_NumFontFamilies);
    setEnv("LC_CTYPE", sOldLang);
    for (int i = 0; i < m_NumFontFamilies; ++i) {
        m_sFonts.push_back(pango_font_family_get_name(m_ppFontFamilies[i]));
    }
    sort(m_sFonts.begin(), m_sFonts.end());
}

void TextEngine::deinit()
{
    g_object_unref(m_pPangoContext);
    m_sFonts.clear();
    g_free(m_ppFontFamilies);
    cairo_surface_destroy(m_pCairoSurface);
    cairo_destroy(m_pCairo);
    g_object_unref(m_pFontMap);
}

void TextEngine::addFontDir(const std::string& sDir)
{
    deinit();
    m_sFontDirs.push_back(sDir);
    init();
}

PangoContext * TextEngine::getPangoContext()
{
    return m_pPangoContext;
}

const vector<string>& TextEngine::getFontFamilies()
{
    return m_sFonts;
}

const vector<string>& TextEngine::getFontVariants(const string& sFontName)
{
    PangoFontFamily * pCurFamily = getFontFamily(sFontName);
    PangoFontFace ** ppFaces;
    int numFaces;
    pango_font_family_list_faces (pCurFamily, &ppFaces, &numFaces);
    static vector<string> sVariants;
    for (int i = 0; i < numFaces; ++i) {
        sVariants.push_back(pango_font_face_get_face_name(ppFaces[i]));
    }
    g_free(ppFaces);
    return sVariants;
}

PangoFontDescription * TextEngine::getFontDescription(const string& sFamily,
        const string& sVariant)
{
    PangoFontDescription* pDescription;
    FontDescriptionCache::iterator it;
    it = m_FontDescriptionCache.find(pair<string, string>(sFamily, sVariant));
    if (it == m_FontDescriptionCache.end()) {
        PangoFontFamily * pFamily;
        bool bFamilyFound = true;
        try {
            pFamily = getFontFamily(sFamily);
        } catch (Exception&) {
            if (m_sFontsNotFound.find(sFamily) == m_sFontsNotFound.end()) {
                AVG_TRACE(Logger::WARNING, "Could not find font face " << sFamily <<
                        ". Using sans instead.");
                m_sFontsNotFound.insert(sFamily);
            }
            bFamilyFound = false;
            pFamily = getFontFamily("sans");
        }
        PangoFontFace ** ppFaces;
        int numFaces;
        pango_font_family_list_faces(pFamily, &ppFaces, &numFaces);
        PangoFontFace * pFace = 0;
        if (sVariant == "") {
            pFace = ppFaces[0];
        } else {
            for (int i = 0; i < numFaces; ++i) {
                if (equalIgnoreCase(pango_font_face_get_face_name(ppFaces[i]), sVariant))
                {
                    pFace = ppFaces[i];
                }
            }
        }
        if (!pFace) {
            pFace = ppFaces[0];
            if (bFamilyFound) {
                pair<string, string> variant(sFamily, sVariant);
                if (m_VariantsNotFound.find(variant) == m_VariantsNotFound.end()) {
                    m_VariantsNotFound.insert(variant);
                    AVG_TRACE(Logger::WARNING, "Could not find font variant "
                            << sFamily << ":" << sVariant << ". Using " <<
                            pango_font_face_get_face_name(pFace) << " instead.");
                }
            }
        }
        g_free(ppFaces);
        pDescription = pango_font_face_describe(pFace);
        m_FontDescriptionCache[pair<string, string>(sFamily, sVariant)] =
                pDescription;
    } else {
        pDescription = it->second;
    }
    return pango_font_description_copy(pDescription);
}

void GLibLogFunc(const gchar *log_domain, GLogLevelFlags log_level,
        const gchar *message, gpointer unused_data)
{
#ifndef WIN32
    string s = "Pango ";
    if (log_level & G_LOG_LEVEL_ERROR) {
        s += "error: ";
    } else if (log_level & G_LOG_LEVEL_CRITICAL) {
        s += string("critical: ")+message;
        AVG_TRACE(Logger::ERROR, s);
        return;
    } else if (log_level & G_LOG_LEVEL_WARNING) {
        s += "warning: ";
    } else if (log_level & G_LOG_LEVEL_MESSAGE) {
        s += "message: ";
    } else if (log_level & G_LOG_LEVEL_INFO) {
        s += "info: ";
    } else if (log_level & G_LOG_LEVEL_DEBUG) {
        s += "debug: ";
    }
    s += message;
    AVG_TRACE(Logger::WARNING, s);
#endif
}

void TextEngine::initFonts()
{
    g_type_init();

    std::vector<std::string> fontConfPathPrefixList;
#ifndef WIN32
    fontConfPathPrefixList.push_back("/");
    fontConfPathPrefixList.push_back("/usr/local/");
    fontConfPathPrefixList.push_back("/opt/local/");
#endif
    fontConfPathPrefixList.push_back(getAvgLibPath());

    std::string sFontConfPath;
    for (size_t i = 0; i < fontConfPathPrefixList.size(); ++i) {
        sFontConfPath = fontConfPathPrefixList[i] + "etc/fonts/fonts.conf";
        if (fileExists(sFontConfPath)) {
            break;
        }
    }

    FcConfig * pConfig = FcConfigCreate();
    int ok = (int)FcConfigParseAndLoad(pConfig,
            (const FcChar8 *)(sFontConfPath.c_str()), true);
    checkFontError(ok, string("Font error: could not load config file ")+sFontConfPath);
    ok = (int)FcConfigBuildFonts(pConfig);
    checkFontError(ok, string("Font error: FcConfigBuildFonts failed."));
    ok = (int)FcConfigSetCurrent(pConfig);
    checkFontError(ok, string("Font error: FcConfigSetCurrent failed."));
    for(std::vector<std::string>::const_iterator it = m_sFontDirs.begin();
            it != m_sFontDirs.end(); ++it)
    {
        ok = (int)FcConfigAppFontAddDir(pConfig, (const FcChar8 *)it->c_str());
        checkFontError(ok, string("Font error: FcConfigAppFontAddDir("
                    + *it + ") failed."));
    }

    /*
       FcStrList * pCacheDirs = FcConfigGetCacheDirs(pConfig);
       FcChar8 * pDir;
       do {
       pDir = FcStrListNext(pCacheDirs);
       if (pDir) {
       cerr << pDir << endl;
       }
       } while (pDir);
     */
    g_log_set_default_handler(GLibLogFunc, 0);
}

PangoFontFamily * TextEngine::getFontFamily(const string& sFamily)
{
    PangoFontFamily * pFamily = 0;
    AVG_ASSERT(m_NumFontFamilies != 0);
    for (int i=0; i<m_NumFontFamilies; ++i) {
        if (equalIgnoreCase(pango_font_family_get_name(m_ppFontFamilies[i]), sFamily)) {
            pFamily = m_ppFontFamilies[i];
        }
    }
    if (!pFamily) {
        throw(Exception(AVG_ERR_INVALID_ARGS,
                "getFontFamily: Font family "+sFamily+" not found."));
    }
    return pFamily;
}

void TextEngine::checkFontError(int ok, const string& sMsg)
{
    if (ok == 0) {
        throw Exception(AVG_ERR_FONT_INIT_FAILED, sMsg);
    }
}

}
<|endoftext|>


<commit_before>#include <vector>
#include <string>
#include <limits>
#include <memory>
#include <iostream>

#include <arpa/inet.h>

#include "caf/all.hpp"
#include "caf/io/all.hpp"

CAF_PUSH_WARNINGS
#include "pingpong.pb.h"
CAF_POP_WARNINGS

using namespace std;
using namespace caf;
using namespace caf::io;

void print_on_exit(const actor& hdl, const std::string& name) {
  hdl->attach_functor([=](abstract_actor* ptr, uint32_t reason) {
    aout(ptr) << name << " exited with reason " << reason << endl;
  });
}

behavior ping(event_based_actor* self, size_t num_pings) {
  auto count = make_shared<size_t>(0);
  return {
    on(atom("kickoff"), arg_match) >> [=](const actor& pong) {
      self->send(pong, atom("ping"), 1);
      self->become (
        on(atom("pong"), arg_match) >> [=](int value) -> message {
          if (++*count >= num_pings) self->quit();
          return make_message(atom("ping"), value + 1);
        }
      );
    }
  };
}

behavior pong() {
  return {
    on(atom("ping"), arg_match) >> [](int value) {
      return make_message(atom("pong"), value);
    }
  };
}

void protobuf_io(broker* self, connection_handle hdl, const actor& buddy) {
  self->monitor(buddy);
  auto write = [=](const org::libcppa::PingOrPong& p) {
    string buf = p.SerializeAsString();
    int32_t s = htonl(static_cast<int32_t>(buf.size()));
    self->write(hdl, sizeof(int32_t), &s);
    self->write(hdl, buf.size(), buf.data());
    self->flush(hdl);
  };
  message_handler default_bhvr = {
    [=](const connection_closed_msg&) {
      aout(self) << "connection closed" << endl;
      self->send_exit(buddy, exit_reason::remote_link_unreachable);
      self->quit(exit_reason::remote_link_unreachable);
    },
    on(atom("ping"), arg_match) >> [=](int i) {
      aout(self) << "'ping' " << i << endl;
      org::libcppa::PingOrPong p;
      p.mutable_ping()->set_id(i);
      write(p);
    },
    on(atom("pong"), arg_match) >> [=](int i) {
      aout(self) << "'pong' " << i << endl;
      org::libcppa::PingOrPong p;
      p.mutable_pong()->set_id(i);
      write(p);
    },
    [=](const down_msg& dm) {
      if (dm.source == buddy) {
        aout(self) << "our buddy is down" << endl;
        self->quit(dm.reason);
      }
    },
    others >> [=] {
      cout << "unexpected: " << to_string(self->current_message()) << endl;
    }
  };
  auto await_protobuf_data = message_handler {
    [=](const new_data_msg& msg) {
      org::libcppa::PingOrPong p;
      p.ParseFromArray(msg.buf.data(), static_cast<int>(msg.buf.size()));
      if (p.has_ping()) {
        self->send(buddy, atom("ping"), p.ping().id());
      }
      else if (p.has_pong()) {
        self->send(buddy, atom("pong"), p.pong().id());
      }
      else {
        self->quit(exit_reason::user_shutdown);
        cerr << "neither Ping nor Pong!" << endl;
      }
      // receive next length prefix
      self->configure_read(hdl, receive_policy::exactly(sizeof(int32_t)));
      self->unbecome();
    }
  }.or_else(default_bhvr);
  auto await_length_prefix = message_handler {
    [=](const new_data_msg& msg) {
      int32_t num_bytes;
      memcpy(&num_bytes, msg.buf.data(), sizeof(int32_t));
      num_bytes = htonl(num_bytes);
      if (num_bytes < 0 || num_bytes > (1024 * 1024)) {
        aout(self) << "someone is trying something nasty" << endl;
        self->quit(exit_reason::user_shutdown);
        return;
      }
      // receive protobuf data
      auto nb = static_cast<size_t>(num_bytes);
      self->configure_read(hdl, receive_policy::exactly(nb));
      self->become(keep_behavior, await_protobuf_data);
    }
  }.or_else(default_bhvr);
  // initial setup
  self->configure_read(hdl, receive_policy::exactly(sizeof(int32_t)));
  self->become(await_length_prefix);
}

behavior server(broker* self, actor buddy) {
  aout(self) << "server is running" << endl;
  return {
    [=](const new_connection_msg& msg) {
      aout(self) << "server accepted new connection" << endl;
      auto io_actor = self->fork(protobuf_io, msg.handle, buddy);
      print_on_exit(io_actor, "protobuf_io");
      // only accept 1 connection in our example
      self->quit();
    },
    others >> [=] {
      cout << "unexpected: " << to_string(self->current_message()) << endl;
    }
  };
}

optional<uint16_t> as_u16(const std::string& str) {
  return static_cast<uint16_t>(stoul(str));
}

int main(int argc, char** argv) {
  message_builder{argv + 1, argv + argc}.apply({
    on("-s", as_u16) >> [&](uint16_t port) {
      cout << "run in server mode" << endl;
      auto pong_actor = spawn(pong);
      auto sever_actor = spawn_io_server(server, port, pong_actor);
      print_on_exit(sever_actor, "server");
      print_on_exit(pong_actor, "pong");
    },
    on("-c", val<string>, as_u16) >> [&](const string& host, uint16_t port) {
      auto ping_actor = spawn(ping, 20);
      auto io_actor = spawn_io_client(protobuf_io, host, port, ping_actor);
      print_on_exit(io_actor, "protobuf_io");
      print_on_exit(ping_actor, "ping");
      send_as(io_actor, ping_actor, atom("kickoff"), io_actor);
    },
    others >> [] {
      cerr << "use with eihter '-s PORT' as server or "
          "'-c HOST PORT' as client"
           << endl;
    }
  });
  await_all_actors_done();
  shutdown();
}
<commit_msg>Replace optional with maybe in protobuf example<commit_after>#include <vector>
#include <string>
#include <limits>
#include <memory>
#include <iostream>

#include <arpa/inet.h>

#include "caf/all.hpp"
#include "caf/io/all.hpp"

CAF_PUSH_WARNINGS
#include "pingpong.pb.h"
CAF_POP_WARNINGS

using namespace std;
using namespace caf;
using namespace caf::io;

void print_on_exit(const actor& hdl, const std::string& name) {
  hdl->attach_functor([=](abstract_actor* ptr, uint32_t reason) {
    aout(ptr) << name << " exited with reason " << reason << endl;
  });
}

behavior ping(event_based_actor* self, size_t num_pings) {
  auto count = make_shared<size_t>(0);
  return {
    on(atom("kickoff"), arg_match) >> [=](const actor& pong) {
      self->send(pong, atom("ping"), 1);
      self->become (
        on(atom("pong"), arg_match) >> [=](int value) -> message {
          if (++*count >= num_pings) self->quit();
          return make_message(atom("ping"), value + 1);
        }
      );
    }
  };
}

behavior pong() {
  return {
    on(atom("ping"), arg_match) >> [](int value) {
      return make_message(atom("pong"), value);
    }
  };
}

void protobuf_io(broker* self, connection_handle hdl, const actor& buddy) {
  self->monitor(buddy);
  auto write = [=](const org::libcppa::PingOrPong& p) {
    string buf = p.SerializeAsString();
    int32_t s = htonl(static_cast<int32_t>(buf.size()));
    self->write(hdl, sizeof(int32_t), &s);
    self->write(hdl, buf.size(), buf.data());
    self->flush(hdl);
  };
  message_handler default_bhvr = {
    [=](const connection_closed_msg&) {
      aout(self) << "connection closed" << endl;
      self->send_exit(buddy, exit_reason::remote_link_unreachable);
      self->quit(exit_reason::remote_link_unreachable);
    },
    on(atom("ping"), arg_match) >> [=](int i) {
      aout(self) << "'ping' " << i << endl;
      org::libcppa::PingOrPong p;
      p.mutable_ping()->set_id(i);
      write(p);
    },
    on(atom("pong"), arg_match) >> [=](int i) {
      aout(self) << "'pong' " << i << endl;
      org::libcppa::PingOrPong p;
      p.mutable_pong()->set_id(i);
      write(p);
    },
    [=](const down_msg& dm) {
      if (dm.source == buddy) {
        aout(self) << "our buddy is down" << endl;
        self->quit(dm.reason);
      }
    },
    others >> [=] {
      cout << "unexpected: " << to_string(self->current_message()) << endl;
    }
  };
  auto await_protobuf_data = message_handler {
    [=](const new_data_msg& msg) {
      org::libcppa::PingOrPong p;
      p.ParseFromArray(msg.buf.data(), static_cast<int>(msg.buf.size()));
      if (p.has_ping()) {
        self->send(buddy, atom("ping"), p.ping().id());
      }
      else if (p.has_pong()) {
        self->send(buddy, atom("pong"), p.pong().id());
      }
      else {
        self->quit(exit_reason::user_shutdown);
        cerr << "neither Ping nor Pong!" << endl;
      }
      // receive next length prefix
      self->configure_read(hdl, receive_policy::exactly(sizeof(int32_t)));
      self->unbecome();
    }
  }.or_else(default_bhvr);
  auto await_length_prefix = message_handler {
    [=](const new_data_msg& msg) {
      int32_t num_bytes;
      memcpy(&num_bytes, msg.buf.data(), sizeof(int32_t));
      num_bytes = htonl(num_bytes);
      if (num_bytes < 0 || num_bytes > (1024 * 1024)) {
        aout(self) << "someone is trying something nasty" << endl;
        self->quit(exit_reason::user_shutdown);
        return;
      }
      // receive protobuf data
      auto nb = static_cast<size_t>(num_bytes);
      self->configure_read(hdl, receive_policy::exactly(nb));
      self->become(keep_behavior, await_protobuf_data);
    }
  }.or_else(default_bhvr);
  // initial setup
  self->configure_read(hdl, receive_policy::exactly(sizeof(int32_t)));
  self->become(await_length_prefix);
}

behavior server(broker* self, actor buddy) {
  aout(self) << "server is running" << endl;
  return {
    [=](const new_connection_msg& msg) {
      aout(self) << "server accepted new connection" << endl;
      auto io_actor = self->fork(protobuf_io, msg.handle, buddy);
      print_on_exit(io_actor, "protobuf_io");
      // only accept 1 connection in our example
      self->quit();
    },
    others >> [=] {
      cout << "unexpected: " << to_string(self->current_message()) << endl;
    }
  };
}

maybe<uint16_t> as_u16(const std::string& str) {
  return static_cast<uint16_t>(stoul(str));
}

int main(int argc, char** argv) {
  message_builder{argv + 1, argv + argc}.apply({
    on("-s", as_u16) >> [&](uint16_t port) {
      cout << "run in server mode" << endl;
      auto pong_actor = spawn(pong);
      auto sever_actor = spawn_io_server(server, port, pong_actor);
      print_on_exit(sever_actor, "server");
      print_on_exit(pong_actor, "pong");
    },
    on("-c", val<string>, as_u16) >> [&](const string& host, uint16_t port) {
      auto ping_actor = spawn(ping, 20);
      auto io_actor = spawn_io_client(protobuf_io, host, port, ping_actor);
      print_on_exit(io_actor, "protobuf_io");
      print_on_exit(ping_actor, "ping");
      send_as(io_actor, ping_actor, atom("kickoff"), io_actor);
    },
    others >> [] {
      cerr << "use with eihter '-s PORT' as server or "
          "'-c HOST PORT' as client"
           << endl;
    }
  });
  await_all_actors_done();
  shutdown();
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
/*****************************************************************************
* User of this library should read the documentation
* in the messaging.h file.
******************************************************************************/
#include <sstream>
using std::ostringstream ;

#include <iostream>
using std::endl ;

#include <vector>
using std::vector ;

#include <string>
using std::string ;

#include <algorithm>
using std::remove ;

#include "MessageDispatcher.h"

#include "MessageHandler.h"
#include "ConsoleMessageHandler.h"

#include <sofa/core/objectmodel/Base.h>

#include <sofa/helper/logging/DefaultStyleMessageFormatter.h>
using sofa::helper::logging::DefaultStyleMessageFormatter;

#include <mutex>
using std::lock_guard ;
using std::mutex;

namespace sofa
{

namespace helper
{

namespace logging
{

std::vector<MessageHandler*> getDefaultMessageHandlers(){
    std::vector<MessageHandler*> messageHandlers;
    static ConsoleMessageHandler s_consoleMessageHandler(&DefaultStyleMessageFormatter::getInstance());
    messageHandlers.push_back(&s_consoleMessageHandler);
    return messageHandlers;
}

class MessageDispatcherImpl
{
public:
    std::vector<MessageHandler*> m_messageHandlers = getDefaultMessageHandlers();

    std::vector<MessageHandler*>& getHandlers()
    {
        return m_messageHandlers ;
    }

    int addHandler(MessageHandler* o)
    {
        if( std::find(m_messageHandlers.begin(), m_messageHandlers.end(), o) == m_messageHandlers.end())
        {
            m_messageHandlers.push_back(o) ;
            return (int)(m_messageHandlers.size()-1);
        }
        return -1;
    }

    int rmHandler(MessageHandler* o)
    {
        m_messageHandlers.erase(remove(m_messageHandlers.begin(), m_messageHandlers.end(), o), m_messageHandlers.end());
        return (int)(m_messageHandlers.size()-1);
    }

    void clearHandlers()
    {
        m_messageHandlers.clear() ;
    }

    void process(sofa::helper::logging::Message& m)
    {
        for( size_t i=0 ; i<m_messageHandlers.size() ; i++ )
            m_messageHandlers[i]->process(m) ;
    }
};

MessageDispatcherImpl s_messagedispatcher ;

mutex& getMutex(){
    static mutex s_dispatchermutex ;
    return s_dispatchermutex ;
}

/*static std::vector<MessageHandler*> setDefaultMessageHandler()
{
    /// This static function of the dispatcher has to be protected against concurent access
    /// This is done by a mutex and a scoped_guard as in Use the http://en.cppreference.com/w/cpp/thread/lock_guard
    //lock_guard<mutex> guard(s_dispatchermutex) ;

    std::vector<MessageHandler*> messageHandlers;
    messageHandlers.push_back(&s_consoleMessageHandler);
    return messageHandlers;
}*/

std::vector<MessageHandler*>& MessageDispatcher::getHandlers()
{
    lock_guard<mutex> guard(getMutex()) ;

    return s_messagedispatcher.getHandlers();
}

int MessageDispatcher::addHandler(MessageHandler* o){
    lock_guard<mutex> guard(getMutex()) ;

    return s_messagedispatcher.addHandler(o);
}

int MessageDispatcher::rmHandler(MessageHandler* o){
    lock_guard<mutex> guard(getMutex()) ;

    return s_messagedispatcher.rmHandler(o);
}

void MessageDispatcher::clearHandlers(){
    lock_guard<mutex> guard(getMutex()) ;

    s_messagedispatcher.clearHandlers();
}

void MessageDispatcher::process(sofa::helper::logging::Message& m){
    lock_guard<mutex> guard(getMutex()) ;

    s_messagedispatcher.process(m);
}

MessageDispatcher::LoggerStream MessageDispatcher::log(Message::Class mclass, Message::Type type, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return MessageDispatcher::LoggerStream( mclass, type, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::log(Message::Class mclass, Message::Type type, const sofa::core::objectmodel::Base* sender, const  FileInfo::SPtr& fileInfo) {
    return MessageDispatcher::LoggerStream(mclass, type, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::info(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Info, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::info(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Info, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::deprecated(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Deprecated, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::deprecated(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Deprecated, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::warning(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Warning, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::warning(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Warning, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::error(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Error, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::error(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Error, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::fatal(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Fatal, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::fatal(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Fatal, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::advice(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Advice, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::advice(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Advice, sender, fileInfo);
}

MessageDispatcher::LoggerStream::LoggerStream(Message::Class mclass, Message::Type type,
             const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo)
    : m_message( mclass
                 , type
                 , sender->getClassName()
                 // temporary, until Base object reference kept in the message itself ->
                 // (mattn) not sure it is a good idea, the Message could be kept after the Base is deleted
                 // TODO(dmarchal): by converting this to a string we are not able anymore to
                 // display rich information like the component name or location in the scene tree while these
                 // information are really usefull. I have to make small experiment to see what could be a nice
                 // approach without too much overhead.
                 , fileInfo
                 , ComponentInfo::SPtr( new ComponentInfo(sender)) )
{
}

MessageDispatcher::LoggerStream::~LoggerStream()
{
    if ( !m_message.empty() ) MessageDispatcher::process(m_message);
}

} // logging
} // helper
} // sofa

<commit_msg>[SofaKernel] WIP Fix the VS2013 problem with static mutex<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
/*****************************************************************************
* User of this library should read the documentation
* in the messaging.h file.
******************************************************************************/
#include <sstream>
using std::ostringstream ;

#include <iostream>
using std::endl ;

#include <vector>
using std::vector ;

#include <string>
using std::string ;

#include <algorithm>
using std::remove ;

#include "MessageDispatcher.h"

#include "MessageHandler.h"
#include "ConsoleMessageHandler.h"

#include <sofa/core/objectmodel/Base.h>

#include <sofa/helper/logging/DefaultStyleMessageFormatter.h>
using sofa::helper::logging::DefaultStyleMessageFormatter;

#include <mutex>
using std::lock_guard ;
using std::mutex;

namespace sofa
{

namespace helper
{

namespace logging
{

std::vector<MessageHandler*> getDefaultMessageHandlers(){
    std::vector<MessageHandler*> messageHandlers;
    static ConsoleMessageHandler s_consoleMessageHandler(&DefaultStyleMessageFormatter::getInstance());
    messageHandlers.push_back(&s_consoleMessageHandler);
    return messageHandlers;
}

class MessageDispatcherImpl
{
public:
    mutex dispatchermutex ;

    std::vector<MessageHandler*> m_messageHandlers = getDefaultMessageHandlers();

    std::vector<MessageHandler*>& getHandlers()
    {
        return m_messageHandlers ;
    }

    int addHandler(MessageHandler* o)
    {
        if( std::find(m_messageHandlers.begin(), m_messageHandlers.end(), o) == m_messageHandlers.end())
        {
            m_messageHandlers.push_back(o) ;
            return (int)(m_messageHandlers.size()-1);
        }
        return -1;
    }

    int rmHandler(MessageHandler* o)
    {
        m_messageHandlers.erase(remove(m_messageHandlers.begin(), m_messageHandlers.end(), o), m_messageHandlers.end());
        return (int)(m_messageHandlers.size()-1);
    }

    void clearHandlers()
    {
        m_messageHandlers.clear() ;
    }

    void process(sofa::helper::logging::Message& m)
    {
        for( size_t i=0 ; i<m_messageHandlers.size() ; i++ )
            m_messageHandlers[i]->process(m) ;
    }
};

MessageDispatcherImpl s_messagedispatcher ;

mutex& getMutex(){
    return s_messagedispatcher.dispatchermutex ;
}

/*static std::vector<MessageHandler*> setDefaultMessageHandler()
{
    /// This static function of the dispatcher has to be protected against concurent access
    /// This is done by a mutex and a scoped_guard as in Use the http://en.cppreference.com/w/cpp/thread/lock_guard
    //lock_guard<mutex> guard(s_dispatchermutex) ;

    std::vector<MessageHandler*> messageHandlers;
    messageHandlers.push_back(&s_consoleMessageHandler);
    return messageHandlers;
}*/

std::vector<MessageHandler*>& MessageDispatcher::getHandlers()
{
    lock_guard<mutex> guard(getMutex()) ;

    return s_messagedispatcher.getHandlers();
}

int MessageDispatcher::addHandler(MessageHandler* o){
    lock_guard<mutex> guard(getMutex()) ;

    return s_messagedispatcher.addHandler(o);
}

int MessageDispatcher::rmHandler(MessageHandler* o){
    lock_guard<mutex> guard(getMutex()) ;

    return s_messagedispatcher.rmHandler(o);
}

void MessageDispatcher::clearHandlers(){
    lock_guard<mutex> guard(getMutex()) ;

    s_messagedispatcher.clearHandlers();
}

void MessageDispatcher::process(sofa::helper::logging::Message& m){
    lock_guard<mutex> guard(getMutex()) ;

    s_messagedispatcher.process(m);
}

MessageDispatcher::LoggerStream MessageDispatcher::log(Message::Class mclass, Message::Type type, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return MessageDispatcher::LoggerStream( mclass, type, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::log(Message::Class mclass, Message::Type type, const sofa::core::objectmodel::Base* sender, const  FileInfo::SPtr& fileInfo) {
    return MessageDispatcher::LoggerStream(mclass, type, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::info(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Info, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::info(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Info, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::deprecated(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Deprecated, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::deprecated(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Deprecated, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::warning(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Warning, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::warning(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Warning, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::error(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Error, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::error(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Error, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::fatal(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Fatal, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::fatal(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Fatal, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::advice(Message::Class mclass, const std::string& sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Advice, sender, fileInfo);
}

MessageDispatcher::LoggerStream MessageDispatcher::advice(Message::Class mclass, const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo) {
    return log(mclass, Message::Advice, sender, fileInfo);
}

MessageDispatcher::LoggerStream::LoggerStream(Message::Class mclass, Message::Type type,
             const sofa::core::objectmodel::Base* sender, const FileInfo::SPtr& fileInfo)
    : m_message( mclass
                 , type
                 , sender->getClassName()
                 // temporary, until Base object reference kept in the message itself ->
                 // (mattn) not sure it is a good idea, the Message could be kept after the Base is deleted
                 // TODO(dmarchal): by converting this to a string we are not able anymore to
                 // display rich information like the component name or location in the scene tree while these
                 // information are really usefull. I have to make small experiment to see what could be a nice
                 // approach without too much overhead.
                 , fileInfo
                 , ComponentInfo::SPtr( new ComponentInfo(sender)) )
{
}

MessageDispatcher::LoggerStream::~LoggerStream()
{
    if ( !m_message.empty() ) MessageDispatcher::process(m_message);
}

} // logging
} // helper
} // sofa

<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib 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 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_circle.cpp implementation of the GLC_Circle class.

#include "glc_circle.h"
#include "../glc_openglexception.h"
#include "../glc_state.h"

using namespace glc;
//////////////////////////////////////////////////////////////////////
// Constructor destructor
//////////////////////////////////////////////////////////////////////

GLC_Circle::GLC_Circle(const double &dRadius, double Angle)
:GLC_VboGeom("Circle", true)
, m_Radius(dRadius)
, m_nDiscret(GLC_DISCRET)
, m_dAngle(Angle)
, m_Step(0)
, m_SimpleGeomEngine()
{

}

GLC_Circle::GLC_Circle(const GLC_Circle& sourceCircle)
:GLC_VboGeom(sourceCircle)
, m_Radius(sourceCircle.m_Radius)
, m_nDiscret(sourceCircle.m_nDiscret)
, m_dAngle(sourceCircle.m_dAngle)
, m_SimpleGeomEngine(sourceCircle.m_SimpleGeomEngine)
{
	// Copy inner material hash
	MaterialHash::const_iterator i= m_MaterialHash.begin();
	MaterialHash newMaterialHash;
    while (i != m_MaterialHash.constEnd())
    {
        // update inner material use table
    	i.value()->delGLC_Geom(id());
    	GLC_Material* pNewMaterial= new GLC_Material(*(i.value()));
    	newMaterialHash.insert(pNewMaterial->id(), pNewMaterial);
    	pNewMaterial->addGLC_Geom(this);
         ++i;
    }
    m_MaterialHash= newMaterialHash;
}
GLC_Circle::~GLC_Circle()
{

}
//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Return Circle Discretion
int GLC_Circle::getDiscretion(void) const
{
	return m_nDiscret;
}
// Return Circle radius
double GLC_Circle::getRadius(void) const
{
	return m_Radius;
}
// return Circle diameter
double GLC_Circle::getDiameter(void) const
{
	return 2 * m_Radius;
}

// return the circle bounding box
GLC_BoundingBox& GLC_Circle::boundingBox(void)
{
	if (NULL == m_pBoundingBox)
	{
		m_pBoundingBox= new GLC_BoundingBox();

		GLC_Point3d lower(-m_Radius, -m_Radius, -2.0 * EPSILON);
		GLC_Point3d upper(m_Radius, m_Radius, 2.0 * EPSILON);
		m_pBoundingBox->combine(lower);
		m_pBoundingBox->combine(upper);
	}

	return *m_pBoundingBox;
}

// Return a copy of the current geometry
GLC_VboGeom* GLC_Circle::clone() const
{
	return new GLC_Circle(*this);
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Set Circle diameter
void GLC_Circle::setDiameter(double D)
{
	Q_ASSERT(D > (2 * EPSILON));
	setRadius(D / 2);
}

// Set Circle Radius
void GLC_Circle::setRadius(double R)
{
	Q_ASSERT(R > EPSILON);
	if ( fabs(R - m_Radius) > EPSILON)
	{	// Radius is changing
		m_Radius= R;
		m_GeometryIsValid= false;
		if (NULL != m_pBoundingBox)
		{
			delete m_pBoundingBox;
			m_pBoundingBox= NULL;
		}
	}
}

// Set Circle discret
void GLC_Circle::setDiscretion(int TargetDiscret)
{
	Q_ASSERT(TargetDiscret > 0);
	if (TargetDiscret != m_nDiscret)
	{
		m_nDiscret= TargetDiscret;
		if (m_nDiscret < 6) m_nDiscret= 6;
		m_GeometryIsValid= false;
	}
}

// Set Circle Angle
void GLC_Circle::setAngle(double AngleRadians)	// Angle in Radians
{
	Q_ASSERT((AngleRadians > EPSILON) && (AngleRadians < 2 * PI));
	if ( fabs(AngleRadians - m_dAngle) > EPSILON)
	{	// Angle is changing
			m_dAngle= AngleRadians;
			m_GeometryIsValid= false;
			if (NULL != m_pBoundingBox)
			{
				delete m_pBoundingBox;
				m_pBoundingBox= NULL;
			}
	}
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Circle drawing
void GLC_Circle::glDraw(bool)
{
	const bool vboIsUsed= GLC_State::vboUsed();
	if (vboIsUsed)
	{
		m_SimpleGeomEngine.createVBOs();
		m_SimpleGeomEngine.useVBOs(true);
	}

	if (!m_GeometryIsValid)
	{
		VertexVector* pVertexVector= m_SimpleGeomEngine.vertexVectorHandle();
		// Calculate number of step
		m_Step= static_cast<GLuint>(static_cast<double>(m_nDiscret) * (m_dAngle / (2 * glc::PI)));
		if (m_Step < 2) m_Step= 2;

		// Vertex Vector
		const GLsizeiptr size= (m_Step + 1) * sizeof(GLC_Vertex);
		// Resize the Vertex vector
		pVertexVector->resize(m_Step + 1);
		// Fill Vertex Vector
		for (GLuint i= 0; i <= m_Step; ++i)
		{
			(*pVertexVector)[i].x= static_cast<float>(m_Radius * cos(i * m_dAngle / m_Step));
			(*pVertexVector)[i].y= static_cast<float>(m_Radius * sin(i * m_dAngle / m_Step));
		}

		// Index Vector
		const GLsizeiptr IndexSize = (m_Step + 1) * sizeof(GLuint);
		// Resize index vector
		QVector<GLuint>* pIndexVector= m_SimpleGeomEngine.indexVectorHandle();
		pIndexVector->resize(m_Step + 1);
		// Fill index vector
		for (GLuint i= 0; i <= m_Step; ++i)
		{
			(*pIndexVector)[i]= i;
		}

		if (vboIsUsed)
		{
			// Create VBO
			glBufferData(GL_ARRAY_BUFFER, size, pVertexVector->data(), GL_STATIC_DRAW);
			// Create IBO
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, IndexSize, pIndexVector->data(), GL_STATIC_DRAW);
			// Clear Vector
			pVertexVector->clear();
			pIndexVector->clear();
		}
	}

	if (vboIsUsed)
	{
		// Use VBO
		glVertexPointer(2, GL_FLOAT, sizeof(GLC_Vertex), BUFFER_OFFSET(0));
		glEnableClientState(GL_VERTEX_ARRAY);
		//glDrawRangeElements(GL_LINE_STRIP, 0, m_Step + 1, m_Step + 1, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
		glDrawElements(GL_LINE_STRIP, m_Step + 1, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
		glDisableClientState(GL_VERTEX_ARRAY);
	}
	else
	{
		// Use Vertex Array
		glVertexPointer(2, GL_FLOAT, sizeof(GLC_Vertex), m_SimpleGeomEngine.vertexVectorHandle()->data());
		glEnableClientState(GL_VERTEX_ARRAY);
		glDrawElements(GL_LINE_STRIP, m_Step + 1, GL_UNSIGNED_INT, m_SimpleGeomEngine.indexVectorHandle()->data());
		glDisableClientState(GL_VERTEX_ARRAY);
	}

	if (vboIsUsed)
	{
		m_SimpleGeomEngine.useVBOs(false);
	}

	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Circle::GlDraw ", error);
		throw(OpenGlException);
	}
}
<commit_msg>Use qFuzzyCompare function instead of comparaison with glc::EPSILON to determine if to double or float are equal.<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib 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 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_circle.cpp implementation of the GLC_Circle class.

#include "glc_circle.h"
#include "../glc_openglexception.h"
#include "../glc_state.h"

using namespace glc;
//////////////////////////////////////////////////////////////////////
// Constructor destructor
//////////////////////////////////////////////////////////////////////

GLC_Circle::GLC_Circle(const double &dRadius, double Angle)
:GLC_VboGeom("Circle", true)
, m_Radius(dRadius)
, m_nDiscret(GLC_DISCRET)
, m_dAngle(Angle)
, m_Step(0)
, m_SimpleGeomEngine()
{

}

GLC_Circle::GLC_Circle(const GLC_Circle& sourceCircle)
:GLC_VboGeom(sourceCircle)
, m_Radius(sourceCircle.m_Radius)
, m_nDiscret(sourceCircle.m_nDiscret)
, m_dAngle(sourceCircle.m_dAngle)
, m_SimpleGeomEngine(sourceCircle.m_SimpleGeomEngine)
{
	// Copy inner material hash
	MaterialHash::const_iterator i= m_MaterialHash.begin();
	MaterialHash newMaterialHash;
    while (i != m_MaterialHash.constEnd())
    {
        // update inner material use table
    	i.value()->delGLC_Geom(id());
    	GLC_Material* pNewMaterial= new GLC_Material(*(i.value()));
    	newMaterialHash.insert(pNewMaterial->id(), pNewMaterial);
    	pNewMaterial->addGLC_Geom(this);
         ++i;
    }
    m_MaterialHash= newMaterialHash;
}
GLC_Circle::~GLC_Circle()
{

}
//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Return Circle Discretion
int GLC_Circle::getDiscretion(void) const
{
	return m_nDiscret;
}
// Return Circle radius
double GLC_Circle::getRadius(void) const
{
	return m_Radius;
}
// return Circle diameter
double GLC_Circle::getDiameter(void) const
{
	return 2 * m_Radius;
}

// return the circle bounding box
GLC_BoundingBox& GLC_Circle::boundingBox(void)
{
	if (NULL == m_pBoundingBox)
	{
		m_pBoundingBox= new GLC_BoundingBox();

		GLC_Point3d lower(-m_Radius, -m_Radius, -2.0 * EPSILON);
		GLC_Point3d upper(m_Radius, m_Radius, 2.0 * EPSILON);
		m_pBoundingBox->combine(lower);
		m_pBoundingBox->combine(upper);
	}

	return *m_pBoundingBox;
}

// Return a copy of the current geometry
GLC_VboGeom* GLC_Circle::clone() const
{
	return new GLC_Circle(*this);
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Set Circle diameter
void GLC_Circle::setDiameter(double D)
{
	Q_ASSERT(not qFuzzyCompare(D, 0.0));
	setRadius(D / 2);
}

// Set Circle Radius
void GLC_Circle::setRadius(double R)
{
	Q_ASSERT(not qFuzzyCompare(R, 0.0));
	if (not qFuzzyCompare(R - m_Radius, 0.0))
	{	// Radius is changing
		m_Radius= R;
		m_GeometryIsValid= false;
		if (NULL != m_pBoundingBox)
		{
			delete m_pBoundingBox;
			m_pBoundingBox= NULL;
		}
	}
}

// Set Circle discret
void GLC_Circle::setDiscretion(int TargetDiscret)
{
	Q_ASSERT(TargetDiscret > 0);
	if (TargetDiscret != m_nDiscret)
	{
		m_nDiscret= TargetDiscret;
		if (m_nDiscret < 6) m_nDiscret= 6;
		m_GeometryIsValid= false;
	}
}

// Set Circle Angle
void GLC_Circle::setAngle(double AngleRadians)	// Angle in Radians
{
	Q_ASSERT((not qFuzzyCompare(AngleRadians, 0.0)) && (AngleRadians < 2 * PI));
	if (not qFuzzyCompare(AngleRadians - m_dAngle, 0.0))
	{	// Angle is changing
			m_dAngle= AngleRadians;
			m_GeometryIsValid= false;
			if (NULL != m_pBoundingBox)
			{
				delete m_pBoundingBox;
				m_pBoundingBox= NULL;
			}
	}
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Circle drawing
void GLC_Circle::glDraw(bool)
{
	const bool vboIsUsed= GLC_State::vboUsed();
	if (vboIsUsed)
	{
		m_SimpleGeomEngine.createVBOs();
		m_SimpleGeomEngine.useVBOs(true);
	}

	if (!m_GeometryIsValid)
	{
		VertexVector* pVertexVector= m_SimpleGeomEngine.vertexVectorHandle();
		// Calculate number of step
		m_Step= static_cast<GLuint>(static_cast<double>(m_nDiscret) * (m_dAngle / (2 * glc::PI)));
		if (m_Step < 2) m_Step= 2;

		// Vertex Vector
		const GLsizeiptr size= (m_Step + 1) * sizeof(GLC_Vertex);
		// Resize the Vertex vector
		pVertexVector->resize(m_Step + 1);
		// Fill Vertex Vector
		for (GLuint i= 0; i <= m_Step; ++i)
		{
			(*pVertexVector)[i].x= static_cast<float>(m_Radius * cos(i * m_dAngle / m_Step));
			(*pVertexVector)[i].y= static_cast<float>(m_Radius * sin(i * m_dAngle / m_Step));
		}

		// Index Vector
		const GLsizeiptr IndexSize = (m_Step + 1) * sizeof(GLuint);
		// Resize index vector
		QVector<GLuint>* pIndexVector= m_SimpleGeomEngine.indexVectorHandle();
		pIndexVector->resize(m_Step + 1);
		// Fill index vector
		for (GLuint i= 0; i <= m_Step; ++i)
		{
			(*pIndexVector)[i]= i;
		}

		if (vboIsUsed)
		{
			// Create VBO
			glBufferData(GL_ARRAY_BUFFER, size, pVertexVector->data(), GL_STATIC_DRAW);
			// Create IBO
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, IndexSize, pIndexVector->data(), GL_STATIC_DRAW);
			// Clear Vector
			pVertexVector->clear();
			pIndexVector->clear();
		}
	}

	if (vboIsUsed)
	{
		// Use VBO
		glVertexPointer(2, GL_FLOAT, sizeof(GLC_Vertex), BUFFER_OFFSET(0));
		glEnableClientState(GL_VERTEX_ARRAY);
		//glDrawRangeElements(GL_LINE_STRIP, 0, m_Step + 1, m_Step + 1, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
		glDrawElements(GL_LINE_STRIP, m_Step + 1, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
		glDisableClientState(GL_VERTEX_ARRAY);
	}
	else
	{
		// Use Vertex Array
		glVertexPointer(2, GL_FLOAT, sizeof(GLC_Vertex), m_SimpleGeomEngine.vertexVectorHandle()->data());
		glEnableClientState(GL_VERTEX_ARRAY);
		glDrawElements(GL_LINE_STRIP, m_Step + 1, GL_UNSIGNED_INT, m_SimpleGeomEngine.indexVectorHandle()->data());
		glDisableClientState(GL_VERTEX_ARRAY);
	}

	if (vboIsUsed)
	{
		m_SimpleGeomEngine.useVBOs(false);
	}

	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Circle::GlDraw ", error);
		throw(OpenGlException);
	}
}
<|endoftext|>