Explorar el Código

first release

gapchich hace 13 años
commit
c92bbda85d
Se han modificado 15 ficheros con 4372 adiciones y 0 borrados
  1. 82 0
      ImageDescriptionForm.cpp
  2. 43 0
      ImageDescriptionForm.h
  3. 532 0
      ImageHolder.cpp
  4. 125 0
      ImageHolder.h
  5. 2497 0
      ImageLabeler.cpp
  6. 226 0
      ImageLabeler.h
  7. 18 0
      ImageLabeler.pro
  8. 145 0
      Makefile
  9. 224 0
      Makefile.Debug
  10. 224 0
      Makefile.Release
  11. 79 0
      OptionsForm.cpp
  12. 45 0
      OptionsForm.h
  13. 92 0
      functions.cpp
  14. 23 0
      functions.h
  15. 17 0
      main.cpp

+ 82 - 0
ImageDescriptionForm.cpp

@@ -0,0 +1,82 @@
+/*
+ * ImageDescriptionForm.cpp
+ *
+ *  Created on: Oct 6, 2011
+ *      Author: Gapchich Vlad
+ */
+
+#include "ImageDescriptionForm.h"
+
+#include <QLineEdit>
+#include <QPushButton>
+#include <QBoxLayout>
+#include <QMessageBox>
+#include <QApplication>
+#include <QDesktopWidget>
+
+ImageDescriptionForm::ImageDescriptionForm(QWidget *aParent)
+	: QWidget(aParent)
+{
+	setWindowTitle(tr("Image Description"));
+
+	layout_v_ = new QVBoxLayout(this);
+	layout_h_ = new QHBoxLayout;
+
+	image_description_ = new QLineEdit(this);
+	button_ok_ = new QPushButton(this);
+	button_ok_->setText(tr("OK"));
+	button_cancel_ = new QPushButton(this);
+	button_cancel_->setText(tr("Cancel"));
+
+	layout_v_->addWidget(image_description_);
+	layout_v_->addLayout(layout_h_);
+
+	layout_h_->addWidget(button_ok_);
+	layout_h_->addWidget(button_cancel_);
+
+	connect(
+		button_ok_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(setDescription())
+		);
+	connect(
+		button_cancel_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(hide())
+		);
+
+	adjustSize();
+	move(QApplication::desktop()->screen()->rect().center() - rect().center());
+}
+
+ImageDescriptionForm::~ImageDescriptionForm()
+{
+	delete image_description_;
+	delete button_ok_;
+	delete button_cancel_;
+
+	delete layout_v_;
+}
+
+void
+ImageDescriptionForm::setDescription()
+{
+	if (!image_description_->text().isEmpty()) {
+		emit descriptionSet(image_description_->text());
+		hide();
+	}
+	else
+		QMessageBox::warning(
+			this,
+			tr("Warning!"),
+			tr("Image description is empty"),
+			QMessageBox::Ok,
+			QMessageBox::Cancel
+			);
+}
+
+/*
+ *
+ */

+ 43 - 0
ImageDescriptionForm.h

@@ -0,0 +1,43 @@
+/*
+ * ImageDescriptionForm.h
+ *
+ *  Created on: Oct 6, 2011
+ *      Author: Gapchich Vlad
+ */
+
+#ifndef __IMAGEDESCRIPTIONFORM_H__
+#define __IMAGEDESCRIPTIONFORM_H__
+
+#include <QWidget>
+
+class QLineEdit;
+class QPushButton;
+class QVBoxLayout;
+class QHBoxLayout;
+
+class ImageDescriptionForm : public QWidget{
+	Q_OBJECT
+public:
+	ImageDescriptionForm(QWidget *aParent = 0);
+	virtual ~ImageDescriptionForm();
+
+public slots:
+	void setDescription();
+
+signals:
+	void descriptionSet(QString aDescription);
+
+private:
+	QLineEdit *image_description_;
+	QPushButton *button_ok_;
+	QPushButton *button_cancel_;
+
+	QVBoxLayout *layout_v_;
+	QHBoxLayout *layout_h_;
+};
+
+#endif /* __IMAGEDESCRIPTIONFORM_H__ */
+
+/*
+ *
+ */

+ 532 - 0
ImageHolder.cpp

@@ -0,0 +1,532 @@
+/*
+ * ImageHolder.cpp
+ *
+ *  Created on: Oct 5, 2011
+ *      Author: gapchich
+ */
+
+#include "ImageHolder.h"
+#include "functions.h"
+
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QListWidgetItem>
+#include <QDebug>
+
+ImageHolder::ImageHolder(QWidget *aParent)
+	: QLabel(aParent)
+{
+	repaint_needed_ = 0;
+	tool_ = NoTool;
+	state_ = StandBy;
+	keyboard_modifier_ = Qt::NoModifier;
+
+	focused_selection_ = -1;
+	focused_selection_type_ = NoTool;
+
+	list_bounding_box_ = 0;
+	main_label_ = 0;
+	//list_bounding_box_ = new QList< QRect >;
+
+	scale_ = 1;
+
+	setScaledContents(true);
+}
+
+ImageHolder::~ImageHolder()
+{
+	//list_bounding_box_->clear();
+	//delete list_bounding_box_;
+}
+
+void
+ImageHolder::paintEvent(QPaintEvent *anEvent)
+{
+	QLabel::paintEvent(anEvent);
+
+	QPainter painter(this);
+	painter.setRenderHint(QPainter::Antialiasing);
+	//painter.setRenderHint(QPainter::SmoothPixmapTransform);
+	QPen pen;
+
+	if (NoTool != tool_) {
+		pen.setWidth(1);
+		pen.setColor(QColor(Qt::black));
+		pen.setStyle(Qt::DashLine);
+		painter.setPen(pen);
+		switch(tool_) {
+		case BoundingBoxTool:
+			painter.drawRect(bounding_box_.rect);
+			break;
+		case PolygonTool:
+			painter.drawPolygon(polygon_.poly);
+			break;
+		default:
+			break;
+		}
+
+	}
+
+	/* drawing bounding boxes */
+	drawBoundingBoxes(&painter, &pen);
+	drawPolygons(&painter, &pen);
+}
+
+void
+ImageHolder::drawBoundingBoxes(
+	QPainter *aPainter,
+	QPen *aPen
+)
+{
+	/* FIXME: hardcoded colors */
+	if (0 == list_bounding_box_)
+	{
+		return;
+		/* NOTREACHED */
+	}
+
+	Qt::PenStyle penStyle = Qt::SolidLine;
+	int width = 1;
+	/* confirmed boxes */
+	for (int i = 0; i < list_bounding_box_->size(); i++) {
+		int labelID = list_bounding_box_->at(i).label_ID_;
+
+		aPen->setColor(QColor(list_label_color_->at(labelID)));
+
+		/* checking whether labeled area is of main object or not */
+		if (labelID == *main_label_)
+			width = 3;
+		else
+			width = 1;
+
+		if (BoundingBoxTool == focused_selection_type_ &&
+			focused_selection_ == i) {
+			penStyle = Qt::DotLine;
+			width = 2;
+		}
+
+		aPen->setWidth(width);
+		aPen->setStyle(penStyle);
+		aPainter->setPen(*aPen);
+		aPainter->drawRect(list_bounding_box_->at(i).rect);
+		/* drawing label ids of these boxes */
+		QString labelIDText =
+			QString("%1").arg(labelID);
+		QRect rect = list_bounding_box_->at(i).rect.normalized();
+
+		aPainter->drawText(
+			rect.left() + 5,
+			rect.top() + 5,
+			20,
+			20,
+			Qt::AlignLeft,
+			labelIDText
+			);
+	}
+
+}
+
+void
+ImageHolder::drawPolygons(
+	QPainter *aPainter,
+	QPen *aPen
+)
+{
+	/* FIXME: hardcoded colors */
+	if (0 == list_polygon_)
+	{
+		return;
+		/* NOTREACHED */
+	}
+
+	Qt::PenStyle penStyle = Qt::SolidLine;
+	int width = 1;
+	/* confirmed polygons */
+	for (int i = 0; i < list_polygon_->size(); i++) {
+		penStyle = Qt::SolidLine;
+		int labelID = list_polygon_->at(i).label_ID_;
+
+		aPen->setColor(QColor(list_label_color_->at(labelID)));
+
+		/* checking whether labeled area is of main object or not */
+		if (labelID == *main_label_)
+			width = 3;
+		else
+			width = 1;
+
+		if (PolygonTool == focused_selection_type_ &&
+			focused_selection_ == i) {
+			penStyle = Qt::DotLine;
+			width = 2;
+		}
+
+
+		aPen->setWidth(width);
+		aPen->setStyle(penStyle);
+		aPainter->setPen(*aPen);
+		aPainter->drawPolygon(list_polygon_->at(i).poly);
+		/* drawing label ids of these polys */
+		QString labelIDText =
+			QString("%1").arg(labelID);
+		QRect rect = list_polygon_->at(i).poly.boundingRect();
+		int x = rect.center().x();
+		int y = rect.center().y();
+
+		aPainter->drawText(
+			x,
+			y,
+			20,
+			20,
+			Qt::AlignHCenter,
+			labelIDText
+			);
+	}
+
+}
+
+void
+ImageHolder::triggerBoundBox(
+	const QPoint &aNewPos,
+	const QPoint &anOldPos,
+	QRect *aNewRect
+	)
+{
+	aNewRect->setCoords(
+			 anOldPos.x(),
+			 anOldPos.y(),
+			 aNewPos.x(),
+			 aNewPos.y()
+	);
+
+	state_ = NewSelection;
+	repaint_needed_ = 1;
+}
+
+void
+ImageHolder::triggerPolygon(
+	const QPoint &aPoint,
+	QPolygon *aNewPoly
+	)
+{
+	*aNewPoly << aPoint;
+
+	repaint_needed_ = 1;
+}
+
+void
+ImageHolder::focusOnArea(QListWidgetItem *anItem)
+{
+	QString text = anItem->text();
+
+	Tool tool = NoTool;
+	if (-1 != text.indexOf("BBox"))
+		tool = BoundingBoxTool;
+	else if (-1 != text.indexOf("Poly"))
+		tool = PolygonTool;
+
+	/* looking for a number of selected area */
+	if (NoTool != tool) {
+		bool ok = 0;
+		focused_selection_ = getNumFromString(&text, "#", ";", &ok);
+
+		if (!ok) {
+			focused_selection_ = -1;
+			focused_selection_type_ = NoTool;
+			return;
+			/* NOTREACHED */
+		}
+
+		switch (tool) {
+		case BoundingBoxTool:
+			focused_selection_type_ = BoundingBoxTool;
+			break;
+		case PolygonTool:
+			focused_selection_type_ = PolygonTool;
+			break;
+		default:
+			focused_selection_type_ = NoTool;
+			break;
+		}
+
+	}
+	update();
+}
+
+void
+ImageHolder::scaleImage(
+	ZoomDirection aDirection,
+	double scaleFactor
+)
+{
+	QSize size = pixmap()->size();
+
+	/* zoomin */
+	if (ZoomIn == aDirection) {
+		size *= scaleFactor;
+		scale_ *= scaleFactor;
+	}
+	/* zoomout */
+	else if (ZoomOut == aDirection) {
+		size /= scaleFactor;
+		scale_ /= scaleFactor;
+	}
+
+	setPixmap(
+		pixmap()->scaled(
+			size,
+			Qt::IgnoreAspectRatio,
+			Qt::SmoothTransformation
+			)
+		);
+
+
+	//resize(scaleFactor * pixmap()->size());
+	//emit imageScaled();
+}
+
+void
+ImageHolder::clearFocusOnArea()
+{
+	focused_selection_ = -1;
+	focused_selection_type_ = NoTool;
+}
+
+void
+ImageHolder::setTool(Tool aTool)
+{
+	switch(aTool) {
+	case BoundingBoxTool:
+		tool_ = BoundingBoxTool;
+		break;
+	case PolygonTool:
+		tool_ = PolygonTool;
+		break;
+	case TaggingTool:
+		tool_ = TaggingTool;
+		break;
+	default:
+		tool_ = NoTool;
+		break;
+	}
+}
+
+void
+ImageHolder::setBoundingBoxList(QList< BoundingBox > *aBBoxList)
+{
+	if (0 == aBBoxList) {
+		return;
+		/* NOTREACHED */
+	}
+
+	list_bounding_box_ = aBBoxList;
+}
+
+void
+ImageHolder::setPolygonList(QList< Polygon > *aPolygonList)
+{
+	if (0 == aPolygonList) {
+		return;
+		/* NOTREACHED */
+	}
+
+	list_polygon_ = aPolygonList;
+}
+
+void
+ImageHolder::setLabelColorList(QList< uint > *aLabelColorList)
+{
+	if (0 == aLabelColorList) {
+		return;
+		/* NOTREACHED */
+	}
+
+	list_label_color_ = aLabelColorList;
+}
+
+void
+ImageHolder::setMainLabelNum(int *aNum)
+{
+	if (0 == aNum) {
+		return;
+		/* NOTREACHED */
+	}
+
+	main_label_ = aNum;
+}
+
+void
+ImageHolder::clearAll()
+{
+	//list_bounding_box_->clear();
+	bounding_box_.rect.setRect(-1, -1, 0, 0);
+	//list_polygon_->clear();
+	polygon_.poly.clear();
+	clearFocusOnArea();
+	state_ = StandBy;
+
+	update();
+}
+
+void
+ImageHolder::clearLast()
+{
+	switch (tool_) {
+	case BoundingBoxTool:
+		bounding_box_.rect.setRect(-1, -1, 0, 0);
+		break;
+	case PolygonTool:
+		polygon_.poly.clear();
+		break;
+	case TaggingTool:
+		break;
+	default:
+		break;
+	}
+	bounding_box_.rect.setRect(-1, -1, 0, 0);
+
+	state_ = StandBy;
+	update();
+}
+
+void
+ImageHolder::confirmSelection()
+{
+	if (NewSelection != state_ || NoTool == tool_) {
+		return;
+		/* NOTREACHED */
+	}
+
+	switch (tool_) {
+	case BoundingBoxTool:
+		list_bounding_box_->append(bounding_box_);
+		bounding_box_.rect.setRect(-1, -1, 0, 0);
+		break;
+	case PolygonTool:
+		list_polygon_->append(polygon_);
+		polygon_.poly.clear();
+		break;
+	default:
+		tool_ = NoTool;
+		break;
+	}
+
+	state_ = StandBy;
+	update();
+}
+
+ImageHolder::State
+ImageHolder::state()
+{
+	return state_;
+}
+
+ImageHolder::Tool
+ImageHolder::tool()
+{
+	return tool_;
+}
+
+void
+ImageHolder::keyPressEvent(QKeyEvent *anEvent)
+{
+	QLabel::keyPressEvent(anEvent);
+
+	//keyboard_modifier_ = anEvent->modifiers();
+
+	if (repaint_needed_) {
+		update();
+		repaint_needed_ = 0;
+	}
+}
+
+void
+ImageHolder::mouseMoveEvent(QMouseEvent *anEvent)
+{
+	QPoint pos = anEvent->pos();
+	if (anEvent->pos().x() < 0)
+		pos.setX(0);
+
+	if (width() < anEvent->pos().x())
+		pos.setX(width() - 1);
+
+	if (anEvent->pos().y() < 0)
+		pos.setY(0);
+
+
+	if (height() < anEvent->pos().y())
+		pos.setY(height() - 1);
+
+
+	if ((anEvent->buttons() & Qt::LeftButton) &&
+		BoundingBoxTool == tool_ &&
+		NewSelection == state_ &&
+		Qt::NoModifier == keyboard_modifier_)
+	{
+		triggerBoundBox(pos, prev_cursor_pos_, &(bounding_box_.rect));
+	}
+
+	if (PolygonTool == tool_ &&
+		NewSelection == state_) {
+		polygon_.poly.setPoint(polygon_.poly.count() - 1, pos);
+		repaint_needed_ = 1;
+	}
+
+	if (repaint_needed_) {
+		update();
+		repaint_needed_ = 0;
+	}
+}
+
+void
+ImageHolder::mousePressEvent(QMouseEvent *anEvent)
+{
+	/* remembering coordinates of the click */
+	if ((anEvent->buttons() & Qt::LeftButton) ||
+		(anEvent->buttons() & Qt::RightButton))
+	{
+		prev_cursor_pos_ = anEvent->pos();
+	}
+
+	if (anEvent->buttons() & Qt::LeftButton) {
+		/* clearing the selected area if it is not confirmed */
+		if (NewSelection == state_ && BoundingBoxTool == tool_) {
+			bounding_box_.rect.setRect(-1, -1, 0, 0);
+			state_ = StandBy;
+		}
+
+		/* making new points for poly */
+		if (PolygonTool == tool_ &&
+			NewSelection == state_ &&
+			Qt::NoModifier == keyboard_modifier_)
+		{
+			triggerPolygon(anEvent->pos(), &(polygon_.poly));
+		}
+
+		/* starting new selection by click */
+		if (StandBy == state_ && NoTool != tool_) {
+			state_ = NewSelection;
+			emit selectionStarted();
+
+			polygon_.poly.clear();
+			if (PolygonTool == tool_) {
+				polygon_.poly << prev_cursor_pos_;
+			}
+		}
+	}
+
+	if (repaint_needed_) {
+		update();
+		repaint_needed_ = 0;
+	}
+}
+
+void
+ImageHolder::mouseReleaseEvent(QMouseEvent *anEvent)
+{
+	Q_UNUSED(anEvent)
+}
+
+/*
+ *
+ */

