<commit_before>// Example program
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

void DPrinter(std::vector<int>& data,int left, int right,int part){
#ifndef DEBUG
	for(int i=left ; i < part ; i++){
		std::cout << data[i] << ",";
	}
	std::cout << " =========  " ;
	for(int i=part+1 ; i <= right ; i++){
		std::cout << data[i] << ",";
	}
	std::cout << "\n";
#endif
}

void Printer(std::vector<int>& data,std::string comment= "None"){
#ifndef DEBUG
	for(const auto& x : data)
		std::cout << x << ",";
	std::cout << "\t======== Comment : " << comment << "\n";
#endif
}

int RPartition(std::vector<int>& data,int left, int right,long long& count){
	int pivot = data[right];
	int i = left - 1;
	int tmp;
	for(int j = left ; j < right ; ++j){
		if(data[j] < pivot){
			i++;
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
		}
	}
	data[right] = data[i+1];
	data[i+1] = pivot;
	return i+1; // New Partition boundary.
}

void RQSort(std::vector<int>& data,int left, int right,long long& count){
	if(left < right){
		count += (right-left -1 );
		int part = RPartition(data,left,right,count);
		RQSort(data,left,part-1,count);
		RQSort(data,part+1,right,count);
	}
}

int MPartition(std::vector<int>& data,int left, int right,long long& count){
	int len = right - left  + 1;
	int mid = (left + (len + (len%2))/2 - 1 );
	int tmp;
        if((data[mid] > data[left] && data[mid] < data[right]) ||
	    (data[mid] < data[left] && data[mid] > data[right]) ){
		tmp=data[left];
		data[left]=data[mid];
		data[mid]=tmp;
	}
	else if((data[right] > data[left] && data[right] < data[mid]) ||
	    (data[right] < data[left] && data[right] > data[mid]) ){
		tmp=data[left];
		data[left]=data[right];
		data[right]=tmp;
	}
	int pivot = data[left];

	int i = left + 1;
	for(int j = left + 1 ; j <= right ; ++j){
		if(data[j] < pivot){
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
			i++;
		}
	}
	data[left] = data[i-1];
	data[i-1] = pivot;
	Printer(data, std::to_string(len));
	return i-1; // New Partition boundary.
}

void MQSort(std::vector<int>& data,int left, int right,long long& count){
	if(left < right){
		count += (right - left);
		int part = MPartition(data,left,right,count);
		MQSort(data,left,part-1,count);
		MQSort(data,part+1,right,count);
	}
}

int Partition(std::vector<int>& data,int left, int right,long long& count){
	int pivot = data[left];
	int i = left + 1;
	int tmp;
	for(int j = left + 1 ; j <= right ; ++j){
		if(data[j] < pivot){
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
			i++;
		}
	}
	data[left] = data[i-1];
	data[i-1] = pivot;
	return i-1; // New Partition boundary.
}

void QSort(std::vector<int>& data,int left, int right,long long& count){
	if(left < right){
		count += (right-left );
		int part = Partition(data,left,right,count);
		QSort(data,left,part-1,count);
		QSort(data,part+1,right,count);
	}
}

int main()
{
	//std::vector<int> data = {3,8,2,5,1,4,7,6};
	{
		std::vector<int> data;
		std::ifstream ifs("qdata.txt");
		int x;
		while(ifs>>x){
			data.push_back(x);
		}
		Printer(data,"Unsorted");
		long long inv_count = 0;
		QSort(data,0,data.size()-1,inv_count);
		Printer(data,"Sorted");
		std::cout << "Count of comparisons First Pivot : " << inv_count << "\n\n";
	}
	{
		std::vector<int> data;
		std::ifstream ifs("qdata.txt");
		int x;
		while(ifs>>x){
			data.push_back(x);
		}
		Printer(data,"Unsorted");
		long long inv_count = 0;
		RQSort(data,0,data.size()-1,inv_count);
		Printer(data,"Sorted");
		std::cout << "Count of comparisons Last Pivot : " << inv_count << "\n\n";
	}
	{
		std::vector<int> data;
		std::ifstream ifs("qdata.txt");
		int x;
		while(ifs>>x){
			data.push_back(x);
		}
		Printer(data,"Unsorted");
		long long inv_count = 0;
		MQSort(data,0,data.size()-1,inv_count);
		Printer(data,"Sorted");
		std::cout << "Count of comparisons Median Pivot : " << inv_count << "\n\n";
	}
}
<commit_msg>[Fixed]: Commented code is alternative implementation.<commit_after>// Example program
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

void DPrinter(std::vector<int>& data,int left, int right,int part){
#ifndef DEBUG
	for(int i=left ; i < part ; i++){
		std::cout << data[i] << ",";
	}
	std::cout << " =========  " ;
	for(int i=part+1 ; i <= right ; i++){
		std::cout << data[i] << ",";
	}
	std::cout << "\n";
#endif
}

void Printer(std::vector<int>& data,std::string comment= "None"){
#ifndef DEBUG
	for(const auto& x : data)
		std::cout << x << ",";
	std::cout << "\t======== Comment : " << comment << "\n";
#endif
}

int RPartition(std::vector<int>& data,int left, int right,long long& count){
	//int pivot = data[right];
	//int i = left - 1;
	//int tmp;
	//for(int j = left ; j < right ; j++){
	//	if(data[j] < pivot){
	//		i++;
	//		tmp = data[i];
	//		data[i] = data[j];
	//		data[j] = tmp;
	//	}
	//}
	//data[right] = data[i+1];
	//data[i+1] = pivot;
	//return i+1; // New Partition boundary.
	int tmp = data[left];
	data[left] = data[right];
	data[right]=tmp;

	int pivot = data[left];
	int i = left + 1;
	for(int j = left + 1 ; j <= right ; ++j){
		if(data[j] < pivot){
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
			i++;
		}
	}
	data[left] = data[i-1];
	data[i-1] = pivot;
	return i-1; // New Partition boundary.
}

void RQSort(std::vector<int>& data,int left, int right,long long& count){
	if(left < right){
		count += (right-left) ;
		int part = RPartition(data,left,right,count);
		RQSort(data,left,part-1,count);
		RQSort(data,part+1,right,count);
	}
}

int MPartition(std::vector<int>& data,int left, int right,long long& count){
	int len = right - left  + 1;
	int mid = (left + (len + (len%2))/2 - 1 );
	int tmp;
        if((data[mid] > data[left] && data[mid] < data[right]) ||
	    (data[mid] < data[left] && data[mid] > data[right]) ){
		tmp=data[left];
		data[left]=data[mid];
		data[mid]=tmp;
	}
	else if((data[right] > data[left] && data[right] < data[mid]) ||
	    (data[right] < data[left] && data[right] > data[mid]) ){
		tmp=data[left];
		data[left]=data[right];
		data[right]=tmp;
	}
	int pivot = data[left];

	int i = left + 1;
	for(int j = left + 1 ; j <= right ; ++j){
		if(data[j] < pivot){
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
			i++;
		}
	}
	data[left] = data[i-1];
	data[i-1] = pivot;
	return i-1; // New Partition boundary.
}

void MQSort(std::vector<int>& data,int left, int right,long long& count){
	if(left < right){
		count += (right - left);
		int part = MPartition(data,left,right,count);
		MQSort(data,left,part-1,count);
		MQSort(data,part+1,right,count);
	}
}

int Partition(std::vector<int>& data,int left, int right,long long& count){
	int pivot = data[left];
	int i = left + 1;
	int tmp;
	for(int j = left + 1 ; j <= right ; ++j){
		if(data[j] < pivot){
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
			i++;
		}
	}
	data[left] = data[i-1];
	data[i-1] = pivot;
	return i-1; // New Partition boundary.
}

void QSort(std::vector<int>& data,int left, int right,long long& count){
	if(left < right){
		count += (right-left );
		int part = Partition(data,left,right,count);
		QSort(data,left,part-1,count);
		QSort(data,part+1,right,count);
	}
}

int main()
{
	//std::vector<int> data = {3,8,2,5,1,4,7,6};
	{
		std::vector<int> data;
		std::ifstream ifs("qdata.txt");
		int x;
		while(ifs>>x){
			data.push_back(x);
		}
		Printer(data,"Unsorted");
		long long inv_count = 0;
		QSort(data,0,data.size()-1,inv_count);
		Printer(data,"Sorted");
		std::cout << "Count of comparisons First Pivot : " << inv_count << "\n\n";
	}
	{
		std::vector<int> data;
		std::ifstream ifs("qdata.txt");
		int x;
		while(ifs>>x){
			data.push_back(x);
		}
		Printer(data,"Unsorted");
		long long inv_count = 0;
		RQSort(data,0,data.size()-1,inv_count);
		Printer(data,"Sorted");
		std::cout << "Count of comparisons Last Pivot : " << inv_count << "\n\n";
	}
	{
		std::vector<int> data;
		std::ifstream ifs("qdata.txt");
		int x;
		while(ifs>>x){
			data.push_back(x);
		}
		Printer(data,"Unsorted");
		long long inv_count = 0;
		MQSort(data,0,data.size()-1,inv_count);
		Printer(data,"Sorted");
		std::cout << "Count of comparisons Median Pivot : " << inv_count << "\n\n";
	}
}
<|endoftext|>


<commit_before>#ifndef VECTOR_HPP
#define VECTOR_HPP

#include "Types.hpp"

