source: tspsg-svn/trunk/src/mainwindow.cpp @ 133

Last change on this file since 133 was 133, checked in by laleppa, 14 years ago

Save platform dependent settings (e.g., paths) per platform. This enables sharing of the settings file.

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