source: tspsg/src/mainwindow.cpp @ ccdffe3a5f

0.1.4.170-beta2-bb10
Last change on this file since ccdffe3a5f was ccdffe3a5f, checked in by Oleksii Serdiuk, 12 years ago

Removed printing related items from menu as there's no printer.

Made dialogs to be shown maximized.

  • Property mode set to 100644
File size: 71.5 KB
RevLine 
[1babbd6ba3]1/*
2 *  TSPSG: TSP Solver and Generator
[bfe1e5e2ea]3 *  Copyright (C) 2007-2011 Lёppa <contacts[at]oleksii[dot]name>
[1babbd6ba3]4 *
5 *  $Id$
6 *  $URL$
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
[97e90f9be6]26#ifdef Q_WS_WIN32
[b8a2a118c4]27#   include "shobjidl.h"
[43c29c04ba]28#endif
29
[3cadf24d00]30#ifdef _T_T_L_
31#include "_.h"
[e9db3e216b]32_C_ _R_ _Y_ _P_ _T_
[3cadf24d00]33#endif
34
[1babbd6ba3]35/*!
36 * \brief Class constructor.
37 * \param parent Main Window parent widget.
38 *
39 *  Initializes Main Window and creates its layout based on target OS.
40 *  Loads TSPSG settings and opens a task file if it was specified as a commandline parameter.
41 */
42MainWindow::MainWindow(QWidget *parent)
[9eb63a1598]43    : QMainWindow(parent)
[1babbd6ba3]44{
[9eb63a1598]45    settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this);
[1babbd6ba3]46
[9eb63a1598]47    if (settings->contains("Style")) {
[e3533af1cf]48QStyle *s = QStyleFactory::create(settings->value("Style").toString());
[9eb63a1598]49        if (s != NULL)
50            QApplication::setStyle(s);
51        else
52            settings->remove("Style");
53    }
[e3533af1cf]54
[9eb63a1598]55    loadLanguage();
56    setupUi();
57    setAcceptDrops(true);
[1babbd6ba3]58
[9eb63a1598]59    initDocStyleSheet();
[1babbd6ba3]60
61#ifndef QT_NO_PRINTER
[9eb63a1598]62    printer = new QPrinter(QPrinter::HighResolution);
[a885c3d9d2]63    settings->beginGroup("Printer");
[20e8115cee]64QPrinter::PaperSize size = qvariant_cast<QPrinter::PaperSize>(settings->value("PaperSize", DEF_PAGE_SIZE));
65    if (size != QPrinter::Custom) {
66        printer->setPaperSize(size);
67    } else {
68        printer->setPaperSize(QSizeF(settings->value("PaperWidth").toReal(), settings->value("PaperHeight").toReal()),
69                              QPrinter::Millimeter);
70    }
71
[a885c3d9d2]72    printer->setOrientation(qvariant_cast<QPrinter::Orientation>(settings->value("PageOrientation", DEF_PAGE_ORIENTATION)));
73    printer->setPageMargins(
[20e8115cee]74        settings->value("MarginLeft", DEF_MARGIN_LEFT).toReal(),
75        settings->value("MarginTop", DEF_MARGIN_TOP).toReal(),
76        settings->value("MarginRight", DEF_MARGIN_RIGHT).toReal(),
77        settings->value("MarginBottom", DEF_MARGIN_BOTTOM).toReal(),
[a885c3d9d2]78        QPrinter::Millimeter);
79    settings->endGroup();
[1babbd6ba3]80#endif // QT_NO_PRINTER
81
[97e90f9be6]82#ifdef Q_WS_WINCE_WM
[9eb63a1598]83    currentGeometry = QApplication::desktop()->availableGeometry(0);
84    // We need to react to SIP show/hide and resize the window appropriately
85    connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), SLOT(desktopResized(int)));
[97e90f9be6]86#endif // Q_WS_WINCE_WM
[9eb63a1598]87    connect(actionFileNew, SIGNAL(triggered()), SLOT(actionFileNewTriggered()));
88    connect(actionFileOpen, SIGNAL(triggered()), SLOT(actionFileOpenTriggered()));
89    connect(actionFileSave, SIGNAL(triggered()), SLOT(actionFileSaveTriggered()));
90    connect(actionFileSaveAsTask, SIGNAL(triggered()), SLOT(actionFileSaveAsTaskTriggered()));
91    connect(actionFileSaveAsSolution, SIGNAL(triggered()), SLOT(actionFileSaveAsSolutionTriggered()));
[ccdffe3a5f]92#ifndef QT_NO_PRINTDIALOG
[9eb63a1598]93    connect(actionFilePrintPreview, SIGNAL(triggered()), SLOT(actionFilePrintPreviewTriggered()));
[20e8115cee]94    connect(actionFilePageSetup, SIGNAL(triggered()), SLOT(actionFilePageSetupTriggered()));
[9eb63a1598]95    connect(actionFilePrint, SIGNAL(triggered()), SLOT(actionFilePrintTriggered()));
[1babbd6ba3]96#endif // QT_NO_PRINTER
[7bb19df196]97#ifndef HANDHELD
[9eb63a1598]98    connect(actionSettingsToolbarsConfigure, SIGNAL(triggered()), SLOT(actionSettingsToolbarsConfigureTriggered()));
[7bb19df196]99#endif // HANDHELD
[9eb63a1598]100    connect(actionSettingsPreferences, SIGNAL(triggered()), SLOT(actionSettingsPreferencesTriggered()));
101    if (actionHelpCheck4Updates != NULL)
102        connect(actionHelpCheck4Updates, SIGNAL(triggered()), SLOT(actionHelpCheck4UpdatesTriggered()));
103    connect(actionSettingsLanguageAutodetect, SIGNAL(triggered(bool)), SLOT(actionSettingsLanguageAutodetectTriggered(bool)));
104    connect(groupSettingsLanguageList, SIGNAL(triggered(QAction *)), SLOT(groupSettingsLanguageListTriggered(QAction *)));
105    connect(actionSettingsStyleSystem, SIGNAL(triggered(bool)), SLOT(actionSettingsStyleSystemTriggered(bool)));
106    connect(groupSettingsStyleList, SIGNAL(triggered(QAction*)), SLOT(groupSettingsStyleListTriggered(QAction*)));
107    connect(actionHelpOnlineSupport, SIGNAL(triggered()), SLOT(actionHelpOnlineSupportTriggered()));
108    connect(actionHelpReportBug, SIGNAL(triggered()), SLOT(actionHelpReportBugTriggered()));
109    connect(actionHelpAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
110    connect(actionHelpAbout, SIGNAL(triggered()), SLOT(actionHelpAboutTriggered()));
111
112    connect(buttonSolve, SIGNAL(clicked()), SLOT(buttonSolveClicked()));
113    connect(buttonRandom, SIGNAL(clicked()), SLOT(buttonRandomClicked()));
114    connect(buttonBackToTask, SIGNAL(clicked()), SLOT(buttonBackToTaskClicked()));
115    connect(spinCities, SIGNAL(valueChanged(int)), SLOT(spinCitiesValueChanged(int)));
[1babbd6ba3]116
117#ifndef HANDHELD
[9eb63a1598]118    // Centering main window
[1babbd6ba3]119QRect rect = geometry();
[9eb63a1598]120    rect.moveCenter(QApplication::desktop()->availableGeometry(this).center());
121    setGeometry(rect);
122    if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
123        // Loading of saved window state
124        settings->beginGroup("MainWindow");
125        restoreGeometry(settings->value("Geometry").toByteArray());
126        restoreState(settings->value("State").toByteArray());
127        settings->endGroup();
128    }
[1babbd6ba3]129#endif // HANDHELD
130
[9eb63a1598]131    tspmodel = new CTSPModel(this);
132    taskView->setModel(tspmodel);
133    connect(tspmodel, SIGNAL(numCitiesChanged(int)), SLOT(numCitiesChanged(int)));
134    connect(tspmodel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
135    connect(tspmodel, SIGNAL(layoutChanged()), SLOT(dataChanged()));
136    if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1))))
137        setFileName(QCoreApplication::arguments().at(1));
138    else {
139        setFileName();
140        spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt());
141        spinCitiesValueChanged(spinCities->value());
142    }
143    setWindowModified(false);
144
145    if (actionHelpCheck4Updates != NULL) {
146        if (!settings->contains("Check4Updates/Enabled")) {
147            QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
148            settings->setValue("Check4Updates/Enabled",
149                QMessageBox::question(this, QCoreApplication::applicationName(),
150                    tr("Would you like %1 to automatically check for updates every %n day(s)?", "", settings->value("Check4Updates/Interval", DEF_UPDATE_CHECK_INTERVAL).toInt()).arg(QCoreApplication::applicationName()),
151                    QMessageBox::Yes | QMessageBox::No
152                ) == QMessageBox::Yes
153            );
154            QApplication::restoreOverrideCursor();
155        }
156        if ((settings->value("Check4Updates/Enabled", DEF_CHECK_FOR_UPDATES).toBool())
157            && (QDate(qvariant_cast<QDate>(settings->value("Check4Updates/LastAttempt"))).daysTo(QDate::currentDate()) >= settings->value("Check4Updates/Interval", DEF_UPDATE_CHECK_INTERVAL).toInt())) {
158            check4Updates(true);
159        }
160    }
[1babbd6ba3]161}
162
163MainWindow::~MainWindow()
164{
165#ifndef QT_NO_PRINTER
[9eb63a1598]166    delete printer;
[1babbd6ba3]167#endif
168}
169
170/* Privates **********************************************************/
171
172void MainWindow::actionFileNewTriggered()
173{
[9eb63a1598]174    if (!maybeSave())
175        return;
176    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
177    tspmodel->clear();
178    setFileName();
179    setWindowModified(false);
180    tabWidget->setCurrentIndex(0);
181    solutionText->clear();
[8f2427aaf0]182    graph = QPicture();
[9eb63a1598]183    toggleSolutionActions(false);
184    QApplication::restoreOverrideCursor();
[1babbd6ba3]185}
186
187void MainWindow::actionFileOpenTriggered()
188{
[9eb63a1598]189    if (!maybeSave())
190        return;
[1babbd6ba3]191
192QStringList filters(tr("All Supported Formats") + " (*.tspt *.zkt)");
[9eb63a1598]193    filters.append(tr("%1 Task Files").arg("TSPSG") + " (*.tspt)");
194    filters.append(tr("%1 Task Files").arg("ZKomModRd") + " (*.zkt)");
195    filters.append(tr("All Files") + " (*)");
[1babbd6ba3]196
[ac76a6a753]197QString file;
[9eb63a1598]198    if ((fileName == tr("Untitled") + ".tspt") && settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool())
199        file = settings->value(OS"/LastUsed/TaskLoadPath").toString();
200    else
201        file = QFileInfo(fileName).path();
[1babbd6ba3]202QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
[9eb63a1598]203    file = QFileDialog::getOpenFileName(this, tr("Task Load"), file, filters.join(";;"), NULL, opts);
204    if (file.isEmpty() || !QFileInfo(file).isFile())
205        return;
206    if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool())
207        settings->setValue(OS"/LastUsed/TaskLoadPath", QFileInfo(file).path());
208
209    if (!tspmodel->loadTask(file))
210        return;
211    setFileName(file);
212    tabWidget->setCurrentIndex(0);
213    setWindowModified(false);
214    solutionText->clear();
215    toggleSolutionActions(false);
[1babbd6ba3]216}
217
218bool MainWindow::actionFileSaveTriggered()
219{
[9eb63a1598]220    if ((fileName == tr("Untitled") + ".tspt") || !fileName.endsWith(".tspt", Qt::CaseInsensitive))
221        return saveTask();
222    else
223        if (tspmodel->saveTask(fileName)) {
224            setWindowModified(false);
225            return true;
226        } else
227            return false;
[1babbd6ba3]228}
229
230void MainWindow::actionFileSaveAsTaskTriggered()
231{
[9eb63a1598]232    saveTask();
[1babbd6ba3]233}
234
235void MainWindow::actionFileSaveAsSolutionTriggered()
236{
237static QString selectedFile;
[9eb63a1598]238    if (selectedFile.isEmpty()) {
239        if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) {
240            selectedFile = settings->value(OS"/LastUsed/SolutionSavePath").toString();
241        }
242    } else
243        selectedFile = QFileInfo(selectedFile).path();
244    if (!selectedFile.isEmpty())
245        selectedFile.append("/");
246    if (fileName == tr("Untitled") + ".tspt") {
[1babbd6ba3]247#ifndef QT_NO_PRINTER
[9eb63a1598]248        selectedFile += "solution.pdf";
[1babbd6ba3]249#else
[9eb63a1598]250        selectedFile += "solution.html";
[1babbd6ba3]251#endif // QT_NO_PRINTER
[9eb63a1598]252    } else {
[1babbd6ba3]253#ifndef QT_NO_PRINTER
[9eb63a1598]254        selectedFile += QFileInfo(fileName).completeBaseName() + ".pdf";
[1babbd6ba3]255#else
[9eb63a1598]256        selectedFile += QFileInfo(fileName).completeBaseName() + ".html";
[1babbd6ba3]257#endif // QT_NO_PRINTER
[9eb63a1598]258    }
[1babbd6ba3]259
260QStringList filters;
261#ifndef QT_NO_PRINTER
[9eb63a1598]262    filters.append(tr("PDF Files") + " (*.pdf)");
[1babbd6ba3]263#endif
[9eb63a1598]264    filters.append(tr("HTML Files") + " (*.html *.htm)");
265    filters.append(tr("OpenDocument Files") + " (*.odt)");
266    filters.append(tr("All Files") + " (*)");
[1babbd6ba3]267
268QFileDialog::Options opts(settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog);
269QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"), NULL, opts);
[9eb63a1598]270    if (file.isEmpty())
271        return;
272    selectedFile = file;
273    if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool())
274        settings->setValue(OS"/LastUsed/SolutionSavePath", QFileInfo(selectedFile).path());
275    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[1babbd6ba3]276#ifndef QT_NO_PRINTER
[8f2427aaf0]277    if (selectedFile.endsWith(".pdf", Qt::CaseInsensitive)) {
278        printer->setOutputFileName(selectedFile);
279        solutionText->document()->print(printer);
280        printer->setOutputFileName(QString());
[9eb63a1598]281        QApplication::restoreOverrideCursor();
282        return;
283    }
[1babbd6ba3]284#endif
[9eb63a1598]285    if (selectedFile.endsWith(".htm", Qt::CaseInsensitive) || selectedFile.endsWith(".html", Qt::CaseInsensitive)) {
[1babbd6ba3]286QFile file(selectedFile);
[9eb63a1598]287        if (!file.open(QFile::WriteOnly)) {
288            QApplication::restoreOverrideCursor();
289            QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(file.errorString()));
290            return;
291        }
[ca3d2a30fa]292QFileInfo fi(selectedFile);
[20015b41e7]293QString format = settings->value("Output/GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT).toString();
[2a436ea693]294#if !defined(NOSVG)
[8f2427aaf0]295        if (!QImageWriter::supportedImageFormats().contains(format.toAscii()) && (format != "svg")) {
[2a436ea693]296#else // NOSVG
[8f2427aaf0]297        if (!QImageWriter::supportedImageFormats().contains(format.toAscii())) {
[2a436ea693]298#endif // NOSVG
[8f2427aaf0]299            format = DEF_GRAPH_IMAGE_FORMAT;
300            settings->remove("Output/GraphImageFormat");
301        }
302QString html = solutionText->document()->toHtml("UTF-8");
303
[9eb63a1598]304        html.replace(QRegExp("font-family:([^;]*);"), "font-family:\\1, 'DejaVu Sans Mono', 'Courier New', Courier, monospace;");
[20015b41e7]305
[8f2427aaf0]306        if (!graph.isNull()) {
307            QString img =  fi.completeBaseName() + "." + format;
308            bool embed = settings->value("Output/EmbedGraphIntoHTML", DEF_EMBED_GRAPH_INTO_HTML).toBool();
309            QByteArray data;
310            QBuffer buf(&data);
311            if (!embed) {
312                html.replace(QRegExp("<img\\s+src=\"tspsg://graph.pic\""), QString("<img src=\"%1\" alt=\"%2\"").arg(img, tr("Solution Graph")));
313            }
[20015b41e7]314
[8f2427aaf0]315            // Saving solution graph in SVG or supported raster format (depending on settings and SVG support)
[2a436ea693]316#if !defined(NOSVG)
[8f2427aaf0]317            if (format == "svg") {
318                QSvgGenerator svg;
319                svg.setSize(QSize(graph.width() + 2, graph.height() + 2));
320                svg.setResolution(graph.logicalDpiX());
321                svg.setFileName(fi.path() + "/" + img);
322                svg.setTitle(tr("Solution Graph"));
323                svg.setDescription(tr("Generated with %1").arg(QCoreApplication::applicationName()));
324                QPainter p;
325                p.begin(&svg);
326                p.drawPicture(1, 1, graph);
327                p.end();
328            } else {
[2a436ea693]329#endif // NOSVG
[8f2427aaf0]330                QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_ARGB32);
331                i.fill(0x00FFFFFF);
332                QPainter p;
333                p.begin(&i);
334                p.drawPicture(1, 1, graph);
335                p.end();
336                QImageWriter pic;
337                if (embed) {
338                    pic.setDevice(&buf);
339                    pic.setFormat(format.toAscii());
340                } else {
341                    pic.setFileName(fi.path() + "/" + img);
342                }
343                if (pic.supportsOption(QImageIOHandler::Description)) {
344                    pic.setText("Title", "Solution Graph");
345                    pic.setText("Software", QCoreApplication::applicationName());
346                }
347                if (format == "png")
348                    pic.setQuality(5);
349                else if (format == "jpeg")
350                    pic.setQuality(80);
351                if (!pic.write(i)) {
352                    QApplication::restoreOverrideCursor();
353                    QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution graph.\nError: %1").arg(pic.errorString()));
354                    return;
355                }
356#if !defined(NOSVG)
[9eb63a1598]357            }
[8f2427aaf0]358#endif // NOSVG
359            if (embed) {
360                html.replace(QRegExp("<img\\s+src=\"tspsg://graph.pic\""), QString("<img src=\"data:image/%1;base64,%2\" alt=\"%3\"").arg(format, data.toBase64(), tr("Solution Graph")));
[9eb63a1598]361            }
362        }
[8f2427aaf0]363        // Saving solution text as HTML
364QTextStream ts(&file);
365        ts.setCodec(QTextCodec::codecForName("UTF-8"));
366        ts << html;
367        file.close();
[9eb63a1598]368    } else {
[ca3d2a30fa]369QTextDocumentWriter dw(selectedFile);
[9eb63a1598]370        if (!selectedFile.endsWith(".odt",Qt::CaseInsensitive))
371            dw.setFormat("plaintext");
372        if (!dw.write(solutionText->document()))
373            QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(dw.device()->errorString()));
374    }
375    QApplication::restoreOverrideCursor();
[1babbd6ba3]376}
377
[ccdffe3a5f]378#ifndef QT_NO_PRINTDIALOG
[1babbd6ba3]379void MainWindow::actionFilePrintPreviewTriggered()
380{
381QPrintPreviewDialog ppd(printer, this);
[9eb63a1598]382    connect(&ppd,SIGNAL(paintRequested(QPrinter *)),SLOT(printPreview(QPrinter *)));
383    ppd.exec();
[144fbe6b96]384
385qreal l, t, r, b;
386    printer->getPageMargins(&l, &t, &r, &b, QPrinter::Millimeter);
387
[a885c3d9d2]388    settings->beginGroup("Printer");
[144fbe6b96]389    settings->setValue("PaperSize", printer->paperSize());
[20e8115cee]390    if (printer->paperSize() == QPrinter::Custom) {
391QSizeF size(printer->paperSize(QPrinter::Millimeter));
392        settings->setValue("PaperWidth", size.width());
393        settings->setValue("PaperHeight", size.height());
394    }
395    settings->setValue("PageOrientation", printer->orientation());
396    settings->setValue("MarginLeft", l);
397    settings->setValue("MarginTop", t);
398    settings->setValue("MarginRight", r);
399    settings->setValue("MarginBottom", b);
400    settings->endGroup();
401}
402
403void MainWindow::actionFilePageSetupTriggered()
404{
405QPageSetupDialog psd(printer, this);
406    if (psd.exec() != QDialog::Accepted)
407        return;
408
409qreal l, t, r ,b;
410    printer->getPageMargins(&l, &t, &r, &b, QPrinter::Millimeter);
411
412    settings->beginGroup("Printer");
413    settings->setValue("PaperSize", printer->paperSize());
414    if (printer->paperSize() == QPrinter::Custom) {
415QSizeF size(printer->paperSize(QPrinter::Millimeter));
416        settings->setValue("PaperWidth", size.width());
417        settings->setValue("PaperHeight", size.height());
418    }
[a885c3d9d2]419    settings->setValue("PageOrientation", printer->orientation());
[144fbe6b96]420    settings->setValue("MarginLeft", l);
421    settings->setValue("MarginTop", t);
422    settings->setValue("MarginRight", r);
423    settings->setValue("MarginBottom", b);
[a885c3d9d2]424    settings->endGroup();
[1babbd6ba3]425}
426
427void MainWindow::actionFilePrintTriggered()
428{
429QPrintDialog pd(printer,this);
[9eb63a1598]430    if (pd.exec() != QDialog::Accepted)
431        return;
432    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
433    solutionText->print(printer);
434    QApplication::restoreOverrideCursor();
[1babbd6ba3]435}
[ccdffe3a5f]436#endif // QT_NO_PRINTDIALOG
[1babbd6ba3]437
438void MainWindow::actionSettingsPreferencesTriggered()
439{
440SettingsDialog sd(this);
[9eb63a1598]441    if (sd.exec() != QDialog::Accepted)
442        return;
443    if (sd.colorChanged() || sd.fontChanged()) {
444        if (!solutionText->document()->isEmpty() && sd.colorChanged())
445            QMessageBox::information(this, tr("Settings Changed"), tr("You have changed color settings.\nThey will be applied to the next solution output."));
446        initDocStyleSheet();
447    }
448    if (sd.translucencyChanged() != 0)
449        toggleTranclucency(sd.translucencyChanged() == 1);
[1babbd6ba3]450}
451
452void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked)
453{
[9eb63a1598]454    if (checked) {
455        settings->remove("Language");
456        QMessageBox::information(this, tr("Language change"), tr("Language will be autodetected on the next %1 start.").arg(QCoreApplication::applicationName()));
457    } else
458        settings->setValue("Language", groupSettingsLanguageList->checkedAction()->data().toString());
[1babbd6ba3]459}
460
461void MainWindow::groupSettingsLanguageListTriggered(QAction *action)
462{
[97e90f9be6]463#ifndef Q_WS_MAEMO_5
[9eb63a1598]464    if (actionSettingsLanguageAutodetect->isChecked())
465        actionSettingsLanguageAutodetect->trigger();
[97e90f9be6]466#endif
[1babbd6ba3]467bool untitled = (fileName == tr("Untitled") + ".tspt");
[9eb63a1598]468    if (loadLanguage(action->data().toString())) {
469        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
470        settings->setValue("Language",action->data().toString());
471        retranslateUi();
472        if (untitled)
473            setFileName();
[b8a2a118c4]474#ifndef HANDHELD
[9eb63a1598]475        if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
476            toggleStyle(labelVariant, true);
477            toggleStyle(labelCities, true);
478        }
[1babbd6ba3]479#endif
[9eb63a1598]480        QApplication::restoreOverrideCursor();
481        if (!solutionText->document()->isEmpty())
482            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."));
483    }
[1babbd6ba3]484}
485
[e3533af1cf]486void MainWindow::actionSettingsStyleSystemTriggered(bool checked)
487{
[9eb63a1598]488    if (checked) {
489        settings->remove("Style");
490        QMessageBox::information(this, tr("Style Change"), tr("To apply the default style you need to restart %1.").arg(QCoreApplication::applicationName()));
491    } else {
492        settings->setValue("Style", groupSettingsStyleList->checkedAction()->text());
493    }
[e3533af1cf]494}
495
496void MainWindow::groupSettingsStyleListTriggered(QAction *action)
497{
498QStyle *s = QStyleFactory::create(action->text());
[9eb63a1598]499    if (s != NULL) {
500        QApplication::setStyle(s);
501        settings->setValue("Style", action->text());
502        actionSettingsStyleSystem->setChecked(false);
503    }
[e3533af1cf]504}
505
[7bb19df196]506#ifndef HANDHELD
507void MainWindow::actionSettingsToolbarsConfigureTriggered()
508{
509QtToolBarDialog dlg(this);
[9eb63a1598]510    dlg.setToolBarManager(toolBarManager);
511    dlg.exec();
[7bb19df196]512QToolButton *tb = static_cast<QToolButton *>(toolBarMain->widgetForAction(actionFileSave));
[9eb63a1598]513    if (tb != NULL) {
514        tb->setMenu(menuFileSaveAs);
515        tb->setPopupMode(QToolButton::MenuButtonPopup);
516        tb->resize(tb->sizeHint());
517    }
[7bb19df196]518
[9eb63a1598]519    loadToolbarList();
[7bb19df196]520}
521#endif // HANDHELD
522
[1babbd6ba3]523void MainWindow::actionHelpCheck4UpdatesTriggered()
524{
[9eb63a1598]525    if (!hasUpdater()) {
[019894f5ef]526        QMessageBox::warning(this, tr("Unsupported Feature"), tr("Sorry, but this feature is not supported on your\nplatform or support for it was not installed."));
[9eb63a1598]527        return;
528    }
[1babbd6ba3]529
[9eb63a1598]530    check4Updates();
[1babbd6ba3]531}
532
533void MainWindow::actionHelpAboutTriggered()
534{
[9eb63a1598]535    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[43c29c04ba]536
[1babbd6ba3]537QString title;
[9eb63a1598]538    title += QString("<b>%1</b><br>").arg(QCoreApplication::applicationName());
539    title += QString("%1: <b>%2</b><br>").arg(tr("Version"), QCoreApplication::applicationVersion());
[1babbd6ba3]540#ifndef HANDHELD
[9eb63a1598]541    title += QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b><br>").arg(QDate::currentDate().toString("yyyy"), QCoreApplication::organizationDomain(), QCoreApplication::organizationName());
[7bb19df196]542#endif // HANDHELD
[9eb63a1598]543    title += QString("<b><a href=\"http://tspsg.info/\">http://tspsg.info/</a></b>");
[1babbd6ba3]544
545QString about;
[9eb63a1598]546    about += QString("%1: <b>%2</b><br>").arg(tr("Target OS (ARCH)"), PLATFROM);
[fddcfa4b55]547    about += QString("%1:<br>").arg(tr("Qt library"));
[9eb63a1598]548    about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Build time"), QT_VERSION_STR);
549    about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Runtime"), qVersion());
[03df0acb95]550    about.append(QString("%1: <b>%2x%3</b><br>").arg(tr("Logical screen DPI")).arg(logicalDpiX()).arg(logicalDpiY()));
[9eb63a1598]551    about += tr("Buid <b>%1</b>, built on <b>%2</b> at <b>%3</b> with <b>%4</b> compiler.").arg(BUILD_NUMBER).arg(__DATE__).arg(__TIME__).arg(COMPILER) + "<br>";
552    about += QString("%1: <b>%2</b><br>").arg(tr("Algorithm"), CTSPSolver::getVersionId());
553    about += "<br>";
554    about += tr("This program is free software: you can redistribute it and/or modify<br>\n"
555        "it under the terms of the GNU General Public License as published by<br>\n"
556        "the Free Software Foundation, either version 3 of the License, or<br>\n"
557        "(at your option) any later version.<br>\n"
558        "<br>\n"
559        "This program is distributed in the hope that it will be useful,<br>\n"
560        "but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\n"
561        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>\n"
562        "GNU General Public License for more details.<br>\n"
563        "<br>\n"
564        "You should have received a copy of the GNU General Public License<br>\n"
565        "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">www.gnu.org/licenses/</a>.");
[43c29c04ba]566
567QString credits;
[9eb63a1598]568    credits += tr("%1 was created using <b>Qt&nbsp;framework</b> licensed "
569        "under the terms of the GNU Lesser General Public License,<br>\n"
570        "see <a href=\"http://qt.nokia.com/\">qt.nokia.com</a><br>\n"
571        "<br>\n"
572        "Most icons used in %1 are part of <b>Oxygen&nbsp;Icons</b> project "
573        "licensed according to the GNU Lesser General Public License,<br>\n"
574        "see <a href=\"http://www.oxygen-icons.org/\">www.oxygen-icons.org</a><br>\n"
575        "<br>\n"
576        "Country flag icons used in %1 are part of the free "
577        "<b>Flag&nbsp;Icons</b> collection created by <b>IconDrawer</b>,<br>\n"
578        "see <a href=\"http://www.icondrawer.com/\">www.icondrawer.com</a><br>\n"
579        "<br>\n"
580        "%1 comes with the default \"embedded\" font <b>DejaVu&nbsp;LGC&nbsp;Sans&nbsp;"
581        "Mono</b> from the <b>DejaVu fonts</b> licensed under a Free license</a>,<br>\n"
582        "see <a href=\"http://dejavu-fonts.org/\">dejavu-fonts.org</a>")
583            .arg("TSPSG");
[43c29c04ba]584
585QFile f(":/files/COPYING");
[9eb63a1598]586    f.open(QIODevice::ReadOnly);
[43c29c04ba]587
[88a59e4d65]588QString translation = QCoreApplication::translate("--------", "AUTHORS %1", "Please, provide translator credits here. %1 will be replaced with VERSION");
[9eb63a1598]589    if ((translation != "AUTHORS %1") && (translation.contains("%1"))) {
[88a59e4d65]590QString about = QCoreApplication::translate("--------", "VERSION", "Please, provide your translation version here.");
[9eb63a1598]591        if (about != "VERSION")
592            translation = translation.arg(about);
593    }
[1babbd6ba3]594
595QDialog *dlg = new QDialog(this);
596QLabel *lblIcon = new QLabel(dlg),
[9eb63a1598]597    *lblTitle = new QLabel(dlg);
[1babbd6ba3]598#ifdef HANDHELD
[88a59e4d65]599QLabel *lblSubTitle = new QLabel(QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b>").arg(QDate::currentDate().toString("yyyy"), QCoreApplication::organizationDomain(), QCoreApplication::organizationName()), dlg);
[1babbd6ba3]600#endif // HANDHELD
[43c29c04ba]601QTabWidget *tabs = new QTabWidget(dlg);
[1babbd6ba3]602QTextBrowser *txtAbout = new QTextBrowser(dlg);
[43c29c04ba]603QTextBrowser *txtLicense = new QTextBrowser(dlg);
604QTextBrowser *txtCredits = new QTextBrowser(dlg);
[1babbd6ba3]605QVBoxLayout *vb = new QVBoxLayout();
606QHBoxLayout *hb1 = new QHBoxLayout(),
[9eb63a1598]607    *hb2 = new QHBoxLayout();
[1babbd6ba3]608QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dlg);
609
[9eb63a1598]610    lblTitle->setOpenExternalLinks(true);
611    lblTitle->setText(title);
612    lblTitle->setAlignment(Qt::AlignTop);
613    lblTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
[1babbd6ba3]614#ifndef HANDHELD
[9eb63a1598]615    lblTitle->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 4px; padding: 1px;}").arg(palette().alternateBase().color().name(), palette().shadow().color().name()));
[1babbd6ba3]616#endif // HANDHELD
617
[9eb63a1598]618    lblIcon->setPixmap(QPixmap(":/images/tspsg.png").scaledToHeight(lblTitle->sizeHint().height(), Qt::SmoothTransformation));
619    lblIcon->setAlignment(Qt::AlignVCenter);
[1babbd6ba3]620#ifndef HANDHELD
[9eb63a1598]621    lblIcon->setStyleSheet(QString("QLabel {background-color: white; border-color: %1; border-width: 1px; border-style: solid; border-radius: 4px; padding: 1px;}").arg(palette().windowText().color().name()));
[1babbd6ba3]622#endif // HANDHELD
623
[9eb63a1598]624    hb1->addWidget(lblIcon);
625    hb1->addWidget(lblTitle);
[1babbd6ba3]626
[9eb63a1598]627    txtAbout->setWordWrapMode(QTextOption::NoWrap);
628    txtAbout->setOpenExternalLinks(true);
629    txtAbout->setHtml(about);
630    txtAbout->moveCursor(QTextCursor::Start);
631    txtAbout->setFrameShape(QFrame::NoFrame);
[1babbd6ba3]632
[43c29c04ba]633//      txtCredits->setWordWrapMode(QTextOption::NoWrap);
[9eb63a1598]634    txtCredits->setOpenExternalLinks(true);
635    txtCredits->setHtml(credits);
636    txtCredits->moveCursor(QTextCursor::Start);
637    txtCredits->setFrameShape(QFrame::NoFrame);
[1babbd6ba3]638
[9eb63a1598]639    txtLicense->setWordWrapMode(QTextOption::NoWrap);
640    txtLicense->setOpenExternalLinks(true);
641    txtLicense->setText(f.readAll());
642    txtLicense->moveCursor(QTextCursor::Start);
643    txtLicense->setFrameShape(QFrame::NoFrame);
[1babbd6ba3]644
[9eb63a1598]645    bb->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor));
646    bb->button(QDialogButtonBox::Ok)->setIcon(GET_ICON("dialog-ok"));
[3cadf24d00]647
[9eb63a1598]648    hb2->addWidget(bb);
[1babbd6ba3]649
[97e90f9be6]650#ifdef Q_WS_WINCE_WM
[9eb63a1598]651    vb->setMargin(3);
[97e90f9be6]652#endif // Q_WS_WINCE_WM
[9eb63a1598]653    vb->addLayout(hb1);
[1babbd6ba3]654#ifdef HANDHELD
[9eb63a1598]655    vb->addWidget(lblSubTitle);
[1babbd6ba3]656#endif // HANDHELD
[43c29c04ba]657
[9eb63a1598]658    tabs->addTab(txtAbout, tr("About"));
659    tabs->addTab(txtLicense, tr("License"));
660    tabs->addTab(txtCredits, tr("Credits"));
661    if (translation != "AUTHORS %1") {
[43c29c04ba]662QTextBrowser *txtTranslation = new QTextBrowser(dlg);
663//              txtTranslation->setWordWrapMode(QTextOption::NoWrap);
[9eb63a1598]664        txtTranslation->setOpenExternalLinks(true);
665        txtTranslation->setText(translation);
666        txtTranslation->moveCursor(QTextCursor::Start);
667        txtTranslation->setFrameShape(QFrame::NoFrame);
[43c29c04ba]668
[9eb63a1598]669        tabs->addTab(txtTranslation, tr("Translation"));
670    }
[43c29c04ba]671#ifndef HANDHELD
[9eb63a1598]672    tabs->setStyleSheet(QString("QTabWidget::pane {background-color: %1; border-color: %3; border-width: 1px; border-style: solid; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; padding: 1px;} QTabBar::tab {background-color: %2; border-color: %3; border-width: 1px; border-style: solid; border-bottom: none; border-top-left-radius: 4px; border-top-right-radius: 4px; padding: 2px 6px;} QTabBar::tab:selected {background-color: %4;} QTabBar::tab:!selected {margin-top: 1px;}").arg(palette().base().color().name(), palette().button().color().name(), palette().shadow().color().name(), palette().light().color().name()));
[43c29c04ba]673#endif // HANDHELD
674
[9eb63a1598]675    vb->addWidget(tabs);
676    vb->addLayout(hb2);
[1babbd6ba3]677
[9eb63a1598]678    dlg->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
679    dlg->setWindowTitle(tr("About %1").arg(QCoreApplication::applicationName()));
680    dlg->setWindowIcon(GET_ICON("help-about"));
[d97db6d321]681
[9eb63a1598]682    dlg->setLayout(vb);
[1babbd6ba3]683
[9eb63a1598]684    connect(bb, SIGNAL(accepted()), dlg, SLOT(accept()));
[1babbd6ba3]685
[b8a2a118c4]686#ifndef HANDHELD
687    // Adding some eyecandy
[9eb63a1598]688    if (QtWin::isCompositionEnabled())  {
689        QtWin::enableBlurBehindWindow(dlg, true);
690    }
[b8a2a118c4]691#endif // HANDHELD
[1babbd6ba3]692
[5cbcd091ed]693#ifndef HANDHELD
[9eb63a1598]694    dlg->resize(450, 350);
[ccdffe3a5f]695#elif defined(Q_OS_BLACKBERRY)
696    dlg->setWindowState(Qt::WindowMaximized);
[5cbcd091ed]697#endif
[9eb63a1598]698    QApplication::restoreOverrideCursor();
[1babbd6ba3]699
[9eb63a1598]700    dlg->exec();
[1babbd6ba3]701
[9eb63a1598]702    delete dlg;
[1babbd6ba3]703}
704
705void MainWindow::buttonBackToTaskClicked()
706{
[9eb63a1598]707    tabWidget->setCurrentIndex(0);
[1babbd6ba3]708}
709
710void MainWindow::buttonRandomClicked()
711{
[9eb63a1598]712    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
713    tspmodel->randomize();
714    QApplication::restoreOverrideCursor();
[1babbd6ba3]715}
716
717void MainWindow::buttonSolveClicked()
718{
719TMatrix matrix;
720QList<double> row;
721int n = spinCities->value();
722bool ok;
[9eb63a1598]723    for (int r = 0; r < n; r++) {
724        row.clear();
725        for (int c = 0; c < n; c++) {
726            row.append(tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok));
727            if (!ok) {
728                QMessageBox::critical(this, tr("Data error"), tr("Error in cell [Row %1; Column %2]: Invalid data format.").arg(r + 1).arg(c + 1));
729                return;
730            }
731        }
732        matrix.append(row);
733    }
[1babbd6ba3]734
735QProgressDialog pd(this);
736QProgressBar *pb = new QProgressBar(&pd);
[9eb63a1598]737    pb->setAlignment(Qt::AlignCenter);
738    pb->setFormat(tr("%v of %1 parts found").arg(n));
739    pd.setBar(pb);
[43c29c04ba]740QPushButton *cancel = new QPushButton(&pd);
[9eb63a1598]741    cancel->setIcon(GET_ICON("dialog-cancel"));
[019894f5ef]742    cancel->setText(QCoreApplication::translate("QDialogButtonBox", "Cancel", "No need to translate this. The translation will be taken from Qt translation files."));
[9eb63a1598]743    pd.setCancelButton(cancel);
744    pd.setMaximum(n);
745    pd.setAutoReset(false);
746    pd.setLabelText(tr("Calculating optimal route..."));
747    pd.setWindowTitle(tr("Solution Progress"));
748    pd.setWindowModality(Qt::ApplicationModal);
749    pd.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
750    pd.show();
[1babbd6ba3]751
[97e90f9be6]752#ifdef Q_WS_WIN32
[43c29c04ba]753HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID*)&tl);
[9eb63a1598]754    if (SUCCEEDED(hr)) {
755        hr = tl->HrInit();
756        if (FAILED(hr)) {
757            tl->Release();
758            tl = NULL;
759        } else {
760            tl->SetProgressValue(winId(), 0, n * 2);
761        }
762    }
[43c29c04ba]763#endif
764
[1babbd6ba3]765CTSPSolver solver;
[9eb63a1598]766    solver.setCleanupOnCancel(false);
767    connect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
768    connect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
[97e90f9be6]769#ifdef Q_WS_WIN32
[9eb63a1598]770    if (tl != NULL)
771        connect(&solver, SIGNAL(routePartFound(int)), SLOT(solverRoutePartFound(int)));
[43c29c04ba]772#endif
[1babbd6ba3]773SStep *root = solver.solve(n, matrix);
[97e90f9be6]774#ifdef Q_WS_WIN32
[9eb63a1598]775    if (tl != NULL)
776        disconnect(&solver, SIGNAL(routePartFound(int)), this, SLOT(solverRoutePartFound(int)));
[43c29c04ba]777#endif
[9eb63a1598]778    disconnect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
779    disconnect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
780    if (!root) {
781        pd.reset();
782        if (!solver.wasCanceled()) {
[97e90f9be6]783#ifdef Q_WS_WIN32
[9eb63a1598]784            if (tl != NULL) {
785                tl->SetProgressState(winId(), TBPF_ERROR);
786            }
[43c29c04ba]787#endif
[9eb63a1598]788            QApplication::alert(this);
789            QMessageBox::warning(this, tr("Solution Result"), tr("Unable to find a solution.\nMaybe, this task has no solution."));
790        }
[d97db6d321]791        pd.setLabelText(tr("Memory cleanup..."));
[9eb63a1598]792        pd.setMaximum(0);
793        pd.setCancelButton(NULL);
794        pd.show();
[97e90f9be6]795#ifdef Q_WS_WIN32
[9eb63a1598]796        if (tl != NULL)
797            tl->SetProgressState(winId(), TBPF_INDETERMINATE);
[43c29c04ba]798#endif
[9eb63a1598]799        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
[43c29c04ba]800
[a713b103e8]801#ifndef QT_NO_CONCURRENT
[43c29c04ba]802QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
[9eb63a1598]803        while (!f.isFinished()) {
804            QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
805        }
[a713b103e8]806#else
[9eb63a1598]807        solver.cleanup(true);
[a713b103e8]808#endif
[9eb63a1598]809        pd.reset();
[97e90f9be6]810#ifdef Q_WS_WIN32
[9eb63a1598]811        if (tl != NULL) {
812            tl->SetProgressState(winId(), TBPF_NOPROGRESS);
813            tl->Release();
814            tl = NULL;
815        }
[43c29c04ba]816#endif
[9eb63a1598]817        return;
818    }
819    pb->setFormat(tr("Generating header"));
820    pd.setLabelText(tr("Generating solution output..."));
821    pd.setMaximum(solver.getTotalSteps() + 1);
822    pd.setValue(0);
[1babbd6ba3]823
[97e90f9be6]824#ifdef Q_WS_WIN32
[9eb63a1598]825    if (tl != NULL)
826        tl->SetProgressValue(winId(), spinCities->value(), spinCities->value() + solver.getTotalSteps() + 1);
[43c29c04ba]827#endif
828
[9eb63a1598]829    solutionText->clear();
830    solutionText->setDocumentTitle(tr("Solution of Variant #%1 Task").arg(spinVariant->value()));
[317ba0432e]831
[345e7b6132]832QPainter pic;
[8f2427aaf0]833bool dograph = settings->value("Output/GenerateGraph", DEF_GENERATE_GRAPH).toBool();
834    if (dograph) {
[9eb63a1598]835        pic.begin(&graph);
836        pic.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
[20e8115cee]837QFont font = qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE)));
[fddcfa4b55]838        font.setStyleHint(QFont::TypeWriter);
[8f2427aaf0]839        // Font size in pixels = graph node radius / 2.75.
840        // See MainWindow::drawNode() for graph node radius calcualtion description.
[fddcfa4b55]841#ifndef Q_WS_S60
[8f2427aaf0]842        font.setPixelSize(logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5 / 2.75);
[fddcfa4b55]843#else
844        // Also, see again MainWindow::drawNode() for why is additional 1.3 divider added in Symbian.
845        font.setPixelSize(logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5 / 2.75 / 1.3);
846#endif
[9eb63a1598]847        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
848            font.setWeight(QFont::DemiBold);
[8f2427aaf0]849            font.setPixelSize(font.pixelSize() * HQ_FACTOR);
[9eb63a1598]850        }
851        pic.setFont(font);
852        pic.setBrush(QBrush(QColor(Qt::white)));
853        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
[7aaa0b0ec7]854QPen pen = pic.pen();
[8f2427aaf0]855            pen.setWidth(HQ_FACTOR);
[9eb63a1598]856            pic.setPen(pen);
857        }
858        pic.setBackgroundMode(Qt::OpaqueMode);
[8f2427aaf0]859    } else {
860        graph = QPicture();
[9eb63a1598]861    }
[345e7b6132]862
[317ba0432e]863QTextDocument *doc = solutionText->document();
864QTextCursor cur(doc);
865
[9eb63a1598]866    cur.beginEditBlock();
867    cur.setBlockFormat(fmt_paragraph);
868    cur.insertText(tr("Variant #%1 Task").arg(spinVariant->value()), fmt_default);
869    cur.insertBlock(fmt_paragraph);
[a885c3d9d2]870    cur.insertText(tr("Task:"), fmt_default);
[9eb63a1598]871    outputMatrix(cur, matrix);
[8f2427aaf0]872    if (dograph) {
[3cadf24d00]873#ifdef _T_T_L_
[9eb63a1598]874        _b_ _i_ _z_ _a_ _r_ _r_ _e_
[3cadf24d00]875#endif
[9eb63a1598]876        drawNode(pic, 0);
877    }
878    cur.insertHtml("<hr>");
879    cur.insertBlock(fmt_paragraph);
[345e7b6132]880int imgpos = cur.position();
[9eb63a1598]881    cur.insertText(tr("Variant #%1 Solution").arg(spinVariant->value()), fmt_default);
882    cur.endEditBlock();
[317ba0432e]883
[1babbd6ba3]884SStep *step = root;
[9cda6e0f5d]885int c = n = 1;
[9eb63a1598]886    pb->setFormat(tr("Generating step %v"));
887    while ((step->next != SStep::NoNextStep) && (c < spinCities->value())) {
888        if (pd.wasCanceled()) {
[d97db6d321]889            pd.setLabelText(tr("Memory cleanup..."));
[9eb63a1598]890            pd.setMaximum(0);
891            pd.setCancelButton(NULL);
892            pd.show();
893            QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
[97e90f9be6]894#ifdef Q_WS_WIN32
[9eb63a1598]895            if (tl != NULL)
896                tl->SetProgressState(winId(), TBPF_INDETERMINATE);
[43c29c04ba]897#endif
[a713b103e8]898#ifndef QT_NO_CONCURRENT
[43c29c04ba]899QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
[9eb63a1598]900            while (!f.isFinished()) {
901                QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
902            }
[a713b103e8]903#else
[9eb63a1598]904            solver.cleanup(true);
[a713b103e8]905#endif
[9eb63a1598]906            solutionText->clear();
907            toggleSolutionActions(false);
[97e90f9be6]908#ifdef Q_WS_WIN32
[9eb63a1598]909            if (tl != NULL) {
910                tl->SetProgressState(winId(), TBPF_NOPROGRESS);
911                tl->Release();
912                tl = NULL;
913            }
[43c29c04ba]914#endif
[9eb63a1598]915            return;
916        }
917        pd.setValue(n);
[97e90f9be6]918#ifdef Q_WS_WIN32
[9eb63a1598]919        if (tl != NULL)
920            tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1);
[43c29c04ba]921#endif
[1babbd6ba3]922
[9eb63a1598]923        cur.beginEditBlock();
924        cur.insertBlock(fmt_paragraph);
[a885c3d9d2]925        cur.insertText(tr("Step #%1").arg(n), fmt_default);
[9eb63a1598]926        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())))) {
927            outputMatrix(cur, *step);
928        }
[8f2427aaf0]929        if (step->alts.empty())
930            cur.insertBlock(fmt_lastparagraph);
931        else
932            cur.insertBlock(fmt_paragraph);
[9eb63a1598]933        cur.insertText(tr("Selected route %1 %2 part.").arg((step->next == SStep::RightBranch) ? tr("with") : tr("without")).arg(tr("(%1;%2)").arg(step->candidate.nRow + 1).arg(step->candidate.nCol + 1)), fmt_default);
934        if (!step->alts.empty()) {
935            SStep::SCandidate cand;
936            QString alts;
937            foreach(cand, step->alts) {
938                if (!alts.isEmpty())
939                    alts += ", ";
940                alts += tr("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1);
941            }
[8f2427aaf0]942            cur.insertBlock(fmt_lastparagraph);
[9eb63a1598]943            cur.insertText(tr("%n alternate candidate(s) for branching: %1.", "", step->alts.count()).arg(alts), fmt_altlist);
944        }
945        cur.endEditBlock();
946
[8f2427aaf0]947        if (dograph) {
[9eb63a1598]948            if (step->prNode != NULL)
949                drawNode(pic, n, false, step->prNode);
950            if (step->plNode != NULL)
951                drawNode(pic, n, true, step->plNode);
952        }
953        n++;
954
955        if (step->next == SStep::RightBranch) {
956            c++;
957            step = step->prNode;
958        } else if (step->next == SStep::LeftBranch) {
959            step = step->plNode;
960        } else
961            break;
962    }
963    pb->setFormat(tr("Generating footer"));
964    pd.setValue(n);
[97e90f9be6]965#ifdef Q_WS_WIN32
[9eb63a1598]966    if (tl != NULL)
967        tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1);
[43c29c04ba]968#endif
[1babbd6ba3]969
[9eb63a1598]970    cur.beginEditBlock();
971    cur.insertBlock(fmt_paragraph);
972    if (solver.isOptimal())
[8f2427aaf0]973        cur.insertText(tr("Optimal path:"), fmt_default);
[9eb63a1598]974    else
[8f2427aaf0]975        cur.insertText(tr("Resulting path:"), fmt_default);
[9eb63a1598]976
977    cur.insertBlock(fmt_paragraph);
978    cur.insertText("  " + solver.getSortedPath(tr("City %1")));
979
[8f2427aaf0]980    if (solver.isOptimal())
981        cur.insertBlock(fmt_paragraph);
982    else
983        cur.insertBlock(fmt_lastparagraph);
[9eb63a1598]984    if (isInteger(step->price))
985        cur.insertHtml("<p>" + tr("The price is <b>%n</b> unit(s).", "", qRound(step->price)) + "</p>");
986    else
987        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>");
988    if (!solver.isOptimal()) {
989        cur.insertBlock(fmt_paragraph);
990        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>");
991    }
992    cur.endEditBlock();
993
[8f2427aaf0]994    if (dograph) {
[9eb63a1598]995        pic.end();
[345e7b6132]996
[131c5fc3ba]997QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_RGB32);
[9eb63a1598]998        i.fill(0xFFFFFF);
999        pic.begin(&i);
1000        pic.drawPicture(1, 1, graph);
1001        pic.end();
1002        doc->addResource(QTextDocument::ImageResource, QUrl("tspsg://graph.pic"), i);
[345e7b6132]1003
1004QTextImageFormat img;
[9eb63a1598]1005        img.setName("tspsg://graph.pic");
1006        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
[8f2427aaf0]1007            img.setWidth(i.width() / HQ_FACTOR);
1008            img.setHeight(i.height() / HQ_FACTOR);
[9eb63a1598]1009        } else {
1010            img.setWidth(i.width());
1011            img.setHeight(i.height());
1012        }
1013
1014        cur.setPosition(imgpos);
1015        cur.insertImage(img, QTextFrameFormat::FloatRight);
1016    }
1017
1018    if (settings->value("Output/ScrollToEnd", DEF_SCROLL_TO_END).toBool()) {
1019        // Scrolling to the end of the text.
1020        solutionText->moveCursor(QTextCursor::End);
1021    } else
1022        solutionText->moveCursor(QTextCursor::Start);
1023
[d97db6d321]1024    pd.setLabelText(tr("Memory cleanup..."));
[9eb63a1598]1025    pd.setMaximum(0);
1026    pd.setCancelButton(NULL);
1027    QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
[97e90f9be6]1028#ifdef Q_WS_WIN32
[9eb63a1598]1029    if (tl != NULL)
1030        tl->SetProgressState(winId(), TBPF_INDETERMINATE);
[43c29c04ba]1031#endif
[a713b103e8]1032#ifndef QT_NO_CONCURRENT
[43c29c04ba]1033QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
[9eb63a1598]1034    while (!f.isFinished()) {
1035        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1036    }
[a713b103e8]1037#else
[9eb63a1598]1038    solver.cleanup(true);
[a713b103e8]1039#endif
[9eb63a1598]1040    toggleSolutionActions();
1041    tabWidget->setCurrentIndex(1);
[97e90f9be6]1042#ifdef Q_WS_WIN32
[9eb63a1598]1043    if (tl != NULL) {
1044        tl->SetProgressState(winId(), TBPF_NOPROGRESS);
1045        tl->Release();
1046        tl = NULL;
1047    }
[43c29c04ba]1048#endif
1049
[9eb63a1598]1050    pd.reset();
1051    QApplication::alert(this, 3000);
[1babbd6ba3]1052}
1053
1054void MainWindow::dataChanged()
1055{
[9eb63a1598]1056    setWindowModified(true);
[1babbd6ba3]1057}
1058
1059void MainWindow::dataChanged(const QModelIndex &tl, const QModelIndex &br)
1060{
[9eb63a1598]1061    setWindowModified(true);
1062    if (settings->value("Autosize", DEF_AUTOSIZE).toBool()) {
1063        for (int k = tl.row(); k <= br.row(); k++)
1064            taskView->resizeRowToContents(k);
1065        for (int k = tl.column(); k <= br.column(); k++)
1066            taskView->resizeColumnToContents(k);
1067    }
[1babbd6ba3]1068}
1069
[97e90f9be6]1070#ifdef Q_WS_WINCE_WM
[1babbd6ba3]1071void MainWindow::changeEvent(QEvent *ev)
1072{
[9eb63a1598]1073    if ((ev->type() == QEvent::ActivationChange) && isActiveWindow())
1074        desktopResized(0);
[1babbd6ba3]1075
[9eb63a1598]1076    QWidget::changeEvent(ev);
[1babbd6ba3]1077}
1078
1079void MainWindow::desktopResized(int screen)
1080{
[9eb63a1598]1081    if ((screen != 0) || !isActiveWindow())
1082        return;
[1babbd6ba3]1083
1084QRect availableGeometry = QApplication::desktop()->availableGeometry(0);
[9eb63a1598]1085    if (currentGeometry != availableGeometry) {
1086        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1087        /*!
1088         * \hack HACK: This hack checks whether \link QDesktopWidget::availableGeometry() availableGeometry()\endlink's \c top + \c hegiht = \link QDesktopWidget::screenGeometry() screenGeometry()\endlink's \c height.
1089         *  If \c true, the window gets maximized. If we used \c setGeometry() in this case, the bottom of the
1090         *  window would end up being behind the soft buttons. Is this a bug in Qt or Windows Mobile?
1091         */
1092        if ((availableGeometry.top() + availableGeometry.height()) == QApplication::desktop()->screenGeometry().height()) {
1093            setWindowState(windowState() | Qt::WindowMaximized);
1094        } else {
1095            if (windowState() & Qt::WindowMaximized)
1096                setWindowState(windowState() ^ Qt::WindowMaximized);
1097            setGeometry(availableGeometry);
1098        }
1099        currentGeometry = availableGeometry;
1100        QApplication::restoreOverrideCursor();
1101    }
[1babbd6ba3]1102}
[97e90f9be6]1103#endif // Q_WS_WINCE_WM
[1babbd6ba3]1104
1105void MainWindow::numCitiesChanged(int nCities)
1106{
[9eb63a1598]1107    blockSignals(true);
1108    spinCities->setValue(nCities);
1109    blockSignals(false);
[1babbd6ba3]1110}
1111
1112#ifndef QT_NO_PRINTER
1113void MainWindow::printPreview(QPrinter *printer)
1114{
[9eb63a1598]1115    solutionText->print(printer);
[1babbd6ba3]1116}
1117#endif // QT_NO_PRINTER
1118
[97e90f9be6]1119#ifdef Q_WS_WIN32
[43c29c04ba]1120void MainWindow::solverRoutePartFound(int n)
1121{
[9eb63a1598]1122    tl->SetProgressValue(winId(), n, spinCities->value() * 2);
[43c29c04ba]1123}
[97e90f9be6]1124#endif // Q_WS_WIN32
[43c29c04ba]1125
[1babbd6ba3]1126void MainWindow::spinCitiesValueChanged(int n)
1127{
[9eb63a1598]1128    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[1babbd6ba3]1129int count = tspmodel->numCities();
[9eb63a1598]1130    tspmodel->setNumCities(n);
1131    if ((n > count) && settings->value("Autosize", DEF_AUTOSIZE).toBool())
1132        for (int k = count; k < n; k++) {
1133            taskView->resizeColumnToContents(k);
1134            taskView->resizeRowToContents(k);
1135        }
1136    QApplication::restoreOverrideCursor();
[1babbd6ba3]1137}
1138
[f5c945d7ac]1139void MainWindow::check4Updates(bool silent)
1140{
[97e90f9be6]1141#ifdef Q_WS_WIN32
[9eb63a1598]1142    if (silent)
1143        QProcess::startDetached("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\" -silentcheck");
1144    else {
1145        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1146        QProcess::execute("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\"");
1147        QApplication::restoreOverrideCursor();
1148    }
[0007f69c46]1149#else
[9eb63a1598]1150    Q_UNUSED(silent)
[f5c945d7ac]1151#endif
[9eb63a1598]1152    settings->setValue("Check4Updates/LastAttempt", QDate::currentDate().toString(Qt::ISODate));
[f5c945d7ac]1153}
1154
[1babbd6ba3]1155void MainWindow::closeEvent(QCloseEvent *ev)
1156{
[9eb63a1598]1157    if (!maybeSave()) {
1158        ev->ignore();
1159        return;
1160    }
1161    if (!settings->value("SettingsReset", false).toBool()) {
1162        settings->setValue("NumCities", spinCities->value());
1163
1164        // Saving Main Window state
[7bb19df196]1165#ifndef HANDHELD
[9eb63a1598]1166        if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
1167            settings->beginGroup("MainWindow");
1168            settings->setValue("Geometry", saveGeometry());
1169            settings->setValue("State", saveState());
1170            settings->setValue("Toolbars", toolBarManager->saveState());
1171            settings->endGroup();
1172        }
[a713b103e8]1173#else
[9eb63a1598]1174        settings->setValue("MainWindow/ToolbarVisible", toolBarMain->isVisible());
[7bb19df196]1175#endif // HANDHELD
[9eb63a1598]1176    } else {
1177        settings->remove("SettingsReset");
1178    }
[1babbd6ba3]1179
[9eb63a1598]1180    QMainWindow::closeEvent(ev);
[1babbd6ba3]1181}
1182
[b574c383b7]1183void MainWindow::dragEnterEvent(QDragEnterEvent *ev)
1184{
[9eb63a1598]1185    if (ev->mimeData()->hasUrls() && (ev->mimeData()->urls().count() == 1)) {
[b574c383b7]1186QFileInfo fi(ev->mimeData()->urls().first().toLocalFile());
[9eb63a1598]1187        if ((fi.suffix() == "tspt") || (fi.suffix() == "zkt"))
1188            ev->acceptProposedAction();
1189    }
[b574c383b7]1190}
1191
[345e7b6132]1192void MainWindow::drawNode(QPainter &pic, int nstep, bool left, SStep *step)
1193{
[8f2427aaf0]1194qreal r; // Radius of graph node
1195    // We calculate r from the full graph width in centimeters:
1196    //   r = width in pixels / 4.5.
1197    //   width in pixels = DPI * width in inches.
1198    //   width in inches = width in cm / cm in inch.
1199    r = logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5;
[9eb63a1598]1200    if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool())
[8f2427aaf0]1201        r *= HQ_FACTOR;
[23ad8db4a5]1202#ifdef Q_WS_S60
[144fbe6b96]1203    /*! \hack HACK: Solution graph on Symbian is visually larger than on
[23ad8db4a5]1204     *   Windows Mobile. This coefficient makes it about the same size.
1205     */
1206    r /= 1.3;
1207#endif
1208
[345e7b6132]1209qreal x, y;
[9eb63a1598]1210    if (step != NULL)
1211        x = left ? r : r * 3.5;
1212    else
1213        x = r * 2.25;
1214    y = r * (3 * nstep + 1);
[345e7b6132]1215
[3cadf24d00]1216#ifdef _T_T_L_
[9eb63a1598]1217    if (nstep == -481124) {
1218        _t_t_l_(pic, r, x);
1219        return;
1220    }
[3cadf24d00]1221#endif
1222
[9eb63a1598]1223    pic.drawEllipse(QPointF(x, y), r, r);
[345e7b6132]1224
[9eb63a1598]1225    if (step != NULL) {
[345e7b6132]1226QFont font;
[9eb63a1598]1227        if (left) {
1228            font = pic.font();
1229            font.setStrikeOut(true);
1230            pic.setFont(font);
1231        }
1232        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");
1233        if (left) {
1234            font.setStrikeOut(false);
1235            pic.setFont(font);
1236        }
1237        if (step->price != INFINITY) {
[5cbcd091ed]1238            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()));
[9eb63a1598]1239        } else {
1240            pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, "\n"INFSTR);
1241        }
1242    } else {
1243        pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, tr("Root"));
1244    }
1245
1246    if (nstep == 1) {
1247        pic.drawLine(QPointF(x, y - r), QPointF(r * 2.25, y - 2 * r));
1248    } else if (nstep > 1) {
1249        pic.drawLine(QPointF(x, y - r), QPointF((step->pNode->pNode->next == SStep::RightBranch) ? r * 3.5 : r, y - 2 * r));
1250    }
[345e7b6132]1251
1252}
1253
[b574c383b7]1254void MainWindow::dropEvent(QDropEvent *ev)
1255{
[9eb63a1598]1256    if (maybeSave() && tspmodel->loadTask(ev->mimeData()->urls().first().toLocalFile())) {
1257        setFileName(ev->mimeData()->urls().first().toLocalFile());
1258        tabWidget->setCurrentIndex(0);
1259        setWindowModified(false);
1260        solutionText->clear();
1261        toggleSolutionActions(false);
1262
1263        ev->setDropAction(Qt::CopyAction);
1264        ev->accept();
1265    }
[b574c383b7]1266}
1267
[1babbd6ba3]1268void MainWindow::initDocStyleSheet()
1269{
[9eb63a1598]1270    solutionText->document()->setDefaultFont(qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE, DEF_FONT_SIZE))));
[317ba0432e]1271
[a885c3d9d2]1272    fmt_paragraph.setTopMargin(5);
[9eb63a1598]1273    fmt_paragraph.setRightMargin(10);
1274    fmt_paragraph.setBottomMargin(0);
1275    fmt_paragraph.setLeftMargin(10);
[8f2427aaf0]1276
1277    fmt_lastparagraph.setTopMargin(5);
1278    fmt_lastparagraph.setRightMargin(10);
1279    fmt_lastparagraph.setBottomMargin(15);
1280    fmt_lastparagraph.setLeftMargin(10);
[317ba0432e]1281
[9eb63a1598]1282    fmt_table.setTopMargin(5);
1283    fmt_table.setRightMargin(10);
[a885c3d9d2]1284    fmt_table.setBottomMargin(0);
[9eb63a1598]1285    fmt_table.setLeftMargin(10);
1286    fmt_table.setBorder(0);
1287    fmt_table.setBorderStyle(QTextFrameFormat::BorderStyle_None);
1288    fmt_table.setCellSpacing(5);
[317ba0432e]1289
[9eb63a1598]1290    fmt_cell.setAlignment(Qt::AlignHCenter);
[317ba0432e]1291
[9eb63a1598]1292    settings->beginGroup("Output/Colors");
[8b0661d1ee]1293
[a713b103e8]1294QColor color = qvariant_cast<QColor>(settings->value("Text", DEF_TEXT_COLOR));
[1babbd6ba3]1295QColor hilight;
[9eb63a1598]1296    if (color.value() < 192)
1297        hilight.setHsv(color.hue(), color.saturation(), 127 + qRound(color.value() / 2));
1298    else
1299        hilight.setHsv(color.hue(), color.saturation(), color.value() / 2);
[317ba0432e]1300
[9eb63a1598]1301    solutionText->document()->setDefaultStyleSheet(QString("* {color: %1;}").arg(color.name()));
1302    fmt_default.setForeground(QBrush(color));
[317ba0432e]1303
[9eb63a1598]1304    fmt_selected.setForeground(QBrush(qvariant_cast<QColor>(settings->value("Selected", DEF_SELECTED_COLOR))));
1305    fmt_selected.setFontWeight(QFont::Bold);
[317ba0432e]1306
[9eb63a1598]1307    fmt_alternate.setForeground(QBrush(qvariant_cast<QColor>(settings->value("Alternate", DEF_ALTERNATE_COLOR))));
1308    fmt_alternate.setFontWeight(QFont::Bold);
1309    fmt_altlist.setForeground(QBrush(hilight));
[317ba0432e]1310
[9eb63a1598]1311    settings->endGroup();
[8b0661d1ee]1312
[9eb63a1598]1313    solutionText->setTextColor(color);
[1babbd6ba3]1314}
1315
1316void MainWindow::loadLangList()
1317{
[3cadf24d00]1318QMap<QString, QStringList> langlist;
1319QFileInfoList langs;
1320QFileInfo lang;
1321QStringList language, dirs;
1322QTranslator t;
1323QDir dir;
[9eb63a1598]1324    dir.setFilter(QDir::Files);
1325    dir.setNameFilters(QStringList("tspsg_*.qm"));
1326    dir.setSorting(QDir::NoSort);
1327
1328    dirs << PATH_L10N << ":/l10n";
1329    foreach (QString dirname, dirs) {
1330        dir.setPath(dirname);
1331        if (dir.exists()) {
1332            langs = dir.entryInfoList();
1333            for (int k = 0; k < langs.size(); k++) {
1334                lang = langs.at(k);
1335                if (lang.completeBaseName().compare("tspsg_en", Qt::CaseInsensitive) && !langlist.contains(lang.completeBaseName().mid(6)) && t.load(lang.completeBaseName(), dirname)) {
1336
1337                    language.clear();
1338                    language.append(lang.completeBaseName().mid(6));
1339                    language.append(t.translate("--------", "COUNTRY", "Please, provide an ISO 3166-1 alpha-2 country code for this translation language here (eg., UA).").toLower());
1340                    language.append(t.translate("--------", "LANGNAME", "Please, provide a native name of your translation language here."));
1341                    language.append(t.translate("MainWindow", "Set application language to %1", "").arg(language.at(2)));
1342
1343                    langlist.insert(language.at(0), language);
1344                }
1345            }
1346        }
1347    }
[3cadf24d00]1348
1349QAction *a;
[9eb63a1598]1350    foreach (language, langlist) {
1351        a = menuSettingsLanguage->addAction(language.at(2));
[9adbc413c7]1352#ifndef QT_NO_STATUSTIP
[9eb63a1598]1353        a->setStatusTip(language.at(3));
[9adbc413c7]1354#endif
[2a436ea693]1355#if QT_VERSION >= 0x040600
[9eb63a1598]1356        a->setIcon(QIcon::fromTheme(QString("flag-%1").arg(language.at(1)), QIcon(QString(":/images/icons/l10n/flag-%1.png").arg(language.at(1)))));
[2a436ea693]1357#else
[9eb63a1598]1358        a->setIcon(QIcon(QString(":/images/icons/l10n/flag-%1.png").arg(language.at(1))));
[2a436ea693]1359#endif
[9eb63a1598]1360        a->setData(language.at(0));
1361        a->setCheckable(true);
1362        a->setActionGroup(groupSettingsLanguageList);
1363        if (settings->value("Language", QLocale::system().name()).toString().startsWith(language.at(0)))
1364            a->setChecked(true);
1365    }
[1babbd6ba3]1366}
1367
1368bool MainWindow::loadLanguage(const QString &lang)
1369{
1370// i18n
1371bool ad = false;
1372QString lng = lang;
[9eb63a1598]1373    if (lng.isEmpty()) {
1374        ad = settings->value("Language").toString().isEmpty();
1375        lng = settings->value("Language", QLocale::system().name()).toString();
1376    }
[1babbd6ba3]1377static QTranslator *qtTranslator; // Qt library translator
[9eb63a1598]1378    if (qtTranslator) {
1379        qApp->removeTranslator(qtTranslator);
1380        delete qtTranslator;
1381        qtTranslator = NULL;
1382    }
[1babbd6ba3]1383static QTranslator *translator; // Application translator
[9eb63a1598]1384    if (translator) {
1385        qApp->removeTranslator(translator);
1386        delete translator;
1387        translator = NULL;
1388    }
1389
1390    if (lng == "en")
1391        return true;
1392
1393    // Trying to load system Qt library translation...
1394    qtTranslator = new QTranslator(this);
1395    if (qtTranslator->load("qt_" + lng, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
1396        qApp->installTranslator(qtTranslator);
1397    else {
1398        // No luck. Let's try to load a bundled one.
1399        if (qtTranslator->load("qt_" + lng, PATH_L10N)) {
1400            // We have a translation in the localization direcotry.
1401            qApp->installTranslator(qtTranslator);
1402        } else if (qtTranslator->load("qt_" + lng, ":/l10n")) {
1403            // We have a translation "built-in" into application resources.
1404            qApp->installTranslator(qtTranslator);
1405        } else {
1406            // Qt library translation unavailable for this language.
1407            delete qtTranslator;
1408            qtTranslator = NULL;
1409        }
1410    }
1411
1412    // Now let's load application translation.
1413    translator = new QTranslator(this);
1414    if (translator->load("tspsg_" + lng, PATH_L10N)) {
1415        // We have a translation in the localization directory.
1416        qApp->installTranslator(translator);
1417    } else if (translator->load("tspsg_" + lng, ":/l10n")) {
1418        // We have a translation "built-in" into application resources.
1419        qApp->installTranslator(translator);
1420    } else {
1421        delete translator;
1422        translator = NULL;
1423        if (!ad) {
1424            settings->remove("Language");
1425            QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
1426            QMessageBox::warning(isVisible() ? this : NULL, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection."));
1427            QApplication::restoreOverrideCursor();
1428        }
1429        return false;
1430    }
1431    return true;
[1babbd6ba3]1432}
1433
[e3533af1cf]1434void MainWindow::loadStyleList()
1435{
[9eb63a1598]1436    menuSettingsStyle->clear();
[e3533af1cf]1437QStringList styles = QStyleFactory::keys();
[9eb63a1598]1438    menuSettingsStyle->insertAction(NULL, actionSettingsStyleSystem);
1439    actionSettingsStyleSystem->setChecked(!settings->contains("Style"));
1440    menuSettingsStyle->addSeparator();
[e3533af1cf]1441QAction *a;
[9eb63a1598]1442    foreach (QString style, styles) {
1443        a = menuSettingsStyle->addAction(style);
1444        a->setData(false);
[9adbc413c7]1445#ifndef QT_NO_STATUSTIP
[9eb63a1598]1446        a->setStatusTip(tr("Set application style to %1").arg(style));
[9adbc413c7]1447#endif
[9eb63a1598]1448        a->setCheckable(true);
1449        a->setActionGroup(groupSettingsStyleList);
1450        if ((style == settings->value("Stlye").toString())
[97e90f9be6]1451#ifndef Q_WS_MAEMO_5
[9eb63a1598]1452            || QString(QApplication::style()->metaObject()->className()).contains(QRegExp(QString("^Q?%1(Style)?$").arg(QRegExp::escape(style)), Qt::CaseInsensitive))
[97e90f9be6]1453#endif
[9eb63a1598]1454        ) {
1455            a->setChecked(true);
1456        }
1457    }
[e3533af1cf]1458}
1459
[7bb19df196]1460void MainWindow::loadToolbarList()
1461{
[9eb63a1598]1462    menuSettingsToolbars->clear();
[7bb19df196]1463#ifndef HANDHELD
[9eb63a1598]1464    menuSettingsToolbars->insertAction(NULL, actionSettingsToolbarsConfigure);
1465    menuSettingsToolbars->addSeparator();
[7bb19df196]1466QList<QToolBar *> list = toolBarManager->toolBars();
[9eb63a1598]1467    foreach (QToolBar *t, list) {
1468        menuSettingsToolbars->insertAction(NULL, t->toggleViewAction());
1469    }
[7bb19df196]1470#else // HANDHELD
[9eb63a1598]1471    menuSettingsToolbars->insertAction(NULL, toolBarMain->toggleViewAction());
[7bb19df196]1472#endif // HANDHELD
1473}
1474
[1babbd6ba3]1475bool MainWindow::maybeSave()
1476{
[9eb63a1598]1477    if (!isWindowModified())
1478        return true;
[fddcfa4b55]1479#ifdef Q_WS_S60
1480    int res = QSMessageBox(this).exec();
1481#else
1482    int res = QMessageBox::warning(this, tr("Unsaved Changes"), tr("Would you like to save changes in the current task?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1483#endif
[9eb63a1598]1484    if (res == QMessageBox::Save)
1485        return actionFileSaveTriggered();
1486    else if (res == QMessageBox::Cancel)
1487        return false;
1488    else
1489        return true;
[1babbd6ba3]1490}
1491
[317ba0432e]1492void MainWindow::outputMatrix(QTextCursor &cur, const TMatrix &matrix)
[1babbd6ba3]1493{
1494int n = spinCities->value();
[317ba0432e]1495QTextTable *table = cur.insertTable(n, n, fmt_table);
1496
[9eb63a1598]1497    for (int r = 0; r < n; r++) {
1498        for (int c = 0; c < n; c++) {
1499            cur = table->cellAt(r, c).firstCursorPosition();
1500            cur.setBlockFormat(fmt_cell);
1501            cur.setBlockCharFormat(fmt_default);
1502            if (matrix.at(r).at(c) == INFINITY)
1503                cur.insertText(INFSTR);
1504            else
1505                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()));
1506        }
1507        QCoreApplication::processEvents();
1508    }
1509    cur.movePosition(QTextCursor::End);
[1babbd6ba3]1510}
1511
[317ba0432e]1512void MainWindow::outputMatrix(QTextCursor &cur, const SStep &step)
[1babbd6ba3]1513{
1514int n = spinCities->value();
[317ba0432e]1515QTextTable *table = cur.insertTable(n, n, fmt_table);
1516
[9eb63a1598]1517    for (int r = 0; r < n; r++) {
1518        for (int c = 0; c < n; c++) {
1519            cur = table->cellAt(r, c).firstCursorPosition();
1520            cur.setBlockFormat(fmt_cell);
1521            if (step.matrix.at(r).at(c) == INFINITY)
1522                cur.insertText(INFSTR, fmt_default);
1523            else if ((r == step.candidate.nRow) && (c == step.candidate.nCol))
1524                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);
1525            else {
[9cda6e0f5d]1526SStep::SCandidate cand;
[9eb63a1598]1527                cand.nRow = r;
1528                cand.nCol = c;
1529                if (step.alts.contains(cand))
1530                    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);
1531                else
1532                    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);
1533            }
1534        }
1535        QCoreApplication::processEvents();
1536    }
1537
1538    cur.movePosition(QTextCursor::End);
[1babbd6ba3]1539}
1540
1541void MainWindow::retranslateUi(bool all)
1542{
[9eb63a1598]1543    if (all)
1544        Ui_MainWindow::retranslateUi(this);
[1babbd6ba3]1545
[aa64ad4082]1546#ifdef Q_OS_BLACKBERRY
1547    menuSettings->removeAction(menuSettingsStyle->menuAction());
1548#else
[9eb63a1598]1549    loadStyleList();
[aa64ad4082]1550#endif
[9eb63a1598]1551    loadToolbarList();
[e3533af1cf]1552
[ccdffe3a5f]1553#ifndef QT_NO_PRINTDIALOG
[9eb63a1598]1554    actionFilePrintPreview->setText(tr("P&rint Preview..."));
[1babbd6ba3]1555#ifndef QT_NO_TOOLTIP
[9eb63a1598]1556    actionFilePrintPreview->setToolTip(tr("Preview solution results"));
[1babbd6ba3]1557#endif // QT_NO_TOOLTIP
1558#ifndef QT_NO_STATUSTIP
[9eb63a1598]1559    actionFilePrintPreview->setStatusTip(tr("Preview current solution results before printing"));
[20e8115cee]1560#endif // QT_NO_STATUSTIP
1561
1562    actionFilePageSetup->setText(tr("Pa&ge Setup..."));
1563#ifndef QT_NO_TOOLTIP
1564    actionFilePageSetup->setToolTip(tr("Setup print options"));
1565#endif // QT_NO_TOOLTIP
1566#ifndef QT_NO_STATUSTIP
1567    actionFilePageSetup->setStatusTip(tr("Setup page-related options for printing"));
[88a59e4d65]1568#endif // QT_NO_STATUSTIP
[1babbd6ba3]1569
[9eb63a1598]1570    actionFilePrint->setText(tr("&Print..."));
[1babbd6ba3]1571#ifndef QT_NO_TOOLTIP
[9eb63a1598]1572    actionFilePrint->setToolTip(tr("Print solution"));
[1babbd6ba3]1573#endif // QT_NO_TOOLTIP
1574#ifndef QT_NO_STATUSTIP
[9eb63a1598]1575    actionFilePrint->setStatusTip(tr("Print current solution results"));
[1babbd6ba3]1576#endif // QT_NO_STATUSTIP
[ccdffe3a5f]1577#ifndef QT_NO_SHORTCUT
[9eb63a1598]1578    actionFilePrint->setShortcut(tr("Ctrl+P"));
[ccdffe3a5f]1579#endif // QT_NO_SHORTCUT
1580#endif // QT_NO_PRINTDIALOG
[8b0661d1ee]1581
[20e8115cee]1582#ifndef QT_NO_STATUSTIP
1583    actionFileExit->setStatusTip(tr("Exit %1").arg(QCoreApplication::applicationName()));
1584#endif // QT_NO_STATUSTIP
1585
[8b0661d1ee]1586#ifndef HANDHELD
[9eb63a1598]1587    actionSettingsToolbarsConfigure->setText(tr("Configure..."));
[8b0661d1ee]1588#ifndef QT_NO_STATUSTIP
[9eb63a1598]1589    actionSettingsToolbarsConfigure->setStatusTip(tr("Customize toolbars"));
[8b0661d1ee]1590#endif // QT_NO_STATUSTIP
1591#endif // HANDHELD
1592
[88a59e4d65]1593#ifndef QT_NO_STATUSTIP
[9eb63a1598]1594    actionHelpReportBug->setStatusTip(tr("Report about a bug in %1").arg(QCoreApplication::applicationName()));
[88a59e4d65]1595#endif // QT_NO_STATUSTIP
[9eb63a1598]1596    if (actionHelpCheck4Updates != NULL) {
1597        actionHelpCheck4Updates->setText(tr("Check for &Updates..."));
[1babbd6ba3]1598#ifndef QT_NO_STATUSTIP
[9eb63a1598]1599        actionHelpCheck4Updates->setStatusTip(tr("Check for %1 updates").arg(QCoreApplication::applicationName()));
[1babbd6ba3]1600#endif // QT_NO_STATUSTIP
[9eb63a1598]1601    }
[88a59e4d65]1602#ifndef QT_NO_STATUSTIP
[9eb63a1598]1603    actionHelpAbout->setStatusTip(tr("About %1").arg(QCoreApplication::applicationName()));
[88a59e4d65]1604#endif // QT_NO_STATUSTIP
[23ad8db4a5]1605
1606#ifdef Q_WS_S60
1607    actionRightSoftKey->setText(tr("E&xit"));
1608#endif
[1babbd6ba3]1609}
1610
1611bool MainWindow::saveTask() {
1612QStringList filters(tr("%1 Task File").arg("TSPSG") + " (*.tspt)");
[9eb63a1598]1613    filters.append(tr("All Files") + " (*)");
[1babbd6ba3]1614QString file;
[9eb63a1598]1615    if ((fileName == tr("Untitled") + ".tspt") && settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) {
1616        file = settings->value(OS"/LastUsed/TaskSavePath").toString();
1617        if (!file.isEmpty())
1618            file.append("/");
1619        file.append(fileName);
1620    } else if (fileName.endsWith(".tspt", Qt::CaseInsensitive))
1621        file = fileName;
1622    else
1623        file = QFileInfo(fileName).path() + "/" + QFileInfo(fileName).completeBaseName() + ".tspt";
[1babbd6ba3]1624
1625QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
[9eb63a1598]1626    file = QFileDialog::getSaveFileName(this, tr("Task Save"), file, filters.join(";;"), NULL, opts);
1627    if (file.isEmpty())
1628        return false;
1629    else if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool())
1630        settings->setValue(OS"/LastUsed/TaskSavePath", QFileInfo(file).path());
[144fbe6b96]1631    if (QFileInfo(file).suffix().isEmpty()) {
1632        file.append(".tspt");
1633    }
[9eb63a1598]1634
1635    if (tspmodel->saveTask(file)) {
1636        setFileName(file);
1637        setWindowModified(false);
1638        return true;
1639    }
1640    return false;
[1babbd6ba3]1641}
1642
1643void MainWindow::setFileName(const QString &fileName)
1644{
[9eb63a1598]1645    this->fileName = fileName;
1646    setWindowTitle(QString("%1[*] - %2").arg(QFileInfo(fileName).completeBaseName()).arg(QCoreApplication::applicationName()));
[1babbd6ba3]1647}
1648
1649void MainWindow::setupUi()
1650{
[9eb63a1598]1651    Ui_MainWindow::setupUi(this);
[1babbd6ba3]1652
[9eb63a1598]1653    // File Menu
1654    actionFileNew->setIcon(GET_ICON("document-new"));
1655    actionFileOpen->setIcon(GET_ICON("document-open"));
1656    actionFileSave->setIcon(GET_ICON("document-save"));
[95b0ef73dc]1657#if !defined(HANDHELD) || defined(Q_OS_BLACKBERRY)
[9eb63a1598]1658    menuFileSaveAs->setIcon(GET_ICON("document-save-as"));
[a713b103e8]1659#endif
[9eb63a1598]1660    actionFileExit->setIcon(GET_ICON("application-exit"));
1661    // Settings Menu
[95b0ef73dc]1662#if !defined(HANDHELD) || defined(Q_OS_BLACKBERRY)
[9eb63a1598]1663    menuSettingsLanguage->setIcon(GET_ICON("preferences-desktop-locale"));
[a713b103e8]1664#if QT_VERSION >= 0x040600
[9eb63a1598]1665    actionSettingsLanguageEnglish->setIcon(QIcon::fromTheme("flag-gb", QIcon(":/images/icons/l10n/flag-gb.png")));
[a713b103e8]1666#else // QT_VERSION >= 0x040600
[9eb63a1598]1667    actionSettingsLanguageEnglish->setIcon(QIcon(":/images/icons/l10n/flag-gb.png"));
[a713b103e8]1668#endif // QT_VERSION >= 0x040600
[9eb63a1598]1669    menuSettingsStyle->setIcon(GET_ICON("preferences-desktop-theme"));
[a713b103e8]1670#endif // HANDHELD
[9eb63a1598]1671    actionSettingsPreferences->setIcon(GET_ICON("preferences-system"));
1672    // Help Menu
[95b0ef73dc]1673#if !defined(HANDHELD) || defined(Q_OS_BLACKBERRY)
[9eb63a1598]1674    actionHelpContents->setIcon(GET_ICON("help-contents"));
1675    actionHelpContextual->setIcon(GET_ICON("help-contextual"));
1676    actionHelpOnlineSupport->setIcon(GET_ICON("applications-internet"));
1677    actionHelpReportBug->setIcon(GET_ICON("tools-report-bug"));
1678    actionHelpAbout->setIcon(GET_ICON("help-about"));
[aa64ad4082]1679#ifdef Q_OS_BLACKBERRY
1680    // Qt about dialog is too big for the screen
1681    // and it's impossible to close it.
1682    menuHelp->removeAction(actionHelpAboutQt);
1683#else
[fddcfa4b55]1684    actionHelpAboutQt->setIcon(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"));
[a713b103e8]1685#endif
[aa64ad4082]1686#endif
[9eb63a1598]1687    // Buttons
1688    buttonRandom->setIcon(GET_ICON("roll"));
1689    buttonSolve->setIcon(GET_ICON("dialog-ok"));
1690    buttonSaveSolution->setIcon(GET_ICON("document-save-as"));
1691    buttonBackToTask->setIcon(GET_ICON("go-previous"));
[3cadf24d00]1692
[2a436ea693]1693//      action->setIcon(GET_ICON(""));
[3cadf24d00]1694
[1babbd6ba3]1695#if QT_VERSION >= 0x040600
[9eb63a1598]1696    setToolButtonStyle(Qt::ToolButtonFollowStyle);
[1babbd6ba3]1697#endif
1698
1699#ifndef HANDHELD
1700QStatusBar *statusbar = new QStatusBar(this);
[9eb63a1598]1701    statusbar->setObjectName("statusbar");
1702    setStatusBar(statusbar);
[1babbd6ba3]1703#endif // HANDHELD
1704
[97e90f9be6]1705#ifdef Q_WS_WINCE_WM
[9eb63a1598]1706    menuBar()->setDefaultAction(menuFile->menuAction());
[1babbd6ba3]1707
1708QScrollArea *scrollArea = new QScrollArea(this);
[9eb63a1598]1709    scrollArea->setFrameShape(QFrame::NoFrame);
1710    scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1711    scrollArea->setWidgetResizable(true);
1712    scrollArea->setWidget(tabWidget);
1713    setCentralWidget(scrollArea);
[1babbd6ba3]1714#else
[9eb63a1598]1715    setCentralWidget(tabWidget);
[97e90f9be6]1716#endif // Q_WS_WINCE_WM
[1babbd6ba3]1717
[9eb63a1598]1718    //! \hack HACK: A little hack for toolbar icons to have a sane size.
[97e90f9be6]1719#if defined(HANDHELD) && !defined(Q_WS_MAEMO_5)
[5cbcd091ed]1720#ifdef Q_WS_S60
[23ad8db4a5]1721    toolBarMain->setIconSize(QSize(logicalDpiX() / 5.2, logicalDpiY() / 5.2));
[5cbcd091ed]1722#else
[9eb63a1598]1723    toolBarMain->setIconSize(QSize(logicalDpiX() / 4, logicalDpiY() / 4));
[5cbcd091ed]1724#endif // Q_WS_S60
1725#endif // HANDHELD && !Q_WS_MAEMO_5
[7bb19df196]1726QToolButton *tb = static_cast<QToolButton *>(toolBarMain->widgetForAction(actionFileSave));
[5cbcd091ed]1727    if (tb != NULL) {
[9eb63a1598]1728        tb->setMenu(menuFileSaveAs);
1729        tb->setPopupMode(QToolButton::MenuButtonPopup);
1730    }
[1babbd6ba3]1731
[8b0661d1ee]1732//      solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>());
[9eb63a1598]1733    solutionText->setWordWrapMode(QTextOption::WordWrap);
[1babbd6ba3]1734
[ccdffe3a5f]1735#ifndef QT_NO_PRINTDIALOG
[9eb63a1598]1736    actionFilePrintPreview = new QAction(this);
1737    actionFilePrintPreview->setObjectName("actionFilePrintPreview");
1738    actionFilePrintPreview->setEnabled(false);
1739    actionFilePrintPreview->setIcon(GET_ICON("document-print-preview"));
[1babbd6ba3]1740
[20e8115cee]1741    actionFilePageSetup = new QAction(this);
1742    actionFilePageSetup->setObjectName("actionFilePrintSetup");
1743//    actionFilePageSetup->setEnabled(false);
1744#if QT_VERSION >= 0x040600
1745    actionFilePageSetup->setIcon(QIcon::fromTheme("document-page-setup", QIcon(":/trolltech/dialogs/qprintpreviewdialog/images/page-setup-32.png")));
1746#else
1747    actionFilePageSetup->setIcon(QIcon(":/trolltech/dialogs/qprintpreviewdialog/images/page-setup-32.png"));
1748#endif
1749
[9eb63a1598]1750    actionFilePrint = new QAction(this);
1751    actionFilePrint->setObjectName("actionFilePrint");
1752    actionFilePrint->setEnabled(false);
1753    actionFilePrint->setIcon(GET_ICON("document-print"));
[1babbd6ba3]1754
[20e8115cee]1755    menuFile->insertAction(actionFileExit, actionFilePrintPreview);
1756    menuFile->insertAction(actionFileExit, actionFilePageSetup);
1757    menuFile->insertAction(actionFileExit, actionFilePrint);
[9eb63a1598]1758    menuFile->insertSeparator(actionFileExit);
[1babbd6ba3]1759
[9eb63a1598]1760    toolBarMain->insertAction(actionSettingsPreferences, actionFilePrint);
[ccdffe3a5f]1761#endif // QT_NO_PRINTDIALOG
[e51c78af27]1762
[9eb63a1598]1763    groupSettingsLanguageList = new QActionGroup(this);
[97e90f9be6]1764#ifdef Q_WS_MAEMO_5
[9eb63a1598]1765    groupSettingsLanguageList->addAction(actionSettingsLanguageAutodetect);
[97e90f9be6]1766#endif
[9eb63a1598]1767    actionSettingsLanguageEnglish->setData("en");
1768    actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
1769    loadLangList();
1770    actionSettingsLanguageAutodetect->setChecked(settings->value("Language", "").toString().isEmpty());
[e3533af1cf]1771
[9eb63a1598]1772    actionSettingsStyleSystem->setData(true);
1773    groupSettingsStyleList = new QActionGroup(this);
[97e90f9be6]1774#ifdef Q_WS_MAEMO_5
[9eb63a1598]1775    groupSettingsStyleList->addAction(actionSettingsStyleSystem);
[97e90f9be6]1776#endif
[e3533af1cf]1777
[7bb19df196]1778#ifndef HANDHELD
[9eb63a1598]1779    actionSettingsToolbarsConfigure = new QAction(this);
1780    actionSettingsToolbarsConfigure->setIcon(GET_ICON("configure-toolbars"));
[7bb19df196]1781#endif // HANDHELD
1782
[9eb63a1598]1783    if (hasUpdater()) {
1784        actionHelpCheck4Updates = new QAction(this);
1785        actionHelpCheck4Updates->setIcon(GET_ICON("system-software-update"));
1786        actionHelpCheck4Updates->setEnabled(hasUpdater());
1787        menuHelp->insertAction(actionHelpAboutQt, actionHelpCheck4Updates);
1788        menuHelp->insertSeparator(actionHelpAboutQt);
1789    } else
1790        actionHelpCheck4Updates = NULL;
[1babbd6ba3]1791
[9eb63a1598]1792    spinCities->setMaximum(MAX_NUM_CITIES);
[1babbd6ba3]1793
[94cd045fad]1794#ifndef HANDHELD
[20e8115cee]1795    toolBarManager = new QtToolBarManager(this);
[9eb63a1598]1796    toolBarManager->setMainWindow(this);
[7bb19df196]1797QString cat = toolBarMain->windowTitle();
[9eb63a1598]1798    toolBarManager->addToolBar(toolBarMain, cat);
[94cd045fad]1799#ifndef QT_NO_PRINTER
[9eb63a1598]1800    toolBarManager->addAction(actionFilePrintPreview, cat);
[20e8115cee]1801    toolBarManager->addAction(actionFilePageSetup, cat);
[94cd045fad]1802#endif // QT_NO_PRINTER
[9eb63a1598]1803    toolBarManager->addAction(actionHelpContents, cat);
1804    toolBarManager->addAction(actionHelpContextual, cat);
1805    toolBarManager->restoreState(settings->value("MainWindow/Toolbars").toByteArray());
[a713b103e8]1806#else
[9eb63a1598]1807    toolBarMain->setVisible(settings->value("MainWindow/ToolbarVisible", true).toBool());
[94cd045fad]1808#endif // HANDHELD
[7bb19df196]1809
[23ad8db4a5]1810#ifdef Q_WS_S60
1811    // Replace Exit on the right soft key with our own exit action.
1812    // This makes it translatable.
1813    actionRightSoftKey = new QAction(this);
1814    actionRightSoftKey->setSoftKeyRole(QAction::NegativeSoftKey);
1815    connect(actionRightSoftKey, SIGNAL(triggered()), SLOT(close()));
1816    addAction(actionRightSoftKey);
1817#endif
1818
[9eb63a1598]1819    retranslateUi(false);
[7bb19df196]1820
[b8a2a118c4]1821#ifndef HANDHELD
1822    // Adding some eyecandy
[9eb63a1598]1823    if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
1824        toggleTranclucency(true);
1825    }
[b8a2a118c4]1826#endif // HANDHELD
[1babbd6ba3]1827}
1828
1829void MainWindow::toggleSolutionActions(bool enable)
1830{
[9eb63a1598]1831    buttonSaveSolution->setEnabled(enable);
1832    actionFileSaveAsSolution->setEnabled(enable);
1833    solutionText->setEnabled(enable);
[ccdffe3a5f]1834#ifndef QT_NO_PRINTDIALOG
[9eb63a1598]1835    actionFilePrint->setEnabled(enable);
1836    actionFilePrintPreview->setEnabled(enable);
[ccdffe3a5f]1837#endif // QT_NO_PRINTDIALOG
[1babbd6ba3]1838}
1839
1840void MainWindow::toggleTranclucency(bool enable)
1841{
[b8a2a118c4]1842#ifndef HANDHELD
[9eb63a1598]1843    toggleStyle(labelVariant, enable);
1844    toggleStyle(labelCities, enable);
1845    toggleStyle(statusBar(), enable);
1846    tabWidget->setDocumentMode(enable);
1847    QtWin::enableBlurBehindWindow(this, enable);
[1babbd6ba3]1848#else
[9eb63a1598]1849    Q_UNUSED(enable);
[b8a2a118c4]1850#endif // HANDHELD
[1babbd6ba3]1851}
[88a59e4d65]1852
1853void MainWindow::actionHelpOnlineSupportTriggered()
1854{
[9eb63a1598]1855    QDesktopServices::openUrl(QUrl("http://tspsg.info/goto/support"));
[88a59e4d65]1856}
1857
1858void MainWindow::actionHelpReportBugTriggered()
1859{
[9eb63a1598]1860    QDesktopServices::openUrl(QUrl("http://tspsg.info/goto/bugtracker"));
[88a59e4d65]1861}
[fddcfa4b55]1862
1863#ifdef Q_WS_S60
1864QSMessageBox::QSMessageBox(QWidget *parent)
1865    : QMessageBox(parent)
1866{
1867    setIcon(QMessageBox::Warning);
1868    setWindowTitle(QApplication::translate("MainWindow", "Unsaved Changes"));
1869    setText(QApplication::translate("MainWindow", "Would you like to save changes in the current task?"));
1870    setStandardButtons(QMessageBox::Save);
1871
1872    QMenu *m = new QMenu(this);
[019894f5ef]1873    m->addAction(QApplication::translate("QDialogButtonBox", "Discard", "No need to translate this. The translation will be taken from Qt translation files."),
[fddcfa4b55]1874                 this, SLOT(discard()));
[019894f5ef]1875    m->addAction(QApplication::translate("QDialogButtonBox", "Cancel", "No need to translate this. The translation will be taken from Qt translation files."),
[fddcfa4b55]1876                 this, SLOT(cancel()));
1877
[019894f5ef]1878    QAction *o = new QAction(QApplication::translate("QtToolBarDialog", "Actions"), this);
[fddcfa4b55]1879    o->setSoftKeyRole(QAction::NegativeSoftKey);
1880    o->setMenu(m);
1881    addAction(o);
1882}
1883
1884void QSMessageBox::cancel(){
1885    done(QMessageBox::Cancel);
1886}
1887
1888void QSMessageBox::discard() {
1889    done(QMessageBox::Discard);
1890}
1891#endif // Q_WS_S60
Note: See TracBrowser for help on using the repository browser.