<commit_before>#include "mainwindow.h"
#include <cmath>

/**
 * Performs appropriate actions every time timer is called.
 *

 grab keyboard x error bad window
 merrick said it seems like an issue that you can't fix with my code, but rather something about
 qt or the vm

 get rid of player image, set player coordinates, set explosion image to that location,
 recreate player

 * @return nothing
 */
void MainWindow::handleTimer()
{
	bg->scroll(0, WINDOW_MAX_X);
	bg2->scroll(0, WINDOW_MAX_X);

	c->move();
	a->move();
	d->move();
	mb->move();
	t->move();
	moveCount++;

	/**
	if(mousePressed)
	{
		p->moveUp(game_min_y);
	}
	else if(moveCount == 15)
	{
		moveCount = 0;
		p->moveDown(game_min_y);
	}
	**/

}

/**
 * Function is called every time a tile is clicked.
 *
 * @param e Mouse event
 * @return nothing
 */
void MainWindow::keyPressEvent(QKeyEvent *e)
{
	//setFocusPolicy(Qt::StrongFocus);
	//std::cout<<"key";
	switch(e->key())
	{
		case Qt::Key_Up:
			std::cout<<"Up\n";
			p->moveUp(game_min_y);
			p->moveUp(game_min_y);
			p->moveUp(game_min_y);
			break;
		case Qt::Key_Down:
			std::cout<<"Down\n";
			p->moveDown(game_max_y);
			p->moveDown(game_max_y);
			p->moveDown(game_max_y);
			break;
		default:
			QWidget::keyPressEvent(e);
	}

	/**
	if(e->key() == Qt::Key_Q)
	{
		std::cout<<"Up\n";
		//p->moveUp();
	}
	else if(e->key() == Qt::Key_Down)
	{
		std::cout<<"Down\n";
		//p->moveDown();
	}
	**/
}

/**
 * Pauses the app.
 *
 * @return nothing
 */
void MainWindow::pauseApp()
{
	//p->moveDown(game_max_y);
	p->moveUp(game_min_y);
/**
	if(timer->isActive())
	{
		timer->stop();
	}
	else
	{
		timer->start();
	}
	**/
}

/**
 * Sets up the game every time the start button is pressed.
 *
 * @return nothing
 */
void MainWindow::startGame()
{
	userName = userNameLine->text();
	if(userName != "")
	{
		gameStarted = true;
		nameLine->setText(userName);
		userNameLine->setText("");
		errors->setText("");
		livesLine->setText("3");
		pointsLine->setText("0");
		popupView->close();
		userName = userNameLine->text();

		createBackground();
		playerImage = new QPixmap("images/astronaut.jpg");
		*playerImage = playerImage->scaledToHeight(70);
		p = new Player(playerImage);
		timer->start();
		//p->setPos(500, 500);

		scene->addItem(p);

		c = new Coin(coinImage, WINDOW_MAX_X - 50, 300, this);
		scene->addItem(c);

		a = new Alien(alienImage, WINDOW_MAX_X - 75, 400, this);
		scene->addItem(a);

		d = new Doctor(doctorImage, WINDOW_MAX_X, WINDOW_MAX_Y -100, this);
		scene->addItem(d);

		mb = new MoneyBag(moneybagImage, WINDOW_MAX_X, 250, this);
		scene->addItem(mb);

		t = new Turtle(turtleImage, WINDOW_MAX_X, WINDOW_MAX_Y-45, this);
		scene->addItem(t);

		this->grabKeyboard();

	}
	else
	{
		errorsExists = true;
		errors->setText("Enter a name above!");
	}
}

void MainWindow::callPopup()
{
	popupView->show();
}

void MainWindow::cancelPopup()
{
	userNameLine->setText("");
	errors->setText("");
	popupView->close();
}

/**
 * Constructor for the MainWindow
 *
 * @return nothing
 */
//MainWindow::MainWindow(QWidget* parent) : QWidget(parent)
MainWindow::MainWindow(QMainWindow* parent) : QMainWindow(parent)
{
	//this->setFocusPolicy(Qt::StrongFocus);

	scene = new QGraphicsScene();
	view = new QGraphicsView( scene );
	layout = new QFormLayout();
	window = new QWidget();
	gameStarted = false;

	initializeVariables();
	createPopup();
	createButtons();
	createOutput();

	QPalette pal(palette());
	//pal.setColor(QPalette::Background, QColor(152, 251, 152, 200));
	//pal.setColor(QPalette::Background, QColor(138, 43, 226, 50));
	pal.setColor(QPalette::Background, QColor(75, 209, 214, 100));
	window->setAutoFillBackground(true);
	window->setPalette(pal);

	view->setLayout(layout);
	window->setLayout(layout);
	window->setFixedSize(WINDOW_MAX_X-3, game_min_y);

	view->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	scene->addWidget(window);
	view->setFixedSize( WINDOW_MAX_X, WINDOW_MAX_Y);

	qreal _w = WINDOW_MAX_X - 3;
	qreal _h = WINDOW_MAX_Y - 3;
	qreal _x = 0;
	qreal _y = 0;
	scene->setSceneRect(_x, _y, _w, _h);
	view->setWindowTitle( "Space Invasion");

	//setting IMAGES of 5 things!
	coinImage = new QPixmap("images/coin.png");
	*coinImage = coinImage->scaledToHeight(30);

	alienImage = new QPixmap("images/alien2.jpg");
	*alienImage = alienImage->scaledToHeight(60);

	doctorImage = new QPixmap("images/doctor.jpg");
	*doctorImage = doctorImage->scaledToHeight(60);

	moneybagImage = new QPixmap("images/money-bag.png");
	*moneybagImage = moneybagImage->scaledToHeight(40);

	turtleImage = new QPixmap("images/spaceturtle.gif");
	*turtleImage = turtleImage->scaledToHeight(45);

	//This is how we do animation. We use a timer with an interval of 20 milliseconds
	//We connect the signal from the timer - the timeout() function to a function
	//of our own - called handleTimer - which is in this same MainWindow class
	timer = new QTimer(this);
	timer->setInterval(35);

	//connects
	connect(timer, SIGNAL(timeout()), this, SLOT(handleTimer()));
	connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
	connect(start, SIGNAL(clicked()), this, SLOT(callPopup()));
	connect(popupStart, SIGNAL(clicked()), this, SLOT(startGame()));
	connect(popupCancel, SIGNAL(clicked()), this, SLOT(cancelPopup()));
	connect(pause, SIGNAL(clicked()), this, SLOT(pauseApp()));

	//setFocus();
	view->setFocus();
	//std::cout<<QApplication::focusWidget();
}

/**
 * Displays the MainWindow
 *
 * @return nothing
 */
void MainWindow::show()
{
	//This is how we get our view displayed.
	window->show();
	view->show();
}

void MainWindow::initializeVariables()
{
	game_max_y = WINDOW_MAX_Y;
	game_min_y = WINDOW_MAX_Y/5 - 20;
	mousePressed = false;
	moveCount = 0;
}

void MainWindow::createPopup()
{
	popupScene = new QGraphicsScene();
	popupView = new QGraphicsView(popupScene);
	popupLayout = new QFormLayout();
	popupWindow = new QWidget();
	popupView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	popupView->setGeometry(WINDOW_MAX_X/2 - 80, WINDOW_MAX_Y/2, 300, 120);
	popupWindow->setGeometry(0, 0, 300 -3, 120 -3);
	popupNameLabel = new QLabel();
	popupNameLine = new QLineEdit();
	popupStart = new QPushButton("Start");
	popupCancel = new QPushButton("Cancel");
	userNameLabel = new QLabel("Enter name: ");
	userNameLine = new QLineEdit();
	errorsExists = false;
	errors = new QLineEdit();

	h1 = new QHBoxLayout();
	h1->addWidget(userNameLabel);
	h1->addWidget(userNameLine);
	h2 = new QHBoxLayout();
	h2->addWidget(popupStart);
	h2->addWidget(popupCancel);
	popupLayout->addItem(h2);
	popupLayout->addItem(h1);
	popupLayout->addWidget(errors);

	//popupLayout->addRow(userNameLabel, userNameLine);
	//popupLayout->addRow(popupStart, popupCancel);
	//popupView->setLayout(popupLayout);
	popupWindow->setLayout(popupLayout);
	errors->setText("");
	errors->setReadOnly(true);
	popupView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	popupScene->addWidget(popupWindow);
	popupView->setWindowTitle( "Start Screen");
}

void MainWindow::createButtons()
{
	startStopLayout = new QHBoxLayout();
	start = new QPushButton("Start Game");
	pause = new QPushButton("Pause");
	quit = new QPushButton("Quit");
	startStopLayout->addWidget(start);
	startStopLayout->addWidget(pause);
	startStopLayout->addWidget(quit);
	layout->addRow(startStopLayout);
}

void MainWindow::createOutput()
{

	labelsLayout = new QHBoxLayout();
	outputLayout = new QHBoxLayout();

	nameLabel = new QLabel("Name:");
	livesLabel = new QLabel("Lives:");
	pointsLabel = new QLabel("Points:");
	labelsLayout->addWidget(nameLabel);
	labelsLayout->addWidget(livesLabel);
	labelsLayout->addWidget(pointsLabel);
	layout->addRow(labelsLayout);

	nameLine = new QLineEdit();
	livesLine = new QLineEdit();
	pointsLine = new QLineEdit();
	nameLine->setReadOnly(true);
	livesLine->setReadOnly(true);
	pointsLine->setReadOnly(true);
	outputLayout->addWidget(nameLine);
	outputLayout->addWidget(livesLine);
	outputLayout->addWidget(pointsLine);
	layout->addRow(outputLayout);

}

void MainWindow::removeCoin(Coin *c)
{
	scene->removeItem(c);
}

void MainWindow::createBackground()
{
	bgImage = new QPixmap("images/stars.jpg");
	*bgImage = bgImage->scaled(WINDOW_MAX_X + 3, game_max_y - game_min_y, Qt::IgnoreAspectRatio, Qt::FastTransformation);
	bg = new Background(bgImage, 0, game_min_y);
	scene->addItem(bg);

	bg2 = new Background(bgImage, WINDOW_MAX_X, game_min_y);
	scene->addItem(bg2);
}

/**
 * Destructor
 *
 * @return nothing
 */
MainWindow::~MainWindow()
{
	timer->stop();
	delete timer;
	delete scene;
	delete view;

}
<commit_msg>Trying to debug error messages<commit_after>#include "mainwindow.h"
#include <cmath>

/**
 * Performs appropriate actions every time timer is called.
 *

 grab keyboard x error bad window
 merrick said it seems like an issue that you can't fix with my code, but rather something about
 qt or the vm

 get rid of player image, set player coordinates, set explosion image to that location,
 recreate player

 * @return nothing
 */
void MainWindow::handleTimer()
{
	bg->scroll(0, WINDOW_MAX_X);
	bg2->scroll(0, WINDOW_MAX_X);

	c->move();
	a->move();
	d->move();
	mb->move();
	t->move();
	moveCount++;

	/**
	if(mousePressed)
	{
		p->moveUp(game_min_y);
	}
	else if(moveCount == 15)
	{
		moveCount = 0;
		p->moveDown(game_min_y);
	}
	**/

}

/**
 * Function is called every time a tile is clicked.
 *
 * @param e Mouse event
 * @return nothing
 */