#define DECLARE_VECTOR_WITH_CHUNKSIZE(TYPENAME, CHUNKSIZE)               \
  class Vector_ ## TYPENAME {                                            \
  public:                                                                \
    Vector_ ## TYPENAME(void) : vector_(NULL), capacity_(0), size_(0) {} \
                                                                         \
    ~Vector_ ## TYPENAME(void) {                                         \
      if (vector_) {                                                     \
        delete[] vector_;                                                \
      }                                                                  \
    }                                                                    \
                                                                         \
    void reserve(size_t n) {                                             \
      if (n <= capacity_) return;                                        \
                                                                         \
      TYPENAME* p = new TYPENAME[n];                                     \
      if (p) {                                                           \
        capacity_ = n;                                                   \
        for (size_t i = 0; i < size_; ++i) {                             \
          p[i] = vector_[i];                                             \
        }                                                                \
                                                                         \
        if (vector_) {                                                   \
          delete[] vector_;                                              \
        }                                                                \
        vector_ = p;                                                     \
      }                                                                  \
    }                                                                    \
                                                                         \
    void clear(void) {                                                   \
      if (vector_) {                                                     \
        delete[] vector_;                                                \
        vector_ = NULL;                                                  \
      }                                                                  \
      capacity_ = 0;                                                     \
      size_ = 0;                                                         \
    }                                                                    \
                                                                         \
    Vector_ ## TYPENAME & push_back(const TYPENAME &newval) {            \
      if (size_ >= capacity_) {                                          \
        reserve(capacity_ + CHUNKSIZE);                                  \
      }                                                                  \
                                                                         \
      if (size_ < capacity_) {                                           \
        vector_[size_] = newval;                                         \
        ++size_;                                                         \
      }                                                                  \
                                                                         \
      return *this;                                                      \
    }                                                                    \
                                                                         \
    size_t size(void) const { return size_; }                            \
    size_t capacity(void) const { return capacity_; }                    \
    bool empty(void) const { return size_ == 0; }                        \
                                                                         \
    Vector_ ## TYPENAME& operator=(const Vector_ ## TYPENAME& rhs) {     \
      if (this == &rhs) return *this;                                    \
                                                                         \
      clear();                                                           \
      capacity_ = rhs.capacity_;                                         \
      size_ = rhs.size_;                                                 \
      vector_ = new TYPENAME[capacity_];                                 \
      for (size_t i = 0; i < size_; ++i) {                               \
        vector_[i] = rhs.vector_[i];                                     \
      }                                                                  \
                                                                         \
      return *this;                                                      \
    }                                                                    \
    TYPENAME& operator[](size_t n) { return vector_[n]; }                \
    const TYPENAME& operator[](size_t n) const { return vector_[n]; }    \
    TYPENAME& front(void) { return vector_[0]; }                         \
    TYPENAME& back(void) { return vector_[size_ - 1]; }                  \
                                                                         \
  private:                                                               \
    Vector_ ## TYPENAME(const Vector_ ## TYPENAME & rhs) {}              \
                                                                         \
    TYPENAME* vector_;                                                   \
    size_t capacity_;                                                    \
    size_t size_;                                                        \
  };

#define DECLARE_VECTOR(TYPENAME) DECLARE_VECTOR_WITH_CHUNKSIZE(TYPENAME, 16)

#endif
<commit_msg>Added DECLARE_VECTOR_WITH_HELPER<commit_after>#ifndef VECTOR_HPP
#define VECTOR_HPP

#include "Types.hpp"

#define DECLARE_VECTOR_CLASS_BODY(TYPENAME, CHUNKSIZE)                 \
public:                                                                \
  Vector_ ## TYPENAME(void) : vector_(NULL), capacity_(0), size_(0) {} \
                                                                       \
  ~Vector_ ## TYPENAME(void) {                                         \
    if (vector_) {                                                     \
      delete[] vector_;                                                \
    }                                                                  \
  }                                                                    \
                                                                       \
  void reserve(size_t n) {                                             \
    if (n <= capacity_) return;                                        \
                                                                       \
    TYPENAME* p = new TYPENAME[n];                                     \
    if (p) {                                                           \
      capacity_ = n;                                                   \
      for (size_t i = 0; i < size_; ++i) {                             \
        p[i] = vector_[i];                                             \
      }                                                                \
                                                                       \
      if (vector_) {                                                   \
        delete[] vector_;                                              \
      }                                                                \
      vector_ = p;                                                     \
    }                                                                  \
  }                                                                    \
                                                                       \
  void clear(void) {                                                   \
    if (vector_) {                                                     \
      delete[] vector_;                                                \
      vector_ = NULL;                                                  \
    }                                                                  \
    capacity_ = 0;                                                     \
    size_ = 0;                                                         \
  }                                                                    \
                                                                       \
  Vector_ ## TYPENAME & push_back(const TYPENAME &newval) {            \
    if (size_ >= capacity_) {                                          \
      reserve(capacity_ + CHUNKSIZE);                                  \
    }                                                                  \
                                                                       \
    if (size_ < capacity_) {                                           \
      vector_[size_] = newval;                                         \
      ++size_;                                                         \
    }                                                                  \
                                                                       \
    return *this;                                                      \
  }                                                                    \
                                                                       \
  size_t size(void) const { return size_; }                            \
  size_t capacity(void) const { return capacity_; }                    \
  bool empty(void) const { return size_ == 0; }                        \
                                                                       \
  Vector_ ## TYPENAME& operator=(const Vector_ ## TYPENAME& rhs) {     \
    if (this == &rhs) return *this;                                    \
                                                                       \
    clear();                                                           \
    capacity_ = rhs.capacity_;                                         \
    size_ = rhs.size_;                                                 \
    vector_ = new TYPENAME[capacity_];                                 \
    for (size_t i = 0; i < size_; ++i) {                               \
      vector_[i] = rhs.vector_[i];                                     \
    }                                                                  \
                                                                       \
    return *this;                                                      \
  }                                                                    \
  TYPENAME& operator[](size_t n) { return vector_[n]; }                \
  const TYPENAME& operator[](size_t n) const { return vector_[n]; }    \
  TYPENAME& front(void) { return vector_[0]; }                         \
  TYPENAME& back(void) { return vector_[size_ - 1]; }                  \
                                                                       \
private:                                                               \
  Vector_ ## TYPENAME(const Vector_ ## TYPENAME & rhs) {}              \
                                                                       \
  TYPENAME* vector_;                                                   \
  size_t capacity_;                                                    \
  size_t size_;                                                        \

#define DECLARE_VECTOR_WITH_CHUNKSIZE(TYPENAME, CHUNKSIZE) \
  class Vector_ ## TYPENAME {                              \
    DECLARE_VECTOR_CLASS_BODY(TYPENAME, CHUNKSIZE)         \
  };                                                       \

#define DECLARE_VECTOR_WITH_CHUNKSIZE_WITH_HELPER(TYPENAME, CHUNKSIZE) \
  class Vector_ ## TYPENAME {                                          \
    DECLARE_VECTOR_CLASS_BODY(TYPENAME, CHUNKSIZE)                     \
  public:                                                              \
    bool is_include(const TYPENAME &v) const {                         \
      for (size_t i = 0; i < size_; ++i) {                             \
        if (vector_[i] == v) {                                         \
          return true;                                                 \
        }                                                              \
      }                                                                \
      return false;                                                    \
    }                                                                  \
  };                                                                   \

#define DECLARE_VECTOR(TYPENAME) DECLARE_VECTOR_WITH_CHUNKSIZE(TYPENAME, 16)
#define DECLARE_VECTOR_WITH_HELPER(TYPENAME) DECLARE_VECTOR_WITH_CHUNKSIZE_WITH_HELPER(TYPENAME, 16)

#endif
<|endoftext|>


<commit_before>#include "primitives.hpp"

#include "texture.hpp"

namespace mo {
namespace renderer {

	Vertex_layout simple_vertex_layout {
		Vertex_layout::Mode::triangles,
		vertex("position", &Simple_vertex::xy),
		vertex("uv", &Simple_vertex::uv)
	};

	namespace {
		struct Ray_vertex {
			glm::vec2 pos;
			float radius_pos;
		};

		auto ray_layout = renderer::Vertex_layout{
			renderer::Vertex_layout::Mode::triangle_strip,
			renderer::vertex("position", &Ray_vertex::pos),
			renderer::vertex("radius_pos", &Ray_vertex::radius_pos)
		};
		auto ray_mesh = std::vector<Ray_vertex>{
			{{0,0},-1}, {{1,0},-1}, {{0,1},1}, {{1,1},1}
		};
	}

	Ray_renderer::Ray_renderer(asset::Asset_manager& assets)
		: _obj(ray_layout, create_buffer(ray_mesh)) {

		_prog.attach_shader(assets.load<Shader>("frag_shader:ray"_aid))
			 .attach_shader(assets.load<Shader>("vert_shader:ray"_aid))
			 .bind_all_attribute_locations(ray_layout)
			 .build()
			 .bind()
			 .set_uniform("color", glm::vec4(1,0,0,0.5));
	}

	void Ray_renderer::set_vp(const glm::mat4& vp) {
		_prog.bind().set_uniform("vp", vp);
	}

	void Ray_renderer::draw(glm::vec3 p, Angle a, float length, glm::vec4 color, float width) {
		auto scale = glm::scale(glm::translate(glm::mat4(), glm::vec3(0,-width/2.f,0)),
								glm::vec3(length, width, 1));
		auto rot = glm::rotate(a.value(), glm::vec3(0,0,1));
		auto trans = glm::translate(glm::mat4(), p);

		_prog.bind()
				.set_uniform("model", trans*rot*scale)
		        .set_uniform("color", color);
		_obj.draw();
	}

