Index: trunk/src/defines.h
===================================================================
--- trunk/src/defines.h	(revision 30)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- *  TSPSG - TSP Solver and Generator
- *  Copyright (C) 2007-2009 Lёppa <contacts[at]oleksii[dot]name>
- *
- *  $Id$
- *  $URL$
- *
- *  This file is part of TSPSG.
- *
- *  TSPSG is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  TSPSG is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with TSPSG.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef DEFINES_H
-#define DEFINES_H
-
-// Default values
-#define DEF_RAND_MIN 1
-#define DEF_RAND_MAX 10
-#define DEF_OFFSET 100
-#define DEF_FONT_FAMILY "Courier New"
-#define DEF_FONT_SIZE 12
-#define DEF_FONT_COLOR Qt::black
-
-// 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 :-)
-#ifndef INFINITY
-	#define INFINITY 1.7E+308
-#endif
-// This is string, which represents infinite value in table
-#define INFSTR "-----"
-
-#endif // DEFINES_H
Index: trunk/src/globals.h
===================================================================
--- trunk/src/globals.h	(revision 31)
+++ trunk/src/globals.h	(revision 31)
@@ -0,0 +1,68 @@
+/*
+ *  TSPSG - TSP Solver and Generator
+ *  Copyright (C) 2007-2009 Lёppa <contacts[at]oleksii[dot]name>
+ *
+ *  $Id$
+ *  $URL$
+ *
+ *  This file is part of TSPSG.
+ *
+ *  TSPSG is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  TSPSG is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with TSPSG.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GLOBALS_H
+#define GLOBALS_H
+
+// INCLUDES
+#include <QtCore>
+#include <QtGui>
+
+// OS detection
+#include "os.h"
+
+// DEFINES
+// Default values
+#define DEF_RAND_MIN 1
+#define DEF_RAND_MAX 10
+#define DEF_OFFSET 100
+#define DEF_FONT_FAMILY "Courier New"
+#define DEF_FONT_SIZE 12
+#define DEF_FONT_COLOR Qt::black
+
+// TSPSG Task file signature - letters TSPT
+#define TSPT quint32(0x54535054)
+// TSPSG Task file version
+#define TSPT_VERSION quint8(1)
+// TSPSG Task file metadata version
+#define TSPT_META_VERSION quint8(1)
+// TSPSG Task file metadata size in bytes (incl. version)
+#define TSPT_META_SIZE 2
+// ZKomModRd Task file signature - letters ZK
+#define ZKT quint16(0x5A4B)
+// ZKomModRd Task file version
+#define ZKT_VERSION quint8(1)
+
+// 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 :-)
+#ifndef INFINITY
+	#define INFINITY 1.7E+308
+#endif
+// This is string, which represents infinite value in table
+#define INFSTR "-----"
+
+#endif // GLOBALS_H
Index: trunk/src/main.cpp
===================================================================
--- trunk/src/main.cpp	(revision 30)
+++ trunk/src/main.cpp	(revision 31)
@@ -22,7 +22,4 @@
  */
 
-#include <QApplication>
-#include <QTranslator>
-#include <QMessageBox>
 #include "mainwindow.h"
 
Index: trunk/src/mainwindow.cpp
===================================================================
--- trunk/src/mainwindow.cpp	(revision 30)
+++ trunk/src/mainwindow.cpp	(revision 31)
@@ -22,8 +22,4 @@
  */
 
-#include <QtGui>
-#ifndef Q_OS_WINCE
-	#include <QPrintDialog>
-#endif // Q_OS_WINCE
 #include "mainwindow.h"
 
@@ -44,4 +40,6 @@
 	actionSettingsLanguageAutodetect->setChecked(settings->value("Language","").toString().isEmpty());
 	connect(actionFileNew,SIGNAL(triggered()),this,SLOT(actionFileNewTriggered()));