+ 125 - 0
ImageHolder.h

@@ -0,0 +1,125 @@
+/*
+ * ImageHolder.h
+ *
+ *  Created on: Oct 5, 2011
+ *      Author: Gapchich Vladislav
+ */
+
+#ifndef __IMAGEHOLDER_H__
+#define __IMAGEHOLDER_H__
+
+#include <QLabel>
+
+struct BoundingBox {
+	QRect rect;
+	int label_ID_;
+};
+
+struct Polygon {
+	QPolygon poly;
+	int label_ID_;
+};
+
+enum ZoomDirection {
+	NoZoom,
+	ZoomIn,
+	ZoomOut
+};
+
+class QListWidgetItem;
+class QPixmap;
+
+class ImageHolder : public QLabel
+{
+	Q_OBJECT
+protected:
+	void keyPressEvent(QKeyEvent *anEvent);
+	void mouseMoveEvent(QMouseEvent *anEvent);
+	void mousePressEvent(QMouseEvent *anEvent);
+	void mouseReleaseEvent(QMouseEvent *anEvent);
+	void paintEvent (QPaintEvent *anEvent);
+
+	void triggerBoundBox(
+		const QPoint &aNewPos,
+		const QPoint &anOldPos,
+		QRect *aNewBox
+		);
+	void triggerPolygon(
+		const QPoint &aPoint,
+		QPolygon *aNewPoly
+		);
+	void drawBoundingBoxes(
+		QPainter *aPainter,
+		QPen *aPen
+		);
+	void drawPolygons(
+		QPainter *aPainter,
+		QPen *aPen
+		);
+
+	void scaleImage(ZoomDirection aDirection, double scaleFactor);
+
+public:
+	enum Tool {
+		NoTool,
+		BoundingBoxTool,
+		PolygonTool,
+		TaggingTool,
+		EraserTool
+	};
+
+	enum State {
+		StandBy,
+		NewSelection
+	};
+
+	ImageHolder(QWidget *aParent = 0);
+	virtual ~ImageHolder();
+
+	void setTool(Tool aTool);
+	void setBoundingBoxList(QList< BoundingBox > *aBBoxList);
+	void setPolygonList(QList< Polygon > *aPolyList);
+	void setLabelColorList(QList< uint > *aLabelColorList);
+	void setMainLabelNum(int *aNum);
+	State state();
+	Tool tool();
+
+
+public slots:
+	void clearAll();
+	void clearLast();
+	void confirmSelection();
+	void focusOnArea(QListWidgetItem *anItem);
+	void clearFocusOnArea();
+
+signals:
+	void selectionStarted();
+	void imageScaled();
+
+private:
+	bool repaint_needed_;
+
+	QList< BoundingBox > *list_bounding_box_;
+	QList< Polygon > *list_polygon_;
+	QList< uint > *list_label_color_;
+	int *main_label_;
+	BoundingBox bounding_box_;
+	Polygon polygon_;
+	int keyboard_modifier_;
+
+	QPoint prev_cursor_pos_;
+
+	Tool tool_;
+	State state_;
+
+	int focused_selection_;
+	Tool focused_selection_type_;
+
+	int scale_;
+};
+
+#endif /* IMAGEHOLDER_H_ */
+
+/*
+ *
+ */

+ 2497 - 0
ImageLabeler.cpp

