<commit_before>//	Simple Chatterbox client written in C++
//	Many of the functions are taken from the excellent Winsock FAQ at
//		http://tangentsoft.net/wskfaq/

#include <iostream>
#include <string>
#include <stdexcept>
#include <winsock2.h>
// #include <winsock.h>

using namespace std;

class WASDataWrapper {
	WSADATA wsaData_;
public:
	WASDataWrapper() {
		if(WSAStartup(MAKEWORD(2,2), &wsaData_) != 0) {
			throw runtime_error("WSAStartup failed");
		}
	}

	~WASDataWrapper() {
		WSACleanup();
	}

};

//// LookupAddress /////////////////////////////////////////////////////
// Given an address string, determine if it's a dotted-quad IP address
// or a domain address.  If the latter, ask DNS to resolve it.  In
// either case, return resolved IP address.  If we fail, we return
// INADDR_NONE.
u_long LookupAddress(const char* pcHost)
{
    u_long nRemoteAddr = inet_addr(pcHost);
    if (nRemoteAddr == INADDR_NONE) {
        // pcHost isn't a dotted IP, so resolve it through DNS
        hostent* pHE = gethostbyname(pcHost);
        if (pHE == 0) {
            return INADDR_NONE;
        }
        nRemoteAddr = *((u_long*)pHE->h_addr_list[0]);
    }

    return nRemoteAddr;
}

//// EstablishConnection ///////////////////////////////////////////////
// Connects to a given address, on a given port, both of which must be
// in network byte order.  Returns newly-connected socket if we succeed,
// or INVALID_SOCKET if we fail.
SOCKET EstablishConnection(u_long nRemoteAddr, u_short nPort)
{
    // Create a stream socket
    // SOCKET sd = socket(AF_INET, SOCK_STREAM, 0);
    SOCKET sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sd != INVALID_SOCKET) {
        SOCKADDR_IN sinRemote;
        sinRemote.sin_family = AF_INET;
        sinRemote.sin_addr.s_addr = nRemoteAddr;
        sinRemote.sin_port = nPort;
        if (connect(sd, (sockaddr*)&sinRemote, sizeof(sockaddr_in)) ==
                SOCKET_ERROR) {
            sd = INVALID_SOCKET;
        }
    }

    return sd;
}

//// ShutdownConnection ////////////////////////////////////////////////
// Gracefully shuts the connection sd down.  Returns true if we're
// successful, false otherwise.
bool ShutdownConnection(SOCKET sd)
{
	const int kBufferSize = 1024;
	// const int SD_SEND = 1;

    // Disallow any further data sends.  This will tell the other side
    // that we want to go away now.  If we skip this step, we don't
    // shut the connection down nicely.
    if (shutdown(sd, SD_SEND) == SOCKET_ERROR) {
        return false;
    }

    // Receive any extra data still sitting on the socket.  After all
    // data is received, this call will block until the remote host
    // acknowledges the TCP control packet sent by the shutdown above.
    // Then we'll get a 0 back from recv, signalling that the remote
    // host has closed its side of the connection.
    char acReadBuffer[kBufferSize];
    while (1) {
        int nNewBytes = recv(sd, acReadBuffer, kBufferSize, 0);
        if (nNewBytes == SOCKET_ERROR) {
            return false;
        }
        else if (nNewBytes != 0) {
            cerr << endl << "FYI, received " << nNewBytes <<
                    " unexpected bytes during shutdown." << endl;
        }
        else {
            // Okay, we're done!
            break;
        }
    }

    // Close the socket.
    if (closesocket(sd) == SOCKET_ERROR) {
        return false;
    }

    return true;
}

int main() {

	WASDataWrapper wsaData;

	//	Connect to a Chatterbox server
	string host = "localhost";
	u_short port = 20000;

    u_long remote_addr = LookupAddress(host.c_str());
    if (remote_addr == INADDR_NONE) {
        cerr << "Could not detremine remote host address." ;
        return 1;
    }

    cout << "remote_addr=" << remote_addr << '\n';
    in_addr address;
    memcpy(&address, &remote_addr, sizeof(u_long));
    cout << "Connecting to Chatterbox server at, " << inet_ntoa(address) << ":" << port << endl;

	// Create a stream socket
	SOCKET sd = EstablishConnection(remote_addr, port);
	if(sd == INVALID_SOCKET) {
		cout << "Could not connect to Chatterbox server\n";
    	cerr << "WSAGetLastError() says:" << WSAGetLastError() << '\n';
		return 1;
	}

	cout << "Connected to Chatterbox server!";

	//	Let user enter an id
	//	auto userID = "";
	//	userID << cin;

	//	Send the user ID
	//	socket.send(userID);

	//	Create a sender thread and listener thread
	//	Start listener thread
	//	Start sender thread

	//	Wait for threads to exit

	// Shut connection down
	cout << "Disconnectiong from Chatterbox server.\n";
	if (ShutdownConnection(sd)) {
	    cout << "Disconnected successfully.\n" << endl;
	}
	else {
	    cout << "Problem disconnecting.\n";
	}

	cout << "Exiting Chatterbox client." << endl;

	return 0;
}
<commit_msg>Add build comment.<commit_after>//	Simple Chatterbox client written in C++
//	Many of the functions are taken from the excellent Winsock FAQ at
//		http://tangentsoft.net/wskfaq/
//	Build using:
//		g++ -std=c++0x -Wall -o cbclient cbclient.cpp -lws2_32

#include <iostream>
#include <string>
#include <stdexcept>
#include <winsock2.h>
// #include <winsock.h>

using namespace std;

class WASDataWrapper {
	WSADATA wsaData_;
public:
	WASDataWrapper() {
		if(WSAStartup(MAKEWORD(2,2), &wsaData_) != 0) {
			throw runtime_error("WSAStartup failed");
		}
	}

	~WASDataWrapper() {
		WSACleanup();
	}

};

//// LookupAddress /////////////////////////////////////////////////////
// Given an address string, determine if it's a dotted-quad IP address
// or a domain address.  If the latter, ask DNS to resolve it.  In
// either case, return resolved IP address.  If we fail, we return
// INADDR_NONE.
u_long LookupAddress(const char* pcHost)
{
    u_long nRemoteAddr = inet_addr(pcHost);
    if (nRemoteAddr == INADDR_NONE) {
        // pcHost isn't a dotted IP, so resolve it through DNS
        hostent* pHE = gethostbyname(pcHost);
        if (pHE == 0) {
            return INADDR_NONE;
        }
        nRemoteAddr = *((u_long*)pHE->h_addr_list[0]);
    }

    return nRemoteAddr;
}

//// EstablishConnection ///////////////////////////////////////////////
// Connects to a given address, on a given port, both of which must be
// in network byte order.  Returns newly-connected socket if we succeed,
// or INVALID_SOCKET if we fail.
SOCKET EstablishConnection(u_long nRemoteAddr, u_short nPort)
{
    // Create a stream socket
    // SOCKET sd = socket(AF_INET, SOCK_STREAM, 0);
    SOCKET sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sd != INVALID_SOCKET) {
        SOCKADDR_IN sinRemote;
        sinRemote.sin_family = AF_INET;
        sinRemote.sin_addr.s_addr = nRemoteAddr;
        sinRemote.sin_port = nPort;
        if (connect(sd, (sockaddr*)&sinRemote, sizeof(sockaddr_in)) ==
                SOCKET_ERROR) {
            sd = INVALID_SOCKET;
        }
    }

    return sd;
}

//// ShutdownConnection ////////////////////////////////////////////////
// Gracefully shuts the connection sd down.  Returns true if we're
// successful, false otherwise.
bool ShutdownConnection(SOCKET sd)
{
	const int kBufferSize = 1024;
	// const int SD_SEND = 1;

    // Disallow any further data sends.  This will tell the other side
    // that we want to go away now.  If we skip this step, we don't
    // shut the connection down nicely.
    if (shutdown(sd, SD_SEND) == SOCKET_ERROR) {
        return false;
    }

    // Receive any extra data still sitting on the socket.  After all
    // data is received, this call will block until the remote host
    // acknowledges the TCP control packet sent by the shutdown above.
    // Then we'll get a 0 back from recv, signalling that the remote
    // host has closed its side of the connection.
    char acReadBuffer[kBufferSize];
    while (1) {
        int nNewBytes = recv(sd, acReadBuffer, kBufferSize, 0);
        if (nNewBytes == SOCKET_ERROR) {
            return false;
        }
        else if (nNewBytes != 0) {
            cerr << endl << "FYI, received " << nNewBytes <<
                    " unexpected bytes during shutdown." << endl;
        }
        else {
            // Okay, we're done!
            break;
        }
    }

    // Close the socket.
    if (closesocket(sd) == SOCKET_ERROR) {
        return false;
    }

    return true;
}

int main() {

	WASDataWrapper wsaData;

	//	Connect to a Chatterbox server
	string host = "localhost";
	u_short port = 20000;

    u_long remote_addr = LookupAddress(host.c_str());
    if (remote_addr == INADDR_NONE) {
        cerr << "Could not detremine remote host address." ;
        return 1;
    }

    cout << "remote_addr=" << remote_addr << '\n';
    in_addr address;
    memcpy(&address, &remote_addr, sizeof(u_long));
    cout << "Connecting to Chatterbox server at, " << inet_ntoa(address) << ":" << port << endl;

	// Create a stream socket
	SOCKET sd = EstablishConnection(remote_addr, port);
	if(sd == INVALID_SOCKET) {
		cout << "Could not connect to Chatterbox server\n";
    	cerr << "WSAGetLastError() says:" << WSAGetLastError() << '\n';
		return 1;
	}

	cout << "Connected to Chatterbox server!";

	//	Let user enter an id
	//	auto userID = "";
	//	userID << cin;

	//	Send the user ID
	//	socket.send(userID);

	//	Create a sender thread and listener thread
	//	Start listener thread
	//	Start sender thread

	//	Wait for threads to exit

	// Shut connection down
	cout << "Disconnectiong from Chatterbox server.\n";
	if (ShutdownConnection(sd)) {
	    cout << "Disconnected successfully.\n" << endl;
	}
	else {
	    cout << "Problem disconnecting.\n";
	}

	cout << "Exiting Chatterbox client." << endl;

	return 0;
}
<|endoftext|>


