source: tspsg/src/mainwindow.cpp @ 1299ea5b49

appveyorimgbotreadme
Last change on this file since 1299ea5b49 was 1299ea5b49, checked in by Oleksii Serdiuk, 12 years ago

Updated version info to be set based on git tags.

'git describe' is now used for version definition. Major, minor and
release are taken from the latest git tag. Build is defined as number of
commits since the latest tag. If we're out of source, then .tag file
should contain output of 'git describe --abbrev=40' command.

Also, moved version related code from tspsg.pro to version.pri.

  • Property mode set to 100644
File size: 72.1 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 *
[7ba743d983]5 *  $Id: $Format:%h %ai %an$ $
6 *  $URL: http://tspsg.info/ $
[1babbd6ba3]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()));
[1babbd6ba3]92#ifndef QT_NO_PRINTER
[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
378#ifndef QT_NO_PRINTER
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}
436#endif // QT_NO_PRINTER
437
438void MainWindow::actionSettingsPreferencesTriggered()
439{
440SettingsDialog sd(this);
[1b40fef578]441#ifdef Q_WS_S60
442    sd.setWindowState(Qt::WindowMaximized);
443#endif
[9eb63a1598]444    if (sd.exec() != QDialog::Accepted)
445        return;
446    if (sd.colorChanged() || sd.fontChanged()) {
447        if (!solutionText->document()->isEmpty() && sd.colorChanged())
448            QMessageBox::information(this, tr("Settings Changed"), tr("You have changed color settings.\nThey will be applied to the next solution output."));
449        initDocStyleSheet();
450    }
451    if (sd.translucencyChanged() != 0)
452        toggleTranclucency(sd.translucencyChanged() == 1);
[1babbd6ba3]453}
454
455void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked)
456{
[9eb63a1598]457    if (checked) {
458        settings->remove("Language");
459        QMessageBox::information(this, tr("Language change"), tr("Language will be autodetected on the next %1 start.").arg(QCoreApplication::applicationName()));
460    } else
461        settings->setValue("Language", groupSettingsLanguageList->checkedAction()->data().toString());
[1babbd6ba3]462}
463
464void MainWindow::groupSettingsLanguageListTriggered(QAction *action)
465{
[97e90f9be6]466#ifndef Q_WS_MAEMO_5
[9eb63a1598]467    if (actionSettingsLanguageAutodetect->isChecked())
468        actionSettingsLanguageAutodetect->trigger();
[97e90f9be6]469#endif
[1babbd6ba3]470bool untitled = (fileName == tr("Untitled") + ".tspt");
[9eb63a1598]471    if (loadLanguage(action->data().toString())) {
472        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
473        settings->setValue("Language",action->data().toString());
474        retranslateUi();
475        if (untitled)
476            setFileName();
[b8a2a118c4]477#ifndef HANDHELD
[9eb63a1598]478        if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
479            toggleStyle(labelVariant, true);
480            toggleStyle(labelCities, true);
481        }
[1babbd6ba3]482#endif
[9eb63a1598]483        QApplication::restoreOverrideCursor();
484        if (!solutionText->document()->isEmpty())
485            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."));
486    }
[1babbd6ba3]487}
488
[e3533af1cf]489void MainWindow::actionSettingsStyleSystemTriggered(bool checked)
490{
[9eb63a1598]491    if (checked) {
492        settings->remove("Style");
493        QMessageBox::information(this, tr("Style Change"), tr("To apply the default style you need to restart %1.").arg(QCoreApplication::applicationName()));
494    } else {
495        settings->setValue("Style", groupSettingsStyleList->checkedAction()->text());
496    }
[e3533af1cf]497}
498
499void MainWindow::groupSettingsStyleListTriggered(QAction *action)
500{
501QStyle *s = QStyleFactory::create(action->text());
[9eb63a1598]502    if (s != NULL) {
503        QApplication::setStyle(s);
504        settings->setValue("Style", action->text());
505        actionSettingsStyleSystem->setChecked(false);
506    }
[e3533af1cf]507}
508
[7bb19df196]509#ifndef HANDHELD
510void MainWindow::actionSettingsToolbarsConfigureTriggered()
511{
512QtToolBarDialog dlg(this);
[9eb63a1598]513    dlg.setToolBarManager(toolBarManager);
514    dlg.exec();
[7bb19df196]515QToolButton *tb = static_cast<QToolButton *>(toolBarMain->widgetForAction(actionFileSave));
[9eb63a1598]516    if (tb != NULL) {
517        tb->setMenu(menuFileSaveAs);
518        tb->setPopupMode(QToolButton::MenuButtonPopup);
519        tb->resize(tb->sizeHint());
520    }
[7bb19df196]521
[9eb63a1598]522    loadToolbarList();
[7bb19df196]523}
524#endif // HANDHELD
525
[1babbd6ba3]526void MainWindow::actionHelpCheck4UpdatesTriggered()
527{
[9eb63a1598]528    if (!hasUpdater()) {
[019894f5ef]529        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]530        return;
531    }
[1babbd6ba3]532
[9eb63a1598]533    check4Updates();
[1babbd6ba3]534}
535
536void MainWindow::actionHelpAboutTriggered()
537{
[9eb63a1598]538    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[43c29c04ba]539
[1babbd6ba3]540QString title;
[9eb63a1598]541    title += QString("<b>%1</b><br>").arg(QCoreApplication::applicationName());
542    title += QString("%1: <b>%2</b><br>").arg(tr("Version"), QCoreApplication::applicationVersion());
[1babbd6ba3]543#ifndef HANDHELD
[9eb63a1598]544    title += QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b><br>").arg(QDate::currentDate().toString("yyyy"), QCoreApplication::organizationDomain(), QCoreApplication::organizationName());
[7bb19df196]545#endif // HANDHELD
[9eb63a1598]546    title += QString("<b><a href=\"http://tspsg.info/\">http://tspsg.info/</a></b>");
[1babbd6ba3]547
548QString about;
[9eb63a1598]549    about += QString("%1: <b>%2</b><br>").arg(tr("Target OS (ARCH)"), PLATFROM);
[fddcfa4b55]550    about += QString("%1:<br>").arg(tr("Qt library"));
[9eb63a1598]551    about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Build time"), QT_VERSION_STR);
552    about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Runtime"), qVersion());
[03df0acb95]553    about.append(QString("%1: <b>%2x%3</b><br>").arg(tr("Logical screen DPI")).arg(logicalDpiX()).arg(logicalDpiY()));
[1299ea5b49]554QString tag;
555#ifdef REVISION_STR
556    tag = tr(" from git revision <b>%1</b>").arg(REVISION_STR);
557#endif
558    about += tr("Build <b>%1</b>, built%5 on <b>%2</b> at <b>%3</b> with <b>%4</b> compiler.").arg(BUILD_NUMBER).arg(__DATE__).arg(__TIME__).arg(COMPILER).arg(tag) + "<br>";
[9eb63a1598]559    about += QString("%1: <b>%2</b><br>").arg(tr("Algorithm"), CTSPSolver::getVersionId());
560    about += "<br>";
561    about += tr("This program is free software: you can redistribute it and/or modify<br>\n"
562        "it under the terms of the GNU General Public License as published by<br>\n"
563        "the Free Software Foundation, either version 3 of the License, or<br>\n"
564        "(at your option) any later version.<br>\n"
565        "<br>\n"
566        "This program is distributed in the hope that it will be useful,<br>\n"
567        "but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\n"
568        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>\n"
569        "GNU General Public License for more details.<br>\n"
570        "<br>\n"
571        "You should have received a copy of the GNU General Public License<br>\n"
572        "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">www.gnu.org/licenses/</a>.");
[43c29c04ba]573
574QString credits;
[9eb63a1598]575    credits += tr("%1 was created using <b>Qt&nbsp;framework</b> licensed "
576        "under the terms of the GNU Lesser General Public License,<br>\n"
577        "see <a href=\"http://qt.nokia.com/\">qt.nokia.com</a><br>\n"
578        "<br>\n"
579        "Most icons used in %1 are part of <b>Oxygen&nbsp;Icons</b> project "
580        "licensed according to the GNU Lesser General Public License,<br>\n"
581        "see <a href=\"http://www.oxygen-icons.org/\">www.oxygen-icons.org</a><br>\n"
582        "<br>\n"
583        "Country flag icons used in %1 are part of the free "
584        "<b>Flag&nbsp;Icons</b> collection created by <b>IconDrawer</b>,<br>\n"
585        "see <a href=\"http://www.icondrawer.com/\">www.icondrawer.com</a><br>\n"
586        "<br>\n"
587        "%1 comes with the default \"embedded\" font <b>DejaVu&nbsp;LGC&nbsp;Sans&nbsp;"
588        "Mono</b> from the <b>DejaVu fonts</b> licensed under a Free license</a>,<br>\n"
589        "see <a href=\"http://dejavu-fonts.org/\">dejavu-fonts.org</a>")
590            .arg("TSPSG");
[43c29c04ba]591
592QFile f(":/files/COPYING");
[9eb63a1598]593    f.open(QIODevice::ReadOnly);
[43c29c04ba]594
[88a59e4d65]595QString translation = QCoreApplication::translate("--------", "AUTHORS %1", "Please, provide translator credits here. %1 will be replaced with VERSION");
[9eb63a1598]596    if ((translation != "AUTHORS %1") && (translation.contains("%1"))) {
[88a59e4d65]597QString about = QCoreApplication::translate("--------", "VERSION", "Please, provide your translation version here.");
[9eb63a1598]598        if (about != "VERSION")
599            translation = translation.arg(about);
600    }
[1babbd6ba3]601
602QDialog *dlg = new QDialog(this);
603QLabel *lblIcon = new QLabel(dlg),
[9eb63a1598]604    *lblTitle = new QLabel(dlg);
[1babbd6ba3]605#ifdef HANDHELD
[88a59e4d65]606QLabel *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]607#endif // HANDHELD
[43c29c04ba]608QTabWidget *tabs = new QTabWidget(dlg);
[1babbd6ba3]609QTextBrowser *txtAbout = new QTextBrowser(dlg);
[43c29c04ba]610QTextBrowser *txtLicense = new QTextBrowser(dlg);
611QTextBrowser *txtCredits = new QTextBrowser(dlg);
[1babbd6ba3]612QVBoxLayout *vb = new QVBoxLayout();
613QHBoxLayout *hb1 = new QHBoxLayout(),
[9eb63a1598]614    *hb2 = new QHBoxLayout();
[1babbd6ba3]615QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dlg);
616
[9eb63a1598]617    lblTitle->setOpenExternalLinks(true);
618    lblTitle->setText(title);
619    lblTitle->setAlignment(Qt::AlignTop);
620    lblTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
[1babbd6ba3]621#ifndef HANDHELD
[9eb63a1598]622    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]623#endif // HANDHELD
624
[9eb63a1598]625    lblIcon->setPixmap(QPixmap(":/images/tspsg.png").scaledToHeight(lblTitle->sizeHint().height(), Qt::SmoothTransformation));
626    lblIcon->setAlignment(Qt::AlignVCenter);
[1babbd6ba3]627#ifndef HANDHELD
[9eb63a1598]628    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]629#endif // HANDHELD
630
[9eb63a1598]631    hb1->addWidget(lblIcon);
632    hb1->addWidget(lblTitle);
[1babbd6ba3]633
[9eb63a1598]634    txtAbout->setWordWrapMode(QTextOption::NoWrap);
635    txtAbout->setOpenExternalLinks(true);
636    txtAbout->setHtml(about);
637    txtAbout->moveCursor(QTextCursor::Start);
638    txtAbout->setFrameShape(QFrame::NoFrame);
[1babbd6ba3]639
[43c29c04ba]640//      txtCredits->setWordWrapMode(QTextOption::NoWrap);
[9eb63a1598]641    txtCredits->setOpenExternalLinks(true);
642    txtCredits->setHtml(credits);
643    txtCredits->moveCursor(QTextCursor::Start);
644    txtCredits->setFrameShape(QFrame::NoFrame);
[1babbd6ba3]645
[9eb63a1598]646    txtLicense->setWordWrapMode(QTextOption::NoWrap);
647    txtLicense->setOpenExternalLinks(true);
648    txtLicense->setText(f.readAll());
649    txtLicense->moveCursor(QTextCursor::Start);
650    txtLicense->setFrameShape(QFrame::NoFrame);
[1babbd6ba3]651
[9eb63a1598]652    bb->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor));
653    bb->button(QDialogButtonBox::Ok)->setIcon(GET_ICON("dialog-ok"));
[3cadf24d00]654
[9eb63a1598]655    hb2->addWidget(bb);
[1babbd6ba3]656
[97e90f9be6]657#ifdef Q_WS_WINCE_WM
[9eb63a1598]658    vb->setMargin(3);
[97e90f9be6]659#endif // Q_WS_WINCE_WM
[9eb63a1598]660    vb->addLayout(hb1);
[1babbd6ba3]661#ifdef HANDHELD
[9eb63a1598]662    vb->addWidget(lblSubTitle);
[1babbd6ba3]663#endif // HANDHELD
[43c29c04ba]664
[9eb63a1598]665    tabs->addTab(txtAbout, tr("About"));
666    tabs->addTab(txtLicense, tr("License"));
667    tabs->addTab(txtCredits, tr("Credits"));
668    if (translation != "AUTHORS %1") {
[43c29c04ba]669QTextBrowser *txtTranslation = new QTextBrowser(dlg);
670//              txtTranslation->setWordWrapMode(QTextOption::NoWrap);
[9eb63a1598]671        txtTranslation->setOpenExternalLinks(true);
672        txtTranslation->setText(translation);
673        txtTranslation->moveCursor(QTextCursor::Start);
674        txtTranslation->setFrameShape(QFrame::NoFrame);
[43c29c04ba]675
[9eb63a1598]676        tabs->addTab(txtTranslation, tr("Translation"));
677    }
[43c29c04ba]678#ifndef HANDHELD
[9eb63a1598]679    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]680#endif // HANDHELD
681
[9eb63a1598]682    vb->addWidget(tabs);
683    vb->addLayout(hb2);
[1babbd6ba3]684
[9eb63a1598]685    dlg->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
686    dlg->setWindowTitle(tr("About %1").arg(QCoreApplication::applicationName()));
687    dlg->setWindowIcon(GET_ICON("help-about"));
[d97db6d321]688
[9eb63a1598]689    dlg->setLayout(vb);
[1babbd6ba3]690
[9eb63a1598]691    connect(bb, SIGNAL(accepted()), dlg, SLOT(accept()));
[1babbd6ba3]692
[b8a2a118c4]693#ifndef HANDHELD
694    // Adding some eyecandy
[9eb63a1598]695    if (QtWin::isCompositionEnabled())  {
696        QtWin::enableBlurBehindWindow(dlg, true);
697    }
[b8a2a118c4]698#endif // HANDHELD
[1babbd6ba3]699
[5cbcd091ed]700#ifndef HANDHELD
[9eb63a1598]701    dlg->resize(450, 350);
[1b40fef578]702#elif defined(Q_WS_S60)
703    dlg->setWindowState(Qt::WindowMaximized);
[5cbcd091ed]704#endif
[9eb63a1598]705    QApplication::restoreOverrideCursor();
[1babbd6ba3]706
[9eb63a1598]707    dlg->exec();
[1babbd6ba3]708
[9eb63a1598]709    delete dlg;
[1babbd6ba3]710}
711
712void MainWindow::buttonBackToTaskClicked()
713{
[9eb63a1598]714    tabWidget->setCurrentIndex(0);
[1babbd6ba3]715}
716
717void MainWindow::buttonRandomClicked()
718{
[9eb63a1598]719    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
720    tspmodel->randomize();
721    QApplication::restoreOverrideCursor();
[1babbd6ba3]722}
723
724void MainWindow::buttonSolveClicked()
725{
726TMatrix matrix;
727QList<double> row;
728int n = spinCities->value();
729bool ok;
[9eb63a1598]730    for (int r = 0; r < n; r++) {
731        row.clear();
732        for (int c = 0; c < n; c++) {
733            row.append(tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok));
734            if (!ok) {
735                QMessageBox::critical(this, tr("Data error"), tr("Error in cell [Row %1; Column %2]: Invalid data format.").arg(r + 1).arg(c + 1));
736                return;
737            }
738        }
739        matrix.append(row);
740    }
[1babbd6ba3]741
742QProgressDialog pd(this);
743QProgressBar *pb = new QProgressBar(&pd);
[9eb63a1598]744    pb->setAlignment(Qt::AlignCenter);
745    pb->setFormat(tr("%v of %1 parts found").arg(n));
746    pd.setBar(pb);
[43c29c04ba]747QPushButton *cancel = new QPushButton(&pd);
[9eb63a1598]748    cancel->setIcon(GET_ICON("dialog-cancel"));
[019894f5ef]749    cancel->setText(QCoreApplication::translate("QDialogButtonBox", "Cancel", "No need to translate this. The translation will be taken from Qt translation files."));
[9eb63a1598]750    pd.setCancelButton(cancel);
751    pd.setMaximum(n);
752    pd.setAutoReset(false);
753    pd.setLabelText(tr("Calculating optimal route..."));
754    pd.setWindowTitle(tr("Solution Progress"));
755    pd.setWindowModality(Qt::ApplicationModal);
756    pd.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
757    pd.show();
[1babbd6ba3]758
[97e90f9be6]759#ifdef Q_WS_WIN32
[43c29c04ba]760HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID*)&tl);
[9eb63a1598]761    if (SUCCEEDED(hr)) {
762        hr = tl->HrInit();
763        if (FAILED(hr)) {
764            tl->Release();
765            tl = NULL;
766        } else {
767            tl->SetProgressValue(winId(), 0, n * 2);
768        }
769    }
[43c29c04ba]770#endif
771
[1babbd6ba3]772CTSPSolver solver;
[9eb63a1598]773    solver.setCleanupOnCancel(false);
774    connect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
775    connect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
[97e90f9be6]776#ifdef Q_WS_WIN32
[9eb63a1598]777    if (tl != NULL)
778        connect(&solver, SIGNAL(routePartFound(int)), SLOT(solverRoutePartFound(int)));
[43c29c04ba]779#endif
[1babbd6ba3]780SStep *root = solver.solve(n, matrix);
[97e90f9be6]781#ifdef Q_WS_WIN32
[9eb63a1598]782    if (tl != NULL)
783        disconnect(&solver, SIGNAL(routePartFound(int)), this, SLOT(solverRoutePartFound(int)));
[43c29c04ba]784#endif
[9eb63a1598]785    disconnect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
786    disconnect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
787    if (!root) {
788        pd.reset();
789        if (!solver.wasCanceled()) {
[97e90f9be6]790#ifdef Q_WS_WIN32
[9eb63a1598]791            if (tl != NULL) {
792                tl->SetProgressState(winId(), TBPF_ERROR);
793            }
[43c29c04ba]794#endif
[9eb63a1598]795            QApplication::alert(this);
796            QMessageBox::warning(this, tr("Solution Result"), tr("Unable to find a solution.\nMaybe, this task has no solution."));
797        }
[d97db6d321]798        pd.setLabelText(tr("Memory cleanup..."));
[9eb63a1598]799        pd.setMaximum(0);
800        pd.setCancelButton(NULL);
801        pd.show();
[97e90f9be6]802#ifdef Q_WS_WIN32
[9eb63a1598]803        if (tl != NULL)
804            tl->SetProgressState(winId(), TBPF_INDETERMINATE);
[43c29c04ba]805#endif
[9eb63a1598]806        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
[43c29c04ba]807
[a713b103e8]808#ifndef QT_NO_CONCURRENT
[43c29c04ba]809QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
[9eb63a1598]810        while (!f.isFinished()) {
811            QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
812        }
[a713b103e8]813#else
[9eb63a1598]814        solver.cleanup(true);
[a713b103e8]815#endif
[9eb63a1598]816        pd.reset();
[97e90f9be6]817#ifdef Q_WS_WIN32
[9eb63a1598]818        if (tl != NULL) {
819            tl->SetProgressState(winId(), TBPF_NOPROGRESS);
820            tl->Release();
821            tl = NULL;
822        }
[43c29c04ba]823#endif
[9eb63a1598]824        return;
825    }
826    pb->setFormat(tr("Generating header"));
827    pd.setLabelText(tr("Generating solution output..."));
828    pd.setMaximum(solver.getTotalSteps() + 1);
829    pd.setValue(0);
[1babbd6ba3]830
[97e90f9be6]831#ifdef Q_WS_WIN32
[9eb63a1598]832    if (tl != NULL)
833        tl->SetProgressValue(winId(), spinCities->value(), spinCities->value() + solver.getTotalSteps() + 1);
[43c29c04ba]834#endif
835
[9eb63a1598]836    solutionText->clear();
837    solutionText->setDocumentTitle(tr("Solution of Variant #%1 Task").arg(spinVariant->value()));
[317ba0432e]838
[345e7b6132]839QPainter pic;
[8f2427aaf0]840bool dograph = settings->value("Output/GenerateGraph", DEF_GENERATE_GRAPH).toBool();
841    if (dograph) {
[9eb63a1598]842        pic.begin(&graph);
843        pic.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
[20e8115cee]844QFont font = qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE)));
[fddcfa4b55]845        font.setStyleHint(QFont::TypeWriter);
[8f2427aaf0]846        // Font size in pixels = graph node radius / 2.75.
847        // See MainWindow::drawNode() for graph node radius calcualtion description.
[fddcfa4b55]848#ifndef Q_WS_S60
[8f2427aaf0]849        font.setPixelSize(logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5 / 2.75);
[fddcfa4b55]850#else
851        // Also, see again MainWindow::drawNode() for why is additional 1.3 divider added in Symbian.
852        font.setPixelSize(logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5 / 2.75 / 1.3);
853#endif
[9eb63a1598]854        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
855            font.setWeight(QFont::DemiBold);
[8f2427aaf0]856            font.setPixelSize(font.pixelSize() * HQ_FACTOR);
[9eb63a1598]857        }
858        pic.setFont(font);
859        pic.setBrush(QBrush(QColor(Qt::white)));
860        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
[7aaa0b0ec7]861QPen pen = pic.pen();
[8f2427aaf0]862            pen.setWidth(HQ_FACTOR);
[9eb63a1598]863            pic.setPen(pen);
864        }
865        pic.setBackgroundMode(Qt::OpaqueMode);
[8f2427aaf0]866    } else {
867        graph = QPicture();
[9eb63a1598]868    }
[345e7b6132]869
[317ba0432e]870QTextDocument *doc = solutionText->document();
871QTextCursor cur(doc);
872
[9eb63a1598]873    cur.beginEditBlock();
874    cur.setBlockFormat(fmt_paragraph);
875    cur.insertText(tr("Variant #%1 Task").arg(spinVariant->value()), fmt_default);
876    cur.insertBlock(fmt_paragraph);
[a885c3d9d2]877    cur.insertText(tr("Task:"), fmt_default);
[9eb63a1598]878    outputMatrix(cur, matrix);
[8f2427aaf0]879    if (dograph) {
[3cadf24d00]880#ifdef _T_T_L_
[9eb63a1598]881        _b_ _i_ _z_ _a_ _r_ _r_ _e_
[3cadf24d00]882#endif
[9eb63a1598]883        drawNode(pic, 0);
884    }
885    cur.insertHtml("<hr>");
886    cur.insertBlock(fmt_paragraph);
[345e7b6132]887int imgpos = cur.position();
[9eb63a1598]888    cur.insertText(tr("Variant #%1 Solution").arg(spinVariant->value()), fmt_default);
889    cur.endEditBlock();
[317ba0432e]890
[1babbd6ba3]891SStep *step = root;
[9cda6e0f5d]892int c = n = 1;
[9eb63a1598]893    pb->setFormat(tr("Generating step %v"));
894    while ((step->next != SStep::NoNextStep) && (c < spinCities->value())) {
895        if (pd.wasCanceled()) {
[d97db6d321]896            pd.setLabelText(tr("Memory cleanup..."));
[9eb63a1598]897            pd.setMaximum(0);
898            pd.setCancelButton(NULL);
899            pd.show();
900            QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
[97e90f9be6]901#ifdef Q_WS_WIN32
[9eb63a1598]902            if (tl != NULL)
903                tl->SetProgressState(winId(), TBPF_INDETERMINATE);
[43c29c04ba]904#endif
[a713b103e8]905#ifndef QT_NO_CONCURRENT
[43c29c04ba]906QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
[9eb63a1598]907            while (!f.isFinished()) {
908                QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
909            }
[a713b103e8]910#else
[9eb63a1598]911            solver.cleanup(true);
[a713b103e8]912#endif
[9eb63a1598]913            solutionText->clear();
914            toggleSolutionActions(false);
[97e90f9be6]915#ifdef Q_WS_WIN32
[9eb63a1598]916            if (tl != NULL) {
917                tl->SetProgressState(winId(), TBPF_NOPROGRESS);
918                tl->Release();
919                tl = NULL;
920            }
[43c29c04ba]921#endif
[9eb63a1598]922            return;
923        }
924        pd.setValue(n);
[97e90f9be6]925#ifdef Q_WS_WIN32
[9eb63a1598]926        if (tl != NULL)
927            tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1);
[43c29c04ba]928#endif
[1babbd6ba3]929
[9eb63a1598]930        cur.beginEditBlock();
931        cur.insertBlock(fmt_paragraph);
[a885c3d9d2]932        cur.insertText(tr("Step #%1").arg(n), fmt_default);
[9eb63a1598]933        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())))) {
934            outputMatrix(cur, *step);
935        }
[8f2427aaf0]936        if (step->alts.empty())
937            cur.insertBlock(fmt_lastparagraph);
938        else
939            cur.insertBlock(fmt_paragraph);
[9eb63a1598]940        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);
941        if (!step->alts.empty()) {
942            SStep::SCandidate cand;
943            QString alts;
944            foreach(cand, step->alts) {
945                if (!alts.isEmpty())
946                    alts += ", ";
947                alts += tr("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1);
948            }
[8f2427aaf0]949            cur.insertBlock(fmt_lastparagraph);
[9eb63a1598]950            cur.insertText(tr("%n alternate candidate(s) for branching: %1.", "", step->alts.count()).arg(alts), fmt_altlist);
951        }
952        cur.endEditBlock();
953
[8f2427aaf0]954        if (dograph) {
[9eb63a1598]955            if (step->prNode != NULL)
956                drawNode(pic, n, false, step->prNode);
957            if (step->plNode != NULL)
958                drawNode(pic, n, true, step->plNode);
959        }
960        n++;
961
962        if (step->next == SStep::RightBranch) {
963            c++;
964            step = step->prNode;
965        } else if (step->next == SStep::LeftBranch) {
966            step = step->plNode;
967        } else
968            break;
969    }
970    pb->setFormat(tr("Generating footer"));
971    pd.setValue(n);
[97e90f9be6]972#ifdef Q_WS_WIN32
[9eb63a1598]973    if (tl != NULL)
974        tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1);
[43c29c04ba]975#endif
[1babbd6ba3]976
[9eb63a1598]977    cur.beginEditBlock();
978    cur.insertBlock(fmt_paragraph);
979    if (solver.isOptimal())
[8f2427aaf0]980        cur.insertText(tr("Optimal path:"), fmt_default);
[9eb63a1598]981    else
[8f2427aaf0]982        cur.insertText(tr("Resulting path:"), fmt_default);
[9eb63a1598]983
984    cur.insertBlock(fmt_paragraph);
985    cur.insertText("  " + solver.getSortedPath(tr("City %1")));
986
[8f2427aaf0]987    if (solver.isOptimal())
988        cur.insertBlock(fmt_paragraph);
989    else
990        cur.insertBlock(fmt_lastparagraph);
[9eb63a1598]991    if (isInteger(step->price))
992        cur.insertHtml("<p>" + tr("The price is <b>%n</b> unit(s).", "", qRound(step->price)) + "</p>");
993    else
994        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>");
995    if (!solver.isOptimal()) {
996        cur.insertBlock(fmt_paragraph);
997        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>");
998    }
999    cur.endEditBlock();
1000
[8f2427aaf0]1001    if (dograph) {
[9eb63a1598]1002        pic.end();
[345e7b6132]1003
[131c5fc3ba]1004QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_RGB32);
[9eb63a1598]1005        i.fill(0xFFFFFF);
1006        pic.begin(&i);
1007        pic.drawPicture(1, 1, graph);
1008        pic.end();
1009        doc->addResource(QTextDocument::ImageResource, QUrl("tspsg://graph.pic"), i);
[345e7b6132]1010
1011QTextImageFormat img;
[9eb63a1598]1012        img.setName("tspsg://graph.pic");
1013        if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) {
[8f2427aaf0]1014            img.setWidth(i.width() / HQ_FACTOR);
1015            img.setHeight(i.height() / HQ_FACTOR);
[9eb63a1598]1016        } else {
1017            img.setWidth(i.width());
1018            img.setHeight(i.height());
1019        }
1020
1021        cur.setPosition(imgpos);
1022        cur.insertImage(img, QTextFrameFormat::FloatRight);
1023    }
1024
1025    if (settings->value("Output/ScrollToEnd", DEF_SCROLL_TO_END).toBool()) {
1026        // Scrolling to the end of the text.
1027        solutionText->moveCursor(QTextCursor::End);
1028    } else
1029        solutionText->moveCursor(QTextCursor::Start);
1030
[d97db6d321]1031    pd.setLabelText(tr("Memory cleanup..."));
[9eb63a1598]1032    pd.setMaximum(0);
1033    pd.setCancelButton(NULL);
1034    QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
[97e90f9be6]1035#ifdef Q_WS_WIN32
[9eb63a1598]1036    if (tl != NULL)
1037        tl->SetProgressState(winId(), TBPF_INDETERMINATE);
[43c29c04ba]1038#endif
[a713b103e8]1039#ifndef QT_NO_CONCURRENT
[43c29c04ba]1040QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
[9eb63a1598]1041    while (!f.isFinished()) {
1042        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1043    }
[a713b103e8]1044#else
[9eb63a1598]1045    solver.cleanup(true);
[a713b103e8]1046#endif
[9eb63a1598]1047    toggleSolutionActions();
1048    tabWidget->setCurrentIndex(1);
[97e90f9be6]1049#ifdef Q_WS_WIN32
[9eb63a1598]1050    if (tl != NULL) {
1051        tl->SetProgressState(winId(), TBPF_NOPROGRESS);
1052        tl->Release();
1053        tl = NULL;
1054    }
[43c29c04ba]1055#endif
1056
[9eb63a1598]1057    pd.reset();
1058    QApplication::alert(this, 3000);
[1babbd6ba3]1059}
1060
1061void MainWindow::dataChanged()
1062{
[9eb63a1598]1063    setWindowModified(true);
[1babbd6ba3]1064}
1065
1066void MainWindow::dataChanged(const QModelIndex &tl, const QModelIndex &br)
1067{
[9eb63a1598]1068    setWindowModified(true);
1069    if (settings->value("Autosize", DEF_AUTOSIZE).toBool()) {
1070        for (int k = tl.row(); k <= br.row(); k++)
1071            taskView->resizeRowToContents(k);
1072        for (int k = tl.column(); k <= br.column(); k++)
1073            taskView->resizeColumnToContents(k);
1074    }
[1babbd6ba3]1075}
1076
[97e90f9be6]1077#ifdef Q_WS_WINCE_WM
[1babbd6ba3]1078void MainWindow::changeEvent(QEvent *ev)
1079{
[9eb63a1598]1080    if ((ev->type() == QEvent::ActivationChange) && isActiveWindow())
1081        desktopResized(0);
[1babbd6ba3]1082
[9eb63a1598]1083    QWidget::changeEvent(ev);
[1babbd6ba3]1084}
1085
1086void MainWindow::desktopResized(int screen)
1087{
[9eb63a1598]1088    if ((screen != 0) || !isActiveWindow())
1089        return;
[1babbd6ba3]1090
1091QRect availableGeometry = QApplication::desktop()->availableGeometry(0);
[9eb63a1598]1092    if (currentGeometry != availableGeometry) {
1093        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1094        /*!
1095         * \hack HACK: This hack checks whether \link QDesktopWidget::availableGeometry() availableGeometry()\endlink's \c top + \c hegiht = \link QDesktopWidget::screenGeometry() screenGeometry()\endlink's \c height.
1096         *  If \c true, the window gets maximized. If we used \c setGeometry() in this case, the bottom of the
1097         *  window would end up being behind the soft buttons. Is this a bug in Qt or Windows Mobile?
1098         */
1099        if ((availableGeometry.top() + availableGeometry.height()) == QApplication::desktop()->screenGeometry().height()) {
1100            setWindowState(windowState() | Qt::WindowMaximized);
1101        } else {
1102            if (windowState() & Qt::WindowMaximized)
1103                setWindowState(windowState() ^ Qt::WindowMaximized);
1104            setGeometry(availableGeometry);
1105        }
1106        currentGeometry = availableGeometry;
1107        QApplication::restoreOverrideCursor();
1108    }
[1babbd6ba3]1109}
[97e90f9be6]1110#endif // Q_WS_WINCE_WM
[1babbd6ba3]1111
1112void MainWindow::numCitiesChanged(int nCities)
1113{
[9eb63a1598]1114    blockSignals(true);
1115    spinCities->setValue(nCities);
1116    blockSignals(false);
[1babbd6ba3]1117}
1118
1119#ifndef QT_NO_PRINTER
1120void MainWindow::printPreview(QPrinter *printer)
1121{
[9eb63a1598]1122    solutionText->print(printer);
[1babbd6ba3]1123}
1124#endif // QT_NO_PRINTER
1125
[97e90f9be6]1126#ifdef Q_WS_WIN32
[43c29c04ba]1127void MainWindow::solverRoutePartFound(int n)
1128{
[9eb63a1598]1129    tl->SetProgressValue(winId(), n, spinCities->value() * 2);
[43c29c04ba]1130}
[97e90f9be6]1131#endif // Q_WS_WIN32
[43c29c04ba]1132
[1babbd6ba3]1133void MainWindow::spinCitiesValueChanged(int n)
1134{
[9eb63a1598]1135    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[1babbd6ba3]1136int count = tspmodel->numCities();
[9eb63a1598]1137    tspmodel->setNumCities(n);
1138    if ((n > count) && settings->value("Autosize", DEF_AUTOSIZE).toBool())
1139        for (int k = count; k < n; k++) {
1140            taskView->resizeColumnToContents(k);
1141            taskView->resizeRowToContents(k);
1142        }
1143    QApplication::restoreOverrideCursor();
[1babbd6ba3]1144}
1145
[f5c945d7ac]1146void MainWindow::check4Updates(bool silent)
1147{
[97e90f9be6]1148#ifdef Q_WS_WIN32
[9eb63a1598]1149    if (silent)
1150        QProcess::startDetached("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\" -silentcheck");
1151    else {
1152        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1153        QProcess::execute("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\"");
1154        QApplication::restoreOverrideCursor();
1155    }
[0007f69c46]1156#else
[9eb63a1598]1157    Q_UNUSED(silent)
[f5c945d7ac]1158#endif
[9eb63a1598]1159    settings->setValue("Check4Updates/LastAttempt", QDate::currentDate().toString(Qt::ISODate));
[f5c945d7ac]1160}
1161
[1babbd6ba3]1162void MainWindow::closeEvent(QCloseEvent *ev)
1163{
[9eb63a1598]1164    if (!maybeSave()) {
1165        ev->ignore();
1166        return;
1167    }
1168    if (!settings->value("SettingsReset", false).toBool()) {
1169        settings->setValue("NumCities", spinCities->value());
1170
1171        // Saving Main Window state
[7bb19df196]1172#ifndef HANDHELD
[9eb63a1598]1173        if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
1174            settings->beginGroup("MainWindow");
1175            settings->setValue("Geometry", saveGeometry());
1176            settings->setValue("State", saveState());
1177            settings->setValue("Toolbars", toolBarManager->saveState());
1178            settings->endGroup();
1179        }
[a713b103e8]1180#else
[9eb63a1598]1181        settings->setValue("MainWindow/ToolbarVisible", toolBarMain->isVisible());
[7bb19df196]1182#endif // HANDHELD
[9eb63a1598]1183    } else {
1184        settings->remove("SettingsReset");
1185    }
[1babbd6ba3]1186
[9eb63a1598]1187    QMainWindow::closeEvent(ev);
[1babbd6ba3]1188}
1189
[b574c383b7]1190void MainWindow::dragEnterEvent(QDragEnterEvent *ev)
1191{
[9eb63a1598]1192    if (ev->mimeData()->hasUrls() && (ev->mimeData()->urls().count() == 1)) {
[b574c383b7]1193QFileInfo fi(ev->mimeData()->urls().first().toLocalFile());
[9eb63a1598]1194        if ((fi.suffix() == "tspt") || (fi.suffix() == "zkt"))
1195            ev->acceptProposedAction();
1196    }
[b574c383b7]1197}
1198
[345e7b6132]1199void MainWindow::drawNode(QPainter &pic, int nstep, bool left, SStep *step)
1200{
[8f2427aaf0]1201qreal r; // Radius of graph node
1202    // We calculate r from the full graph width in centimeters:
1203    //   r = width in pixels / 4.5.
1204    //   width in pixels = DPI * width in inches.
1205    //   width in inches = width in cm / cm in inch.
1206    r = logicalDpiX() * (settings->value("Output/GraphWidth", DEF_GRAPH_WIDTH).toReal() / CM_IN_INCH) / 4.5;
[9eb63a1598]1207    if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool())
[8f2427aaf0]1208        r *= HQ_FACTOR;
[23ad8db4a5]1209#ifdef Q_WS_S60
[144fbe6b96]1210    /*! \hack HACK: Solution graph on Symbian is visually larger than on
[23ad8db4a5]1211     *   Windows Mobile. This coefficient makes it about the same size.
1212     */
1213    r /= 1.3;
1214#endif
1215
[345e7b6132]1216qreal x, y;
[9eb63a1598]1217    if (step != NULL)
1218        x = left ? r : r * 3.5;
1219    else
1220        x = r * 2.25;
1221    y = r * (3 * nstep + 1);
[345e7b6132]1222
[3cadf24d00]1223#ifdef _T_T_L_
[9eb63a1598]1224    if (nstep == -481124) {
1225        _t_t_l_(pic, r, x);
1226        return;
1227    }
[3cadf24d00]1228#endif
1229
[9eb63a1598]1230    pic.drawEllipse(QPointF(x, y), r, r);
[345e7b6132]1231
[9eb63a1598]1232    if (step != NULL) {
[345e7b6132]1233QFont font;
[9eb63a1598]1234        if (left) {
1235            font = pic.font();
1236            font.setStrikeOut(true);
1237            pic.setFont(font);
1238        }
1239        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");
1240        if (left) {
1241            font.setStrikeOut(false);
1242            pic.setFont(font);
1243        }
1244        if (step->price != INFINITY) {
[5cbcd091ed]1245            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]1246        } else {
1247            pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, "\n"INFSTR);
1248        }
1249    } else {
1250        pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, tr("Root"));
1251    }
1252
1253    if (nstep == 1) {
1254        pic.drawLine(QPointF(x, y - r), QPointF(r * 2.25, y - 2 * r));
1255    } else if (nstep > 1) {
1256        pic.drawLine(QPointF(x, y - r), QPointF((step->pNode->pNode->next == SStep::RightBranch) ? r * 3.5 : r, y - 2 * r));
1257    }
[345e7b6132]1258
1259}
1260
[b574c383b7]1261void MainWindow::dropEvent(QDropEvent *ev)
1262{
[9eb63a1598]1263    if (maybeSave() && tspmodel->loadTask(ev->mimeData()->urls().first().toLocalFile())) {
1264        setFileName(ev->mimeData()->urls().first().toLocalFile());
1265        tabWidget->setCurrentIndex(0);
1266        setWindowModified(false);
1267        solutionText->clear();
1268        toggleSolutionActions(false);
1269
1270        ev->setDropAction(Qt::CopyAction);
1271        ev->accept();
1272    }
[b574c383b7]1273}
1274
[1babbd6ba3]1275void MainWindow::initDocStyleSheet()
1276{
[9eb63a1598]1277    solutionText->document()->setDefaultFont(qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE, DEF_FONT_SIZE))));
[317ba0432e]1278
[a885c3d9d2]1279    fmt_paragraph.setTopMargin(5);
[9eb63a1598]1280    fmt_paragraph.setRightMargin(10);
1281    fmt_paragraph.setBottomMargin(0);
1282    fmt_paragraph.setLeftMargin(10);
[8f2427aaf0]1283
1284    fmt_lastparagraph.setTopMargin(5);
1285    fmt_lastparagraph.setRightMargin(10);
1286    fmt_lastparagraph.setBottomMargin(15);
1287    fmt_lastparagraph.setLeftMargin(10);
[317ba0432e]1288
[0a4e16b182]1289    settings->beginGroup("Output/Colors");
1290
[9eb63a1598]1291    fmt_table.setTopMargin(5);
1292    fmt_table.setRightMargin(10);
[a885c3d9d2]1293    fmt_table.setBottomMargin(0);
[9eb63a1598]1294    fmt_table.setLeftMargin(10);
[0a4e16b182]1295    fmt_table.setBorder(1);
1296    fmt_table.setBorderBrush(QBrush(QColor(settings->value("TableBorder", DEF_TABLE_COLOR).toString())));
1297    fmt_table.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
1298    fmt_table.setCellSpacing(0);
1299    fmt_table.setCellPadding(2);
[317ba0432e]1300
[9eb63a1598]1301    fmt_cell.setAlignment(Qt::AlignHCenter);
[317ba0432e]1302
[0a4e16b182]1303QColor color = QColor(settings->value("Text", DEF_TEXT_COLOR).toString());
[1babbd6ba3]1304QColor hilight;
[9eb63a1598]1305    if (color.value() < 192)
1306        hilight.setHsv(color.hue(), color.saturation(), 127 + qRound(color.value() / 2));
1307    else
1308        hilight.setHsv(color.hue(), color.saturation(), color.value() / 2);
[317ba0432e]1309
[9eb63a1598]1310    solutionText->document()->setDefaultStyleSheet(QString("* {color: %1;}").arg(color.name()));
1311    fmt_default.setForeground(QBrush(color));
[317ba0432e]1312
[0a4e16b182]1313    fmt_selected.setForeground(QBrush(QColor(settings->value("Selected", DEF_SELECTED_COLOR).toString())));
[9eb63a1598]1314    fmt_selected.setFontWeight(QFont::Bold);
[317ba0432e]1315
[0a4e16b182]1316    fmt_alternate.setForeground(QBrush(QColor(settings->value("Alternate", DEF_ALTERNATE_COLOR).toString())));
[9eb63a1598]1317    fmt_alternate.setFontWeight(QFont::Bold);
1318    fmt_altlist.setForeground(QBrush(hilight));
[317ba0432e]1319
[9eb63a1598]1320    settings->endGroup();
[8b0661d1ee]1321
[9eb63a1598]1322    solutionText->setTextColor(color);
[1babbd6ba3]1323}
1324
1325void MainWindow::loadLangList()
1326{
[3cadf24d00]1327QMap<QString, QStringList> langlist;
1328QFileInfoList langs;
1329QFileInfo lang;
1330QStringList language, dirs;
1331QTranslator t;
1332QDir dir;
[9eb63a1598]1333    dir.setFilter(QDir::Files);
1334    dir.setNameFilters(QStringList("tspsg_*.qm"));
1335    dir.setSorting(QDir::NoSort);
1336
1337    dirs << PATH_L10N << ":/l10n";
1338    foreach (QString dirname, dirs) {
1339        dir.setPath(dirname);
1340        if (dir.exists()) {
1341            langs = dir.entryInfoList();
1342            for (int k = 0; k < langs.size(); k++) {
1343                lang = langs.at(k);
1344                if (lang.completeBaseName().compare("tspsg_en", Qt::CaseInsensitive) && !langlist.contains(lang.completeBaseName().mid(6)) && t.load(lang.completeBaseName(), dirname)) {
1345
1346                    language.clear();
1347                    language.append(lang.completeBaseName().mid(6));
1348                    language.append(t.translate("--------", "COUNTRY", "Please, provide an ISO 3166-1 alpha-2 country code for this translation language here (eg., UA).").toLower());
1349                    language.append(t.translate("--------", "LANGNAME", "Please, provide a native name of your translation language here."));
1350                    language.append(t.translate("MainWindow", "Set application language to %1", "").arg(language.at(2)));
1351
1352                    langlist.insert(language.at(0), language);
1353                }
1354            }
1355        }
1356    }
[3cadf24d00]1357
1358QAction *a;
[9eb63a1598]1359    foreach (language, langlist) {
1360        a = menuSettingsLanguage->addAction(language.at(2));
[9adbc413c7]1361#ifndef QT_NO_STATUSTIP
[9eb63a1598]1362        a->setStatusTip(language.at(3));
[9adbc413c7]1363#endif
[2a436ea693]1364#if QT_VERSION >= 0x040600
[9eb63a1598]1365        a->setIcon(QIcon::fromTheme(QString("flag-%1").arg(language.at(1)), QIcon(QString(":/images/icons/l10n/flag-%1.png").arg(language.at(1)))));
[2a436ea693]1366#else
[9eb63a1598]1367        a->setIcon(QIcon(QString(":/images/icons/l10n/flag-%1.png").arg(language.at(1))));
[2a436ea693]1368#endif
[9eb63a1598]1369        a->setData(language.at(0));
1370        a->setCheckable(true);
1371        a->setActionGroup(groupSettingsLanguageList);
1372        if (settings->value("Language", QLocale::system().name()).toString().startsWith(language.at(0)))
1373            a->setChecked(true);
1374    }
[1babbd6ba3]1375}
1376
1377bool MainWindow::loadLanguage(const QString &lang)
1378{
1379// i18n
1380bool ad = false;
1381QString lng = lang;
[9eb63a1598]1382    if (lng.isEmpty()) {
1383        ad = settings->value("Language").toString().isEmpty();
1384        lng = settings->value("Language", QLocale::system().name()).toString();
1385    }
[1babbd6ba3]1386static QTranslator *qtTranslator; // Qt library translator
[9eb63a1598]1387    if (qtTranslator) {
1388        qApp->removeTranslator(qtTranslator);
1389        delete qtTranslator;
1390        qtTranslator = NULL;
1391    }
[1babbd6ba3]1392static QTranslator *translator; // Application translator
[9eb63a1598]1393    if (translator) {
1394        qApp->removeTranslator(translator);
1395        delete translator;
1396        translator = NULL;
1397    }
1398
1399    if (lng == "en")
1400        return true;
1401
1402    // Trying to load system Qt library translation...
1403    qtTranslator = new QTranslator(this);
1404    if (qtTranslator->load("qt_" + lng, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
1405        qApp->installTranslator(qtTranslator);
1406    else {
1407        // No luck. Let's try to load a bundled one.
1408        if (qtTranslator->load("qt_" + lng, PATH_L10N)) {
1409            // We have a translation in the localization direcotry.
1410            qApp->installTranslator(qtTranslator);
1411        } else if (qtTranslator->load("qt_" + lng, ":/l10n")) {
1412            // We have a translation "built-in" into application resources.
1413            qApp->installTranslator(qtTranslator);
1414        } else {
1415            // Qt library translation unavailable for this language.
1416            delete qtTranslator;
1417            qtTranslator = NULL;
1418        }
1419    }
1420
1421    // Now let's load application translation.
1422    translator = new QTranslator(this);
1423    if (translator->load("tspsg_" + lng, PATH_L10N)) {
1424        // We have a translation in the localization directory.
1425        qApp->installTranslator(translator);
1426    } else if (translator->load("tspsg_" + lng, ":/l10n")) {
1427        // We have a translation "built-in" into application resources.
1428        qApp->installTranslator(translator);
1429    } else {
1430        delete translator;
1431        translator = NULL;
1432        if (!ad) {
1433            settings->remove("Language");
1434            QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
1435            QMessageBox::warning(isVisible() ? this : NULL, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection."));
1436            QApplication::restoreOverrideCursor();
1437        }
1438        return false;
1439    }
1440    return true;
[1babbd6ba3]1441}
1442
[e3533af1cf]1443void MainWindow::loadStyleList()
1444{
[9eb63a1598]1445    menuSettingsStyle->clear();
[e3533af1cf]1446QStringList styles = QStyleFactory::keys();
[9eb63a1598]1447    menuSettingsStyle->insertAction(NULL, actionSettingsStyleSystem);
1448    actionSettingsStyleSystem->setChecked(!settings->contains("Style"));
1449    menuSettingsStyle->addSeparator();
[e3533af1cf]1450QAction *a;
[9eb63a1598]1451    foreach (QString style, styles) {
1452        a = menuSettingsStyle->addAction(style);
1453        a->setData(false);
[9adbc413c7]1454#ifndef QT_NO_STATUSTIP
[9eb63a1598]1455        a->setStatusTip(tr("Set application style to %1").arg(style));
[9adbc413c7]1456#endif
[9eb63a1598]1457        a->setCheckable(true);
1458        a->setActionGroup(groupSettingsStyleList);
1459        if ((style == settings->value("Stlye").toString())
[97e90f9be6]1460#ifndef Q_WS_MAEMO_5
[9eb63a1598]1461            || QString(QApplication::style()->metaObject()->className()).contains(QRegExp(QString("^Q?%1(Style)?$").arg(QRegExp::escape(style)), Qt::CaseInsensitive))
[97e90f9be6]1462#endif
[9eb63a1598]1463        ) {
1464            a->setChecked(true);
1465        }
1466    }
[e3533af1cf]1467}
1468
[7bb19df196]1469void MainWindow::loadToolbarList()
1470{
[9eb63a1598]1471    menuSettingsToolbars->clear();
[7bb19df196]1472#ifndef HANDHELD
[9eb63a1598]1473    menuSettingsToolbars->insertAction(NULL, actionSettingsToolbarsConfigure);
1474    menuSettingsToolbars->addSeparator();
[7bb19df196]1475QList<QToolBar *> list = toolBarManager->toolBars();
[9eb63a1598]1476    foreach (QToolBar *t, list) {
1477        menuSettingsToolbars->insertAction(NULL, t->toggleViewAction());
1478    }
[7bb19df196]1479#else // HANDHELD
[9eb63a1598]1480    menuSettingsToolbars->insertAction(NULL, toolBarMain->toggleViewAction());
[7bb19df196]1481#endif // HANDHELD
1482}
1483
[1babbd6ba3]1484bool MainWindow::maybeSave()
1485{
[9eb63a1598]1486    if (!isWindowModified())
1487        return true;
[fddcfa4b55]1488#ifdef Q_WS_S60
1489    int res = QSMessageBox(this).exec();
1490#else
1491    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);
1492#endif
[9eb63a1598]1493    if (res == QMessageBox::Save)
1494        return actionFileSaveTriggered();
1495    else if (res == QMessageBox::Cancel)
1496        return false;
1497    else
1498        return true;
[1babbd6ba3]1499}
1500
[317ba0432e]1501void MainWindow::outputMatrix(QTextCursor &cur, const TMatrix &matrix)
[1babbd6ba3]1502{
1503int n = spinCities->value();
[317ba0432e]1504QTextTable *table = cur.insertTable(n, n, fmt_table);
1505
[9eb63a1598]1506    for (int r = 0; r < n; r++) {
1507        for (int c = 0; c < n; c++) {
1508            cur = table->cellAt(r, c).firstCursorPosition();
1509            cur.setBlockFormat(fmt_cell);
1510            cur.setBlockCharFormat(fmt_default);
1511            if (matrix.at(r).at(c) == INFINITY)
1512                cur.insertText(INFSTR);
1513            else
1514                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()));
1515        }
1516        QCoreApplication::processEvents();
1517    }
1518    cur.movePosition(QTextCursor::End);
[1babbd6ba3]1519}
1520
[317ba0432e]1521void MainWindow::outputMatrix(QTextCursor &cur, const SStep &step)
[1babbd6ba3]1522{
1523int n = spinCities->value();
[317ba0432e]1524QTextTable *table = cur.insertTable(n, n, fmt_table);
1525
[9eb63a1598]1526    for (int r = 0; r < n; r++) {
1527        for (int c = 0; c < n; c++) {
1528            cur = table->cellAt(r, c).firstCursorPosition();
1529            cur.setBlockFormat(fmt_cell);
1530            if (step.matrix.at(r).at(c) == INFINITY)
1531                cur.insertText(INFSTR, fmt_default);
1532            else if ((r == step.candidate.nRow) && (c == step.candidate.nCol))
1533                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);
1534            else {
[9cda6e0f5d]1535SStep::SCandidate cand;
[9eb63a1598]1536                cand.nRow = r;
1537                cand.nCol = c;
1538                if (step.alts.contains(cand))
1539                    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);
1540                else
1541                    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);
1542            }
1543        }
1544        QCoreApplication::processEvents();
1545    }
1546
1547    cur.movePosition(QTextCursor::End);
[1babbd6ba3]1548}
1549
[1b40fef578]1550#ifdef Q_WS_S60
1551void MainWindow::resizeEvent(QResizeEvent *ev)
1552{
1553    static bool tb = toolBarMain->isVisible();
1554    if ((ev->size().width() < ev->size().height())
1555            && (ev->oldSize().width() > ev->oldSize().height())) {
1556        // From landscape to portrait
1557        if (tb)
1558            toolBarMain->show();
1559        setWindowState(Qt::WindowMaximized);
1560    } else if ((ev->size().width() > ev->size().height())
1561               && (ev->oldSize().width() < ev->oldSize().height())) {
1562        // From portrait to landscape
1563        if (tb = toolBarMain->isVisible())
1564            toolBarMain->hide();
1565        setWindowState(Qt::WindowFullScreen);
1566    }
1567
1568    QWidget::resizeEvent(ev);
1569}
1570#endif // Q_WS_S60
1571
[1babbd6ba3]1572void MainWindow::retranslateUi(bool all)
1573{
[9eb63a1598]1574    if (all)
1575        Ui_MainWindow::retranslateUi(this);
[1babbd6ba3]1576
[9eb63a1598]1577    loadStyleList();
1578    loadToolbarList();
[e3533af1cf]1579
[1babbd6ba3]1580#ifndef QT_NO_PRINTER
[9eb63a1598]1581    actionFilePrintPreview->setText(tr("P&rint Preview..."));
[1babbd6ba3]1582#ifndef QT_NO_TOOLTIP
[9eb63a1598]1583    actionFilePrintPreview->setToolTip(tr("Preview solution results"));
[1babbd6ba3]1584#endif // QT_NO_TOOLTIP
1585#ifndef QT_NO_STATUSTIP
[9eb63a1598]1586    actionFilePrintPreview->setStatusTip(tr("Preview current solution results before printing"));
[20e8115cee]1587#endif // QT_NO_STATUSTIP
1588
1589    actionFilePageSetup->setText(tr("Pa&ge Setup..."));
1590#ifndef QT_NO_TOOLTIP
1591    actionFilePageSetup->setToolTip(tr("Setup print options"));
1592#endif // QT_NO_TOOLTIP
1593#ifndef QT_NO_STATUSTIP
1594    actionFilePageSetup->setStatusTip(tr("Setup page-related options for printing"));
[88a59e4d65]1595#endif // QT_NO_STATUSTIP
[1babbd6ba3]1596
[9eb63a1598]1597    actionFilePrint->setText(tr("&Print..."));
[1babbd6ba3]1598#ifndef QT_NO_TOOLTIP
[9eb63a1598]1599    actionFilePrint->setToolTip(tr("Print solution"));
[1babbd6ba3]1600#endif // QT_NO_TOOLTIP
1601#ifndef QT_NO_STATUSTIP
[9eb63a1598]1602    actionFilePrint->setStatusTip(tr("Print current solution results"));
[1babbd6ba3]1603#endif // QT_NO_STATUSTIP
[9eb63a1598]1604    actionFilePrint->setShortcut(tr("Ctrl+P"));
[1babbd6ba3]1605#endif // QT_NO_PRINTER
[8b0661d1ee]1606
[20e8115cee]1607#ifndef QT_NO_STATUSTIP
1608    actionFileExit->setStatusTip(tr("Exit %1").arg(QCoreApplication::applicationName()));
1609#endif // QT_NO_STATUSTIP
1610
[8b0661d1ee]1611#ifndef HANDHELD
[9eb63a1598]1612    actionSettingsToolbarsConfigure->setText(tr("Configure..."));
[8b0661d1ee]1613#ifndef QT_NO_STATUSTIP
[9eb63a1598]1614    actionSettingsToolbarsConfigure->setStatusTip(tr("Customize toolbars"));
[8b0661d1ee]1615#endif // QT_NO_STATUSTIP
1616#endif // HANDHELD
1617
[88a59e4d65]1618#ifndef QT_NO_STATUSTIP
[9eb63a1598]1619    actionHelpReportBug->setStatusTip(tr("Report about a bug in %1").arg(QCoreApplication::applicationName()));
[88a59e4d65]1620#endif // QT_NO_STATUSTIP
[9eb63a1598]1621    if (actionHelpCheck4Updates != NULL) {
1622        actionHelpCheck4Updates->setText(tr("Check for &Updates..."));
[1babbd6ba3]1623#ifndef QT_NO_STATUSTIP
[9eb63a1598]1624        actionHelpCheck4Updates->setStatusTip(tr("Check for %1 updates").arg(QCoreApplication::applicationName()));
[1babbd6ba3]1625#endif // QT_NO_STATUSTIP
[9eb63a1598]1626    }
[88a59e4d65]1627#ifndef QT_NO_STATUSTIP
[9eb63a1598]1628    actionHelpAbout->setStatusTip(tr("About %1").arg(QCoreApplication::applicationName()));
[88a59e4d65]1629#endif // QT_NO_STATUSTIP
[23ad8db4a5]1630
1631#ifdef Q_WS_S60
1632    actionRightSoftKey->setText(tr("E&xit"));
1633#endif
[1babbd6ba3]1634}
1635
1636bool MainWindow::saveTask() {
1637QStringList filters(tr("%1 Task File").arg("TSPSG") + " (*.tspt)");
[9eb63a1598]1638    filters.append(tr("All Files") + " (*)");
[1babbd6ba3]1639QString file;
[9eb63a1598]1640    if ((fileName == tr("Untitled") + ".tspt") && settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) {
1641        file = settings->value(OS"/LastUsed/TaskSavePath").toString();
1642        if (!file.isEmpty())
1643            file.append("/");
1644        file.append(fileName);
1645    } else if (fileName.endsWith(".tspt", Qt::CaseInsensitive))
1646        file = fileName;
1647    else
1648        file = QFileInfo(fileName).path() + "/" + QFileInfo(fileName).completeBaseName() + ".tspt";
[1babbd6ba3]1649
1650QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
[9eb63a1598]1651    file = QFileDialog::getSaveFileName(this, tr("Task Save"), file, filters.join(";;"), NULL, opts);
1652    if (file.isEmpty())
1653        return false;
1654    else if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool())
1655        settings->setValue(OS"/LastUsed/TaskSavePath", QFileInfo(file).path());
[144fbe6b96]1656    if (QFileInfo(file).suffix().isEmpty()) {
1657        file.append(".tspt");
1658    }
[9eb63a1598]1659
1660    if (tspmodel->saveTask(file)) {
1661        setFileName(file);
1662        setWindowModified(false);
1663        return true;
1664    }
1665    return false;
[1babbd6ba3]1666}
1667
1668void MainWindow::setFileName(const QString &fileName)
1669{
[9eb63a1598]1670    this->fileName = fileName;
1671    setWindowTitle(QString("%1[*] - %2").arg(QFileInfo(fileName).completeBaseName()).arg(QCoreApplication::applicationName()));
[1babbd6ba3]1672}
1673
1674void MainWindow::setupUi()
1675{
[9eb63a1598]1676    Ui_MainWindow::setupUi(this);
[1babbd6ba3]1677
[1b40fef578]1678#ifdef Q_WS_S60
1679    setWindowFlags(windowFlags() | Qt::WindowSoftkeysVisibleHint);
1680#endif // Q_WS_S60
1681
[9eb63a1598]1682    // File Menu
1683    actionFileNew->setIcon(GET_ICON("document-new"));
1684    actionFileOpen->setIcon(GET_ICON("document-open"));
1685    actionFileSave->setIcon(GET_ICON("document-save"));
[a713b103e8]1686#ifndef HANDHELD
[9eb63a1598]1687    menuFileSaveAs->setIcon(GET_ICON("document-save-as"));
[a713b103e8]1688#endif
[9eb63a1598]1689    actionFileExit->setIcon(GET_ICON("application-exit"));
1690    // Settings Menu
[a713b103e8]1691#ifndef HANDHELD
[9eb63a1598]1692    menuSettingsLanguage->setIcon(GET_ICON("preferences-desktop-locale"));
[a713b103e8]1693#if QT_VERSION >= 0x040600
[9eb63a1598]1694    actionSettingsLanguageEnglish->setIcon(QIcon::fromTheme("flag-gb", QIcon(":/images/icons/l10n/flag-gb.png")));
[a713b103e8]1695#else // QT_VERSION >= 0x040600
[9eb63a1598]1696    actionSettingsLanguageEnglish->setIcon(QIcon(":/images/icons/l10n/flag-gb.png"));
[a713b103e8]1697#endif // QT_VERSION >= 0x040600
[9eb63a1598]1698    menuSettingsStyle->setIcon(GET_ICON("preferences-desktop-theme"));
[a713b103e8]1699#endif // HANDHELD
[9eb63a1598]1700    actionSettingsPreferences->setIcon(GET_ICON("preferences-system"));
1701    // Help Menu
[a713b103e8]1702#ifndef HANDHELD
[9eb63a1598]1703    actionHelpContents->setIcon(GET_ICON("help-contents"));
1704    actionHelpContextual->setIcon(GET_ICON("help-contextual"));
1705    actionHelpOnlineSupport->setIcon(GET_ICON("applications-internet"));
1706    actionHelpReportBug->setIcon(GET_ICON("tools-report-bug"));
1707    actionHelpAbout->setIcon(GET_ICON("help-about"));
[fddcfa4b55]1708    actionHelpAboutQt->setIcon(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"));
[a713b103e8]1709#endif
[9eb63a1598]1710    // Buttons
1711    buttonRandom->setIcon(GET_ICON("roll"));
1712    buttonSolve->setIcon(GET_ICON("dialog-ok"));
1713    buttonSaveSolution->setIcon(GET_ICON("document-save-as"));
1714    buttonBackToTask->setIcon(GET_ICON("go-previous"));
[3cadf24d00]1715
[2a436ea693]1716//      action->setIcon(GET_ICON(""));
[3cadf24d00]1717
[1babbd6ba3]1718#if QT_VERSION >= 0x040600
[9eb63a1598]1719    setToolButtonStyle(Qt::ToolButtonFollowStyle);
[1babbd6ba3]1720#endif
1721
1722#ifndef HANDHELD
1723QStatusBar *statusbar = new QStatusBar(this);
[9eb63a1598]1724    statusbar->setObjectName("statusbar");
1725    setStatusBar(statusbar);
[1babbd6ba3]1726#endif // HANDHELD
1727
[97e90f9be6]1728#ifdef Q_WS_WINCE_WM
[9eb63a1598]1729    menuBar()->setDefaultAction(menuFile->menuAction());
[1babbd6ba3]1730
1731QScrollArea *scrollArea = new QScrollArea(this);
[9eb63a1598]1732    scrollArea->setFrameShape(QFrame::NoFrame);
1733    scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1734    scrollArea->setWidgetResizable(true);
1735    scrollArea->setWidget(tabWidget);
1736    setCentralWidget(scrollArea);
[1babbd6ba3]1737#else
[9eb63a1598]1738    setCentralWidget(tabWidget);
[97e90f9be6]1739#endif // Q_WS_WINCE_WM
[1babbd6ba3]1740
[9eb63a1598]1741    //! \hack HACK: A little hack for toolbar icons to have a sane size.
[97e90f9be6]1742#if defined(HANDHELD) && !defined(Q_WS_MAEMO_5)
[5cbcd091ed]1743#ifdef Q_WS_S60
[23ad8db4a5]1744    toolBarMain->setIconSize(QSize(logicalDpiX() / 5.2, logicalDpiY() / 5.2));
[5cbcd091ed]1745#else
[9eb63a1598]1746    toolBarMain->setIconSize(QSize(logicalDpiX() / 4, logicalDpiY() / 4));
[5cbcd091ed]1747#endif // Q_WS_S60
1748#endif // HANDHELD && !Q_WS_MAEMO_5
[7bb19df196]1749QToolButton *tb = static_cast<QToolButton *>(toolBarMain->widgetForAction(actionFileSave));
[5cbcd091ed]1750    if (tb != NULL) {
[9eb63a1598]1751        tb->setMenu(menuFileSaveAs);
1752        tb->setPopupMode(QToolButton::MenuButtonPopup);
1753    }
[1babbd6ba3]1754
[8b0661d1ee]1755//      solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>());
[9eb63a1598]1756    solutionText->setWordWrapMode(QTextOption::WordWrap);
[1babbd6ba3]1757
1758#ifndef QT_NO_PRINTER
[9eb63a1598]1759    actionFilePrintPreview = new QAction(this);
1760    actionFilePrintPreview->setObjectName("actionFilePrintPreview");
1761    actionFilePrintPreview->setEnabled(false);
1762    actionFilePrintPreview->setIcon(GET_ICON("document-print-preview"));
[1babbd6ba3]1763
[20e8115cee]1764    actionFilePageSetup = new QAction(this);
1765    actionFilePageSetup->setObjectName("actionFilePrintSetup");
1766//    actionFilePageSetup->setEnabled(false);
1767#if QT_VERSION >= 0x040600
1768    actionFilePageSetup->setIcon(QIcon::fromTheme("document-page-setup", QIcon(":/trolltech/dialogs/qprintpreviewdialog/images/page-setup-32.png")));
1769#else
1770    actionFilePageSetup->setIcon(QIcon(":/trolltech/dialogs/qprintpreviewdialog/images/page-setup-32.png"));
1771#endif
1772
[9eb63a1598]1773    actionFilePrint = new QAction(this);
1774    actionFilePrint->setObjectName("actionFilePrint");
1775    actionFilePrint->setEnabled(false);
1776    actionFilePrint->setIcon(GET_ICON("document-print"));
[1babbd6ba3]1777
[20e8115cee]1778    menuFile->insertAction(actionFileExit, actionFilePrintPreview);
1779    menuFile->insertAction(actionFileExit, actionFilePageSetup);
1780    menuFile->insertAction(actionFileExit, actionFilePrint);
[9eb63a1598]1781    menuFile->insertSeparator(actionFileExit);
[1babbd6ba3]1782
[9eb63a1598]1783    toolBarMain->insertAction(actionSettingsPreferences, actionFilePrint);
[1babbd6ba3]1784#endif // QT_NO_PRINTER
[e51c78af27]1785
[9eb63a1598]1786    groupSettingsLanguageList = new QActionGroup(this);
[97e90f9be6]1787#ifdef Q_WS_MAEMO_5
[9eb63a1598]1788    groupSettingsLanguageList->addAction(actionSettingsLanguageAutodetect);
[97e90f9be6]1789#endif
[9eb63a1598]1790    actionSettingsLanguageEnglish->setData("en");
1791    actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
1792    loadLangList();
1793    actionSettingsLanguageAutodetect->setChecked(settings->value("Language", "").toString().isEmpty());
[e3533af1cf]1794
[9eb63a1598]1795    actionSettingsStyleSystem->setData(true);
1796    groupSettingsStyleList = new QActionGroup(this);
[97e90f9be6]1797#ifdef Q_WS_MAEMO_5
[9eb63a1598]1798    groupSettingsStyleList->addAction(actionSettingsStyleSystem);
[97e90f9be6]1799#endif
[e3533af1cf]1800
[7bb19df196]1801#ifndef HANDHELD
[9eb63a1598]1802    actionSettingsToolbarsConfigure = new QAction(this);
1803    actionSettingsToolbarsConfigure->setIcon(GET_ICON("configure-toolbars"));
[7bb19df196]1804#endif // HANDHELD
1805
[9eb63a1598]1806    if (hasUpdater()) {
1807        actionHelpCheck4Updates = new QAction(this);
1808        actionHelpCheck4Updates->setIcon(GET_ICON("system-software-update"));
1809        actionHelpCheck4Updates->setEnabled(hasUpdater());
1810        menuHelp->insertAction(actionHelpAboutQt, actionHelpCheck4Updates);
1811        menuHelp->insertSeparator(actionHelpAboutQt);
1812    } else
1813        actionHelpCheck4Updates = NULL;
[1babbd6ba3]1814
[9eb63a1598]1815    spinCities->setMaximum(MAX_NUM_CITIES);
[1babbd6ba3]1816
[94cd045fad]1817#ifndef HANDHELD
[20e8115cee]1818    toolBarManager = new QtToolBarManager(this);
[9eb63a1598]1819    toolBarManager->setMainWindow(this);
[7bb19df196]1820QString cat = toolBarMain->windowTitle();
[9eb63a1598]1821    toolBarManager->addToolBar(toolBarMain, cat);
[94cd045fad]1822#ifndef QT_NO_PRINTER
[9eb63a1598]1823    toolBarManager->addAction(actionFilePrintPreview, cat);
[20e8115cee]1824    toolBarManager->addAction(actionFilePageSetup, cat);
[94cd045fad]1825#endif // QT_NO_PRINTER
[9eb63a1598]1826    toolBarManager->addAction(actionHelpContents, cat);
1827    toolBarManager->addAction(actionHelpContextual, cat);
1828    toolBarManager->restoreState(settings->value("MainWindow/Toolbars").toByteArray());
[a713b103e8]1829#else
[9eb63a1598]1830    toolBarMain->setVisible(settings->value("MainWindow/ToolbarVisible", true).toBool());
[94cd045fad]1831#endif // HANDHELD
[7bb19df196]1832
[23ad8db4a5]1833#ifdef Q_WS_S60
1834    // Replace Exit on the right soft key with our own exit action.
1835    // This makes it translatable.
1836    actionRightSoftKey = new QAction(this);
1837    actionRightSoftKey->setSoftKeyRole(QAction::NegativeSoftKey);
1838    connect(actionRightSoftKey, SIGNAL(triggered()), SLOT(close()));
1839    addAction(actionRightSoftKey);
1840#endif
1841
[9eb63a1598]1842    retranslateUi(false);
[7bb19df196]1843
[b8a2a118c4]1844#ifndef HANDHELD
1845    // Adding some eyecandy
[9eb63a1598]1846    if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
1847        toggleTranclucency(true);
1848    }
[b8a2a118c4]1849#endif // HANDHELD
[1babbd6ba3]1850}
1851
1852void MainWindow::toggleSolutionActions(bool enable)
1853{
[9eb63a1598]1854    buttonSaveSolution->setEnabled(enable);
1855    actionFileSaveAsSolution->setEnabled(enable);
1856    solutionText->setEnabled(enable);
[1babbd6ba3]1857#ifndef QT_NO_PRINTER
[9eb63a1598]1858    actionFilePrint->setEnabled(enable);
1859    actionFilePrintPreview->setEnabled(enable);
[1babbd6ba3]1860#endif // QT_NO_PRINTER
1861}
1862
1863void MainWindow::toggleTranclucency(bool enable)
1864{
[b8a2a118c4]1865#ifndef HANDHELD
[9eb63a1598]1866    toggleStyle(labelVariant, enable);
1867    toggleStyle(labelCities, enable);
1868    toggleStyle(statusBar(), enable);
1869    tabWidget->setDocumentMode(enable);
1870    QtWin::enableBlurBehindWindow(this, enable);
[1babbd6ba3]1871#else
[9eb63a1598]1872    Q_UNUSED(enable);
[b8a2a118c4]1873#endif // HANDHELD
[1babbd6ba3]1874}
[88a59e4d65]1875
1876void MainWindow::actionHelpOnlineSupportTriggered()
1877{
[9eb63a1598]1878    QDesktopServices::openUrl(QUrl("http://tspsg.info/goto/support"));
[88a59e4d65]1879}
1880
1881void MainWindow::actionHelpReportBugTriggered()
1882{
[9eb63a1598]1883    QDesktopServices::openUrl(QUrl("http://tspsg.info/goto/bugtracker"));
[88a59e4d65]1884}
[fddcfa4b55]1885
1886#ifdef Q_WS_S60
1887QSMessageBox::QSMessageBox(QWidget *parent)
1888    : QMessageBox(parent)
1889{
1890    setIcon(QMessageBox::Warning);
1891    setWindowTitle(QApplication::translate("MainWindow", "Unsaved Changes"));
1892    setText(QApplication::translate("MainWindow", "Would you like to save changes in the current task?"));
1893    setStandardButtons(QMessageBox::Save);
1894
1895    QMenu *m = new QMenu(this);
[019894f5ef]1896    m->addAction(QApplication::translate("QDialogButtonBox", "Discard", "No need to translate this. The translation will be taken from Qt translation files."),
[fddcfa4b55]1897                 this, SLOT(discard()));
[019894f5ef]1898    m->addAction(QApplication::translate("QDialogButtonBox", "Cancel", "No need to translate this. The translation will be taken from Qt translation files."),
[fddcfa4b55]1899                 this, SLOT(cancel()));
1900
[019894f5ef]1901    QAction *o = new QAction(QApplication::translate("QtToolBarDialog", "Actions"), this);
[fddcfa4b55]1902    o->setSoftKeyRole(QAction::NegativeSoftKey);
1903    o->setMenu(m);
1904    addAction(o);
1905}
1906
1907void QSMessageBox::cancel(){
1908    done(QMessageBox::Cancel);
1909}
1910
1911void QSMessageBox::discard() {
1912    done(QMessageBox::Discard);
1913}
1914#endif // Q_WS_S60
Note: See TracBrowser for help on using the repository browser.