	namespace {
		auto create_bubble_mesh(float radius) -> std::vector<Simple_vertex> {
			using glm::vec2;

			constexpr auto steps = 12;

			std::vector<Simple_vertex> m;
			m.reserve(steps+1);

			m.emplace_back(vec2{0,0},vec2{.5f,.5f});

			for(auto phi=0.f; phi<=1; phi+=1.f/steps) {
				auto x = std::cos(phi * 2*PI);
				auto y = std::sin(phi * 2*PI);
				m.emplace_back(vec2{x,y} * radius, (vec2{x,-y}+1.f)/2.f);
			}

			return m;
		}

		Vertex_layout bubble_vertex_layout {
			Vertex_layout::Mode::triangle_fan,
			vertex("position", &Simple_vertex::xy),
			vertex("uv", &Simple_vertex::uv)
		};
	}

	Bubble_renderer::Bubble_renderer(asset::Asset_manager& assets, float radius)
	    : _obj(bubble_vertex_layout, create_buffer(create_bubble_mesh(radius)))
	{
		_prog.attach_shader(assets.load<Shader>("frag_shader:bubble"_aid))
			 .attach_shader(assets.load<Shader>("vert_shader:bubble"_aid))
			 .bind_all_attribute_locations(bubble_vertex_layout)
			 .build();
	}

	void Bubble_renderer::set_vp(const glm::mat4& vp) {
		_prog.bind().set_uniform("vp", vp);
	}

	void Bubble_renderer::draw(glm::vec2 center, float fill_level, float activity, float time, const Texture& texture) {
		auto trans = glm::translate(glm::mat4(), {center.x, center.y, 0});

		texture.bind();
		_prog.bind()
				.set_uniform("model", trans)
		        .set_uniform("fill_level", glm::clamp(fill_level, 0.f, 1.f))
		        .set_uniform("time", time)
		        .set_uniform("activity", glm::clamp(activity, 0.f, 1.f))
		        .set_uniform("texture", 0);
		_obj.draw();
	}

}
}
<commit_msg>element-indicator fix (JS-only)<commit_after>#include "primitives.hpp"

#include "texture.hpp"

namespace mo {
namespace renderer {

	Vertex_layout simple_vertex_layout {
		Vertex_layout::Mode::triangles,
		vertex("position", &Simple_vertex::xy),
		vertex("uv", &Simple_vertex::uv)
	};

	namespace {
		struct Ray_vertex {
			glm::vec2 pos;
			float radius_pos;
		};

		auto ray_layout = renderer::Vertex_layout{
			renderer::Vertex_layout::Mode::triangle_strip,
			renderer::vertex("position", &Ray_vertex::pos),
			renderer::vertex("radius_pos", &Ray_vertex::radius_pos)
		};
		auto ray_mesh = std::vector<Ray_vertex>{
			{{0,0},-1}, {{1,0},-1}, {{0,1},1}, {{1,1},1}
		};
	}

	Ray_renderer::Ray_renderer(asset::Asset_manager& assets)
		: _obj(ray_layout, create_buffer(ray_mesh)) {

		_prog.attach_shader(assets.load<Shader>("frag_shader:ray"_aid))
			 .attach_shader(assets.load<Shader>("vert_shader:ray"_aid))
			 .bind_all_attribute_locations(ray_layout)
			 .build()
			 .bind()
			 .set_uniform("color", glm::vec4(1,0,0,0.5));
	}

	void Ray_renderer::set_vp(const glm::mat4& vp) {
		_prog.bind().set_uniform("vp", vp);
	}

	void Ray_renderer::draw(glm::vec3 p, Angle a, float length, glm::vec4 color, float width) {
		auto scale = glm::scale(glm::translate(glm::mat4(), glm::vec3(0,-width/2.f,0)),
								glm::vec3(length, width, 1));
		auto rot = glm::rotate(a.value(), glm::vec3(0,0,1));
		auto trans = glm::translate(glm::mat4(), p);

		_prog.bind()
				.set_uniform("model", trans*rot*scale)
		        .set_uniform("color", color);
		_obj.draw();
	}

	namespace {
		auto create_bubble_mesh(float radius) -> std::vector<Simple_vertex> {
			using glm::vec2;

			constexpr auto steps = 12;

			std::vector<Simple_vertex> m;
			m.reserve(steps+1);

			m.emplace_back(vec2{0,0},vec2{.5f,.5f});

			for(int i=0; i<=steps; ++i) {
				float phi = i/float(steps);

				auto x = std::cos(phi * 2*PI);
				auto y = std::sin(phi * 2*PI);
				m.emplace_back(vec2{x,y} * radius, (vec2{x,-y}+1.f)/2.f);
			}

			return m;
		}

		Vertex_layout bubble_vertex_layout {
			Vertex_layout::Mode::triangle_fan,
			vertex("position", &Simple_vertex::xy),
			vertex("uv", &Simple_vertex::uv)
		};
	}

	Bubble_renderer::Bubble_renderer(asset::Asset_manager& assets, float radius)
	    : _obj(bubble_vertex_layout, create_buffer(create_bubble_mesh(radius)))
	{
		_prog.attach_shader(assets.load<Shader>("frag_shader:bubble"_aid))
			 .attach_shader(assets.load<Shader>("vert_shader:bubble"_aid))
			 .bind_all_attribute_locations(bubble_vertex_layout)
			 .build();
	}

	void Bubble_renderer::set_vp(const glm::mat4& vp) {
		_prog.bind().set_uniform("vp", vp);
	}

	void Bubble_renderer::draw(glm::vec2 center, float fill_level, float activity, float time, const Texture& texture) {
		auto trans = glm::translate(glm::mat4(), {center.x, center.y, 0});

		texture.bind();
		_prog.bind()
				.set_uniform("model", trans)
		        .set_uniform("fill_level", glm::clamp(fill_level, 0.f, 1.f))
		        .set_uniform("time", time)
		        .set_uniform("activity", glm::clamp(activity, 0.f, 1.f))
		        .set_uniform("texture", 0);
		_obj.draw();
	}

}
}
<|endoftext|>


<commit_before>#include "data/vocab_base.h"

#ifdef USE_SENTENCEPIECE
#include "sentencepiece/src/sentencepiece_processor.h"
#include "sentencepiece/src/sentencepiece_trainer.h"
#endif

#include "common/config.h"
#include "common/options.h"
#include "common/logging.h"
#include "common/filesystem.h"
#include "common/regex.h"

#include <sstream>

namespace marian {

#ifdef USE_SENTENCEPIECE

// Wrapper around https://github.com/google/sentencepiece
class SentencePieceVocab : public VocabBase {
private:
  // Actual SentencePiece processor object
  UPtr<sentencepiece::SentencePieceProcessor> spm_;

  // Sampling factor for subword regularization, disabled when 0
  float alpha_{0};

  // Allowed suffixes for SentencePiece model
  std::vector<std::string> suffixes_ = {".spm"};

  Ptr<Options> options_;
  size_t batchIndex_{0};

  std::mt19937 generator_;
  std::uniform_int_distribution<int> randInt_; // from 0 to INT_MAX

public:
  SentencePieceVocab(Ptr<Options> options, size_t batchIndex)
    : options_(options), batchIndex_(batchIndex), generator_(Config::seed) {

    if(options_->has("sentencepiece-alphas")) {
      auto alphas = options_->get<std::vector<float>>("sentencepiece-alphas");
      if(alphas.size() <= batchIndex)
        alpha_ = 0.f;
      else
        alpha_ = alphas[batchIndex_];

      if(alpha_ > 0)
        LOG(debug,
            "Setting SentencePieceVocab sampling factor to {} for input {}",
            alpha_,
            batchIndex_);
    }

  }

  virtual const std::string& canonicalExtension() const { return suffixes_[0]; }
  virtual const std::vector<std::string>& suffixes() const { return suffixes_; }

  virtual std::string suffix() { return suffixes_[0]; };

  virtual std::string type() const { return "SentencePieceVocab"; }

  virtual Word getEosId() const override { return (Word)spm_->eos_id(); }
  virtual Word getUnkId() const override { return (Word)spm_->unk_id(); }

  void resevoirSampling(std::vector<std::string>& sample, size_t& seenLines,
                        const std::string& trainPath, size_t maxLines, size_t maxBytes) {
    std::unique_ptr<io::InputFileStream> trainStrm(
      trainPath == "stdin" ? new io::InputFileStream(std::cin)
                           : new io::InputFileStream(trainPath)
    );

    std::string line;
    while(getline(*trainStrm, line)) {
      if(line.size() < maxBytes) {
        if(maxLines == 0 || sample.size() < maxLines) {
          sample.push_back(line);
        }
        else {
          size_t i = randInt_(generator_) % (seenLines + 1);
          if(i < maxLines)
            sample[i] = line;
        }
        seenLines++;
      }
    }
  }

  // Iterate over all input files and collect a representative sample via reservoir sampling.
  // The sample will first grow to the desired size and next keep sampling with decreasing
  // probability in the hope to get a uniform sample from the union of all files.
  size_t resevoirSamplingAll(io::TemporaryFile& temp,
                             const std::vector<std::string>& trainPaths,
                             size_t maxLines, size_t maxBytes) {
    LOG(info, "[SentencePiece] Sampling at most {} lines from {}", maxLines, utils::join(trainPaths, ", "));

    std::vector<std::string> sample;
    size_t seenLines = 0;
    for(const auto& trainPath : trainPaths)
      resevoirSampling(sample, seenLines, trainPath, maxLines, maxBytes);

    io::OutputFileStream out(temp);
    for(const auto& line : sample)
        out << line << std::endl;

    LOG(info, "[SentencePiece] Selected {} lines", sample.size());
    return sample.size();
  }