void MainWindow::keyPressEvent(QKeyEvent *e)
{
	//setFocusPolicy(Qt::StrongFocus);
	//std::cout<<"key";
	switch(e->key())
	{
		case Qt::Key_Up:
			std::cout<<"Up\n";
			p->moveUp(game_min_y);
			p->moveUp(game_min_y);
			p->moveUp(game_min_y);
			break;
		case Qt::Key_Down:
			std::cout<<"Down\n";
			p->moveDown(game_max_y);
			p->moveDown(game_max_y);
			p->moveDown(game_max_y);
			break;
		default:
			QWidget::keyPressEvent(e);
	}

	/**
	if(e->key() == Qt::Key_Q)
	{
		std::cout<<"Up\n";
		//p->moveUp();
	}
	else if(e->key() == Qt::Key_Down)
	{
		std::cout<<"Down\n";
		//p->moveDown();
	}
	**/
}

/**
 * Pauses the app.
 *
 * @return nothing
 */
void MainWindow::pauseApp()
{
	//p->moveDown(game_max_y);
	p->moveUp(game_min_y);
/**
	if(timer->isActive())
	{
		timer->stop();
	}
	else
	{
		timer->start();
	}
	**/
}

/**
 * Sets up the game every time the start button is pressed.
 *
 * @return nothing
 */
void MainWindow::startGame()
{
	userName = userNameLine->text();
	if(userName != "")
	{
		gameStarted = true;
		nameLine->setText(userName);
		userNameLine->setText("");
		errors->setText("");
		livesLine->setText("3");
		pointsLine->setText("0");
		popupView->close();
		userName = userNameLine->text();

		createBackground();
		playerImage = new QPixmap("images/astronaut.jpg");
		*playerImage = playerImage->scaledToHeight(70);
		p = new Player(playerImage);
		timer->start();
		//p->setPos(500, 500);

		scene->addItem(p);

		c = new Coin(coinImage, WINDOW_MAX_X - 50, 300, this);
		scene->addItem(c);

		a = new Alien(alienImage, WINDOW_MAX_X - 75, 400, this);
		scene->addItem(a);

		d = new Doctor(doctorImage, WINDOW_MAX_X, WINDOW_MAX_Y -100, this);
		scene->addItem(d);

		mb = new MoneyBag(moneybagImage, WINDOW_MAX_X, 250, this);
		scene->addItem(mb);

		t = new Turtle(turtleImage, WINDOW_MAX_X, WINDOW_MAX_Y-45, this);
		scene->addItem(t);

		this->grabKeyboard();

	}
	else
	{
		errorsExists = true;
		errors->setText("Enter a name above!");
	}
}

void MainWindow::callPopup()
{
	popupView->grabKeyboard();
	popupView->show();
}

void MainWindow::cancelPopup()
{
	userNameLine->setText("");
	errors->setText("");
	popupView->close();
}

/**
 * Constructor for the MainWindow
 *
 * @return nothing
 */
//MainWindow::MainWindow(QWidget* parent) : QWidget(parent)
MainWindow::MainWindow(QMainWindow* parent) : QMainWindow(parent)
{
	//this->setFocusPolicy(Qt::StrongFocus);

	scene = new QGraphicsScene();
	view = new QGraphicsView( scene );
	layout = new QFormLayout();
	window = new QWidget();
	gameStarted = false;

	initializeVariables();
	createPopup();
	createButtons();
	createOutput();

	QPalette pal(palette());
	//pal.setColor(QPalette::Background, QColor(152, 251, 152, 200));
	//pal.setColor(QPalette::Background, QColor(138, 43, 226, 50));
	pal.setColor(QPalette::Background, QColor(75, 209, 214, 100));
	window->setAutoFillBackground(true);
	window->setPalette(pal);

	view->setLayout(layout);
	window->setLayout(layout);
	window->setFixedSize(WINDOW_MAX_X-3, game_min_y);

	view->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	scene->addWidget(window);
	view->setFixedSize( WINDOW_MAX_X, WINDOW_MAX_Y);

	qreal _w = WINDOW_MAX_X - 3;
	qreal _h = WINDOW_MAX_Y - 3;
	qreal _x = 0;
	qreal _y = 0;
	scene->setSceneRect(_x, _y, _w, _h);
	view->setWindowTitle( "Space Invasion");

	//setting IMAGES of 5 things!
	coinImage = new QPixmap("images/coin.png");
	*coinImage = coinImage->scaledToHeight(30);

	alienImage = new QPixmap("images/alien2.jpg");
	*alienImage = alienImage->scaledToHeight(60);

	doctorImage = new QPixmap("images/doctor.jpg");
	*doctorImage = doctorImage->scaledToHeight(60);

	moneybagImage = new QPixmap("images/money-bag.png");
	*moneybagImage = moneybagImage->scaledToHeight(40);

	turtleImage = new QPixmap("images/spaceturtle.gif");
	*turtleImage = turtleImage->scaledToHeight(45);

	//This is how we do animation. We use a timer with an interval of 20 milliseconds
	//We connect the signal from the timer - the timeout() function to a function
	//of our own - called handleTimer - which is in this same MainWindow class
	timer = new QTimer(this);
	timer->setInterval(35);

	//connects
	connect(timer, SIGNAL(timeout()), this, SLOT(handleTimer()));
	connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
	connect(start, SIGNAL(clicked()), this, SLOT(callPopup()));
	connect(popupStart, SIGNAL(clicked()), this, SLOT(startGame()));
	connect(popupCancel, SIGNAL(clicked()), this, SLOT(cancelPopup()));
	connect(pause, SIGNAL(clicked()), this, SLOT(pauseApp()));

	//setFocus();
	view->setFocus();
	//std::cout<<QApplication::focusWidget();
}

/**
 * Displays the MainWindow
 *
 * @return nothing
 */
void MainWindow::show()
{
	//This is how we get our view displayed.
	window->show();
	view->show();
}

void MainWindow::initializeVariables()
{
	game_max_y = WINDOW_MAX_Y;
	game_min_y = WINDOW_MAX_Y/5 - 20;
	mousePressed = false;
	moveCount = 0;
}

void MainWindow::createPopup()
{
	popupScene = new QGraphicsScene();
	popupView = new QGraphicsView(popupScene);
	popupLayout = new QFormLayout();
	popupWindow = new QWidget();
	popupView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	popupView->setGeometry(WINDOW_MAX_X/2 - 80, WINDOW_MAX_Y/2, 300, 120);
	popupWindow->setGeometry(0, 0, 300 -3, 120 -3);
	popupNameLabel = new QLabel();
	popupNameLine = new QLineEdit();
	popupStart = new QPushButton("Start");
	popupCancel = new QPushButton("Cancel");
	userNameLabel = new QLabel("Enter name: ");
	userNameLine = new QLineEdit();
	errorsExists = false;
	errors = new QLineEdit();

	h1 = new QHBoxLayout();
	h1->addWidget(userNameLabel);
	h1->addWidget(userNameLine);
	h2 = new QHBoxLayout();
	h2->addWidget(popupStart);
	h2->addWidget(popupCancel);
	popupLayout->addItem(h2);
	popupLayout->addItem(h1);
	popupLayout->addWidget(errors);

	//popupLayout->addRow(userNameLabel, userNameLine);
	//popupLayout->addRow(popupStart, popupCancel);
	//popupView->setLayout(popupLayout);
	popupWindow->setLayout(popupLayout);
	errors->setText("");
	errors->setReadOnly(true);
	popupView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	popupScene->addWidget(popupWindow);
	popupView->setWindowTitle( "Start Screen");
}

void MainWindow::createButtons()
{
	startStopLayout = new QHBoxLayout();
	start = new QPushButton("Start Game");
	pause = new QPushButton("Pause");
	quit = new QPushButton("Quit");
	startStopLayout->addWidget(start);
	startStopLayout->addWidget(pause);
	startStopLayout->addWidget(quit);
	layout->addRow(startStopLayout);
}

void MainWindow::createOutput()
{

	labelsLayout = new QHBoxLayout();
	outputLayout = new QHBoxLayout();

	nameLabel = new QLabel("Name:");
	livesLabel = new QLabel("Lives:");
	pointsLabel = new QLabel("Points:");
	labelsLayout->addWidget(nameLabel);
	labelsLayout->addWidget(livesLabel);
	labelsLayout->addWidget(pointsLabel);
	layout->addRow(labelsLayout);

	nameLine = new QLineEdit();
	livesLine = new QLineEdit();
	pointsLine = new QLineEdit();
	nameLine->setReadOnly(true);
	livesLine->setReadOnly(true);
	pointsLine->setReadOnly(true);
	outputLayout->addWidget(nameLine);
	outputLayout->addWidget(livesLine);
	outputLayout->addWidget(pointsLine);
	layout->addRow(outputLayout);

}

void MainWindow::removeCoin(Coin *c)
{
	scene->removeItem(c);
}

void MainWindow::createBackground()
{
	bgImage = new QPixmap("images/stars.jpg");
	*bgImage = bgImage->scaled(WINDOW_MAX_X + 3, game_max_y - game_min_y, Qt::IgnoreAspectRatio, Qt::FastTransformation);
	bg = new Background(bgImage, 0, game_min_y);
	scene->addItem(bg);

	bg2 = new Background(bgImage, WINDOW_MAX_X, game_min_y);
	scene->addItem(bg2);
}

/**
 * Destructor
 *
 * @return nothing
 */
MainWindow::~MainWindow()
{
	timer->stop();
	delete timer;
	delete scene;
	delete view;

}
<|endoftext|>


<commit_before>#include "source.h"
#include <iostream>
#include "sourcefile.h"
#include <boost/property_tree/json_parser.hpp>
#include <fstream>
#include <boost/timer/timer.hpp>

#define log( var )                                                      \
  std::cout << "source.cc (" << __LINE__ << ") " << #var  << std::endl

Source::Location::
Location(int line_number, int column_offset) :
  line_number_(line_number), column_offset_(column_offset) { }

Source::Location::
Location(const Source::Location &org) :
  line_number_(org.line_number_), column_offset_(org.column_offset_) { }

Source::Range::
Range(const Location &start, const Location &end, int kind) :
  start_(start), end_(end), kind_(kind) { }

Source::Range::
Range(const Source::Range &org) :
  start_(org.start_), end_(org.end_), kind_(org.kind_) { }

//////////////
//// View ////
//////////////
Source::View::View() {
  override_font(Pango::FontDescription("Monospace"));
}

string Source::View::GetLine(const Gtk::TextIter &begin) {
  Gtk::TextIter end(begin);
  while (!end.ends_line())
    end++;
  return begin.get_text(end);
}

// Source::View::ApplyTheme()
// Applies theme in textview
void Source::View::ApplyConfig(const Source::Config &config) {
  for (auto &item : config.tagtable()) {
    get_buffer()->create_tag(item.first)->property_foreground() = item.second;
  }
}

// Source::View::Config::Config(Config &config)
// copy-constructor
Source::Config::Config(const Source::Config &original) {
  SetTagTable(original.tagtable());
  SetTypeTable(original.typetable());
}

Source::Config::Config() {}

// Source::View::Config::tagtable()
// returns a const refrence to the tagtable
const std::unordered_map<string, string>& Source::Config::tagtable() const {
  return tagtable_;
}

// Source::View::Config::tagtable()
// returns a const refrence to the tagtable
const std::unordered_map<string, string>& Source::Config::typetable() const {
  return typetable_;
}

