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

Last change on this file since 104 was 104, checked in by laleppa, 14 years ago
  • Improved the solution output generation algorithm. Now it works directly with QTextDocument instead of "feeding" it with HTML. Thanks to this the solution output generation is now about 1.65 times faster.
  • Added .txt extension to ChangeLog?, INSTALL and README files to simplify opening these files in Windows.
  • Made a small improvement to Settings Dialog to follow the current application palette.
  • Output text color if not set is now determmined based on the current application palette.
  • Property svn:keywords set to Id URL
File size: 38.5 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 104 2010-04-19 20:33:02Z 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/*!
27 * \brief Class constructor.
28 * \param parent Main Window parent widget.
29 *
30 *  Initializes Main Window and creates its layout based on target OS.
31 *  Loads TSPSG settings and opens a task file if it was specified as a commandline parameter.
32 */
33MainWindow::MainWindow(QWidget *parent)
34        : QMainWindow(parent)
35{
36        settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this);
37
38        loadLanguage();
39        setupUi();
40
41        initDocStyleSheet();
42
43#ifndef QT_NO_PRINTER
44        printer = new QPrinter(QPrinter::HighResolution);
45#endif // QT_NO_PRINTER
46
47#ifdef Q_OS_WINCE_WM
48        currentGeometry = QApplication::desktop()->availableGeometry(0);
49        // We need to react to SIP show/hide and resize the window appropriately
50        connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), SLOT(desktopResized(int)));
51#endif // Q_OS_WINCE_WM
52        connect(actionFileNew,SIGNAL(triggered()),this,SLOT(actionFileNewTriggered()));
53        connect(actionFileOpen,SIGNAL(triggered()),this,SLOT(actionFileOpenTriggered()));
54        connect(actionFileSave,SIGNAL(triggered()),this,SLOT(actionFileSaveTriggered()));
55        connect(actionFileSaveAsTask,SIGNAL(triggered()),this,SLOT(actionFileSaveAsTaskTriggered()));
56        connect(actionFileSaveAsSolution,SIGNAL(triggered()),this,SLOT(actionFileSaveAsSolutionTriggered()));
57#ifndef QT_NO_PRINTER
58        connect(actionFilePrintPreview,SIGNAL(triggered()),this,SLOT(actionFilePrintPreviewTriggered()));
59        connect(actionFilePrint,SIGNAL(triggered()),this,SLOT(actionFilePrintTriggered()));
60#endif // QT_NO_PRINTER
61        connect(actionSettingsPreferences,SIGNAL(triggered()),this,SLOT(actionSettingsPreferencesTriggered()));
62#ifdef Q_OS_WIN32
63        connect(actionHelpCheck4Updates, SIGNAL(triggered()), SLOT(actionHelpCheck4UpdatesTriggered()));
64#endif // Q_OS_WIN32
65        connect(actionSettingsLanguageAutodetect,SIGNAL(triggered(bool)),this,SLOT(actionSettingsLanguageAutodetectTriggered(bool)));
66        connect(groupSettingsLanguageList,SIGNAL(triggered(QAction *)),this,SLOT(groupSettingsLanguageListTriggered(QAction *)));
67        connect(actionHelpAboutQt,SIGNAL(triggered()),qApp,SLOT(aboutQt()));
68        connect(actionHelpAbout,SIGNAL(triggered()),this,SLOT(actionHelpAboutTriggered()));
69
70        connect(buttonSolve,SIGNAL(clicked()),this,SLOT(buttonSolveClicked()));
71        connect(buttonRandom,SIGNAL(clicked()),this,SLOT(buttonRandomClicked()));
72        connect(buttonBackToTask,SIGNAL(clicked()),this,SLOT(buttonBackToTaskClicked()));
73        connect(spinCities,SIGNAL(valueChanged(int)),this,SLOT(spinCitiesValueChanged(int)));
74
75#ifndef HANDHELD
76        // Centering main window
77QRect rect = geometry();
78        rect.moveCenter(QApplication::desktop()->availableGeometry(this).center());
79        setGeometry(rect);
80        if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
81                // Loading of saved window state
82                settings->beginGroup("MainWindow");
83                restoreGeometry(settings->value("Geometry").toByteArray());
84                restoreState(settings->value("State").toByteArray());
85                settings->endGroup();
86        }
87#else
88        setWindowState(Qt::WindowMaximized);
89#endif // HANDHELD
90
91        tspmodel = new CTSPModel(this);
92        taskView->setModel(tspmodel);
93        connect(tspmodel,SIGNAL(numCitiesChanged(int)),this,SLOT(numCitiesChanged(int)));
94        connect(tspmodel,SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
95        connect(tspmodel,SIGNAL(layoutChanged()),this,SLOT(dataChanged()));
96        if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1))))
97                setFileName(QCoreApplication::arguments().at(1));
98        else {
99                setFileName();
100                spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt());
101                spinCitiesValueChanged(spinCities->value());
102        }
103        setWindowModified(false);
104}
105
106MainWindow::~MainWindow()
107{
108#ifndef QT_NO_PRINTER
109        delete printer;
110#endif
111}
112
113/* Privates **********************************************************/
114
115void MainWindow::actionFileNewTriggered()
116{
117        if (!maybeSave())
118                return;
119        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
120        tspmodel->clear();
121        setFileName();
122        setWindowModified(false);
123        tabWidget->setCurrentIndex(0);
124        solutionText->clear();
125        toggleSolutionActions(false);
126        QApplication::restoreOverrideCursor();
127}
128
129void MainWindow::actionFileOpenTriggered()
130{
131        if (!maybeSave())
132                return;
133
134QStringList filters(tr("All Supported Formats") + " (*.tspt *.zkt)");
135        filters.append(tr("%1 Task Files").arg("TSPSG") + " (*.tspt)");
136        filters.append(tr("%1 Task Files").arg("ZKomModRd") + " (*.zkt)");
137        filters.append(tr("All Files") + " (*)");
138
139QString file = QFileInfo(fileName).canonicalPath();
140QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
141        file = QFileDialog::getOpenFileName(this, tr("Task Load"), file, filters.join(";;"), NULL, opts);
142        if (file.isEmpty() || !QFileInfo(file).isFile())
143                return;
144        if (!tspmodel->loadTask(file))
145                return;
146        setFileName(file);
147        tabWidget->setCurrentIndex(0);
148        setWindowModified(false);
149        solutionText->clear();
150        toggleSolutionActions(false);
151}
152
153bool MainWindow::actionFileSaveTriggered()
154{
155        if ((fileName == tr("Untitled") + ".tspt") || (!fileName.endsWith(".tspt", Qt::CaseInsensitive)))
156                return saveTask();
157        else
158                if (tspmodel->saveTask(fileName)) {
159                        setWindowModified(false);
160                        return true;
161                } else
162                        return false;
163}
164
165void MainWindow::actionFileSaveAsTaskTriggered()
166{
167        saveTask();
168}
169
170void MainWindow::actionFileSaveAsSolutionTriggered()
171{
172static QString selectedFile;
173        if (selectedFile.isEmpty())
174                selectedFile = QFileInfo(fileName).canonicalPath();
175        else
176                selectedFile = QFileInfo(selectedFile).canonicalPath();
177        if (!selectedFile.isEmpty())
178                selectedFile += "/";
179        if (fileName == tr("Untitled") + ".tspt") {
180#ifndef QT_NO_PRINTER
181                selectedFile += "solution.pdf";
182#else
183                selectedFile += "solution.html";
184#endif // QT_NO_PRINTER
185        } else {
186#ifndef QT_NO_PRINTER
187                selectedFile += QFileInfo(fileName).completeBaseName() + ".pdf";
188#else
189                selectedFile += QFileInfo(fileName).completeBaseName() + ".html";
190#endif // QT_NO_PRINTER
191        }
192
193QStringList filters;
194#ifndef QT_NO_PRINTER
195        filters.append(tr("PDF Files") + " (*.pdf)");
196#endif
197        filters.append(tr("HTML Files") + " (*.html *.htm)");
198#if QT_VERSION >= 0x040500
199        filters.append(tr("OpenDocument Files") + " (*.odt)");
200#endif // QT_VERSION >= 0x040500
201        filters.append(tr("All Files") + " (*)");
202
203QFileDialog::Options opts(settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog);
204QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"), NULL, opts);
205        if (file.isEmpty())
206                return;
207        selectedFile = file;
208        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
209#ifndef QT_NO_PRINTER
210        if (selectedFile.endsWith(".pdf",Qt::CaseInsensitive)) {
211QPrinter printer(QPrinter::HighResolution);
212                printer.setOutputFormat(QPrinter::PdfFormat);
213                printer.setOutputFileName(selectedFile);
214                solutionText->document()->print(&printer);
215                QApplication::restoreOverrideCursor();
216                return;
217        }
218#endif
219#if QT_VERSION >= 0x040500
220QTextDocumentWriter dw(selectedFile);
221        if (!(selectedFile.endsWith(".htm",Qt::CaseInsensitive) || selectedFile.endsWith(".html",Qt::CaseInsensitive) || selectedFile.endsWith(".odt",Qt::CaseInsensitive) || selectedFile.endsWith(".txt",Qt::CaseInsensitive)))
222                dw.setFormat("plaintext");
223        if (!dw.write(solutionText->document()))
224                QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(dw.device()->errorString()));
225#else // QT_VERSION >= 0x040500
226        // Qt < 4.5 has no QTextDocumentWriter class
227QFile file(selectedFile);
228        if (!file.open(QFile::WriteOnly)) {
229                QApplication::restoreOverrideCursor();
230                QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(file->errorString()));
231                return;
232        }
233QTextStream ts(&file);
234        ts.setCodec(QTextCodec::codecForName("UTF-8"));
235        ts << solutionText->document()->toHtml("UTF-8");
236        file.close();
237#endif // QT_VERSION >= 0x040500
238        QApplication::restoreOverrideCursor();
239}
240
241#ifndef QT_NO_PRINTER
242void MainWindow::actionFilePrintPreviewTriggered()
243{
244QPrintPreviewDialog ppd(printer, this);
245        connect(&ppd,SIGNAL(paintRequested(QPrinter *)),SLOT(printPreview(QPrinter *)));
246        ppd.exec();
247}
248
249void MainWindow::actionFilePrintTriggered()
250{
251QPrintDialog pd(printer,this);
252#if QT_VERSION >= 0x040500
253        // No such methods in Qt < 4.5
254        pd.setOption(QAbstractPrintDialog::PrintSelection,false);
255        pd.setOption(QAbstractPrintDialog::PrintPageRange,false);
256#endif
257        if (pd.exec() != QDialog::Accepted)
258                return;
259        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
260        solutionText->document()->print(printer);
261        QApplication::restoreOverrideCursor();
262}
263#endif // QT_NO_PRINTER
264
265void MainWindow::actionSettingsPreferencesTriggered()
266{
267SettingsDialog sd(this);
268        if (sd.exec() != QDialog::Accepted)
269                return;
270        if (sd.colorChanged() || sd.fontChanged()) {
271                if (!solutionText->document()->isEmpty() && sd.colorChanged())
272                        QMessageBox::information(this, tr("Settings Changed"), tr("You have changed color settings.\nThey will be applied to the next solution output."));
273                initDocStyleSheet();
274        }
275        if (sd.translucencyChanged() != 0)
276                toggleTranclucency(sd.translucencyChanged() == 1);
277}
278
279void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked)
280{
281        if (checked) {
282                settings->remove("Language");
283                QMessageBox::information(this, tr("Language change"), tr("Language will be autodetected on the next application start."));
284        } else
285                settings->setValue("Language", groupSettingsLanguageList->checkedAction()->data().toString());
286}
287
288void MainWindow::groupSettingsLanguageListTriggered(QAction *action)
289{
290        if (actionSettingsLanguageAutodetect->isChecked()) {
291                // We have language autodetection. It needs to be disabled to change language.
292                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) {
293                        actionSettingsLanguageAutodetect->trigger();
294                } else
295                        return;
296        }
297bool untitled = (fileName == tr("Untitled") + ".tspt");
298        if (loadLanguage(action->data().toString())) {
299                QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
300                settings->setValue("Language",action->data().toString());
301                retranslateUi();
302                if (untitled)
303                        setFileName();
304#ifdef Q_OS_WIN32
305                if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
306                        toggleStyle(labelVariant, true);
307                        toggleStyle(labelCities, true);
308                }
309#endif
310                QApplication::restoreOverrideCursor();
311                if (!solutionText->document()->isEmpty())
312                        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."));
313        }
314}
315
316#ifdef Q_OS_WIN32
317void MainWindow::actionHelpCheck4UpdatesTriggered()
318{
319        if (!hasUpdater()) {
320                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."));
321                return;
322        }
323
324        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
325        QProcess::execute("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\"");
326        QApplication::restoreOverrideCursor();
327}
328#endif // Q_OS_WIN32
329
330void MainWindow::actionHelpAboutTriggered()
331{
332QString title;
333#ifdef HANDHELD
334        title += QString("<b>TSPSG<br>TSP Solver and Generator</b><br>");
335#else
336        title += QString("<b>TSPSG: TSP Solver and Generator</b><br>");
337#endif // HANDHELD
338        title += QString("%1: <b>%2</b><br>").arg(tr("Version"), QApplication::applicationVersion());
339#ifndef HANDHELD
340        title += QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b><br>").arg(QDate::currentDate().toString("yyyy"), QApplication::organizationDomain(), QApplication::organizationName());
341        title += QString("<b><a href=\"http://tspsg.sourceforge.net/\">http://tspsg.sourceforge.net/</a></b>");
342#else
343        title += QString("<b><a href=\"http://tspsg.sourceforge.net/\">http://tspsg.sf.net/</a></b>");
344#endif // Q_OS_WINCE_WM && Q_OS_SYMBIAN
345
346QString about;
347        about += QString("%1: <b>%2</b><br>").arg(tr("Target OS (ARCH)"), OS);
348#ifndef STATIC_BUILD
349        about += QString("%1 (%2):<br>").arg(tr("Qt library"), tr("shared"));
350        about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Build time"), QT_VERSION_STR);
351        about += QString("&nbsp;&nbsp;&nbsp;&nbsp;%1: <b>%2</b><br>").arg(tr("Runtime"), qVersion());
352#else
353        about += QString("%1: <b>%2</b> (%3)<br>").arg(tr("Qt library"), QT_VERSION_STR, tr("static"));
354#endif // STATIC_BUILD
355        about += tr("Buid <b>%1</b>, built on <b>%2</b> at <b>%3</b>").arg(BUILD_NUMBER).arg(__DATE__).arg(__TIME__) + "<br>";
356        about += QString("%1: <b>%2</b><br>").arg(tr("Algorithm"), CTSPSolver::getVersionId());
357        about += "<br>";
358        about += tr("TSPSG is free software: you can redistribute it and/or modify it<br>"
359                "under the terms of the GNU General Public License as published<br>"
360                "by the Free Software Foundation, either version 3 of the License,<br>"
361                "or (at your option) any later version.<br>"
362                "<br>"
363                "TSPSG is distributed in the hope that it will be useful, but<br>"
364                "WITHOUT ANY WARRANTY; without even the implied warranty of<br>"
365                "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>"
366                "GNU General Public License for more details.<br>"
367                "<br>"
368                "You should have received a copy of the GNU General Public License<br>"
369                "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">http://www.gnu.org/licenses/</a>.");
370
371QDialog *dlg = new QDialog(this);
372QLabel *lblIcon = new QLabel(dlg),
373        *lblTitle = new QLabel(dlg),
374        *lblTranslated = new QLabel(dlg);
375#ifdef HANDHELD
376QLabel *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);
377#endif // HANDHELD
378QTextBrowser *txtAbout = new QTextBrowser(dlg);
379QVBoxLayout *vb = new QVBoxLayout();
380QHBoxLayout *hb1 = new QHBoxLayout(),
381        *hb2 = new QHBoxLayout();
382QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dlg);
383
384        lblTitle->setOpenExternalLinks(true);
385        lblTitle->setText(title);
386        lblTitle->setAlignment(Qt::AlignTop);
387        lblTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
388#ifndef HANDHELD
389        lblTitle->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().window().color().name(), palette().shadow().color().name()));
390#endif // HANDHELD
391
392        lblIcon->setPixmap(QPixmap(":/images/tspsg.png").scaledToHeight(lblTitle->sizeHint().height(), Qt::SmoothTransformation));
393        lblIcon->setAlignment(Qt::AlignVCenter);
394#ifndef HANDHELD
395        lblIcon->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().window().color().name(), palette().windowText().color().name()));
396#endif // HANDHELD
397
398        hb1->addWidget(lblIcon);
399        hb1->addWidget(lblTitle);
400
401        txtAbout->setWordWrapMode(QTextOption::NoWrap);
402        txtAbout->setOpenExternalLinks(true);
403        txtAbout->setHtml(about);
404        txtAbout->moveCursor(QTextCursor::Start);
405#ifndef HANDHELD
406        txtAbout->setStyleSheet(QString("QTextBrowser {border-color: %1; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().shadow().color().name()));
407#endif // HANDHELD
408
409        bb->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor));
410
411        lblTranslated->setText(QApplication::translate("--------", "TRANSLATION", "Please, provide translator credits here."));
412        if (lblTranslated->text() == "TRANSLATION")
413                lblTranslated->hide();
414        else {
415                lblTranslated->setOpenExternalLinks(true);
416#ifndef HANDHELD
417                lblTranslated->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(palette().window().color().name(), palette().shadow().color().name()));
418#endif // HANDHELD
419                hb2->addWidget(lblTranslated);
420        }
421
422        hb2->addWidget(bb);
423
424#ifdef Q_OS_WINCE_WM
425        vb->setMargin(3);
426#endif // Q_OS_WINCE_WM
427        vb->addLayout(hb1);
428#ifdef HANDHELD
429        vb->addWidget(lblSubTitle);
430#endif // HANDHELD
431        vb->addWidget(txtAbout);
432        vb->addLayout(hb2);
433
434        dlg->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
435        dlg->setWindowTitle(tr("About TSPSG"));
436        dlg->setLayout(vb);
437
438        connect(bb, SIGNAL(accepted()), dlg, SLOT(accept()));
439
440#ifdef Q_OS_WIN32
441        // Adding some eyecandy in Vista and 7 :-)
442        if (QtWin::isCompositionEnabled())  {
443                QtWin::enableBlurBehindWindow(dlg, true);
444        }
445#endif // Q_OS_WIN32
446
447        dlg->resize(450, 350);
448
449        dlg->exec();
450
451        delete dlg;
452}
453
454void MainWindow::buttonBackToTaskClicked()
455{
456        tabWidget->setCurrentIndex(0);
457}
458
459void MainWindow::buttonRandomClicked()
460{
461        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
462        tspmodel->randomize();
463        QApplication::restoreOverrideCursor();
464}
465
466void MainWindow::buttonSolveClicked()
467{
468TMatrix matrix;
469QList<double> row;
470int n = spinCities->value();
471bool ok;
472        for (int r = 0; r < n; r++) {
473                row.clear();
474                for (int c = 0; c < n; c++) {
475                        row.append(tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok));
476                        if (!ok) {
477                                QMessageBox::critical(this, tr("Data error"), tr("Error in cell [Row %1; Column %2]: Invalid data format.").arg(r + 1).arg(c + 1));
478                                return;
479                        }
480                }
481                matrix.append(row);
482        }
483
484QProgressDialog pd(this);
485QProgressBar *pb = new QProgressBar(&pd);
486        pb->setAlignment(Qt::AlignCenter);
487        pb->setFormat(tr("%v of %1 parts found").arg(n));
488        pd.setBar(pb);
489        pd.setMaximum(n);
490        pd.setAutoReset(false);
491        pd.setLabelText(tr("Calculating optimal route..."));
492        pd.setWindowTitle(tr("Solution Progress"));
493        pd.setWindowModality(Qt::ApplicationModal);
494        pd.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
495        pd.show();
496
497CTSPSolver solver;
498        connect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
499        connect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
500SStep *root = solver.solve(n, matrix);
501        disconnect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
502        disconnect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
503        if (!root) {
504                pd.reset();
505                if (!solver.wasCanceled())
506                        QMessageBox::warning(this, tr("Solution Result"), tr("Unable to find a solution.\nMaybe, this task has no solution."));
507                return;
508        }
509        pb->setFormat(tr("Generating header"));
510        pd.setLabelText(tr("Generating solution output..."));
511        pd.setMaximum(n);
512        pd.setValue(0);
513
514#ifdef DEBUG
515QTime t;
516        t.start();
517#endif
518        solutionText->clear();
519#ifdef DEBUG
520        qDebug() << "Clear:" << t.elapsed();
521        t.restart();
522#endif
523        solutionText->setDocumentTitle(tr("Solution of Variant #%1 Task").arg(spinVariant->value()));
524
525QTextDocument *doc = solutionText->document();
526QTextCursor cur(doc);
527
528        cur.beginEditBlock();
529        cur.setBlockFormat(fmt_paragraph);
530        cur.insertText(tr("Variant #%1").arg(spinVariant->value()), fmt_default);
531        cur.insertBlock(fmt_paragraph);
532        cur.insertText(tr("Task:"));
533        outputMatrix(cur, matrix);
534        cur.insertHtml("<hr>");
535        cur.insertBlock(fmt_paragraph);
536        cur.insertText(tr("Solution of Variant #%1 Task").arg(spinVariant->value()), fmt_default);
537        cur.endEditBlock();
538
539SStep *step = root;
540        n = 1;
541        pb->setFormat(tr("Generating step %v"));
542        while (n < spinCities->value()) {
543                if (pd.wasCanceled()) {
544                        pd.setLabelText(tr("Cleaning up..."));
545                        pd.setMaximum(0);
546                        pd.setCancelButton(NULL);
547                        pd.show();
548                        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
549                        solver.cleanup(true);
550                        solutionText->clear();
551                        toggleSolutionActions(false);
552                        return;
553                }
554                pd.setValue(n);
555
556                if (step->prNode->prNode != NULL || ((step->prNode->prNode == NULL) && (step->plNode->prNode == NULL))) {
557                        if (n != spinCities->value()) {
558                                cur.beginEditBlock();
559                                cur.insertBlock(fmt_paragraph);
560                                cur.insertText(tr("Step #%1").arg(n++));
561                                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())))) {
562                                        outputMatrix(cur, *step);
563                                }
564                                cur.insertBlock(fmt_paragraph);
565                                cur.insertText(tr("Selected candidate for branching: %1.").arg(tr("(%1;%2)").arg(step->candidate.nRow + 1).arg(step->candidate.nCol + 1)), fmt_default);
566                                if (!step->alts.empty()) {
567SCandidate cand;
568QString alts;
569                                        foreach(cand, step->alts) {
570                                                if (!alts.isEmpty())
571                                                        alts += ", ";
572                                                alts += tr("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1);
573                                        }
574                                        cur.insertBlock(fmt_paragraph);
575                                        cur.insertText(tr("%n alternate candidate(s) for branching: %1.", "", step->alts.count()).arg(alts), fmt_altlist);
576                                }
577                                cur.insertBlock(fmt_paragraph);
578                                cur.insertText(" ", fmt_default);
579                                cur.endEditBlock();
580                        }
581                }
582                if (step->prNode->prNode != NULL)
583                        step = step->prNode;
584                else if (step->plNode->prNode != NULL)
585                        step = step->plNode;
586                else
587                        break;
588        }
589        pb->setFormat(tr("Generating footer"));
590        pd.setValue(n);
591
592        cur.beginEditBlock();
593        cur.insertBlock(fmt_paragraph);
594        if (solver.isOptimal())
595                cur.insertText(tr("Optimal path:"));
596        else
597                cur.insertText(tr("Resulting path:"));
598
599        cur.insertBlock(fmt_paragraph);
600        cur.insertText("  " + solver.getSortedPath());
601
602        cur.insertBlock(fmt_paragraph);
603        if (isInteger(step->price))
604                cur.insertHtml("<p>" + tr("The price is <b>%n</b> unit(s).", "", qRound(step->price)) + "</p>");
605        else
606                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>");
607        if (!solver.isOptimal()) {
608                cur.insertBlock(fmt_paragraph);
609                cur.insertText(" ");
610                cur.insertBlock(fmt_paragraph);
611                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>");
612        }
613        cur.endEditBlock();
614#ifdef DEBUG
615        qDebug() << "Generate:" << t.elapsed();
616#endif
617
618        if (settings->value("Output/ScrollToEnd", DEF_SCROLL_TO_END).toBool()) {
619                // Scrolling to the end of the text.
620                solutionText->moveCursor(QTextCursor::End);
621        } else
622                solutionText->moveCursor(QTextCursor::Start);
623
624        pd.setLabelText(tr("Cleaning up..."));
625        pd.setMaximum(0);
626        pd.setCancelButton(NULL);
627        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
628        solver.cleanup(true);
629        toggleSolutionActions();
630        tabWidget->setCurrentIndex(1);
631}
632
633void MainWindow::dataChanged()
634{
635        setWindowModified(true);
636}
637
638void MainWindow::dataChanged(const QModelIndex &tl, const QModelIndex &br)
639{
640        setWindowModified(true);
641        if (settings->value("Autosize", DEF_AUTOSIZE).toBool()) {
642                for (int k = tl.row(); k <= br.row(); k++)
643                        taskView->resizeRowToContents(k);
644                for (int k = tl.column(); k <= br.column(); k++)
645                        taskView->resizeColumnToContents(k);
646        }
647}
648
649#ifdef Q_OS_WINCE_WM
650void MainWindow::changeEvent(QEvent *ev)
651{
652        if ((ev->type() == QEvent::ActivationChange) && isActiveWindow())
653                desktopResized(0);
654
655        QWidget::changeEvent(ev);
656}
657
658void MainWindow::desktopResized(int screen)
659{
660        if ((screen != 0) || !isActiveWindow())
661                return;
662
663QRect availableGeometry = QApplication::desktop()->availableGeometry(0);
664        if (currentGeometry != availableGeometry) {
665                QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
666                /*!
667                 * \hack HACK: This hack checks whether \link QDesktopWidget::availableGeometry() availableGeometry()\endlink's \c top + \c hegiht = \link QDesktopWidget::screenGeometry() screenGeometry()\endlink's \c height.
668                 *  If \c true, the window gets maximized. If we used \c setGeometry() in this case, the bottom of the
669                 *  window would end up being behind the soft buttons. Is this a bug in Qt or Windows Mobile?
670                 */
671                if ((availableGeometry.top() + availableGeometry.height()) == QApplication::desktop()->screenGeometry().height()) {
672                        setWindowState(windowState() | Qt::WindowMaximized);
673                } else {
674                        if (windowState() & Qt::WindowMaximized)
675                                setWindowState(windowState() ^ Qt::WindowMaximized);
676                        setGeometry(availableGeometry);
677                }
678                currentGeometry = availableGeometry;
679                QApplication::restoreOverrideCursor();
680        }
681}
682#endif // Q_OS_WINCE_WM
683
684void MainWindow::numCitiesChanged(int nCities)
685{
686        blockSignals(true);
687        spinCities->setValue(nCities);
688        blockSignals(false);
689}
690
691#ifndef QT_NO_PRINTER
692void MainWindow::printPreview(QPrinter *printer)
693{
694        solutionText->print(printer);
695}
696#endif // QT_NO_PRINTER
697
698void MainWindow::spinCitiesValueChanged(int n)
699{
700        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
701int count = tspmodel->numCities();
702        tspmodel->setNumCities(n);
703        if ((n > count) && settings->value("Autosize", DEF_AUTOSIZE).toBool())
704                for (int k = count; k < n; k++) {
705                        taskView->resizeColumnToContents(k);
706                        taskView->resizeRowToContents(k);
707                }
708        QApplication::restoreOverrideCursor();
709}
710
711void MainWindow::closeEvent(QCloseEvent *ev)
712{
713        if (!maybeSave()) {
714                ev->ignore();
715                return;
716        }
717        if (!settings->value("SettingsReset", false).toBool()) {
718                settings->setValue("NumCities", spinCities->value());
719
720                // Saving Main Window state
721                if (settings->value("SavePos", DEF_SAVEPOS).toBool()) {
722                        settings->beginGroup("MainWindow");
723#ifndef HANDHELD
724                        settings->setValue("Geometry", saveGeometry());
725#endif // HANDHELD
726                        settings->setValue("State", saveState());
727                        settings->endGroup();
728                }
729        } else {
730                settings->remove("SettingsReset");
731        }
732
733        QMainWindow::closeEvent(ev);
734}
735
736bool MainWindow::hasUpdater() const
737{
738#ifdef Q_OS_WIN32
739        return QFile::exists("updater/Update.exe");
740#else // Q_OS_WIN32
741        return false;
742#endif // Q_OS_WIN32
743}
744
745void MainWindow::initDocStyleSheet()
746{
747        solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>());
748
749        fmt_paragraph.setTopMargin(0);
750        fmt_paragraph.setRightMargin(10);
751        fmt_paragraph.setBottomMargin(0);
752        fmt_paragraph.setLeftMargin(10);
753
754        fmt_table.setTopMargin(5);
755        fmt_table.setRightMargin(10);
756        fmt_table.setBottomMargin(5);
757        fmt_table.setLeftMargin(10);
758        fmt_table.setBorder(0);
759        fmt_table.setBorderStyle(QTextFrameFormat::BorderStyle_None);
760        fmt_table.setCellSpacing(5);
761
762        fmt_center.setAlignment(Qt::AlignHCenter);
763
764QColor color = settings->value("Output/Colors/Text", DEF_TEXT_COLOR).value<QColor>();
765QColor hilight;
766        if (color.value() < 192)
767                hilight.setHsv(color.hue(), color.saturation(), 127 + qRound(color.value() / 2));
768        else
769                hilight.setHsv(color.hue(), color.saturation(), color.value() / 2);
770
771        solutionText->document()->setDefaultStyleSheet(QString("* {color: %1;}").arg(color.name()));
772        fmt_default.setForeground(QBrush(color));
773
774        fmt_selected.setForeground(QBrush(settings->value("Output/Colors/Selected", DEF_SELECTED_COLOR).value<QColor>()));
775        fmt_selected.setFontWeight(QFont::Bold);
776
777        fmt_alternate.setForeground(QBrush(settings->value("Output/Colors/Alternate", DEF_ALTERNATE_COLOR).value<QColor>()));
778        fmt_alternate.setFontWeight(QFont::Bold);
779        fmt_altlist.setForeground(QBrush(hilight));
780
781        solutionText->setTextColor(color);
782}
783
784void MainWindow::loadLangList()
785{
786QDir dir(PATH_L10N, "tspsg_*.qm", QDir::Name | QDir::IgnoreCase, QDir::Files);
787        if (!dir.exists())
788                return;
789QFileInfoList langs = dir.entryInfoList();
790        if (langs.size() <= 0)
791                return;
792QAction *a;
793QTranslator t;
794QString name;
795        for (int k = 0; k < langs.size(); k++) {
796                QFileInfo lang = langs.at(k);
797                if (lang.completeBaseName().compare("tspsg_en", Qt::CaseInsensitive) && t.load(lang.completeBaseName(), PATH_L10N)) {
798                        name = t.translate("--------", "LANGNAME", "Please, provide a native name of your translation language here.");
799                        a = menuSettingsLanguage->addAction(name);
800                        a->setStatusTip(QString("Set application language to %1").arg(name));
801                        a->setData(lang.completeBaseName().mid(6));
802                        a->setCheckable(true);
803                        a->setActionGroup(groupSettingsLanguageList);
804                        if (settings->value("Language", QLocale::system().name()).toString().startsWith(lang.completeBaseName().mid(6)))
805                                a->setChecked(true);
806                }
807        }
808}
809
810bool MainWindow::loadLanguage(const QString &lang)
811{
812// i18n
813bool ad = false;
814QString lng = lang;
815        if (lng.isEmpty()) {
816                ad = settings->value("Language", "").toString().isEmpty();
817                lng = settings->value("Language", QLocale::system().name()).toString();
818        }
819static QTranslator *qtTranslator; // Qt library translator
820        if (qtTranslator) {
821                qApp->removeTranslator(qtTranslator);
822                delete qtTranslator;
823                qtTranslator = NULL;
824        }
825static QTranslator *translator; // Application translator
826        if (translator) {
827                qApp->removeTranslator(translator);
828                delete translator;
829                translator = NULL;
830        }
831
832        if (lng == "en")
833                return true;
834
835        // Trying to load system Qt library translation...
836        qtTranslator = new QTranslator(this);
837        if (qtTranslator->load("qt_" + lng, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
838                qApp->installTranslator(qtTranslator);
839        else {
840                // No luck. Let's try to load a bundled one.
841                if (qtTranslator->load("qt_" + lng, PATH_L10N))
842                        qApp->installTranslator(qtTranslator);
843                else {
844                        // Qt library translation unavailable
845                        delete qtTranslator;
846                        qtTranslator = NULL;
847                }
848        }
849
850        // Now let's load application translation.
851        translator = new QTranslator(this);
852        if (translator->load("tspsg_" + lng, PATH_L10N))
853                qApp->installTranslator(translator);
854        else {
855                delete translator;
856                translator = NULL;
857                if (!ad) {
858                        settings->remove("Language");
859                        QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
860                        if (isVisible())
861                                QMessageBox::warning(this, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection."));
862                        else
863                                QMessageBox::warning(NULL, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection."));
864                        QApplication::restoreOverrideCursor();
865                }
866                return false;
867        }
868        return true;
869}
870
871bool MainWindow::maybeSave()
872{
873        if (!isWindowModified())
874                return true;
875int res = QMessageBox::warning(this, tr("Unsaved Changes"), tr("Would you like to save changes in the current task?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
876        if (res == QMessageBox::Save)
877                return actionFileSaveTriggered();
878        else if (res == QMessageBox::Cancel)
879                return false;
880        else
881                return true;
882}
883
884void MainWindow::outputMatrix(QTextCursor &cur, const TMatrix &matrix)
885{
886int n = spinCities->value();
887QTextTable *table = cur.insertTable(n, n, fmt_table);
888
889        for (int r = 0; r < n; r++) {
890                for (int c = 0; c < n; c++) {
891                        cur = table->cellAt(r, c).firstCursorPosition();
892                        cur.setBlockFormat(fmt_center);
893                        cur.setBlockCharFormat(fmt_default);
894                        if (matrix.at(r).at(c) == INFINITY)
895                                cur.insertText(INFSTR);
896                        else
897                                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()));
898                }
899                QApplication::processEvents();
900        }
901        cur.movePosition(QTextCursor::End);
902}
903
904void MainWindow::outputMatrix(QTextCursor &cur, const SStep &step)
905{
906int n = spinCities->value();
907QTextTable *table = cur.insertTable(n, n, fmt_table);
908
909        for (int r = 0; r < n; r++) {
910                for (int c = 0; c < n; c++) {
911                        cur = table->cellAt(r, c).firstCursorPosition();
912                        cur.setBlockFormat(fmt_center);
913                        if (step.matrix.at(r).at(c) == INFINITY)
914                                cur.insertText(INFSTR, fmt_default);
915                        else if ((r == step.candidate.nRow) && (c == step.candidate.nCol))
916                                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);
917                        else {
918SCandidate cand;
919                                cand.nRow = r;
920                                cand.nCol = c;
921                                if (step.alts.contains(cand))
922                                        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);
923                                else
924                                        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);
925                        }
926                }
927                QApplication::processEvents();
928        }
929
930        cur.movePosition(QTextCursor::End);
931}
932
933void MainWindow::retranslateUi(bool all)
934{
935        if (all)
936                Ui::MainWindow::retranslateUi(this);
937
938        actionSettingsLanguageEnglish->setStatusTip(tr("Set application language to %1").arg("English"));
939
940#ifndef QT_NO_PRINTER
941        actionFilePrintPreview->setText(QApplication::translate("MainWindow", "P&rint Preview...", 0, QApplication::UnicodeUTF8));
942#ifndef QT_NO_TOOLTIP
943        actionFilePrintPreview->setToolTip(QApplication::translate("MainWindow", "Preview solution results", 0, QApplication::UnicodeUTF8));
944#endif // QT_NO_TOOLTIP
945#ifndef QT_NO_STATUSTIP
946        actionFilePrintPreview->setStatusTip(QApplication::translate("MainWindow", "Preview current solution results before printing", 0, QApplication::UnicodeUTF8));
947#endif // QT_NO_STATUSTIP
948
949        actionFilePrint->setText(QApplication::translate("MainWindow", "&Print...", 0, QApplication::UnicodeUTF8));
950#ifndef QT_NO_TOOLTIP
951        actionFilePrint->setToolTip(QApplication::translate("MainWindow", "Print solution", 0, QApplication::UnicodeUTF8));
952#endif // QT_NO_TOOLTIP
953#ifndef QT_NO_STATUSTIP
954        actionFilePrint->setStatusTip(QApplication::translate("MainWindow", "Print current solution results", 0, QApplication::UnicodeUTF8));
955#endif // QT_NO_STATUSTIP
956        actionFilePrint->setShortcut(QApplication::translate("MainWindow", "Ctrl+P", 0, QApplication::UnicodeUTF8));
957#endif // QT_NO_PRINTER
958#ifdef Q_OS_WIN32
959        actionHelpCheck4Updates->setText(tr("Check for &Updates..."));
960#ifndef QT_NO_TOOLTIP
961        actionHelpCheck4Updates->setToolTip(tr("Check for %1 updates").arg(QApplication::applicationName()));
962#endif // QT_NO_TOOLTIP
963#ifndef QT_NO_STATUSTIP
964        actionHelpCheck4Updates->setStatusTip(tr("Check for %1 updates").arg(QApplication::applicationName()));
965#endif // QT_NO_STATUSTIP
966#endif // Q_OS_WIN32
967}
968
969bool MainWindow::saveTask() {
970QStringList filters(tr("%1 Task File").arg("TSPSG") + " (*.tspt)");
971        filters.append(tr("All Files") + " (*)");
972QString file;
973        if (fileName.endsWith(".tspt", Qt::CaseInsensitive))
974                file = fileName;
975        else
976                file = QFileInfo(fileName).canonicalPath() + "/" + QFileInfo(fileName).completeBaseName() + ".tspt";
977
978QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog;
979        file = QFileDialog::getSaveFileName(this, tr("Task Save"), file, filters.join(";;"), NULL, opts);
980
981        if (file.isEmpty())
982                return false;
983        if (tspmodel->saveTask(file)) {
984                setFileName(file);
985                setWindowModified(false);
986                return true;
987        }
988        return false;
989}
990
991void MainWindow::setFileName(const QString &fileName)
992{
993        this->fileName = fileName;
994        setWindowTitle(QString("%1[*] - %2").arg(QFileInfo(fileName).completeBaseName()).arg(tr("Travelling Salesman Problem")));
995}
996
997void MainWindow::setupUi()
998{
999        Ui::MainWindow::setupUi(this);
1000
1001#if QT_VERSION >= 0x040600
1002        setToolButtonStyle(Qt::ToolButtonFollowStyle);
1003#endif
1004
1005#ifndef HANDHELD
1006QStatusBar *statusbar = new QStatusBar(this);
1007        statusbar->setObjectName("statusbar");
1008        setStatusBar(statusbar);
1009#endif // HANDHELD
1010
1011#ifdef Q_OS_WINCE_WM
1012        menuBar()->setDefaultAction(menuFile->menuAction());
1013
1014QScrollArea *scrollArea = new QScrollArea(this);
1015        scrollArea->setFrameShape(QFrame::NoFrame);
1016        scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1017        scrollArea->setWidgetResizable(true);
1018        scrollArea->setWidget(tabWidget);
1019        setCentralWidget(scrollArea);
1020#else
1021        setCentralWidget(tabWidget);
1022#endif // Q_OS_WINCE_WM
1023
1024        //! \hack HACK: A little hack for toolbar icons to have a sane size.
1025#ifdef Q_OS_WINCE_WM
1026        toolBar->setIconSize(QSize(logicalDpiX() / 4, logicalDpiY() / 4));
1027#elif defined(Q_OS_SYMBIAN)
1028        toolBar->setIconSize(QSize(logicalDpiX() / 5, logicalDpiY() / 5));
1029#endif // Q_OS_WINCE_WM
1030
1031        solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>());
1032        solutionText->setWordWrapMode(QTextOption::WordWrap);
1033
1034#ifndef QT_NO_PRINTER
1035        actionFilePrintPreview = new QAction(this);
1036        actionFilePrintPreview->setObjectName("actionFilePrintPreview");
1037        actionFilePrintPreview->setEnabled(false);
1038        actionFilePrintPreview->setIcon(QIcon(":/images/icons/document_preview.png"));
1039
1040        actionFilePrint = new QAction(this);
1041        actionFilePrint->setObjectName("actionFilePrint");
1042        actionFilePrint->setEnabled(false);
1043        actionFilePrint->setIcon(QIcon(":/images/icons/fileprint.png"));
1044
1045        menuFile->insertAction(actionFileExit,actionFilePrintPreview);
1046        menuFile->insertAction(actionFileExit,actionFilePrint);
1047        menuFile->insertSeparator(actionFileExit);
1048
1049        toolBar->insertAction(actionSettingsPreferences,actionFilePrint);
1050#endif // QT_NO_PRINTER
1051#ifdef Q_OS_WIN32
1052        actionHelpCheck4Updates = new QAction(this);
1053        actionHelpCheck4Updates->setEnabled(hasUpdater());
1054        menuHelp->insertAction(actionHelpAboutQt, actionHelpCheck4Updates);
1055        menuHelp->insertSeparator(actionHelpAboutQt);
1056#endif // Q_OS_WIN32
1057
1058        groupSettingsLanguageList = new QActionGroup(this);
1059        actionSettingsLanguageEnglish->setData("en");
1060        actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
1061        loadLangList();
1062        actionSettingsLanguageAutodetect->setChecked(settings->value("Language", "").toString().isEmpty());
1063
1064        spinCities->setMaximum(MAX_NUM_CITIES);
1065
1066        retranslateUi(false);
1067
1068#ifdef Q_OS_WIN32
1069        // Adding some eyecandy in Vista and 7 :-)
1070        if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool())  {
1071                toggleTranclucency(true);
1072        }
1073#endif // Q_OS_WIN32
1074}
1075
1076void MainWindow::toggleSolutionActions(bool enable)
1077{
1078        buttonSaveSolution->setEnabled(enable);
1079        actionFileSaveAsSolution->setEnabled(enable);
1080        solutionText->setEnabled(enable);
1081#ifndef QT_NO_PRINTER
1082        actionFilePrint->setEnabled(enable);
1083        actionFilePrintPreview->setEnabled(enable);
1084#endif // QT_NO_PRINTER
1085}
1086
1087void MainWindow::toggleTranclucency(bool enable)
1088{
1089#ifdef Q_OS_WIN32
1090        toggleStyle(labelVariant, enable);
1091        toggleStyle(labelCities, enable);
1092        toggleStyle(statusBar(), enable);
1093        tabWidget->setDocumentMode(enable);
1094        QtWin::enableBlurBehindWindow(this, enable);
1095#else
1096        Q_UNUSED(enable);
1097#endif // Q_OS_WIN32
1098}
Note: See TracBrowser for help on using the repository browser.