  size_t dumpAll(io::TemporaryFile& temp,
                 const std::vector<std::string>& trainPaths,
                 size_t maxBytes) {
    LOG(info, "[SentencePiece] Selecting all lines from {}", utils::join(trainPaths, ", "));

    size_t seenLines = 0;
    std::string line;
    io::OutputFileStream out(temp);
    for(const auto& trainPath : trainPaths) {
      io::InputFileStream in(trainPath);
      while(getline(in, line)) {
        if(line.size() < maxBytes) {
          out << line << std::endl;
          seenLines++;
        }
      }
    }

    LOG(info, "[SentencePiece] Selected {} lines", seenLines);
    return seenLines;
  }

  void create(const std::string& vocabPath,
              const std::vector<std::string>& trainPaths,
              size_t maxSize) override {

    size_t defaultMaxSize = 32000;
    size_t maxLines = options_->get<size_t>("sentencepiece-max-lines");
    size_t maxBytes = 2048;

    LOG(info, "[SentencePiece] Training SentencePiece vocabulary {}", vocabPath);

    if(maxSize == 0) {
      LOG(info, "[SentencePiece] Vocabulary size is undefined (set with --dim-vocabs ...) - setting to {}", defaultMaxSize);
      maxSize = defaultMaxSize;
    }

    // Create temporary file to hold the sample for the SentencePiece trainer
    io::TemporaryFile temp(options_->get<std::string>("tempdir"), false);
    std::string tempFileName = temp.getFileName();
    LOG(info, "[SentencePiece] Creating temporary file {}", tempFileName);

    size_t seenLines = 0;
    if(maxLines == 0)
      seenLines = dumpAll(temp, trainPaths, maxBytes);
    else
      seenLines = resevoirSamplingAll(temp, trainPaths, maxLines, maxBytes);

    // Compose the SentencePiece training command from filenames and parameters
    std::string sentencePieceOptions = options_->get<std::string>("sentencepiece-options");
    std::stringstream command;
    command
      << " --bos_id=-1 --eos_id=0 --unk_id=1" // these should not be changed as they match Marian defaults
      << " --input="               << tempFileName
      << " --model_prefix="        << vocabPath
      << " --vocab_size="          << maxSize
      << " --max_sentence_length=" << maxBytes
      << " --input_sentence_size=" << seenLines
      << " " << sentencePieceOptions;

    // Train the SentencePiece model
    const auto status = sentencepiece::SentencePieceTrainer::Train(command.str());
    ABORT_IF(!status.ok(),
             "SentencePieceVocab error: {}",
             status.ToString());

    LOG(info, "[SentencePiece] Removing {}", vocabPath + ".vocab");
    ABORT_IF(remove((vocabPath + ".vocab").c_str()) != 0,
             "Could not remove {}",
             vocabPath + ".vocab");

    LOG(info, "[SentencePiece] Renaming {} to {}", vocabPath + ".model", vocabPath);
    ABORT_IF(rename((vocabPath + ".model").c_str(), vocabPath.c_str()) != 0,
             "Could not rename {} to {}",
             vocabPath + ".model", vocabPath);
  }

  void createFake() {
    ABORT("[SentencePiece] Fake SentencePieceVocab not supported");
  }

  Word operator[](const std::string& token) const {
    return (Word)spm_->PieceToId(token);
  }

  const std::string& operator[](Word id) const {
    ABORT_IF(id >= size(), "Unknown word id: ", id);
    return spm_->IdToPiece(id);
  }

  Words encode(const std::string& line, bool addEOS, bool inference) const {
    std::vector<int> spmIds;
    if(inference || alpha_ == 0)
      spm_->Encode(line, &spmIds);
    else
      spm_->SampleEncode(line, -1, alpha_, &spmIds);

    Words words(spmIds.begin(), spmIds.end());

    if(addEOS)
      words.push_back(getEosId());
    return words;
  }

  std::string decode(const Words& sentence, bool ignoreEOS) const {
    std::string line;
    // convert vector of Word to vector of int
    std::vector<int> spmSentence(sentence.begin(), sentence.end());
    spm_->Decode(spmSentence, &line);
    return line;
  }

  size_t size() const {
    return spm_->GetPieceSize();
  }

  int load(const std::string& vocabPath, int /*max*/) {
    LOG(info, "[data] Loading SentencePieceVocab from file {}", vocabPath);

    ABORT_IF(!filesystem::exists(vocabPath),
             "SentencePieceVocab file {} does not exits",
             vocabPath);

    spm_.reset(new sentencepiece::SentencePieceProcessor());
    const auto status = spm_->Load(vocabPath);

    ABORT_IF(!status.ok(),
             "SentencePieceVocab error: {}",
             status.ToString());

    return spm_->GetPieceSize();
  }

};
#endif

Ptr<VocabBase> createSentencePieceVocab(const std::string& vocabPath, Ptr<Options> options, size_t batchIndex) {
  bool isSentencePiece = regex::regex_search(vocabPath, regex::regex("\\.(spm)$"));
  if(isSentencePiece) {
#ifdef USE_SENTENCEPIECE
    return New<SentencePieceVocab>(options, batchIndex);
#else
    batchIndex; options;
    ABORT("*.spm suffix in path {} reserved for SentencePiece models, "
          "but support for SentencePiece is not compiled into Marian. "
          "Try to recompile after `cmake .. -DUSE_SENTENCEPIECE=on [...]`",
          vocabPath);
#endif
  }
  // Not a SentencePiece model based on suffix;
  return nullptr;
}

}
<commit_msg>add size check on sample<commit_after>#include "data/vocab_base.h"

#ifdef USE_SENTENCEPIECE
#include "sentencepiece/src/sentencepiece_processor.h"
#include "sentencepiece/src/sentencepiece_trainer.h"
#endif

#include "common/config.h"
#include "common/options.h"
#include "common/logging.h"
#include "common/filesystem.h"
#include "common/regex.h"

#include <sstream>

namespace marian {

#ifdef USE_SENTENCEPIECE

// Wrapper around https://github.com/google/sentencepiece
class SentencePieceVocab : public VocabBase {
private:
  // Actual SentencePiece processor object
  UPtr<sentencepiece::SentencePieceProcessor> spm_;

  // Sampling factor for subword regularization, disabled when 0
  float alpha_{0};

  // Allowed suffixes for SentencePiece model
  std::vector<std::string> suffixes_ = {".spm"};

  Ptr<Options> options_;
  size_t batchIndex_{0};

  std::mt19937 generator_;
  std::uniform_int_distribution<int> randInt_; // from 0 to INT_MAX

public:
  SentencePieceVocab(Ptr<Options> options, size_t batchIndex)
    : options_(options), batchIndex_(batchIndex), generator_(Config::seed) {

    if(options_->has("sentencepiece-alphas")) {
      auto alphas = options_->get<std::vector<float>>("sentencepiece-alphas");
      if(alphas.size() <= batchIndex)
        alpha_ = 0.f;
      else
        alpha_ = alphas[batchIndex_];

      if(alpha_ > 0)
        LOG(debug,
            "Setting SentencePieceVocab sampling factor to {} for input {}",
            alpha_,
            batchIndex_);
    }

  }

  virtual const std::string& canonicalExtension() const { return suffixes_[0]; }
  virtual const std::vector<std::string>& suffixes() const { return suffixes_; }

  virtual std::string suffix() { return suffixes_[0]; };

  virtual std::string type() const { return "SentencePieceVocab"; }

  virtual Word getEosId() const override { return (Word)spm_->eos_id(); }
  virtual Word getUnkId() const override { return (Word)spm_->unk_id(); }

  // Sample from one file, based on first algorithm from:
  // https://en.wikipedia.org/wiki/Reservoir_sampling
  void resevoirSampling(std::vector<std::string>& sample, size_t& seenLines,
                        const std::string& trainPath, size_t maxLines, size_t maxBytes) {

    ABORT_IF(maxLines == 0, "Sample needs to be larger 0");

    std::unique_ptr<io::InputFileStream> trainStrm(
      trainPath == "stdin" ? new io::InputFileStream(std::cin)
                           : new io::InputFileStream(trainPath)
    );

    std::string line;
    while(getline(*trainStrm, line)) {
      if(line.size() < maxBytes) {
        if(sample.size() < maxLines) {
          sample.push_back(line);
        }
        else {
          size_t i = randInt_(generator_) % (seenLines + 1);
          if(i < maxLines)
            sample[i] = line;
        }
        seenLines++;
      }
    }
  }

  // Iterate over all input files and collect a representative sample via reservoir sampling.
  // The sample will first grow to the desired size and next keep sampling with decreasing
  // probability in the hope to get a uniform sample from the union of all files.
  size_t resevoirSamplingAll(io::TemporaryFile& temp,
                             const std::vector<std::string>& trainPaths,
                             size_t maxLines, size_t maxBytes) {
    LOG(info, "[SentencePiece] Sampling at most {} lines from {}", maxLines, utils::join(trainPaths, ", "));

    std::vector<std::string> sample;
    size_t seenLines = 0;
    for(const auto& trainPath : trainPaths)
      resevoirSampling(sample, seenLines, trainPath, maxLines, maxBytes);

    io::OutputFileStream out(temp);
    for(const auto& line : sample)
        out << line << std::endl;

    LOG(info, "[SentencePiece] Selected {} lines", sample.size());
    return sample.size();
  }

