source: tspsg/src/mainwindow.cpp @ 50b614b0ea

appveyorimgbotreadme
Last change on this file since 50b614b0ea was c8ed26ddf1, checked in by Oleksii Serdiuk, 12 years ago

Implemented color selection from Settings Dialog.

Changing background color appeared to be much harder than expected, so
this feature was removed for now. It is possible to change background
color of the solution output area. However, this background change
doesn't affect printing and export - there background color always stays
white. Will investigate possible workarounds later...

Closes ticket:13 - All colors should be configurable through Settings Dialog

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