void Source::Config::InsertTag(const string &key, const string &value) {
  tagtable_[key] = value;
}
// Source::View::Config::SetTagTable()
// sets the tagtable for the view
void Source::Config::
SetTypeTable(const std::unordered_map<string, string> &typetable) {
  typetable_ = typetable;
}

void Source::Config::InsertType(const string &key, const string &value) {
  typetable_[key] = value;
}
// Source::View::Config::SetTagTable()
// sets the tagtable for the view
void Source::Config::
SetTagTable(const std::unordered_map<string, string> &tagtable) {
  tagtable_ = tagtable;
}

///////////////
//// Model ////
///////////////
Source::Model::Model(const Source::Config &config) :
  config_(config) {
}

void Source::Model::
InitSyntaxHighlighting(const std::string &filepath,
                       const std::string &project_path,
                       const std::string &text,
                       int start_offset,
                       int end_offset) {
  set_file_path(filepath);
  set_project_path(project_path);
  std::vector<const char*> arguments = get_compilation_commands();
  tu_ = clang::TranslationUnit(true,
                               filepath,
                               arguments,
                               text);
}

// Source::View::UpdateLine
void Source::View::
OnLineEdit(const std::vector<Source::Range> &locations,
           const Source::Config &config) {
  log("before onupdatesyntax");
  OnUpdateSyntax(locations, config);
  log("after onupdatesyntax");
}

// Source::Model::UpdateLine
int Source::Model::
ReParse(const std::string &buffer) {
  return tu_.ReparseTranslationUnit(file_path(), buffer);
}

// Source::Controller::OnLineEdit()
// fired when a line in the buffer is edited
void Source::Controller::OnLineEdit() {

}

// sets the filepath for this mvc
void Source::Model::
set_file_path(const std::string &file_path) {
  file_path_ = file_path;
}
// sets the project path for this mvc
void Source::Model::
set_project_path(const std::string &project_path) {
  project_path_ = project_path;
}
// gets the file_path member
const std::string& Source::Model::file_path() const {
  return file_path_;
}
// gets the project_path member
const std::string& Source::Model::project_path() const {
  return project_path_;
}
// gets the config member
const Source::Config& Source::Model::config() const {
  return config_;
}

std::vector<const char*> Source::Model::
get_compilation_commands() {
  clang::CompilationDatabase db(project_path()+"/");
  clang::CompileCommands commands(file_path(), &db);
  std::vector<clang::CompileCommand> cmds = commands.get_commands();
  std::vector<const char*> arguments;
  for (auto &i : cmds) {
    std::vector<std::string> lol = i.get_command_as_args();
    for (int a = 1; a < lol.size()-4; a++) {
      arguments.emplace_back(lol[a].c_str());
    }
  }
  return arguments;
}

std::vector<Source::Range> Source::Model::
ExtractTokens(int start_offset, int end_offset) {
  std::vector<Source::Range> ranges;
  clang::SourceLocation start(&tu_, file_path(), start_offset);
  clang::SourceLocation end(&tu_, file_path(), end_offset);
  clang::SourceRange range(&start, &end);
  clang::Tokens tokens(&tu_, &range);
  std::vector<clang::Token> tks = tokens.tokens();
  for (auto &token : tks) {
    switch (token.kind()) {
    case 0: HighlightCursor(&token, &ranges); break;  // PunctuationToken
    case 1: HighlightToken(&token, &ranges, 702); break;  // KeywordToken
    case 2: HighlightCursor(&token, &ranges); break;  // IdentifierToken
    case 3: HighlightToken(&token, &ranges, 109); break;  // LiteralToken
    case 4: HighlightToken(&token, &ranges, 705); break;  // CommentToken
    }
  }
  log("returns ranges");
  return ranges;
}

void Source::Model::
HighlightCursor(clang::Token *token,
                std::vector<Source::Range> *source_ranges) {
  clang::SourceLocation location = token->get_source_location(&tu_);
  clang::Cursor cursor(&tu_, &location);
  clang::SourceRange range(&cursor);
  clang::SourceLocation begin(&range, true);
  clang::SourceLocation end(&range, false);
  unsigned begin_line_num, begin_offset, end_line_num, end_offset;
  begin.get_location_info(NULL, &begin_line_num, &begin_offset, NULL);
  end.get_location_info(NULL, &end_line_num, &end_offset, NULL);
  source_ranges->emplace_back(Source::Location(begin_line_num,
                                               begin_offset),
                              Source::Location(end_line_num,
                                               end_offset), (int) cursor.kind());
}
void Source::Model::
HighlightToken(clang::Token *token,
               std::vector<Source::Range> *source_ranges,
               int token_kind) {
  clang::SourceRange range = token->get_source_range(&tu_);
  unsigned begin_line_num, begin_offset, end_line_num, end_offset;
  clang::SourceLocation begin(&range, true);
  clang::SourceLocation end(&range, false);
  begin.get_location_info(NULL, &begin_line_num, &begin_offset, NULL);
  end.get_location_info(NULL, &end_line_num, &end_offset, NULL);
  source_ranges->emplace_back(Source::Location(begin_line_num,
                                               begin_offset),
                              Source::Location(end_line_num,
                                               end_offset), token_kind);
}

////////////////////
//// Controller ////
////////////////////

// Source::Controller::Controller()
// Constructor for Controller
Source::Controller::Controller(const Source::Config &config) :
  model_(config) {
}

// Source::Controller::view()
// return shared_ptr to the view
Source::View& Source::Controller::view() {
  return view_;
}
// Source::Controller::model()
// return shared_ptr to the model()
Source::Model& Source::Controller::model() {
  return model_;
}

void Source::Controller::OnNewEmptyFile() {
  string filename("/tmp/juci_t");
  sourcefile s(filename);
  model().set_file_path(filename);
  model().set_project_path(filename);
  s.save("");
}

string extract_file_path(const std::string &file_path) {
  return file_path.substr(0, file_path.find_last_of('/'));
}

std::vector<std::string> extentions() {
  return {".h", ".cc", ".cpp", ".hpp"};
}

bool check_extention(const std::string &file_path) {
  std::string extention = file_path.substr(file_path.find_last_of('.'),
                                           file_path.size());
  for (auto &ex : extentions()) {
    if (extention == ex) {
      return true;
    }
  }
  return false;
}

void Source::View::OnUpdateSyntax(const std::vector<Source::Range> &ranges,
                                  const Source::Config &config) {
  if (ranges.empty() || ranges.size() == 0) {
    log("ranges empty");
    return;
  }
  Glib::RefPtr<Gtk::TextBuffer> buffer = get_buffer();
  log("after getting buffer");
  int i = 0;
  log("after i int");
  std::cout << "rangeslengde: " << ranges.size() << std::endl;
  for (auto &range : ranges) {
    string type = std::to_string(range.kind());
    try {
      config.typetable().at(type);
    } catch (std::exception) {
      continue;
    }

    int linum_start = range.start().line_number()-1;
    int linum_end = range.end().line_number()-1;

    int begin = range.start().column_offset()-1;
    int end = range.end().column_offset()-1;

    if (end < 0) end = 0;
    if (begin < 0) begin = 0;
    Gtk::TextIter begin_iter =
      buffer->get_iter_at_line_offset(linum_start, begin);
    Gtk::TextIter end_iter  =
      buffer->get_iter_at_line_offset(linum_end, end);
    buffer->remove_all_tags(begin_iter, end_iter);
    if (begin_iter.get_line() ==  end_iter.get_line()) {
      buffer->apply_tag_by_name(config.typetable().at(type),
                                begin_iter, end_iter);
    }
    i++;
  }
  log("End of onupdatesyntax");
}

void Source::Controller::OnOpenFile(const string &filepath) {
  sourcefile s(filepath);
  buffer()->set_text(s.get_content());
  int start_offset = buffer()->begin().get_offset();
  int end_offset = buffer()->end().get_offset();

  if (check_extention(filepath)) {
    view().ApplyConfig(model().config());
    model().InitSyntaxHighlighting(filepath,
                                   extract_file_path(filepath),
                                   buffer()->get_text().raw(),
                                   start_offset,
                                   end_offset);
    view().OnUpdateSyntax(model().ExtractTokens(start_offset, end_offset),
                          model().config());
  }

  buffer()->signal_end_user_action().connect([this]() {
      if (!go) {
        std::thread parse([this]() {
            if(parsing.try_lock()) {
              const std::string raw = buffer()->get_text().raw();
              int b = model().ReParse(raw);
              if (b == 0) {
                if (raw == buffer()->get_text().raw()) {
                  log("alike!");
                  syntax.lock();
                  go = true;
                  syntax.unlock();
                } else {
                  log("buffer changed");
                }
              }
              parsing.unlock();
            }
          });
        parse.detach();
      }
    });

  buffer()->signal_begin_user_action().connect([this]() {
      if (go) {
        syntax.lock();
        view().
          OnUpdateSyntax(model().ExtractTokens(0, buffer()->get_text().size()),
                         model().config());
        go = false;
        syntax.unlock();
      }
    });
}
Glib::RefPtr<Gtk::TextBuffer> Source::Controller::buffer() {
  return view().get_buffer();
}
<commit_msg>fix syntax<commit_after>#include "source.h"
#include <iostream>
#include "sourcefile.h"
#include <boost/property_tree/json_parser.hpp>
#include <fstream>
#include <boost/timer/timer.hpp>

#define log( var )                                                      \
  std::cout << "source.cc (" << __LINE__ << ") " << #var  << std::endl

Source::Location::
Location(int line_number, int column_offset) :
  line_number_(line_number), column_offset_(column_offset) { }

Source::Location::
Location(const Source::Location &org) :
  line_number_(org.line_number_), column_offset_(org.column_offset_) { }

Source::Range::
Range(const Location &start, const Location &end, int kind) :
  start_(start), end_(end), kind_(kind) { }

Source::Range::
Range(const Source::Range &org) :
  start_(org.start_), end_(org.end_), kind_(org.kind_) { }

//////////////
//// View ////
//////////////
Source::View::View() {
  override_font(Pango::FontDescription("Monospace"));
}

string Source::View::GetLine(const Gtk::TextIter &begin) {
  Gtk::TextIter end(begin);
  while (!end.ends_line())
    end++;
  return begin.get_text(end);
}

// Source::View::ApplyTheme()
// Applies theme in textview
void Source::View::ApplyConfig(const Source::Config &config) {
  for (auto &item : config.tagtable()) {
    get_buffer()->create_tag(item.first)->property_foreground() = item.second;
  }
}

// Source::View::Config::Config(Config &config)
// copy-constructor
Source::Config::Config(const Source::Config &original) {
  SetTagTable(original.tagtable());
  SetTypeTable(original.typetable());
}

Source::Config::Config() {}

// Source::View::Config::tagtable()
// returns a const refrence to the tagtable
const std::unordered_map<string, string>& Source::Config::tagtable() const {
  return tagtable_;
}

// Source::View::Config::tagtable()
// returns a const refrence to the tagtable
const std::unordered_map<string, string>& Source::Config::typetable() const {
  return typetable_;
}

void Source::Config::InsertTag(const string &key, const string &value) {
  tagtable_[key] = value;
}
// Source::View::Config::SetTagTable()
// sets the tagtable for the view
void Source::Config::
SetTypeTable(const std::unordered_map<string, string> &typetable) {
  typetable_ = typetable;
}