  // Just concatenate all files to a temporary file so SentencePiece can consume it.
  size_t dumpAll(io::TemporaryFile& temp,
                 const std::vector<std::string>& trainPaths,
                 size_t maxBytes) {
    LOG(info, "[SentencePiece] Selecting all lines from {}", utils::join(trainPaths, ", "));

    size_t seenLines = 0;
    std::string line;
    io::OutputFileStream out(temp);
    for(const auto& trainPath : trainPaths) {
      io::InputFileStream in(trainPath);
      while(getline(in, line)) {
        if(line.size() < maxBytes) {
          out << line << std::endl;
          seenLines++;
        }
      }
    }

    LOG(info, "[SentencePiece] Selected {} lines", seenLines);
    return seenLines;
  }

  void create(const std::string& vocabPath,
              const std::vector<std::string>& trainPaths,
              size_t maxSize) override {

    size_t defaultMaxSize = 32000;
    size_t maxLines = options_->get<size_t>("sentencepiece-max-lines");
    size_t maxBytes = 2048;

    LOG(info, "[SentencePiece] Training SentencePiece vocabulary {}", vocabPath);

    if(maxSize == 0) {
      LOG(info, "[SentencePiece] Vocabulary size is undefined (set with --dim-vocabs ...) - setting to {}", defaultMaxSize);
      maxSize = defaultMaxSize;
    }

    // Create temporary file to hold the sample for the SentencePiece trainer
    io::TemporaryFile temp(options_->get<std::string>("tempdir"), false);
    std::string tempFileName = temp.getFileName();
    LOG(info, "[SentencePiece] Creating temporary file {}", tempFileName);

    size_t seenLines = 0;
    if(maxLines == 0)
      seenLines = dumpAll(temp, trainPaths, maxBytes);
    else
      seenLines = resevoirSamplingAll(temp, trainPaths, maxLines, maxBytes);

    // Compose the SentencePiece training command from filenames and parameters0
    std::stringstream command;
    command
      << " --bos_id=-1 --eos_id=0 --unk_id=1" // these should not be changed as they match Marian defaults
      << " --input="               << tempFileName
      << " --model_prefix="        << vocabPath
      << " --vocab_size="          << maxSize
      << " --max_sentence_length=" << maxBytes
      << " --input_sentence_size=" << seenLines
      << " " << options_->get<std::string>("sentencepiece-options"); // these are SentencePiece command line options

    // Train the SentencePiece model
    const auto status = sentencepiece::SentencePieceTrainer::Train(command.str());
    ABORT_IF(!status.ok(),
             "SentencePieceVocab error: {}",
             status.ToString());

    LOG(info, "[SentencePiece] Removing {}", vocabPath + ".vocab");
    ABORT_IF(remove((vocabPath + ".vocab").c_str()) != 0,
             "Could not remove {}",
             vocabPath + ".vocab");

    LOG(info, "[SentencePiece] Renaming {} to {}", vocabPath + ".model", vocabPath);
    ABORT_IF(rename((vocabPath + ".model").c_str(), vocabPath.c_str()) != 0,
             "Could not rename {} to {}",
             vocabPath + ".model", vocabPath);
  }

  void createFake() {
    ABORT("[SentencePiece] Fake SentencePieceVocab not supported");
  }

  Word operator[](const std::string& token) const {
    return (Word)spm_->PieceToId(token);
  }

  const std::string& operator[](Word id) const {
    ABORT_IF(id >= size(), "Unknown word id: ", id);
    return spm_->IdToPiece(id);
  }

  Words encode(const std::string& line, bool addEOS, bool inference) const {
    std::vector<int> spmIds;
    if(inference || alpha_ == 0)
      spm_->Encode(line, &spmIds);
    else
      spm_->SampleEncode(line, -1, alpha_, &spmIds);

    Words words(spmIds.begin(), spmIds.end());

    if(addEOS)
      words.push_back(getEosId());
    return words;
  }

  std::string decode(const Words& sentence, bool ignoreEOS) const {
    std::string line;
    // convert vector of Word to vector of int
    std::vector<int> spmSentence(sentence.begin(), sentence.end());
    spm_->Decode(spmSentence, &line);
    return line;
  }

  size_t size() const {
    return spm_->GetPieceSize();
  }

  int load(const std::string& vocabPath, int /*max*/) {
    LOG(info, "[data] Loading SentencePieceVocab from file {}", vocabPath);

    ABORT_IF(!filesystem::exists(vocabPath),
             "SentencePieceVocab file {} does not exits",
             vocabPath);

    spm_.reset(new sentencepiece::SentencePieceProcessor());
    const auto status = spm_->Load(vocabPath);

    ABORT_IF(!status.ok(),
             "SentencePieceVocab error: {}",
             status.ToString());

    return spm_->GetPieceSize();
  }

};
#endif

Ptr<VocabBase> createSentencePieceVocab(const std::string& vocabPath, Ptr<Options> options, size_t batchIndex) {
  bool isSentencePiece = regex::regex_search(vocabPath, regex::regex("\\.(spm)$"));
  if(isSentencePiece) {
#ifdef USE_SENTENCEPIECE
    return New<SentencePieceVocab>(options, batchIndex);
#else
    batchIndex; options;
    ABORT("*.spm suffix in path {} reserved for SentencePiece models, "
          "but support for SentencePiece is not compiled into Marian. "
          "Try to recompile after `cmake .. -DUSE_SENTENCEPIECE=on [...]`",
          vocabPath);
#endif
  }
  // Not a SentencePiece model based on suffix;
  return nullptr;
}

}
<|endoftext|>


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

#include "dawn_native/ShaderModule.h"

#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Device.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/PipelineLayout.h"

#include <spirv-cross/spirv_cross.hpp>

namespace dawn_native {

    MaybeError ValidateShaderModuleDescriptor(DeviceBase*, const ShaderModuleDescriptor*) {
        // TODO(cwallez@chromium.org): Use spirv-val to check the module is well-formed
        return {};
    }

    // ShaderModuleBase

    ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor*)
        : mDevice(device) {
    }

    DeviceBase* ShaderModuleBase::GetDevice() const {
        return mDevice;
    }

    void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
        // TODO(cwallez@chromium.org): make errors here builder-level
        // currently errors here do not prevent the shadermodule from being used
        const auto& resources = compiler.get_shader_resources();

        switch (compiler.get_execution_model()) {
            case spv::ExecutionModelVertex:
                mExecutionModel = dawn::ShaderStage::Vertex;
                break;
            case spv::ExecutionModelFragment:
                mExecutionModel = dawn::ShaderStage::Fragment;
                break;
            case spv::ExecutionModelGLCompute:
                mExecutionModel = dawn::ShaderStage::Compute;
                break;
            default:
                UNREACHABLE();
        }

        // Extract push constants
        mPushConstants.mask.reset();
        mPushConstants.sizes.fill(0);
        mPushConstants.types.fill(PushConstantType::Int);

        if (resources.push_constant_buffers.size() > 0) {
            auto interfaceBlock = resources.push_constant_buffers[0];

            const auto& blockType = compiler.get_type(interfaceBlock.type_id);
            ASSERT(blockType.basetype == spirv_cross::SPIRType::Struct);

            for (uint32_t i = 0; i < blockType.member_types.size(); i++) {
                ASSERT(compiler.get_member_decoration_mask(blockType.self, i) &
                       1ull << spv::DecorationOffset);
                uint32_t offset =
                    compiler.get_member_decoration(blockType.self, i, spv::DecorationOffset);
                ASSERT(offset % 4 == 0);
                offset /= 4;

                auto memberType = compiler.get_type(blockType.member_types[i]);
                PushConstantType constantType;
                if (memberType.basetype == spirv_cross::SPIRType::Int) {
                    constantType = PushConstantType::Int;
                } else if (memberType.basetype == spirv_cross::SPIRType::UInt) {
                    constantType = PushConstantType::UInt;
                } else {
                    ASSERT(memberType.basetype == spirv_cross::SPIRType::Float);
                    constantType = PushConstantType::Float;
                }

                // TODO(cwallez@chromium.org): check for overflows and make the logic better take
                // into account things like the array of types with padding.
                uint32_t size = memberType.vecsize * memberType.columns;
                // Handle unidimensional arrays
                if (!memberType.array.empty()) {
                    size *= memberType.array[0];
                }

                if (offset + size > kMaxPushConstants) {
                    mDevice->HandleError("Push constant block too big in the SPIRV");
                    return;
                }

                mPushConstants.mask.set(offset);
                mPushConstants.names[offset] =
                    interfaceBlock.name + "." + compiler.get_member_name(blockType.self, i);
                mPushConstants.sizes[offset] = size;
                mPushConstants.types[offset] = constantType;
            }
        }

        // Fill in bindingInfo with the SPIRV bindings
        auto ExtractResourcesBinding = [this](const std::vector<spirv_cross::Resource>& resources,
                                              const spirv_cross::Compiler& compiler,
                                              dawn::BindingType bindingType) {
            constexpr uint64_t requiredBindingDecorationMask =
                (1ull << spv::DecorationBinding) | (1ull << spv::DecorationDescriptorSet);

            for (const auto& resource : resources) {
                ASSERT((compiler.get_decoration_mask(resource.id) &
                        requiredBindingDecorationMask) == requiredBindingDecorationMask);
                uint32_t binding = compiler.get_decoration(resource.id, spv::DecorationBinding);
                uint32_t set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);

                if (binding >= kMaxBindingsPerGroup || set >= kMaxBindGroups) {
                    mDevice->HandleError("Binding over limits in the SPIRV");
                    continue;
                }

                auto& info = mBindingInfo[set][binding];
                info.used = true;
                info.id = resource.id;
                info.base_type_id = resource.base_type_id;
                info.type = bindingType;
            }
        };

        ExtractResourcesBinding(resources.uniform_buffers, compiler,
                                dawn::BindingType::UniformBuffer);
        ExtractResourcesBinding(resources.separate_images, compiler,
                                dawn::BindingType::SampledTexture);
        ExtractResourcesBinding(resources.separate_samplers, compiler, dawn::BindingType::Sampler);
        ExtractResourcesBinding(resources.storage_buffers, compiler,
                                dawn::BindingType::StorageBuffer);

        // Extract the vertex attributes
        if (mExecutionModel == dawn::ShaderStage::Vertex) {
            for (const auto& attrib : resources.stage_inputs) {
                ASSERT(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation));
                uint32_t location = compiler.get_decoration(attrib.id, spv::DecorationLocation);

                if (location >= kMaxVertexAttributes) {
                    mDevice->HandleError("Attribute location over limits in the SPIRV");
                    return;
                }

                mUsedVertexAttributes.set(location);
            }

            // Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives them
            // all the location 0, causing a compile error.
            for (const auto& attrib : resources.stage_outputs) {
                if (!(compiler.get_decoration_mask(attrib.id) &
                      (1ull << spv::DecorationLocation))) {
                    mDevice->HandleError("Need location qualifier on vertex output");
                    return;
                }
            }
        }

        if (mExecutionModel == dawn::ShaderStage::Fragment) {
            // Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives them
            // all the location 0, causing a compile error.
            for (const auto& attrib : resources.stage_inputs) {
                if (!(compiler.get_decoration_mask(attrib.id) &
                      (1ull << spv::DecorationLocation))) {
                    mDevice->HandleError("Need location qualifier on fragment input");
                    return;
                }
            }
        }
    }

    const ShaderModuleBase::PushConstantInfo& ShaderModuleBase::GetPushConstants() const {
        return mPushConstants;
    }

    const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const {
        return mBindingInfo;
    }

    const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const {
        return mUsedVertexAttributes;
    }

    dawn::ShaderStage ShaderModuleBase::GetExecutionModel() const {
        return mExecutionModel;
    }

    bool ShaderModuleBase::IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout) {
        for (size_t group = 0; group < kMaxBindGroups; ++group) {
            if (!IsCompatibleWithBindGroupLayout(group, layout->GetBindGroupLayout(group))) {
                return false;
            }
        }
        return true;
    }

    bool ShaderModuleBase::IsCompatibleWithBindGroupLayout(size_t group,
                                                           const BindGroupLayoutBase* layout) {
        const auto& layoutInfo = layout->GetBindingInfo();
        for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) {
            const auto& moduleInfo = mBindingInfo[group][i];

            if (!moduleInfo.used) {
                continue;
            }

            if (moduleInfo.type != layoutInfo.types[i]) {
                return false;
            }
            if ((layoutInfo.visibilities[i] & StageBit(mExecutionModel)) == 0) {
                return false;
            }
        }

        return true;
    }

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

