source: tspsg/src/mainwindow.cpp @ b8a2a118c4

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