@@ -0,0 +1,2497 @@
+/*
+ * ImageLabeler.cpp
+ *
+ *  Created on: Oct 4, 2011
+ *      Author: Gapchich Vladislav
+ */
+
+#include "ImageLabeler.h"
+#include "functions.h"
+
+#include <QApplication>
+#include <QFrame>
+#include <QMenuBar>
+#include <QMenu>
+#include <QAction>
+#include <QBoxLayout>
+#include <QGridLayout>
+#include <QPixmap>
+#include <QLabel>
+#include <QPushButton>
+#include <QButtonGroup>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QFileDialog>
+#include <QColorDialog>
+#include <QDir>
+#include <QMessageBox>
+#include <QListIterator>
+#include <QDomDocument>
+#include <QFile>
+#include <QKeyEvent>
+#include <QDebug>
+
+ImageLabeler::ImageLabeler(QWidget *aParent) :
+	QMainWindow(aParent)
+{
+	/*
+	 * Variables
+	 */
+
+	list_images_ = new QStringList();
+
+	main_label_ = -1;
+	pure_data_ = 0;
+	//label_ID_ = -1;
+
+	/* options */
+	auto_color_generation_ = 0;
+
+	/*
+	 * menu bar part begins
+	 */
+
+	menu_bar_ = new QMenuBar(this);
+	setMenuBar(menu_bar_);
+
+	menu_file_ = new QMenu(menu_bar_);
+	menu_file_->setTitle(tr("&File"));
+	menu_edit_ = new QMenu(menu_bar_);
+	menu_edit_->setTitle(tr("&Edit"));
+	menu_help_ = new QMenu(menu_bar_);
+	menu_help_->setTitle(tr("&Help"));
+
+	action_open_images_ = new QAction(this);
+	action_open_images_->setText(tr("&Load images"));
+
+	action_open_labeled_image_ = new QAction(this);
+	action_open_labeled_image_->setText(tr("&Open labeled image"));
+
+	action_load_legend_ = new QAction(this);
+	action_load_legend_->setText(tr("Load &legend"));
+
+	action_save_labels_ = new QAction(this);
+	action_save_labels_->setText(tr("&Save all info"));
+	action_save_labels_->setEnabled(false);
+
+	action_save_segmented_ = new QAction(this);
+	action_save_segmented_->setText(tr("Save segmented &picture"));
+	action_save_segmented_->setEnabled(false);
+
+	action_save_legend_ = new QAction(this);
+	action_save_legend_->setText(tr("Save &legend"));
+	action_save_legend_->setEnabled(false);
+
+	action_undo_ = new QAction(this);
+	action_undo_->setText(tr("&Undo"));
+	action_undo_->setEnabled(false);
+	action_redo_ = new QAction(this);
+	action_redo_->setText(tr("&Redo"));
+	action_redo_->setEnabled(false);
+	action_bound_box_tool_ = new QAction(this);
+	action_bound_box_tool_->setText(tr("Bounding box tool"));
+	action_bound_box_tool_->setEnabled(false);
+	action_polygon_tool_ = new QAction(this);
+	action_polygon_tool_->setText(tr("&Polygon tool"));
+	action_polygon_tool_->setEnabled(false);
+	action_tagging_tool_ = new QAction(this);
+	action_tagging_tool_->setText(tr("&Tagging tool"));
+	action_tagging_tool_->setEnabled(false);
+	action_add_description_ = new QAction(this);
+	action_add_description_->setText(tr("&Add image description"));
+	action_add_description_->setEnabled(false);
+	action_options_ = new QAction(this);
+	action_options_->setText(tr("&Options"));
+
+	action_help_content_ = new QAction(this);
+	action_help_content_->setText(tr("&Help content"));
+	action_help_content_->setEnabled(false);
+	action_about_ = new QAction(this);
+	action_about_->setText(tr("&About"));
+	action_about_->setEnabled(false);
+	/* ------------------ */
+
+	action_quit_ = new QAction(this);
+	action_quit_->setText(tr("&Quit"));
+
+	menu_bar_->addAction(menu_file_->menuAction());
+	menu_bar_->addAction(menu_edit_->menuAction());
+	menu_bar_->addAction(menu_help_->menuAction());
+
+	menu_file_->addAction(action_open_images_);
+	menu_file_->addAction(action_open_labeled_image_);
+	menu_file_->addAction(action_load_legend_);
+	menu_file_->addAction(action_save_segmented_);
+	menu_file_->addAction(action_save_legend_);
+	menu_file_->addAction(action_save_labels_);
+	menu_file_->addAction(action_quit_);
+
+	menu_edit_->addAction(action_undo_);
+	menu_edit_->addAction(action_redo_);
+	menu_edit_->addAction(action_bound_box_tool_);
+	menu_edit_->addAction(action_polygon_tool_);
+	menu_edit_->addAction(action_tagging_tool_);
+	menu_edit_->addAction(action_add_description_);
+	menu_edit_->addAction(action_options_);
+
+	menu_help_->addAction(action_help_content_);
+	menu_help_->addAction(action_about_);
+
+	/*
+	 * popup menu part begins
+	 */
+	popup_area_list_ = new QMenu;
+
+	action_delete_area_ = new QAction(this);
+	action_delete_area_->setText(tr("&Delete area"));
+	action_edit_area_ = new QAction(this);
+	action_edit_area_->setText(tr("&Change area"));
+
+	popup_area_list_->addAction(action_delete_area_);
+	popup_area_list_->addAction(action_edit_area_);
+
+	popup_label_list_ = new QMenu;
+
+	action_set_color_ = new QAction(this);
+	action_set_color_->setText(tr("Set &color"));
+	action_toggle_priority_ = new QAction(this);
+	action_toggle_priority_->setText(tr("Toggle &priority"));
+	action_delete_label_ = new QAction(this);
+	action_delete_label_->setText(tr("&Delete"));
+
+	popup_label_list_->addAction(action_set_color_);
+	popup_label_list_->addAction(action_toggle_priority_);
+	popup_label_list_->addAction(action_delete_label_);
+
+	/*
+	 * widgets part begins
+	 */
+	central_widget_ = new QWidget(this);
+	setCentralWidget(central_widget_);
+
+	frame_toolbox_ = new QFrame(central_widget_);
+	frame_toolbox_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+	frame_toolbox_->setLineWidth(0);
+	frame_toolbox_->setMidLineWidth(0);
+	frame_center_ = new QFrame(central_widget_);
+	//frame_image_->setFrameStyle(QFrame::Box | QFrame::Plain);
+	//frame_image_->setLineWidth(1);
+	frame_image_ = new QFrame(frame_center_);
+	//frame_image_->setStyleSheet("QWidget {background: #888888;}");
+	frame_image_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+	frame_image_->setLineWidth(0);
+	frame_image_->setMidLineWidth(0);
+	frame_labelbox_ = new QFrame(central_widget_);
+	frame_labelbox_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+	frame_labelbox_->setLineWidth(0);
+	frame_labelbox_->setMidLineWidth(0);
+
+	image_ = new QPixmap(500, 500);
+	image_->fill(QColor(Qt::white));
+
+	//image_holder_ = new ImageHolder(frame_image_);
+	image_holder_ = new ImageHolder(frame_image_);
+	image_holder_->setPixmap(*image_);
+	image_holder_->setStyleSheet("QLabel {background: #ffffff;}");
+	image_holder_->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+	image_holder_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+	image_holder_->setFocusPolicy(Qt::StrongFocus);
+	image_holder_->setFocus();
+	//image_holder_->setScaledContents(true);
+	image_holder_->setFrameStyle(QFrame::Box | QFrame::Plain);
+	image_holder_->setLineWidth(0);
+
+	list_label_ = new QListWidget(central_widget_);
+	list_label_->setContextMenuPolicy(Qt::CustomContextMenu);
+	list_areas_ = new QListWidget(central_widget_);
+	list_areas_->setContextMenuPolicy(Qt::CustomContextMenu);
+//	addLabel(0, false, "BACKGROUND");
+//	list_label_->item(0)->setFlags(Qt::ItemIsSelectable);
+	//QListWidgetItem *background = list_label_->item(0);
+	//qDebug() << background;
+	//background->setFlags(Qt::ItemIsSelectable);
+
+	label_toolbox_ = new QLabel(tr("Tool box"), frame_toolbox_);
+	label_list_areas_ = new QLabel(tr("Selected areas"), central_widget_);
+
+	/* buttons */
+	button_bound_box_tool_ = new QPushButton(frame_toolbox_);
+	button_bound_box_tool_->setText(tr("bbox"));
+	button_bound_box_tool_->setEnabled(false);
+	button_bound_box_tool_->setCheckable(true);
+	button_polygon_tool_ = new QPushButton(frame_toolbox_);
+	button_polygon_tool_->setText(tr("poly tool"));
+	button_polygon_tool_->setEnabled(false);
+	button_polygon_tool_->setCheckable(true);
+	button_tagging_tool_ = new QPushButton(frame_toolbox_);
+	button_tagging_tool_->setText(tr("tagging"));
+	button_tagging_tool_->setEnabled(false);
+	button_tagging_tool_->setCheckable(true);
+	button_clear_selection_tool_ = new QPushButton(frame_toolbox_);
+	button_clear_selection_tool_->setText(tr("clear selection"));
+	button_clear_selection_tool_->setEnabled(false);
+	button_generate_colors_ = new QPushButton(frame_toolbox_);
+	button_generate_colors_->setText(tr("generate label colors"));
+	button_generate_colors_->setEnabled(false);
+	button_delete_all_labels_ = new QPushButton(frame_toolbox_);
+	button_delete_all_labels_->setText(tr("delete all labels"));
+	button_delete_all_labels_->setEnabled(false);
+
+	group_tools_ = new QButtonGroup;
+	group_tools_->addButton(button_bound_box_tool_);
+	group_tools_->addButton(button_polygon_tool_);
+	group_tools_->addButton(button_tagging_tool_);
+
+	button_confirm_selection_ = new QPushButton(central_widget_);
+	button_confirm_selection_->setText(tr("Confirm selection"));
+	button_confirm_selection_->setEnabled(false);
+
+	button_add_label_ = new QPushButton(frame_labelbox_);
+	button_add_label_->setText(tr("Add label"));
+	button_add_label_->setEnabled(false);
+	button_remove_label_ = new QPushButton(frame_labelbox_);
+	button_remove_label_->setText(tr("Remove label"));
+	button_remove_label_->setEnabled(false);
+
+	button_prev_image_ = new QPushButton(central_widget_);
+	button_prev_image_->setText("←");
+	button_next_image_ = new QPushButton(central_widget_);
+	button_next_image_->setText("→");
+
+	/*
+	 * layouts part begins
+	 */
+	layout_main_ = new QHBoxLayout(central_widget_);
+	layout_left_ = new QVBoxLayout();
+	layout_toolbox_ = new QVBoxLayout();
+	layout_center_ = new QVBoxLayout();
+	layout_frame_image_ = new QVBoxLayout();
+	layout_image_widget_ = new QGridLayout();
+	layout_center_buttons_ = new QHBoxLayout();
+	layout_right_ = new QVBoxLayout();
+	layout_labelbox_ = new QVBoxLayout();
+	layout_labelbox_buttons_ = new QHBoxLayout();
+
+	layout_main_->addLayout(layout_left_);
+	layout_main_->addLayout(layout_center_);
+	layout_main_->addLayout(layout_right_);
+
+	/* making the center part stretchable */
+	layout_main_->setStretch(1, 1);
+
+	/* left part */
+	layout_left_->addWidget(frame_toolbox_);
+	frame_toolbox_->setLayout(layout_toolbox_);
+
+	layout_toolbox_->addWidget(label_toolbox_);
+	layout_toolbox_->addWidget(button_bound_box_tool_);
+	layout_toolbox_->addWidget(button_polygon_tool_);
+	layout_toolbox_->addWidget(button_tagging_tool_);
+	layout_toolbox_->addSpacing(10);
+	layout_toolbox_->addWidget(button_clear_selection_tool_);
+	layout_toolbox_->addWidget(button_delete_all_labels_);
+	layout_toolbox_->addSpacing(10);
+	layout_toolbox_->addWidget(button_generate_colors_);
+	/* stretch is for making toolbox as small as it can be */
+	layout_left_->addStretch(1);
+	layout_left_->addWidget(button_confirm_selection_);
+
+
+	/* central part */
+	layout_center_->addWidget(frame_center_);
+	frame_center_->setLayout(layout_frame_image_);
+
+	//layout_frame_image_->addWidget(image_holder_);
+	layout_frame_image_->setContentsMargins(0, 0, 0, 0);
+	layout_frame_image_->addWidget(frame_image_);
+
+	frame_image_->setLayout(layout_image_widget_);
+	layout_image_widget_->setRowStretch(0, 1);
+	layout_image_widget_->setColumnStretch(0, 1);
+	layout_image_widget_->addWidget(image_holder_, 1, 1);
+	layout_image_widget_->setRowStretch(2, 1);
+	layout_image_widget_->setColumnStretch(2, 1);
+
+	//layout_frame_image_->addStretch(1);
+	layout_frame_image_->addLayout(layout_center_buttons_);
+	layout_center_buttons_->addWidget(button_prev_image_);
+	layout_center_buttons_->addWidget(button_next_image_);
+
+	/* right part */
+	layout_right_->addWidget(frame_labelbox_);
+	frame_labelbox_->setFixedWidth(300);
+	frame_labelbox_->setLayout(layout_labelbox_);
+
+	layout_labelbox_->addLayout(layout_labelbox_buttons_);
+	layout_labelbox_buttons_->addWidget(button_add_label_);
+	layout_labelbox_buttons_->addWidget(button_remove_label_);
+
+	layout_labelbox_->addWidget(list_label_);
+	layout_labelbox_->addWidget(label_list_areas_);
+	layout_labelbox_->addWidget(list_areas_);
+
+	connect(
+		action_quit_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(close())
+		);
+	connect(
+		action_open_images_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(loadImages())
+		);
+	connect(
+		action_open_labeled_image_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(loadInfo())
+		);
+	connect(
+		action_load_legend_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(loadLegendFromFile())
+		);
+	connect(
+		action_save_legend_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(saveLegend())
+		);
+	connect(
+		action_save_segmented_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(saveSegmentedPicture())
+		);
+	connect(
+		action_save_labels_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(saveAllInfo())
+		);
+	connect(
+		button_add_label_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(addLabel())
+		);
+	connect(
+		button_remove_label_,
+		SIGNAL(clicked()),
+		this, SLOT(removeLabel())
+		);
+	connect(
+		button_next_image_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(nextImage())
+		);
+	connect(
+		button_prev_image_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(prevImage())
+		);
+	connect(
+		button_bound_box_tool_,
+		SIGNAL(toggled(bool)),
+		this,
+		SLOT(setBoundingBoxTool(bool))
+		);
+	connect(
+		button_polygon_tool_,
+		SIGNAL(toggled(bool)),
+		this,
+		SLOT(setPolygonTool(bool))
+		);
+	connect(
+		button_clear_selection_tool_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(clearAllTool())
+		);
+	connect(
+		button_generate_colors_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(generateColors())
+		);
+	connect(
+		button_delete_all_labels_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(clearLabelList())
+		);
+	connect(
+		button_confirm_selection_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(confirmSelection())
+		);
+	connect(
+		list_label_,
+		SIGNAL(itemChanged(QListWidgetItem *)),
+		this,
+		SLOT(editLabel(QListWidgetItem *))
+		);
+	connect(
+		list_label_,
+		SIGNAL(itemClicked(QListWidgetItem *)),
+		this,
+		SLOT(setLabelID(QListWidgetItem *))
+		);
+	connect(
+		list_areas_,
+		SIGNAL(itemDoubleClicked(QListWidgetItem *)),
+		image_holder_,
+		SLOT(focusOnArea(QListWidgetItem *))
+		);
+	connect(
+		list_areas_,
+		SIGNAL(customContextMenuRequested(const QPoint &)),
+		this,
+		SLOT(areaListPopupMenu(const QPoint &))
+		);
+	connect(
+		list_areas_,
+		SIGNAL(itemChanged(QListWidgetItem *)),
+		this,
+		SLOT(onAreaChange(QListWidgetItem *))
+		);
+	connect(
+		list_label_,
+		SIGNAL(customContextMenuRequested(const QPoint &)),
+		this,
+		SLOT(labelListPopupMenu(const QPoint &))
+		);
+	connect(
+		action_delete_area_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(deleteArea())
+		);
+	connect(
+		action_edit_area_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(editArea())
+		);
+	connect(
+		action_set_color_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(setLabelColor())
+		);
+	connect(
+		action_toggle_priority_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(toggleLabelPriority())
+		);
+	connect(
+		action_delete_label_,
+		SIGNAL(triggered()),
+		this,
+		SLOT(removeLabel())
+		);
+	connect(
+		action_add_description_,
+		SIGNAL(triggered()),
+		&image_description_form_,
+		SLOT(show())
+		);
+	connect(
+		action_options_,
+		SIGNAL(triggered()),
+		&options_form_,
+		SLOT(show())
+		);
+	connect(
+		image_holder_,
+		SIGNAL(selectionStarted()),
+		this,
+		SLOT(onSelectionStarted())
+		);
+	connect(
+		&image_description_form_,
+		SIGNAL(descriptionSet(QString)),
+		this,
+		SLOT(setDescription(QString))
+		);
+	connect(
+		image_holder_,
+		SIGNAL(imageScaled()),
+		this,
+		SLOT(onImageScaled())
+		);
+	connect(
+		&options_form_,
+		SIGNAL(optionsSet()),
+		this,
+		SLOT(onOptionsSet())
+		);
+
+
+	image_holder_->setBoundingBoxList(&list_bounding_box_);
+	image_holder_->setPolygonList(&list_polygon_);
+	image_holder_->setLabelColorList(&list_label_colors_);
+	image_holder_->setMainLabelNum(&main_label_);
+}
+
+ImageLabeler::~ImageLabeler()
+{
+	delete action_quit_;
+	delete action_open_labeled_image_;
+	delete action_open_images_;
+	delete action_load_legend_;
+	delete action_save_legend_;
+	delete action_save_segmented_;
+	delete action_save_labels_;
+	delete action_undo_;
+	delete action_redo_;
+	delete action_bound_box_tool_;
+	delete action_polygon_tool_;
+	delete action_tagging_tool_;
+	delete action_add_description_;
+	delete action_options_;
+	delete action_about_;
+	delete action_help_content_;
+
+	delete menu_file_;
+	delete menu_edit_;
+	delete menu_help_;
+
+	delete menu_bar_;
+
+	delete action_delete_area_;
+	delete action_edit_area_;
+
+	delete popup_area_list_;
+
+	delete action_toggle_priority_;
+	delete action_set_color_;
+	delete action_delete_label_;
+
+	delete popup_label_list_;
+
+	delete image_;
+	delete image_holder_;
+
+	delete button_add_label_;
+	delete button_remove_label_;
+	delete button_bound_box_tool_;
+	delete button_polygon_tool_;
+	delete button_tagging_tool_;
+	delete button_clear_selection_tool_;
+	delete button_generate_colors_;
+	delete button_delete_all_labels_;
+	delete button_next_image_;
+	delete button_prev_image_;
+
+	delete button_confirm_selection_;
+
+	delete label_list_areas_;
+	delete label_toolbox_;
+	delete list_areas_;
+	delete list_label_;
+
+	delete layout_toolbox_;
+	delete layout_right_;
+	delete layout_center_buttons_;
+	delete layout_frame_image_;
+	delete layout_center_;
+	delete layout_labelbox_buttons_;
+	delete layout_labelbox_;
+	delete layout_left_;
+	delete layout_main_;
+
+	delete frame_labelbox_;
+	delete frame_toolbox_;
+	delete frame_image_;
+	delete frame_center_;
+
+	delete central_widget_;
+
+	delete list_images_;
+	//delete current_image_;
+
+	if (pure_data_) {
+		delete[] *pure_data_;
+		delete pure_data_;
+	}
+}
+
+void
+ImageLabeler::addLabel()
+{
+	QListWidgetItem *newItem = new QListWidgetItem;
+
+	QString label;
+	int itemNum = list_label_->count();
+	label.append(QString("%1: ").arg(itemNum));
+
+	if (itemNum) {
+		newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+		label.append("New label");
+	}
+	else {
+		newItem->setFlags(
+				Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |
+				Qt::ItemIsEnabled
+				);
+		label.append("BACKGROUND");
+	}
+	newItem->setText(label);
+
+	QPixmap iconPix = QPixmap(20, 20);
+	iconPix.fill(Qt::white);
+	QIcon icon(iconPix);
+	list_label_colors_.append(0xffffffff);
+
+	newItem->setIcon(icon);
+
+	list_label_->addItem(newItem);
+	list_label_->setItemSelected(newItem, true);
+}
+
+void
+ImageLabeler::addLabel(
+	int aLabelID,
+	bool isMain,
+	QString aLabel
+)
+{
+	QListWidgetItem *newItem = new QListWidgetItem;
+
+	if (0 == aLabelID) {
+		aLabel = QString("BACKGROUND");
+		newItem->setFlags(
+				Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |
+				Qt::ItemIsEnabled
+				);
+	}
+
+	QString label;
+	label.append(QString("%1: %2").
+		arg(aLabelID).
+		arg(aLabel)
+		);
+
+	/* TODO: check if there is another main label and make it common */
+	if (isMain) {
+		main_label_ = aLabelID;
+	}
+
+	QPixmap iconPix = QPixmap(20, 20);
+	QColor color;
+	if (0 != aLabelID)
+		color = Qt::white;
+	else
+		color = Qt::black;
+	iconPix.fill(color);
+	QIcon icon(iconPix);
+	list_label_colors_.append(color.rgb());
+
+	newItem->setIcon(icon);
+
+	newItem->setText(label);
+	newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+	list_label_->addItem(newItem);
+	list_label_->setItemSelected(newItem, true);
+}
+
+void
+ImageLabeler::editLabel(QListWidgetItem *anItem)
+{
+	QString label = anItem->text();
+	int itemRow = list_label_->row(anItem);
+
+	QString prefix = QString("%1: ").arg(itemRow);
+	if (-1 != label.indexOf(prefix)) {
+		return;
+		/* NOTREACHED */
+	}
+
+	label.prepend(QString("%1: ").arg(itemRow));
+
+	if (main_label_ == itemRow) {
+		label.append(" #main");
+	}
+
+	list_label_->blockSignals(true);
+	anItem->setText(label);
+	list_label_->blockSignals(false);
+}
+
+void
+ImageLabeler::removeLabel()
+{
+	if (0 == list_label_->count()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QListWidgetItem *current = list_label_->currentItem();
+
+	/* because we need to keep BACKGROUND category */
+	if (0 == list_label_->row(current)) {
+		return;
+		/* NOTREACHED */
+	}
+
+	int row = list_label_->row(current);
+	list_label_->takeItem(row);
+	list_label_colors_.takeAt(row);
+	delete current;
+}
+
+void
+ImageLabeler::setLabelID(
+	QListWidgetItem *anItem
+)
+{
+	Q_UNUSED(anItem)
+
+	if (!list_label_->count()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	label_ID_ = list_label_->row(anItem);
+}
+void
+ImageLabeler::addBBoxArea(
+	int anID,
+	BoundingBox aBBox
+)
+{
+	QListWidgetItem *newItem = new QListWidgetItem;
+
+	QString label;
+	label.append(QString("%1: ").arg(list_areas_->count()));
+
+	label.append(QString("BBox #%1; ").arg(anID));
+	label.append(QString("LabelID: %1; ").arg(aBBox.label_ID_));
+	label.append(
+		QString("points:%1;%2;%3;%4; ").
+		arg(aBBox.rect.topLeft().x()).
+		arg(aBBox.rect.topLeft().y()).
+		arg(aBBox.rect.bottomRight().x()).
+		arg(aBBox.rect.bottomRight().y())
+		);
+
+	newItem->setText(label);
+	//newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+	list_areas_->addItem(newItem);
+	list_areas_->setItemSelected(newItem, true);
+}
+
+void
+ImageLabeler::addPolyArea(
+	int aPolyID,
+	Polygon aPoly
+)
+{
+	QListWidgetItem *newItem = new QListWidgetItem;
+
+	QString label;
+	label.append(QString("%1: ").arg(list_areas_->count()));
+
+	label.append(QString("Poly #%1; ").arg(aPolyID));
+	label.append(QString("LabelID: %1; ").arg(aPoly.label_ID_));
+	label.append("points:");
+	for (int i = 0; i < aPoly.poly.count(); i++) {
+		label.append(
+			QString("%1;%2;").
+			arg(aPoly.poly.point(i).x()).
+			arg(aPoly.poly.point(i).y())
+			);
+	}
+
+	newItem->setText(label);
+	//newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+	list_areas_->addItem(newItem);
+	list_areas_->setItemSelected(newItem, true);
+}
+
+/* TODO: finish area editing */
+void
+ImageLabeler::editArea()
+{
+	bool oldState = list_areas_->blockSignals(true);
+	if (!list_areas_->currentItem() || !list_areas_->count()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QListWidgetItem *current = list_areas_->currentItem();
+
+	old_area_string_ = current->text();
+	current->setFlags(current->flags() | Qt::ItemIsEditable);
+	list_areas_->editItem(current);
+	list_areas_->blockSignals(oldState);
+}
+
+void
+ImageLabeler::onAreaChange(QListWidgetItem *anItem)
+{
+	list_areas_->blockSignals(true);
+	QString areaString = anItem->text();
+	int oldID = -1;
+	if (-1 != areaString.indexOf("Poly")) {
+		Polygon poly = polyFromString(&areaString, &oldID);
+
+		if (-1 < poly.label_ID_ && !poly.poly.isEmpty() &&
+			-1 < oldID) {
+			list_polygon_.takeAt(oldID);
+			list_polygon_.insert(oldID, poly);
+		}
+		else
+			anItem->setText(old_area_string_);
+	}
+	else if (-1 != areaString.indexOf("BBox")) {
+		BoundingBox bbox = BBoxFromString(&areaString, &oldID);
+
+		if (-1 < bbox.label_ID_ && -1 < oldID) {
+			list_bounding_box_.takeAt(oldID);
+			list_bounding_box_.insert(oldID, bbox);
+		}
+		else
+			anItem->setText(old_area_string_);
+	}
+	else {
+		showWarning(tr("record format is corrupted, try again"));
+		anItem->setText(old_area_string_);
+	}
+
+	anItem->setFlags(anItem->flags() ^ Qt::ItemIsEditable);
+	list_areas_->blockSignals(false);
+}
+
+void
+ImageLabeler::deleteArea()
+{
+	if (!list_areas_->currentItem() || !list_areas_->count()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QString text = list_areas_->currentItem()->text();
+
+	bool ok = 0;
+	//int labelID = getNumFromString(&text, "LabelID:", ";", &ok);
+
+//	if (!ok) {
+//		return;
+//		/* NOTREACHED */
+//	}
+
+	/*
+	 * 0 - bbox
+	 * 1 - poly
+	 */
+	QString shape;
+	if (-1 != text.indexOf("BBox"))
+		shape = QString("BBox");
+	else if (-1 != text.indexOf("Poly"))
+		shape = QString("Poly");
+	else {
+		return;
+		/* NOTREACHED */
+	}
+
+	int areaNum = getNumFromString(&text, "#", ";", &ok);
+
+	if (!ok) {
+		return;
+		/* NOTREACHED */
+	}
+
+	int currentItemRow = list_areas_->row(list_areas_->currentItem());
+
+	/* changing all shapes(depends on current) which are next in the list */
+	for (int i = list_areas_->count() - 1; i > currentItemRow; i--) {
+		QListWidgetItem item = *(list_areas_->item(i));
+		QString newText = item.text();
+
+		if (-1 == newText.indexOf(shape))
+			continue;
+
+		int num = getNumFromString(&newText, "#", ";", &ok);
+		num--;
+		QString numString = QString("%1").arg(num);
+
+		int numPos = newText.indexOf("#") + 1;
+		newText.replace(numPos, numString.size(), numString);
+
+		list_areas_->takeItem(i);
+		list_areas_->insertItem(i, newText);
+	}
+
+	list_areas_->takeItem(currentItemRow);
+	if (shape == "BBox")
+		list_bounding_box_.removeAt(areaNum);
+	else
+		list_polygon_.removeAt(areaNum);
+
+	image_holder_->update();
+}
+
+void
+ImageLabeler::toggleLabelPriority()
+{
+	if (!list_label_->count()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QListWidgetItem *item = list_label_->currentItem();
+
+	/* because we need to keep BACKGROUND category */
+	if (0 == list_label_->row(item)) {
+		return;
+		/* NOTREACHED */
+	}
+
+	int itemRow = list_label_->row(item);
+	QString text = item->text();
+
+	/* cleaning previous " #main" mark */
+	if (-1 != main_label_) {
+		QListWidgetItem *lastMain = list_label_->item(main_label_);
+		QString lastMainText = lastMain->text();
+		int mainPos = lastMainText.indexOf(" #main");
+		lastMainText = lastMainText.mid(0, mainPos);
+		list_label_->blockSignals(true);
+		lastMain->setText(lastMainText);
+		list_label_->blockSignals(false);
+	}
+
+	if (main_label_ == itemRow) {
+		int mainPos = text.indexOf(" #main");
+		text = text.mid(0, mainPos);
+		main_label_ = -1;
+	}
+	else {
+		text.append(" #main");
+		main_label_ = list_label_->row(item);
+	}
+
+	list_label_->blockSignals(true);
+	item->setText(text);
+	list_label_->blockSignals(false);
+
+	image_holder_->update();
+}
+
+void
+ImageLabeler::getImagesFromDir(const QDir &dir)
+{
+	/* avoiding freezing during recursive search for files */
+	QApplication::processEvents();
+
+	QStringList filenameFilter;
+	filenameFilter <<
+		"*.jpeg" <<
+		"*.jpg" <<
+		"*.gif" <<
+		"*.png" <<
+		"*.bmp" <<
+		"*.tiff"
+		;
+
+	QStringList listImages =
+		dir.entryList(filenameFilter, QDir::Files);
+
+	foreach (QString file, listImages)
+		list_images_->append(dir.absoluteFilePath(file));
+
+	QStringList listDir = dir.entryList(QDir::Dirs);
+	foreach (QString subdir, listDir) {
+		if ("." == subdir || ".." == subdir)
+			continue;
+		getImagesFromDir(QDir(dir.absoluteFilePath(subdir)));
+	}
+}
+
+void
+ImageLabeler::nextImage()
+{
+	if (list_images_->isEmpty()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	if (askForUnsavedData()) {
+		return;
+		/* NOTREACHED */
+	}
+
+
+
+	if (list_images_->end() == current_image_ + 1)
+		current_image_ = list_images_->begin();
+	else
+		current_image_++;
+	image_->load(*current_image_);
+	image_holder_->setPixmap(*image_);
+	list_bounding_box_.clear();
+	list_polygon_.clear();
+	list_areas_->clear();
+	image_holder_->clearAll();
+
+	setWindowTitle(tr("ImageLabeler"));
+}
+
+void
+ImageLabeler::prevImage()
+{
+	if (list_images_->isEmpty()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	if (askForUnsavedData()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	if (list_images_->begin() == current_image_)
+		current_image_ = list_images_->end() - 1;
+	else
+		current_image_--;
+	image_->load(*current_image_);
+	image_holder_->setPixmap(*image_);
+	list_bounding_box_.clear();
+	list_polygon_.clear();
+	list_areas_->clear();
+	image_holder_->clearAll();
+
+	setWindowTitle(tr("ImageLabeler"));
+}
+
+void
+ImageLabeler::saveAllInfo()
+{
+	if (list_images_->isEmpty()) {
+		showWarning("You have not opened any image yet");
+		return;
+		/* NOTREACHED */
+	}
+
+	/* ------------------------------------------------------------------------
+	 * XML part
+	 */
+	QDomDocument doc(tr("ImageLabeler"));
+	QDomElement root = doc.createElement(tr("pixelwise_labeling"));
+	doc.appendChild(root);
+
+	QDomElement image = doc.createElement(tr("image"));
+	root.appendChild(image);
+
+	QDomText pathToImage = doc.createTextNode(*current_image_);
+	image.appendChild(pathToImage);
+
+	QDomElement description = doc.createElement(tr("description"));
+	root.appendChild(description);
+
+	QDomText descriptionText = doc.createTextNode(image_description_);
+	description.appendChild(descriptionText);
+
+	legendToXml(&doc, &root);
+//	QDomElement legend = doc.createElement(tr("legend"));
+//	root.appendChild(legend);
+//
+//	/* storing all labels made by user */
+//	int labelCount = list_label_->count();
+//	for (int i = 0; i < labelCount; i++) {
+//		QDomElement label = doc.createElement(tr("label"));
+//		label.setAttribute("color", QString("%1").arg(list_label_colors_.at(i), 0, 16));
+//		label.setAttribute("id", i);
+//
+//		QString priority;
+//		if (main_label_ == i)
+//			priority.append("1");
+//		else
+//			priority.append("0");
+//		label.setAttribute("isMain", priority);
+//
+//		QString labelText = list_label_->item(i)->text();
+//
+//		/* removing the number prefix of label */
+//		if (-1 != labelText.indexOf(QString("%1: ").arg(i))) {
+//			labelText = labelText.mid(3, labelText.size() - 3);
+//		}
+//
+//		QDomText labelName = doc.createTextNode(labelText);
+//		label.appendChild(labelName);
+//		legend.appendChild(label);
+//	}
+//
+//	/* in case we have no labels */
+//	if (0 == labelCount) {
+//		QDomElement label = doc.createElement(tr("label"));
+//		label.setAttribute(tr("id"), -1);
+//		legend.appendChild(label);
+//	}
+
+	/* objects - selected areas */
+	objectsToXml(&doc, &root);
+//	QDomElement objects = doc.createElement(tr("objects"));
+//	root.appendChild(objects);
+//
+//	/* rects first */
+//	for (int i = 0; i < list_bounding_box_.size(); i++) {
+//		QDomElement rectData = doc.createElement(tr("bbox"));
+//
+//		rectData.setAttribute("id", list_bounding_box_.at(i).label_ID_);
+//
+//		QRect rect = list_bounding_box_.at(i).rect.normalized();
+//
+//		QString rectDataString =
+//			QString("%1;%2;%3;%4;").
+//				arg(rect.x()).
+//				arg(rect.y()).
+//				arg(rect.width()).
+//				arg(rect.height());
+//
+//		QDomText rectDataText = doc.createTextNode(rectDataString);
+//		rectData.appendChild(rectDataText);
+//		objects.appendChild(rectData);
+//	}
+//
+//	/* polys next */
+//	for (int i = 0; i < list_polygon_.size(); i++) {
+//		QDomElement polyData = doc.createElement(tr("poly"));
+//
+//		polyData.setAttribute("id", list_polygon_.at(i).label_ID_);
+//
+//		QPolygon poly = list_polygon_.at(i).poly;
+//
+//		QString polyDataString;
+//		for (int j = 0; j < poly.count(); j++)
+//			polyDataString.append(
+//				QString("%1;%2;").
+//					arg(poly.point(j).x()).
+//					arg(poly.point(j).y())
+//				);
+//
+//
+//		QDomText polyDataText = doc.createTextNode(polyDataString);
+//		polyData.appendChild(polyDataText);
+//		objects.appendChild(polyData);
+//	}
+
+	setPureData();
+	QDomElement pureData = doc.createElement(tr("pure_data"));
+	QSize imageSize = image_->size();
+	QString pixelValues;
+
+	for (int i = 0; i < imageSize.height(); i++) {
+		for (int j = 0; j < imageSize.width(); j++) {
+			pixelValues.append(QString("%1").arg(pure_data_[i][j]));
+			//pixelValues.append(QString(""));
+		}
+		pixelValues.append("\n");
+	}
+
+	QDomText pureDataText = doc.createTextNode(pixelValues);
+	pureData.appendChild(pureDataText);
+	root.appendChild(pureData);
+
+	QString xml = doc.toString();
+	/* ------------------------------------------------------------------------
+	 * XML part ends
+	 */
+
+	QFileDialog fileDialog(0, tr("Save all info"));
+	fileDialog.setAcceptMode(QFileDialog::AcceptSave);
+	fileDialog.setDefaultSuffix("dat");
+	fileDialog.setFileMode(QFileDialog::AnyFile);
+
+	/* altering the name of a new file */
+	QString newFileName = alterFileName(*current_image_, "_labeled");
+
+	fileDialog.selectFile(newFileName);
+
+	QString filename;
+	if (fileDialog.exec()) {
+		filename = fileDialog.selectedFiles().last();
+	}
+	else {
+		//showWarning(tr("Can not open file dialog"));
+		return;
+		/* NOTREACHED */
+	}
+
+	if (filename.isEmpty()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QFile file(filename);
+	if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+		showWarning(tr("Can not open file for writing"));
+		return;
+		/* NOTREACHED */
+	}
+
+	file.write(xml.toLocal8Bit());
+	file.close();
+}
+
+void
+ImageLabeler::saveSegmentedPicture()
+{
+	if (list_bounding_box_.isEmpty() && list_polygon_.isEmpty()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	setPureData();
+
+//	QString suffix = *current_image_;
+//	int dotPos = suffix.lastIndexOf(".");
+//	suffix.mid(dotPos + 1, suffix.size() - dotPos - 1);
+
+	QFileDialog fileDialog(0, tr("Save segmented picture"));
+	fileDialog.setAcceptMode(QFileDialog::AcceptSave);
+	fileDialog.setDefaultSuffix("png");
+	fileDialog.setFileMode(QFileDialog::AnyFile);
+
+	/* altering the name of a new file */
+	QString newFileName = alterFileName(*current_image_, "_segmented");
+
+	fileDialog.selectFile(newFileName);
+
+	QString filename;
+	if (fileDialog.exec()) {
+		filename = fileDialog.selectedFiles().last();
+	}
+	else {
+		return;
+		/* NOTREACHED */
+	}
+
+	QSize imageSize = image_holder_->pixmap()->size();
+	QImage newImage(imageSize, QImage::Format_RGB32);
+	bool generateColorsFlag = auto_color_generation_;
+	bool flag = 0;
+
+
+	/* checking if all the colors are are different from white(default) */
+	if (!generateColorsFlag) {
+		for (int i = 1; i < list_label_->count(); i++) {
+			if (list_label_colors_.at(i) == 0xffffffff && !flag)
+				flag = 1;
+			else if (list_label_colors_.at(i) == 0xffffffff && flag) {
+				QMessageBox msgBox;
+				msgBox.setText(tr("There are few labels with default white color."));
+				msgBox.setInformativeText(tr("Do you want to generate all colors automatically? Otherwise you'll have to do it manually."));
+				msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+				msgBox.setDefaultButton(QMessageBox::Yes);
+				msgBox.setIcon(QMessageBox::Question);
+				int ret = msgBox.exec();
+
+				if (QMessageBox::Yes == ret) {
+					generateColorsFlag = 1;
+					break;
+				}
+				else {
+					return;
+					/* NOTREACHED */
+				}
+			}
+		}
+	}
+
+	/* generating colors for labels */
+	if (list_label_colors_.count() < list_label_->count() ||
+		generateColorsFlag) {
+		generateColors();
+	}
+
+	for (int i = 0; i < imageSize.height(); i++)
+		for (int j = 0; j < imageSize.width(); j++) {
+			newImage.setPixel(j, i, list_label_colors_.at(pure_data_[i][j]));
+		}
+
+	if (!newImage.save(filename, "png", 100))
+		showWarning(tr("An error occurred while saving the segmented image"));
+}
+
+void
+ImageLabeler::saveLegend()
+{
+	if (!list_label_->count()) {
+			showWarning("You have not added any label yet");
+			return;
+			/* NOTREACHED */
+		}
+
+		/* ------------------------------------------------------------------------
+		 * XML part
+		 */
+		QDomDocument doc(tr("ImageLabeler"));
+		QDomElement root = doc.createElement(tr("root"));
+		doc.appendChild(root);
+
+		legendToXml(&doc, &root);
+
+//		QDomElement legend = doc.createElement(tr("legend"));
+//		root.appendChild(legend);
+//
+//		/* storing all labels made by user */
+//		int labelCount = list_label_->count();
+//		for (int i = 0; i < labelCount; i++) {
+//			QDomElement label = doc.createElement(tr("label"));
+//			label.setAttribute("color", QString("%1").arg(list_label_colors_.at(i), 0, 16));
+//			label.setAttribute("id", i);
+//
+//			QString priority;
+//			if (main_label_ == i)
+//				priority.append("1");
+//			else
+//				priority.append("0");
+//			label.setAttribute("isMain", priority);
+//
+//			QString labelText = list_label_->item(i)->text();
+//
+//			/* removing the number prefix of label */
+//			if (-1 != labelText.indexOf(QString("%1: ").arg(i))) {
+//				labelText = labelText.mid(3, labelText.size() - 3);
+//			}
+//
+//			QDomText labelName = doc.createTextNode(labelText);
+//			label.appendChild(labelName);
+//			legend.appendChild(label);
+//		}
+//
+//		/* in case we have no labels */
+//		if (0 == labelCount) {
+//			QDomElement label = doc.createElement(tr("label"));
+//			label.setAttribute(tr("id"), -1);
+//			legend.appendChild(label);
+//		}
+
+		QString xml = doc.toString();
+		/* ------------------------------------------------------------------------
+		 * XML part ends
+		 */
+
+		QFileDialog fileDialog(0, tr("Save legend"));
+		fileDialog.setAcceptMode(QFileDialog::AcceptSave);
+		fileDialog.setDefaultSuffix("dat");
+		fileDialog.setFileMode(QFileDialog::AnyFile);
+
+		/* altering the name of a new file */
+		QString newFileName = alterFileName(*current_image_, "_legend");
+
+		fileDialog.selectFile(newFileName);
+
+		QString filename;
+		if (fileDialog.exec()) {
+			filename = fileDialog.selectedFiles().last();
+		}
+		else {
+			//showWarning(tr("Can not open file dialog"));
+			return;
+			/* NOTREACHED */
+		}
+
+		if (filename.isEmpty()) {
+			return;
+			/* NOTREACHED */
+		}
+
+		QFile file(filename);
+		if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+			showWarning(tr("Can not open file for writing"));
+			return;
+			/* NOTREACHED */
+		}
+
+		file.write(xml.toLocal8Bit());
+		file.close();
+}
+
+void
+ImageLabeler::loadInfo()
+{
+	if (askForUnsavedData()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QFileDialog fileDialog(0, tr("Load file with info"));
+	fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
+	fileDialog.setDefaultSuffix("dat");
+	fileDialog.setFileMode(QFileDialog::AnyFile);
+
+	QString filename;
+	if (fileDialog.exec()) {
+		filename = fileDialog.selectedFiles().last();
+	}
+	else {
+		//showWarning(tr("Can not open file dialog"));
+		return;
+		/* NOTREACHED */
+	}
+
+	QDomDocument doc("Image Labeler");
+	QFile file(filename);
+	if (!file.open(QIODevice::ReadOnly)) {
+		showWarning(tr("Can not open such file"));
+		return;
+		/* NOTREACHED */
+	}
+
+	QString errMsg;
+	if (!doc.setContent(&file, &errMsg)) {
+		showWarning(errMsg);
+		file.close();
+		return;
+		/* NOTREACHED */
+	}
+
+	file.close();
+
+	clearAll();
+	list_label_->clear();
+	enableTools();
+
+	/* getting all info */
+	QDomElement elements = doc.documentElement();
+	QDomNode rootNode = elements.firstChild();
+	QString string;
+
+	while(!rootNode.isNull()) {
+		QDomElement element = rootNode.toElement();
+		if(!element.isNull()) {
+			/* path to the image */
+			if (element.tagName() == "image") {
+				string = element.text();
+				if (string.isNull()) {
+					showWarning(
+						tr(
+						"The file with data doesn't contain path to the image"
+						)
+						);
+					return;
+					/* NOTREACHED */
+				}
+				list_images_->append(string);
+				current_image_ = list_images_->end();
+				current_image_--;
+				image_->load(*current_image_);
+				image_holder_->setPixmap(*image_);
+			}
+			/* image description */
+			else if (element.tagName() == "description" &&
+				!element.text().isNull()) {
+				image_description_ = element.text();
+			}
+			/* legend */
+			else if (element.tagName() == "legend") {
+				loadLegendFromNode(&element);
+			}
+			/* objects */
+			else if (element.tagName() == "objects") {
+				QDomNode subNode = element.firstChild();
+				QDomElement subElement;
+
+				while(!subNode.isNull()) {
+					subElement = subNode.toElement();
+
+					if (subElement.isNull() || subElement.text().isNull()) {
+						subNode = subNode.nextSibling();
+						continue;
+					}
+
+					string = subElement.attribute("id");
+					bool ok = 1;
+					int id = string.toInt(&ok, 10);
+
+					if (!ok) {
+						qDebug() <<
+							"while getting poly: "
+							"poly id format is corrupted";
+						subNode = subNode.nextSibling();
+						continue;
+					}
+
+					string = subElement.text();
+
+					if (subElement.tagName() == "bbox") {
+						setBBoxFromData(&string, &id);
+					}
+					if (subElement.tagName() == "poly") {
+						setPolyFromData(&string, &id);
+					}
+
+					subNode = subNode.nextSibling();
+				}
+			}
+		}
+		rootNode = rootNode.nextSibling();
+	}
+}
+
+void
+ImageLabeler::loadImages()
+{
+	if (askForUnsavedData()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QFileDialog fileDialog(0, tr("Load images"));
+	fileDialog.setFileMode(QFileDialog::Directory);
+	QString dirName("");
+
+	if (fileDialog.exec()) {
+		/* TODO: make it possible to select multiple folders */
+		dirName = fileDialog.selectedFiles().last();
+	}
+	else {
+		//showWarning(tr("Could not open file dialog"));
+		return;
+		/* NOTREACHED */
+	}
+
+	clearAll();
+
+	getImagesFromDir(QDir(dirName));
+
+	if (list_images_->isEmpty()) {
+		showWarning(tr("The folder you selected contains no images"));
+		return;
+		/* NOTREACHED */
+	}
+
+	current_image_ = list_images_->begin();
+
+	image_->load(list_images_->first());
+	image_holder_->setPixmap(*image_);
+
+	enableTools();
+}
+
+void
+ImageLabeler::loadLegendFromFile()
+{
+	QFileDialog fileDialog(0, tr("Load legend"));
+	fileDialog.setFileMode(QFileDialog::AnyFile);
+	QString filename;
+
+	if (fileDialog.exec()) {
+		filename = fileDialog.selectedFiles().last();
+	}
+	else {
+		//showWarning(tr("Could not open file dialog"));
+		return;
+		/* NOTREACHED */
+	}
+
+	QDomDocument doc("Image Labeler");
+	QFile file(filename);
+	if (!file.open(QIODevice::ReadOnly)) {
+		showWarning(tr("Can not open such file"));
+		return;
+		/* NOTREACHED */
+	}
+
+	QString errMsg;
+	if (!doc.setContent(&file, &errMsg)) {
+		showWarning(errMsg);
+		file.close();
+		return;
+		/* NOTREACHED */
+	}
+
+	file.close();
+
+	list_label_->clear();
+
+	/* getting legend */
+	QDomElement elements = doc.documentElement();
+	QDomNode rootNode = elements.firstChild();
+	QString string;
+
+	while(!rootNode.isNull()) {
+		QDomElement element = rootNode.toElement();
+		if(!element.isNull()) {
+			if (element.tagName() == "legend") {
+				loadLegendFromNode(&element);
+			}
+		}
+		rootNode = rootNode.nextSibling();
+	}
+}
+
+void
+ImageLabeler::loadLegendFromNode(QDomElement *anElement)
+{
+	if (!anElement) {
+		return;
+		/* NOTREACHED */
+	}
+	QDomNode subNode = anElement->firstChild();
+	QDomElement subElement;
+	QString string;
+	int id = -1;
+	bool isMain;
+	uint color = 0xff000000;
+
+	while(!subNode.isNull()) {
+		subElement = subNode.toElement();
+
+		if (!subElement.isNull() && !subElement.text().isNull()) {
+			string = subElement.attribute("id");
+			bool ok = 0;
+			id = string.toInt(&ok, 10);
+
+			if (!ok) {
+				qDebug() <<
+					"while getting legend: "
+					"label id format is corrupted";
+				subNode = subNode.nextSibling();
+				continue;
+			}
+
+			string = subElement.attribute("isMain");
+			isMain = string.toInt(&ok, 2);
+
+			if (!ok) {
+				qDebug() <<
+					"while getting legend: "
+					"label isMain flag format is corrupted";
+				subNode = subNode.nextSibling();
+				continue;
+			}
+
+			string = subElement.attribute("color");
+			color = string.toUInt(&ok, 16);
+
+			if (!ok) {
+				qDebug() <<
+					"while getting legend: "
+					"label color format is corrupted";
+				subNode = subNode.nextSibling();
+				continue;
+			}
+
+			string = subElement.text();
+
+			addLabel(id, isMain, string);
+			setLabelColor(id, color);
+		}
+
+		subNode = subNode.nextSibling();
+	}
+}
+
+void
+ImageLabeler::legendToXml(QDomDocument *aDoc, QDomElement *aRoot)
+{
+	QDomElement legend = aDoc->createElement(tr("legend"));
+	aRoot->appendChild(legend);
+
+	/* storing all labels made by user */
+	int labelCount = list_label_->count();
+	for (int i = 0; i < labelCount; i++) {
+		QDomElement label = aDoc->createElement(tr("label"));
+		label.setAttribute("color", QString("%1").arg(list_label_colors_.at(i), 0, 16));
+		label.setAttribute("id", i);
+
+		QString priority;
+		if (main_label_ == i)
+			priority.append("1");
+		else
+			priority.append("0");
+		label.setAttribute("isMain", priority);
+
+		QString labelText = list_label_->item(i)->text();
+
+		/* removing the number prefix of label */
+		if (-1 != labelText.indexOf(QString("%1: ").arg(i))) {
+			labelText = labelText.mid(3, labelText.size() - 3);
+		}
+
+		QDomText labelName = aDoc->createTextNode(labelText);
+		label.appendChild(labelName);
+		legend.appendChild(label);
+	}
+
+	/* in case we have no labels */
+	if (0 == labelCount) {
+		QDomElement label = aDoc->createElement(tr("label"));
+		label.setAttribute(tr("id"), -1);
+		legend.appendChild(label);
+	}
+}
+
+void
+ImageLabeler::objectsToXml(QDomDocument *aDoc, QDomElement *aRoot)
+{
+	QDomElement objects = aDoc->createElement(tr("objects"));
+	aRoot->appendChild(objects);
+
+	/* rects first */
+	for (int i = 0; i < list_bounding_box_.size(); i++) {
+		QDomElement rectData = aDoc->createElement(tr("bbox"));
+
+		rectData.setAttribute("id", list_bounding_box_.at(i).label_ID_);
+
+		QRect rect = list_bounding_box_.at(i).rect.normalized();
+
+		QString rectDataString =
+			QString("%1;%2;%3;%4;").
+				arg(rect.x()).
+				arg(rect.y()).
+				arg(rect.width()).
+				arg(rect.height());
+
+		QDomText rectDataText = aDoc->createTextNode(rectDataString);
+		rectData.appendChild(rectDataText);
+		objects.appendChild(rectData);
+	}
+
+	/* polys next */
+	for (int i = 0; i < list_polygon_.size(); i++) {
+		QDomElement polyData = aDoc->createElement(tr("poly"));
+
+		polyData.setAttribute("id", list_polygon_.at(i).label_ID_);
+
+		QPolygon poly = list_polygon_.at(i).poly;
+
+		QString polyDataString;
+		for (int j = 0; j < poly.count(); j++)
+			polyDataString.append(
+				QString("%1;%2;").
+					arg(poly.point(j).x()).
+					arg(poly.point(j).y())
+				);
+
+
+		QDomText polyDataText = aDoc->createTextNode(polyDataString);
+		polyData.appendChild(polyDataText);
+		objects.appendChild(polyData);
+	}
+}
+
+void
+ImageLabeler::generateColors()
+{
+	int labelCount = list_label_->count();
+
+	if (!labelCount) {
+		showWarning(tr("you have not added any labels yet"));
+		return;
+		/* NOTREACHED */
+	}
+
+	int coeff = (0xff / labelCount) * 3;
+	//QList< uint > colors;
+	list_label_colors_.clear();
+	list_label_colors_.append(0);
+	uchar red = 0xff;
+	uchar green = 0xff;
+	uchar blue = 0xff;
+	uchar iterationColor = coeff;
+	uint color = 0xffffffff;
+	int j = 1;
+	for (int i = 1; i < labelCount; i++) {
+		if (6 == j) {
+			iterationColor += coeff;
+			j = 1;
+		}
+
+		if (5 == j) {
+			red = 0xff - iterationColor;
+			green = 0xff - iterationColor;
+			blue = 0xff;
+		}
+		else if (4 == j) {
+			red = 0xff - iterationColor;
+			green = 0xff;
+			blue = 0xff - iterationColor;
+		}
+		else if (3 == j) {
+			red = 0xff - iterationColor;
+			green = 0xff;
+			blue = 0xff;
+		}
+		else if (2 == j) {
+			red = 0xff;
+			green = 0xff - iterationColor;
+			blue = 0xff;
+		}
+		else if (1 == j){
+			red = 0xff;
+			green = 0xff;
+			blue = 0xff - iterationColor;
+		}
+		j++;
+		color = red + (green * 0x100) + (blue * 0x10000) + 0xff000000;
+
+		int itemNo = list_label_colors_.count();
+
+		QPixmap iconPix = QPixmap(20, 20);
+		iconPix.fill(color);
+		QIcon icon(iconPix);
+
+		list_label_->item(itemNo)->setIcon(icon);
+		list_label_colors_.append(color);
+	}
+}
+
+void
+ImageLabeler::setBBoxFromData(
+	QString *aBBoxData,
+	int *ID
+)
+{
+	BoundingBox bbox = BBoxFromData(aBBoxData);
+	if (!bbox.rect.isValid() || !ID) {
+		return;
+		/* NOTREACHED */
+	}
+
+	bbox.label_ID_ = *ID;
+	list_bounding_box_.append(bbox);
+	addBBoxArea(list_bounding_box_.count() - 1, bbox);
+}
+
+BoundingBox
+ImageLabeler::BBoxFromData(
+	QString *aBBoxData
+)
+{
+	BoundingBox bbox;
+	QString buffer;
+	bbox.rect.setRect(-1, -1, -1, -1);
+	int startPos = 0;
+	bool ok = 1;
+
+	for (int i = 0; i < aBBoxData->size(); i++) {
+		if (';' != aBBoxData->at(i))
+			continue;
+
+		buffer = aBBoxData->mid(startPos, i - startPos);
+
+		int bboxData = buffer.toInt(&ok, 10);
+		if (!ok) {
+			qDebug() <<
+				"while getting objects: "
+				"poly format is corrupted";
+			break;
+		}
+
+		if (-1 == bbox.rect.x()) {
+			bbox.rect.setX(bboxData);
+			bbox.rect.setWidth(-1);
+		}
+		else if (-1 == bbox.rect.y()) {
+			bbox.rect.setY(bboxData);
+			bbox.rect.setHeight(-1);
+		}
+		else if (-1 == bbox.rect.width()) {
+			bbox.rect.setWidth(bboxData);
+		}
+		else if (-1 == bbox.rect.height()) {
+			bbox.rect.setHeight(bboxData);
+		}
+
+		startPos = i + 1;
+	}
+
+	if (!bbox.rect.isValid()) {
+		qDebug() <<
+			"BBoxFromData: "
+			"bbox format is corrupted";
+		bbox.rect.setRect(-1, -1, -1, -1);
+	}
+	else if (!ok) {
+		bbox.rect.setRect(-1, -1, -1, -1);
+	}
+
+	return bbox;
+}
+
+BoundingBox
+ImageLabeler::BBoxFromString(
+	QString *aString,
+	int *oldID
+)
+{
+	BoundingBox bbox;
+	bbox.label_ID_ = -1;
+	*oldID = -1;
+
+	if (!aString) {
+		return bbox;
+		/* NOTREACHED */
+	}
+
+	if (-1 == aString->indexOf("BBox")) {
+		return bbox;
+		/* NOTREACHED */
+	}
+
+	/* getting bbox id in the list(it cannot be changed) */
+	bool ok = 0;
+	int bboxID = getNumFromString(aString, "BBox #", ";", &ok);
+	if (!ok || -1 <= bboxID) {
+		qDebug() <<
+			"BBoxFromString: poly ID is corrupted";
+		return bbox;
+		/* NOTREACHED */
+	}
+
+	/* getting new label id */
+	int labelID = getNumFromString(aString, "LabelID: ", ";", &ok);
+	if (!ok || -1 <= labelID) {
+		showWarning(
+			tr("new LabelID is wrong, area can not be changed")
+				);
+		return bbox;
+		/* NOTREACHED */
+	}
+
+	/* getting new points */
+	int pointsPos = aString->indexOf("points:") + 7;
+	int pointsLen = aString->size() - pointsPos;
+	if (pointsLen <= 0) {
+		showWarning(
+			tr("new points data is wrong, area can not be changed")
+				);
+		return bbox;
+		/* NOTREACHED */
+	}
+	QString pointsData = aString->mid(pointsPos, pointsLen);
+	bbox = BBoxFromData(&pointsData);
+	bbox.label_ID_ = labelID;
+
+
+	*oldID = bboxID;
+	return bbox;
+}
+
+void
+ImageLabeler::setPolyFromData(
+	QString *aPolyData,
+	int *ID
+)
+{
+	Polygon poly = polyFromData(aPolyData);
+
+	if (poly.poly.isEmpty() || !ID) {
+		return;
+		/* NOTREACHED */
+	}
+
+	poly.label_ID_ = *ID;
+	list_polygon_.append(poly);
+	addPolyArea(list_polygon_.count() - 1, poly);
+}
+
+Polygon
+ImageLabeler::polyFromData(
+	QString *aPolyData
+)
+{
+	Polygon poly;
+	poly.label_ID_ = -1;
+	QPoint point;
+	QString buffer;
+	int startPos = 0;
+	bool ok = 1;
+	bool evenFlag = 0;
+
+	for (int i = 0; i < aPolyData->size(); i++) {
+		if (';' != aPolyData->at(i))
+			continue;
+
+		buffer = aPolyData->mid(startPos, i - startPos);
+
+		int polyCoor = buffer.toInt(&ok, 10);
+		if (!ok) {
+			qDebug() <<
+				"while getting objects: "
+				"poly format is corrupted";
+			break;
+		}
+
+		if (!evenFlag) {
+			point.setX(polyCoor);
+			evenFlag = 1;
+		}
+		else {
+			point.setY(polyCoor);
+			poly.poly.append(point);
+			evenFlag = 0;
+		}
+		startPos = i + 1;
+	}
+
+	if (evenFlag) {
+		qDebug() <<
+			"polyFromData: "
+			"poly format is corrupted";
+		poly.poly.clear();
+	}
+	else if (!ok) {
+		poly.poly.clear();
+	}
+
+	return poly;
+}
+
+Polygon
+ImageLabeler::polyFromString(
+	QString *aString,
+	int *oldID
+)
+{
+	Polygon poly;
+	poly.label_ID_ = -1;
+	*oldID = -1;
+
+	if (!aString) {
+		return poly;
+		/* NOTREACHED */
+	}
+
+	if (-1 == aString->indexOf("Poly")) {
+		return poly;
+		/* NOTREACHED */
+	}
+
+	/* getting poly id in the list(it cannot be changed) */
+	bool ok = 0;
+	int polyID = getNumFromString(aString, "Poly #", ";", &ok);
+	if (!ok || -1 <= polyID) {
+		qDebug() <<
+			"polyFromString: poly ID is corrupted";
+		return poly;
+		/* NOTREACHED */
+	}
+
+	/* getting new label id */
+	int labelID = getNumFromString(aString, "LabelID: ", ";", &ok);
+	if (!ok || -1 <= labelID) {
+		showWarning(
+			tr("new LabelID is wrong, area can not be changed")
+				);
+		return poly;
+		/* NOTREACHED */
+	}
+
+	/* getting new points */
+	int pointsPos = aString->indexOf("points:") + 7;
+	int pointsLen = aString->size() - pointsPos;
+	if (pointsLen <= 0) {
+		showWarning(
+			tr("new points data is wrong, area can not be changed")
+				);
+		return poly;
+		/* NOTREACHED */
+	}
+	QString pointsData = aString->mid(pointsPos, pointsLen);
+	poly = polyFromData(&pointsData);
+	poly.label_ID_ = labelID;
+
+
+	*oldID = polyID;
+	return poly;
+}
+
+void
+ImageLabeler::showWarning(
+		const QString text
+)
+{
+	if (text.isEmpty()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	QMessageBox msgBox;
+	msgBox.setText(text);
+	msgBox.setIcon(QMessageBox::Warning);
+	msgBox.exec();
+}
+
+bool
+ImageLabeler::askForUnsavedData()
+{
+	if (!list_bounding_box_.isEmpty() ||
+		!list_polygon_.isEmpty())
+	{
+		QMessageBox msgBox;
+		msgBox.setText(tr("There is some unsaved data"));
+		msgBox.setInformativeText(tr("Do you want to save your progress?"));
+		msgBox.setStandardButtons(
+			QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+		msgBox.setDefaultButton(QMessageBox::Save);
+		msgBox.setIcon(QMessageBox::Question);
+		int ret = msgBox.exec();
+
+		if (QMessageBox::Save == ret)
+			saveAllInfo();
+		else if (QMessageBox::Cancel == ret)
+			return true;
+	}
+	return false;
+}
+
+void
+ImageLabeler::setBoundingBoxTool(bool aButtonPressed)
+{
+	if (aButtonPressed)
+		image_holder_->setTool(ImageHolder::BoundingBoxTool);
+	else {
+		image_holder_->setTool(ImageHolder::NoTool);
+		image_holder_->clearLast();
+	}
+}
+
+void
+ImageLabeler::setPolygonTool(bool aButtonPressed)
+{
+	if (aButtonPressed) {
+		image_holder_->setTool(ImageHolder::PolygonTool);
+		image_holder_->setFocus();
+	}
+	else {
+		image_holder_->setTool(ImageHolder::NoTool);
+		image_holder_->clearLast();
+	}
+}
+
+void
+ImageLabeler::onSelectionStarted()
+{
+	button_confirm_selection_->setEnabled(true);
+}
+
+void
+ImageLabeler::onImageScaled()
+{
+
+}
+
+void
+ImageLabeler::confirmSelection()
+{
+	if (!list_label_->count()) {
+		showWarning(tr("You haven't added any label"));
+		return;
+		/* NOTREACHED */
+	}
+
+	image_holder_->confirmSelection();
+
+	if (label_ID_ < 0)
+		label_ID_ = 0;
+
+	ImageHolder::Tool tool = image_holder_->tool();
+	switch (tool) {
+	case ImageHolder::BoundingBoxTool:
+		list_bounding_box_.last().label_ID_ = label_ID_;
+		addBBoxArea(
+			list_bounding_box_.count() - 1,
+			list_bounding_box_.last()
+			);
+		break;
+	case ImageHolder::PolygonTool:
+		list_polygon_.last().label_ID_ = label_ID_;
+		addPolyArea(
+			list_polygon_.count() - 1,
+			list_polygon_.last()
+			);
+		break;
+	default:
+		break;
+	}
+	button_confirm_selection_->setEnabled(false);
+}
+
+void
+ImageLabeler::clearAll()
+{
+	clearLabelList();
+	list_areas_->clear();
+	list_bounding_box_.clear();
+	list_polygon_.clear();
+	list_images_->clear();
+	main_label_ = -1;
+	image_holder_->clearAll();
+}
+
+void
+ImageLabeler::clearAllTool()
+{
+	list_areas_->clear();
+	list_bounding_box_.clear();
+	list_polygon_.clear();
+	main_label_ = -1;
+	image_holder_->clearAll();
+}
+
+void ImageLabeler::clearLabelList()
+{
+	list_label_->clear();
+	addLabel(0, false, "BACKGROUND");
+	list_label_->item(0)->setFlags(
+		Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |
+		Qt::ItemIsEnabled
+		);
+}
+
+void
+ImageLabeler::enableTools()
+{
+	action_save_labels_->setEnabled(true);
+	action_save_segmented_->setEnabled(true);
+	action_save_legend_->setEnabled(true);
+	action_bound_box_tool_->setEnabled(true);
+	action_polygon_tool_->setEnabled(true);
+	action_add_description_->setEnabled(true);
+	button_bound_box_tool_->setEnabled(true);
+	button_polygon_tool_->setEnabled(true);
+	button_add_label_->setEnabled(true);
+	button_remove_label_->setEnabled(true);
+	button_prev_image_->setEnabled(true);
+	button_next_image_->setEnabled(true);
+	button_clear_selection_tool_->setEnabled(true);
+	button_generate_colors_->setEnabled(true);
+	button_delete_all_labels_->setEnabled(true);
+}
+
+void
+ImageLabeler::disableTools()
+{
+	action_save_labels_->setEnabled(false);
+	action_save_segmented_->setEnabled(false);
+	action_save_legend_->setEnabled(false);
+	action_bound_box_tool_->setEnabled(false);
+	action_polygon_tool_->setEnabled(false);
+	action_add_description_->setEnabled(false);
+	button_bound_box_tool_->setEnabled(false);
+	button_polygon_tool_->setEnabled(false);
+	button_add_label_->setEnabled(false);
+	button_remove_label_->setEnabled(false);
+	button_prev_image_->setEnabled(false);
+	button_next_image_->setEnabled(false);
+	button_clear_selection_tool_->setEnabled(false);
+	button_generate_colors_->setEnabled(false);
+	button_delete_all_labels_->setEnabled(false);
+}
+
+void
+ImageLabeler::areaListPopupMenu(const QPoint &aPos)
+{
+	QPoint globalPos = list_areas_->mapToGlobal(aPos);
+	QModelIndex index = list_areas_->indexAt(aPos);
+
+	if (-1 == index.row()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	list_areas_->item(index.row())->setSelected(true);
+
+	popup_area_list_->exec(globalPos);
+}
+
+void
+ImageLabeler::labelListPopupMenu(const QPoint &aPos)
+{
+	QPoint globalPos = list_label_->mapToGlobal(aPos);
+	QModelIndex index = list_label_->indexAt(aPos);
+
+	if (-1 == index.row() || !index.row()) {
+		return;
+		/* NOTREACHED */
+	}
+
+	list_label_->item(index.row())->setSelected(true);
+
+	popup_label_list_->exec(globalPos);
+}
+
+void
+ImageLabeler::setDescription(QString aDescription)
+{
+	image_description_ = aDescription;
+	setWindowTitle(image_description_);
+}
+
+void
+ImageLabeler::setPureData()
+{
+	/* initializing array */
+	if (pure_data_) {
+		delete[] *pure_data_;
+		delete pure_data_;
+	}
+
+	QSize imageSize = image_->size();
+	pure_data_ = new int *[imageSize.height()];
+	if (!pure_data_) {
+		return;
+		/* NOTREACHED */
+	}
+	for (int i = 0; i < imageSize.height(); i++) {
+		pure_data_[i] = new int[imageSize.width()];
+		if (!pure_data_[i]) {
+			return;
+			/* NOTREACHED */
+		}
+	}
+
+	int bboxCnt = list_bounding_box_.count();
+	int polyCnt = list_polygon_.count();
+	for (int i = 0; i < imageSize.height(); i++)
+		for (int j = 0; j < imageSize.width(); j++) {
+			pure_data_[i][j] = 0;
+			/* bboxes first */
+			for (int cnt = 0; cnt < bboxCnt; cnt++) {
+				BoundingBox bbox = list_bounding_box_.at(cnt);
+				if (bbox.rect.contains(j, i)) {
+					pure_data_[i][j] = bbox.label_ID_;
+				}
+			}
+			/* polys next */
+			for (int cnt = 0; cnt < polyCnt; cnt++) {
+				Polygon poly = list_polygon_.at(cnt);
+				if (poly.poly.containsPoint(QPoint(j, i), Qt::OddEvenFill)) {
+					pure_data_[i][j] = poly.label_ID_;
+				}
+			}
+		}
+
+
+}
+
+void
+ImageLabeler::setLabelColor()
+{
+	if (list_label_colors_.count() < list_label_->count()) {
+		generateColors();
+	}
+
+	QListWidgetItem *current = list_label_->currentItem();
+
+	int labelID = list_label_->row(current);
+	QColor defaultColor;
+	defaultColor.setRgb(list_label_colors_.at(labelID));
+	QColor newColor = QColorDialog::getColor(
+		defaultColor,
+		list_label_
+		);
+
+	if (!newColor.isValid()) {
+		return;
+		/* NOTREACHED */
+	}
+	list_label_colors_.takeAt(labelID);
+	list_label_colors_.insert(labelID, newColor.rgb());
+
+	QPixmap iconPix = QPixmap(20, 20);
+	iconPix.fill(newColor);
+	QIcon icon(iconPix);
+
+	current->setIcon(icon);
+}
+
+void
+ImageLabeler::setLabelColor(int anID, QColor aColor)
+{
+	if (anID < 0) {
+		return;
+		/* NOTREACHED */
+	}
+
+	if (list_label_colors_.count() < list_label_->count()) {
+		generateColors();
+	}
+
+	QListWidgetItem *item = list_label_->item(anID);
+	list_label_colors_.takeAt(anID);
+	list_label_colors_.insert(anID, aColor.rgb());
+
+	QPixmap iconPix = QPixmap(20, 20);
+	iconPix.fill(aColor);
+	QIcon icon(iconPix);
+
+	item->setIcon(icon);
+}
+
+void
+ImageLabeler::onOptionsSet()
+{
+	auto_color_generation_ = options_form_.autoColorGeneration();
+}
+
+void
+ImageLabeler::resizeEvent (QResizeEvent *anEvent)
+{
+	QWidget::resizeEvent(anEvent);
+}
+
+void
+ImageLabeler::mousePressEvent(QMouseEvent *anEvent)
+{
+	QWidget::mousePressEvent(anEvent);
+}
+
+void
+ImageLabeler::keyPressEvent(QKeyEvent *anEvent)
+{
+	if (Qt::Key_Left == anEvent->key() &&
+		Qt::NoModifier == anEvent->modifiers()) {
+		prevImage();
+	}
+
+	if (Qt::Key_Right == anEvent->key() &&
+		Qt::NoModifier == anEvent->modifiers()) {
+		nextImage();
+	}
+
+	if (Qt::Key_Enter == anEvent->key() &&
+	//	Qt::NoModifier == anEvent->modifiers() &&
+		ImageHolder::NewSelection == image_holder_->state()) {
+		confirmSelection();
+	}
+
+	if (Qt::Key_Escape == anEvent->key()) {
+		image_holder_->clearLast();
+		image_holder_->clearFocusOnArea();
+	}
+
+	QWidget::keyPressEvent(anEvent);
+}
+
+/* TODO: finish scaling */
+void
+ImageLabeler::wheelEvent(QWheelEvent *anEvent)
+{
+	/* zoomin */
+	if (0 < anEvent->delta()) {
+		//image_holder_->scaleImage(ZoomIn, 1.1);
+	}
+	/* zoomout */
+	else if (anEvent->delta() < 0) {
+		//image_holder_->scaleImage(ZoomOut, 1.1);
+	}
+}
+
+/*
+ *
+ */

+ 226 - 0
ImageLabeler.h

@@ -0,0 +1,226 @@
+/*
+ * ImageLabeler.h
+ *
+ *  Created on: Oct 4, 2011
+ *      Author: Gapchich Vladislav
+ */
+
+#ifndef __IMAGELABELER_H__
+#define __IMAGELABELER_H__
+
+#include "ImageHolder.h"
+#include "ImageDescriptionForm.h"
+#include "OptionsForm.h"
+
+#include <QMainWindow>
+#include <QDir>
+
+/* forward declarations */
+class QMenuBar;
+class QMenu;
+class QAction;
+class QHBoxLayout;
+class QVBoxLayout;
+class QGridLayout;
+class QPushButton;
+class QPixmap;
+class QLabel;
+class QFrame;
+class QListWidget;
+class QListWidgetItem;
+class QButtonGroup;
+class QDomDocument;
+class QDomElement;
+
+class ImageLabeler : public QMainWindow
+{
+	Q_OBJECT
+protected:
+	/* events */
+	void resizeEvent(QResizeEvent *anEvent);
+	void mousePressEvent(QMouseEvent *anEvent);
+	void wheelEvent(QWheelEvent *anEvent);
+	void keyPressEvent(QKeyEvent *anEvent);
+
+	void getImagesFromDir(const QDir &dir);
+	void showWarning(const QString text);
+	bool askForUnsavedData();
+	void loadLegendFromNode(QDomElement *anElement);
+	void setPolyFromData(
+		QString *aPolyData,
+		int *ID
+		);
+	void setBBoxFromData(
+		QString *aBBoxData,
+		int *ID
+		);
+	Polygon polyFromData(
+		QString *aPolyData
+		);
+	Polygon	polyFromString(
+		QString *aString,
+		int *oldID
+		);
+	BoundingBox BBoxFromData(
+		QString *aBBoxData
+		);
+	BoundingBox	BBoxFromString(
+		QString *aString,
+		int *oldID
+		);
+	void enableTools();
+	void disableTools();
+	void legendToXml(QDomDocument *aDoc, QDomElement *aRoot);
+	void objectsToXml(QDomDocument *aDoc, QDomElement *aRoot);
+
+public:
+	ImageLabeler(QWidget *aParent = 0);
+	virtual ~ImageLabeler();
+
+public slots:
+	void addLabel();
+	void addLabel(
+		int aLabelID,
+		bool isMain,
+		QString aLabel
+	);
+	void removeLabel();
+	void setLabelID(QListWidgetItem *anItem);
+	void addBBoxArea(
+		int anID,
+		BoundingBox aBBox
+		);
+	void addPolyArea(
+		int aPolyID,
+		Polygon aPoly
+		);
+	void deleteArea();
+	void editArea();
+	void toggleLabelPriority();
+	void loadImages();
+	void nextImage();
+	void prevImage();
+	void editLabel(QListWidgetItem *anItem);
+	void saveAllInfo();
+	void saveSegmentedPicture();
+	void saveLegend();
+	void loadInfo();
+	void loadLegendFromFile();
+	void setBoundingBoxTool(bool aButtonPressed);
+	void setPolygonTool(bool aButtonPressed);
+	void generateColors();
+	void confirmSelection();
+	void clearAll();
+	void clearAllTool();
+	void clearLabelList();
+	void areaListPopupMenu(const QPoint &aPos);
+	void labelListPopupMenu(const QPoint &aPos);
+	void setDescription(QString aDescription);
+	void onImageScaled();
+	void onOptionsSet();
+	void onSelectionStarted();
+	void onAreaChange(QListWidgetItem *);
+	void setPureData();
+	void setLabelColor();
+	void setLabelColor(int anID, QColor aColor);
+
+private:
+	/* menu */
+	QMenuBar *menu_bar_;
+	QMenu *menu_file_;
+	QMenu *menu_edit_;
+	QMenu *menu_help_;
+	QAction *action_open_images_;
+	QAction *action_open_image_;
+	QAction *action_open_labeled_image_;
+	QAction *action_load_legend_;
+	QAction *action_save_labels_;
+	QAction *action_save_segmented_;
+	QAction *action_save_legend_;
+	QAction *action_quit_;
+	QAction *action_undo_;
+	QAction *action_redo_;
+	QAction *action_bound_box_tool_;
+	QAction *action_polygon_tool_;
+	QAction *action_tagging_tool_;
+	QAction *action_add_description_;
+	QAction *action_options_;
+	QAction *action_about_;
+	QAction *action_help_content_;
+
+	/* popup menu */
+	QMenu *popup_area_list_;
+
+	QAction *action_delete_area_;
+	QAction *action_edit_area_;
+
+	QMenu *popup_label_list_;
+
+	QAction *action_toggle_priority_;
+	QAction *action_set_color_;
+	QAction *action_delete_label_;
+
+	/* layouts */
+	QHBoxLayout *layout_main_;
+	QVBoxLayout *layout_left_;
+	QVBoxLayout *layout_toolbox_;
+	QVBoxLayout *layout_center_;
+	QVBoxLayout *layout_frame_image_;
+	QGridLayout *layout_image_widget_;
+	QHBoxLayout *layout_center_buttons_;
+	QVBoxLayout *layout_right_;
+	QVBoxLayout *layout_labelbox_;
+	QHBoxLayout *layout_labelbox_buttons_;
+
+	/* widgets */
+	QWidget *central_widget_;
+	QFrame *frame_image_;
+	QFrame *frame_center_;
+	QFrame *frame_toolbox_;
+	QFrame *frame_labelbox_;
+	QPixmap *image_;
+	ImageHolder *image_holder_;
+	QLabel *label_toolbox_;
+	QLabel *label_list_areas_;
+	QListWidget *list_label_;
+	QListWidget *list_areas_;
+	ImageDescriptionForm image_description_form_;
+	OptionsForm options_form_;
+
+	QPushButton *button_bound_box_tool_;
+	QPushButton *button_polygon_tool_;
+	QPushButton *button_tagging_tool_;
+	QPushButton *button_clear_selection_tool_;
+	QPushButton *button_delete_all_labels_;
+	QPushButton *button_generate_colors_;
+	QPushButton *button_add_label_;
+	QPushButton *button_remove_label_;
+	QPushButton *button_prev_image_;
+	QPushButton *button_next_image_;
+	QPushButton *button_confirm_selection_;
+
+	QButtonGroup *group_tools_;
+
+	/* variables */
+	int main_label_;
+	int **pure_data_;
+	int label_ID_;
+
+	QString image_description_;
+	QStringList *list_images_;
+	QStringList::iterator current_image_;
+	QList< BoundingBox > list_bounding_box_;
+	QList< Polygon > list_polygon_;
+	QList< uint > list_label_colors_;
+
+	QString old_area_string_;
+
+	/* options */
+	bool auto_color_generation_;
+};
+
+#endif /* __IMAGELABELER_H__ */
+
+/*
+ *
+ */

+ 18 - 0
ImageLabeler.pro

@@ -0,0 +1,18 @@
+TEMPLATE = app
+TARGET = ImageLabeler
+QT += core \
+    gui \
+    xml
+HEADERS += OptionsForm.h \
+    ImageDescriptionForm.h \
+    functions.h \
+    ImageHolder.h \
+    ImageLabeler.h
+SOURCES += OptionsForm.cpp \
+    ImageDescriptionForm.cpp \
+    functions.cpp \
+    ImageHolder.cpp \
+    ImageLabeler.cpp \
+    main.cpp
+FORMS += 
+RESOURCES += 

+ 145 - 0
Makefile

@@ -0,0 +1,145 @@
+#############################################################################
+# Makefile for building: ImageLabeler
+# Generated by qmake (2.01a) (Qt 4.7.1) on: Tue Oct 11 14:53:52 2011
+# Project:  ImageLabeler.pro
+# Template: app
+# Command: /usr/bin/qmake CONFIG+=debug_and_release -o Makefile ImageLabeler.pro
+#############################################################################
+
+first: release
+install: release-install
+uninstall: release-uninstall
+MAKEFILE      = Makefile
+QMAKE         = /usr/bin/qmake
+DEL_FILE      = rm -f
+CHK_DIR_EXISTS= test -d
+MKDIR         = mkdir -p
+COPY          = cp -f
+COPY_FILE     = $(COPY)
+COPY_DIR      = $(COPY) -r
+INSTALL_FILE  = install -m 644 -p
+INSTALL_PROGRAM = install -m 755 -p
+INSTALL_DIR   = $(COPY_DIR)
+DEL_FILE      = rm -f
+SYMLINK       = ln -f -s
+DEL_DIR       = rmdir
+MOVE          = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR         = mkdir -p
+SUBTARGETS    =  \
+		release \
+		debug
+
+release: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release
+release-make_default: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release 
+release-make_first: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release first
+release-all: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release all
+release-clean: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release clean
+release-distclean: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release distclean
+release-install: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release install
+release-uninstall: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release uninstall
+debug: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug
+debug-make_default: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug 
+debug-make_first: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug first
+debug-all: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug all
+debug-clean: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug clean
+debug-distclean: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug distclean
+debug-install: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug install
+debug-uninstall: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug uninstall
+
+Makefile: ImageLabeler.pro  /usr/share/qt4/mkspecs/default/qmake.conf /usr/share/qt4/mkspecs/common/g++.conf \
+		/usr/share/qt4/mkspecs/common/unix.conf \
+		/usr/share/qt4/mkspecs/common/linux.conf \
+		/usr/share/qt4/mkspecs/qconfig.pri \
+		/usr/share/qt4/mkspecs/modules/qt_phonon.pri \
+		/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \
+		/usr/share/qt4/mkspecs/features/qt_functions.prf \
+		/usr/share/qt4/mkspecs/features/qt_config.prf \
+		/usr/share/qt4/mkspecs/features/exclusive_builds.prf \
+		/usr/share/qt4/mkspecs/features/default_pre.prf \
+		/usr/share/qt4/mkspecs/features/release.prf \
+		/usr/share/qt4/mkspecs/features/debug_and_release.prf \
+		/usr/share/qt4/mkspecs/features/default_post.prf \
+		/usr/share/qt4/mkspecs/features/warn_on.prf \
+		/usr/share/qt4/mkspecs/features/qt.prf \
+		/usr/share/qt4/mkspecs/features/unix/thread.prf \
+		/usr/share/qt4/mkspecs/features/moc.prf \
+		/usr/share/qt4/mkspecs/features/resources.prf \
+		/usr/share/qt4/mkspecs/features/uic.prf \
+		/usr/share/qt4/mkspecs/features/yacc.prf \
+		/usr/share/qt4/mkspecs/features/lex.prf \
+		/usr/share/qt4/mkspecs/features/include_source_dir.prf \
+		/usr/lib64/libQtXml.prl \
+		/usr/lib64/libQtCore.prl \
+		/usr/lib64/libQtGui.prl
+	$(QMAKE) CONFIG+=debug_and_release -o Makefile ImageLabeler.pro
+/usr/share/qt4/mkspecs/common/g++.conf:
+/usr/share/qt4/mkspecs/common/unix.conf:
+/usr/share/qt4/mkspecs/common/linux.conf:
+/usr/share/qt4/mkspecs/qconfig.pri:
+/usr/share/qt4/mkspecs/modules/qt_phonon.pri:
+/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri:
+/usr/share/qt4/mkspecs/features/qt_functions.prf:
+/usr/share/qt4/mkspecs/features/qt_config.prf:
+/usr/share/qt4/mkspecs/features/exclusive_builds.prf:
+/usr/share/qt4/mkspecs/features/default_pre.prf:
+/usr/share/qt4/mkspecs/features/release.prf:
+/usr/share/qt4/mkspecs/features/debug_and_release.prf:
+/usr/share/qt4/mkspecs/features/default_post.prf:
+/usr/share/qt4/mkspecs/features/warn_on.prf:
+/usr/share/qt4/mkspecs/features/qt.prf:
+/usr/share/qt4/mkspecs/features/unix/thread.prf:
+/usr/share/qt4/mkspecs/features/moc.prf:
+/usr/share/qt4/mkspecs/features/resources.prf:
+/usr/share/qt4/mkspecs/features/uic.prf:
+/usr/share/qt4/mkspecs/features/yacc.prf:
+/usr/share/qt4/mkspecs/features/lex.prf:
+/usr/share/qt4/mkspecs/features/include_source_dir.prf:
+/usr/lib64/libQtXml.prl:
+/usr/lib64/libQtCore.prl:
+/usr/lib64/libQtGui.prl:
+qmake: qmake_all FORCE
+	@$(QMAKE) CONFIG+=debug_and_release -o Makefile ImageLabeler.pro
+
+qmake_all: FORCE
+
+make_default: release-make_default debug-make_default FORCE
+make_first: release-make_first debug-make_first FORCE
+all: release-all debug-all FORCE
+clean: release-clean debug-clean FORCE
+distclean: release-distclean debug-distclean FORCE
+	-$(DEL_FILE) Makefile
+
+check: first
+
+release-mocclean: $(MAKEFILE).Release
+	$(MAKE) -f $(MAKEFILE).Release mocclean
+debug-mocclean: $(MAKEFILE).Debug
+	$(MAKE) -f $(MAKEFILE).Debug mocclean
+mocclean: release-mocclean debug-mocclean
+
+release-mocables: $(MAKEFILE).Release
+	$(MAKE) -f $(MAKEFILE).Release mocables
+debug-mocables: $(MAKEFILE).Debug
+	$(MAKE) -f $(MAKEFILE).Debug mocables
+mocables: release-mocables debug-mocables
+FORCE:
+
+$(MAKEFILE).Release: Makefile
+$(MAKEFILE).Debug: Makefile

+ 224 - 0
Makefile.Debug

@@ -0,0 +1,224 @@
+#############################################################################
+# Makefile for building: ImageLabeler
+# Generated by qmake (2.01a) (Qt 4.7.1) on: Tue Oct 11 14:53:52 2011
+# Project:  ImageLabeler.pro
+# Template: app
+#############################################################################
+
+####### Compiler, tools and options
+
+CC            = gcc
+CXX           = g++
+DEFINES       = -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
+CFLAGS        = -m64 -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
+CXXFLAGS      = -m64 -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
+INCPATH       = -I/usr/share/qt4/mkspecs/default -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtXml -I/usr/include -Idebug
+LINK          = g++
+LFLAGS        = -m64
+LIBS          = $(SUBLIBS)  -L/usr/lib64 -lQtXml -L/usr/lib64 -lQtGui -L/usr/X11R6/lib64 -lQtCore -lpthread 
+AR            = ar cqs
+RANLIB        = 
+QMAKE         = /usr/bin/qmake
+TAR           = tar -cf
+COMPRESS      = gzip -9f
+COPY          = cp -f
+SED           = sed
+COPY_FILE     = $(COPY)
+COPY_DIR      = $(COPY) -r
+STRIP         = strip
+INSTALL_FILE  = install -m 644 -p
+INSTALL_DIR   = $(COPY_DIR)
+INSTALL_PROGRAM = install -m 755 -p
+DEL_FILE      = rm -f
+SYMLINK       = ln -f -s
+DEL_DIR       = rmdir
+MOVE          = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR         = mkdir -p
+
+####### Output directory
+
+OBJECTS_DIR   = debug/
+
+####### Files
+
+SOURCES       = OptionsForm.cpp \
+		ImageDescriptionForm.cpp \
+		functions.cpp \
+		ImageHolder.cpp \
+		ImageLabeler.cpp \
+		main.cpp debug/moc_OptionsForm.cpp \
+		debug/moc_ImageDescriptionForm.cpp \
+		debug/moc_ImageHolder.cpp \
+		debug/moc_ImageLabeler.cpp
+OBJECTS       = debug/OptionsForm.o \
+		debug/ImageDescriptionForm.o \
+		debug/functions.o \
+		debug/ImageHolder.o \
+		debug/ImageLabeler.o \
+		debug/main.o \
+		debug/moc_OptionsForm.o \
+		debug/moc_ImageDescriptionForm.o \
+		debug/moc_ImageHolder.o \
+		debug/moc_ImageLabeler.o
+DIST          = /usr/share/qt4/mkspecs/common/g++.conf \
+		/usr/share/qt4/mkspecs/common/unix.conf \
+		/usr/share/qt4/mkspecs/common/linux.conf \
+		/usr/share/qt4/mkspecs/qconfig.pri \
+		/usr/share/qt4/mkspecs/modules/qt_phonon.pri \
+		/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \
+		/usr/share/qt4/mkspecs/features/qt_functions.prf \
+		/usr/share/qt4/mkspecs/features/qt_config.prf \
+		/usr/share/qt4/mkspecs/features/exclusive_builds.prf \
+		/usr/share/qt4/mkspecs/features/default_pre.prf \
+		/usr/share/qt4/mkspecs/features/debug.prf \
+		/usr/share/qt4/mkspecs/features/debug_and_release.prf \
+		/usr/share/qt4/mkspecs/features/default_post.prf \
+		/usr/share/qt4/mkspecs/features/build_pass.prf \
+		/usr/share/qt4/mkspecs/features/warn_on.prf \
+		/usr/share/qt4/mkspecs/features/qt.prf \
+		/usr/share/qt4/mkspecs/features/unix/thread.prf \
+		/usr/share/qt4/mkspecs/features/moc.prf \
+		/usr/share/qt4/mkspecs/features/resources.prf \
+		/usr/share/qt4/mkspecs/features/uic.prf \
+		/usr/share/qt4/mkspecs/features/yacc.prf \
+		/usr/share/qt4/mkspecs/features/lex.prf \
+		/usr/share/qt4/mkspecs/features/include_source_dir.prf \
+		ImageLabeler.pro
+QMAKE_TARGET  = ImageLabeler
+DESTDIR       = 
+TARGET        = ImageLabeler
+
+first: all
+####### Implicit rules
+
+.SUFFIXES: .o .c .cpp .cc .cxx .C
+
+.cpp.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cc.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cxx.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.C.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
+
+####### Build rules
+
+all: Makefile.Debug $(TARGET)
+
+$(TARGET):  $(OBJECTS)  
+	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
+
+qmake:  FORCE
+	@$(QMAKE) CONFIG+=debug_and_release -o Makefile.Debug ImageLabeler.pro
+
+dist: 
+	@$(CHK_DIR_EXISTS) debug/ImageLabeler1.0.0 || $(MKDIR) debug/ImageLabeler1.0.0 
+	$(COPY_FILE) --parents $(SOURCES) $(DIST) debug/ImageLabeler1.0.0/ && $(COPY_FILE) --parents OptionsForm.h ImageDescriptionForm.h functions.h ImageHolder.h ImageLabeler.h debug/ImageLabeler1.0.0/ && $(COPY_FILE) --parents OptionsForm.cpp ImageDescriptionForm.cpp functions.cpp ImageHolder.cpp ImageLabeler.cpp main.cpp debug/ImageLabeler1.0.0/ && (cd `dirname debug/ImageLabeler1.0.0` && $(TAR) ImageLabeler1.0.0.tar ImageLabeler1.0.0 && $(COMPRESS) ImageLabeler1.0.0.tar) && $(MOVE) `dirname debug/ImageLabeler1.0.0`/ImageLabeler1.0.0.tar.gz . && $(DEL_FILE) -r debug/ImageLabeler1.0.0
+
+
+clean:compiler_clean 
+	-$(DEL_FILE) $(OBJECTS)
+	-$(DEL_FILE) *~ core *.core
+
+
+####### Sub-libraries
+
+distclean: clean
+	-$(DEL_FILE) $(TARGET) 
+	-$(DEL_FILE) Makefile.Debug
+
+
+check: first
+
+mocclean: compiler_moc_header_clean compiler_moc_source_clean
+
+mocables: compiler_moc_header_make_all compiler_moc_source_make_all
+
+compiler_moc_header_make_all: debug/moc_OptionsForm.cpp debug/moc_ImageDescriptionForm.cpp debug/moc_ImageHolder.cpp debug/moc_ImageLabeler.cpp
+compiler_moc_header_clean:
+	-$(DEL_FILE) debug/moc_OptionsForm.cpp debug/moc_ImageDescriptionForm.cpp debug/moc_ImageHolder.cpp debug/moc_ImageLabeler.cpp
+debug/moc_OptionsForm.cpp: OptionsForm.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) OptionsForm.h -o debug/moc_OptionsForm.cpp
+
+debug/moc_ImageDescriptionForm.cpp: ImageDescriptionForm.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) ImageDescriptionForm.h -o debug/moc_ImageDescriptionForm.cpp
+
+debug/moc_ImageHolder.cpp: ImageHolder.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) ImageHolder.h -o debug/moc_ImageHolder.cpp
+
+debug/moc_ImageLabeler.cpp: ImageHolder.h \
+		ImageDescriptionForm.h \
+		ImageLabeler.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) ImageLabeler.h -o debug/moc_ImageLabeler.cpp
+
+compiler_rcc_make_all:
+compiler_rcc_clean:
+compiler_image_collection_make_all: qmake_image_collection.cpp
+compiler_image_collection_clean:
+	-$(DEL_FILE) qmake_image_collection.cpp
+compiler_moc_source_make_all:
+compiler_moc_source_clean:
+compiler_uic_make_all:
+compiler_uic_clean:
+compiler_yacc_decl_make_all:
+compiler_yacc_decl_clean:
+compiler_yacc_impl_make_all:
+compiler_yacc_impl_clean:
+compiler_lex_make_all:
+compiler_lex_clean:
+compiler_clean: compiler_moc_header_clean 
+
+####### Compile
+
+debug/OptionsForm.o: OptionsForm.cpp OptionsForm.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/OptionsForm.o OptionsForm.cpp
+
+debug/ImageDescriptionForm.o: ImageDescriptionForm.cpp ImageDescriptionForm.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/ImageDescriptionForm.o ImageDescriptionForm.cpp
+
+debug/functions.o: functions.cpp functions.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/functions.o functions.cpp
+
+debug/ImageHolder.o: ImageHolder.cpp ImageHolder.h \
+		functions.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/ImageHolder.o ImageHolder.cpp
+
+debug/ImageLabeler.o: ImageLabeler.cpp ImageLabeler.h \
+		ImageHolder.h \
+		ImageDescriptionForm.h \
+		functions.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/ImageLabeler.o ImageLabeler.cpp
+
+debug/main.o: main.cpp ImageLabeler.h \
+		ImageHolder.h \
+		ImageDescriptionForm.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/main.o main.cpp
+
+debug/moc_OptionsForm.o: debug/moc_OptionsForm.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/moc_OptionsForm.o debug/moc_OptionsForm.cpp
+
+debug/moc_ImageDescriptionForm.o: debug/moc_ImageDescriptionForm.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/moc_ImageDescriptionForm.o debug/moc_ImageDescriptionForm.cpp
+
+debug/moc_ImageHolder.o: debug/moc_ImageHolder.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/moc_ImageHolder.o debug/moc_ImageHolder.cpp
+
+debug/moc_ImageLabeler.o: debug/moc_ImageLabeler.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/moc_ImageLabeler.o debug/moc_ImageLabeler.cpp
+
+####### Install
+
+install:   FORCE
+
+uninstall:   FORCE
+
+FORCE:
+

+ 224 - 0
Makefile.Release

@@ -0,0 +1,224 @@
+#############################################################################
+# Makefile for building: ImageLabeler
+# Generated by qmake (2.01a) (Qt 4.7.1) on: Tue Oct 11 14:53:52 2011
+# Project:  ImageLabeler.pro
+# Template: app
+#############################################################################
+
+####### Compiler, tools and options
+
+CC            = gcc
+CXX           = g++
+DEFINES       = -DQT_NO_DEBUG -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
+CFLAGS        = -m64 -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES)
+CXXFLAGS      = -m64 -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES)
+INCPATH       = -I/usr/share/qt4/mkspecs/default -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtXml -I/usr/include -Irelease
+LINK          = g++
+LFLAGS        = -m64 -Wl,-O1
+LIBS          = $(SUBLIBS)  -L/usr/lib64 -lQtXml -L/usr/lib64 -lQtGui -L/usr/X11R6/lib64 -lQtCore -lpthread 
+AR            = ar cqs
+RANLIB        = 
+QMAKE         = /usr/bin/qmake
+TAR           = tar -cf
+COMPRESS      = gzip -9f
+COPY          = cp -f
+SED           = sed
+COPY_FILE     = $(COPY)
+COPY_DIR      = $(COPY) -r
+STRIP         = strip
+INSTALL_FILE  = install -m 644 -p
+INSTALL_DIR   = $(COPY_DIR)
+INSTALL_PROGRAM = install -m 755 -p
+DEL_FILE      = rm -f
+SYMLINK       = ln -f -s
+DEL_DIR       = rmdir
+MOVE          = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR         = mkdir -p
+
+####### Output directory
+
+OBJECTS_DIR   = release/
+
+####### Files
+
+SOURCES       = OptionsForm.cpp \
+		ImageDescriptionForm.cpp \
+		functions.cpp \
+		ImageHolder.cpp \
+		ImageLabeler.cpp \
+		main.cpp release/moc_OptionsForm.cpp \
+		release/moc_ImageDescriptionForm.cpp \
+		release/moc_ImageHolder.cpp \
+		release/moc_ImageLabeler.cpp
+OBJECTS       = release/OptionsForm.o \
+		release/ImageDescriptionForm.o \
+		release/functions.o \
+		release/ImageHolder.o \
+		release/ImageLabeler.o \
+		release/main.o \
+		release/moc_OptionsForm.o \
+		release/moc_ImageDescriptionForm.o \
+		release/moc_ImageHolder.o \
+		release/moc_ImageLabeler.o
+DIST          = /usr/share/qt4/mkspecs/common/g++.conf \
+		/usr/share/qt4/mkspecs/common/unix.conf \
+		/usr/share/qt4/mkspecs/common/linux.conf \
+		/usr/share/qt4/mkspecs/qconfig.pri \
+		/usr/share/qt4/mkspecs/modules/qt_phonon.pri \
+		/usr/share/qt4/mkspecs/modules/qt_webkit_version.pri \
+		/usr/share/qt4/mkspecs/features/qt_functions.prf \
+		/usr/share/qt4/mkspecs/features/qt_config.prf \
+		/usr/share/qt4/mkspecs/features/exclusive_builds.prf \
+		/usr/share/qt4/mkspecs/features/default_pre.prf \
+		/usr/share/qt4/mkspecs/features/release.prf \
+		/usr/share/qt4/mkspecs/features/debug_and_release.prf \
+		/usr/share/qt4/mkspecs/features/default_post.prf \
+		/usr/share/qt4/mkspecs/features/build_pass.prf \
+		/usr/share/qt4/mkspecs/features/warn_on.prf \
+		/usr/share/qt4/mkspecs/features/qt.prf \
+		/usr/share/qt4/mkspecs/features/unix/thread.prf \
+		/usr/share/qt4/mkspecs/features/moc.prf \
+		/usr/share/qt4/mkspecs/features/resources.prf \
+		/usr/share/qt4/mkspecs/features/uic.prf \
+		/usr/share/qt4/mkspecs/features/yacc.prf \
+		/usr/share/qt4/mkspecs/features/lex.prf \
+		/usr/share/qt4/mkspecs/features/include_source_dir.prf \
+		ImageLabeler.pro
+QMAKE_TARGET  = ImageLabeler
+DESTDIR       = 
+TARGET        = ImageLabeler
+
+first: all
+####### Implicit rules
+
+.SUFFIXES: .o .c .cpp .cc .cxx .C
+
+.cpp.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cc.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cxx.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.C.o:
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
+
+####### Build rules
+
+all: Makefile.Release $(TARGET)
+
+$(TARGET):  $(OBJECTS)  
+	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
+
+qmake:  FORCE
+	@$(QMAKE) CONFIG+=debug_and_release -o Makefile.Release ImageLabeler.pro
+
+dist: 
+	@$(CHK_DIR_EXISTS) release/ImageLabeler1.0.0 || $(MKDIR) release/ImageLabeler1.0.0 
+	$(COPY_FILE) --parents $(SOURCES) $(DIST) release/ImageLabeler1.0.0/ && $(COPY_FILE) --parents OptionsForm.h ImageDescriptionForm.h functions.h ImageHolder.h ImageLabeler.h release/ImageLabeler1.0.0/ && $(COPY_FILE) --parents OptionsForm.cpp ImageDescriptionForm.cpp functions.cpp ImageHolder.cpp ImageLabeler.cpp main.cpp release/ImageLabeler1.0.0/ && (cd `dirname release/ImageLabeler1.0.0` && $(TAR) ImageLabeler1.0.0.tar ImageLabeler1.0.0 && $(COMPRESS) ImageLabeler1.0.0.tar) && $(MOVE) `dirname release/ImageLabeler1.0.0`/ImageLabeler1.0.0.tar.gz . && $(DEL_FILE) -r release/ImageLabeler1.0.0
+
+
+clean:compiler_clean 
+	-$(DEL_FILE) $(OBJECTS)
+	-$(DEL_FILE) *~ core *.core
+
+
+####### Sub-libraries
+
+distclean: clean
+	-$(DEL_FILE) $(TARGET) 
+	-$(DEL_FILE) Makefile.Release
+
+
+check: first
+
+mocclean: compiler_moc_header_clean compiler_moc_source_clean
+
+mocables: compiler_moc_header_make_all compiler_moc_source_make_all
+
+compiler_moc_header_make_all: release/moc_OptionsForm.cpp release/moc_ImageDescriptionForm.cpp release/moc_ImageHolder.cpp release/moc_ImageLabeler.cpp
+compiler_moc_header_clean:
+	-$(DEL_FILE) release/moc_OptionsForm.cpp release/moc_ImageDescriptionForm.cpp release/moc_ImageHolder.cpp release/moc_ImageLabeler.cpp
+release/moc_OptionsForm.cpp: OptionsForm.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) OptionsForm.h -o release/moc_OptionsForm.cpp
+
+release/moc_ImageDescriptionForm.cpp: ImageDescriptionForm.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) ImageDescriptionForm.h -o release/moc_ImageDescriptionForm.cpp
+
+release/moc_ImageHolder.cpp: ImageHolder.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) ImageHolder.h -o release/moc_ImageHolder.cpp
+
+release/moc_ImageLabeler.cpp: ImageHolder.h \
+		ImageDescriptionForm.h \
+		ImageLabeler.h
+	/usr/bin/moc $(DEFINES) $(INCPATH) ImageLabeler.h -o release/moc_ImageLabeler.cpp
+
+compiler_rcc_make_all:
+compiler_rcc_clean:
+compiler_image_collection_make_all: qmake_image_collection.cpp
+compiler_image_collection_clean:
+	-$(DEL_FILE) qmake_image_collection.cpp
+compiler_moc_source_make_all:
+compiler_moc_source_clean:
+compiler_uic_make_all:
+compiler_uic_clean:
+compiler_yacc_decl_make_all:
+compiler_yacc_decl_clean:
+compiler_yacc_impl_make_all:
+compiler_yacc_impl_clean:
+compiler_lex_make_all:
+compiler_lex_clean:
+compiler_clean: compiler_moc_header_clean 
+
+####### Compile
+
+release/OptionsForm.o: OptionsForm.cpp OptionsForm.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/OptionsForm.o OptionsForm.cpp
+
+release/ImageDescriptionForm.o: ImageDescriptionForm.cpp ImageDescriptionForm.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/ImageDescriptionForm.o ImageDescriptionForm.cpp
+
+release/functions.o: functions.cpp functions.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/functions.o functions.cpp
+
+release/ImageHolder.o: ImageHolder.cpp ImageHolder.h \
+		functions.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/ImageHolder.o ImageHolder.cpp
+
+release/ImageLabeler.o: ImageLabeler.cpp ImageLabeler.h \
+		ImageHolder.h \
+		ImageDescriptionForm.h \
+		functions.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/ImageLabeler.o ImageLabeler.cpp
+
+release/main.o: main.cpp ImageLabeler.h \
+		ImageHolder.h \
+		ImageDescriptionForm.h
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/main.o main.cpp
+
+release/moc_OptionsForm.o: release/moc_OptionsForm.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/moc_OptionsForm.o release/moc_OptionsForm.cpp
+
+release/moc_ImageDescriptionForm.o: release/moc_ImageDescriptionForm.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/moc_ImageDescriptionForm.o release/moc_ImageDescriptionForm.cpp
+
+release/moc_ImageHolder.o: release/moc_ImageHolder.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/moc_ImageHolder.o release/moc_ImageHolder.cpp
+
+release/moc_ImageLabeler.o: release/moc_ImageLabeler.cpp 
+	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/moc_ImageLabeler.o release/moc_ImageLabeler.cpp
+
+####### Install
+
+install:   FORCE
+
+uninstall:   FORCE
+
+FORCE:
+

+ 79 - 0
OptionsForm.cpp

@@ -0,0 +1,79 @@
+/*
+ * ImageDescriptionForm.cpp
+ *
+ *  Created on: Oct 11, 2011
+ *      Author: Gapchich Vlad
+ */
+
+#include "OptionsForm.h"
+
+#include <QCheckBox>
+#include <QPushButton>
+#include <QBoxLayout>
+#include <QMessageBox>
+#include <QApplication>
+#include <QDesktopWidget>
+
+OptionsForm::OptionsForm(QWidget *aParent)
+	: QWidget(aParent)
+{
+	setWindowTitle(tr("Options"));
+
+	layout_v_ = new QVBoxLayout(this);
+	layout_h_ = new QHBoxLayout;
+
+	auto_color_generation_ = new QCheckBox(this);
+	auto_color_generation_->setText(tr("Automatic label color generation"));
+	button_ok_ = new QPushButton(this);
+	button_ok_->setText(tr("OK"));
+	button_cancel_ = new QPushButton(this);
+	button_cancel_->setText(tr("Cancel"));
+
+	layout_v_->addWidget(auto_color_generation_);
+	layout_v_->addLayout(layout_h_);
+
+	layout_h_->addWidget(button_ok_);
+	layout_h_->addWidget(button_cancel_);
+
+	connect(
+		button_ok_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(setOptions())
+		);
+	connect(
+		button_cancel_,
+		SIGNAL(clicked()),
+		this,
+		SLOT(hide())
+		);
+
+	adjustSize();
+	move(QApplication::desktop()->screen()->rect().center() - rect().center());
+}
+
+OptionsForm::~OptionsForm()
+{
+	delete auto_color_generation_;
+	delete button_ok_;
+	delete button_cancel_;
+
+	delete layout_v_;
+}
+
+void
+OptionsForm::setOptions()
+{
+	emit optionsSet();
+	hide();
+}
+
+bool
+OptionsForm::autoColorGeneration()
+{
+	return auto_color_generation_->isChecked();
+}
+
+/*
+ *
+ */

+ 45 - 0
OptionsForm.h

@@ -0,0 +1,45 @@
+/*
+ * ImageDescriptionForm.h
+ *
+ *  Created on: Oct 11, 2011
+ *      Author: Gapchich Vlad
+ */
+
+#ifndef __OPTIONSFORM_H__
+#define __OPTIONSFORM_H__
+
+#include <QWidget>
+
+class QCheckBox;
+class QPushButton;
+class QVBoxLayout;
+class QHBoxLayout;
+
+class OptionsForm : public QWidget {
+	Q_OBJECT
+public:
+	OptionsForm(QWidget *aParent = 0);
+	virtual ~OptionsForm();
+
+	bool autoColorGeneration();
+
+public slots:
+	void setOptions();
+
+signals:
+	void optionsSet();
+
+private:
+	QCheckBox *auto_color_generation_;
+	QPushButton *button_ok_;
+	QPushButton *button_cancel_;
+
+	QVBoxLayout *layout_v_;
+	QHBoxLayout *layout_h_;
+};
+
+#endif /* __OPTIONSFORM_H__ */
+
+/*
+ *
+ */

+ 92 - 0
functions.cpp

@@ -0,0 +1,92 @@
+/*
+ * functions.cpp
+ *
+ *  Created on: Oct 6, 2011
+ *      Author: Gapchich Vladislav
+ */
+
+#include "functions.h"
+
+#include <QString>
+#include <QChar>
+#include <QDomDocument>
+#include <QDomNode>
+#include <QDomText>
+#include <QDebug>
+
+int
+getNumFromString(
+	QString *aString,
+	const QString &aFirstStr,
+	const QString &aSecondStr,
+	bool *anOkFlag
+)
+{
+	int numPos = aString->indexOf(aFirstStr) + aFirstStr.size();
+
+	if (-1 <= numPos) {
+		*anOkFlag = 0;
+		return -1;
+		/* NOTREACHED */
+	}
+
+	int numLength = -1;
+	for (int i = numPos; i < aString->size(); i++) {
+		if (aSecondStr == aString->at(i)) {
+			numLength = i - numPos;
+			break;
+		}
+	}
+
+	if (numLength <= 0) {
+		*anOkFlag = 0;
+		return -1;
+		/* NOTREACHED */
+	}
+
+	QString numString = aString->mid(numPos, numLength);
+	if (numString.isEmpty()) {
+		*anOkFlag = 0;
+		return -1;
+		/* NOTREACHED */
+	}
+
+	bool ok = 0;
+	int num = numString.toInt(&ok, 10);
+
+	if (!ok) {
+		*anOkFlag = 0;
+		return -1;
+		/* NOTREACHED */
+	}
+
+	*anOkFlag = 1;
+	return num;
+}
+
+/*
+ * adds given suffix to the file name and removes path from it
+ */
+QString alterFileName(const QString &aFilename, const QString &aSuffix)
+{
+	/* altering the name of a new file */
+	QString newFileName = aFilename;
+	int dotPos = newFileName.lastIndexOf('.');
+
+	if (-1 == dotPos)
+		dotPos = newFileName.size();
+	else
+		newFileName.remove(dotPos, newFileName.size() - dotPos);
+
+	newFileName.insert(dotPos, aSuffix);
+	qDebug() << newFileName;
+
+	int slashPos = newFileName.lastIndexOf('/');
+	newFileName.remove(0, slashPos);
+
+	return newFileName;
+}
+
+/*
+ *
+ */

+ 23 - 0
functions.h

@@ -0,0 +1,23 @@
+/*
+ * functions.h
+ *
+ *  Created on: Oct 6, 2011
+ *      Author: Gapchich Vladislav
+ */
+
+#ifndef FUNCTIONS_H_
+#define FUNCTIONS_H_
+
+class QString;
+class QChar;
+class QDomDocument;
+
+int getNumFromString(
+	QString *aString,
+	const QString &aFirstStr,
+	const QString &aSecondStr,
+	bool *anOkFlag
+	);
+QString alterFileName(const QString &aFilename, const QString &aSuffix);
+
+#endif /* __FUNCTIONS_H__ */

+ 17 - 0
main.cpp

@@ -0,0 +1,17 @@
+#include <QApplication>
+#include <QTextCodec>
+
+#include "ImageLabeler.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication app(argc, argv);
+    app.setApplicationName(QObject::tr("Image Labeler"));
+
+    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
+
+    ImageLabeler imageLabeler;
+    imageLabeler.show();
+
+    return app.exec();
+}