Index: trunk/src/globals.h
===================================================================
--- trunk/src/globals.h	(revision 49)
+++ trunk/src/globals.h	(revision 50)
@@ -38,4 +38,5 @@
 #define DEF_RAND_MIN 1
 #define DEF_RAND_MAX 10
+#define DEF_NUM_CITIES 5
 #define DEF_OFFSET 100
 #define DEF_FONT_FAMILY "Courier New"
@@ -56,4 +57,6 @@
 #define ZKT_VERSION quint8(1)
 
+// Maximum available number of cities
+#define MAX_NUM_CITIES 20
 // This value means infinity :-)
 #ifndef INFINITY
@@ -63,3 +66,9 @@
 #define INFSTR "---"
 
+// Let's check that default number of cities is sane (<= MAX_NUM_CITIES)
+#if DEF_NUM_CITIES > MAX_NUM_CITIES
+	#undef DEF_NUM_CITIES
+	#define DEF_NUM_CITIES MAX_NUM_CITIES
+#endif
+
 #endif // GLOBALS_H
Index: trunk/src/mainwindow.cpp
===================================================================
--- trunk/src/mainwindow.cpp	(revision 49)
+++ trunk/src/mainwindow.cpp	(revision 50)
@@ -46,8 +46,9 @@
 	actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
 	loadLangList();
-	spinCities->setValue(settings->value("NumCities",5).toInt());
+	spinCities->setMaximum(MAX_NUM_CITIES);
 	actionSettingsLanguageAutodetect->setChecked(settings->value("Language","").toString().isEmpty());
 	connect(actionFileNew,SIGNAL(triggered()),this,SLOT(actionFileNewTriggered()));
 	connect(actionFileOpen,SIGNAL(triggered()),this,SLOT(actionFileOpenTriggered()));
+	connect(actionFileSave,SIGNAL(triggered()),this,SLOT(actionFileSaveTriggered()));
 	connect(actionFileSaveAsTask,SIGNAL(triggered()),this,SLOT(actionFileSaveAsTaskTriggered()));
 	connect(actionFileSaveAsSolution,SIGNAL(triggered()),this,SLOT(actionFileSaveAsSolutionTriggered()));
@@ -62,7 +63,8 @@
 	connect(buttonSolve,SIGNAL(clicked()),this,SLOT(buttonSolveClicked()));
 	connect(buttonRandom,SIGNAL(clicked()),this,SLOT(buttonRandomClicked()));
+	connect(buttonBackToTask,SIGNAL(clicked()),this,SLOT(buttonBackToTaskClicked()));
 	connect(spinCities,SIGNAL(valueChanged(int)),this,SLOT(spinCitiesValueChanged(int)));
+	setCentralWidget(tabWidget);
 QRect rect = geometry();
-	setCentralWidget(tabWidget);
 #ifndef Q_OS_WINCE
 	if (settings->value("SavePos",false).toBool()) {
@@ -82,22 +84,22 @@
 	qsrand(QDateTime().currentDateTime().toTime_t());
 	tspmodel = new CTSPModel();
-	tspmodel->setNumCities(spinCities->value());
-	taskView->setModel(tspmodel);
 	connect(tspmodel,SIGNAL(numCitiesChanged(int)),this,SLOT(numCitiesChanged(int)));
 	connect(tspmodel,SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(dataChanged()));
 	connect(tspmodel,SIGNAL(layoutChanged()),this,SLOT(dataChanged()));
-	if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1)))) {
+	if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1))))
 		setFileName(QCoreApplication::arguments().at(1));
-		setWindowModified(false);
-	} else
+	else {
 		setFileName();
-#ifdef Q_OS_WINCE
+		spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt());
+	}
+	taskView->setModel(tspmodel);
+	setWindowModified(false);
 	taskView->resizeColumnsToContents();
 	taskView->resizeRowsToContents();
