Index: trunk/src/mainwindow.cpp
===================================================================
--- trunk/src/mainwindow.cpp	(revision 14)
+++ trunk/src/mainwindow.cpp	(revision 15)
@@ -38,73 +38,17 @@
 	// TODO: Loading of saved window state
 QRect rect = geometry();
-    rect.moveCenter(QApplication::desktop()->screenGeometry(QApplication::desktop()->primaryScreen()).center());
+	rect.moveCenter(QApplication::desktop()->screenGeometry(QApplication::desktop()->primaryScreen()).center());
 	setGeometry(rect);
 	qsrand(QDateTime().currentDateTime().toTime_t());
-	PrepareTable();
-}
-
-int MainWindow::rand(int min, int max)
-{
-	return min + (int)(((float)qrand() / RAND_MAX) * max);
-}
-
-void MainWindow::PrepareTable()
-{
-QTableWidgetItem *item;
-	for (int y = 0; y < spinCities->value(); y++) {
-		item = new QTableWidgetItem(trUtf8("Город ") + QVariant(y + 1).toString());
-		tableTask->setVerticalHeaderItem(y,item);
-		item = new QTableWidgetItem(trUtf8("Город ") + QVariant(y + 1).toString());
-		tableTask->setHorizontalHeaderItem(y,item);
-		for (int x = 0; x < spinCities->value(); x++) {
-			if (y == x) {
-				item = new QTableWidgetItem("...");
-				item->setFlags(item->flags() ^ Qt::ItemIsEditable);
-			} else {
-				item = new QTableWidgetItem(QVariant(rand(randMin,randMax)).toString());
-QFont font = item->font();
-				font.setBold(true);
-				item->setFont(font);
-			}
-			item->setTextAlignment(Qt::AlignCenter);
-			tableTask->setItem(x,y,item);
-		}
-	}
-	tableTask->resizeRowsToContents();
-	tableTask->resizeColumnsToContents();
+	tspmodel = new CTSPModel();
+	tspmodel->randMin = randMin;
+	tspmodel->randMax = randMax;
+	tspmodel->setNumCities(spinCities->value());
+	taskView->setModel(tspmodel);
 }
 
 void MainWindow::CitiesNumberChanged(int n)
 {
-bool increased = tableTask->rowCount() < n ? true : false;
-	tableTask->setRowCount(n);
-	tableTask->setColumnCount(n);
-	for (int k = 0; k < n; k++)
-//		tableTask->setColumnWidth(k,tableTask->viewport()->width() / n);
-	// If number of cities increased we need to reset headers and set
-	// appropriate sizes for new column and row
-	if (increased) {
-QTableWidgetItem *item = new QTableWidgetItem(trUtf8("Город ") + QVariant(n).toString());
-		tableTask->setVerticalHeaderItem(n - 1,item);
-		item = new QTableWidgetItem(trUtf8("Город ") + QVariant(n).toString());
-		tableTask->setHorizontalHeaderItem(n - 1,item);
-		tableTask->resizeRowToContents(n - 1);
-		tableTask->resizeColumnToContents(n - 1);
-		item = new QTableWidgetItem("...");
-		item->setFlags(item->flags() ^ Qt::ItemIsEditable);
-		tableTask->setItem(spinCities->value() - 1,spinCities->value() - 1,item);
-		for (int k = 0; k < spinCities->value() - 1; k++) {
-			item = new QTableWidgetItem(QVariant(rand(randMin, randMax)).toString());
-QFont font = item->font();
-			font.setBold(true);
-			item->setFont(font);
-			tableTask->setItem(k,spinCities->value() - 1,item);
-			item = new QTableWidgetItem(QVariant(rand(randMin, randMax)).toString());
-			font = item->font();
-			font.setBold(true);
-			item->setFont(font);
-			tableTask->setItem(spinCities->value() - 1,k,item);
-		}
-	}
+	tspmodel->setNumCities(n);
 }
 
@@ -122,8 +66,5 @@
 void MainWindow::Random()
 {
-	for (int y = 0; y < spinCities->value(); y++)
-		for (int x = 0; x < spinCities->value(); x++)
-			if (x != y)
-				tableTask->item(x,y)->setText(QVariant(rand(randMin, randMax)).toString());
+	tspmodel->randomize();
 }
 
@@ -133,19 +74,13 @@
 tMatrix matrix;
 double *row;
+int n = spinCities->value();
 bool ok;
