source: tspsg-svn/trunk/src/mainwindow.cpp @ 37

Last change on this file since 37 was 37, checked in by laleppa, 15 years ago

+ Task save prompt before creating or opening task and closing application if current task was modified.

  • Translation updates.
  • Property svn:keywords set to Id URL
File size: 13.3 KB
Line 
1/*
2 *  TSPSG - TSP Solver and Generator
3 *  Copyright (C) 2007-2009 Lёppa <contacts[at]oleksii[dot]name>
4 *
5 *  $Id: mainwindow.cpp 37 2009-07-16 16:00:27Z laleppa $
6 *  $URL: https://tspsg.svn.sourceforge.net/svnroot/tspsg/trunk/src/mainwindow.cpp $
7 *
8 *  This file is part of TSPSG.
9 *
10 *  TSPSG is free software: you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License as published by
12 *  the Free Software Foundation, either version 3 of the License, or
13 *  (at your option) any later version.
14 *
15 *  TSPSG is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with TSPSG.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include "mainwindow.h"
25
26MainWindow::MainWindow(QWidget *parent)
27        : QMainWindow(parent)
28{
29        settings = new QSettings(QSettings::IniFormat,QSettings::UserScope,"TSPSG","tspsg");
30        loadLanguage();
31        setupUi(this);
32#ifndef Q_OS_WINCE
33        printer = new QPrinter();
34#endif // Q_OS_WINCE
35        groupSettingsLanguageList = new QActionGroup(this);
36        actionSettingsLanguageEnglish->setData("en");
37        actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
38        loadLangList();
39        spinCities->setValue(settings->value("NumCities",5).toInt());
40        actionSettingsLanguageAutodetect->setChecked(settings->value("Language","").toString().isEmpty());
41        connect(actionFileNew,SIGNAL(triggered()),this,SLOT(actionFileNewTriggered()));
42        connect(actionFileOpen,SIGNAL(triggered()),this,SLOT(actionFileOpenTriggered()));
43        connect(actionFileSaveTask,SIGNAL(triggered()),this,SLOT(actionFileSaveTaskTriggered()));
44        connect(actionSettingsPreferences,SIGNAL(triggered()),this,SLOT(actionSettingsPreferencesTriggered()));
45        connect(actionSettingsLanguageAutodetect,SIGNAL(triggered(bool)),this,SLOT(actionSettingsLanguageAutodetectTriggered(bool)));
46        connect(groupSettingsLanguageList,SIGNAL(triggered(QAction *)),this,SLOT(groupSettingsLanguageListTriggered(QAction *)));
47        connect(actionHelpAboutQt,SIGNAL(triggered()),qApp,SLOT(aboutQt()));
48        connect(actionHelpAbout,SIGNAL(triggered()),this,SLOT(actionHelpAboutTriggered()));
49#ifndef Q_OS_WINCE
50        connect(actionFilePrintSetup,SIGNAL(triggered()),this,SLOT(actionFilePrintSetupTriggered()));
51#endif // Q_OS_WINCE
52        connect(buttonSolve,SIGNAL(clicked()),this,SLOT(buttonSolveClicked()));
53        connect(buttonRandom,SIGNAL(clicked()),this,SLOT(buttonRandomClicked()));
54        connect(spinCities,SIGNAL(valueChanged(int)),this,SLOT(spinCitiesValueChanged(int)));
55QRect rect = geometry();
56#ifdef Q_OS_WINCE
57        // HACK: Fix for all tabWidget elements becoming "unclickable" if making it central widget.
58        rect.setSize(QApplication::desktop()->availableGeometry().size());
59        rect.setHeight(rect.height() - (QApplication::desktop()->screenGeometry().height() - QApplication::desktop()->availableGeometry().height()));
60        tabWidget->resize(rect.width(),rect.height() - toolBar->size().height());
61#else
62        if (settings->value("SavePos",false).toBool()) {
63                // Loading of saved window state
64                settings->beginGroup("MainWindow");
65                resize(settings->value("Size",size()).toSize());
66                move(settings->value("Position",pos()).toPoint());
67                if (settings->value("Maximized",false).toBool())
68                        setWindowState(windowState() | Qt::WindowMaximized);
69                settings->endGroup();
70        } else {
71                // Centering main window
72                rect.moveCenter(QApplication::desktop()->availableGeometry(this).center());
73                setGeometry(rect);
74        }
75#endif // Q_OS_WINCE
76        qsrand(QDateTime().currentDateTime().toTime_t());
77        tspmodel = new CTSPModel();
78        tspmodel->setNumCities(spinCities->value());
79        taskView->setModel(tspmodel);
80        connect(tspmodel,SIGNAL(numCitiesChanged(int)),this,SLOT(numCitiesChanged(int)));
81        connect(tspmodel,SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(dataChanged()));
82        connect(tspmodel,SIGNAL(layoutChanged()),this,SLOT(dataChanged()));
83#ifdef Q_OS_WINCE
84        taskView->resizeColumnsToContents();
85        taskView->resizeRowsToContents();
86#endif // Q_OS_WINCE
87}
88
89bool MainWindow::loadLanguage(QString lang)
90{
91// i18n
92bool ad = false;
93        if (lang.isEmpty()) {
94                ad = settings->value("Language","").toString().isEmpty();
95                lang = settings->value("Language",QLocale::system().name()).toString();
96        }
97static QTranslator *qtTranslator;
98        if (qtTranslator) {
99                qApp->removeTranslator(qtTranslator);
100                delete qtTranslator;
101                qtTranslator = NULL;
102        }
103        qtTranslator = new QTranslator();
104static QTranslator *translator;
105        if (translator) {
106                qApp->removeTranslator(translator);
107                delete translator;
108        }
109        translator = new QTranslator();
110        if (lang.compare("en") && !lang.startsWith("en_")) {
111                // Trying to load system Qt library translation...
112                if (qtTranslator->load("qt_" + lang,QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
113                        qApp->installTranslator(qtTranslator);
114                else
115                        // No luck. Let's try to load bundled one.
116                        if (qtTranslator->load("qt_" + lang,"i18n"))
117                                qApp->installTranslator(qtTranslator);
118                        else {
119                                delete qtTranslator;
120                                qtTranslator = NULL;
121                        }
122                // Now let's load application translation.
123                if (translator->load(lang,"i18n"))
124                        qApp->installTranslator(translator);
125                else {
126                        if (!ad)
127                                QMessageBox(QMessageBox::Warning,trUtf8("Language change"),trUtf8("Unable to load translation language."),QMessageBox::Ok,this).exec();
128                        delete translator;
129                        translator = NULL;
130                        return false;
131                }
132        }
133        return true;
134}
135
136void MainWindow::spinCitiesValueChanged(int n)
137{
138#ifdef Q_OS_WINCE
139int count = tspmodel->numCities();
140#endif // Q_OS_WINCE
141        tspmodel->setNumCities(n);
142#ifdef Q_OS_WINCE
143        if (n > count)
144                for (int k = count; k < n; k++) {
145                        taskView->resizeColumnToContents(k);
146                        taskView->resizeRowToContents(k);
147                }
148#endif // Q_OS_WINCE
149}
150
151
152void MainWindow::actionFileNewTriggered()
153{
154        if (isWindowModified()) {
155int res = QMessageBox(QMessageBox::Warning,trUtf8("New Task"),trUtf8("Would you like to save changes in current task?"),QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,this).exec();
156                if ((res == QMessageBox::Cancel) || ((res == QMessageBox::Yes) && !saveTask()))
157                        return;
158        }
159        tspmodel->clear();
160        setWindowModified(false);
161}
162
163void MainWindow::actionFileOpenTriggered()
164{
165        if (isWindowModified()) {
166int res = QMessageBox(QMessageBox::Warning,trUtf8("Task Open"),trUtf8("Would you like to save changes in current task?"),QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,this).exec();
167                if ((res == QMessageBox::Cancel) || ((res == QMessageBox::Yes) && !saveTask()))
168                        return;
169        }
170QFileDialog od(this);
171        od.setAcceptMode(QFileDialog::AcceptOpen);
172        od.setFileMode(QFileDialog::ExistingFile);
173QStringList filters(trUtf8("All Supported Formats") + " (*.tspt *.zkt)");
174        filters.append(QString(trUtf8("%1 Task Files")).arg("TSPSG") + " (*.tspt)");
175        filters.append(QString(trUtf8("%1 Task Files")).arg("ZKomModRd") + " (*.zkt)");
176        filters.append(trUtf8("All Files") + " (*)");
177        od.setNameFilters(filters);
178        if (od.exec() != QDialog::Accepted)
179                return;
180QStringList files = od.selectedFiles();
181        if (files.size() < 1)
182                return;
183        tspmodel->loadTask(files.first());
184        setWindowModified(false);
185}
186
187void MainWindow::actionFileSaveTaskTriggered()
188{
189        saveTask();
190}
191
192bool MainWindow::saveTask() {
193QFileDialog sd(this);
194        sd.setAcceptMode(QFileDialog::AcceptSave);
195QStringList filters(QString(trUtf8("%1 Task File")).arg("TSPSG") + " (*.tspt)");
196        filters.append(trUtf8("All Files") + " (*)");
197        sd.setNameFilters(filters);
198        sd.setDefaultSuffix("tspt");
199        if (sd.exec() != QDialog::Accepted)
200                return false;
201QStringList files = sd.selectedFiles();
202        if (files.size() < 1)
203                return false;
204        if (tspmodel->saveTask(files.first())) {
205                setWindowModified(false);
206                return true;
207        } else
208                return false;
209}
210
211void MainWindow::actionSettingsPreferencesTriggered()
212{
213SettingsDialog sd(this);
214        sd.exec();
215}
216
217#ifndef Q_OS_WINCE
218void MainWindow::actionFilePrintSetupTriggered()
219{
220QPrintDialog pd(printer,this);
221#if QT_VERSION >= 0x040500
222        // No such methods in Qt < 4.5
223        pd.setOption(QAbstractPrintDialog::PrintSelection,false);
224        pd.setOption(QAbstractPrintDialog::PrintPageRange,false);
225#endif
226        pd.exec();
227}
228#endif // Q_OS_WINCE
229
230void MainWindow::buttonRandomClicked()
231{
232        tspmodel->randomize();
233        setWindowModified(true);
234#ifdef Q_OS_WINCE
235        taskView->resizeColumnsToContents();
236        taskView->resizeRowsToContents();
237#endif // Q_OS_WINCE
238}
239
240void MainWindow::buttonSolveClicked()
241{
242        // TODO: Task solving goes here :-)
243tMatrix matrix;
244double *row;
245int n = spinCities->value();
246bool ok;
247        for (int r = 0; r < n; r++) {
248                row = new double[n];
249                for (int c = 0; c < n; c++) {
250                        row[c] = tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok);
251                        if (!ok) {
252                                QMessageBox(QMessageBox::Critical,trUtf8("Data error"),QString(trUtf8("Error in cell [Row %1; Column %2]: Invalid data format.")).arg(r + 1).arg(c + 1),QMessageBox::Ok,this).exec();
253                                return;
254                        }
255                }
256                matrix.append(row);
257        }
258CTSPSolver solver;
259sStep *root = solver.solve(spinCities->value(),matrix);
260        if (!root)
261                QMessageBox(QMessageBox::Critical,trUtf8("Solution error"),trUtf8("There was an error while solving the task."),QMessageBox::Ok,this).exec();
262        // tabWidget->setCurrentIndex(1);
263}
264
265void MainWindow::actionHelpAboutTriggered()
266{
267        // TODO: Normal about window :-)
268QString about = QString::fromUtf8("TSPSG - TSP Solver and Generator\n");
269about += QString::fromUtf8("    Copyright (C) 2007-%1 Lёppa <contacts[at]oleksii[dot]name>\n").arg(QDate::currentDate().toString("yyyy"));
270        about += QString::fromUtf8("Target OS: %1\n").arg(OS);
271        about += "Qt library:\n";
272        about += QString::fromUtf8("    Compile time: %1\n").arg(QT_VERSION_STR);
273        about += QString::fromUtf8("    Runtime: %1\n").arg(qVersion());
274        about += "\n";
275        about += "TSPSG is licensed under the terms of the GNU General Public License. You should have received a copy of the GNU General Public License along with TSPSG.";
276        QMessageBox(QMessageBox::Information,"About",about,QMessageBox::Ok,this).exec();
277}
278
279void MainWindow::loadLangList()
280{
281QSettings langinfo("i18n/languages.ini",QSettings::IniFormat);
282#if QT_VERSION >= 0x040500
283        // In Qt < 4.5 QSettings doesn't have method setIniCodec.
284        langinfo.setIniCodec("UTF-8");
285#endif
286QDir dir("i18n","*.qm",QDir::Name | QDir::IgnoreCase,QDir::Files);
287        if (!dir.exists())
288                return;
289QFileInfoList langs = dir.entryInfoList();
290        if (langs.size() <= 0)
291                return;
292QAction *a;
293        for (int k = 0; k < langs.size(); k++) {
294                QFileInfo lang = langs.at(k);
295                if (!lang.completeBaseName().startsWith("qt_") && lang.completeBaseName().compare("en")) {
296#if QT_VERSION >= 0x040500
297                        a = menuSettingsLanguage->addAction(langinfo.value(lang.completeBaseName() + "/NativeName",lang.completeBaseName()).toString());
298#else
299                        // We use Name if Qt < 4.5 because NativeName is in UTF-8, QSettings
300                        // reads .ini file as ASCII and there is no way to set file encoding.
301                        a = menuSettingsLanguage->addAction(langinfo.value(lang.completeBaseName() + "/Name",lang.completeBaseName()).toString());
302#endif
303                        a->setData(lang.completeBaseName());
304                        a->setCheckable(true);
305                        a->setActionGroup(groupSettingsLanguageList);
306                        if (settings->value("Language",QLocale::system().name()).toString().startsWith(lang.completeBaseName()))
307                                a->setChecked(true);
308                }
309        }
310}
311
312void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked)
313{
314        if (checked) {
315                settings->remove("Language");
316                QMessageBox(QMessageBox::Information,trUtf8("Language change"),trUtf8("Language will be autodetected on next application start."),QMessageBox::Ok,this).exec();
317        } else
318                settings->setValue("Language",groupSettingsLanguageList->checkedAction()->data().toString());
319}
320
321void MainWindow::groupSettingsLanguageListTriggered(QAction *action)
322{
323        if (actionSettingsLanguageAutodetect->isChecked()) {
324                // We have language autodetection. It needs to be disabled to change language.
325                if (QMessageBox(QMessageBox::Question,trUtf8("Language change"),trUtf8("You have language autodetection turned on.\nIt needs to be off.\nDo you wish to turn it off?"),QMessageBox::Yes | QMessageBox::No,this).exec() == QMessageBox::Yes) {
326                        actionSettingsLanguageAutodetect->trigger();
327                } else
328                        return;
329        }
330        if (loadLanguage(action->data().toString())) {
331                settings->setValue("Language",action->data().toString());
332                retranslateUi(this);
333        }
334}
335
336void MainWindow::closeEvent(QCloseEvent *event)
337{
338        if (isWindowModified()) {
339int res = QMessageBox(QMessageBox::Warning,trUtf8("Application Close"),trUtf8("Would you like to save changes in current task?"),QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,this).exec();
340                if ((res == QMessageBox::Cancel) || ((res == QMessageBox::Yes) && !saveTask())) {
341                        event->ignore();
342                        return;
343                }
344        }
345        settings->setValue("NumCities",spinCities->value());
346#ifndef Q_OS_WINCE
347        // Saving windows state
348        if (settings->value("SavePos",false).toBool()) {
349                settings->beginGroup("MainWindow");
350                settings->setValue("Maximized",isMaximized());
351                if (!isMaximized()) {
352                        settings->setValue("Size",size());
353                        settings->setValue("Position",pos());
354                }
355                settings->endGroup();
356        }
357#endif // Q_OS_WINCE
358        QMainWindow::closeEvent(event);
359}
360
361void MainWindow::dataChanged()
362{
363        setWindowModified(true);
364}
365
366void MainWindow::numCitiesChanged(int nCities)
367{
368        spinCities->setValue(nCities);
369}
Note: See TracBrowser for help on using the repository browser.