-#endif // Q_OS_WINCE
 }
 
 void MainWindow::enableSolutionActions(bool enable)
 {
+	buttonSaveSolution->setEnabled(enable);
 	actionFileSaveAsSolution->setEnabled(enable);
 	solutionText->setEnabled(enable);
@@ -173,9 +175,6 @@
 void MainWindow::spinCitiesValueChanged(int n)
 {
-#ifdef Q_OS_WINCE
 int count = tspmodel->numCities();
-#endif // Q_OS_WINCE
 	tspmodel->setNumCities(n);
-#ifdef Q_OS_WINCE
 	if (n > count)
 		for (int k = count; k < n; k++) {
@@ -183,5 +182,4 @@
 			taskView->resizeRowToContents(k);
 		}
-#endif // Q_OS_WINCE
 }
 
@@ -204,8 +202,6 @@
 		return;
 	tspmodel->clear();
-#ifdef Q_OS_WINCE
 	taskView->resizeColumnsToContents();
 	taskView->resizeRowsToContents();
-#endif
 	setFileName();
 	setWindowModified(false);
@@ -238,8 +234,6 @@
 	}
 	setFileName(files.first());
-#ifdef Q_OS_WINCE
 	taskView->resizeColumnsToContents();
 	taskView->resizeRowsToContents();
-#endif
 	tabWidget->setCurrentIndex(0);
 	setWindowModified(false);
@@ -247,4 +241,16 @@
 	enableSolutionActions(false);
 	QApplication::restoreOverrideCursor();
+}
+
+void MainWindow::actionFileSaveTriggered()
+{
+	if ((fileName == trUtf8("Untitled") + ".tspt") || (!fileName.endsWith(".tspt",Qt::CaseInsensitive)))
+		saveTask();
+	else {
+		QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+		if (tspmodel->saveTask(fileName))
+			setWindowModified(false);
+		QApplication::restoreOverrideCursor();
+	}
 }
 
@@ -350,8 +356,11 @@
 	tspmodel->randomize();
 	setWindowModified(true);
-#ifdef Q_OS_WINCE
 	taskView->resizeColumnsToContents();
 	taskView->resizeRowsToContents();
-#endif // Q_OS_WINCE
+}
+
+void MainWindow::buttonBackToTaskClicked()
+{
+	tabWidget->setCurrentIndex(0);
 }
 
@@ -395,5 +404,5 @@
 	}
 CTSPSolver solver;
-sStep *root = solver.solve(spinCities->value(),matrix);
+sStep *root = solver.solve(n,matrix,this);
 	if (!root)
 		return;
@@ -542,4 +551,6 @@
 void MainWindow::numCitiesChanged(int nCities)
 {
+	blockSignals(true);
 	spinCities->setValue(nCities);
-}
+	blockSignals(false);
+}
Index: trunk/src/mainwindow.h
===================================================================
--- trunk/src/mainwindow.h	(revision 49)
+++ trunk/src/mainwindow.h	(revision 50)
@@ -46,4 +46,5 @@
 	void actionFileNewTriggered();
 	void actionFileOpenTriggered();
+	void actionFileSaveTriggered();
 	void actionFileSaveAsTaskTriggered();
 	void actionFileSaveAsSolutionTriggered();
@@ -58,4 +59,5 @@
 	void buttonSolveClicked();
 	void buttonRandomClicked();
+	void buttonBackToTaskClicked();
 	void spinCitiesValueChanged(int);
 	void numCitiesChanged(int);
@@ -63,5 +65,7 @@
 private:
 	QSettings *settings;
+#ifndef Q_OS_WINCE
 	QPrinter *printer;
+#endif // Q_OS_WINCE
 	CTSPModel *tspmodel;
 	QString fileName;
Index: trunk/src/tspmodel.cpp
===================================================================
--- trunk/src/tspmodel.cpp	(revision 49)
+++ trunk/src/tspmodel.cpp	(revision 50)
@@ -206,16 +206,18 @@
 	if (loadError(ds->status()))
 		return false;
-	// Cities number
+	// Number of cities
 quint16 size;
 	*ds >> size;
 	if (loadError(ds->status()))
 		return false;