#include "dawn_native/ShaderModule.h"

#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Device.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/PipelineLayout.h"

#include <spirv-cross/spirv_cross.hpp>

namespace dawn_native {

    MaybeError ValidateShaderModuleDescriptor(DeviceBase*, const ShaderModuleDescriptor* descriptor) {
        DAWN_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
        // TODO(cwallez@chromium.org): Use spirv-val to check the module is well-formed
        return {};
    }

    // ShaderModuleBase

    ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor*)
        : mDevice(device) {
    }

    DeviceBase* ShaderModuleBase::GetDevice() const {
        return mDevice;
    }

    void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
        // TODO(cwallez@chromium.org): make errors here builder-level
        // currently errors here do not prevent the shadermodule from being used
        const auto& resources = compiler.get_shader_resources();

        switch (compiler.get_execution_model()) {
            case spv::ExecutionModelVertex:
                mExecutionModel = dawn::ShaderStage::Vertex;
                break;
            case spv::ExecutionModelFragment:
                mExecutionModel = dawn::ShaderStage::Fragment;
                break;
            case spv::ExecutionModelGLCompute:
                mExecutionModel = dawn::ShaderStage::Compute;
                break;
            default:
                UNREACHABLE();
        }

        // Extract push constants
        mPushConstants.mask.reset();
        mPushConstants.sizes.fill(0);
        mPushConstants.types.fill(PushConstantType::Int);

        if (resources.push_constant_buffers.size() > 0) {
            auto interfaceBlock = resources.push_constant_buffers[0];

            const auto& blockType = compiler.get_type(interfaceBlock.type_id);
            ASSERT(blockType.basetype == spirv_cross::SPIRType::Struct);

            for (uint32_t i = 0; i < blockType.member_types.size(); i++) {
                ASSERT(compiler.get_member_decoration_mask(blockType.self, i) &
                       1ull << spv::DecorationOffset);
                uint32_t offset =
                    compiler.get_member_decoration(blockType.self, i, spv::DecorationOffset);
                ASSERT(offset % 4 == 0);
                offset /= 4;

                auto memberType = compiler.get_type(blockType.member_types[i]);
                PushConstantType constantType;
                if (memberType.basetype == spirv_cross::SPIRType::Int) {
                    constantType = PushConstantType::Int;
                } else if (memberType.basetype == spirv_cross::SPIRType::UInt) {
                    constantType = PushConstantType::UInt;
                } else {
                    ASSERT(memberType.basetype == spirv_cross::SPIRType::Float);
                    constantType = PushConstantType::Float;
                }

                // TODO(cwallez@chromium.org): check for overflows and make the logic better take
                // into account things like the array of types with padding.
                uint32_t size = memberType.vecsize * memberType.columns;
                // Handle unidimensional arrays
                if (!memberType.array.empty()) {
                    size *= memberType.array[0];
                }

                if (offset + size > kMaxPushConstants) {
                    mDevice->HandleError("Push constant block too big in the SPIRV");
                    return;
                }

                mPushConstants.mask.set(offset);
                mPushConstants.names[offset] =
                    interfaceBlock.name + "." + compiler.get_member_name(blockType.self, i);
                mPushConstants.sizes[offset] = size;
                mPushConstants.types[offset] = constantType;
            }
        }

        // Fill in bindingInfo with the SPIRV bindings
        auto ExtractResourcesBinding = [this](const std::vector<spirv_cross::Resource>& resources,
                                              const spirv_cross::Compiler& compiler,
                                              dawn::BindingType bindingType) {
            constexpr uint64_t requiredBindingDecorationMask =
                (1ull << spv::DecorationBinding) | (1ull << spv::DecorationDescriptorSet);

            for (const auto& resource : resources) {
                ASSERT((compiler.get_decoration_mask(resource.id) &
                        requiredBindingDecorationMask) == requiredBindingDecorationMask);
                uint32_t binding = compiler.get_decoration(resource.id, spv::DecorationBinding);
                uint32_t set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);

                if (binding >= kMaxBindingsPerGroup || set >= kMaxBindGroups) {
                    mDevice->HandleError("Binding over limits in the SPIRV");
                    continue;
                }

                auto& info = mBindingInfo[set][binding];
                info.used = true;
                info.id = resource.id;
                info.base_type_id = resource.base_type_id;
                info.type = bindingType;
            }
        };

        ExtractResourcesBinding(resources.uniform_buffers, compiler,
                                dawn::BindingType::UniformBuffer);
        ExtractResourcesBinding(resources.separate_images, compiler,
                                dawn::BindingType::SampledTexture);
        ExtractResourcesBinding(resources.separate_samplers, compiler, dawn::BindingType::Sampler);
        ExtractResourcesBinding(resources.storage_buffers, compiler,
                                dawn::BindingType::StorageBuffer);

        // Extract the vertex attributes
        if (mExecutionModel == dawn::ShaderStage::Vertex) {
            for (const auto& attrib : resources.stage_inputs) {
                ASSERT(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation));
                uint32_t location = compiler.get_decoration(attrib.id, spv::DecorationLocation);

                if (location >= kMaxVertexAttributes) {
                    mDevice->HandleError("Attribute location over limits in the SPIRV");
                    return;
                }

                mUsedVertexAttributes.set(location);
            }

            // Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives them
            // all the location 0, causing a compile error.
            for (const auto& attrib : resources.stage_outputs) {
                if (!(compiler.get_decoration_mask(attrib.id) &
                      (1ull << spv::DecorationLocation))) {
                    mDevice->HandleError("Need location qualifier on vertex output");
                    return;
                }
            }
        }

        if (mExecutionModel == dawn::ShaderStage::Fragment) {
            // Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives them
            // all the location 0, causing a compile error.
            for (const auto& attrib : resources.stage_inputs) {
                if (!(compiler.get_decoration_mask(attrib.id) &
                      (1ull << spv::DecorationLocation))) {
                    mDevice->HandleError("Need location qualifier on fragment input");
                    return;
                }
            }
        }
    }

    const ShaderModuleBase::PushConstantInfo& ShaderModuleBase::GetPushConstants() const {
        return mPushConstants;
    }

    const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const {
        return mBindingInfo;
    }

    const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const {
        return mUsedVertexAttributes;
    }

    dawn::ShaderStage ShaderModuleBase::GetExecutionModel() const {
        return mExecutionModel;
    }

    bool ShaderModuleBase::IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout) {
        for (size_t group = 0; group < kMaxBindGroups; ++group) {
            if (!IsCompatibleWithBindGroupLayout(group, layout->GetBindGroupLayout(group))) {
                return false;
            }
        }
        return true;
    }

    bool ShaderModuleBase::IsCompatibleWithBindGroupLayout(size_t group,
                                                           const BindGroupLayoutBase* layout) {
        const auto& layoutInfo = layout->GetBindingInfo();
        for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) {
            const auto& moduleInfo = mBindingInfo[group][i];

            if (!moduleInfo.used) {
                continue;
            }

            if (moduleInfo.type != layoutInfo.types[i]) {
                return false;
            }
            if ((layoutInfo.visibilities[i] & StageBit(mExecutionModel)) == 0) {
                return false;
            }
        }

        return true;
    }

}  // namespace dawn_native
<|endoftext|>


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