void Source::Config::InsertType(const string &key, const string &value) {
  typetable_[key] = value;
}
// Source::View::Config::SetTagTable()
// sets the tagtable for the view
void Source::Config::
SetTagTable(const std::unordered_map<string, string> &tagtable) {
  tagtable_ = tagtable;
}

///////////////
//// Model ////
///////////////
Source::Model::Model(const Source::Config &config) :
  config_(config) {
}

void Source::Model::
InitSyntaxHighlighting(const std::string &filepath,
                       const std::string &project_path,
                       const std::string &text,
                       int start_offset,
                       int end_offset) {
  set_file_path(filepath);
  set_project_path(project_path);
  std::vector<const char*> arguments = get_compilation_commands();
  tu_ = clang::TranslationUnit(true,
                               filepath,
                               arguments,
                               text);
}

// Source::View::UpdateLine
void Source::View::
OnLineEdit(const std::vector<Source::Range> &locations,
           const Source::Config &config) {
  OnUpdateSyntax(locations, config);
}

// Source::Model::UpdateLine
int Source::Model::
ReParse(const std::string &buffer) {
  return tu_.ReparseTranslationUnit(file_path(), buffer);
}

// Source::Controller::OnLineEdit()
// fired when a line in the buffer is edited
void Source::Controller::OnLineEdit() { }

// sets the filepath for this mvc
void Source::Model::
set_file_path(const std::string &file_path) {
  file_path_ = file_path;
}
// sets the project path for this mvc
void Source::Model::
set_project_path(const std::string &project_path) {
  project_path_ = project_path;
}
// gets the file_path member
const std::string& Source::Model::file_path() const {
  return file_path_;
}
// gets the project_path member
const std::string& Source::Model::project_path() const {
  return project_path_;
}
// gets the config member
const Source::Config& Source::Model::config() const {
  return config_;
}

std::vector<const char*> Source::Model::
get_compilation_commands() {
  clang::CompilationDatabase db(project_path()+"/");
  clang::CompileCommands commands(file_path(), &db);
  std::vector<clang::CompileCommand> cmds = commands.get_commands();
  std::vector<const char*> arguments;
  for (auto &i : cmds) {
    std::vector<std::string> lol = i.get_command_as_args();
    for (int a = 1; a < lol.size()-4; a++) {
      arguments.emplace_back(lol[a].c_str());
    }
  }
  return arguments;
}

std::vector<Source::Range> Source::Model::
ExtractTokens(int start_offset, int end_offset) {
  std::vector<Source::Range> ranges;
  clang::SourceLocation start(&tu_, file_path(), start_offset);
  clang::SourceLocation end(&tu_, file_path(), end_offset);
  clang::SourceRange range(&start, &end);
  clang::Tokens tokens(&tu_, &range);
  std::vector<clang::Token> tks = tokens.tokens();
  for (auto &token : tks) {
    switch (token.kind()) {
    case 0: HighlightCursor(&token, &ranges); break;  // PunctuationToken
    case 1: HighlightToken(&token, &ranges, 702); break;  // KeywordToken
    case 2: HighlightCursor(&token, &ranges); break;  // IdentifierToken
    case 3: HighlightToken(&token, &ranges, 109); break;  // LiteralToken
    case 4: HighlightToken(&token, &ranges, 705); break;  // CommentToken
    }
  }
  return ranges;
}

void Source::Model::
HighlightCursor(clang::Token *token,
                std::vector<Source::Range> *source_ranges) {
  clang::SourceLocation location = token->get_source_location(&tu_);
  clang::Cursor cursor(&tu_, &location);
  clang::SourceRange range(&cursor);
  clang::SourceLocation begin(&range, true);
  clang::SourceLocation end(&range, false);
  unsigned begin_line_num, begin_offset, end_line_num, end_offset;
  begin.get_location_info(NULL, &begin_line_num, &begin_offset, NULL);
  end.get_location_info(NULL, &end_line_num, &end_offset, NULL);
  source_ranges->emplace_back(Source::Location(begin_line_num,
                                               begin_offset),
                              Source::Location(end_line_num,
                                               end_offset), (int) cursor.kind());
}
void Source::Model::
HighlightToken(clang::Token *token,
               std::vector<Source::Range> *source_ranges,
               int token_kind) {
  clang::SourceRange range = token->get_source_range(&tu_);
  unsigned begin_line_num, begin_offset, end_line_num, end_offset;
  clang::SourceLocation begin(&range, true);
  clang::SourceLocation end(&range, false);
  begin.get_location_info(NULL, &begin_line_num, &begin_offset, NULL);
  end.get_location_info(NULL, &end_line_num, &end_offset, NULL);
  source_ranges->emplace_back(Source::Location(begin_line_num,
                                               begin_offset),
                              Source::Location(end_line_num,
                                               end_offset), token_kind);
}

////////////////////
//// Controller ////
////////////////////

// Source::Controller::Controller()
// Constructor for Controller
Source::Controller::Controller(const Source::Config &config) :
  model_(config) {
}

// Source::Controller::view()
// return shared_ptr to the view
Source::View& Source::Controller::view() {
  return view_;
}
// Source::Controller::model()
// return shared_ptr to the model()
Source::Model& Source::Controller::model() {
  return model_;
}

void Source::Controller::OnNewEmptyFile() {
  string filename("/tmp/juci_t");
  sourcefile s(filename);
  model().set_file_path(filename);
  model().set_project_path(filename);
  s.save("");
}

string extract_file_path(const std::string &file_path) {
  return file_path.substr(0, file_path.find_last_of('/'));
}

std::vector<std::string> extentions() {
  return {".h", ".cc", ".cpp", ".hpp"};
}

bool check_extention(const std::string &file_path) {
  std::string extention = file_path.substr(file_path.find_last_of('.'),
                                           file_path.size());
  for (auto &ex : extentions()) {
    if (extention == ex) {
      return true;
    }
  }
  return false;
}

void Source::View::OnUpdateSyntax(const std::vector<Source::Range> &ranges,
                                  const Source::Config &config) {
  if (ranges.empty() || ranges.size() == 0) {
    return;
  }
  Glib::RefPtr<Gtk::TextBuffer> buffer = get_buffer();
  buffer->remove_all_tags(buffer->begin(), buffer->end());
  int i = 0;
  for (auto &range : ranges) {
    string type = std::to_string(range.kind());
    try {
      config.typetable().at(type);
    } catch (std::exception) {
      continue;
    }

    int linum_start = range.start().line_number()-1;
    int linum_end = range.end().line_number()-1;

    int begin = range.start().column_offset()-1;
    int end = range.end().column_offset()-1;

    if (end < 0) end = 0;
    if (begin < 0) begin = 0;
    Gtk::TextIter begin_iter =
      buffer->get_iter_at_line_offset(linum_start, begin);
    Gtk::TextIter end_iter  =
      buffer->get_iter_at_line_offset(linum_end, end);
    if (begin_iter.get_line() ==  end_iter.get_line()) {
      buffer->apply_tag_by_name(config.typetable().at(type),
                                begin_iter, end_iter);
    }
    i++;
  }
}

void Source::Controller::OnOpenFile(const string &filepath) {
  sourcefile s(filepath);
  buffer()->set_text(s.get_content());
  int start_offset = buffer()->begin().get_offset();
  int end_offset = buffer()->end().get_offset();

  if (check_extention(filepath)) {
    view().ApplyConfig(model().config());
    model().InitSyntaxHighlighting(filepath,
                                   extract_file_path(filepath),
                                   buffer()->get_text().raw(),
                                   start_offset,
                                   end_offset);
    view().OnUpdateSyntax(model().ExtractTokens(start_offset, end_offset),
                          model().config());
  }

  buffer()->signal_end_user_action().connect([this]() {
      if (!go) {
        std::thread parse([this]() {
            if (parsing.try_lock()) {
              while (true) {
                const std::string raw = buffer()->get_text().raw();
                if (model().ReParse(raw) == 0 &&
                    raw == buffer()->get_text().raw()) {
                  syntax.lock();
                  go = true;
                  syntax.unlock();
                  break;
                }
              }
              parsing.unlock();
            }
          });
        parse.detach();
      }
    });

  buffer()->signal_begin_user_action().connect([this]() {
      if (go) {
        syntax.lock();
        view().
          OnUpdateSyntax(model().ExtractTokens(0, buffer()->get_text().size()),
                         model().config());
        go = false;
        syntax.unlock();
      }
    });
}
Glib::RefPtr<Gtk::TextBuffer> Source::Controller::buffer() {
  return view().get_buffer();
}
<|endoftext|>


<commit_before>#include "model.h"
#include <string>
#include <algorithm>
#include <map>

double figures::Segment::getApproximateDistanceToBorder(const Point &p) {
    double res = std::min((p - a).length(), (p - b).length());
    // Please note that here we do not care about floatint-point error,
    // as if 'start' falls near 'a' or 'b', we've already calculated it
    if (Point::dotProduct(p - a, b - a) >= 0
            && Point::dotProduct(p - b, a - b) >= 0) {
        res = std::min(res, getDistanceToLine(p));
    }
    return res;
}

double figures::Segment::getDistanceToLine(const Point &p) {
    // Coefficients of A*x + B*y + C = 0
    double A = b.y - a.y;
    double B = a.x - b.x;
    double C = -A * a.x - B * a.y;

    // normalization of the equation
    double D = sqrt(A * A + B * B);
    if (fabs(D) < 1e-8) { return HUGE_VAL; } // degenerate case

    A /= D; B /= D; C /= D;
    return fabs(A * p.x + B * p.y + C);
}

double figures::Rectangle::getApproximateDistanceToBorder(const Point &p) {
    bool inX = box.leftDown.x <= p.x && p.x <= box.rightUp.x;
    bool inY = box.leftDown.y <= p.y && p.y <= box.rightUp.y;
    double res = HUGE_VAL;
    if (inX) { // Point lies in a vertical bar bounded by Left and Right
        res = std::min(res, fabs(p.y - box.leftDown.y));
        res = std::min(res, fabs(p.y - box.rightUp.y));
    }
    if (inY) { // Point lies in a horizontal bar
        res = std::min(res, fabs(p.x - box.leftDown.x));
        res = std::min(res, fabs(p.x - box.rightUp.x));
    }
    if (!inX && !inY) {
        res = std::min(res, (p - box.leftDown).length());
        res = std::min(res, (p - box.rightUp).length());
        res = std::min(res, (p - box.leftUp()).length());
        res = std::min(res, (p - box.rightDown()).length());
    }
    return res;
}

double figures::Ellipse::getApproximateDistanceToBorder(const Point &_p) {
    Point p = _p - box.center();
    if (p.length() < 1e-7) { return std::min(box.width(), box.height()) / 2; }
    double a = box.width() / 2;
    double b = box.height() / 2;
    Point near = p;
    near.x /= a; near.y /= b;
    double d = near.length();
    near.x /= d; near.y /= d;
    near.x *= a; near.y *= b;
    return (p - near).length();
}

std::vector<Point> getMiddleBorderPoints(BoundingBox box) {
    std::vector<Point> res;
    res.push_back(Point(box.center().x, box.leftDown.y));
    res.push_back(Point(box.center().x, box.rightUp.y));
    res.push_back(Point(box.leftDown.x, box.center().y));
    res.push_back(Point(box.rightUp.x, box.center().y));
    return res;
}