<commit_before>//@author A0094446X
#include "stdafx.h"
#include <QApplication>
#include <QList>
#include <QPair>
#include "task_panel_manager.h"
namespace You {
namespace GUI {

using Date = boost::gregorian::date;
const QString MainWindow::TaskPanelManager::TASK_COLUMN_1 = "Hidden ID Column";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_2 = "Index";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_3 = "Description";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_4 = "Deadline";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_5 = "Priority";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_6 = "Dependencies";

MainWindow::TaskPanelManager::TaskPanelManager(MainWindow* const parentGUI)
: BaseManager(parentGUI), deleteAction(QString("Delete"), this),
editAction(QString("Edit"), this), addAction(QString("Add"), this),
deleteSignalMapper(this), editSignalMapper(this) {
}

MainWindow::TaskPanelManager::~TaskPanelManager() {
}

void MainWindow::TaskPanelManager::setup() {
	QStringList columnHeaders({
		TASK_COLUMN_1,
		TASK_COLUMN_2,
		TASK_COLUMN_3,
		TASK_COLUMN_4,
		TASK_COLUMN_5,
		TASK_COLUMN_6
	});
	QTreeWidget* taskTreePanel = parentGUI->ui.taskTreePanel;
	connect(taskTreePanel, SIGNAL(itemSelectionChanged()),
		parentGUI, SLOT(taskSelected()));

	connect(taskTreePanel, SIGNAL(customContextMenuRequested(const QPoint &)),
		this, SLOT(contextMenu(const QPoint &)));
	taskTreePanel->setColumnCount(columnHeaders.size());
	taskTreePanel->setHeaderItem(createItem(columnHeaders).release());
	// TODO(angathorion): remove magic constants.
	QHeaderView* header = taskTreePanel->header();
	header->setStretchLastSection(true);

	for (int i = 1; i < columnHeaders.size(); ++i) {
		if (i == 2) {
			continue;
		}
		header->resizeSection(i, header->defaultSectionSize());
	}

	taskTreePanel->header()->setMinimumSectionSize(75);
	taskTreePanel->setColumnHidden(0, true);
	taskTreePanel->setColumnHidden(5, true);
}

void MainWindow::TaskPanelManager::addTask(const Task& task) {
	std::unique_ptr<QTreeWidgetItem> item(createItem(task));
	parentGUI->ui.taskTreePanel->addTopLevelItem(item.release());
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::addSubtask(QTreeWidgetItem* parent,
	const QStringList& rowStrings) {
	std::unique_ptr<QTreeWidgetItem> item(createItem(rowStrings));
	parent->addChild(item.release());
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::editTask(const Task& task) {
	QList<QTreeWidgetItem*> items = findItems(task.getID());
	assert(items.length() == 1);
	QTreeWidgetItem item = *items.at(0);
	QStringList wstr = taskToStrVec(task);
	*items.at(0) = *createItem(wstr);
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::deleteTask(Task::ID taskID) {
	QList<QTreeWidgetItem*> items = findItems(taskID);
	assert(items.length() == 1);
	deleteTask(items.at(0));
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::deleteTask(QTreeWidgetItem* task) {
	delete task;
}

std::unique_ptr<QTreeWidgetItem> MainWindow::TaskPanelManager::createItem(
	const Task& task) {
	return createItem(taskToStrVec(task));
}

std::unique_ptr<QTreeWidgetItem> MainWindow::TaskPanelManager::createItem(
	const QStringList& rowStrings) {
	return std::make_unique<QTreeWidgetItem>(rowStrings);
}

QList<QTreeWidgetItem*> MainWindow::TaskPanelManager::findItems(
	You::Controller::Task::ID taskID) const {
	return parentGUI->ui.taskTreePanel->findItems(
		boost::lexical_cast<QString>(taskID), 0);
}

QStringList MainWindow::TaskPanelManager::taskToStrVec(
	const You::Controller::Task& task) {
	QStringList result;

	// Insert id
	result.push_back(boost::lexical_cast<QString>(task.getID()));

	// Insert dummy count
	result.push_back("0");

	// Insert description
	result.push_back(QString::fromStdWString(task.getDescription()));

	// Insert deadline
	std::wstringstream wss;
	if (task.getDeadline() == Task::NEVER) {
		wss << L"Never";
	} else if (isPastDue(task.getDeadline())) {
		wss << L"Overdue (" << task.getDeadline() << L")";
	} else if (isDueAfter(task.getDeadline(), 0)) {
		wss << L"Today (" << task.getDeadline() << L")";
	} else if (isDueAfter(task.getDeadline(), 1)) {
		wss << L"Tomorrow (" << task.getDeadline() << L")";
	} else if (isDueAfter(task.getDeadline(), 2)) {
		wss << L"In two days (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 7)) {
		wss << L"Within one week (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 14)) {
		wss << L"Within two weeks (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 21)) {
		wss << L"Within three weeks (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 28)) {
		wss << L"Within one month (" << task.getDeadline() << L")";
	} else {
		wss << L"More than a month away (" << task.getDeadline() << L")";
	}
	result.push_back(boost::lexical_cast<QString>(wss.str()));

	// Insert priority
	QString priority[] { "High", "Normal" };

	switch (task.getPriority()) {
	case Task::Priority::HIGH:
		result.push_back(priority[0]);
	case Task::Priority::NORMAL:
		result.push_back(priority[1]);
	}

	// Insert dependencies
	std::ostringstream ss;
	if (task.getDependencies().size() != 0) {
		Task::Dependencies dependencies = task.getDependencies();
		std::copy(dependencies.begin(), --dependencies.end(),
			std::ostream_iterator<Task::ID>(ss, ", "));
		ss << *dependencies.end();
		result.push_back(QString::fromStdString(ss.str()));
	} else {
		result.push_back("None");
	}

	return result;
}

void MainWindow::TaskPanelManager::updateRowNumbers() {
	int rowNum = 0;
	for (QTreeWidgetItemIterator it(parentGUI->ui.taskTreePanel); *it; ++it) {
		(*it)->setData(1, Qt::DisplayRole, rowNum++);
	}
}

bool MainWindow::TaskPanelManager::isPastDue(Task::Time deadline) {
	Task::Time now = boost::posix_time::second_clock::local_time();
	return deadline < now;
}

bool MainWindow::TaskPanelManager::isDueAfter(
		Task::Time deadline, int daysLeft) {
	Date by = Date(deadline.date());
	Date today = boost::gregorian::day_clock::local_day();
	return by.modjulian_day() - today.modjulian_day() == daysLeft;
}

bool MainWindow::TaskPanelManager::isDueWithin(
	Task::Time deadline, int daysLeft) {
	Date by = Date(deadline.date());
	Date today = boost::gregorian::day_clock::local_day();
	return by.julian_day() - today.julian_day() < daysLeft;
}

void MainWindow::TaskPanelManager::contextMenu(const QPoint &pos) {
	/// Try to get the item at the position of the context menu
	QTreeWidgetItem *item = parentGUI->ui.taskTreePanel->itemAt(pos);
	itemContextMenu.reset(new QMenu(parentGUI->ui.taskTreePanel));

	/// Adds the Add Task action. This is always present in the menu.
	itemContextMenu->addAction(&addAction);
	connect(&addAction, SIGNAL(triggered()), parentGUI, SLOT(contextAddTask()));

	/// Adds the Edit Task and Delete Task actions if an item is selected.
	/// QSignalMapper is necessary because arguments need to be passed
	/// as part of the signal.
	if (item) {
		deleteSignalMapper.setMapping(&deleteAction, item->text(1).toInt());
		connect(&deleteAction, SIGNAL(triggered()),
			&deleteSignalMapper, SLOT(map()));
		itemContextMenu->addAction(&deleteAction);
		connect(&deleteSignalMapper, SIGNAL(mapped(int)),
			parentGUI, SLOT(contextDeleteTask(int)));

		editSignalMapper.setMapping(&editAction, item->text(1).toInt());
		connect(&editAction, SIGNAL(triggered()),
			&editSignalMapper, SLOT(map()));
		itemContextMenu->addAction(&editAction);
		connect(&editSignalMapper, SIGNAL(mapped(int)),
			parentGUI, SLOT(contextEditTask(int)));
	}

	itemContextMenu->popup(
		parentGUI->ui.taskTreePanel->viewport()->mapToGlobal(pos));
}

}  // namespace GUI
}  // namespace You
<commit_msg>Set to element before end<commit_after>//@author A0094446X
#include "stdafx.h"
#include <QApplication>
#include <QList>
#include <QPair>
#include "task_panel_manager.h"
namespace You {
namespace GUI {

using Date = boost::gregorian::date;
const QString MainWindow::TaskPanelManager::TASK_COLUMN_1 = "Hidden ID Column";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_2 = "Index";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_3 = "Description";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_4 = "Deadline";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_5 = "Priority";
const QString MainWindow::TaskPanelManager::TASK_COLUMN_6 = "Dependencies";

MainWindow::TaskPanelManager::TaskPanelManager(MainWindow* const parentGUI)
: BaseManager(parentGUI), deleteAction(QString("Delete"), this),
editAction(QString("Edit"), this), addAction(QString("Add"), this),
deleteSignalMapper(this), editSignalMapper(this) {
}

MainWindow::TaskPanelManager::~TaskPanelManager() {
}

void MainWindow::TaskPanelManager::setup() {
	QStringList columnHeaders({
		TASK_COLUMN_1,
		TASK_COLUMN_2,
		TASK_COLUMN_3,
		TASK_COLUMN_4,
		TASK_COLUMN_5,
		TASK_COLUMN_6
	});
	QTreeWidget* taskTreePanel = parentGUI->ui.taskTreePanel;
	connect(taskTreePanel, SIGNAL(itemSelectionChanged()),
		parentGUI, SLOT(taskSelected()));

	connect(taskTreePanel, SIGNAL(customContextMenuRequested(const QPoint &)),
		this, SLOT(contextMenu(const QPoint &)));
	taskTreePanel->setColumnCount(columnHeaders.size());
	taskTreePanel->setHeaderItem(createItem(columnHeaders).release());
	// TODO(angathorion): remove magic constants.
	QHeaderView* header = taskTreePanel->header();
	header->setStretchLastSection(true);

	for (int i = 1; i < columnHeaders.size(); ++i) {
		if (i == 2) {
			continue;
		}
		header->resizeSection(i, header->defaultSectionSize());
	}

	taskTreePanel->header()->setMinimumSectionSize(75);
	taskTreePanel->setColumnHidden(0, true);
	taskTreePanel->setColumnHidden(5, true);
}

void MainWindow::TaskPanelManager::addTask(const Task& task) {
	std::unique_ptr<QTreeWidgetItem> item(createItem(task));
	parentGUI->ui.taskTreePanel->addTopLevelItem(item.release());
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::addSubtask(QTreeWidgetItem* parent,
	const QStringList& rowStrings) {
	std::unique_ptr<QTreeWidgetItem> item(createItem(rowStrings));
	parent->addChild(item.release());
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::editTask(const Task& task) {
	QList<QTreeWidgetItem*> items = findItems(task.getID());
	assert(items.length() == 1);
	QTreeWidgetItem item = *items.at(0);
	QStringList wstr = taskToStrVec(task);
	*items.at(0) = *createItem(wstr);
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::deleteTask(Task::ID taskID) {
	QList<QTreeWidgetItem*> items = findItems(taskID);
	assert(items.length() == 1);
	deleteTask(items.at(0));
	updateRowNumbers();
}

void MainWindow::TaskPanelManager::deleteTask(QTreeWidgetItem* task) {
	delete task;
}

std::unique_ptr<QTreeWidgetItem> MainWindow::TaskPanelManager::createItem(
	const Task& task) {
	return createItem(taskToStrVec(task));
}

std::unique_ptr<QTreeWidgetItem> MainWindow::TaskPanelManager::createItem(
	const QStringList& rowStrings) {
	return std::make_unique<QTreeWidgetItem>(rowStrings);
}

QList<QTreeWidgetItem*> MainWindow::TaskPanelManager::findItems(
	You::Controller::Task::ID taskID) const {
	return parentGUI->ui.taskTreePanel->findItems(
		boost::lexical_cast<QString>(taskID), 0);
}

QStringList MainWindow::TaskPanelManager::taskToStrVec(
	const You::Controller::Task& task) {
	QStringList result;

	// Insert id
	result.push_back(boost::lexical_cast<QString>(task.getID()));

	// Insert dummy count
	result.push_back("0");

	// Insert description
	result.push_back(QString::fromStdWString(task.getDescription()));

	// Insert deadline
	std::wstringstream wss;
	if (task.getDeadline() == Task::NEVER) {
		wss << L"Never";
	} else if (isPastDue(task.getDeadline())) {
		wss << L"Overdue (" << task.getDeadline() << L")";
	} else if (isDueAfter(task.getDeadline(), 0)) {
		wss << L"Today (" << task.getDeadline() << L")";
	} else if (isDueAfter(task.getDeadline(), 1)) {
		wss << L"Tomorrow (" << task.getDeadline() << L")";
	} else if (isDueAfter(task.getDeadline(), 2)) {
		wss << L"In two days (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 7)) {
		wss << L"Within one week (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 14)) {
		wss << L"Within two weeks (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 21)) {
		wss << L"Within three weeks (" << task.getDeadline() << L")";
	} else if (isDueWithin(task.getDeadline(), 28)) {
		wss << L"Within one month (" << task.getDeadline() << L")";
	} else {
		wss << L"More than a month away (" << task.getDeadline() << L")";
	}
	result.push_back(boost::lexical_cast<QString>(wss.str()));

	// Insert priority
	QString priority[] { "High", "Normal" };

	switch (task.getPriority()) {
	case Task::Priority::HIGH:
		result.push_back(priority[0]);
	case Task::Priority::NORMAL:
		result.push_back(priority[1]);
	}

	// Insert dependencies
	std::ostringstream ss;
	if (task.getDependencies().size() != 0) {
		Task::Dependencies dependencies = task.getDependencies();
		std::copy(dependencies.begin(), --dependencies.end(),
			std::ostream_iterator<Task::ID>(ss, ", "));
		ss << *--dependencies.end();
		result.push_back(QString::fromStdString(ss.str()));
	} else {
		result.push_back("None");
	}

	return result;
}

void MainWindow::TaskPanelManager::updateRowNumbers() {
	int rowNum = 0;
	for (QTreeWidgetItemIterator it(parentGUI->ui.taskTreePanel); *it; ++it) {
		(*it)->setData(1, Qt::DisplayRole, rowNum++);
	}
}

bool MainWindow::TaskPanelManager::isPastDue(Task::Time deadline) {
	Task::Time now = boost::posix_time::second_clock::local_time();
	return deadline < now;
}

bool MainWindow::TaskPanelManager::isDueAfter(
		Task::Time deadline, int daysLeft) {
	Date by = Date(deadline.date());
	Date today = boost::gregorian::day_clock::local_day();
	return by.modjulian_day() - today.modjulian_day() == daysLeft;
}

bool MainWindow::TaskPanelManager::isDueWithin(
	Task::Time deadline, int daysLeft) {
	Date by = Date(deadline.date());
	Date today = boost::gregorian::day_clock::local_day();
	return by.julian_day() - today.julian_day() < daysLeft;
}

void MainWindow::TaskPanelManager::contextMenu(const QPoint &pos) {
	/// Try to get the item at the position of the context menu
	QTreeWidgetItem *item = parentGUI->ui.taskTreePanel->itemAt(pos);
	itemContextMenu.reset(new QMenu(parentGUI->ui.taskTreePanel));

	/// Adds the Add Task action. This is always present in the menu.
	itemContextMenu->addAction(&addAction);
	connect(&addAction, SIGNAL(triggered()), parentGUI, SLOT(contextAddTask()));

	/// Adds the Edit Task and Delete Task actions if an item is selected.
	/// QSignalMapper is necessary because arguments need to be passed
	/// as part of the signal.
	if (item) {
		deleteSignalMapper.setMapping(&deleteAction, item->text(1).toInt());
		connect(&deleteAction, SIGNAL(triggered()),
			&deleteSignalMapper, SLOT(map()));
		itemContextMenu->addAction(&deleteAction);
		connect(&deleteSignalMapper, SIGNAL(mapped(int)),
			parentGUI, SLOT(contextDeleteTask(int)));

		editSignalMapper.setMapping(&editAction, item->text(1).toInt());
		connect(&editAction, SIGNAL(triggered()),
			&editSignalMapper, SLOT(map()));
		itemContextMenu->addAction(&editAction);
		connect(&editSignalMapper, SIGNAL(mapped(int)),
			parentGUI, SLOT(contextEditTask(int)));
	}

	itemContextMenu->popup(
		parentGUI->ui.taskTreePanel->viewport()->mapToGlobal(pos));
}

}  // namespace GUI
}  // namespace You
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "internal/parser.h"
#include "exception.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;

#pragma region boost::variant visitor helpers

namespace {

struct ToStringVisitor : public boost::static_visitor<std::wstring> {
	template<typename T>
	std::wstring operator()(const T& value) {
		return ToString(value);
	}
};

}

namespace boost {

template<typename T1>
std::wstring ToString(const variant<T1>& t) {
	ToStringVisitor visitor;
	return apply_visitor(visitor, t);
}

}

#pragma endregion

namespace You {
namespace NLP {
namespace Internal {
	template <typename Q> static std::wstring ToString(const Q& q) {
		return q.toString();
	}
}

namespace UnitTests {

using You::NLP::ParserException;

using You::NLP::Internal::Parser;
using You::NLP::Internal::ADD_QUERY;
using You::NLP::Internal::QUERY;

TEST_CLASS(ParserTests) {
public:
	TEST_METHOD(throwsExceptionWhenParseFails) {
		Assert::ExpectException<ParserException>([]() {
				// "throw" is currently not defined, so this should work.
				Parser::parse(L"/throw");
			}, L"Throws exception on syntax error");
	}

	TEST_METHOD(parsesStringAsTask) {
		QUERY q = Parser::parse(L"win");

		Assert::AreEqual(QUERY(ADD_QUERY{
			L"win",
			std::wstring()
		}), q);
	}
};

}  // namespace UnitTests
}  // namespace NLP
}  // namespace You
<commit_msg>Forgot to commit the test suite.<commit_after>#include "stdafx.h"
#include "internal/query_parser.h"
#include "exception.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;

#pragma region boost::variant visitor helpers

namespace {

struct ToStringVisitor : public boost::static_visitor<std::wstring> {
	template<typename T>
	std::wstring operator()(const T& value) {
		return ToString(value);
	}
};

}

namespace boost {

template<typename T1>
std::wstring ToString(const variant<T1>& t) {
	ToStringVisitor visitor;
	return apply_visitor(visitor, t);
}

}

#pragma endregion

namespace You {
namespace NLP {
namespace Internal {
	template <typename Q> static std::wstring ToString(const Q& q) {
		return q.toString();
	}
}

namespace UnitTests {

using You::NLP::ParserException;

using You::NLP::Internal::QueryParser;
using You::NLP::Internal::ADD_QUERY;
using You::NLP::Internal::QUERY;

TEST_CLASS(ParserTests) {
public:
	TEST_METHOD(throwsExceptionWhenParseFails) {
		Assert::ExpectException<ParserException>([]() {
				// "throw" is currently not defined, so this should work.
				QueryParser::parse(L"/throw");
			}, L"Throws exception on syntax error");
	}

	TEST_METHOD(parsesStringAsTask) {
		QUERY q = QueryParser::parse(L"win");

		Assert::AreEqual(QUERY(ADD_QUERY{
			L"win",
			std::wstring()
		}), q);
	}
};

}  // namespace UnitTests
}  // namespace NLP
}  // namespace You
<|endoftext|>


<commit_before>namespace TAnomalyDetection {

/////////////////////////////////////////////
/// Nearest Neighbor based Annomaly Detection.
void TNearestNeighbor::UpdateDistance(const int& ColId, const int& IgnoreCol) {
    // get vector we update distances for and precompute its norm
    const TIntFltKdV& ColVec = Mat[ColId];
    const double ColNorm = TLinAlg::Norm2(ColVec);
    // search for nearest neighbor
    int NearId = -1; double NearDist = TFlt::Mx;
    for (int ColN = 0; ColN < Mat.Len(); ColN++) {
        // skip column itself and columns to ignore
        if (ColN == ColId) { continue; }
        if (ColN == IgnoreCol) { continue; }
        // get distance
        const TIntFltKdV& _ColVec = Mat[ColN];
        const double Dist = ColNorm - 2 * TLinAlg::DotProduct(ColVec, _ColVec) + TLinAlg::Norm2(_ColVec);
        // check if new nearest neighbor for existing vector ColN
        if (Dist < DistV[ColN]) { DistV[ColN] = Dist; DistColV[ColN] = ColId; }
        // check if new nearest neighbor for new vector ColId
        if (Dist < NearDist) { NearId = ColN; NearDist = Dist; }
    }
    // remember new neighbor
    DistV[ColId] = NearDist;
    DistColV[ColId] = NearId;
}

void TNearestNeighbor::UpdateThreshold() {
    ThresholdV.Gen(RateV.Len(), 0);
    // sort distances
    TFltV SortedV = DistV; SortedV.Sort(true);
    // establish thrashold for each rate
    for (const double Rate : RateV) {
        // element Id corresponding to Rate-th percentile
        const int Elt = floor((1.0 - Rate) * SortedV.Len());
        // remember the distance as threshold
        ThresholdV.Add(SortedV[Elt]);
    }
}

void TNearestNeighbor::Forget(const int& ColId) {
    // identify which vectors we should update
    TIntV CheckV;
    for (int ColN = 0; ColN < Mat.Len(); ColN++) {
        // skip self
        if (ColN == ColId) { continue; }
        // we are the nearest neighbor, need to find a new one
        if (DistColV[ColN] == ColId) { CheckV.Add(ColN); }
    }
    // reasses
    for (const int ColN : CheckV) {
        // update distance for ColN ignoring vector ColId
        UpdateDistance(ColN, ColId);
    }
}

TNearestNeighbor::TNearestNeighbor(const double& Rate, const int& _WindowSize):
        WindowSize(_WindowSize) {

    // remember the rate
    RateV.Add(Rate);
    // initialize all vectors to window size
    Mat.Gen(WindowSize, 0);
    DistV.Gen(WindowSize, 0);
    DistColV.Gen(WindowSize, 0);
}

TNearestNeighbor::TNearestNeighbor(TSIn& SIn): RateV(SIn), WindowSize(SIn), Mat(SIn),
    DistV(SIn), DistColV(SIn), ThresholdV(SIn), InitVecs(SIn), NextCol(SIn) { }

void TNearestNeighbor::Save(TSOut& SOut) {
    RateV.Save(SOut);
    WindowSize.Save(SOut);
    Mat.Save(SOut);
    DistV.Save(SOut);
    DistColV.Save(SOut);
    ThresholdV.Save(SOut);
    InitVecs.Save(SOut);
    NextCol.Save(SOut);
}

void TNearestNeighbor::PartialFit(const TIntFltKdV& Vec) {
    if (InitVecs < WindowSize) {
        // not yet full, extend matrix and distance vectors
        Mat.Add(Vec);
        // make sure we are very far from everything for update distance to kick in
        DistV.Add(TFlt::Mx); DistColV.Add(InitVecs);
        // update distance for new vector
        UpdateDistance(InitVecs);
        // move onwards
        InitVecs++;
        // check if we are initialized
        if (InitVecs == WindowSize) { UpdateThreshold(); }
    } else {
        // we are full, make space first
        Forget(NextCol);
        // overwrite
        Mat[NextCol] = Vec;
        DistV[NextCol] = TFlt::Mx;
        DistColV[NextCol] = NextCol;
        // update distance for overwriten vector
        UpdateDistance(NextCol);
        // establish new threshold
        UpdateThreshold();
        // move onwards
        NextCol++;
        if (NextCol >= WindowSize) { NextCol = 0; }
    }
}

double TNearestNeighbor::DecisionFunction(const TIntFltKdV& Vec) const {
    double NearDist = TFlt::Mx;
    for (const TIntFltKdV& Col : Mat) {
        const double Dist = TLinAlg::Norm2(Vec) - 2 * TLinAlg::DotProduct(Vec, Col) + TLinAlg::Norm2(Col);
        if (Dist < NearDist) { NearDist = Dist; }
    }
    return NearDist;
}

int TNearestNeighbor::Predict(const TIntFltKdV& Vec) const {
    // if not initialized, do nothing
    if (!IsInit()) { return 0; }
    // get distance to nearest stored element
    const double Dist = DecisionFunction(Vec);
    // find in which rate bucket if falls (zero means none)
    int Rate = 0;
    while (Rate < RateV.Len() && Dist > ThresholdV[Rate]) { Rate++; }
    // we are done
    return Rate;
}

};<commit_msg>Nearest neighbor checked that rate parameters is between 0 and 1.<commit_after>namespace TAnomalyDetection {

/////////////////////////////////////////////
/// Nearest Neighbor based Annomaly Detection.
void TNearestNeighbor::UpdateDistance(const int& ColId, const int& IgnoreCol) {
    // get vector we update distances for and precompute its norm
    const TIntFltKdV& ColVec = Mat[ColId];
    const double ColNorm = TLinAlg::Norm2(ColVec);
    // search for nearest neighbor
    int NearId = -1; double NearDist = TFlt::Mx;
    for (int ColN = 0; ColN < Mat.Len(); ColN++) {
        // skip column itself and columns to ignore
        if (ColN == ColId) { continue; }
        if (ColN == IgnoreCol) { continue; }
        // get distance
        const TIntFltKdV& _ColVec = Mat[ColN];
        const double Dist = ColNorm - 2 * TLinAlg::DotProduct(ColVec, _ColVec) + TLinAlg::Norm2(_ColVec);
        // check if new nearest neighbor for existing vector ColN
        if (Dist < DistV[ColN]) { DistV[ColN] = Dist; DistColV[ColN] = ColId; }
        // check if new nearest neighbor for new vector ColId
        if (Dist < NearDist) { NearId = ColN; NearDist = Dist; }
    }
    // remember new neighbor
    DistV[ColId] = NearDist;
    DistColV[ColId] = NearId;
}

void TNearestNeighbor::UpdateThreshold() {
    ThresholdV.Gen(RateV.Len(), 0);
    // sort distances
    TFltV SortedV = DistV; SortedV.Sort(true);
    // establish thrashold for each rate
    for (const double Rate : RateV) {
        // element Id corresponding to Rate-th percentile
        const int Elt = floor((1.0 - Rate) * SortedV.Len());
        // remember the distance as threshold
        ThresholdV.Add(SortedV[Elt]);
    }
}

void TNearestNeighbor::Forget(const int& ColId) {
    // identify which vectors we should update
    TIntV CheckV;
    for (int ColN = 0; ColN < Mat.Len(); ColN++) {
        // skip self
        if (ColN == ColId) { continue; }
        // we are the nearest neighbor, need to find a new one
        if (DistColV[ColN] == ColId) { CheckV.Add(ColN); }
    }
    // reasses
    for (const int ColN : CheckV) {
        // update distance for ColN ignoring vector ColId
        UpdateDistance(ColN, ColId);
    }
}

TNearestNeighbor::TNearestNeighbor(const double& Rate, const int& _WindowSize):
        WindowSize(_WindowSize) {

    // assert rate parameter range
    EAssertR(0.0 < Rate && Rate < 1.0, "TAnomalyDetection::TNearestNeighbor: Rate parameter not > 0.0 and < 1.0");
    // remember the rate
    RateV.Add(Rate);
    // initialize all vectors to window size
    Mat.Gen(WindowSize, 0);
    DistV.Gen(WindowSize, 0);
    DistColV.Gen(WindowSize, 0);
}

TNearestNeighbor::TNearestNeighbor(TSIn& SIn): RateV(SIn), WindowSize(SIn), Mat(SIn),
    DistV(SIn), DistColV(SIn), ThresholdV(SIn), InitVecs(SIn), NextCol(SIn) { }

void TNearestNeighbor::Save(TSOut& SOut) {
    RateV.Save(SOut);
    WindowSize.Save(SOut);
    Mat.Save(SOut);
    DistV.Save(SOut);
    DistColV.Save(SOut);
    ThresholdV.Save(SOut);
    InitVecs.Save(SOut);
    NextCol.Save(SOut);
}

void TNearestNeighbor::PartialFit(const TIntFltKdV& Vec) {
    if (InitVecs < WindowSize) {
        // not yet full, extend matrix and distance vectors
        Mat.Add(Vec);
        // make sure we are very far from everything for update distance to kick in
        DistV.Add(TFlt::Mx); DistColV.Add(InitVecs);
        // update distance for new vector
        UpdateDistance(InitVecs);
        // move onwards
        InitVecs++;
        // check if we are initialized
        if (InitVecs == WindowSize) { UpdateThreshold(); }
    } else {
        // we are full, make space first
        Forget(NextCol);
        // overwrite
        Mat[NextCol] = Vec;
        DistV[NextCol] = TFlt::Mx;
        DistColV[NextCol] = NextCol;
        // update distance for overwriten vector
        UpdateDistance(NextCol);
        // establish new threshold
        UpdateThreshold();
        // move onwards
        NextCol++;
        if (NextCol >= WindowSize) { NextCol = 0; }
    }
}

double TNearestNeighbor::DecisionFunction(const TIntFltKdV& Vec) const {
    double NearDist = TFlt::Mx;
    for (const TIntFltKdV& Col : Mat) {
        const double Dist = TLinAlg::Norm2(Vec) - 2 * TLinAlg::DotProduct(Vec, Col) + TLinAlg::Norm2(Col);
        if (Dist < NearDist) { NearDist = Dist; }
    }
    return NearDist;
}

int TNearestNeighbor::Predict(const TIntFltKdV& Vec) const {
    // if not initialized, do nothing
    if (!IsInit()) { return 0; }
    // get distance to nearest stored element
    const double Dist = DecisionFunction(Vec);
    // find in which rate bucket if falls (zero means none)
    int Rate = 0;
    while (Rate < RateV.Len() && Dist > ThresholdV[Rate]) { Rate++; }
    // we are done
    return Rate;
}

};<|endoftext|>


<commit_before> /**
 * global_odom_to_tf.cpp
 * Broadcast transform between local_origin and fcu.
 *
 * @author  Syler Wagner      <syler@mit.edu>

 * @date    2016-07-01  syler   creation
 *
 * This node listens for odometry messages on the /mavros/global_position/local topic
 * and broadcasts a transform between local_origin and fcu.
 **/

#include "ros/ros.h"
#include "nav_msgs/Odometry.h"
#include "tf/transform_broadcaster.h"

//$ TODO: use mavros.get_namespace() instead of hardcoding
tf::TransformBroadcaster odom_broadcaster;

void odometryCallback(const nav_msgs::Odometry::ConstPtr& odom) {
  geometry_msgs::TransformStamped odom_trans;
  odom_trans.header.stamp = ros::Time::now();
  odom_trans.header.frame_id = "local_origin";
  odom_trans.child_frame_id = "fcu";

  odom_trans.transform.translation.x = odom->pose.pose.position.x;
  odom_trans.transform.translation.y = odom->pose.pose.position.y;
  odom_trans.transform.translation.z = odom->pose.pose.position.z;
  odom_trans.transform.rotation = odom->pose.pose.orientation;

  odom_broadcaster.sendTransform(odom_trans);
}

int main(int argc, char** argv) {
  ros::init(argc, argv, "odometry_publisher");

  ros::NodeHandle n;

  ros::Subscriber odom_sub = n.subscribe("/mavros/global_position/local", 1000, odometryCallback);
  ros::Rate r(1000.0);

  while (n.ok()) {
    ros::spin();
  }
}
<commit_msg>Fixed global_odom_to_tf.cpp broadcasting runtime error<commit_after> /**
 * global_odom_to_tf.cpp
 * Broadcast transform between local_origin and fcu.
 *
 * @author  Syler Wagner      <syler@mit.edu>

 * @date    2016-07-01  syler   creation
 *
 * This node listens for odometry messages on the /mavros/global_position/local topic
 * and broadcasts a transform between local_origin and fcu.
 **/

#include "ros/ros.h"
#include "nav_msgs/Odometry.h"
#include "tf/transform_broadcaster.h"

//$ TODO: use mavros.get_namespace() instead of hardcoding

 geometry_msgs::TransformStamped odom_trans;

 void odometryCallback(const nav_msgs::Odometry::ConstPtr& odom) {

  odom_trans.header.stamp = ros::Time::now();
  odom_trans.header.frame_id = "local_origin";
  odom_trans.child_frame_id = "fcu";

  odom_trans.transform.translation.x = odom->pose.pose.position.x;
  odom_trans.transform.translation.y = odom->pose.pose.position.y;
  odom_trans.transform.translation.z = odom->pose.pose.position.z;
  odom_trans.transform.rotation = odom->pose.pose.orientation;

}

int main(int argc, char** argv) {
  ros::init(argc, argv, "global_odom_to_tf");

  ros::NodeHandle n;
  tf::TransformBroadcaster odom_broadcaster;

  ros::Subscriber odom_sub = n.subscribe("/mavros/global_position/local", 1000, odometryCallback);
  ros::Rate r(1000.0);

  while (n.ok()) {
    ros::spinOnce();
    odom_broadcaster.sendTransform(odom_trans);
    r.sleep();
  }
}
<|endoftext|>


<commit_before>/*
 * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 */
#include "ime.h"
#include "config.h"
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <fcitx-config/iniparser.h>
#include <fcitx-utils/log.h>
#include <fcitx-utils/standardpath.h>
#include <fcntl.h>
#include <libime/core/utils.h>
#include <libime/table/tablebaseddictionary.h>
#include <libime/table/tableoptions.h>

namespace fcitx {

FCITX_DEFINE_LOG_CATEGORY(table_logcategory, "table")

namespace {

libime::OrderPolicy converOrderPolicy(fcitx::OrderPolicy policy) {
    switch (policy) {
#define POLICY_CONVERT(NAME)                                                   \
    case fcitx::OrderPolicy::NAME:                                             \
        return libime::OrderPolicy::NAME;
        POLICY_CONVERT(No)
        POLICY_CONVERT(Freq)
        POLICY_CONVERT(Fast)
    }
    return libime::OrderPolicy::Freq;
}

void populateOptions(libime::TableBasedDictionary *dict,
                     const TableConfigRoot &root) {
    libime::TableOptions options;

    options.setOrderPolicy(converOrderPolicy(*root.config->orderPolicy));
    options.setNoSortInputLength(*root.config->noSortInputLength);
    options.setAutoSelect(*root.config->autoSelect);
    options.setAutoSelectLength(*root.config->autoSelectLength);
    options.setNoMatchAutoSelectLength(*root.config->noMatchAutoSelectLength);
    options.setCommitRawInput(*root.config->commitRawInput);
    options.setMatchingKey(
        Key::keySymToUnicode(root.config->matchingKey->sym()));
    std::set<uint32_t> endKeys;
    TABLE_DEBUG() << "End key" << *root.config->endKey;
    for (const auto &key : *root.config->endKey) {
        auto chr = Key::keySymToUnicode(key.sym());
        if (chr) {
            endKeys.insert(chr);
        }
    }
    options.setEndKey(endKeys);
    options.setExactMatch(*root.config->exactMatch);
    options.setLearning(*root.config->learning);
    options.setAutoPhraseLength(*root.config->autoPhraseLength);
    options.setSaveAutoPhraseAfter(*root.config->saveAutoPhraseAfter);
    options.setAutoRuleSet(std::unordered_set<std::string>(
        root.config->autoRuleSet->begin(), root.config->autoRuleSet->end()));
    options.setLanguageCode(*root.im->languageCode);

    dict->setTableOptions(options);
}
} // namespace

TableIME::TableIME(libime::LanguageModelResolver *lm) : lm_(lm) {}

std::tuple<libime::TableBasedDictionary *, libime::UserLanguageModel *,
           const TableConfig *>
TableIME::requestDict(const std::string &name) {
    auto iter = tables_.find(name);
    if (iter == tables_.end()) {
        TABLE_DEBUG() << "Load table config for: " << name;
        std::string filename = "inputmethod/";
        filename.append(name.begin(), name.end());
        filename += ".conf";
        auto files = StandardPath::global().openAll(StandardPath::Type::PkgData,
                                                    filename, O_RDONLY);
        RawConfig rawConfig;
        // reverse the order, so we end up parse user file at last.
        for (const auto &file : files | boost::adaptors::reversed) {
            readFromIni(rawConfig, file.fd());
        }

        iter = tables_
                   .emplace(std::piecewise_construct, std::make_tuple(name),
                            std::make_tuple())
                   .first;
        auto &root = iter->second.root;
        root.load(rawConfig);

        try {
            auto dict = std::make_unique<libime::TableBasedDictionary>();
            auto dictFile = StandardPath::global().open(
                StandardPath::Type::PkgData, *root.config->file, O_RDONLY);
            TABLE_DEBUG() << "Load table at: " << *root.config->file;
            if (dictFile.fd() < 0) {
                throw std::runtime_error("Couldn't open file");
            }
            boost::iostreams::stream_buffer<
                boost::iostreams::file_descriptor_source>
                buffer(dictFile.fd(), boost::iostreams::file_descriptor_flags::
                                          never_close_handle);
            std::istream in(&buffer);
            dict->load(in);
            iter->second.dict = std::move(dict);
        } catch (const std::exception &) {
        }

        if (auto dict = iter->second.dict.get()) {
            try {
                auto dictFile = StandardPath::global().openUser(
                    StandardPath::Type::PkgData,
                    stringutils::concat("table/", name, ".user.dict"),
                    O_RDONLY);
                boost::iostreams::stream_buffer<
                    boost::iostreams::file_descriptor_source>
                    buffer(dictFile.fd(),
                           boost::iostreams::file_descriptor_flags::
                               never_close_handle);
                std::istream in(&buffer);
                dict->loadUser(in);
            } catch (const std::exception &e) {
                TABLE_DEBUG() << e.what();
            }

            populateOptions(dict, iter->second.root);
            std::shared_ptr<const libime::StaticLanguageModelFile> lmFile;
            try {
                lmFile = lm_->languageModelFileForLanguage(
                    dict->tableOptions().languageCode());
            } catch (...) {
                TABLE_DEBUG()
                    << "Load language model for "
                    << dict->tableOptions().languageCode() << " failed.";
            }
            iter->second.model =
                std::make_unique<libime::UserLanguageModel>(lmFile);

            try {
                auto dictFile = StandardPath::global().openUser(
                    StandardPath::Type::PkgData,
                    stringutils::concat("table/", name, ".history"), O_RDONLY);
                boost::iostreams::stream_buffer<
                    boost::iostreams::file_descriptor_source>
                    buffer(dictFile.fd(),
                           boost::iostreams::file_descriptor_flags::
                               never_close_handle);
                std::istream in(&buffer);
                iter->second.model->load(in);
            } catch (const std::exception &e) {
                TABLE_DEBUG() << e.what();
            }
        }
    }

    return {iter->second.dict.get(), iter->second.model.get(),
            &(*iter->second.root.config)};
}

void TableIME::saveAll() {
    for (const auto &p : tables_) {
        saveDict(p.first);
    }
}

void TableIME::updateConfig(const std::string &name, const RawConfig &config) {
    auto iter = tables_.find(name);
    if (iter == tables_.end()) {
        return;
    }
    iter->second.root.config.mutableValue()->load(config, true);

    if (iter->second.dict) {
        populateOptions(iter->second.dict.get(), iter->second.root);
    }
    safeSaveAsIni(iter->second.root,
                  stringutils::concat("inputmethod/", name, ".conf"));
}

void TableIME::releaseUnusedDict(const std::unordered_set<std::string> &names) {
    for (auto iter = tables_.begin(); iter != tables_.end();) {
        if (names.count(iter->first) == 0) {
            TABLE_DEBUG() << "Release unused table: " << iter->first;
            saveDict(iter->first);
            iter = tables_.erase(iter);
        } else {
            ++iter;
        }
    }
}

void TableIME::saveDict(const std::string &name) {
    auto iter = tables_.find(name);
    if (iter == tables_.end()) {
        return;
    }
    libime::TableBasedDictionary *dict = iter->second.dict.get();
    libime::UserLanguageModel *lm = iter->second.model.get();
    if (!dict || !lm || !*iter->second.root.config->learning) {
        return;
    }
    auto fileName = stringutils::joinPath("table", name);

    StandardPath::global().safeSave(
        StandardPath::Type::PkgData, fileName + ".user.dict", [dict](int fd) {
            boost::iostreams::stream_buffer<
                boost::iostreams::file_descriptor_sink>
                buffer(fd, boost::iostreams::file_descriptor_flags::
                               never_close_handle);
            std::ostream out(&buffer);
            try {
                dict->saveUser(out);
                return static_cast<bool>(out);
            } catch (const std::exception &) {
                return false;
            }
        });

    StandardPath::global().safeSave(
        StandardPath::Type::PkgData, fileName + ".history", [lm](int fd) {
            boost::iostreams::stream_buffer<
                boost::iostreams::file_descriptor_sink>
                buffer(fd, boost::iostreams::file_descriptor_flags::
                               never_close_handle);
            std::ostream out(&buffer);
            try {
                lm->save(out);
                return static_cast<bool>(out);
            } catch (const std::exception &) {
                return false;
            }
        });
}
} // namespace fcitx
<commit_msg>Table input specific config should write to pkgdata.<commit_after>/*
 * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 */
#include "ime.h"
#include "config.h"
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <fcitx-config/iniparser.h>
#include <fcitx-utils/log.h>
#include <fcitx-utils/standardpath.h>
#include <fcntl.h>
#include <libime/core/utils.h>
#include <libime/table/tablebaseddictionary.h>
#include <libime/table/tableoptions.h>

namespace fcitx {

FCITX_DEFINE_LOG_CATEGORY(table_logcategory, "table")

namespace {

libime::OrderPolicy converOrderPolicy(fcitx::OrderPolicy policy) {
    switch (policy) {
#define POLICY_CONVERT(NAME)                                                   \
    case fcitx::OrderPolicy::NAME:                                             \
        return libime::OrderPolicy::NAME;
        POLICY_CONVERT(No)
        POLICY_CONVERT(Freq)
        POLICY_CONVERT(Fast)
    }
    return libime::OrderPolicy::Freq;
}

void populateOptions(libime::TableBasedDictionary *dict,
                     const TableConfigRoot &root) {
    libime::TableOptions options;

    options.setOrderPolicy(converOrderPolicy(*root.config->orderPolicy));
    options.setNoSortInputLength(*root.config->noSortInputLength);
    options.setAutoSelect(*root.config->autoSelect);
    options.setAutoSelectLength(*root.config->autoSelectLength);
    options.setNoMatchAutoSelectLength(*root.config->noMatchAutoSelectLength);
    options.setCommitRawInput(*root.config->commitRawInput);
    options.setMatchingKey(
        Key::keySymToUnicode(root.config->matchingKey->sym()));
    std::set<uint32_t> endKeys;
    TABLE_DEBUG() << "End key" << *root.config->endKey;
    for (const auto &key : *root.config->endKey) {
        auto chr = Key::keySymToUnicode(key.sym());
        if (chr) {
            endKeys.insert(chr);
        }
    }
    options.setEndKey(endKeys);
    options.setExactMatch(*root.config->exactMatch);
    options.setLearning(*root.config->learning);
    options.setAutoPhraseLength(*root.config->autoPhraseLength);
    options.setSaveAutoPhraseAfter(*root.config->saveAutoPhraseAfter);
    options.setAutoRuleSet(std::unordered_set<std::string>(
        root.config->autoRuleSet->begin(), root.config->autoRuleSet->end()));
    options.setLanguageCode(*root.im->languageCode);

    dict->setTableOptions(options);
}
} // namespace

TableIME::TableIME(libime::LanguageModelResolver *lm) : lm_(lm) {}

std::tuple<libime::TableBasedDictionary *, libime::UserLanguageModel *,
           const TableConfig *>
TableIME::requestDict(const std::string &name) {
    auto iter = tables_.find(name);
    if (iter == tables_.end()) {
        TABLE_DEBUG() << "Load table config for: " << name;
        std::string filename = "inputmethod/";
        filename.append(name.begin(), name.end());
        filename += ".conf";
        auto files = StandardPath::global().openAll(StandardPath::Type::PkgData,
                                                    filename, O_RDONLY);
        RawConfig rawConfig;
        // reverse the order, so we end up parse user file at last.
        for (const auto &file : files | boost::adaptors::reversed) {
            readFromIni(rawConfig, file.fd());
        }

        iter = tables_
                   .emplace(std::piecewise_construct, std::make_tuple(name),
                            std::make_tuple())
                   .first;
        auto &root = iter->second.root;
        root.load(rawConfig);

        try {
            auto dict = std::make_unique<libime::TableBasedDictionary>();
            auto dictFile = StandardPath::global().open(
                StandardPath::Type::PkgData, *root.config->file, O_RDONLY);
            TABLE_DEBUG() << "Load table at: " << *root.config->file;
            if (dictFile.fd() < 0) {
                throw std::runtime_error("Couldn't open file");
            }
            boost::iostreams::stream_buffer<
                boost::iostreams::file_descriptor_source>
                buffer(dictFile.fd(), boost::iostreams::file_descriptor_flags::
                                          never_close_handle);
            std::istream in(&buffer);
            dict->load(in);
            iter->second.dict = std::move(dict);
        } catch (const std::exception &) {
        }

        if (auto dict = iter->second.dict.get()) {
            try {
                auto dictFile = StandardPath::global().openUser(
                    StandardPath::Type::PkgData,
                    stringutils::concat("table/", name, ".user.dict"),
                    O_RDONLY);
                boost::iostreams::stream_buffer<
                    boost::iostreams::file_descriptor_source>
                    buffer(dictFile.fd(),
                           boost::iostreams::file_descriptor_flags::
                               never_close_handle);
                std::istream in(&buffer);
                dict->loadUser(in);
            } catch (const std::exception &e) {
                TABLE_DEBUG() << e.what();
            }

            populateOptions(dict, iter->second.root);
            std::shared_ptr<const libime::StaticLanguageModelFile> lmFile;
            try {
                lmFile = lm_->languageModelFileForLanguage(
                    dict->tableOptions().languageCode());
            } catch (...) {
                TABLE_DEBUG()
                    << "Load language model for "
                    << dict->tableOptions().languageCode() << " failed.";
            }
            iter->second.model =
                std::make_unique<libime::UserLanguageModel>(lmFile);

            try {
                auto dictFile = StandardPath::global().openUser(
                    StandardPath::Type::PkgData,
                    stringutils::concat("table/", name, ".history"), O_RDONLY);
                boost::iostreams::stream_buffer<
                    boost::iostreams::file_descriptor_source>
                    buffer(dictFile.fd(),
                           boost::iostreams::file_descriptor_flags::
                               never_close_handle);
                std::istream in(&buffer);
                iter->second.model->load(in);
            } catch (const std::exception &e) {
                TABLE_DEBUG() << e.what();
            }
        }
    }

    return {iter->second.dict.get(), iter->second.model.get(),
            &(*iter->second.root.config)};
}

void TableIME::saveAll() {
    for (const auto &p : tables_) {
        saveDict(p.first);
    }
}

void TableIME::updateConfig(const std::string &name, const RawConfig &config) {
    auto iter = tables_.find(name);
    if (iter == tables_.end()) {
        return;
    }
    iter->second.root.config.mutableValue()->load(config, true);

    if (iter->second.dict) {
        populateOptions(iter->second.dict.get(), iter->second.root);
    }
    safeSaveAsIni(iter->second.root, StandardPath::Type::PkgData,
                  stringutils::concat("inputmethod/", name, ".conf"));
}

void TableIME::releaseUnusedDict(const std::unordered_set<std::string> &names) {
    for (auto iter = tables_.begin(); iter != tables_.end();) {
        if (names.count(iter->first) == 0) {
            TABLE_DEBUG() << "Release unused table: " << iter->first;
            saveDict(iter->first);
            iter = tables_.erase(iter);
        } else {
            ++iter;
        }
    }
}

void TableIME::saveDict(const std::string &name) {
    auto iter = tables_.find(name);
    if (iter == tables_.end()) {
        return;
    }
    libime::TableBasedDictionary *dict = iter->second.dict.get();
    libime::UserLanguageModel *lm = iter->second.model.get();
    if (!dict || !lm || !*iter->second.root.config->learning) {
        return;
    }
    auto fileName = stringutils::joinPath("table", name);

    StandardPath::global().safeSave(
        StandardPath::Type::PkgData, fileName + ".user.dict", [dict](int fd) {
            boost::iostreams::stream_buffer<
                boost::iostreams::file_descriptor_sink>
                buffer(fd, boost::iostreams::file_descriptor_flags::
                               never_close_handle);
            std::ostream out(&buffer);
            try {
                dict->saveUser(out);
                return static_cast<bool>(out);
            } catch (const std::exception &) {
                return false;
            }
        });

    StandardPath::global().safeSave(
        StandardPath::Type::PkgData, fileName + ".history", [lm](int fd) {
            boost::iostreams::stream_buffer<
                boost::iostreams::file_descriptor_sink>
                buffer(fd, boost::iostreams::file_descriptor_flags::
                               never_close_handle);
            std::ostream out(&buffer);
            try {
                lm->save(out);
                return static_cast<bool>(out);
            } catch (const std::exception &) {
                return false;
            }
        });
}
} // namespace fcitx
<|endoftext|>


<commit_before>#include "SliceRenderer.h"

#include "GLBlaat/GL.h"
#include "GLBlaat/GLFramebuffer.h"
#include "GLBlaat/GLTextureManager.h"

#include "View.h"

#include "Renderables/Renderable.h"
#include "Renderables/VBOMesh.h"

namespace NQVTK
{
	// ------------------------------------------------------------------------
	SliceRenderer::SliceRenderer()
		: shader(0)
	{
	}

	// ------------------------------------------------------------------------
	SliceRenderer::~SliceRenderer()
	{
	}

	// ------------------------------------------------------------------------
	void SliceRenderer::PrepareForRenderable(int objectId,
		Renderable *renderable)
	{
		if (shader)
		{
			if (shaderAttribs.size() > 0)
			{
				NQVTK::VBOMesh *mesh = dynamic_cast<NQVTK::VBOMesh*>(renderable);
				if (mesh) mesh->SetupAttributes(shaderAttribs);
			}
			renderable->ApplyParamSets(shader, tm);
		}
	}

	// ------------------------------------------------------------------------
	void SliceRenderer::Draw()
	{
		// Prepare for rendering
		if (fboTarget)
		{
			fboTarget->Bind();
		}
		glViewport(viewportX, viewportY, viewportWidth, viewportHeight);

		// TODO: per-object textures are not initialized before SetupProgram
		// This doesn't matter in layered rendering because the scribe doesn't
		// use them, but will add them to the tm. However, here we don't have
		// such an extra pass...
		if (shader) shader->Start();
		for (unsigned int objectId = 0;
			objectId < view->GetNumberOfRenderables();
			++objectId)
		{
			Renderable *renderable = view->GetRenderable(objectId);
			PrepareForRenderable(objectId, renderable);
		}
		if (shader) shader->Stop();

		glPushAttrib(GL_ALL_ATTRIB_BITS);
		glDisable(GL_LIGHTING);

		// Use alpha blending for now (with premultiplied alpha)
		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);

		Clear();

		if (view)
		{
			if (shader)
			{
				shader->Start();
				tm->SetupProgram(shader);
				tm->Bind();
			}

			// Draw a single slice for each renderable
			for (unsigned int objectId = 0;
				objectId < view->GetNumberOfRenderables();
				++objectId)
			{
				// The shader should discard renderables without volumes and
				// generate appropriate alpha values or discards for blending

				// Visibility implies that the renderable is not null
				if (view->GetVisibility(objectId))
				{
					Renderable *renderable = view->GetRenderable(objectId);
					PrepareForRenderable(objectId, renderable);

					glColor4d(
						renderable->color.x,
						renderable->color.y,
						renderable->color.z,
						renderable->opacity);

					// Draw the full screen quad for our slice plane
					glBegin(GL_QUADS);
					glTexCoord3dv(origin.V);
					glVertex3d(-1.0, -1.0, 0.0);
					glTexCoord3dv((origin + right).V);
					glVertex3d(1.0, -1.0, 0.0);
					glTexCoord3dv((origin + right + up).V);
					glVertex3d(1.0, 1.0, 0.0);
					glTexCoord3dv((origin + up).V);
					glVertex3d(-1.0, 1.0, 0.0);
					glEnd();
				}
			}

			if (shader)
			{
				tm->Unbind();
				shader->Stop();
			}
		}

		glPopAttrib();

		if (fboTarget)
		{
			fboTarget->Unbind();
		}
	}

	// ------------------------------------------------------------------------
	void SliceRenderer::SetPlane(const Vector3 &origin,
		const Vector3 &right, const Vector3 &up)
	{
		this->origin = origin;
		this->right = right;
		this->up = up;
	}

	// ------------------------------------------------------------------------
	GLProgram *SliceRenderer::SetShader(GLProgram *shader)
	{
		GLProgram *oldshader = this->shader;
		this->shader = shader;
		shaderAttribs.clear();
		if (shader) shaderAttribs = shader->GetActiveAttributes();
		if (shader == oldshader) return 0;
		return oldshader;
	}

	// ------------------------------------------------------------------------
	bool SliceRenderer::CreateDefaultShader()
	{
		GLProgram *shader = GLProgram::New();
		if (!shader) return false;
		bool ok = true;
		if (ok) ok = shader->AddVertexShader(
			"void main() {"
			"   gl_TexCoord[0] = gl_MultiTexCoord0;"
			"   gl_Position = gl_Vertex;"
			"}");
		// TODO: we need the actual object transform here
		if (ok) ok = shader->AddFragmentShader(
			"uniform sampler3D volume;"
			"uniform vec3 volumeOrigin;"
			"uniform vec3 volumeSize;"
			"uniform float volumeDataShift;"
			"uniform float volumeDataScale;"
			"void main() {"
			"   vec3 tc = (gl_TexCoord[0].xyz - volumeOrigin) / volumeSize;"
			"   vec3 tex = vec3(volumeDataShift) + volumeDataScale * "
			"      texture3D(volume, tc).xyz;"
			"   gl_FragColor = vec4(abs(tex), 1.0);"
			"}");
		if (ok) ok = shader->Link();
		if (ok) SetShader(shader);
		if (!ok) delete shader;
		return ok;
	}
}
<commit_msg>Fixed blending.<commit_after>#include "SliceRenderer.h"

#include "GLBlaat/GL.h"
#include "GLBlaat/GLFramebuffer.h"
#include "GLBlaat/GLTextureManager.h"

#include "View.h"

#include "Renderables/Renderable.h"
#include "Renderables/VBOMesh.h"

namespace NQVTK
{
	// ------------------------------------------------------------------------
	SliceRenderer::SliceRenderer()
		: shader(0)
	{
	}

	// ------------------------------------------------------------------------
	SliceRenderer::~SliceRenderer()
	{
	}

	// ------------------------------------------------------------------------
	void SliceRenderer::PrepareForRenderable(int objectId,
		Renderable *renderable)
	{
		if (shader)
		{
			shader->SetUniform1i("objectId", objectId);
			if (shaderAttribs.size() > 0)
			{
				NQVTK::VBOMesh *mesh = dynamic_cast<NQVTK::VBOMesh*>(renderable);
				if (mesh) mesh->SetupAttributes(shaderAttribs);
			}
			renderable->ApplyParamSets(shader, tm);
		}
	}

	// ------------------------------------------------------------------------
	void SliceRenderer::Draw()
	{
		// Prepare for rendering
		if (fboTarget)
		{
			fboTarget->Bind();
		}
		glViewport(viewportX, viewportY, viewportWidth, viewportHeight);

		// TODO: per-object textures are not initialized before SetupProgram
		// This doesn't matter in layered rendering because the scribe doesn't
		// use them, but will add them to the tm. However, here we don't have
		// such an extra pass...
		if (shader) shader->Start();
		for (unsigned int objectId = 0;
			objectId < view->GetNumberOfRenderables();
			++objectId)
		{
			Renderable *renderable = view->GetRenderable(objectId);
			PrepareForRenderable(objectId, renderable);
		}
		if (shader) shader->Stop();

		glPushAttrib(GL_ALL_ATTRIB_BITS);
		glDisable(GL_LIGHTING);
		glDepthMask(GL_FALSE);

		// Use alpha blending for now (with premultiplied alpha)
		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);

		Clear();

		if (view)
		{
			if (shader)
			{
				shader->Start();
				tm->SetupProgram(shader);
				tm->Bind();
			}

			// Draw a single slice for each renderable
			for (unsigned int objectId = 0;
				objectId < view->GetNumberOfRenderables();
				++objectId)
			{
				// The shader should discard renderables without volumes and
				// generate appropriate alpha values or discards for blending

				// Visibility implies that the renderable is not null
				if (view->GetVisibility(objectId))
				{
					Renderable *renderable = view->GetRenderable(objectId);
					PrepareForRenderable(objectId, renderable);

					glColor4d(
						renderable->color.x,
						renderable->color.y,
						renderable->color.z,
						renderable->opacity);

					// Draw the full screen quad for our slice plane
					glBegin(GL_QUADS);
					glTexCoord3dv(origin.V);
					glVertex3d(-1.0, -1.0, 0.0);
					glTexCoord3dv((origin + right).V);
					glVertex3d(1.0, -1.0, 0.0);
					glTexCoord3dv((origin + right + up).V);
					glVertex3d(1.0, 1.0, 0.0);
					glTexCoord3dv((origin + up).V);
					glVertex3d(-1.0, 1.0, 0.0);
					glEnd();
				}
			}

			if (shader)
			{
				tm->Unbind();
				shader->Stop();
			}
		}

		glPopAttrib();

		if (fboTarget)
		{
			fboTarget->Unbind();
		}
	}

	// ------------------------------------------------------------------------
	void SliceRenderer::SetPlane(const Vector3 &origin,
		const Vector3 &right, const Vector3 &up)
	{
		this->origin = origin;
		this->right = right;
		this->up = up;
	}

	// ------------------------------------------------------------------------
	GLProgram *SliceRenderer::SetShader(GLProgram *shader)
	{
		GLProgram *oldshader = this->shader;
		this->shader = shader;
		shaderAttribs.clear();
		if (shader) shaderAttribs = shader->GetActiveAttributes();
		if (shader == oldshader) return 0;
		return oldshader;
	}

	// ------------------------------------------------------------------------
	bool SliceRenderer::CreateDefaultShader()
	{
		GLProgram *shader = GLProgram::New();
		if (!shader) return false;
		bool ok = true;
		if (ok) ok = shader->AddVertexShader(
			"void main() {"
			"   gl_TexCoord[0] = gl_MultiTexCoord0;"
			"   gl_Position = gl_Vertex;"
			"}");
		// TODO: we need the actual object transform here
		if (ok) ok = shader->AddFragmentShader(
			"uniform sampler3D volume;"
			"uniform vec3 volumeOrigin;"
			"uniform vec3 volumeSize;"
			"uniform float volumeDataShift;"
			"uniform float volumeDataScale;"
			"uniform int objectId;"
			"void main() {"
			"   vec3 tc = (gl_TexCoord[0].xyz - volumeOrigin) / volumeSize;"
			"   if (objectId == 1) tc.z = 1.0-tc.z;"
			"   vec3 tex = vec3(volumeDataShift) + volumeDataScale * "
			"      texture3D(volume, tc).xyz;"
			"   vec4 color = vec4(abs(tex), length(tex));"
			"   gl_FragColor = vec4(color.rgb * color.a, color.a);"
			"}");
		if (ok) ok = shader->Link();
		if (ok) SetShader(shader);
		if (!ok) delete shader;
		return ok;
	}
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkImageStack.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkImageStack.h"
#include "vtkImageSliceCollection.h"
#include "vtkImageProperty.h"
#include "vtkImageMapper3D.h"
#include "vtkMatrix4x4.h"
#include "vtkAssemblyPath.h"
#include "vtkAssemblyPaths.h"
#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkImageStack);

//----------------------------------------------------------------------------
vtkImageStack::vtkImageStack()
{
  this->Images = vtkImageSliceCollection::New();
  this->ImageMatrices = NULL;
  this->ActiveLayer = 0;
}

//----------------------------------------------------------------------------
vtkImageStack::~vtkImageStack()
{
  if (this->Images)
    {
    vtkCollectionSimpleIterator pit;
    this->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->RemoveConsumer(this);
      }

    this->Images->Delete();
    }

  if (this->ImageMatrices)
    {
    this->ImageMatrices->Delete();
    }
}

//----------------------------------------------------------------------------
vtkImageSlice *vtkImageStack::GetActiveImage()
{
  vtkImageSlice *activeImage = 0;

  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    vtkImageProperty *p = image->GetProperty();
    if (p->GetLayerNumber() == this->ActiveLayer)
      {
      activeImage = image;
      }
    }

  return activeImage;
}

//----------------------------------------------------------------------------
void vtkImageStack::AddImage(vtkImageSlice *prop)
{
  if (!this->Images->IsItemPresent(prop) &&
      !vtkImageStack::SafeDownCast(prop))
    {
    this->Images->AddItem(prop);
    prop->AddConsumer(this);
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::RemoveImage(vtkImageSlice *prop)
{
  if (this->Images->IsItemPresent(prop))
    {
    prop->RemoveConsumer(this);
    this->Images->RemoveItem(prop);
    }
}

//----------------------------------------------------------------------------
int vtkImageStack::HasImage(vtkImageSlice *prop)
{
  return this->Images->IsItemPresent(prop);
}

//----------------------------------------------------------------------------
void vtkImageStack::GetImages(vtkPropCollection *vc)
{
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    image->GetImages(vc);
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::ShallowCopy(vtkProp *prop)
{
  vtkImageStack *v = vtkImageStack::SafeDownCast(prop);

  if (v != NULL)
    {
    this->Images->RemoveAllItems();
    vtkCollectionSimpleIterator pit;
    v->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = v->Images->GetNextImage(pit)) != 0)
      {
      this->Images->AddItem(image);
      }
    this->SetActiveLayer(v->GetActiveLayer());
    }

  // Now do prop superclass (NOT vtkImageSlice)
  this->vtkProp3D::ShallowCopy(prop);
}

//----------------------------------------------------------------------------
void vtkImageStack::SetProperty(vtkImageProperty *)
{
  // do nothing
}

//----------------------------------------------------------------------------
vtkImageProperty *vtkImageStack::GetProperty()
{
  // Get the property with the active layer number
  vtkImageSlice *image = this->GetActiveImage();
  if (image)
    {
    return image->GetProperty();
    }

  // Return a dummy property, can't return NULL.
  if (this->Property == 0)
    {
    this->Property = vtkImageProperty::New();
    this->Property->Register(this);
    this->Property->Delete();
    }
  return this->Property;
}

//----------------------------------------------------------------------------
void vtkImageStack::SetMapper(vtkImageMapper3D *)
{
  // do nothing
}

//----------------------------------------------------------------------------
vtkImageMapper3D *vtkImageStack::GetMapper()
{
  // Get the mapper with the active layer number
  vtkImageSlice *image = this->GetActiveImage();
  if (image)
    {
    return image->GetMapper();
    }

  return NULL;
}

//----------------------------------------------------------------------------
double *vtkImageStack::GetBounds()
{
  this->UpdatePaths();

  double bounds[6];
  bool nobounds = true;

  bounds[0] = VTK_DOUBLE_MAX;
  bounds[1] = VTK_DOUBLE_MIN;
  bounds[2] = VTK_DOUBLE_MAX;
  bounds[3] = VTK_DOUBLE_MIN;
  bounds[4] = VTK_DOUBLE_MAX;
  bounds[5] = VTK_DOUBLE_MIN;

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    double *b = image->GetBounds();
    if (b)
      {
      nobounds = false;
      bounds[0] = (bounds[0] < b[0] ? bounds[0] : b[0]);
      bounds[1] = (bounds[1] > b[1] ? bounds[1] : b[1]);
      bounds[2] = (bounds[2] < b[2] ? bounds[2] : b[2]);
      bounds[3] = (bounds[3] > b[3] ? bounds[3] : b[3]);
      bounds[4] = (bounds[4] < b[4] ? bounds[4] : b[4]);
      bounds[5] = (bounds[5] > b[5] ? bounds[5] : b[5]);
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  if (nobounds)
    {
    return 0;
    }

  this->Bounds[0] = bounds[0];
  this->Bounds[1] = bounds[1];
  this->Bounds[2] = bounds[2];
  this->Bounds[3] = bounds[3];
  this->Bounds[4] = bounds[4];
  this->Bounds[5] = bounds[5];

  return this->Bounds;
}

//----------------------------------------------------------------------------
// Does this prop have some translucent polygonal geometry?
int vtkImageStack::HasTranslucentPolygonalGeometry()
{
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    if (image->HasTranslucentPolygonalGeometry())
      {
      return 1;
      }
    }

  return 0;
}

//----------------------------------------------------------------------------
// Assembly-like behavior
void vtkImageStack::PokeMatrices(vtkMatrix4x4 *matrix)
{
  if (this->ImageMatrices == NULL)
    {
    this->ImageMatrices = vtkCollection::New();
    }

  if (matrix)
    {
    vtkCollectionSimpleIterator pit;
    this->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      vtkMatrix4x4 *propMatrix = vtkMatrix4x4::New();
      propMatrix->Multiply4x4(image->GetMatrix(), matrix, propMatrix);
      image->PokeMatrix(propMatrix);
      this->ImageMatrices->AddItem(propMatrix);
      propMatrix->Delete();
      }
    }
  else
    {
    vtkCollectionSimpleIterator pit;
    this->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->PokeMatrix(NULL);
      }
    this->ImageMatrices->RemoveAllItems();
    }
}

//----------------------------------------------------------------------------
int vtkImageStack::RenderOpaqueGeometry(vtkViewport* viewport)
{
  vtkDebugMacro(<< "vtkImageStack::RenderOpaqueGeometry");

  // Opaque render is always called first, so sort here
  this->Images->Sort();
  this->UpdatePaths();

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  int rendered = 0;
  vtkImageSlice *image = 0;
  vtkCollectionSimpleIterator pit;
  vtkIdType n = this->Images->GetNumberOfItems();
  double renderTime = this->AllocatedRenderTime/(n + (n == 0));

  if (n == 1)
    {
    // no multi-pass if only one image
    this->Images->InitTraversal(pit);
    image = this->Images->GetNextImage(pit);
    image->SetAllocatedRenderTime(renderTime, viewport);
    return image->RenderOpaqueGeometry(viewport);
    }

  for (int pass = 0; pass < 3; pass++)
    {
    this->Images->InitTraversal(pit);
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->SetAllocatedRenderTime(renderTime, viewport);
      image->SetStackedImagePass(pass);
      rendered |= image->RenderOpaqueGeometry(viewport);
      image->SetStackedImagePass(-1);
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  return rendered;
}

//----------------------------------------------------------------------------
int vtkImageStack::RenderTranslucentPolygonalGeometry(vtkViewport* viewport)
{
  vtkDebugMacro(<< "vtkImageStack::RenderTranslucentPolygonalGeometry");

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  int rendered = 0;
  vtkImageSlice *image = 0;
  vtkCollectionSimpleIterator pit;
  vtkIdType n = this->Images->GetNumberOfItems();
  double renderTime = this->AllocatedRenderTime/(n + (n == 0));

  if (n == 1)
    {
    // no multi-pass if only one image
    this->Images->InitTraversal(pit);
    image = this->Images->GetNextImage(pit);
    image->SetAllocatedRenderTime(renderTime, viewport);
    return image->RenderTranslucentPolygonalGeometry(viewport);
    }

  for (int pass = 1; pass < 3; pass++)
    {
    this->Images->InitTraversal(pit);
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->SetAllocatedRenderTime(renderTime, viewport);
      image->SetStackedImagePass(pass);
      rendered |= image->RenderTranslucentPolygonalGeometry(viewport);
      image->SetStackedImagePass(-1);
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  return rendered;
}

//----------------------------------------------------------------------------
int vtkImageStack::RenderOverlay(vtkViewport* viewport)
{
  vtkDebugMacro(<< "vtkImageStack::RenderOverlay");

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  int rendered = 0;
  vtkImageSlice *image = 0;
  vtkCollectionSimpleIterator pit;
  vtkIdType n = this->Images->GetNumberOfItems();
  double renderTime = this->AllocatedRenderTime/(n + (n == 0));

  if (n == 1)
    {
    // no multi-pass if only one image
    this->Images->InitTraversal(pit);
    image = this->Images->GetNextImage(pit);
    image->SetAllocatedRenderTime(renderTime, viewport);
    return image->RenderOverlay(viewport);
    }

  for (int pass = 1; pass < 3; pass++)
    {
    this->Images->InitTraversal(pit);
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->SetAllocatedRenderTime(renderTime, viewport);
      image->SetStackedImagePass(pass);
      rendered |= image->RenderOverlay(viewport);
      image->SetStackedImagePass(-1);
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  return rendered;
}

//----------------------------------------------------------------------------
void vtkImageStack::ReleaseGraphicsResources(vtkWindow *win)
{
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    image->ReleaseGraphicsResources(win);
    }
}

//----------------------------------------------------------------------------
unsigned long int vtkImageStack::GetMTime()
{
  unsigned long mTime = this->Superclass::GetMTime();
  unsigned long t;

  // Get the max mtime of all the images
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    t = image->GetMTime();
    mTime = (t < mTime ? mTime : t);
    }

  return mTime;
}

//----------------------------------------------------------------------------
unsigned long int vtkImageStack::GetRedrawMTime()
{
  // Just call GetMTime on ourselves, not GetRedrawMTime
  unsigned long mTime = this->Superclass::GetMTime();
  unsigned long t;

  // Get the max mtime of all the images
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    t = image->GetRedrawMTime();
    mTime = (t < mTime ? mTime : t);
    }

  return mTime;
}

//----------------------------------------------------------------------------
void vtkImageStack::InitPathTraversal()
{
  this->UpdatePaths();
  this->Paths->InitTraversal();
}

//----------------------------------------------------------------------------
vtkAssemblyPath *vtkImageStack::GetNextPath()
{
  if (this->Paths)
    {
    return this->Paths->GetNextItem();
    }
  return NULL;
}

//----------------------------------------------------------------------------
int vtkImageStack::GetNumberOfPaths()
{
  this->UpdatePaths();
  return this->Paths->GetNumberOfItems();
}

//----------------------------------------------------------------------------
void vtkImageStack::UpdatePaths()
{
  if (this->GetMTime() > this->PathTime ||
      (this->Paths && this->Paths->GetMTime() > this->PathTime))
    {
    if (this->Paths)
      {
      this->Paths->Delete();
      }

    // Create the list to hold all the paths
    this->Paths = vtkAssemblyPaths::New();
    vtkAssemblyPath *path = vtkAssemblyPath::New();

    // Add ourselves to the path to start things off
    path->AddNode(this, this->GetMatrix());

    // Add the active image
    vtkImageSlice *image = this->GetActiveImage();

    if (image)
      {
      path->AddNode(image, image->GetMatrix());
      image->BuildPaths(this->Paths, path);
      path->DeleteLastNode();
      }

    path->Delete();
    this->PathTime.Modified();
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path)
{
  // the path consists only of the active image
  vtkImageSlice *image = this->GetActiveImage();

  if (image)
    {
    path->AddNode(image, image->GetMatrix());
    image->BuildPaths(paths, path);
    path->DeleteLastNode();
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Images: " << this->Images << "\n";
  os << indent << "ActiveLayer: " << this->ActiveLayer << "\n";
  os << indent << "ActiveImage: " << this->GetActiveImage() << "\n";
}
<commit_msg>BUG: Visibility was ignored for images in vtkImageStack.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageStack.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkImageStack.h"
#include "vtkImageSliceCollection.h"
#include "vtkImageProperty.h"
#include "vtkImageMapper3D.h"
#include "vtkMatrix4x4.h"
#include "vtkAssemblyPath.h"
#include "vtkAssemblyPaths.h"
#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkImageStack);

//----------------------------------------------------------------------------
vtkImageStack::vtkImageStack()
{
  this->Images = vtkImageSliceCollection::New();
  this->ImageMatrices = NULL;
  this->ActiveLayer = 0;
}

//----------------------------------------------------------------------------
vtkImageStack::~vtkImageStack()
{
  if (this->Images)
    {
    vtkCollectionSimpleIterator pit;
    this->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->RemoveConsumer(this);
      }

    this->Images->Delete();
    }

  if (this->ImageMatrices)
    {
    this->ImageMatrices->Delete();
    }
}

//----------------------------------------------------------------------------
vtkImageSlice *vtkImageStack::GetActiveImage()
{
  vtkImageSlice *activeImage = 0;

  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    vtkImageProperty *p = image->GetProperty();
    if (p->GetLayerNumber() == this->ActiveLayer)
      {
      activeImage = image;
      }
    }

  return activeImage;
}

//----------------------------------------------------------------------------
void vtkImageStack::AddImage(vtkImageSlice *prop)
{
  if (!this->Images->IsItemPresent(prop) &&
      !vtkImageStack::SafeDownCast(prop))
    {
    this->Images->AddItem(prop);
    prop->AddConsumer(this);
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::RemoveImage(vtkImageSlice *prop)
{
  if (this->Images->IsItemPresent(prop))
    {
    prop->RemoveConsumer(this);
    this->Images->RemoveItem(prop);
    }
}

//----------------------------------------------------------------------------
int vtkImageStack::HasImage(vtkImageSlice *prop)
{
  return this->Images->IsItemPresent(prop);
}

//----------------------------------------------------------------------------
void vtkImageStack::GetImages(vtkPropCollection *vc)
{
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    image->GetImages(vc);
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::ShallowCopy(vtkProp *prop)
{
  vtkImageStack *v = vtkImageStack::SafeDownCast(prop);

  if (v != NULL)
    {
    this->Images->RemoveAllItems();
    vtkCollectionSimpleIterator pit;
    v->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = v->Images->GetNextImage(pit)) != 0)
      {
      this->Images->AddItem(image);
      }
    this->SetActiveLayer(v->GetActiveLayer());
    }

  // Now do prop superclass (NOT vtkImageSlice)
  this->vtkProp3D::ShallowCopy(prop);
}

//----------------------------------------------------------------------------
void vtkImageStack::SetProperty(vtkImageProperty *)
{
  // do nothing
}

//----------------------------------------------------------------------------
vtkImageProperty *vtkImageStack::GetProperty()
{
  // Get the property with the active layer number
  vtkImageSlice *image = this->GetActiveImage();
  if (image)
    {
    return image->GetProperty();
    }

  // Return a dummy property, can't return NULL.
  if (this->Property == 0)
    {
    this->Property = vtkImageProperty::New();
    this->Property->Register(this);
    this->Property->Delete();
    }
  return this->Property;
}

//----------------------------------------------------------------------------
void vtkImageStack::SetMapper(vtkImageMapper3D *)
{
  // do nothing
}

//----------------------------------------------------------------------------
vtkImageMapper3D *vtkImageStack::GetMapper()
{
  // Get the mapper with the active layer number
  vtkImageSlice *image = this->GetActiveImage();
  if (image)
    {
    return image->GetMapper();
    }

  return NULL;
}

//----------------------------------------------------------------------------
double *vtkImageStack::GetBounds()
{
  this->UpdatePaths();

  double bounds[6];
  bool nobounds = true;

  bounds[0] = VTK_DOUBLE_MAX;
  bounds[1] = VTK_DOUBLE_MIN;
  bounds[2] = VTK_DOUBLE_MAX;
  bounds[3] = VTK_DOUBLE_MIN;
  bounds[4] = VTK_DOUBLE_MAX;
  bounds[5] = VTK_DOUBLE_MIN;

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    double *b = image->GetBounds();
    if (b)
      {
      nobounds = false;
      bounds[0] = (bounds[0] < b[0] ? bounds[0] : b[0]);
      bounds[1] = (bounds[1] > b[1] ? bounds[1] : b[1]);
      bounds[2] = (bounds[2] < b[2] ? bounds[2] : b[2]);
      bounds[3] = (bounds[3] > b[3] ? bounds[3] : b[3]);
      bounds[4] = (bounds[4] < b[4] ? bounds[4] : b[4]);
      bounds[5] = (bounds[5] > b[5] ? bounds[5] : b[5]);
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  if (nobounds)
    {
    return 0;
    }

  this->Bounds[0] = bounds[0];
  this->Bounds[1] = bounds[1];
  this->Bounds[2] = bounds[2];
  this->Bounds[3] = bounds[3];
  this->Bounds[4] = bounds[4];
  this->Bounds[5] = bounds[5];

  return this->Bounds;
}

//----------------------------------------------------------------------------
// Does this prop have some translucent polygonal geometry?
int vtkImageStack::HasTranslucentPolygonalGeometry()
{
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    if (image->HasTranslucentPolygonalGeometry())
      {
      return 1;
      }
    }

  return 0;
}

//----------------------------------------------------------------------------
// Assembly-like behavior
void vtkImageStack::PokeMatrices(vtkMatrix4x4 *matrix)
{
  if (this->ImageMatrices == NULL)
    {
    this->ImageMatrices = vtkCollection::New();
    }

  if (matrix)
    {
    vtkCollectionSimpleIterator pit;
    this->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      vtkMatrix4x4 *propMatrix = vtkMatrix4x4::New();
      propMatrix->Multiply4x4(image->GetMatrix(), matrix, propMatrix);
      image->PokeMatrix(propMatrix);
      this->ImageMatrices->AddItem(propMatrix);
      propMatrix->Delete();
      }
    }
  else
    {
    vtkCollectionSimpleIterator pit;
    this->Images->InitTraversal(pit);
    vtkImageSlice *image = 0;
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      image->PokeMatrix(NULL);
      }
    this->ImageMatrices->RemoveAllItems();
    }
}

//----------------------------------------------------------------------------
int vtkImageStack::RenderOpaqueGeometry(vtkViewport* viewport)
{
  vtkDebugMacro(<< "vtkImageStack::RenderOpaqueGeometry");

  // Opaque render is always called first, so sort here
  this->Images->Sort();
  this->UpdatePaths();

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  int rendered = 0;
  vtkImageSlice *image = 0;
  vtkCollectionSimpleIterator pit;
  vtkIdType n = 0;
  this->Images->InitTraversal(pit);
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    n += (image->GetVisibility() != 0);
    }
  double renderTime = this->AllocatedRenderTime/(n + (n == 0));