+	connect(actionFileOpen,SIGNAL(triggered()),this,SLOT(actionFileOpenTriggered()));
+	connect(actionFileSaveTask,SIGNAL(triggered()),this,SLOT(actionFileSaveTaskTriggered()));
 	connect(actionSettingsPreferences,SIGNAL(triggered()),this,SLOT(actionSettingsPreferencesTriggered()));
 	connect(actionSettingsLanguageAutodetect,SIGNAL(triggered(bool)),this,SLOT(actionSettingsLanguageAutodetectTriggered(bool)));
@@ -79,4 +77,5 @@
 	tspmodel->setNumCities(spinCities->value());
 	taskView->setModel(tspmodel);
+	connect(tspmodel,SIGNAL(numCitiesChanged(int)),this,SLOT(numCitiesChanged(int)));
 #ifdef Q_OS_WINCE
 	taskView->resizeColumnsToContents();
@@ -153,4 +152,38 @@
 }
 
+void MainWindow::actionFileOpenTriggered()
+{
+QFileDialog od(this);
+	od.setAcceptMode(QFileDialog::AcceptOpen);
+	od.setFileMode(QFileDialog::ExistingFile);
+QStringList filters(trUtf8("All Supported Formats") + " (*.tspt *.zkt)");
+	filters.append(QString(trUtf8("%1 Task Files")).arg("TSPSG") + " (*.tspt)");
+	filters.append(QString(trUtf8("%1 Task Files")).arg("ZKomModRd") + " (*.zkt)");
+	filters.append(trUtf8("All Files") + " (*)");
+	od.setNameFilters(filters);
+	if (od.exec() != QDialog::Accepted)
+		return;
+QStringList files = od.selectedFiles();
+	if (files.size() < 1)
+		return;
+	tspmodel->loadTask(files.first());
+}
+
+void MainWindow::actionFileSaveTaskTriggered()
+{
+QFileDialog sd(this);
+	sd.setAcceptMode(QFileDialog::AcceptSave);
+QStringList filters(QString(trUtf8("%1 Task File")).arg("TSPSG") + " (*.tspt)");
+	filters.append(trUtf8("All Files") + " (*)");
+	sd.setNameFilters(filters);
+	sd.setDefaultSuffix("tspt");
+	if (sd.exec() != QDialog::Accepted)
+		return;
+QStringList files = sd.selectedFiles();
+	if (files.size() < 1)
+		return;
+	tspmodel->saveTask(files.first());
+}
+
 void MainWindow::actionSettingsPreferencesTriggered()
 {
@@ -209,4 +242,5 @@
 about += QString::fromUtf8("    Copyright (C) 2007-%1 Lёppa <contacts[at]oleksii[dot]name>\n").arg(QDate::currentDate().toString("yyyy"));
 	about += "Qt library versions:\n";
+	about += QString::fromUtf8("    OS: %1\n").arg(OS);
 	about += QString::fromUtf8("    Compile time: %1\n").arg(QT_VERSION_STR);
 	about += QString::fromUtf8("    Runtime: %1\n").arg(qVersion());
@@ -281,2 +315,7 @@
 	QMainWindow::closeEvent(event);
 }
+
+void MainWindow::numCitiesChanged(int nCities)
+{
+	spinCities->setValue(nCities);
+}
Index: trunk/src/mainwindow.h
===================================================================
--- trunk/src/mainwindow.h	(revision 30)
+++ trunk/src/mainwindow.h	(revision 31)
@@ -25,6 +25,5 @@
 #define MAINWINDOW_H
 
-#include <QMainWindow>
-#include <QSettings>
+#include "globals.h"
 #ifdef Q_OS_WINCE
 	#include "ui_mainwindow.ce.h"
@@ -41,10 +40,12 @@
 public:
 	MainWindow(QWidget *parent = 0);
-	void closeEvent(QCloseEvent *event);
+	void closeEvent(QCloseEvent *);
 private slots:
 	void actionFileNewTriggered();
+	void actionFileOpenTriggered();
+	void actionFileSaveTaskTriggered();
 	void actionSettingsPreferencesTriggered();