-	if (size < 3) {
+	if ((size < 3) || (size > MAX_NUM_CITIES)) {
 		QMessageBox(QMessageBox::Critical,trUtf8("Task Load"),trUtf8("Unable to load task:") + "\n" + trUtf8("Unexpected data read.\nFile is possibly corrupted."),QMessageBox::Ok).exec();
 		return false;
 	}
-	if (nCities != size)
+	if (nCities != size) {
+		setNumCities(size);
 		emit numCitiesChanged(size);
-	// Costs
+	}
+	// Travel costs
 	for (int r = 0; r < size; r++)
 		for (int c = 0; c < size; c++)
@@ -246,5 +248,5 @@
 		return false;
 	}
-	// Cities number
+	// Number of cities
 quint8 size;
 	ds->readRawData(reinterpret_cast<char *>(&size),1);
@@ -255,7 +257,9 @@
 		return false;
 	}
-	if (nCities != size)
+	if (nCities != size) {
+		setNumCities(size);
 		emit numCitiesChanged(size);
-	// Costs
+	}
+	// Travel costs
 double val;
 	for (int r = 0; r < 5; r++)
Index: trunk/src/tspmodel.h
===================================================================
--- trunk/src/tspmodel.h	(revision 49)
+++ trunk/src/tspmodel.h	(revision 50)
@@ -54,6 +54,6 @@
 	quint16 nCities;
 	bool loadError(QDataStream::Status);
+	bool loadTSPT(QDataStream *);
 	bool loadZKT(QDataStream *);
-	bool loadTSPT(QDataStream *);
 	int rand(int, int) const;
 };
Index: trunk/src/tspsolver.cpp
===================================================================
--- trunk/src/tspsolver.cpp	(revision 49)
+++ trunk/src/tspsolver.cpp	(revision 50)
@@ -97,5 +97,6 @@
 	for (int r = 0; r < nCities; r++)
 		for (int c = 0; c < nCities; c++)
-			if ((matrix[r][c] == 0) && !forbidden.values(r).contains(c)) {
+//			if ((matrix[r][c] == 0) && !forbidden.values(r).contains(c)) {
+			if (matrix[r][c] == 0) {
 				sum = findMinInRow(r,matrix,c) + findMinInCol(c,matrix,r);
 				if (sum > h) {
@@ -154,8 +155,8 @@
 int nRow, nCol;
 	while (route.size() < nCities) {
-		forbidden.clear();
+//		forbidden.clear();
 		step->alts = findCandidate(step->matrix,nRow,nCol,s);
 		while (hasSubCycles(nRow,nCol)) {
-			forbidden[nRow] = nCol;
+//			forbidden[nRow] = nCol;
 			step->matrix[nRow][nCol] = INFINITY;
 			step->price += align(step->matrix);
@@ -204,11 +205,11 @@
 	}
 
-	pd.reset();
+	if (!root && !pd.wasCanceled()) {
+		pd.reset();
+		QMessageBox(QMessageBox::Warning,trUtf8("Solution Result"),trUtf8("Unable to find solution.\nMaybe, this task has no solutions."),QMessageBox::Ok,parent).exec();
+	}
+
 	qApp->processEvents();
 
-	if (!root && !pd.wasCanceled()) {
-		QMessageBox(QMessageBox::Warning,trUtf8("Solution Result"),trUtf8("This task has no solution."),QMessageBox::Ok,parent).exec();
-	}
-
 	return root;
 }
Index: trunk/src/tspsolver.h
===================================================================
--- trunk/src/tspsolver.h	(revision 49)
+++ trunk/src/tspsolver.h	(revision 50)
@@ -53,5 +53,5 @@
 	sStep *root;
 	QHash<int,int> route;
-	QHash<int,int> forbidden;
+//	QHash<int,int> forbidden;
 	double align(tMatrix &);
 	void cleanup();
Index: trunk/src/version.h
===================================================================
--- trunk/src/version.h	(revision 49)
+++ trunk/src/version.h	(revision 50)
@@ -45,5 +45,5 @@
 #endif // BUILD_NUMBER == 65535
 
-// "Converting" number to string
+// "Converting" x to quoted string
 #define QUOTE_X(x) #x
 #define QUOTE(x) QUOTE_X(x)
