source: tspsg/src/mainwindow.cpp @ aa64ad4082

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

Added proxy style and stylesheet to fix some UI issues on BlackBerry?.

Also, removed style selection option because most styles have UI issues
and removed About Qt menu item because About Qt dialog is too big.

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