void figures::SegmentConnection::recalculate() {
    using std::vector;
    using std::get;
    vector<Point> as = getMiddleBorderPoints(figA->getBoundingBox());
    vector<Point> bs = getMiddleBorderPoints(figB->getBoundingBox());
    double minDistSquared = HUGE_VAL;
    for (Point a : as) {
        for (Point b : bs) {
            double curDistSquared = (a - b).lengthSquared();
            if (minDistSquared > curDistSquared) {
                minDistSquared = curDistSquared;
                this->a = a;
                this->b = b;
            }
        }
    }
}

std::istream &operator>>(std::istream &in, Model &model) {
    int count;
    if (!(in >> count)) {
        throw model_format_error("unable to read number of figures");
    }
    std::vector<PFigure> figures;
    while (count -- > 0) {
        std::string type;
        if (!(in >> type)) {
            throw model_format_error("unable to read fngure type");
        }
        if (type == "segment" || type == "segment_connection") {
            std::shared_ptr<figures::Segment> segm;
            if (type == "segment_connection") {
                size_t aId, bId;
                if (!(in >> aId >> bId)) {
                    throw model_format_error("unable to read connection information");
                }
                aId--, bId--;
                if (aId >= figures.size() || bId >= figures.size()) {
                    throw model_format_error("invalid figures in connection");
                }
                auto figA = std::dynamic_pointer_cast<figures::BoundedFigure>(figures.at(aId));
                auto figB = std::dynamic_pointer_cast<figures::BoundedFigure>(figures.at(bId));
                if (!figA || !figB) {
                    throw model_format_error("invalid reference in connection");
                }
                segm = std::make_shared<figures::SegmentConnection>(figA, figB);
            } else {
                double x1, y1, x2, y2;
                if (!(in >> x1 >> y1 >> x2 >> y2)) {
                    throw model_format_error("unable to read segment");
                }
                segm = std::make_shared<figures::Segment>(Point(x1, y1), Point(x2, y2));
            }
            bool arrowA, arrowB;
            if (!(in >> arrowA >> arrowB)) {
                throw model_format_error("unable to read segment");
            }
            segm->setArrowedA(arrowA);
            segm->setArrowedB(arrowB);
            figures.push_back(segm);
        } else if (type == "rectangle") {
            double x1, y1, x2, y2;
            if (!(in >> x1 >> y1 >> x2 >> y2)) {
                throw model_format_error("unable to read rectangle");
            }
            figures.push_back(std::make_shared<figures::Rectangle>(BoundingBox({Point(x1, y1), Point(x2, y2)})));
        } else if (type == "ellipse") {
            double x1, y1, x2, y2;
            if (!(in >> x1 >> y1 >> x2 >> y2)) {
                throw model_format_error("unable to read ellipse");
            }
            figures.push_back(std::make_shared<figures::Ellipse>(BoundingBox({Point(x1, y1), Point(x2, y2)})));
        } else {
            throw model_format_error("unknown type: '" + type + "'");
        }
    }
    for (PFigure figure : figures) {
        model.addFigure(figure);
    }
    return in;
}

class FigurePrinter : public FigureVisitor {
public:
    FigurePrinter(std::ostream &out, const std::map<PFigure, size_t> &ids) : out(out), ids(ids) {}

    virtual void accept(figures::Segment &segm) {
        out << "segment ";
        printPoint(segm.getA());
        out << " ";
        printPoint(segm.getB());
        out << " " << segm.getArrowedA() << " " << segm.getArrowedB() << "\n";
    }
    virtual void accept(figures::SegmentConnection &segm) {
        out << "segment_connection ";
        out << ids.at(segm.getFigureA()) << " ";
        out << ids.at(segm.getFigureB()) << " ";
        out << " " << segm.getArrowedA() << " " << segm.getArrowedB() << "\n";
    }

    virtual void accept(figures::Ellipse &fig) {
        out << "ellipse ";
        printBoundingBox(fig.getBoundingBox());
        out << "\n";
    }

    virtual void accept(figures::Rectangle &fig) {
        out << "rectangle ";
        printBoundingBox(fig.getBoundingBox());
        out << "\n";
    }

private:
    std::ostream &out;
    const std::map<PFigure, size_t> &ids;
    void printPoint(const Point &p) {
        out << p.x << " " << p.y;
    }
    void printBoundingBox(const BoundingBox &box) {
        printPoint(box.leftDown);
        out << " ";
        printPoint(box.rightUp);
    }
};

std::ostream &operator<<(std::ostream &out, Model &model) {
    out << model.size() << '\n';

    std::map<PFigure, size_t> ids;
    for (PFigure figure : model) {
        int id = ids.size() + 1;
        ids[figure] = id;
    }

    FigurePrinter printer(out, ids);
    for (PFigure figure : model) {
        figure->visit(printer);
    }
    return out;
}

class CloningVisitor : public FigureVisitor {
public:
    CloningVisitor(const std::map<PFigure, PFigure> &mapping) : mapping(mapping) {}
    PFigure getResult() { return result; }

    virtual void accept(figures::Segment &fig) override {
        result = std::make_shared<figures::Segment>(fig);
    }
    virtual void accept(figures::SegmentConnection &fig) {
        auto res = std::make_shared<figures::SegmentConnection>(fig.getFigureA(), fig.getFigureB());
        res->setArrowedA(fig.getArrowedA());
        res->setArrowedB(fig.getArrowedB());
        result = res;
    }

    virtual void accept(figures::Ellipse &fig) {
        result = std::make_shared<figures::Ellipse>(fig);
    }

    virtual void accept(figures::Rectangle &fig) {
        result = std::make_shared<figures::Rectangle>(fig);
    }

private:
    const std::map<PFigure, PFigure> &mapping;
    PFigure result;
};

PFigure clone(PFigure figure, const std::map<PFigure, PFigure> &othersMapping) {
    CloningVisitor visitor(othersMapping);
    figure->visit(visitor);
    return visitor.getResult();
}
<commit_msg>model.cpp: got rid of warning: int --> size_t<commit_after>#include "model.h"
#include <string>
#include <algorithm>
#include <map>

double figures::Segment::getApproximateDistanceToBorder(const Point &p) {
    double res = std::min((p - a).length(), (p - b).length());
    // Please note that here we do not care about floatint-point error,
    // as if 'start' falls near 'a' or 'b', we've already calculated it
    if (Point::dotProduct(p - a, b - a) >= 0
            && Point::dotProduct(p - b, a - b) >= 0) {
        res = std::min(res, getDistanceToLine(p));
    }
    return res;
}

double figures::Segment::getDistanceToLine(const Point &p) {
    // Coefficients of A*x + B*y + C = 0
    double A = b.y - a.y;
    double B = a.x - b.x;
    double C = -A * a.x - B * a.y;

    // normalization of the equation
    double D = sqrt(A * A + B * B);
    if (fabs(D) < 1e-8) { return HUGE_VAL; } // degenerate case

    A /= D; B /= D; C /= D;
    return fabs(A * p.x + B * p.y + C);
}

double figures::Rectangle::getApproximateDistanceToBorder(const Point &p) {
    bool inX = box.leftDown.x <= p.x && p.x <= box.rightUp.x;
    bool inY = box.leftDown.y <= p.y && p.y <= box.rightUp.y;
    double res = HUGE_VAL;
    if (inX) { // Point lies in a vertical bar bounded by Left and Right
        res = std::min(res, fabs(p.y - box.leftDown.y));
        res = std::min(res, fabs(p.y - box.rightUp.y));
    }
    if (inY) { // Point lies in a horizontal bar
        res = std::min(res, fabs(p.x - box.leftDown.x));
        res = std::min(res, fabs(p.x - box.rightUp.x));
    }
    if (!inX && !inY) {
        res = std::min(res, (p - box.leftDown).length());
        res = std::min(res, (p - box.rightUp).length());
        res = std::min(res, (p - box.leftUp()).length());
        res = std::min(res, (p - box.rightDown()).length());
    }
    return res;
}

double figures::Ellipse::getApproximateDistanceToBorder(const Point &_p) {
    Point p = _p - box.center();
    if (p.length() < 1e-7) { return std::min(box.width(), box.height()) / 2; }
    double a = box.width() / 2;
    double b = box.height() / 2;
    Point near = p;
    near.x /= a; near.y /= b;
    double d = near.length();
    near.x /= d; near.y /= d;
    near.x *= a; near.y *= b;
    return (p - near).length();
}

std::vector<Point> getMiddleBorderPoints(BoundingBox box) {
    std::vector<Point> res;
    res.push_back(Point(box.center().x, box.leftDown.y));
    res.push_back(Point(box.center().x, box.rightUp.y));
    res.push_back(Point(box.leftDown.x, box.center().y));
    res.push_back(Point(box.rightUp.x, box.center().y));
    return res;
}

void figures::SegmentConnection::recalculate() {
    using std::vector;
    using std::get;
    vector<Point> as = getMiddleBorderPoints(figA->getBoundingBox());
    vector<Point> bs = getMiddleBorderPoints(figB->getBoundingBox());
    double minDistSquared = HUGE_VAL;
    for (Point a : as) {
        for (Point b : bs) {
            double curDistSquared = (a - b).lengthSquared();
            if (minDistSquared > curDistSquared) {
                minDistSquared = curDistSquared;
                this->a = a;
                this->b = b;
            }
        }
    }
}

std::istream &operator>>(std::istream &in, Model &model) {
    int count;
    if (!(in >> count)) {
        throw model_format_error("unable to read number of figures");
    }
    std::vector<PFigure> figures;
    while (count -- > 0) {
        std::string type;
        if (!(in >> type)) {
            throw model_format_error("unable to read fngure type");
        }
        if (type == "segment" || type == "segment_connection") {
            std::shared_ptr<figures::Segment> segm;
            if (type == "segment_connection") {
                size_t aId, bId;
                if (!(in >> aId >> bId)) {
                    throw model_format_error("unable to read connection information");
                }
                aId--, bId--;
                if (aId >= figures.size() || bId >= figures.size()) {
                    throw model_format_error("invalid figures in connection");
                }
                auto figA = std::dynamic_pointer_cast<figures::BoundedFigure>(figures.at(aId));
                auto figB = std::dynamic_pointer_cast<figures::BoundedFigure>(figures.at(bId));
                if (!figA || !figB) {
                    throw model_format_error("invalid reference in connection");
                }
                segm = std::make_shared<figures::SegmentConnection>(figA, figB);
            } else {
                double x1, y1, x2, y2;
                if (!(in >> x1 >> y1 >> x2 >> y2)) {
                    throw model_format_error("unable to read segment");
                }
                segm = std::make_shared<figures::Segment>(Point(x1, y1), Point(x2, y2));
            }
            bool arrowA, arrowB;
            if (!(in >> arrowA >> arrowB)) {
                throw model_format_error("unable to read segment");
            }
            segm->setArrowedA(arrowA);
            segm->setArrowedB(arrowB);
            figures.push_back(segm);
        } else if (type == "rectangle") {
            double x1, y1, x2, y2;
            if (!(in >> x1 >> y1 >> x2 >> y2)) {
                throw model_format_error("unable to read rectangle");
            }
            figures.push_back(std::make_shared<figures::Rectangle>(BoundingBox({Point(x1, y1), Point(x2, y2)})));
        } else if (type == "ellipse") {
            double x1, y1, x2, y2;
            if (!(in >> x1 >> y1 >> x2 >> y2)) {
                throw model_format_error("unable to read ellipse");
            }
            figures.push_back(std::make_shared<figures::Ellipse>(BoundingBox({Point(x1, y1), Point(x2, y2)})));
        } else {
            throw model_format_error("unknown type: '" + type + "'");
        }
    }
    for (PFigure figure : figures) {
        model.addFigure(figure);
    }
    return in;
}