  if (n == 1)
    {
    // no multi-pass if only one image
    this->Images->InitTraversal(pit);
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      if (image->GetVisibility())
        {
        image->SetAllocatedRenderTime(renderTime, viewport);
        rendered = image->RenderOpaqueGeometry(viewport);
        }
      }
    }
  else
    {
    for (int pass = 0; pass < 3; pass++)
      {
      this->Images->InitTraversal(pit);
      while ( (image = this->Images->GetNextImage(pit)) != 0)
        {
        if (image->GetVisibility())
          {
          image->SetAllocatedRenderTime(renderTime, viewport);
          image->SetStackedImagePass(pass);
          rendered |= image->RenderOpaqueGeometry(viewport);
          image->SetStackedImagePass(-1);
          }
        }
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  return rendered;
}

//----------------------------------------------------------------------------
int vtkImageStack::RenderTranslucentPolygonalGeometry(vtkViewport* viewport)
{
  vtkDebugMacro(<< "vtkImageStack::RenderTranslucentPolygonalGeometry");

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  int rendered = 0;
  vtkImageSlice *image = 0;
  vtkCollectionSimpleIterator pit;
  vtkIdType n = 0;
  this->Images->InitTraversal(pit);
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    n += (image->GetVisibility() != 0);
    }
  double renderTime = this->AllocatedRenderTime/(n + (n == 0));

  if (n == 1)
    {
    // no multi-pass if only one image
    this->Images->InitTraversal(pit);
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      if (image->GetVisibility())
        {
        image->SetAllocatedRenderTime(renderTime, viewport);
        rendered = image->RenderTranslucentPolygonalGeometry(viewport);
        }
      }
    }
  else
    {
    for (int pass = 1; pass < 3; pass++)
      {
      this->Images->InitTraversal(pit);
      while ( (image = this->Images->GetNextImage(pit)) != 0)
        {
        if (image->GetVisibility())
          {
          image->SetAllocatedRenderTime(renderTime, viewport);
          image->SetStackedImagePass(pass);
          rendered |= image->RenderTranslucentPolygonalGeometry(viewport);
          image->SetStackedImagePass(-1);
          }
        }
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  return rendered;
}

//----------------------------------------------------------------------------
int vtkImageStack::RenderOverlay(vtkViewport* viewport)
{
  vtkDebugMacro(<< "vtkImageStack::RenderOverlay");

  if (!this->IsIdentity)
    {
    this->PokeMatrices(this->GetMatrix());
    }

  int rendered = 0;
  vtkImageSlice *image = 0;
  vtkCollectionSimpleIterator pit;
  vtkIdType n = 0;
  this->Images->InitTraversal(pit);
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    n += (image->GetVisibility() != 0);
    }
  double renderTime = this->AllocatedRenderTime/(n + (n == 0));

  if (n == 1)
    {
    // no multi-pass if only one image
    this->Images->InitTraversal(pit);
    while ( (image = this->Images->GetNextImage(pit)) != 0)
      {
      if (image->GetVisibility())
        {
        image->SetAllocatedRenderTime(renderTime, viewport);
        rendered = image->RenderOverlay(viewport);
        }
      }
    }
  else
    {
    for (int pass = 1; pass < 3; pass++)
      {
      this->Images->InitTraversal(pit);
      while ( (image = this->Images->GetNextImage(pit)) != 0)
        {
        if (image->GetVisibility())
          {
          image->SetAllocatedRenderTime(renderTime, viewport);
          image->SetStackedImagePass(pass);
          rendered |= image->RenderOverlay(viewport);
          image->SetStackedImagePass(-1);
          }
        }
      }
    }

  if (!this->IsIdentity)
    {
    this->PokeMatrices(NULL);
    }

  return rendered;
}

//----------------------------------------------------------------------------
void vtkImageStack::ReleaseGraphicsResources(vtkWindow *win)
{
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    image->ReleaseGraphicsResources(win);
    }
}