-	void actionSettingsLanguageAutodetectTriggered(bool checked);
-	void groupSettingsLanguageListTriggered(QAction *action);
+	void actionSettingsLanguageAutodetectTriggered(bool);
+	void groupSettingsLanguageListTriggered(QAction *);
 	void actionHelpAboutTriggered();
 #ifndef Q_OS_WINCE
@@ -53,5 +54,6 @@
 	void buttonSolveClicked();
 	void buttonRandomClicked();
-	void spinCitiesValueChanged(int n);
+	void spinCitiesValueChanged(int);
+	void numCitiesChanged(int);
 private:
 	QSettings *settings;
Index: trunk/src/os.h
===================================================================
--- trunk/src/os.h	(revision 31)
+++ trunk/src/os.h	(revision 31)
@@ -0,0 +1,119 @@
+/*
+ *  TSPSG - TSP Solver and Generator
+ *  Copyright (C) 2007-2009 Lёppa <contacts[at]oleksii[dot]name>
+ *
+ *  $Id$
+ *  $URL$
+ *
+ *  This file is part of TSPSG.
+ *
+ *  TSPSG is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  TSPSG is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with TSPSG.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef OS_H
+#define OS_H
+
+#ifdef Q_OS_AIX
+	#define OS "AIX"
+	#define OSID quint8(1)
+#elif defined Q_OS_BSD4
+	#define OS "BSD 4.4"
+	#define OSID quint8(2)
+#elif defined Q_OS_BSDI
+	#define OS "BSD/OS"
+	#define OSID quint8(3)
+#elif defined Q_OS_CYGWIN
+	#define OS "Cygwin"
+	#define OSID quint8(4)
+#elif defined Q_OS_DARWIN
+	#define OS "Darwin OS"
+	#define OSID quint8(5)
+#elif defined Q_OS_DGUX
+	#define OS "DG/UX"
+	#define OSID quint8(6)
+#elif defined Q_OS_DYNIX
+	#define OS "DYNIX/ptx"
+	#define OSID quint8(7)
+#elif defined Q_OS_FREEBSD
+	#define OS "FreeBSD"
+	#define OSID quint8(8)
+#elif defined Q_OS_HPUX
+	#define OS "HP-UX"
+	#define OSID quint8(9)
+#elif defined Q_OS_HURD
+	#define OS "GNU Hurd"
+	#define OSID quint8(10)
+#elif defined Q_OS_IRIX
+	#define OS "SGI Irix"
+	#define OSID quint8(11)
+#elif defined Q_OS_LINUX
+	#define OS "Linux"
+	#define OSID quint8(12)
+#elif defined Q_OS_LYNX
+	#define OS "LynxOS"
+	#define OSID quint8(13)
+#elif defined Q_OS_MSDOS
+	#define OS "MS-DOS"
+	#define OSID quint8(14)
+#elif defined Q_OS_NETBSD
+	#define OS "NetBSD"
+	#define OSID quint8(15)
+#elif defined Q_OS_OS2
+	#define OS "OS/2"
+	#define OSID quint8(16)
+#elif defined Q_OS_OPENBSD
+	#define OS "OpenBSD"
+	#define OSID quint8(17)
+#elif defined Q_OS_OS2EMX
+	#define OS "OS/2"
+	#define OSID quint8(18)
+#elif defined Q_OS_OSF
+	#define OS "HP Tru64 UNIX"
+	#define OSID quint8(19)
+#elif defined Q_OS_QNX6
+	#define OS "QNX RTP 6.1"
+	#define OSID quint8(20)
+#elif defined Q_OS_QNX
+	#define OS "QNX"
+	#define OSID quint8(21)
+#elif defined Q_OS_RELIANT
+	#define OS "Reliant UNIX"
+	#define OSID quint8(22)
+#elif defined Q_OS_SCO
+	#define OS "SCO OpenServer 5"
+	#define OSID quint8(23)
+#elif defined Q_OS_SOLARIS
+	#define OS "Sun Solaris"
+	#define OSID quint8(24)
+#elif defined Q_OS_ULTRIX
+	#define OS "DEC Ultrix"
+	#define OSID quint8(25)
+#elif defined Q_OS_UNIX
+	#define OS "UNIX BSD/SYSV"
+	#define OSID quint8(26)
+#elif defined Q_OS_UNIXWARE
+	#define OS "UnixWare 7/Open UNIX 8"
+	#define OSID quint8(27)
+#elif defined Q_OS_WIN32
+	#define OS "Windows"
+	#define OSID quint8(28)
+#elif defined Q_OS_WINCE
+	#define OS "Windows CE"
+	#define OSID quint8(29)
+#else
+	#define OS "Unknown"
+	#define OSID quint8(255)
+#endif
+
+#endif // OS_H
Index: trunk/src/settingsdialog.cpp
===================================================================
--- trunk/src/settingsdialog.cpp	(revision 30)
+++ trunk/src/settingsdialog.cpp	(revision 31)
@@ -22,9 +22,4 @@
  */
 