#include "draco/compression/decode.h"
#include "draco/core/cycle_timer.h"
#include "draco/io/obj_encoder.h"
#include "draco/io/parser_utils.h"
#include "draco/io/ply_encoder.h"

namespace {

struct Options {
  Options();

  std::string input;
  std::string output;
};

Options::Options() {}

void Usage() {
  printf("Usage: draco_decoder [options] -i input\n");
  printf("\n");
  printf("Main options:\n");
  printf("  -h | -?               show help.\n");
  printf("  -o <output>           output file name.\n");
}

int ReturnError(const draco::Status &status) {
  printf("Failed to decode the input file %s\n", status.error_msg());
  return -1;
}

}  // namespace

int main(int argc, char **argv) {
  Options options;
  const int argc_check = argc - 1;

  for (int i = 1; i < argc; ++i) {
    if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) {
      Usage();
      return 0;
    } else if (!strcmp("-i", argv[i]) && i < argc_check) {
      options.input = argv[++i];
    } else if (!strcmp("-o", argv[i]) && i < argc_check) {
      options.output = argv[++i];
    }
  }
  if (argc < 3 || options.input.empty()) {
    Usage();
    return -1;
  }

  std::ifstream input_file(options.input, std::ios::binary);
  if (!input_file) {
    printf("Failed opening the input file.\n");
    return -1;
  }

  // Read the file stream into a buffer.
  std::streampos file_size = 0;
  input_file.seekg(0, std::ios::end);
  file_size = input_file.tellg() - file_size;
  input_file.seekg(0, std::ios::beg);
  std::vector<char> data(file_size);
  input_file.read(data.data(), file_size);

  if (data.empty()) {
    printf("Empty input file.\n");
    return -1;
  }

  // Create a draco decoding buffer. Note that no data is copied in this step.
  draco::DecoderBuffer buffer;
  buffer.Init(data.data(), data.size());

  draco::CycleTimer timer;
  // Decode the input data into a geometry.
  std::unique_ptr<draco::PointCloud> pc;
  draco::Mesh *mesh = nullptr;
  auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer);
  if (!type_statusor.ok()) {
    return ReturnError(type_statusor.status());
  }
  const draco::EncodedGeometryType geom_type = type_statusor.value();
  if (geom_type == draco::TRIANGULAR_MESH) {
    timer.Start();
    draco::Decoder decoder;
    auto statusor = decoder.DecodeMeshFromBuffer(&buffer);
    if (!statusor.ok()) {
      return ReturnError(statusor.status());
    }
    std::unique_ptr<draco::Mesh> in_mesh = std::move(statusor).value();
    timer.Stop();
    if (in_mesh) {
      mesh = in_mesh.get();
      pc = std::move(in_mesh);
    }
  } else if (geom_type == draco::POINT_CLOUD) {
    // Failed to decode it as mesh, so let's try to decode it as a point cloud.
    timer.Start();
    draco::Decoder decoder;
    auto statusor = decoder.DecodePointCloudFromBuffer(&buffer);
    if (!statusor.ok()) {
      return ReturnError(statusor.status());
    }
    pc = std::move(statusor).value();
    timer.Stop();
  }

  if (pc == nullptr) {
    printf("Failed to decode the input file.\n");
    return -1;
  }

  if (options.output.empty()) {
    // Save the output model into a ply file.
    options.output = options.input + ".ply";
  }

  // Save the decoded geometry into a file.
  // TODO(fgalligan): Change extension code to look for '.'.
  const std::string extension = draco::parser::ToLower(
      options.output.size() >= 4
          ? options.output.substr(options.output.size() - 4)
          : options.output);

  if (extension == ".obj") {
    draco::ObjEncoder obj_encoder;
    if (mesh) {
      if (!obj_encoder.EncodeToFile(*mesh, options.output)) {
        printf("Failed to store the decoded mesh as OBJ.\n");
        return -1;
      }
    } else {
      if (!obj_encoder.EncodeToFile(*pc.get(), options.output)) {
        printf("Failed to store the decoded point cloud as OBJ.\n");
        return -1;
      }
    }
  } else if (extension == ".ply") {
    draco::PlyEncoder ply_encoder;
    if (mesh) {
      if (!ply_encoder.EncodeToFile(*mesh, options.output)) {
        printf("Failed to store the decoded mesh as PLY.\n");
        return -1;
      }
    } else {
      if (!ply_encoder.EncodeToFile(*pc.get(), options.output)) {
        printf("Failed to store the decoded point cloud as PLY.\n");
        return -1;
      }
    }
  } else {
    printf(
        "Invalid extension of the output file. Use either .ply, .obj, or "
        ".gltf\n");
    return -1;
  }
  printf("Decoded geometry saved to %s (%" PRId64 " ms to decode)\n",
         options.output.c_str(), timer.GetInMs());
  return 0;
}
<commit_msg>Add -v param, display dracdo_decoder version<commit_after>// Copyright 2016 The Draco Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <cinttypes>
#include <fstream>

#include "draco/compression/decode.h"
#include "draco/core/draco_version.h"
#include "draco/core/cycle_timer.h"
#include "draco/io/obj_encoder.h"
#include "draco/io/parser_utils.h"
#include "draco/io/ply_encoder.h"

namespace {

struct Options {
  Options();

  std::string input;
  std::string output;
};

Options::Options() {}

void Usage() {
  printf("Usage: draco_decoder [options] -i input\n");
  printf("\n");
  printf("Main options:\n");
  printf("  -h | -?               show help.\n");
  printf("  -o <output>           output file name.\n");
}

int ReturnError(const draco::Status &status) {
  printf("Failed to decode the input file %s\n", status.error_msg());
  return -1;
}

}  // namespace

int main(int argc, char **argv) {
  Options options;
  const int argc_check = argc - 1;

  for (int i = 1; i < argc; ++i) {
    if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) {
      Usage();
      return 0;
    } else if (!strcmp("-v", argv[i])) {
        printf("draco_decoder version: %s\n", draco::Version());
	return 0;
    } else if (!strcmp("-i", argv[i]) && i < argc_check) {
      options.input = argv[++i];
    } else if (!strcmp("-o", argv[i]) && i < argc_check) {
      options.output = argv[++i];
    }
  }
  if (argc < 3 || options.input.empty()) {
    Usage();
    return -1;
  }

  std::ifstream input_file(options.input, std::ios::binary);
  if (!input_file) {
    printf("Failed opening the input file.\n");
    return -1;
  }

  // Read the file stream into a buffer.
  std::streampos file_size = 0;
  input_file.seekg(0, std::ios::end);
  file_size = input_file.tellg() - file_size;
  input_file.seekg(0, std::ios::beg);
  std::vector<char> data(file_size);
  input_file.read(data.data(), file_size);

  if (data.empty()) {
    printf("Empty input file.\n");
    return -1;
  }

  // Create a draco decoding buffer. Note that no data is copied in this step.
  draco::DecoderBuffer buffer;
  buffer.Init(data.data(), data.size());

  draco::CycleTimer timer;
  // Decode the input data into a geometry.
  std::unique_ptr<draco::PointCloud> pc;
  draco::Mesh *mesh = nullptr;
  auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer);
  if (!type_statusor.ok()) {
    return ReturnError(type_statusor.status());
  }
  const draco::EncodedGeometryType geom_type = type_statusor.value();
  if (geom_type == draco::TRIANGULAR_MESH) {
    timer.Start();
    draco::Decoder decoder;
    auto statusor = decoder.DecodeMeshFromBuffer(&buffer);
    if (!statusor.ok()) {
      return ReturnError(statusor.status());
    }
    std::unique_ptr<draco::Mesh> in_mesh = std::move(statusor).value();
    timer.Stop();
    if (in_mesh) {
      mesh = in_mesh.get();
      pc = std::move(in_mesh);
    }
  } else if (geom_type == draco::POINT_CLOUD) {
    // Failed to decode it as mesh, so let's try to decode it as a point cloud.
    timer.Start();
    draco::Decoder decoder;
    auto statusor = decoder.DecodePointCloudFromBuffer(&buffer);
    if (!statusor.ok()) {
      return ReturnError(statusor.status());
    }
    pc = std::move(statusor).value();
    timer.Stop();
  }

  if (pc == nullptr) {
    printf("Failed to decode the input file.\n");
    return -1;
  }

  if (options.output.empty()) {
    // Save the output model into a ply file.
    options.output = options.input + ".ply";
  }

  // Save the decoded geometry into a file.
  // TODO(fgalligan): Change extension code to look for '.'.
  const std::string extension = draco::parser::ToLower(
      options.output.size() >= 4
          ? options.output.substr(options.output.size() - 4)
          : options.output);

  if (extension == ".obj") {
    draco::ObjEncoder obj_encoder;
    if (mesh) {
      if (!obj_encoder.EncodeToFile(*mesh, options.output)) {
        printf("Failed to store the decoded mesh as OBJ.\n");
        return -1;
      }
    } else {
      if (!obj_encoder.EncodeToFile(*pc.get(), options.output)) {
        printf("Failed to store the decoded point cloud as OBJ.\n");
        return -1;
      }
    }
  } else if (extension == ".ply") {
    draco::PlyEncoder ply_encoder;
    if (mesh) {
      if (!ply_encoder.EncodeToFile(*mesh, options.output)) {
        printf("Failed to store the decoded mesh as PLY.\n");
        return -1;
      }
    } else {
      if (!ply_encoder.EncodeToFile(*pc.get(), options.output)) {
        printf("Failed to store the decoded point cloud as PLY.\n");
        return -1;
      }
    }
  } else {
    printf(
        "Invalid extension of the output file. Use either .ply, .obj, or "
        ".gltf\n");
    return -1;
  }
  printf("Decoded geometry saved to %s (%" PRId64 " ms to decode)\n",
         options.output.c_str(), timer.GetInMs());
  return 0;
}
<|endoftext|>