//----------------------------------------------------------------------------
unsigned long int vtkImageStack::GetMTime()
{
  unsigned long mTime = this->Superclass::GetMTime();
  unsigned long t;

  // Get the max mtime of all the images
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    t = image->GetMTime();
    mTime = (t < mTime ? mTime : t);
    }

  return mTime;
}

//----------------------------------------------------------------------------
unsigned long int vtkImageStack::GetRedrawMTime()
{
  // Just call GetMTime on ourselves, not GetRedrawMTime
  unsigned long mTime = this->Superclass::GetMTime();
  unsigned long t;

  // Get the max mtime of all the images
  vtkCollectionSimpleIterator pit;
  this->Images->InitTraversal(pit);
  vtkImageSlice *image = 0;
  while ( (image = this->Images->GetNextImage(pit)) != 0)
    {
    t = image->GetRedrawMTime();
    mTime = (t < mTime ? mTime : t);
    }

  return mTime;
}

//----------------------------------------------------------------------------
void vtkImageStack::InitPathTraversal()
{
  this->UpdatePaths();
  this->Paths->InitTraversal();
}

//----------------------------------------------------------------------------
vtkAssemblyPath *vtkImageStack::GetNextPath()
{
  if (this->Paths)
    {
    return this->Paths->GetNextItem();
    }
  return NULL;
}