-	for (int x = 0; x < spinCities->value(); x++) {
-		row = new double[spinCities->value()];
-		for (int y = 0; y < spinCities->value(); y++) {
-			if (x == y)
-				row[y] = infinity;
-			else {
-				row[y] = tableTask->item(x,y)->text().toDouble(&ok);
-				if (!ok) {
-					QMessageBox(QMessageBox::Critical,trUtf8("Ошибка в данных"),QString(trUtf8("Ошибка в ячейке [Строка %1; Колонка %2]: Неверный формат данных.")).arg(x + 1).arg(y + 1),QMessageBox::Ok,this).exec();
-					return;
-				} else if (row[y] < 0) {
-					QMessageBox(QMessageBox::Critical,trUtf8("Ошибка в данных"),QString(trUtf8("Ошибка в ячейке [Строка %1; Колонка %2]: Значение не может быть меньше нуля.")).arg(x + 1).arg(y + 1),QMessageBox::Ok,this).exec();
-					return;
-				}
+	for (int r = 0; r < n; r++) {
+		row = new double[n];
+		for (int c = 0; c < n; c++) {
+			row[c] = tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok);
+			if (!ok) {
+				QMessageBox(QMessageBox::Critical,trUtf8("Ошибка в данных"),QString(trUtf8("Ошибка в ячейке [Строка %1; Колонка %2]: Неверный формат данных.")).arg(r + 1).arg(c + 1),QMessageBox::Ok,this).exec();
+				return;
 			}
 		}
Index: trunk/src/mainwindow.h
===================================================================
--- trunk/src/mainwindow.h	(revision 14)
+++ trunk/src/mainwindow.h	(revision 15)
@@ -29,4 +29,5 @@
 #include "settingsdialog.h"
 #include "tspsolver.h"
+#include "tspmodel.h"
 
 class MainWindow: public QMainWindow, Ui::MainWindow
@@ -41,6 +42,5 @@
 	void CitiesNumberChanged(int n);
 private:
-	void PrepareTable();
-	int rand(int, int);
+	CTSPModel *tspmodel;
 	int randMin;
 	int randMax;
Index: trunk/src/tspmodel.cpp
===================================================================
--- trunk/src/tspmodel.cpp	(revision 14)
+++ trunk/src/tspmodel.cpp	(revision 15)
@@ -1,5 +1,5 @@
 /*
  *  TSPSG - TSP Solver and Generator
- *  Copyright (C) 2007 L¸ppa <lacontacts[at]gmail[dot]com>
+ *  Copyright (C) 2007 Lёppa <lacontacts[at]gmail[dot]com>
  *
  *  $Id$
@@ -26,5 +26,5 @@
 
 CTSPModel::CTSPModel(QObject *parent)
-	: QAbstractTableModel(parent), randMin(1), randMax(10)
+	: QAbstractTableModel(parent), randMin(1), randMax(10), nCities(0)
 {
 }
@@ -48,5 +48,5 @@
 {
 	if (role == Qt::DisplayRole)
-		return trUtf8("Ãîðîä %1").arg(section + 1);
+		return trUtf8("Город %1").arg(section + 1);
 	return QVariant();
 }
@@ -58,12 +58,19 @@
 	if (role == Qt::TextAlignmentRole)
 		return int(Qt::AlignCenter);
-	else if (role == Qt::DisplayRole) {
-		if (index.row() == index.column())
-			return trUtf8("---");
+	else if (role == Qt::FontRole) {
+QFont font;
+		font.setBold(true);
+		return font;
+	} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
 		if (index.row() < nCities && index.column() < nCities)
-			return table.at(index.row())->at(index.column());
+			if (table[index.row()][index.column()] == INFINITY)
+				return trUtf8(INFSTR);
+			else
+				// HACK: Converting to string to prevent spinbox in edit mode
+				return QVariant(table[index.row()][index.column()]).toString();
 		else
 			return QVariant();
-	}
+	} else if (role == Qt::UserRole)
+		return table[index.row()][index.column()];
 	return QVariant();
 }
@@ -71,5 +78,21 @@
 bool CTSPModel::setData(const QModelIndex &index, const QVariant &value, int role)
 {
-	return true;
+	if (!index.isValid())
+		return false;
+	if (role == Qt::EditRole && index.row() != index.column()) {
+		if (value.toString().compare(INFSTR) == 0)
+			table[index.row()][index.column()] = INFINITY;
+		else {
+bool ok;
+double tmp = value.toDouble(&ok);
+			if (!ok || tmp < 0)
+				return false;
+			else
+				table[index.row()][index.column()] = tmp;
+		}
+		emit dataChanged(index,index);
+		return true;
+	}
+	return false;
 }
 
@@ -77,5 +100,5 @@
 {
 Qt::ItemFlags flags = QAbstractItemModel::flags(index);
-	if (index.row() == index.column())
+	if (index.row() != index.column())
 		flags |= Qt::ItemIsEditable;
 	return flags;
@@ -89,19 +112,34 @@
 void CTSPModel::setNumCities(int n)
 {
+	if (n == nCities)
+		return;
+	emit layoutAboutToBeChanged();
 	if (n > nCities) {
-		foreach(QList<double> *row,table) {
-			for (int k = nCities; k < n; k++)
-				row->append(rand(randMin,randMax));
+		for (int r = 0; r < nCities; r++) {
+			for (int c = nCities; c < n; c++)
+				if (r == c)
+					table[r][c] = INFINITY;
+				else
+					table[r][c] = rand(randMin,randMax);
 		}
-		for (int k = nCities; k < n; k++) {
-QList<double> *row = new QList<double>[n];
-			foreach(double cell,*row)
-				cell = rand(randMin,randMax);
-			table.append(row);
+		for (int r = nCities; r < n; r++) {
+			for (int c = 0; c < n; c++)
+				if (r == c)
+					table[r][c] = INFINITY;
+				else
+					table[r][c] = rand(randMin,randMax);
 		}
-	} else if (n < nCities) {
-		// TODO: Shrinking table
 	}
 	nCities = n;
+	emit layoutChanged();
 }
 
+void CTSPModel::randomize()
+{
+	for (int r = 0; r < nCities; r++)
+		for (int c = 0; c < nCities; c++)
+			if (r != c)
+				table[r][c] = rand(randMin,randMax);
+	emit dataChanged(index(0,0),index(nCities - 1,nCities - 1));
+}
+
Index: trunk/src/tspmodel.h
===================================================================
--- trunk/src/tspmodel.h	(revision 14)
+++ trunk/src/tspmodel.h	(revision 15)
@@ -1,5 +1,5 @@
 /*
  *  TSPSG - TSP Solver and Generator
- *  Copyright (C) 2007 L¸ppa <lacontacts[at]gmail[dot]com>
+ *  Copyright (C) 2007 Lёppa <lacontacts[at]gmail[dot]com>
  *
  *  $Id$
@@ -25,4 +25,14 @@
 #define TSPMODEL_H
 
+// Decided, that static array with 100 of cities maximum hard limit
+// will be enough for most cases, but the code will be simplier than
+// when using dynamic lists. If you need more, just change this value
+// and recompile the program ;-)
+#define MAX_CITIES 100
+// This value means infinity :-)
+#define INFINITY 1.7E+308
+// This is string, which represents infinite value in table
+#define INFSTR "---"
+
 #include <QAbstractTableModel>
 
@@ -40,8 +50,9 @@
 	int numCities() const;
 	void setNumCities(int);
+	void randomize();
 	int randMin;
 	int randMax;
 private:
-	QList<QList<double> *> table;
+	double table[MAX_CITIES][MAX_CITIES];
 	int nCities;
 	int rand(int, int);
Index: trunk/src/tspsolver.cpp
===================================================================
--- trunk/src/tspsolver.cpp	(revision 14)
+++ trunk/src/tspsolver.cpp	(revision 15)
@@ -23,4 +23,5 @@
 
 #include "tspsolver.h"
+#include "tspmodel.h"
 
 CTSPSolver::CTSPSolver()
@@ -30,18 +31,18 @@
 double CTSPSolver::findMinInRow(int nRow, tMatrix matrix)
 {
-double min = infinity;
+double min = INFINITY;
 	for (int k = 0; k < nCities; k++)
 		if (min > matrix[nRow][k])
 			min = matrix[nRow][k];
-	return min == infinity ? 0 : min;
+	return min == INFINITY ? 0 : min;
 }
 
 double CTSPSolver::findMinInCol(int nCol, tMatrix matrix)
 {
-double min = infinity;
+double min = INFINITY;
 	for (int k = 0; k < nCities; k++)
 		if (min > matrix[k][nCol])
 			min = matrix[k][nCol];
-	return min == infinity ? 0 : min;
+	return min == INFINITY ? 0 : min;
 }
 
Index: trunk/src/tspsolver.h
===================================================================
--- trunk/src/tspsolver.h	(revision 14)
+++ trunk/src/tspsolver.h	(revision 15)
@@ -27,9 +27,7 @@
 #include <QtCore>
 
-const double infinity = 1.7E+308;
-
 typedef QList<double *> tMatrix;
 
-// Structure represent one step of solving
+// This structure represents one step of solving
 // The tree of such elements will represent the solving process
 struct sStep {
Index: trunk/ui/mainwindow.ui
===================================================================
--- trunk/ui/mainwindow.ui	(revision 14)
+++ trunk/ui/mainwindow.ui	(revision 15)
@@ -117,5 +117,5 @@
         </item>
         <item>
-         <widget class="QTableWidget" name="tableTask" >
+         <widget class="QTableView" name="taskView" >
           <property name="statusTip" >
            <string>Стоимости переходов/переездов из города в город</string>
@@ -124,20 +124,4 @@
            <enum>QAbstractItemView::NoSelection</enum>
           </property>
-          <property name="rowCount" >
-           <number>5</number>
-          </property>
-          <property name="columnCount" >
-           <number>5</number>
-          </property>
-          <row/>
-          <row/>
-          <row/>
-          <row/>
-          <row/>
-          <column/>
-          <column/>
-          <column/>
-          <column/>
-          <column/>
          </widget>
         </item>
