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

Last change on this file since 80 was 80, checked in by laleppa, 15 years ago

+ Added Wait Cursor on city number change, because it can take some time (e.g. when changing from 5 to 50 cities).

  • Moved platform specific action definitions from .ui to source.
  • Changed random generation to include defined maximum (it was up to maximum previously).
  • Reverted from native to Qt open/save file dialog under WinCE, because it is more convenient than the native one.
  • English translation is now always loaded at application start before any other language is loaded. This is done to support plurals and some special characters that Qt translation system doesn't "like".
  • Updated translations to reflect recent changes.
  • Property svn:keywords set to Id URL
File size: 28.9 KB
RevLine 
[45]1/*
[42]2 *  TSPSG: TSP Solver and Generator
[17]3 *  Copyright (C) 2007-2009 Lёppa <contacts[at]oleksii[dot]name>
[1]4 *
[6]5 *  $Id: mainwindow.cpp 80 2009-12-22 19:56:21Z laleppa $
6 *  $URL: https://tspsg.svn.sourceforge.net/svnroot/tspsg/trunk/src/mainwindow.cpp $
[4]7 *
[6]8 *  This file is part of TSPSG.
[1]9 *
[6]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.
[1]14 *
[6]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.
[1]19 *
[6]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/>.
[1]22 */
23
24#include "mainwindow.h"
25
[65]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 */
[1]33MainWindow::MainWindow(QWidget *parent)
[21]34        : QMainWindow(parent)
[1]35{
[80]36        settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this);
[29]37        loadLanguage();
[80]38        setupUi();
39
[42]40        initDocStyleSheet();
[80]41
[54]42#ifndef QT_NO_PRINTER
[52]43        printer = new QPrinter(QPrinter::HighResolution);
[54]44#endif // QT_NO_PRINTER
[80]45
[29]46        connect(actionFileNew,SIGNAL(triggered()),this,SLOT(actionFileNewTriggered()));
[31]47        connect(actionFileOpen,SIGNAL(triggered()),this,SLOT(actionFileOpenTriggered()));
[50]48        connect(actionFileSave,SIGNAL(triggered()),this,SLOT(actionFileSaveTriggered()));
[42]49        connect(actionFileSaveAsTask,SIGNAL(triggered()),this,SLOT(actionFileSaveAsTaskTriggered()));
50        connect(actionFileSaveAsSolution,SIGNAL(triggered()),this,SLOT(actionFileSaveAsSolutionTriggered()));
[80]51#ifndef QT_NO_PRINTER
52        connect(actionFilePrintPreview,SIGNAL(triggered()),this,SLOT(actionFilePrintPreviewTriggered()));
53        connect(actionFilePrint,SIGNAL(triggered()),this,SLOT(actionFilePrintTriggered()));
54#endif // QT_NO_PRINTER
[29]55        connect(actionSettingsPreferences,SIGNAL(triggered()),this,SLOT(actionSettingsPreferencesTriggered()));
56        connect(actionSettingsLanguageAutodetect,SIGNAL(triggered(bool)),this,SLOT(actionSettingsLanguageAutodetectTriggered(bool)));
57        connect(groupSettingsLanguageList,SIGNAL(triggered(QAction *)),this,SLOT(groupSettingsLanguageListTriggered(QAction *)));
[37]58        connect(actionHelpAboutQt,SIGNAL(triggered()),qApp,SLOT(aboutQt()));
[29]59        connect(actionHelpAbout,SIGNAL(triggered()),this,SLOT(actionHelpAboutTriggered()));
[80]60
[29]61        connect(buttonSolve,SIGNAL(clicked()),this,SLOT(buttonSolveClicked()));
62        connect(buttonRandom,SIGNAL(clicked()),this,SLOT(buttonRandomClicked()));
[50]63        connect(buttonBackToTask,SIGNAL(clicked()),this,SLOT(buttonBackToTaskClicked()));
[29]64        connect(spinCities,SIGNAL(valueChanged(int)),this,SLOT(spinCitiesValueChanged(int)));
[71]65
66        if (settings->value("SavePos", false).toBool()) {
[21]67                // Loading of saved window state
[23]68                settings->beginGroup("MainWindow");
[71]69#ifndef Q_OS_WINCE
70                restoreGeometry(settings->value("Geometry").toByteArray());
71#endif // Q_OS_WINCE
72                restoreState(settings->value("State").toByteArray());
[23]73                settings->endGroup();
[71]74#ifndef Q_OS_WINCE
[21]75        } else {
76                // Centering main window
[71]77QRect rect = geometry();
[21]78                rect.moveCenter(QApplication::desktop()->availableGeometry(this).center());
79                setGeometry(rect);
[71]80#endif // Q_OS_WINCE
[21]81        }
[71]82
83        tspmodel = new CTSPModel(this);
[52]84        taskView->setModel(tspmodel);
[31]85        connect(tspmodel,SIGNAL(numCitiesChanged(int)),this,SLOT(numCitiesChanged(int)));
[57]86        connect(tspmodel,SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
[37]87        connect(tspmodel,SIGNAL(layoutChanged()),this,SLOT(dataChanged()));
[50]88        if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1))))
[47]89                setFileName(QCoreApplication::arguments().at(1));
[50]90        else {
[47]91                setFileName();
[50]92                spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt());
[52]93                spinCitiesValueChanged(spinCities->value());
[50]94        }
95        setWindowModified(false);
[6]96}
97
[80]98MainWindow::~MainWindow()
99{
100#ifndef QT_NO_PRINTER
101        delete printer;
102#endif
103}
104
[67]105/* Privates **********************************************************/
[42]106
[29]107void MainWindow::actionFileNewTriggered()
[1]108{
[47]109        if (!maybeSave())
110                return;
[54]111        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[29]112        tspmodel->clear();
[47]113        setFileName();
[37]114        setWindowModified(false);
[42]115        tabWidget->setCurrentIndex(0);
116        solutionText->clear();
[78]117        toggleSolutionActions(false);
[54]118        QApplication::restoreOverrideCursor();
[29]119}
120
[31]121void MainWindow::actionFileOpenTriggered()
122{
[47]123        if (!maybeSave())
124                return;
[78]125
[31]126QStringList filters(trUtf8("All Supported Formats") + " (*.tspt *.zkt)");
[47]127        filters.append(trUtf8("%1 Task Files").arg("TSPSG") + " (*.tspt)");
128        filters.append(trUtf8("%1 Task Files").arg("ZKomModRd") + " (*.zkt)");
[31]129        filters.append(trUtf8("All Files") + " (*)");
[78]130
[80]131#ifdef Q_OS_WINCE
132        QString file = QFileDialog::getOpenFileName(this, trUtf8("Task Load"), QString(), filters.join(";;"), NULL, QFileDialog::DontUseNativeDialog);
133#else
[78]134QString file = QFileDialog::getOpenFileName(this, trUtf8("Task Load"), QString(), filters.join(";;"));
[80]135#endif // Q_OS_WINCE
[78]136        if (file.isEmpty() || !QFileInfo(file).isFile())
[31]137                return;
[78]138        if (!tspmodel->loadTask(file))
[31]139                return;
[78]140        setFileName(file);
[47]141        tabWidget->setCurrentIndex(0);
[37]142        setWindowModified(false);
[42]143        solutionText->clear();
[78]144        toggleSolutionActions(false);
[31]145}
146
[50]147void MainWindow::actionFileSaveTriggered()
148{
149        if ((fileName == trUtf8("Untitled") + ".tspt") || (!fileName.endsWith(".tspt",Qt::CaseInsensitive)))
150                saveTask();
[59]151        else
[50]152                if (tspmodel->saveTask(fileName))
153                        setWindowModified(false);
154}
155
[42]156void MainWindow::actionFileSaveAsTaskTriggered()
[31]157{
[37]158        saveTask();
159}
160
[42]161void MainWindow::actionFileSaveAsSolutionTriggered()
162{
163static QString selectedFile;
[78]164        if (selectedFile.isEmpty()) {
165                if (fileName == trUtf8("Untitled") + ".tspt") {
[55]166#ifndef QT_NO_PRINTER
[78]167                        selectedFile = "solution.pdf";
[55]168#else
[78]169                        selectedFile = "solution.html";
[55]170#endif // QT_NO_PRINTER
[78]171                } else {
172#ifndef QT_NO_PRINTER
173                        selectedFile = QFileInfo(fileName).canonicalPath() + "/" + QFileInfo(fileName).completeBaseName() + ".pdf";
174#else
175                        selectedFile = QFileInfo(fileName).canonicalPath() + "/" + QFileInfo(fileName).completeBaseName() + ".html";
176#endif // QT_NO_PRINTER
177                }
178        }
179
[55]180QStringList filters;
181#ifndef QT_NO_PRINTER
[78]182        filters.append(trUtf8("PDF Files") + " (*.pdf)");
[55]183#endif
184        filters.append(trUtf8("HTML Files") + " (*.html *.htm)");
[45]185#if QT_VERSION >= 0x040500
[42]186        filters.append(trUtf8("OpenDocument Files") + " (*.odt)");
[45]187#endif // QT_VERSION >= 0x040500
[42]188        filters.append(trUtf8("All Files") + " (*)");
[78]189
[80]190#ifdef Q_OS_WINCE
191QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"), NULL, QFileDialog::DontUseNativeDialog);
192#else
[78]193QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"));
[80]194#endif
[78]195        if (file.isEmpty())
[42]196                return;
[78]197        selectedFile = file;
[51]198        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[55]199#ifndef QT_NO_PRINTER
200        if (selectedFile.endsWith(".pdf",Qt::CaseInsensitive)) {
201QPrinter printer(QPrinter::HighResolution);
202                printer.setOutputFormat(QPrinter::PdfFormat);
203                printer.setOutputFileName(selectedFile);
204                solutionText->document()->print(&printer);
205                QApplication::restoreOverrideCursor();
206                return;
207        }
208#endif
[45]209#if QT_VERSION >= 0x040500
[42]210QTextDocumentWriter dw(selectedFile);
211        if (!(selectedFile.endsWith(".htm",Qt::CaseInsensitive) || selectedFile.endsWith(".html",Qt::CaseInsensitive) || selectedFile.endsWith(".odt",Qt::CaseInsensitive) || selectedFile.endsWith(".txt",Qt::CaseInsensitive)))
212                dw.setFormat("plaintext");
213        dw.write(solutionText->document());
[45]214#else
215        // Qt < 4.5 has no QTextDocumentWriter class
216QFile file(selectedFile);
[51]217        if (!file.open(QFile::WriteOnly)) {
218                QApplication::restoreOverrideCursor();
[45]219                return;
[51]220        }
[45]221QTextStream ts(&file);
222        ts.setCodec(QTextCodec::codecForName("UTF-8"));
223        ts << solutionText->document()->toHtml("UTF-8");
[51]224        file.close();
[45]225#endif // QT_VERSION >= 0x040500
[51]226        QApplication::restoreOverrideCursor();
[42]227}
228
[67]229#ifndef QT_NO_PRINTER
230void MainWindow::actionFilePrintPreviewTriggered()
231{
232QPrintPreviewDialog ppd(printer, this);
233    connect(&ppd,SIGNAL(paintRequested(QPrinter *)),SLOT(printPreview(QPrinter *)));
234    ppd.exec();
[31]235}
236
[67]237void MainWindow::actionFilePrintTriggered()
238{
239QPrintDialog pd(printer,this);
240#if QT_VERSION >= 0x040500
241        // No such methods in Qt < 4.5
242        pd.setOption(QAbstractPrintDialog::PrintSelection,false);
243        pd.setOption(QAbstractPrintDialog::PrintPageRange,false);
244#endif
245        if (pd.exec() != QDialog::Accepted)
246                return;
247        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
248        solutionText->document()->print(printer);
249        QApplication::restoreOverrideCursor();
250}
251#endif // QT_NO_PRINTER
252
[29]253void MainWindow::actionSettingsPreferencesTriggered()
254{
[1]255SettingsDialog sd(this);
[42]256        if (sd.exec() != QDialog::Accepted)
257                return;
258        if (sd.colorChanged() || sd.fontChanged()) {
259                initDocStyleSheet();
260                if (!output.isEmpty() && sd.colorChanged() && (QMessageBox(QMessageBox::Question,trUtf8("Settings Changed"),trUtf8("You have changed color settings.\nDo you wish to apply them to current solution text?"),QMessageBox::Yes | QMessageBox::No,this).exec() == QMessageBox::Yes)) {
261                        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
262                        solutionText->clear();
263                        solutionText->setHtml(output.join(""));
264                        QApplication::restoreOverrideCursor();
265                }
266        }
[1]267}
[6]268
[67]269void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked)
[17]270{
[67]271        if (checked) {
272                settings->remove("Language");
273                QMessageBox(QMessageBox::Information,trUtf8("Language change"),trUtf8("Language will be autodetected on next application start."),QMessageBox::Ok,this).exec();
274        } else
275                settings->setValue("Language",groupSettingsLanguageList->checkedAction()->data().toString());
[52]276}
277
[67]278void MainWindow::groupSettingsLanguageListTriggered(QAction *action)
[52]279{
[67]280        if (actionSettingsLanguageAutodetect->isChecked()) {
281                // We have language autodetection. It needs to be disabled to change language.
282                if (QMessageBox(QMessageBox::Question,trUtf8("Language change"),trUtf8("You have language autodetection turned on.\nIt needs to be off.\nDo you wish to turn it off?"),QMessageBox::Yes | QMessageBox::No,this).exec() == QMessageBox::Yes) {
283                        actionSettingsLanguageAutodetect->trigger();
284                } else
285                        return;
286        }
287bool untitled = (fileName == trUtf8("Untitled") + ".tspt");
288        if (loadLanguage(action->data().toString())) {
[80]289                QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[67]290                settings->setValue("Language",action->data().toString());
[80]291                retranslateUi();
[67]292                if (untitled)
293                        setFileName();
[80]294                QApplication::restoreOverrideCursor();
[67]295        }
[52]296}
297
[67]298void MainWindow::actionHelpAboutTriggered()
[52]299{
[67]300//! \todo TODO: Normal about window :-)
[78]301QString title;
302#ifdef Q_OS_WINCE
303        title += QString::fromUtf8("<b>TSPSG<br>TSP Solver and Generator</b><br>");
304#else
305        title += QString::fromUtf8("<b>TSPSG: TSP Solver and Generator</b><br>");
306#endif // Q_OS_WINCE
307        title += QString::fromUtf8("Version: <b>"BUILD_VERSION"</b><br>");
308        title += QString::fromUtf8("<b>&copy; 2007-%1 Lёppa</b><br>").arg(QDate::currentDate().toString("yyyy"));
309        title += QString::fromUtf8("<b><a href=\"http://tspsg.sourceforge.net/\">http://tspsg.sf.net/</a></b><br>");
310QString about;
[74]311        about += QString::fromUtf8("Target OS: <b>%1</b><br>").arg(OS);
[78]312#ifndef STATIC_BUILD
313        about += "Qt library (shared):<br>";
[74]314        about += QString::fromUtf8("&nbsp;&nbsp;&nbsp;&nbsp;Build time: <b>%1</b><br>").arg(QT_VERSION_STR);
315        about += QString::fromUtf8("&nbsp;&nbsp;&nbsp;&nbsp;Runtime: <b>%1</b><br>").arg(qVersion());
[78]316#else
317        about += QString::fromUtf8("Qt library: <b>%1</b> (static)<br>").arg(QT_VERSION_STR);
318#endif // STATIC_BUILD
[74]319        about += QString::fromUtf8("Built on <b>%1</b> at <b>%2</b><br>").arg(__DATE__).arg(__TIME__);
[78]320        about += "<br>";
[74]321        about += QString::fromUtf8("Id: <b>"VERSIONID"</b><br>");
322        about += QString::fromUtf8("Algorithm: <b>%1</b><br>").arg(CTSPSolver::getVersionId());
323        about += "<br>";
324        about += "TSPSG is free software: you can redistribute it and/or modify it<br>"
325                "under the terms of the GNU General Public License as published<br>"
326                "by the Free Software Foundation, either version 3 of the License,<br>"
327                "or (at your option) any later version.<br>"
328                "<br>"
329                "TSPSG is distributed in the hope that it will be useful, but<br>"
330                "WITHOUT ANY WARRANTY; without even the implied warranty of<br>"
331                "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>"
332                "GNU General Public License for more details.<br>"
333                "<br>"
334                "You should have received a copy of the GNU General Public License<br>"
335                "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">http://www.gnu.org/licenses/</a>.";
336
337QDialog *dlg = new QDialog(this);
[78]338QLabel *lblIcon = new QLabel(dlg),
339        *lblTitle = new QLabel(dlg);
[74]340QTextBrowser *txtAbout = new QTextBrowser(dlg);
[78]341QVBoxLayout *vb = new QVBoxLayout();
[74]342QHBoxLayout *hb = new QHBoxLayout();
343QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dlg);
344
[78]345        lblIcon->setPixmap(QPixmap(":/images/tspsg.png").scaledToWidth(logicalDpiX() * 2 / 3, Qt::SmoothTransformation));
346        lblIcon->setAlignment(Qt::AlignTop);
[80]347        lblTitle->setOpenExternalLinks(true);
[78]348        lblTitle->setText(title);
[74]349
[78]350        hb->addWidget(lblIcon);
351        hb->addWidget(lblTitle);
352        hb->addStretch();
[74]353
354//      txtAbout->setTextInteractionFlags(txtAbout->textInteractionFlags() ^ Qt::TextEditable);
355        txtAbout->setWordWrapMode(QTextOption::NoWrap);
356        txtAbout->setOpenExternalLinks(true);
357        txtAbout->setHtml(about);
358        txtAbout->moveCursor(QTextCursor::Start);
359
[78]360        vb->addLayout(hb);
361        vb->addWidget(txtAbout);
362        vb->addWidget(bb);
[74]363
[78]364        dlg->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
[74]365        dlg->setWindowTitle(trUtf8("About TSPSG"));
[78]366        dlg->setLayout(vb);
[74]367
368        connect(bb, SIGNAL(accepted()), dlg, SLOT(accept()));
369
[78]370        dlg->resize(410, 300);
[74]371        dlg->exec();
372
373        delete dlg;
[17]374}
375
[50]376void MainWindow::buttonBackToTaskClicked()
377{
378        tabWidget->setCurrentIndex(0);
379}
380
[67]381void MainWindow::buttonRandomClicked()
[42]382{
[67]383        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
384        tspmodel->randomize();
385        QApplication::restoreOverrideCursor();
[42]386}
387
[29]388void MainWindow::buttonSolveClicked()
[6]389{
[74]390TMatrix matrix;
[42]391QList<double> row;
[15]392int n = spinCities->value();
[13]393bool ok;
[15]394        for (int r = 0; r < n; r++) {
[42]395                row.clear();
[15]396                for (int c = 0; c < n; c++) {
[42]397                        row.append(tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok));
[15]398                        if (!ok) {
[47]399                                QMessageBox(QMessageBox::Critical,trUtf8("Data error"),trUtf8("Error in cell [Row %1; Column %2]: Invalid data format.").arg(r + 1).arg(c + 1),QMessageBox::Ok,this).exec();
[15]400                                return;
[13]401                        }
402                }
403                matrix.append(row);
404        }
405CTSPSolver solver;
[74]406SStep *root = solver.solve(n,matrix,this);
[13]407        if (!root)
[42]408                return;
409        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
410QColor color = settings->value("Output/Color",DEF_FONT_COLOR).value<QColor>();
411        output.clear();
412        output.append("<p>" + trUtf8("Variant #%1").arg(spinVariant->value()) + "</p>");
413        output.append("<p>" + trUtf8("Task:") + "</p>");
[78]414        outputMatrix(matrix, output);
[42]415        output.append("<hr>");
416        output.append("<p>" + trUtf8("Solution of Variant #%1 task").arg(spinVariant->value()) + "</p>");
[74]417SStep *step = root;
[42]418        n = 1;
419        while (n <= spinCities->value()) {
[74]420                if (step->prNode->prNode != NULL || ((step->prNode->prNode == NULL) && (step->plNode->prNode == NULL))) {
[42]421                        if (n != spinCities->value()) {
422                                output.append("<p>" + trUtf8("Step #%1").arg(n++) + "</p>");
[78]423                                if (settings->value("Output/ShowMatrix", DEF_SHOW_MATRIX).toBool() && settings->value("Output/UseShowMatrixLimit", DEF_USE_SHOW_MATRIX_LIMIT).toBool() && (spinCities->value() <= settings->value("Output/ShowMatrixCitiesLimit", DEF_SHOW_MATRIX_CITY_LIMIT).toInt())) {
424                                        outputMatrix(*step, output);
425                                }
[74]426                                output.append("<p>" + trUtf8("Selected candidate for branching: %1.").arg(trUtf8("(%1;%2)").arg(step->candidate.nRow + 1).arg(step->candidate.nCol + 1)) + "</p>");
427                                if (!step->alts.empty()) {
[76]428SCandidate cand;
[74]429QString alts;
430                                        foreach(cand, step->alts) {
431                                                if (!alts.isEmpty())
432                                                        alts += ", ";
433                                                alts += trUtf8("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1);
434                                        }
435                                        output.append("<p class=\"hasalts\">" + trUtf8("%n alternate candidate(s) for branching: %1.","",step->alts.count()).arg(alts) + "</p>");
436                                }
[42]437                                output.append("<p>&nbsp;</p>");
438                        }
439                }
440                if (step->prNode->prNode != NULL)
441                        step = step->prNode;
442                else if (step->plNode->prNode != NULL)
443                        step = step->plNode;
444                else
445                        break;
446        }
[60]447        if (solver.isOptimal())
448                output.append("<p>" + trUtf8("Optimal path:") + "</p>");
449        else
450                output.append("<p>" + trUtf8("Resulting path:") + "</p>");
451        output.append("<p>&nbsp;&nbsp;" + solver.getSortedPath() + "</p>");
[80]452        output.append("<p>" + trUtf8("The price is <b>%n</b> unit(s).", "", step->price) + "</p>");
[60]453        if (!solver.isOptimal()) {
454                output.append("<p>&nbsp;</p>");
455                output.append("<p>" + trUtf8("<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>");
456        }
[65]457        output.append("<p></p>");
[78]458
[42]459        solutionText->setHtml(output.join(""));
460        solutionText->setDocumentTitle(trUtf8("Solution of Variant #%1 task").arg(spinVariant->value()));
[65]461
462        // Scrolling to the end of text.
[74]463        solutionText->moveCursor(QTextCursor::End);
[65]464
[78]465        toggleSolutionActions();
[42]466        tabWidget->setCurrentIndex(1);
467        QApplication::restoreOverrideCursor();
[6]468}
[21]469
[67]470void MainWindow::dataChanged()
[21]471{
[67]472        setWindowModified(true);
[21]473}
474
[67]475void MainWindow::dataChanged(const QModelIndex &tl, const QModelIndex &br)
476{
477        setWindowModified(true);
478        if (settings->value("Autosize",true).toBool()) {
479                for (int k = tl.row(); k <= br.row(); k++)
480                        taskView->resizeRowToContents(k);
481                for (int k = tl.column(); k <= br.column(); k++)
482                        taskView->resizeColumnToContents(k);
483        }
484}
485
486void MainWindow::numCitiesChanged(int nCities)
487{
488        blockSignals(true);
489        spinCities->setValue(nCities);
490        blockSignals(false);
491}
492
493#ifndef QT_NO_PRINTER
494void MainWindow::printPreview(QPrinter *printer)
495{
496        solutionText->print(printer);
497}
498#endif // QT_NO_PRINTER
499
500void MainWindow::spinCitiesValueChanged(int n)
501{
[80]502        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
[67]503int count = tspmodel->numCities();
504        tspmodel->setNumCities(n);
505        if ((n > count) && settings->value("Autosize",true).toBool())
506                for (int k = count; k < n; k++) {
507                        taskView->resizeColumnToContents(k);
508                        taskView->resizeRowToContents(k);
509                }
[80]510        QApplication::restoreOverrideCursor();
[67]511}
512
[71]513void MainWindow::closeEvent(QCloseEvent *ev)
[69]514{
515        if (!maybeSave()) {
[71]516                ev->ignore();
[69]517                return;
518        }
[71]519        settings->setValue("NumCities", spinCities->value());
520
521        // Saving Main Window state
522        if (settings->value("SavePos", false).toBool()) {
523                settings->beginGroup("MainWindow");
[69]524#ifndef Q_OS_WINCE
[71]525                settings->setValue("Geometry", saveGeometry());
526#endif // Q_OS_WINCE
527                settings->setValue("State", saveState());
[69]528                settings->endGroup();
529        }
[71]530
531        QMainWindow::closeEvent(ev);
[69]532}
533
[67]534void MainWindow::initDocStyleSheet()
535{
536QColor color = settings->value("Output/Color",DEF_FONT_COLOR).value<QColor>();
537QColor hilight;
538        if (color.value() < 192)
539                hilight.setHsv(color.hue(),color.saturation(),127 + qRound(color.value() / 2));
540        else
541                hilight.setHsv(color.hue(),color.saturation(),color.value() / 2);
542        solutionText->document()->setDefaultStyleSheet("* {color: " + color.name() +";} p {margin: 0px 10px;} table {margin: 5px;} td {padding: 1px 5px;} .hasalts {color: " + hilight.name() + ";} .selected {color: #A00000; font-weight: bold;} .alternate {color: #008000; font-weight: bold;}");
543        solutionText->document()->setDefaultFont(settings->value("Output/Font",QFont(DEF_FONT_FAMILY,DEF_FONT_SIZE)).value<QFont>());
544}
545
[29]546void MainWindow::loadLangList()
547{
[57]548QSettings langinfo(PATH_I18N"/languages.ini",QSettings::IniFormat);
[33]549#if QT_VERSION >= 0x040500
550        // In Qt < 4.5 QSettings doesn't have method setIniCodec.
[29]551        langinfo.setIniCodec("UTF-8");
[33]552#endif
[57]553QDir dir(PATH_I18N,"*.qm",QDir::Name | QDir::IgnoreCase,QDir::Files);
[29]554        if (!dir.exists())
555                return;
556QFileInfoList langs = dir.entryInfoList();
557        if (langs.size() <= 0)
558                return;
559QAction *a;
560        for (int k = 0; k < langs.size(); k++) {
561                QFileInfo lang = langs.at(k);
[30]562                if (!lang.completeBaseName().startsWith("qt_") && lang.completeBaseName().compare("en")) {
[33]563#if QT_VERSION >= 0x040500
[29]564                        a = menuSettingsLanguage->addAction(langinfo.value(lang.completeBaseName() + "/NativeName",lang.completeBaseName()).toString());
[33]565#else
566                        // We use Name if Qt < 4.5 because NativeName is in UTF-8, QSettings
567                        // reads .ini file as ASCII and there is no way to set file encoding.
568                        a = menuSettingsLanguage->addAction(langinfo.value(lang.completeBaseName() + "/Name",lang.completeBaseName()).toString());
569#endif
[29]570                        a->setData(lang.completeBaseName());
571                        a->setCheckable(true);
572                        a->setActionGroup(groupSettingsLanguageList);
573                        if (settings->value("Language",QLocale::system().name()).toString().startsWith(lang.completeBaseName()))
574                                a->setChecked(true);
575                }
576        }
577}
578
[71]579bool MainWindow::loadLanguage(const QString &lang)
[29]580{
[67]581// i18n
582bool ad = false;
[71]583QString lng = lang;
584        if (lng.isEmpty()) {
[67]585                ad = settings->value("Language","").toString().isEmpty();
[71]586                lng = settings->value("Language",QLocale::system().name()).toString();
[29]587        }
[67]588static QTranslator *qtTranslator; // Qt library translator
589        if (qtTranslator) {
590                qApp->removeTranslator(qtTranslator);
591                delete qtTranslator;
592                qtTranslator = NULL;
[29]593        }
[67]594static QTranslator *translator; // Application translator
595        if (translator) {
596                qApp->removeTranslator(translator);
597                delete translator;
[80]598                translator = NULL;
[37]599        }
[80]600
601        if (lng == "en")
602                return true;
603
604        // Trying to load system Qt library translation...
605        qtTranslator = new QTranslator(this);
606        if (qtTranslator->load("qt_" + lng,QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
607                qApp->installTranslator(qtTranslator);
608        else {
609                // No luck. Let's try to load a bundled one.
610                if (qtTranslator->load("qt_" + lng,PATH_I18N))
[67]611                        qApp->installTranslator(qtTranslator);
[74]612                else {
[80]613                        // Qt library translation unavailable
614                        delete qtTranslator;
615                        qtTranslator = NULL;
[74]616                }
617        }
[80]618
[74]619        // Now let's load application translation.
[80]620        translator = new QTranslator(this);
[74]621        if (translator->load(lng,PATH_I18N))
622                qApp->installTranslator(translator);
623        else {
624                delete translator;
625                translator = NULL;
[80]626                if (!ad)
627                        QMessageBox(QMessageBox::Warning,trUtf8("Language Change"),trUtf8("Unable to load translation language."),QMessageBox::Ok,this).exec();
628                return false;
[21]629        }
[67]630        return true;
[21]631}
[31]632
[67]633bool MainWindow::maybeSave()
[37]634{
[67]635        if (!isWindowModified())
636                return true;
637int res = QMessageBox(QMessageBox::Warning,trUtf8("Unsaved Changes"),trUtf8("Would you like to save changes in current task?"),QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,this).exec();
638        if (res == QMessageBox::Save)
639                return saveTask();
640        else if (res == QMessageBox::Cancel)
641                return false;
642        else
643                return true;
[37]644}
645
[74]646void MainWindow::outputMatrix(const TMatrix &matrix, QStringList &output)
[57]647{
[67]648int n = spinCities->value();
649QString line="";
650        output.append("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
651        for (int r = 0; r < n; r++) {
652                line = "<tr>";
653                for (int c = 0; c < n; c++) {
[71]654                        if (matrix.at(r).at(c) == INFINITY)
[67]655                                line += "<td align=\"center\">"INFSTR"</td>";
656                        else
[71]657                                line += "<td align=\"center\">" + QVariant(matrix.at(r).at(c)).toString() + "</td>";
[67]658                }
659                line += "</tr>";
660                output.append(line);
[57]661        }
[67]662        output.append("</table>");
[57]663}
664
[74]665void MainWindow::outputMatrix(const SStep &step, QStringList &output)
666{
667int n = spinCities->value();
668QString line="";
669        output.append("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
670        for (int r = 0; r < n; r++) {
671                line = "<tr>";
672                for (int c = 0; c < n; c++) {
673                        if (step.matrix.at(r).at(c) == INFINITY)
674                                line += "<td align=\"center\">"INFSTR"</td>";
675                        else if ((r == step.candidate.nRow) && (c == step.candidate.nCol))
676                                line += "<td align=\"center\" class=\"selected\">" + QVariant(step.matrix.at(r).at(c)).toString() + "</td>";
677                        else {
[76]678SCandidate cand;
[74]679                                cand.nRow = r;
680                                cand.nCol = c;
681                                if (step.alts.contains(cand))
682                                        line += "<td align=\"center\" class=\"alternate\">" + QVariant(step.matrix.at(r).at(c)).toString() + "</td>";
683                                else
684                                        line += "<td align=\"center\">" + QVariant(step.matrix.at(r).at(c)).toString() + "</td>";
685                        }
686                }
687                line += "</tr>";
688                output.append(line);
689        }
690        output.append("</table>");
691}
692
[80]693void MainWindow::retranslateUi(bool all)
694{
695        if (all)
696                Ui::MainWindow::retranslateUi(this);
697
698#ifndef QT_NO_PRINTER
699        actionFilePrintPreview->setText(QApplication::translate("MainWindow", "P&rint Preview...", 0, QApplication::UnicodeUTF8));
700#ifndef QT_NO_TOOLTIP
701        actionFilePrintPreview->setToolTip(QApplication::translate("MainWindow", "Preview solution results", 0, QApplication::UnicodeUTF8));
702#endif // QT_NO_TOOLTIP
703#ifndef QT_NO_STATUSTIP
704        actionFilePrintPreview->setStatusTip(QApplication::translate("MainWindow", "Preview current solution results before printing", 0, QApplication::UnicodeUTF8));
705#endif // QT_NO_STATUSTIP
706
707        actionFilePrint->setText(QApplication::translate("MainWindow", "&Print...", 0, QApplication::UnicodeUTF8));
708#ifndef QT_NO_TOOLTIP
709        actionFilePrint->setToolTip(QApplication::translate("MainWindow", "Print solution", 0, QApplication::UnicodeUTF8));
710#endif // QT_NO_TOOLTIP
711#ifndef QT_NO_STATUSTIP
712        actionFilePrint->setStatusTip(QApplication::translate("MainWindow", "Print current solution results", 0, QApplication::UnicodeUTF8));
713#endif // QT_NO_STATUSTIP
714        actionFilePrint->setShortcut(QApplication::translate("MainWindow", "Ctrl+P", 0, QApplication::UnicodeUTF8));
715#endif // QT_NO_PRINTER
716}
717
[67]718bool MainWindow::saveTask() {
719QStringList filters(trUtf8("%1 Task File").arg("TSPSG") + " (*.tspt)");
720        filters.append(trUtf8("All Files") + " (*)");
[78]721QString file;
722        if (fileName.endsWith(".tspt", Qt::CaseInsensitive))
723                file = fileName;
[67]724        else
[78]725                file = QFileInfo(fileName).canonicalPath() + "/" + QFileInfo(fileName).completeBaseName() + ".tspt";
726
[80]727#ifdef Q_OS_WINCE
728        file = QFileDialog::getSaveFileName(this, trUtf8("Task Save"), file, filters.join(";;"), NULL, QFileDialog::DontUseNativeDialog);
729#else
[78]730        file = QFileDialog::getSaveFileName(this, trUtf8("Task Save"), file, filters.join(";;"));
[80]731#endif // Q_OS_WINCE
732
[78]733        if (file.isEmpty())
[67]734                return false;
[78]735        if (tspmodel->saveTask(file)) {
736                setFileName(file);
[67]737                setWindowModified(false);
738                return true;
739        }
740        return false;
741}
742
[71]743void MainWindow::setFileName(const QString &fileName)
[31]744{
[67]745        this->fileName = fileName;
746        setWindowTitle(QString("%1[*] - %2").arg(QFileInfo(fileName).completeBaseName()).arg(trUtf8("Travelling Salesman Problem")));
[31]747}
[78]748
[80]749void MainWindow::setupUi()
750{
751        Ui::MainWindow::setupUi(this);
752
753#if QT_VERSION >= 0x040600
754        setToolButtonStyle(Qt::ToolButtonFollowStyle);
755#endif
756
757#ifndef Q_OS_WINCE
758QStatusBar *statusbar = new QStatusBar(this);
759        statusbar->setObjectName("statusbar");
760        setStatusBar(statusbar);
761#endif // Q_OS_WINCE
762
763#ifdef Q_OS_WINCE
764        //! \hack HACK: A little hack for toolbar icons to have a sane size.
765        toolBar->setIconSize(QSize(logicalDpiX() / 4, logicalDpiY() / 4));
766#endif
767
768        solutionText->document()->setDefaultFont(settings->value("Output/Font",QFont(DEF_FONT_FAMILY,DEF_FONT_SIZE)).value<QFont>());
769        solutionText->setTextColor(settings->value("Output/Color",DEF_FONT_COLOR).value<QColor>());
770        solutionText->setWordWrapMode(QTextOption::WordWrap);
771
772#ifndef QT_NO_PRINTER
773        actionFilePrintPreview = new QAction(this);
774        actionFilePrintPreview->setObjectName("actionFilePrintPreview");
775        actionFilePrintPreview->setEnabled(false);
776        actionFilePrintPreview->setIcon(QIcon(":/images/icons/document_preview.png"));
777
778        actionFilePrint = new QAction(this);
779        actionFilePrint->setObjectName("actionFilePrint");
780        actionFilePrint->setEnabled(false);
781        actionFilePrint->setIcon(QIcon(":/images/icons/fileprint.png"));
782
783        menuFile->insertAction(actionFileExit,actionFilePrintPreview);
784        menuFile->insertAction(actionFileExit,actionFilePrint);
785        menuFile->insertSeparator(actionFileExit);
786
787        toolBar->insertAction(actionSettingsPreferences,actionFilePrint);
788#endif // QT_NO_PRINTER
789
790        groupSettingsLanguageList = new QActionGroup(this);
791        actionSettingsLanguageEnglish->setData("en");
792        actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList);
793        loadLangList();
794        actionSettingsLanguageAutodetect->setChecked(settings->value("Language","").toString().isEmpty());
795
796        spinCities->setMaximum(MAX_NUM_CITIES);
797
798        retranslateUi(false);
799
800        setCentralWidget(tabWidget);
801}
802
[78]803void MainWindow::toggleSolutionActions(bool enable)
804{
805        buttonSaveSolution->setEnabled(enable);
806        actionFileSaveAsSolution->setEnabled(enable);
807        solutionText->setEnabled(enable);
808        if (!enable)
809                output.clear();
810#ifndef QT_NO_PRINTER
811        actionFilePrint->setEnabled(enable);
812        actionFilePrintPreview->setEnabled(enable);
813#endif // QT_NO_PRINTER
814}
Note: See TracBrowser for help on using the repository browser.