class FigurePrinter : public FigureVisitor {
public:
    FigurePrinter(std::ostream &out, const std::map<PFigure, size_t> &ids) : out(out), ids(ids) {}

    virtual void accept(figures::Segment &segm) {
        out << "segment ";
        printPoint(segm.getA());
        out << " ";
        printPoint(segm.getB());
        out << " " << segm.getArrowedA() << " " << segm.getArrowedB() << "\n";
    }
    virtual void accept(figures::SegmentConnection &segm) {
        out << "segment_connection ";
        out << ids.at(segm.getFigureA()) << " ";
        out << ids.at(segm.getFigureB()) << " ";
        out << " " << segm.getArrowedA() << " " << segm.getArrowedB() << "\n";
    }

    virtual void accept(figures::Ellipse &fig) {
        out << "ellipse ";
        printBoundingBox(fig.getBoundingBox());
        out << "\n";
    }

    virtual void accept(figures::Rectangle &fig) {
        out << "rectangle ";
        printBoundingBox(fig.getBoundingBox());
        out << "\n";
    }

private:
    std::ostream &out;
    const std::map<PFigure, size_t> &ids;
    void printPoint(const Point &p) {
        out << p.x << " " << p.y;
    }
    void printBoundingBox(const BoundingBox &box) {
        printPoint(box.leftDown);
        out << " ";
        printPoint(box.rightUp);
    }
};

std::ostream &operator<<(std::ostream &out, Model &model) {
    out << model.size() << '\n';

    std::map<PFigure, size_t> ids;
    for (PFigure figure : model) {
        size_t id = ids.size() + 1;
        ids[figure] = id;
    }

    FigurePrinter printer(out, ids);
    for (PFigure figure : model) {
        figure->visit(printer);
    }
    return out;
}

class CloningVisitor : public FigureVisitor {
public:
    CloningVisitor(const std::map<PFigure, PFigure> &mapping) : mapping(mapping) {}
    PFigure getResult() { return result; }

    virtual void accept(figures::Segment &fig) override {
        result = std::make_shared<figures::Segment>(fig);
    }
    virtual void accept(figures::SegmentConnection &fig) {
        auto res = std::make_shared<figures::SegmentConnection>(fig.getFigureA(), fig.getFigureB());
        res->setArrowedA(fig.getArrowedA());
        res->setArrowedB(fig.getArrowedB());
        result = res;
    }

    virtual void accept(figures::Ellipse &fig) {
        result = std::make_shared<figures::Ellipse>(fig);
    }

    virtual void accept(figures::Rectangle &fig) {
        result = std::make_shared<figures::Rectangle>(fig);
    }

private:
    const std::map<PFigure, PFigure> &mapping;
    PFigure result;
};

PFigure clone(PFigure figure, const std::map<PFigure, PFigure> &othersMapping) {
    CloningVisitor visitor(othersMapping);
    figure->visit(visitor);
    return visitor.getResult();
}
<|endoftext|>


<commit_before>/*
 * @COPYRIGHT@
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE
 */

// clxx/platform_layer.hpp

/** // doc: clxx/platform_layer.hpp {{{
 * \file clxx/platform_layer.hpp
 * \todo Write documentation
 */ // }}}
#ifndef CLXX_PLATFORM_LAYER_HPP_INCLUDED
#define CLXX_PLATFORM_LAYER_HPP_INCLUDED

#include <clxx/platforms.hpp>
#include <clxx/devices.hpp>

#include <clxx/platform_layer_info.hpp>
#include <clxx/platform_query.hpp>
#include <clxx/device_query.hpp>

#include <set>
#include <map>
#include <vector>

namespace clxx {

/** // doc: class platform_layer {{{
 * \ingroup Clxx_Cl_platform
 *
 * Simple associative container to store \ref clxx::device "devices",
 * \ref clxx::platform "platforms" and relations between these. It represents
 * information about devices belonging to given platforms, and provides simple
 * interface to create and modify its contents and relations.
 *
 * Note, that this is just a container. It's not synchronized with OpenCL
 * platform layer by definition (it may be filled quite arbitrarily by user).
 * However, it has an interface that allows to initialize it with the actual
 * data retrieved from OpenCL, see \ref load_opencl().
 *
 * The implemented relations have the following properties
 *
 *  - each \ref clxx::device "device" stored in the container refers to exactly
 *    one \ref clxx::platform "platform" (also stored in the container),
 *  - each \ref clxx::platform "platform" stored in the container refers on one
 *    or more \ref clxx::device "devices" (stored in the container).
 *
 * These constraints are enforced internally by the class. The contents may be
 * accessed by the following methods:
 *
 *  - \ref get_devices() const get_devices() returns a plain sequence of
 *    \ref clxx::device "devices", where the \ref clxx::device "devices" appear
 *    in the same order as they were added to the container,
 *  - \ref get_platforms() const get_platforms() returns a plain sequence of
 *    \ref clxx::platform "platforms", where the \ref clxx::platform "platforms"
 *    appear in the same order as they were added to the container,
 *  - \ref get_devices(platform const&) const get_devices(platform const&)
 *    returns plain sequence of \ref clxx::device "devices" related to a given
 *    platform,
 *  - \ref get_platform(device const&) const get_platform(device const&)
 *    returns a \ref clxx::platform "platform" related to a given device,
 *
 * The contents may be modified by the following methods:
 *
 *   - \ref add(device const&, platform const&) stores device, platform and
 *     relation between device and platform in the container,
 *   - \ref add(devices const&, platform const&) stores multiple devices and a
 *     single platform at once and establishes relations between devices and
 *     the platform,
 *   - \ref erase(device const&) removes device from the container, if it was
 *     the last device referencing its platform, the platform will also be
 *     removed from container,
 *   - \ref clear() clears the container entirely.
 *
 * and
 *
 *   - \ref load_opencl(device_type_t) retrieves the platforms, devices and
 *     relations from OpenCL platform layer and adds them to the container.
 *     Note, that this appends stuff to or overrides the existing content.
 *
 * The container may also be filled-in with a data obtained from OpenCL at
 * initialization phase (in constructor).
 */ // }}}
class platform_layer
{
public:
  typedef std::map<device, platform> device_platform_map;
public:
  /** // doc: platform_layer() {{{
   * \brief Default constructor
   *
   * Initializes empty container.
   */ // }}}
  platform_layer() noexcept;
  /** // doc: platform_layer(device_type_t) {{{
   * \brief Constructor
   *
   * Initializes container with OpenCL data.
   *
   * \param type OpenCL device type, retrieve only devices of a given type.
   *
   * \code
   *  platform_layer pl(t);
   * \endcode
   *
   * is equivalent to:
   *
   * \code
   *  platform_layer pl;
   *  pl.load_opencl(t);
   * \endcode
   *
   * \throws clerror_no<status_t::invalid_device_type>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_platform>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_value>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_host_memory>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_resources>
   *    propagated from clxx::get_device_ids()
   * \throws std::bad_alloc
   *    may be raised occasionally
   */ // }}}
  platform_layer(device_type_t type);
  /** // doc: platform_layer(bool, device_type_t) {{{
   * \brief Constructor
   *
   * Either, initializes empty container or retrieves data from OpenCL,
   * depending on the value of \e load flag. The following calls are
   * equivalent
   *
   * \code
   *  platform_layer(false);         // =>  platform_layer();
   *  platform_layer(false, type);   // =>  platform_layer();
   *  platform_layer(true);          // =>  platform_layer(device_type_t::all);
   *  platform_layer(true, type);    // =>  platform_layer(type);
   * \endcode
   *
   *
   * \param load  decides whether to load OpenCL platform layer layout or not,
   * \param type  if \e load is \c true, then retrieve from OpenCL only devices
   *  of this \e type
   *
   * \throws clerror_no<status_t::invalid_device_type>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_platform>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_value>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_host_memory>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_resources>
   *    propagated from clxx::get_device_ids()
   * \throws std::bad_alloc
   *    may be raised occasionally
   */ // }}}
  platform_layer(bool load, device_type_t type = device_type_t::all);
  /** // doc: ~platform_layer() {{{
   * \brief Destructor
   */ // }}}
  virtual ~platform_layer() noexcept;
  /** // doc: get_platforms() {{{
   * \fn get_platforms() const
   * \brief Get platforms
   *
   * Return flat sequence of platforms stored in container. The order of
   * elements in sequence is same as the order of their insertion to the
   * container.
   *
   * \returns flat sequence of platforms stored in container.
   */ // }}}
  platforms const& get_platforms() const noexcept;
  /** // doc: get_devices() {{{
   * \fn get_devices() const
   * \brief Get devices
   *
   * Returns flat sequence of devices stored in container. The order of
   * elements in sequence is same as the order of their insertion to the
   * container.
   *
   * \returns sequence of devices stored in container.
   */ // }}}
  devices const& get_devices() const noexcept;
  /** // doc: get_devices(platform const&) {{{
   * \fn get_devices(platform const&) const
   * \brief Get devices that refer platform \e p
   * \param p the platform
   * \returns flat sequence of devices that reference platform \e p
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  devices get_devices(platform const& p) const;
  /** // doc: get_platform(device const&) {{{
   * \fn get_platform(device const&) const
   * \brief Get platform referenced by given device
   * \param d the device
   * \throws invalid_key_error if \e d does not exist in the container
   * \returns a platform referred by \e d.
   */ // }}}
  platform const& get_platform(device const& d) const;
  /** // doc: has_device(device const&) {{{
   * \brief Check presence of device \e d in container
   * \param d the clxx::device "device" to check
   * \returns \c true if device is found in container, otherwise \c false
   */ // }}}
  bool has_device(device const& d) const noexcept;
  /** // doc: has_platform(platform const&) {{{
   * \brief Check presence of platform \e p in container
   * \param p the \ref clxx::platform "platform" to check
   * \returns \c true if device is found in container, otherwise \c false
   */ // }}}
  bool has_platform(platform const& p) const noexcept;
  /** // doc: add(platform const&, device const&) {{{
   * \brief Add device to container
   * \param d device,
   * \param p platform referenced by device \e d
   * \returns \c true if the number of devices in container increased,
   *    if the device already existed in container returns \c false
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  bool add(device const& d, platform const& p);
  /** // doc: add(platform const&, devices const&) {{{
   * \brief Add device to container
   * \param ds devices
   * \param p platform referenced by devices \e ds
   * \returns number of new devices added to container, the devices that
   *    already existed in container are not counted in the return value
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  size_t add(devices const& ds, platform const& p);
  /** // doc: erase(device const&) {{{
   * \brief Remove device from container
   * \param d the device to remove from container
   * \throws invalid_key_error if \e d does not exist in the container
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  void erase(device const& d);
  /** // doc: clear() {{{
   * \brief Clear the container entirelly
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  void clear() noexcept;
  /** // doc: load_opencl(device_type_t) {{{
   * \brief Retrieve and load data from OpenCL
   *
   * This function retrieves from OpenCL and stores in container the platform
   * layer layout (devices, platforms and relations).
   *
   * \param type retrieve only devices of given type
   *
   * \throws clerror_no<status_t::invalid_device_type>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_platform>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_value>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_host_memory>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_resources>
   *    propagated from clxx::get_device_ids()
   * \throws std::bad_alloc
   *    may be raised occasionally
   */ // }}}
  void load_opencl(device_type_t type = device_type_t::all);
private:
  platforms _platforms;
  devices _devices;
  device_platform_map _device_platform;
};

/** // doc: query_platform_layer_info(layer,pquery,dquery) {{{
 * \todo Write documentation
 */ // }}}
platform_layer_info
query_platform_layer_info(
    platform_layer const& layer = platform_layer(device_type_t::all),
    platform_query const& pquery = platform_query(),
    device_query const& dquery = device_query()
);

} // end namespace clxx