//----------------------------------------------------------------------------
int vtkImageStack::GetNumberOfPaths()
{
  this->UpdatePaths();
  return this->Paths->GetNumberOfItems();
}

//----------------------------------------------------------------------------
void vtkImageStack::UpdatePaths()
{
  if (this->GetMTime() > this->PathTime ||
      (this->Paths && this->Paths->GetMTime() > this->PathTime))
    {
    if (this->Paths)
      {
      this->Paths->Delete();
      }

    // Create the list to hold all the paths
    this->Paths = vtkAssemblyPaths::New();
    vtkAssemblyPath *path = vtkAssemblyPath::New();

    // Add ourselves to the path to start things off
    path->AddNode(this, this->GetMatrix());

    // Add the active image
    vtkImageSlice *image = this->GetActiveImage();

    if (image)
      {
      path->AddNode(image, image->GetMatrix());
      image->BuildPaths(this->Paths, path);
      path->DeleteLastNode();
      }

    path->Delete();
    this->PathTime.Modified();
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path)
{
  // the path consists only of the active image
  vtkImageSlice *image = this->GetActiveImage();

  if (image)
    {
    path->AddNode(image, image->GetMatrix());
    image->BuildPaths(paths, path);
    path->DeleteLastNode();
    }
}

//----------------------------------------------------------------------------
void vtkImageStack::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Images: " << this->Images << "\n";
  os << indent << "ActiveLayer: " << this->ActiveLayer << "\n";
  os << indent << "ActiveImage: " << this->GetActiveImage() << "\n";
}
<|endoftext|>