-#include <QMessageBox>
-#include <QStatusTipEvent>
-#include <QFontDialog>
-#include <QColorDialog>
-#include "defines.h"
 #include "settingsdialog.h"
 
Index: trunk/src/settingsdialog.h
===================================================================
--- trunk/src/settingsdialog.h	(revision 30)
+++ trunk/src/settingsdialog.h	(revision 31)
@@ -25,6 +25,5 @@
 #define SETTINGSDIALOG_H
 
-#include <QDialog>
-#include <QSettings>
+#include "globals.h"
 #ifdef Q_OS_WINCE
 	#include "ui_settingsdialog.ce.h"
Index: trunk/src/tspmodel.cpp
===================================================================
--- trunk/src/tspmodel.cpp	(revision 30)
+++ trunk/src/tspmodel.cpp	(revision 31)
@@ -22,5 +22,4 @@
  */
 
-#include <QtGui>
 #include "tspmodel.h"
 
@@ -109,5 +108,5 @@
 }
 
-int CTSPModel::numCities() const
+quint16 CTSPModel::numCities() const
 {
 	return nCities;
@@ -116,6 +115,6 @@
 void CTSPModel::setNumCities(int n)
 {
-int randMin = settings->value("MinCost",DEF_RAND_MIN).toInt();
-int randMax = settings->value("MaxCost",DEF_RAND_MAX).toInt();
+// int randMin = settings->value("MinCost",DEF_RAND_MIN).toInt();
+// int randMax = settings->value("MaxCost",DEF_RAND_MAX).toInt();
 	if (n == nCities)
 		return;
@@ -127,5 +126,5 @@
 					table[r][c] = INFINITY;
 				else
-					table[r][c] = rand(randMin,randMax);
+					table[r][c] = 0; // rand(randMin,randMax);
 		}
 		for (int r = nCities; r < n; r++) {
@@ -134,5 +133,5 @@
 					table[r][c] = INFINITY;
 				else
-					table[r][c] = rand(randMin,randMax);
+					table[r][c] = 0; // rand(randMin,randMax);
 		}
 	}
@@ -148,4 +147,100 @@
 				table[r][c] = 0;
 	emit dataChanged(index(0,0),index(nCities - 1,nCities - 1));