#endif /* CLXX_PLATFORM_LAYER_HPP_INCLUDED */
// vim: set expandtab tabstop=2 shiftwidth=2:
// vim: set foldmethod=marker foldcolumn=4:
<commit_msg>revised docs in platform_layer.hpp<commit_after>/*
 * @COPYRIGHT@
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE
 */

// clxx/platform_layer.hpp

/** // doc: clxx/platform_layer.hpp {{{
 * \file clxx/platform_layer.hpp
 * \todo Write documentation
 */ // }}}
#ifndef CLXX_PLATFORM_LAYER_HPP_INCLUDED
#define CLXX_PLATFORM_LAYER_HPP_INCLUDED

#include <clxx/platforms.hpp>
#include <clxx/devices.hpp>

#include <clxx/platform_layer_info.hpp>
#include <clxx/platform_query.hpp>
#include <clxx/device_query.hpp>

#include <set>
#include <map>
#include <vector>

namespace clxx {

/** // doc: class platform_layer {{{
 * \ingroup Clxx_Cl_platform
 *
 * Simple associative container to store \ref clxx::device "devices",
 * \ref clxx::platform "platforms" and relations between them. Note, that this
 * is just a container. It's not synchronized with OpenCL platform layer by
 * definition (it may be filled-in quite arbitrarily by user). However, it has
 * an interface that allows to initialize it with the actual data retrieved
 * from OpenCL, see \ref load_opencl().
 *
 * The implemented relations fulfill the following constraints (enforced
 * internally by the class):
 *
 *  - each \ref clxx::device "device" stored in the container refers exactly
 *    one \ref clxx::platform "platform" (also stored in the container),
 *  - each \ref clxx::platform "platform" stored in the container is referred
 *    by one or more \ref clxx::device "devices" (stored in the container).
 *
 * The contents may be accessed by the following methods:
 *
 *  - \ref get_devices() const get_devices() returns a plain sequence of
 *    \ref clxx::device "devices", where the \ref clxx::device "devices" appear
 *    in the same order as they were added to the container,
 *  - \ref get_platforms() const get_platforms() returns a plain sequence of
 *    \ref clxx::platform "platforms", where the \ref clxx::platform "platforms"
 *    appear in the same order as they were added to the container,
 *  - \ref get_devices(platform const&) const get_devices(platform const&)
 *    returns plain sequence of \ref clxx::device "devices" that refer given
 *    platform,
 *  - \ref get_platform(device const&) const get_platform(device const&)
 *    returns a \ref clxx::platform "platform" referred by given device,
 *
 * The contents may be modified by the following methods:
 *
 *   - \ref add(device const&, platform const&) stores device, platform and
 *     relation between device and platform in the container,
 *   - \ref add(devices const&, platform const&) stores multiple devices and a
 *     single platform at once and establishes relations between devices and
 *     the platform,
 *   - \ref erase(device const&) removes device from the container, if it was
 *     the last device referencing its platform, the platform will also be
 *     removed from container,
 *   - \ref clear() clears the container entirely.
 *
 * and
 *
 *   - \ref load_opencl(device_type_t) retrieves the platforms, devices and
 *     relations from OpenCL platform layer and adds them to the container.
 *     Note, that this appends stuff to- or overrides the existing content.
 *
 * The container may also be filled-in with a data obtained from OpenCL at
 * initialization phase (in constructor).
 */ // }}}
class platform_layer
{
public:
  typedef std::map<device, platform> device_platform_map;
public:
  /** // doc: platform_layer() {{{
   * \brief Default constructor
   *
   * Initializes empty container.
   */ // }}}
  platform_layer() noexcept;
  /** // doc: platform_layer(device_type_t) {{{
   * \brief Constructor
   *
   * Initializes container with OpenCL data.
   *
   * \param type OpenCL device type, retrieve only devices of a given type.
   *
   * \code
   *  platform_layer pl(t);
   * \endcode
   *
   * is equivalent to:
   *
   * \code
   *  platform_layer pl;
   *  pl.load_opencl(t);
   * \endcode
   *
   * \throws clerror_no<status_t::invalid_device_type>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_platform>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_value>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_host_memory>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_resources>
   *    propagated from clxx::get_device_ids()
   * \throws std::bad_alloc
   *    may be raised occasionally
   */ // }}}
  platform_layer(device_type_t type);
  /** // doc: platform_layer(bool, device_type_t) {{{
   * \brief Constructor
   *
   * Either, initializes empty container or retrieves data from OpenCL,
   * depending on the value of \e load flag. The following calls are
   * equivalent
   *
   * \code
   *  platform_layer(false);         // =>  platform_layer();
   *  platform_layer(false, type);   // =>  platform_layer();
   *  platform_layer(true);          // =>  platform_layer(device_type_t::all);
   *  platform_layer(true, type);    // =>  platform_layer(type);
   * \endcode
   *
   *
   * \param load  decides whether to load OpenCL platform layer layout or not,
   * \param type  if \e load is \c true, then retrieve from OpenCL only devices
   *  of this \e type
   *
   * \throws clerror_no<status_t::invalid_device_type>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_platform>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_value>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_host_memory>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_resources>
   *    propagated from clxx::get_device_ids()
   * \throws std::bad_alloc
   *    may be raised occasionally
   */ // }}}
  platform_layer(bool load, device_type_t type = device_type_t::all);
  /** // doc: ~platform_layer() {{{
   * \brief Destructor
   */ // }}}
  virtual ~platform_layer() noexcept;
  /** // doc: get_platforms() {{{
   * \fn get_platforms() const
   * \brief Get platforms
   *
   * Return flat sequence of platforms stored in container. The order of
   * elements in sequence is same as the order of their insertion to the
   * container.
   *
   * \returns flat sequence of platforms stored in container.
   */ // }}}
  platforms const& get_platforms() const noexcept;
  /** // doc: get_devices() {{{
   * \fn get_devices() const
   * \brief Get devices
   *
   * Returns flat sequence of devices stored in container. The order of
   * elements in sequence is same as the order of their insertion to the
   * container.
   *
   * \returns sequence of devices stored in container.
   */ // }}}
  devices const& get_devices() const noexcept;
  /** // doc: get_devices(platform const&) {{{
   * \fn get_devices(platform const&) const
   * \brief Get devices that refer platform \e p
   * \param p the platform
   * \returns flat sequence of devices that reference platform \e p
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  devices get_devices(platform const& p) const;
  /** // doc: get_platform(device const&) {{{
   * \fn get_platform(device const&) const
   * \brief Get platform referenced by given device
   * \param d the device
   * \throws invalid_key_error if \e d does not exist in the container
   * \returns a platform referred by \e d.
   */ // }}}
  platform const& get_platform(device const& d) const;
  /** // doc: has_device(device const&) {{{
   * \brief Check presence of device \e d in container
   * \param d the clxx::device "device" to check
   * \returns \c true if device is found in container, otherwise \c false
   */ // }}}
  bool has_device(device const& d) const noexcept;
  /** // doc: has_platform(platform const&) {{{
   * \brief Check presence of platform \e p in container
   * \param p the \ref clxx::platform "platform" to check
   * \returns \c true if device is found in container, otherwise \c false
   */ // }}}
  bool has_platform(platform const& p) const noexcept;
  /** // doc: add(platform const&, device const&) {{{
   * \brief Add device to container
   * \param d device,
   * \param p platform referenced by device \e d
   * \returns \c true if the number of devices in container increased,
   *    if the device already existed in container returns \c false
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  bool add(device const& d, platform const& p);
  /** // doc: add(platform const&, devices const&) {{{
   * \brief Add device to container
   * \param ds devices
   * \param p platform referenced by devices \e ds
   * \returns number of new devices added to container, the devices that
   *    already existed in container are not counted in the return value
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  size_t add(devices const& ds, platform const& p);
  /** // doc: erase(device const&) {{{
   * \brief Remove device from container
   * \param d the device to remove from container
   * \throws invalid_key_error if \e d does not exist in the container
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  void erase(device const& d);
  /** // doc: clear() {{{
   * \brief Clear the container entirelly
   * \throws std::bad_alloc may be raised occasionally
   */ // }}}
  void clear() noexcept;
  /** // doc: load_opencl(device_type_t) {{{
   * \brief Retrieve and load data from OpenCL
   *
   * This function retrieves from OpenCL and stores in container the platform
   * layer layout (devices, platforms and relations).
   *
   * \param type retrieve only devices of given type
   *
   * \throws clerror_no<status_t::invalid_device_type>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_platform>
   *    propagated from clxx::get_device_ids()
   * \throws clerror_no<status_t::invalid_value>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_host_memory>
   *    propagated from clxx::get_device_ids() and clxx::get_platform_ids()
   * \throws clerror_no<status_t::out_of_resources>
   *    propagated from clxx::get_device_ids()
   * \throws std::bad_alloc
   *    may be raised occasionally
   */ // }}}
  void load_opencl(device_type_t type = device_type_t::all);
private:
  platforms _platforms;
  devices _devices;
  device_platform_map _device_platform;
};

/** // doc: query_platform_layer_info(layer,pquery,dquery) {{{
 * \todo Write documentation
 */ // }}}
platform_layer_info
query_platform_layer_info(
    platform_layer const& layer = platform_layer(device_type_t::all),
    platform_query const& pquery = platform_query(),
    device_query const& dquery = device_query()
);

} // end namespace clxx

#endif /* CLXX_PLATFORM_LAYER_HPP_INCLUDED */
// vim: set expandtab tabstop=2 shiftwidth=2:
// vim: set foldmethod=marker foldcolumn=4:
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2010,2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
//

// Own
#include "ServerLayout.h"

#include "GeoSceneTiled.h"
#include "MarbleGlobal.h"
#include "TileId.h"

#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif

#include <math.h>

namespace Marble
{

ServerLayout::ServerLayout( GeoSceneTiled *textureLayer )
    : m_textureLayer( textureLayer )
{
}

ServerLayout::~ServerLayout()
{
}

MarbleServerLayout::MarbleServerLayout( GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl MarbleServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
    QUrl url = prototypeUrl;
    url.setPath( url.path() + m_textureLayer->relativeTileFileName( id ) );

    return url;
}

QString MarbleServerLayout::name() const
{
    return "Marble";
}

OsmServerLayout::OsmServerLayout( GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl OsmServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
    const QString suffix = m_textureLayer->fileFormat().toLower();
    const QString path = QString( "%1/%2/%3.%4" ).arg( id.zoomLevel() )
                                                 .arg( id.x() )
                                                 .arg( id.y() )
                                                 .arg( suffix );

    QUrl url = prototypeUrl;
    url.setPath( url.path() + path );

    return url;
}

QString OsmServerLayout::name() const
{
    return "OpenStreetMap";
}

CustomServerLayout::CustomServerLayout( GeoSceneTiled *texture )
    : ServerLayout( texture )
{
}

QUrl CustomServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
#if QT_VERSION < 0x050000
    QString urlStr = prototypeUrl.toString();
#else
    QString urlStr = prototypeUrl.toString( QUrl::DecodeReserved );
#endif

