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

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

+ Added solution graph generation.

  • Property svn:keywords set to Id URL
File size: 40.9 KB
Line 
1/*
2 *  TSPSG: TSP Solver and Generator
3 *  Copyright (C) 2007-2010 Lёppa <contacts[at]oleksii[dot]name>
4 *
5 *  $Id: mainwindow.cpp 106 2010-04-20 21:18:18Z 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
26/*!
27 * \brief Class constructor.
28 * \param parent Main Window parent widget.
29 *
30 *  Initializes Main Window and creates its layout based on target OS.
31 *  Loads TSPSG settings and opens a task file if it was specified as a commandline parameter.
32 */
33MainWindow::MainWindow(QWidget *parent)
34        : QMainWindow(parent)
35{
36        settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this);
37
38        loadLanguage();
39        setupUi();
40        setAcceptDrops(true);
41
42        initDocStyleSheet();
43
44#ifndef QT_NO_PRINTER
45        printer = new QPrinter(QPrinter::HighResolution);
46#endif // QT_NO_PRINTER
47
48#ifdef Q_OS_WINCE_WM
49        currentGeometry = QApplication::desktop()->availableGeometry(0);
50        // We need to react to SIP show/hide and resize the window appropriately
51        connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), SLOT(desktopResized(int)));
52#endif // Q_OS_WINCE_WM
53        connect(actionFileNew,SIGNAL(triggered()),this,SLOT(actionFileNewTriggered()));
54        connect(actionFileOpen,SIGNAL(triggered()),this,SLOT(actionFileOpenTriggered()));
55        connect(actionFileSave,SIGNAL(triggered()),this,SLOT(actionFileSaveTriggered()));
56        connect(actionFileSaveAsTask,SIGNAL(triggered()),this,SLOT(actionFileSaveAsTaskTriggered()));
57        connect(actionFileSaveAsSolution,SIGNAL(triggered()),this,SLOT(actionFileSaveAsSolutionTriggered()));
58#ifndef QT_NO_PRINTER
59        connect(actionFilePrintPreview,SIGNAL(triggered()),this,SLOT(actionFilePrintPreviewTriggered()));
60        connect(actionFilePrint,SIGNAL(triggered()),this,SLOT(actionFilePrintTriggered()));
61#endif // QT_NO_PRINTER
62        connect(actionSettingsPreferences,SIGNAL(triggered()),this,SLOT(actionSettingsPreferencesTriggered()));
63#ifdef Q_OS_WIN32
64        connect(actionHelpCheck4Updates, SIGNAL(triggered()), SLOT(actionHelpCheck4UpdatesTriggered()));
65#endif // Q_OS_WIN32
66        connect(actionSettingsLanguageAutodetect,SIGNAL(triggered(bool)),this,SLOT(actionSettingsLanguageAutodetectTriggered(bool)));
67        connect(groupSettingsLanguageList,SIGNAL(triggered(QAction *)),this,SLOT(groupSettingsLanguageListTriggered(QAction *)));
68        connect(actionHelpAboutQt,SIGNAL(triggered()),qApp,SLOT(aboutQt()));
69        connect(actionHelpAbout,SIGNAL(triggered()),this,SLOT(actionHelpAboutTriggered()));
70
71        connect(buttonSolve,SIGNAL(clicked()),this,SLOT(buttonSolveClicked()));
72        connect(buttonRandom,SIGNAL(clicked()),this,SLOT(buttonRandomClicked()));
73        connect(buttonBackToTask,SIGNAL(clicked()),this,SLOT(buttonBackToTaskClicked()));
74        connect(spinCities,SIGNAL(valueChanged(int)),this,SLOT(spinCitiesValueChanged(int)));
75
76#ifndef HANDHELD
77        // Centering main window
78QRect rect = geometry();
79        rect.moveCenter(QApplication::desktop()->availableGeometry(this).center());
80        setGeometry(rect);
81        if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
82                // Loading of saved window state
83                settings->beginGroup("MainWindow");
84                restoreGeometry(settings->value("Geometry").toByteArray());
85                restoreState(settings->value("State").toByteArray());
86                settings->endGroup();
87        }
88#else
89        setWindowState(Qt::WindowMaximized);
90#endif // HANDHELD
91
92        tspmodel = new CTSPModel(this);
93        taskView->setModel(tspmodel);
94        connect(tspmodel,SIGNAL(numCitiesChanged(int)),this,SLOT(numCitiesChanged(int)));
95        connect(tspmodel,SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
96        connect(tspmodel,SIGNAL(layoutChanged()),this,SLOT(dataChanged()));
97        if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1))))
98                setFileName(QCoreApplication::arguments().at(1));
99        else {
100                setFileName();
101                spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt());
102                spinCitiesValueChanged(spinCities->value());
103        }
104        setWindowModified(false);
105}
106
107MainWindow::~MainWindow()
108{
109#ifndef QT_NO_PRINTER
110        delete printer;
111#endif
112}
113
114/* Privates **********************************************************/
115
116void MainWindow::actionFileNewTriggered()
117{
118        if (!maybeSave())
119                return;
120        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
121        tspmodel->clear();
122        setFileName();
123        setWindowModified(false);
124        tabWidget->setCurrentIndex(0);
125        solutionText->clear();
126        toggleSolutionActions(false);
127        QApplication::restoreOverrideCursor();
128}
129
130void MainWindow::actionFileOpenTriggered()
131{
132        if (!maybeSave())
133                return;
134
135QStringList filters(tr("All Supported Formats") + " (*.tspt *.zkt)");
136        filters.append(tr("%1 Task Files").arg("TSPSG") + " (*.tspt)");
137        filters.append(tr("%1 Task Files").arg("ZKomModRd") + " (*.zkt)");
138        filters.append(tr("All Files") + " (*)");
139
140QString file = QFileInfo(fileName).canonicalPath();
141QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
142        file = QFileDialog::getOpenFileName(this, tr("Task Load"), file, filters.join(";;"), NULL, opts);
143        if (file.isEmpty() || !QFileInfo(file).isFile())
144                return;
145        if (!tspmodel->loadTask(file))
146                return;
147        setFileName(file);
148        tabWidget->setCurrentIndex(0);
149        setWindowModified(false);
150        solutionText->clear();
151        toggleSolutionActions(false);
152}
153
154bool MainWindow::actionFileSaveTriggered()
155{
156        if ((fileName == tr("Untitled") + ".tspt") || (!fileName.endsWith(".tspt", Qt::CaseInsensitive)))
157                return saveTask();
158        else
159                if (tspmodel->saveTask(fileName)) {
160                        setWindowModified(false);
161                        return true;
162                } else
163                        return false;
164}
165
166void MainWindow::actionFileSaveAsTaskTriggered()
167{
168        saveTask();
169}
170
171void MainWindow::actionFileSaveAsSolutionTriggered()
172{
173static QString selectedFile;
174        if (selectedFile.isEmpty())
175                selectedFile = QFileInfo(fileName).canonicalPath();
176        else
177                selectedFile = QFileInfo(selectedFile).canonicalPath();
178        if (!selectedFile.isEmpty())
179                selectedFile += "/";
180        if (fileName == tr("Untitled") + ".tspt") {
181#ifndef QT_NO_PRINTER
182                selectedFile += "solution.pdf";
183#else
184                selectedFile += "solution.html";
185#endif // QT_NO_PRINTER
186        } else {
187#ifndef QT_NO_PRINTER
188                selectedFile += QFileInfo(fileName).completeBaseName() + ".pdf";
189#else
190                selectedFile += QFileInfo(fileName).completeBaseName() + ".html";
191#endif // QT_NO_PRINTER
192        }
193
194QStringList filters;
195#ifndef QT_NO_PRINTER
196        filters.append(tr("PDF Files") + " (*.pdf)");
197#endif
198        filters.append(tr("HTML Files") + " (*.html *.htm)");
199#if QT_VERSION >= 0x040500
200        filters.append(tr("OpenDocument Files") + " (*.odt)");
201#endif // QT_VERSION >= 0x040500
202        filters.append(tr("All Files") + " (*)");
203
204QFileDialog::Options opts(settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog);
205QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"), NULL, opts);
206        if (file.isEmpty())
207                return;
208        selectedFile = file;
209        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
210#ifndef QT_NO_PRINTER
211        if (selectedFile.endsWith(".pdf",Qt::CaseInsensitive)) {
212QPrinter printer(QPrinter::HighResolution);
213                printer.setOutputFormat(QPrinter::PdfFormat);
214                printer.setOutputFileName(selectedFile);
215                solutionText->document()->print(&printer);
216                QApplication::restoreOverrideCursor();
217                return;
218        }
219#endif
220#if QT_VERSION >= 0x040500
221QTextDocumentWriter dw(selectedFile);
222        if (!(selectedFile.endsWith(".htm",Qt::CaseInsensitive) || selectedFile.endsWith(".html",Qt::CaseInsensitive) || selectedFile.endsWith(".odt",Qt::CaseInsensitive) || selectedFile.endsWith(".txt",Qt::CaseInsensitive)))
223                dw.setFormat("plaintext");
224        if (!dw.write(solutionText->document()))
225                QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(dw.device()->errorString()));
226#else // QT_VERSION >= 0x040500
227        // Qt < 4.5 has no QTextDocumentWriter class
228QFile file(selectedFile);
229        if (!file.open(QFile::WriteOnly)) {
230                QApplication::restoreOverrideCursor();
231                QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(file->errorString()));
232                return;
233        }
234QTextStream ts(&file);
235        ts.setCodec(QTextCodec::codecForName("UTF-8"));
236        ts << solutionText->document()->toHtml("UTF-8");
237        file.close();
238#endif // QT_VERSION >= 0x040500
239        QApplication::restoreOverrideCursor();
240}
241
242#ifndef QT_NO_PRINTER
243void MainWindow::actionFilePrintPreviewTriggered()
244{
245QPrintPreviewDialog ppd(printer, this);
246        connect(&ppd,SIGNAL(paintRequested(QPrinter *)),SLOT(printPreview(QPrinter *)));
247        ppd.exec();
248}
249
250void MainWindow::actionFilePrintTriggered()
251{
252QPrintDialog pd(printer,this);
253#if QT_VERSION >= 0x040500
254        // No such methods in Qt < 4.5
255        pd.setOption(QAbstractPrintDialog::PrintSelection,false);
256        pd.setOption(QAbstractPrintDialog::PrintPageRange,false);
257#endif
258        if (pd.exec() != QDialog::Accepted)
259                return;
260        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
261        solutionText->document()->print(printer);
262        QApplication::restoreOverrideCursor();
263}
264#endif // QT_NO_PRINTER
265
266void MainWindow::actionSettingsPreferencesTriggered()
267{
268SettingsDialog sd(this);
269        if (sd.exec() != QDialog::Accepted)
270                return;
271        if (sd.colorChanged() || sd.fontChanged()) {
272                if (!solutionText->document()->isEmpty() && sd.colorChanged())
273                        QMessageBox::information(this, tr("Settings Changed"), tr("You have changed color settings.\nThey will be applied to the next solution output."));
274                initDocStyleSheet();
275        }
276        if (sd.translucencyChanged() != 0)
277                toggleTranclucency(sd.translucencyChanged() == 1);
278}
279
280void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked)
281{
282        if (checked) {
283                settings->remove("Language");
284                QMessageBox::information(this, tr("Language change"), tr("Language will be autodetected on the next application start."));
285        } else
286                settings->setValue("Language", groupSettingsLanguageList->checkedAction()->data().toString());
287}
288
289void MainWindow::groupSettingsLanguageListTriggered(QAction *action)
290{
291        if (actionSettingsLanguageAutodetect->isChecked()) {
292                // We have language autodetection. It needs to be disabled to change language.
293                if (QMessageBox::question(this, tr("Language change"), tr("You have language autodetection turned on.\nIt needs to be off.\nDo you wish to turn it off?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
294                        actionSettingsLanguageAutodetect->trigger();
295                } else
296                        return;
297        }
298bool untitled = (fileName == tr("Untitled") + ".tspt");
299        if (loadLanguage(action->data().toString())) {
300                QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
301                settings->setValue("Language",action->data().toString());
302                retranslateUi();
303                if (untitled)
304                        setFileName();
305#ifdef Q_OS_WIN32
306                if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
307                        toggleStyle(labelVariant, true);
308                        toggleStyle(labelCities, true);
309                }
310#endif
311                QApplication::restoreOverrideCursor();
312                if (!solutionText->document()->isEmpty())
313                        QMessageBox::information(this, tr("Settings Changed"), tr("You have changed the application language.\nTo get current solution output in the new language\nyou need to re-run the solution process."));
314        }
315}
316
317#ifdef Q_OS_WIN32
318void MainWindow::actionHelpCheck4UpdatesTriggered()
319{
320        if (!hasUpdater()) {
321                QMessageBox::warning(this, tr("Unsupported Feature"), tr("Sorry, but this feature is not supported on your platform\nor support for this feature was not installed."));
322                return;
323        }
324
325        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
326        QProcess::execute("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\"");
327        QApplication::restoreOverrideCursor();
328}
329#endif // Q_OS_WIN32
330
331void MainWindow::actionHelpAboutTriggered()
332{
333QString title;
334#ifdef HANDHELD
335        title += QString("<b>TSPSG<br>TSP Solver and Generator</b><br>");
336#else
337        title += QString("<b>TSPSG: TSP Solver and Generator</b><br>");
338#endif // HANDHELD
339        title += QString("%1: <b>%2</b><br>").arg(tr("Version"), QApplication::applicationVersion());
340#ifndef HANDHELD
341        title += QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b><br>").arg(QDate::currentDate().toString("yyyy"), QApplication::organizationDomain(), QApplication::organizationName());
342        title += QString("<b><a href=\"http://tspsg.sourceforge.net/\">http://tspsg.sourceforge.net/</a></b>");
343#else
344        title += QString("<b><a href=\"http://tspsg.sourceforge.net/\">http://tspsg.sf.net/</a></b>");
345#endif // Q_OS_WINCE_WM && Q_OS_SYMBIAN
346
347QString about;
348        about += QString("%1: <b>%2</b><br>").arg(tr("Target OS (ARCH)"), OS);
349#ifndef STATIC_BUILD
350        about += QString("%1 (%2):<br>").arg(tr("Qt library"), tr("shared"));
351        about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Build time"), QT_VERSION_STR);
352        about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Runtime"), qVersion());
353#else
354        about += QString("%1: <b>%2</b> (%3)<br>").arg(tr("Qt library"), QT_VERSION_STR, tr("static"));
355#endif // STATIC_BUILD
356        about += tr("Buid <b>%1</b>, built on <b>%2</b> at <b>%3</b>").arg(BUILD_NUMBER).arg(__DATE__).arg(__TIME__) + "<br>";
357        about += QString("%1: <b>%2</b><br>").arg(tr("Algorithm"), CTSPSolver::getVersionId());
358        about += "<br>";
359        about += tr("TSPSG is free software: you can redistribute it and/or modify it<br>"
360                "under the terms of the GNU General Public License as published<br>"
361                "by the Free Software Foundation, either version 3 of the License,<br>"
362                "or (at your option) any later version.<br>"
363                "<br>"
364                "TSPSG is distributed in the hope that it will be useful, but<br>"
365                "WITHOUT ANY WARRANTY; without even the implied warranty of<br>"
366                "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>"
367                "GNU General Public License for more details.<br>"
368                "<br>"
369                "You should have received a copy of the GNU General Public License<br>"
370                "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">http://www.gnu.org/licenses/</a>.");
371
372QDialog *dlg = new QDialog(this);
373QLabel *lblIcon = new QLabel(dlg),
374        *lblTitle = new QLabel(dlg),
375        *lblTranslated = new QLabel(dlg);
376#ifdef HANDHELD
377QLabel *lblSubTitle = new QLabel(QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b>").arg(QDate::currentDate().toString("yyyy"), QApplication::organizationDomain(), QApplication::organizationName()), dlg);
378#endif // HANDHELD
379QTextBrowser *txtAbout = new QTextBrowser(dlg);
380QVBoxLayout *vb = new QVBoxLayout();
381QHBoxLayout *hb1 = new QHBoxLayout(),
382        *hb2 = new QHBoxLayout();
383QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dlg);
384
385        lblTitle->setOpenExternalLinks(true);
386        lblTitle->setText(title);
387        lblTitle->setAlignment(Qt::AlignTop);
388        lblTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
389#ifndef HANDHELD
390        lblTitle->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().window().color().name(), palette().shadow().color().name()));
391#endif // HANDHELD
392
393        lblIcon->setPixmap(QPixmap(":/images/tspsg.png").scaledToHeight(lblTitle->sizeHint().height(), Qt::SmoothTransformation));
394        lblIcon->setAlignment(Qt::AlignVCenter);
395#ifndef HANDHELD
396        lblIcon->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().window().color().name(), palette().windowText().color().name()));
397#endif // HANDHELD
398
399        hb1->addWidget(lblIcon);
400        hb1->addWidget(lblTitle);
401
402        txtAbout->setWordWrapMode(QTextOption::NoWrap);
403        txtAbout->setOpenExternalLinks(true);
404        txtAbout->setHtml(about);
405        txtAbout->moveCursor(QTextCursor::Start);
406#ifndef HANDHELD
407        txtAbout->setStyleSheet(QString("QTextBrowser {border-color: %1; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().shadow().color().name()));
408#endif // HANDHELD
409
410        bb->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor));
411
412        lblTranslated->setText(QApplication::translate("--------", "TRANSLATION", "Please, provide translator credits here."));
413        if (lblTranslated->text() == "TRANSLATION")
414                lblTranslated->hide();
415        else {
416                lblTranslated->setOpenExternalLinks(true);
417#ifndef HANDHELD
418                lblTranslated->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().window().color().name(), palette().shadow().color().name()));
419#endif // HANDHELD
420                hb2->addWidget(lblTranslated);
421        }
422
423        hb2->addWidget(bb);
424
425#ifdef Q_OS_WINCE_WM
426        vb->setMargin(3);
427#endif // Q_OS_WINCE_WM
428        vb->addLayout(hb1);
429#ifdef HANDHELD
430        vb->addWidget(lblSubTitle);
431#endif // HANDHELD
432        vb->addWidget(txtAbout);
433        vb->addLayout(hb2);
434
435        dlg->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
436        dlg->setWindowTitle(tr("About TSPSG"));
437        dlg->setLayout(vb);
438
439        connect(bb, SIGNAL(accepted()), dlg, SLOT(accept()));
440
441#ifdef Q_OS_WIN32
442        // Adding some eyecandy in Vista and 7 :-)
443        if (QtWin::isCompositionEnabled())  {
444                QtWin::enableBlurBehindWindow(dlg, true);
445        }
446#endif // Q_OS_WIN32
447
448        dlg->resize(450, 350);
449
450        dlg->exec();
451
452        delete dlg;
453}
454
455void MainWindow::buttonBackToTaskClicked()
456{
457        tabWidget->setCurrentIndex(0);
458}
459
460void MainWindow::buttonRandomClicked()
461{
462        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
463        tspmodel->randomize();
464        QApplication::restoreOverrideCursor();
465}
466
467void MainWindow::buttonSolveClicked()
468{
469TMatrix matrix;
470QList<double> row;
471int n = spinCities->value();
472bool ok;
473        for (int r = 0; r < n; r++) {
474                row.clear();
475                for (int c = 0; c < n; c++) {
476                        row.append(tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok));
477                        if (!ok) {
478                                QMessageBox::critical(this, tr("Data error"), tr("Error in cell [Row %1; Column %2]: Invalid data format.").arg(r + 1).arg(c + 1));
479                                return;
480                        }
481                }
482                matrix.append(row);
483        }
484
485QProgressDialog pd(this);
486QProgressBar *pb = new QProgressBar(&pd);
487        pb->setAlignment(Qt::AlignCenter);
488        pb->setFormat(tr("%v of %1 parts found").arg(n));
489        pd.setBar(pb);
490        pd.setMaximum(n);
491        pd.setAutoReset(false);
492        pd.setLabelText(tr("Calculating optimal route..."));
493        pd.setWindowTitle(tr("Solution Progress"));
494        pd.setWindowModality(Qt::ApplicationModal);
495        pd.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
496        pd.show();
497
498CTSPSolver solver;
499        connect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
500        connect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
501SStep *root = solver.solve(n, matrix);
502        disconnect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
503        disconnect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
504        if (!root) {
505                pd.reset();
506                if (!solver.wasCanceled())
507                        QMessageBox::warning(this, tr("Solution Result"), tr("Unable to find a solution.\nMaybe, this task has no solution."));
508                return;
509        }
510        pb->setFormat(tr("Generating header"));
511        pd.setLabelText(tr("Generating solution output..."));
512        pd.setMaximum(n);
513        pd.setValue(0);
514
515        solutionText->clear();
516        solutionText->setDocumentTitle(tr("Solution of Variant #%1 Task").arg(spinVariant->value()));
517
518QPainter pic;
519        pic.begin(&graph);
520        pic.setRenderHint(QPainter::Antialiasing);
521
522QTextDocument *doc = solutionText->document();
523QTextCursor cur(doc);
524
525        cur.beginEditBlock();
526        cur.setBlockFormat(fmt_paragraph);
527        cur.insertText(tr("Variant #%1 Task").arg(spinVariant->value()), fmt_default);
528        cur.insertBlock(fmt_paragraph);
529        cur.insertText(tr("Task:"));
530        outputMatrix(cur, matrix);
531        drawNode(pic, 0);
532        cur.insertHtml("<hr>");
533        cur.insertBlock(fmt_paragraph);
534int imgpos = cur.position();
535        cur.insertText(tr("Variant #%1 Solution").arg(spinVariant->value()), fmt_default);
536        cur.endEditBlock();
537
538SStep *step = root;
539        n = 1;
540        pb->setFormat(tr("Generating step %v"));
541        while (n < spinCities->value()) {
542                if (pd.wasCanceled()) {
543                        pd.setLabelText(tr("Cleaning up..."));
544                        pd.setMaximum(0);
545                        pd.setCancelButton(NULL);
546                        pd.show();
547                        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
548                        solver.cleanup(true);
549                        solutionText->clear();
550                        toggleSolutionActions(false);
551                        return;
552                }
553                pd.setValue(n);
554
555                if (step->prNode->prNode != NULL || ((step->prNode->prNode == NULL) && (step->plNode->prNode == NULL))) {
556                        if (n != spinCities->value()) {
557                                cur.beginEditBlock();
558                                cur.insertBlock(fmt_paragraph);
559                                cur.insertText(tr("Step #%1").arg(n++));
560                                if (settings->value("Output/ShowMatrix", DEF_SHOW_MATRIX).toBool() && (!settings->value("Output/UseShowMatrixLimit", DEF_USE_SHOW_MATRIX_LIMIT).toBool() || (settings->value("Output/UseShowMatrixLimit", DEF_USE_SHOW_MATRIX_LIMIT).toBool() && (spinCities->value() <= settings->value("Output/ShowMatrixLimit", DEF_SHOW_MATRIX_LIMIT).toInt())))) {
561                                        outputMatrix(cur, *step);
562                                }
563                                cur.insertBlock(fmt_paragraph);
564                                cur.insertText(tr("Selected candidate for branching: %1.").arg(tr("(%1;%2)").arg(step->candidate.nRow + 1).arg(step->candidate.nCol + 1)), fmt_default);
565                                if (!step->alts.empty()) {
566SCandidate cand;
567QString alts;
568                                        foreach(cand, step->alts) {
569                                                if (!alts.isEmpty())
570                                                        alts += ", ";
571                                                alts += tr("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1);
572                                        }
573                                        cur.insertBlock(fmt_paragraph);
574                                        cur.insertText(tr("%n alternate candidate(s) for branching: %1.", "", step->alts.count()).arg(alts), fmt_altlist);
575                                }
576                                cur.insertBlock(fmt_paragraph);
577                                cur.insertText(" ", fmt_default);
578                                cur.endEditBlock();
579                        }
580                }
581                if (n < spinCities->value()) {
582                        if (step->prNode != NULL)
583                                drawNode(pic, n - 1, false, step->prNode);
584                        if (step->plNode != NULL)
585                                drawNode(pic, n - 1, true, step->plNode);
586                }
587                if (step->prNode->prNode != NULL) {
588                        step = step->prNode;
589                } else if (step->plNode->prNode != NULL) {
590                        step = step->plNode;
591                } else
592                        break;
593        }
594        pb->setFormat(tr("Generating footer"));
595        pd.setValue(n);
596
597        cur.beginEditBlock();
598        cur.insertBlock(fmt_paragraph);
599        if (solver.isOptimal())
600                cur.insertText(tr("Optimal path:"));
601        else
602                cur.insertText(tr("Resulting path:"));
603
604        cur.insertBlock(fmt_paragraph);
605        cur.insertText("  " + solver.getSortedPath());
606
607        cur.insertBlock(fmt_paragraph);
608        if (isInteger(step->price))
609                cur.insertHtml("<p>" + tr("The price is <b>%n</b> unit(s).", "", qRound(step->price)) + "</p>");
610        else
611                cur.insertHtml("<p>" + tr("The price is <b>%1</b> units.").arg(step->price, 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()) + "</p>");
612        if (!solver.isOptimal()) {
613                cur.insertBlock(fmt_paragraph);
614                cur.insertText(" ");
615                cur.insertBlock(fmt_paragraph);
616                cur.insertHtml("<p>" + tr("<b>WARNING!!!</b><br>This result is a record, but it may not be optimal.<br>Iterations need to be continued to check whether this result is optimal or get an optimal one.") + "</p>");
617        }
618        cur.endEditBlock();
619        pic.end();
620
621QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_ARGB32);
622        i.fill(0);
623        pic.begin(&i);
624        pic.drawPicture(1, 1, graph);
625        pic.end();
626        doc->addResource(QTextDocument::ImageResource, QUrl("tspsg://graph.pic"), i);
627
628QTextImageFormat img;
629        img.setName("tspsg://graph.pic");
630
631        cur.setPosition(imgpos);
632        cur.insertImage(img, QTextFrameFormat::FloatRight);
633
634        if (settings->value("Output/ScrollToEnd", DEF_SCROLL_TO_END).toBool()) {
635                // Scrolling to the end of the text.
636                solutionText->moveCursor(QTextCursor::End);
637        } else
638                solutionText->moveCursor(QTextCursor::Start);
639
640        pd.setLabelText(tr("Cleaning up..."));
641        pd.setMaximum(0);
642        pd.setCancelButton(NULL);
643        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
644        solver.cleanup(true);
645        toggleSolutionActions();
646        tabWidget->setCurrentIndex(1);
647}
648
649void MainWindow::dataChanged()
650{
651        setWindowModified(true);
652}
653
654void MainWindow::dataChanged(const QModelIndex &tl, const QModelIndex &br)
655{
656        setWindowModified(true);
657        if (settings->value("Autosize", DEF_AUTOSIZE).toBool()) {
658                for (int k = tl.row(); k <= br.row(); k++)
659                        taskView->resizeRowToContents(k);
660                for (int k = tl.column(); k <= br.column(); k++)
661                        taskView->resizeColumnToContents(k);
662        }
663}
664
665#ifdef Q_OS_WINCE_WM
666void MainWindow::changeEvent(QEvent *ev)
667{
668        if ((ev->type() == QEvent::ActivationChange) && isActiveWindow())
669                desktopResized(0);
670
671        QWidget::changeEvent(ev);
672}
673
674void MainWindow::desktopResized(int screen)
675{
676        if ((screen != 0) || !isActiveWindow())
677                return;
678
679QRect availableGeometry = QApplication::desktop()->availableGeometry(0);
680        if (currentGeometry != availableGeometry) {
681                QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
682                /*!
683                 * \hack HACK: This hack checks whether \link QDesktopWidget::availableGeometry() availableGeometry()\endlink's \c top + \c hegiht = \link QDesktopWidget::screenGeometry() screenGeometry()\endlink's \c height.
684                 *  If \c true, the window gets maximized. If we used \c setGeometry() in this case, the bottom of the
685                 *  window would end up being behind the soft buttons. Is this a bug in Qt or Windows Mobile?
686                 */
687                if ((availableGeometry.top() + availableGeometry.height()) == QApplication::desktop()->screenGeometry().height()) {
688                        setWindowState(windowState() | Qt::WindowMaximized);
689                } else {
690                        if (windowState() & Qt::WindowMaximized)
691                                setWindowState(windowState() ^ Qt::WindowMaximized);
692                        setGeometry(availableGeometry);
693                }
694                currentGeometry = availableGeometry;
695                QApplication::restoreOverrideCursor();
696        }
697}
698#endif // Q_OS_WINCE_WM
699
700void MainWindow::numCitiesChanged(int nCities)
701{
702        blockSignals(true);
703        spinCities->setValue(nCities);
704        blockSignals(false);
705}
706
707#ifndef QT_NO_PRINTER
708void MainWindow::printPreview(QPrinter *printer)
709{
710        solutionText->print(printer);
711}
712#endif // QT_NO_PRINTER
713
714void MainWindow::spinCitiesValueChanged(int n)
715{
716        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
717int count = tspmodel->numCities();
718        tspmodel->setNumCities(n);
719        if ((n > count) && settings->value("Autosize", DEF_AUTOSIZE).toBool())
720                for (int k = count; k < n; k++) {
721                        taskView->resizeColumnToContents(k);
722                        taskView->resizeRowToContents(k);
723                }
724        QApplication::restoreOverrideCursor();
725}
726
727void MainWindow::closeEvent(QCloseEvent *ev)
728{
729        if (!maybeSave()) {
730                ev->ignore();
731                return;
732        }
733        if (!settings->value("SettingsReset", false).toBool()) {
734                settings->setValue("NumCities", spinCities->value());
735
736                // Saving Main Window state
737                if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
738                        settings->beginGroup("MainWindow");
739#ifndef HANDHELD
740                        settings->setValue("Geometry", saveGeometry());
741#endif // HANDHELD
742                        settings->setValue("State", saveState());
743                        settings->endGroup();
744                }
745        } else {
746                settings->remove("SettingsReset");
747        }
748
749        QMainWindow::closeEvent(ev);
750}
751
752void MainWindow::dragEnterEvent(QDragEnterEvent *ev)
753{
754        if (ev->mimeData()->hasUrls() && (ev->mimeData()->urls().count() == 1)) {
755QFileInfo fi(ev->mimeData()->urls().first().toLocalFile());
756                if ((fi.suffix() == "tspt") || (fi.suffix() == "zkt"))
757                        ev->acceptProposedAction();
758        }
759}
760
761void MainWindow::drawNode(QPainter &pic, int nstep, bool left, SStep *step)
762{
763const int r = 35;
764qreal x, y;
765        if (step != NULL)
766                x = left ? r : r * 3.5;
767        else
768                x = r * 2.25;
769        y = r * (3 * nstep + 1);
770
771        pic.drawEllipse(QPointF(x, y), r, r);
772
773        if (step != NULL) {
774QFont font;
775                if (left) {
776                        font = pic.font();
777                        font.setStrikeOut(true);
778                        pic.setFont(font);
779                }
780                pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, tr("(%1;%2)").arg(step->pNode->candidate.nRow + 1).arg(step->pNode->candidate.nCol + 1) + "\n");
781                if (left) {
782                        font.setStrikeOut(false);
783                        pic.setFont(font);
784                }
785                pic.setBackgroundMode(Qt::OpaqueMode);
786                pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, isInteger(step->price) ?  QString("\n%1").arg(step->price) : QString("\n%1").arg(step->price, 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()));
787                pic.setBackgroundMode(Qt::TransparentMode);
788        } else {
789                pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, tr("Root"));
790        }
791
792        if (nstep == 1)
793                pic.drawLine(QPointF(r * 2.25, r * (3 * (nstep - 1) + 2)), QPointF(x, y - r));
794        else
795                pic.drawLine(QPointF(r * 3.5, r * (3 * (nstep - 1) + 2)), QPointF(x, y - r));
796
797}
798
799void MainWindow::dropEvent(QDropEvent *ev)
800{
801        if (maybeSave() && tspmodel->loadTask(ev->mimeData()->urls().first().toLocalFile())) {
802                setFileName(ev->mimeData()->urls().first().toLocalFile());
803                tabWidget->setCurrentIndex(0);
804                setWindowModified(false);
805                solutionText->clear();
806                toggleSolutionActions(false);
807
808                ev->acceptProposedAction();
809        }
810}
811
812bool MainWindow::hasUpdater() const
813{
814#ifdef Q_OS_WIN32
815        return QFile::exists("updater/Update.exe");
816#else // Q_OS_WIN32
817        return false;
818#endif // Q_OS_WIN32
819}
820
821void MainWindow::initDocStyleSheet()
822{
823        solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>());
824
825        fmt_paragraph.setTopMargin(0);
826        fmt_paragraph.setRightMargin(10);
827        fmt_paragraph.setBottomMargin(0);
828        fmt_paragraph.setLeftMargin(10);
829
830        fmt_table.setTopMargin(5);
831        fmt_table.setRightMargin(10);
832        fmt_table.setBottomMargin(5);
833        fmt_table.setLeftMargin(10);
834        fmt_table.setBorder(0);
835        fmt_table.setBorderStyle(QTextFrameFormat::BorderStyle_None);
836        fmt_table.setCellSpacing(5);
837
838        fmt_cell.setAlignment(Qt::AlignHCenter);
839
840QColor color = settings->value("Output/Colors/Text", DEF_TEXT_COLOR).value<QColor>();
841QColor hilight;
842        if (color.value() < 192)
843                hilight.setHsv(color.hue(), color.saturation(), 127 + qRound(color.value() / 2));
844        else
845                hilight.setHsv(color.hue(), color.saturation(), color.value() / 2);
846
847        solutionText->document()->setDefaultStyleSheet(QString("* {color: %1;}").arg(color.name()));
848        fmt_default.setForeground(QBrush(color));
849
850        fmt_selected.setForeground(QBrush(settings->value("Output/Colors/Selected", DEF_SELECTED_COLOR).value<QColor>()));
851        fmt_selected.setFontWeight(QFont::Bold);
852
853        fmt_alternate.setForeground(QBrush(settings->value("Output/Colors/Alternate", DEF_ALTERNATE_COLOR).value<QColor>()));
854        fmt_alternate.setFontWeight(QFont::Bold);
855        fmt_altlist.setForeground(QBrush(hilight));
856
857        solutionText->setTextColor(color);
858}
859
860void MainWindow::loadLangList()
861{
862QDir dir(PATH_L10N, "tspsg_*.qm", QDir::Name | QDir::IgnoreCase, QDir::Files);
863        if (!dir.exists())
864                return;
865QFileInfoList langs = dir.entryInfoList();
866        if (langs.size() <= 0)
867                return;
868QAction *a;
869QTranslator t;
870QString name;
871        for (int k = 0; k < langs.size(); k++) {
872                QFileInfo lang = langs.at(k);
873                if (lang.completeBaseName().compare("tspsg_en", Qt::CaseInsensitive) && t.load(lang.completeBaseName(), PATH_L10N)) {
874                        name = t.translate("--------", "LANGNAME", "Please, provide a native name of your translation language here.");
875                        a = menuSettingsLanguage->addAction(name);
876                        a->setStatusTip(QString("Set application language to %1").arg(name));
877                        a->setData(lang.completeBaseName().mid(6));
878                        a->setCheckable(true);
879                        a->setActionGroup(groupSettingsLanguageList);
880                        if (settings->value("Language", QLocale::system().name()).toString().startsWith(lang.completeBaseName().mid(6)))
881                                a->setChecked(true);
882                }
883        }
884}
885
886bool MainWindow::loadLanguage(const QString &lang)
887{
888// i18n
889bool ad = false;
890QString lng = lang;
891        if (lng.isEmpty()) {
892                ad = settings->value("Language", "").toString().isEmpty();
893                lng = settings->value("Language", QLocale::system().name()).toString();
894        }
895static QTranslator *qtTranslator; // Qt library translator
896        if (qtTranslator) {
897                qApp->removeTranslator(qtTranslator);
898                delete qtTranslator;
899                qtTranslator = NULL;
900        }
901static QTranslator *translator; // Application translator
902        if (translator) {
903                qApp->removeTranslator(translator);
904                delete translator;
905                translator = NULL;
906        }
907
908        if (lng == "en")
909                return true;
910
911        // Trying to load system Qt library translation...
912        qtTranslator = new QTranslator(this);
913        if (qtTranslator->load("qt_" + lng, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
914                qApp->installTranslator(qtTranslator);
915        else {
916                // No luck. Let's try to load a bundled one.
917                if (qtTranslator->load("qt_" + lng, PATH_L10N))
918                        qApp->installTranslator(qtTranslator);
919                else {
920                        // Qt library translation unavailable
921                        delete qtTranslator;
922                        qtTranslator = NULL;
923                }
924        }
925
926        // Now let's load application translation.
927        translator = new QTranslator(this);
928        if (translator->load("tspsg_" + lng, PATH_L10N))
929                qApp->installTranslator(translator);
930        else {
931                delete translator;
932                translator = NULL;
933                if (!ad) {
934                        settings->remove("Language");
935                        QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
936                        if (isVisible())
937                                QMessageBox::warning(this, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection."));
938                        else
939                                QMessageBox::warning(NULL, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection."));
940                        QApplication::restoreOverrideCursor();
941                }
942                return false;
943        }
944        return true;
945}
946
947bool MainWindow::maybeSave()
948{
949        if (!isWindowModified())
950                return true;
951int res = QMessageBox::warning(this, tr("Unsaved Changes"), tr("Would you like to save changes in the current task?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
952        if (res == QMessageBox::Save)
953                return actionFileSaveTriggered();
954        else if (res == QMessageBox::Cancel)
955                return false;
956        else
957                return true;
958}
959
960void MainWindow::outputMatrix(QTextCursor &cur, const TMatrix &matrix)
961{
962int n = spinCities->value();
963QTextTable *table = cur.insertTable(n, n, fmt_table);
964
965        for (int r = 0; r < n; r++) {
966                for (int c = 0; c < n; c++) {
967                        cur = table->cellAt(r, c).firstCursorPosition();
968                        cur.setBlockFormat(fmt_cell);
969                        cur.setBlockCharFormat(fmt_default);
970                        if (matrix.at(r).at(c) == INFINITY)
971                                cur.insertText(INFSTR);
972                        else
973                                cur.insertText(isInteger(matrix.at(r).at(c)) ? QString("%1").arg(matrix.at(r).at(c)) : QString("%1").arg(matrix.at(r).at(c), 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()));
974                }
975                QApplication::processEvents();
976        }
977        cur.movePosition(QTextCursor::End);
978}
979
980void MainWindow::outputMatrix(QTextCursor &cur, const SStep &step)
981{
982int n = spinCities->value();
983QTextTable *table = cur.insertTable(n, n, fmt_table);
984
985        for (int r = 0; r < n; r++) {
986                for (int c = 0; c < n; c++) {
987                        cur = table->cellAt(r, c).firstCursorPosition();
988                        cur.setBlockFormat(fmt_cell);
989                        if (step.matrix.at(r).at(c) == INFINITY)
990                                cur.insertText(INFSTR, fmt_default);
991                        else if ((r == step.candidate.nRow) && (c == step.candidate.nCol))
992                                cur.insertText(isInteger(step.matrix.at(r).at(c)) ? QString("%1").arg(step.matrix.at(r).at(c)) : QString("%1").arg(step.matrix.at(r).at(c), 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()), fmt_selected);
993                        else {
994SCandidate cand;
995                                cand.nRow = r;
996                                cand.nCol = c;
997                                if (step.alts.contains(cand))
998                                        cur.insertText(isInteger(step.matrix.at(r).at(c)) ? QString("%1").arg(step.matrix.at(r).at(c)) : QString("%1").arg(step.matrix.at(r).at(c), 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()), fmt_alternate);
999                                else
1000                                        cur.insertText(isInteger(step.matrix.at(r).at(c)) ? QString("%1").arg(step.matrix.at(r).at(c)) : QString("%1").arg(step.matrix.at(r).at(c), 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()), fmt_default);
1001                        }
1002                }
1003                QApplication::processEvents();
1004        }
1005
1006        cur.movePosition(QTextCursor::End);
1007}
1008
1009void MainWindow::retranslateUi(bool all)
1010{
1011        if (all)
1012                Ui::MainWindow::retranslateUi(this);
1013
1014        actionSettingsLanguageEnglish->setStatusTip(tr("Set application language to %1").arg("English"));
1015
1016#ifndef QT_NO_PRINTER
1017        actionFilePrintPreview->setText(QApplication::translate("MainWindow", "P&rint Preview...", 0, QApplication::UnicodeUTF8));
1018#ifndef QT_NO_TOOLTIP
1019        actionFilePrintPreview->setToolTip(QApplication::translate("MainWindow", "Preview solution results", 0, QApplication::UnicodeUTF8));
1020#endif // QT_NO_TOOLTIP
1021#ifndef QT_NO_STATUSTIP
1022        actionFilePrintPreview->setStatusTip(QApplication::translate("MainWindow", "Preview current solution results before printing", 0, QApplication::UnicodeUTF8));
1023#endif // QT_NO_STATUSTIP
1024
1025        actionFilePrint->setText(QApplication::translate("MainWindow", "&Print...", 0, QApplication::UnicodeUTF8));
1026#ifndef QT_NO_TOOLTIP
1027        actionFilePrint->setToolTip(QApplication::translate("MainWindow", "Print solution", 0, QApplication::UnicodeUTF8));
1028#endif // QT_NO_TOOLTIP
1029#ifndef QT_NO_STATUSTIP
1030        actionFilePrint->setStatusTip(QApplication::translate("MainWindow", "Print current solution results", 0, QApplication::UnicodeUTF8));
1031#endif // QT_NO_STATUSTIP
1032        actionFilePrint->setShortcut(QApplication::translate("MainWindow", "Ctrl+P", 0, QApplication::UnicodeUTF8));
1033#endif // QT_NO_PRINTER
1034#ifdef Q_OS_WIN32
1035        actionHelpCheck4Updates->setText(tr("Check for &Updates..."));
1036#ifndef QT_NO_TOOLTIP
1037        actionHelpCheck4Updates->setToolTip(tr("Check for %1 updates").arg(QApplication::applicationName()));
1038#endif // QT_NO_TOOLTIP
1039#ifndef QT_NO_STATUSTIP
1040        actionHelpCheck4Updates->setStatusTip(tr("Check for %1 updates").arg(QApplication::applicationName()));
1041#endif // QT_NO_STATUSTIP
1042#endif // Q_OS_WIN32
1043}
1044
1045bool MainWindow::saveTask() {
1046QStringList filters(tr("%1 Task File").arg("TSPSG") + " (*.tspt)");
1047        filters.append(tr("All Files") + " (*)");
1048QString file;
1049        if (fileName.endsWith(".tspt", Qt::CaseInsensitive))
1050                file = fileName;
1051        else
1052                file = QFileInfo(fileName).canonicalPath() + "/" + QFileInfo(fileName).completeBaseName() + ".tspt";
1053
1054QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
1055        file = QFileDialog::getSaveFileName(this, tr("Task Save"), file, filters.join(";;"), NULL, opts);
1056
1057        if (file.isEmpty())
1058                return false;
1059        if (tspmodel->saveTask(file)) {
1060                setFileName(file);
1061                setWindowModified(false);
1062                return true;
1063        }
1064        return false;
1065}
1066
1067void MainWindow::setFileName(const QString &fileName)
1068{
1069        this->fileName = fileName;
1070        setWindowTitle(QString("%1[*] - %2").arg(QFileInfo(fileName).completeBaseName()).arg(tr("Travelling Salesman Problem")));
1071}
1072
1073void MainWindow::setupUi()
1074{
1075        Ui::MainWindow::setupUi(this);
1076
1077#if QT_VERSION >= 0x040600
1078        setToolButtonStyle(Qt::ToolButtonFollowStyle);
1079#endif
1080
1081#ifndef HANDHELD
1082QStatusBar *statusbar = new QStatusBar(this);
1083        statusbar->setObjectName("statusbar");
1084        setStatusBar(statusbar);
1085#endif // HANDHELD
1086
1087#ifdef Q_OS_WINCE_WM
1088        menuBar()->setDefaultAction(menuFile->menuAction());
1089
1090QScrollArea *scrollArea = new QScrollArea(this);
1091        scrollArea->setFrameShape(QFrame::NoFrame);
1092        scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1093        scrollArea->setWidgetResizable(true);
1094        scrollArea->setWidget(tabWidget);
1095        setCentralWidget(scrollArea);
1096#else
1097        setCentralWidget(tabWidget);
1098#endif // Q_OS_WINCE_WM
1099
1100        //! \hack HACK: A little hack for toolbar icons to have a sane size.
1101#ifdef Q_OS_WINCE_WM
1102        toolBar->setIconSize(QSize(logicalDpiX() / 4, logicalDpiY() / 4));
1103#elif defined(Q_OS_SYMBIAN)
1104        toolBar->setIconSize(QSize(logicalDpiX() / 5, logicalDpiY() / 5));
1105#endif // Q_OS_WINCE_WM
1106
1107        solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>());
1108        solutionText->setWordWrapMode(QTextOption::WordWrap);
1109
1110#ifndef QT_NO_PRINTER
1111        actionFilePrintPreview = new QAction(this);
1112        actionFilePrintPreview->setObjectName("actionFilePrintPreview");
1113        actionFilePrintPreview->setEnabled(false);
1114        actionFilePrintPreview->setIcon(QIcon(":/images/icons/document_preview.png"));
1115
1116        actionFilePrint = new QAction(this);
1117        actionFilePrint->setObjectName("actionFilePrint");
1118        actionFilePrint->setEnabled(false);
1119        actionFilePrint->setIcon(QIcon(":/images/icons/fileprint.png"));
1120
1121        menuFile->insertAction(actionFileExit,actionFilePrintPreview);
1122        menuFile->insertAction(actionFileExit,actionFilePrint);
1123        menuFile->insertSeparator(actionFileExit);
1124
1125        toolBar->insertAction(actionSettingsPreferences,actionFilePrint);
1126#endif // QT_NO_PRINTER
1127#ifdef Q_OS_WIN32
1128        actionHelpCheck4Updates = new QAction(this);
1129        actionHelpCheck4Updates->setEnabled(hasUpdater());
1130        menuHelp->insertAction(actionHelpAboutQt, actionHelpCheck4Updates);
1131        menuHelp->insertSeparator(actionHelpAboutQt);
1132#endif // Q_OS_WIN32
1133
1134        groupSettingsLanguageList = new QActionGroup(this);
1135        actionSettingsLanguageEnglish->setData("en");
1136        actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
1137        loadLangList();
1138        actionSettingsLanguageAutodetect->setChecked(settings->value("Language", "").toString().isEmpty());
1139
1140        spinCities->setMaximum(MAX_NUM_CITIES);
1141
1142        retranslateUi(false);
1143
1144#ifdef Q_OS_WIN32
1145        // Adding some eyecandy in Vista and 7 :-)
1146        if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
1147                toggleTranclucency(true);
1148        }
1149#endif // Q_OS_WIN32
1150}
1151
1152void MainWindow::toggleSolutionActions(bool enable)
1153{
1154        buttonSaveSolution->setEnabled(enable);
1155        actionFileSaveAsSolution->setEnabled(enable);
1156        solutionText->setEnabled(enable);
1157#ifndef QT_NO_PRINTER
1158        actionFilePrint->setEnabled(enable);
1159        actionFilePrintPreview->setEnabled(enable);
1160#endif // QT_NO_PRINTER
1161}
1162
1163void MainWindow::toggleTranclucency(bool enable)
1164{
1165#ifdef Q_OS_WIN32
1166        toggleStyle(labelVariant, enable);
1167        toggleStyle(labelCities, enable);
1168        toggleStyle(statusBar(), enable);
1169        tabWidget->setDocumentMode(enable);
1170        QtWin::enableBlurBehindWindow(this, enable);
1171#else
1172        Q_UNUSED(enable);
1173#endif // Q_OS_WIN32
1174}
Note: See TracBrowser for help on using the repository browser.