+}
+
+void CTSPModel::loadTask(QString fname)
+{
+QFile f(fname);
+	f.open(QIODevice::ReadOnly);
+QDataStream ds(&f);
+	ds.setVersion(QDataStream::Qt_4_4);
+quint32 sig;
+	ds >> sig;
+	ds.device()->reset();
+	if (sig == TSPT)
+		loadTSPT(&ds);
+	else if ((sig >> 16) == ZKT)
+		loadZKT(&ds);
+	else
+		QMessageBox(QMessageBox::Critical,trUtf8("Task Load"),trUtf8("Unable to load task:\nUnknown file format or file is corrupted."),QMessageBox::Ok).exec();
+	f.close();
+}
+
+void CTSPModel::loadTSPT(QDataStream *ds)
+{
+	// Skipping signature
+	ds->skipRawData(sizeof(TSPT));
+	// File version
+quint8 version;
+	*ds >> version;
+	if (version > TSPT_VERSION) {
+		QMessageBox(QMessageBox::Critical,trUtf8("Task Load"),trUtf8("Unable to load task:\nFile version is newer than application supports.\nPlease, try to update application."),QMessageBox::Ok).exec();
+		return;
+	}
+	// Skipping metadata
+	ds->skipRawData(TSPT_META_SIZE);
+	// Cities number
+quint16 size;
+	*ds >> size;
+	if (nCities != size)
+		emit numCitiesChanged(size);
+	// Costs
+	for (int r = 0; r < size; r++)
+		for (int c = 0; c < size; c++)
+			if (r != c)
+				*ds >> table[r][c];
+	emit dataChanged(index(0,0),index(nCities - 1,nCities - 1));
+}
+
+void CTSPModel::loadZKT(QDataStream *ds)
+{
+	// Skipping signature
+	ds->skipRawData(sizeof(ZKT));
+	// File version
+quint16 version;
+	ds->readRawData(reinterpret_cast<char *>(&version),2);
+	if (version > ZKT_VERSION) {
+		QMessageBox(QMessageBox::Critical,trUtf8("Task Load"),trUtf8("Unable to load task:\nFile version is newer than application supports.\nPlease, try to update application."),QMessageBox::Ok).exec();
+		return;
+	}
+	// Cities number
+quint8 size;
+	ds->readRawData(reinterpret_cast<char *>(&size),1);
+	if (nCities != size)
+		emit numCitiesChanged(size);
+	// Costs
+double val;
+	for (int r = 0; r < size; r++)
+		for (int c = 0; c < size; c++)
+			if (r != c) {
+				ds->readRawData(reinterpret_cast<char *>(&val),8);
+				table[r][c] = val;
+			} else
+				ds->skipRawData(8);
+	emit dataChanged(index(0,0),index(nCities - 1,nCities - 1));
+}
+
+void CTSPModel::saveTask(QString fname)
+{
+QFile f(fname);
+	f.open(QIODevice::WriteOnly);
+QDataStream ds(&f);
+	ds.setVersion(QDataStream::Qt_4_4);
+	// File signature
+	ds << TSPT;
+	// File version
+	ds << TSPT_VERSION;
+	// File metadata version
+	ds << TSPT_META_VERSION;
+	// Metadata
+	ds << OSID;
+	// Number of cities
+	ds << nCities;
+	// Costs
+	for (int r = 0; r < nCities; r++)
+		for (int c = 0; c < nCities; c++)
+			if (r != c)
+				ds << table[r][c];
+	f.close();
 }
 
Index: trunk/src/tspmodel.h
===================================================================
--- trunk/src/tspmodel.h	(revision 30)
+++ trunk/src/tspmodel.h	(revision 31)
@@ -25,7 +25,5 @@
 #define TSPMODEL_H
 
-#include <QAbstractTableModel>
-#include <QSettings>
-#include "defines.h"
+#include "globals.h"
 
 class CTSPModel: public QAbstractTableModel
@@ -40,13 +38,19 @@
 	bool setData(const QModelIndex &, const QVariant &, int);
 	Qt::ItemFlags flags(const QModelIndex &) const;
-	int numCities() const;
+	quint16 numCities() const;
 	void setNumCities(int);
 	void clear();
+	void loadTask(QString);
+	void saveTask(QString);
 	void randomize();
+signals:
+	void numCitiesChanged(int);
 private:
 	QSettings *settings;
 	double table[MAX_CITIES][MAX_CITIES];
-	int nCities;
+	quint16 nCities;
 	int rand(int, int);
+	void loadZKT(QDataStream *);
+	void loadTSPT(QDataStream *);
 };
 
Index: trunk/src/tspsolver.h
===================================================================
--- trunk/src/tspsolver.h	(revision 30)
+++ trunk/src/tspsolver.h	(revision 31)
@@ -25,5 +25,5 @@
 #define TSPSOLVER_H
 
-#include <QtCore>
+#include "globals.h"
 
 typedef QList<double *> tMatrix;