    urlStr.replace( "{zoomLevel}", QString::number( id.zoomLevel() ) );
    urlStr.replace( "{x}", QString::number( id.x() ) );
    urlStr.replace( "{y}", QString::number( id.y() ) );

    return QUrl( urlStr );
}

QString CustomServerLayout::name() const
{
    return "Custom";
}

WmsServerLayout::WmsServerLayout( GeoSceneTiled *texture )
    : ServerLayout( texture )
{
}

QUrl WmsServerLayout::downloadUrl( const QUrl &prototypeUrl, const Marble::TileId &tileId ) const
{
    GeoDataLatLonBox box = tileId.toLatLonBox( m_textureLayer );

#if QT_VERSION < 0x050000
    QUrl url = prototypeUrl;
#else
    QUrlQuery url(prototypeUrl.query());
#endif
    url.addQueryItem( "service", "WMS" );
    url.addQueryItem( "request", "GetMap" );
    url.addQueryItem( "version", "1.1.1" );
    if ( !url.hasQueryItem( "styles" ) )
        url.addQueryItem( "styles", "" );
    if ( !url.hasQueryItem( "format" ) ) {
        if ( m_textureLayer->fileFormat().toLower() == "jpg" )
            url.addQueryItem( "format", "image/jpeg" );
        else
            url.addQueryItem( "format", "image/" + m_textureLayer->fileFormat().toLower() );
    }
    if ( !url.hasQueryItem( "srs" ) ) {
        url.addQueryItem( "srs", epsgCode() );
    }
    if ( !url.hasQueryItem( "layers" ) )
        url.addQueryItem( "layers", m_textureLayer->name() );
    url.addQueryItem( "width", QString::number( m_textureLayer->tileSize().width() ) );
    url.addQueryItem( "height", QString::number( m_textureLayer->tileSize().height() ) );
    url.addQueryItem( "bbox", QString( "%1,%2,%3,%4" ).arg( QString::number( box.west( GeoDataCoordinates::Degree ), 'f', 12 ) )
                                                      .arg( QString::number( box.south( GeoDataCoordinates::Degree ), 'f', 12 ) )
                                                      .arg( QString::number( box.east( GeoDataCoordinates::Degree ), 'f', 12 ) )
                                                      .arg( QString::number( box.north( GeoDataCoordinates::Degree ), 'f', 12 ) ) );
#if QT_VERSION < 0x050000
    return url;
#else
    QUrl finalUrl = prototypeUrl;
    finalUrl.setQuery(url);
    return finalUrl;
#endif
}

QString WmsServerLayout::name() const
{
    return "WebMapService";
}

QString WmsServerLayout::epsgCode() const
{
    switch ( m_textureLayer->projection() ) {
        case GeoSceneTiled::Equirectangular:
            return "EPSG:4326";
        case GeoSceneTiled::Mercator:
            return "EPSG:3785";
    }

    Q_ASSERT( false ); // not reached
    return QString();
}

QuadTreeServerLayout::QuadTreeServerLayout( GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl QuadTreeServerLayout::downloadUrl( const QUrl &prototypeUrl, const Marble::TileId &id ) const
{
#if QT_VERSION < 0x050000
    QString urlStr = prototypeUrl.toString();
#else
    QString urlStr = prototypeUrl.toString( QUrl::DecodeReserved );
#endif

    urlStr.replace( "{quadIndex}", encodeQuadTree( id ) );

    return QUrl( urlStr );
}

QString QuadTreeServerLayout::name() const
{
    return "QuadTree";
}

QString QuadTreeServerLayout::encodeQuadTree( const Marble::TileId &id )
{
    QString tileNum;

    for ( int i = id.zoomLevel(); i >= 0; i-- ) {
        const int tileX = (id.x() >> i) % 2;
        const int tileY = (id.y() >> i) % 2;
        const int num = ( 2 * tileY ) + tileX;

        tileNum += QString::number( num );
    }

    return tileNum;
}

TmsServerLayout::TmsServerLayout(GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl TmsServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
    const QString suffix = m_textureLayer->fileFormat().toLower();
    // y coordinate in TMS start at the bottom of the map (South) and go upwards,
    // opposed to OSM which start at the top.
    //
    // http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
    int y_frombottom = ( 1<<id.zoomLevel() ) - id.y() - 1 ;

    const QString path = QString( "%1/%2/%3.%4" ).arg( id.zoomLevel() )
                                                 .arg( id.x() )
                                                 .arg( y_frombottom )
                                                 .arg( suffix );
    QUrl url = prototypeUrl;
    url.setPath( url.path() + path );

    return url;
}

QString TmsServerLayout::name() const
{
    return "TileMapService";
}

}
<commit_msg>decouple remote and local tile paths a bit<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2010,2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
//

// Own
#include "ServerLayout.h"

#include "GeoSceneTiled.h"
#include "MarbleGlobal.h"
#include "TileId.h"

#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif

#include <math.h>

namespace Marble
{

ServerLayout::ServerLayout( GeoSceneTiled *textureLayer )
    : m_textureLayer( textureLayer )
{
}

ServerLayout::~ServerLayout()
{
}

MarbleServerLayout::MarbleServerLayout( GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl MarbleServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
    const QString path = QString( "%1maps/%2/%3/%4/%4_%5.%6" )
        .arg( prototypeUrl.path() )
        .arg( m_textureLayer->sourceDir() )
        .arg( id.zoomLevel() )
        .arg( id.y(), tileDigits, 10, QChar('0') )
        .arg( id.x(), tileDigits, 10, QChar('0') )
        .arg( m_textureLayer->fileFormat().toLower() );

    QUrl url = prototypeUrl;
    url.setPath( path );

    return url;
}

QString MarbleServerLayout::name() const
{
    return "Marble";
}

OsmServerLayout::OsmServerLayout( GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl OsmServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
    const QString suffix = m_textureLayer->fileFormat().toLower();
    const QString path = QString( "%1/%2/%3.%4" ).arg( id.zoomLevel() )
                                                 .arg( id.x() )
                                                 .arg( id.y() )
                                                 .arg( suffix );

    QUrl url = prototypeUrl;
    url.setPath( url.path() + path );

    return url;
}

QString OsmServerLayout::name() const
{
    return "OpenStreetMap";
}

CustomServerLayout::CustomServerLayout( GeoSceneTiled *texture )
    : ServerLayout( texture )
{
}

QUrl CustomServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
#if QT_VERSION < 0x050000
    QString urlStr = prototypeUrl.toString();
#else
    QString urlStr = prototypeUrl.toString( QUrl::DecodeReserved );
#endif

    urlStr.replace( "{zoomLevel}", QString::number( id.zoomLevel() ) );
    urlStr.replace( "{x}", QString::number( id.x() ) );
    urlStr.replace( "{y}", QString::number( id.y() ) );

    return QUrl( urlStr );
}

QString CustomServerLayout::name() const
{
    return "Custom";
}

WmsServerLayout::WmsServerLayout( GeoSceneTiled *texture )
    : ServerLayout( texture )
{
}

QUrl WmsServerLayout::downloadUrl( const QUrl &prototypeUrl, const Marble::TileId &tileId ) const
{
    GeoDataLatLonBox box = tileId.toLatLonBox( m_textureLayer );

#if QT_VERSION < 0x050000
    QUrl url = prototypeUrl;
#else
    QUrlQuery url(prototypeUrl.query());
#endif
    url.addQueryItem( "service", "WMS" );
    url.addQueryItem( "request", "GetMap" );
    url.addQueryItem( "version", "1.1.1" );
    if ( !url.hasQueryItem( "styles" ) )
        url.addQueryItem( "styles", "" );
    if ( !url.hasQueryItem( "format" ) ) {
        if ( m_textureLayer->fileFormat().toLower() == "jpg" )
            url.addQueryItem( "format", "image/jpeg" );
        else
            url.addQueryItem( "format", "image/" + m_textureLayer->fileFormat().toLower() );
    }
    if ( !url.hasQueryItem( "srs" ) ) {
        url.addQueryItem( "srs", epsgCode() );
    }
    if ( !url.hasQueryItem( "layers" ) )
        url.addQueryItem( "layers", m_textureLayer->name() );
    url.addQueryItem( "width", QString::number( m_textureLayer->tileSize().width() ) );
    url.addQueryItem( "height", QString::number( m_textureLayer->tileSize().height() ) );
    url.addQueryItem( "bbox", QString( "%1,%2,%3,%4" ).arg( QString::number( box.west( GeoDataCoordinates::Degree ), 'f', 12 ) )
                                                      .arg( QString::number( box.south( GeoDataCoordinates::Degree ), 'f', 12 ) )
                                                      .arg( QString::number( box.east( GeoDataCoordinates::Degree ), 'f', 12 ) )
                                                      .arg( QString::number( box.north( GeoDataCoordinates::Degree ), 'f', 12 ) ) );
#if QT_VERSION < 0x050000
    return url;
#else
    QUrl finalUrl = prototypeUrl;
    finalUrl.setQuery(url);
    return finalUrl;
#endif
}

QString WmsServerLayout::name() const
{
    return "WebMapService";
}

QString WmsServerLayout::epsgCode() const
{
    switch ( m_textureLayer->projection() ) {
        case GeoSceneTiled::Equirectangular:
            return "EPSG:4326";
        case GeoSceneTiled::Mercator:
            return "EPSG:3785";
    }

    Q_ASSERT( false ); // not reached
    return QString();
}

QuadTreeServerLayout::QuadTreeServerLayout( GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl QuadTreeServerLayout::downloadUrl( const QUrl &prototypeUrl, const Marble::TileId &id ) const
{
#if QT_VERSION < 0x050000
    QString urlStr = prototypeUrl.toString();
#else
    QString urlStr = prototypeUrl.toString( QUrl::DecodeReserved );
#endif

    urlStr.replace( "{quadIndex}", encodeQuadTree( id ) );

    return QUrl( urlStr );
}

QString QuadTreeServerLayout::name() const
{
    return "QuadTree";
}

QString QuadTreeServerLayout::encodeQuadTree( const Marble::TileId &id )
{
    QString tileNum;

    for ( int i = id.zoomLevel(); i >= 0; i-- ) {
        const int tileX = (id.x() >> i) % 2;
        const int tileY = (id.y() >> i) % 2;
        const int num = ( 2 * tileY ) + tileX;

        tileNum += QString::number( num );
    }

    return tileNum;
}

TmsServerLayout::TmsServerLayout(GeoSceneTiled *textureLayer )
    : ServerLayout( textureLayer )
{
}

QUrl TmsServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
{
    const QString suffix = m_textureLayer->fileFormat().toLower();
    // y coordinate in TMS start at the bottom of the map (South) and go upwards,
    // opposed to OSM which start at the top.
    //
    // http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
    int y_frombottom = ( 1<<id.zoomLevel() ) - id.y() - 1 ;

    const QString path = QString( "%1/%2/%3.%4" ).arg( id.zoomLevel() )
                                                 .arg( id.x() )
                                                 .arg( y_frombottom )
                                                 .arg( suffix );
    QUrl url = prototypeUrl;
    url.setPath( url.path() + path );

    return url;
}

QString TmsServerLayout::name() const
{
    return "TileMapService";
}

}
<|endoftext|>