source: tspsg/src/mainwindow.cpp @ 5631fb4d50

0.1.4.170-beta2-bb10appveyorimgbotreadme
Last change on this file since 5631fb4d50 was 5cbcd091ed, checked in by Oleksii Serdiuk, 13 years ago

Fixes and updates to Symbian SIS package generation rules and some small Symbian-related code fixes.

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