<commit_before>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2012 Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
 *
 * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "edit-display-name-button.h"

#include <QtGui/QVBoxLayout>
#include <QtGui/QLabel>

#include <KDE/KDialog>
#include <KDE/KLineEdit>
#include <KDE/KLocalizedString>
#include <KDE/KDebug>

#include <TelepathyQt/Account>
#include <TelepathyQt/PendingOperation>

class EditDisplayNameDialog : public KDialog
{
    Q_OBJECT
    Q_DISABLE_COPY(EditDisplayNameDialog)

public:
    EditDisplayNameDialog(Tp::AccountPtr account,
                          QWidget* parent = 0,
                          Qt::WFlags flags = 0);
    virtual ~EditDisplayNameDialog();

    QString displayName() const;

private Q_SLOTS:
    void onTextChanged(const QString &text);

private:
    Tp::AccountPtr m_account;
    KLineEdit *m_displayNameLineEdit;
};

EditDisplayNameDialog::EditDisplayNameDialog(Tp::AccountPtr account,
                                             QWidget* parent,
                                             Qt::WFlags flags)
    : KDialog(parent, flags),
      m_account(account)
{
    setCaption(i18n("Edit Display Name"));
    setButtons( KDialog::Ok | KDialog::Cancel );
    setWindowIcon(KIcon(QLatin1String("telepathy-kde")));
    setFixedSize(250, 150);
    enableButtonOk(false);

    QVBoxLayout *mainLayout = new QVBoxLayout(this);

    QHBoxLayout *topLayout = new QHBoxLayout(this);

    QLabel *topLabel = new QLabel(i18n("Choose a new display name for your account"), this);
    topLabel->setWordWrap(true);
    QFont font = topLabel->font();
    font.setBold(true);
    topLabel->setFont(font);
    topLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);

    QLabel *icon = new QLabel;
    icon->setPixmap(KIcon(account->iconName()).pixmap(KIconLoader::SizeMedium));
    icon->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

    topLayout->addWidget(topLabel);
    topLayout->addStretch();
    topLayout->addWidget(icon);

    mainLayout->addLayout(topLayout);

    m_displayNameLineEdit = new KLineEdit(account->displayName(), this);
    mainLayout->addWidget(m_displayNameLineEdit);

    QLabel *bottomLabel = new QLabel(i18n("A display name is your local alias for the account, only you will see it."), this);
    bottomLabel->setWordWrap(true);
    mainLayout->addWidget(bottomLabel);

    QWidget * mainWidget = new QWidget(this);
    mainWidget->setLayout(mainLayout);
    setMainWidget(mainWidget);

    connect(m_displayNameLineEdit, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString)));
}

EditDisplayNameDialog::~EditDisplayNameDialog()
{
}

void EditDisplayNameDialog::onTextChanged(const QString& text)
{
    enableButtonOk(text != m_account->displayName());
}

QString EditDisplayNameDialog::displayName() const
{
    return m_displayNameLineEdit->text();
}

EditDisplayNameButton::EditDisplayNameButton(QWidget* parent) :
    KPushButton(parent)
{
    connect(this,
            SIGNAL(clicked(bool)),
            SLOT(onClicked()));
}

EditDisplayNameButton::~EditDisplayNameButton()
{
}

void EditDisplayNameButton::setAccount(Tp::AccountPtr account)
{
    m_account = account;
}

Tp::AccountPtr EditDisplayNameButton::account() const
{
    return m_account;
}

void EditDisplayNameButton::onClicked()
{
    if (!m_account.isNull() && m_account->isValid()) {
        EditDisplayNameDialog *dialog = new EditDisplayNameDialog(m_account, this);
        dialog->exec();
        if (dialog->result() == KDialog::Accepted) {
            kDebug() << "Setting display name" << dialog->displayName() << "for account" << account()->uniqueIdentifier();
            Tp::PendingOperation *op = m_account->setDisplayName(dialog->displayName());
            connect(op, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onFinished(Tp::PendingOperation*)));
        }
    }
}

void EditDisplayNameButton::onFinished(Tp::PendingOperation* op)
{
    if (op->isError()) {
        kWarning() << "Cannot set display name" << op->errorName() << op->errorMessage();
    }
}

#include "edit-display-name-button.moc"
#include "moc_edit-display-name-button.cpp"
<commit_msg>Always enable OK button<commit_after>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2012 Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
 *
 * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "edit-display-name-button.h"

#include <QtGui/QVBoxLayout>
#include <QtGui/QLabel>

#include <KDE/KDialog>
#include <KDE/KLineEdit>
#include <KDE/KLocalizedString>
#include <KDE/KDebug>

#include <TelepathyQt/Account>
#include <TelepathyQt/PendingOperation>

class EditDisplayNameDialog : public KDialog
{
    Q_OBJECT
    Q_DISABLE_COPY(EditDisplayNameDialog)

public:
    EditDisplayNameDialog(Tp::AccountPtr account,
                          QWidget* parent = 0,
                          Qt::WFlags flags = 0);
    virtual ~EditDisplayNameDialog();

    QString displayName() const;

private:
    Tp::AccountPtr m_account;
    KLineEdit *m_displayNameLineEdit;
};

EditDisplayNameDialog::EditDisplayNameDialog(Tp::AccountPtr account,
                                             QWidget* parent,
                                             Qt::WFlags flags)
    : KDialog(parent, flags),
      m_account(account)
{
    setCaption(i18n("Edit Display Name"));
    setButtons( KDialog::Ok | KDialog::Cancel );
    setWindowIcon(KIcon(QLatin1String("telepathy-kde")));
    setFixedSize(250, 150);

    QVBoxLayout *mainLayout = new QVBoxLayout(this);

    QHBoxLayout *topLayout = new QHBoxLayout(this);

    QLabel *topLabel = new QLabel(i18n("Choose a new display name for your account"), this);
    topLabel->setWordWrap(true);
    QFont font = topLabel->font();
    font.setBold(true);
    topLabel->setFont(font);
    topLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);

    QLabel *icon = new QLabel;
    icon->setPixmap(KIcon(account->iconName()).pixmap(KIconLoader::SizeMedium));
    icon->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

    topLayout->addWidget(topLabel);
    topLayout->addStretch();
    topLayout->addWidget(icon);

    mainLayout->addLayout(topLayout);

    m_displayNameLineEdit = new KLineEdit(account->displayName(), this);
    mainLayout->addWidget(m_displayNameLineEdit);

    QLabel *bottomLabel = new QLabel(i18n("A display name is your local alias for the account, only you will see it."), this);
    bottomLabel->setWordWrap(true);
    mainLayout->addWidget(bottomLabel);

    QWidget * mainWidget = new QWidget(this);
    mainWidget->setLayout(mainLayout);
    setMainWidget(mainWidget);
}

EditDisplayNameDialog::~EditDisplayNameDialog()
{
}

QString EditDisplayNameDialog::displayName() const
{
    return m_displayNameLineEdit->text();
}

EditDisplayNameButton::EditDisplayNameButton(QWidget* parent) :
    KPushButton(parent)
{
    connect(this,
            SIGNAL(clicked(bool)),
            SLOT(onClicked()));
}

EditDisplayNameButton::~EditDisplayNameButton()
{
}

void EditDisplayNameButton::setAccount(Tp::AccountPtr account)
{
    m_account = account;
}

Tp::AccountPtr EditDisplayNameButton::account() const
{
    return m_account;
}

void EditDisplayNameButton::onClicked()
{
    if (!m_account.isNull() && m_account->isValid()) {
        EditDisplayNameDialog *dialog = new EditDisplayNameDialog(m_account, this);
        dialog->exec();
        if (dialog->result() == KDialog::Accepted && dialog->displayName() != m_account->displayName()) {
            kDebug() << "Setting display name" << dialog->displayName() << "for account" << account()->uniqueIdentifier();
            Tp::PendingOperation *op = m_account->setDisplayName(dialog->displayName());
            connect(op, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onFinished(Tp::PendingOperation*)));
        }
    }
}

void EditDisplayNameButton::onFinished(Tp::PendingOperation* op)
{
    if (op->isError()) {
        kWarning() << "Cannot set display name" << op->errorName() << op->errorMessage();
    }
}

#include "edit-display-name-button.moc"
#include "moc_edit-display-name-button.cpp"
<|endoftext|>