/* * TSPSG: TSP Solver and Generator * Copyright (C) 2007-2012 Oleksii Serdiuk * * $Id: $Format:%h %ai %an$ $ * $URL: http://tspsg.info/ $ * * This file is part of TSPSG. * * TSPSG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TSPSG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with TSPSG. If not, see . */ #include "mainwindow.h" #ifdef Q_OS_WIN32 # include "shobjidl.h" #endif #ifdef _T_T_L_ #include "_.h" _C_ _R_ _Y_ _P_ _T_ #endif /*! * \brief Class constructor. * \param parent Main Window parent widget. * * Initializes Main Window and creates its layout based on target OS. * Loads TSPSG settings and opens a task file if it was specified as a commandline parameter. */ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this); if (settings->contains("Style")) { QStyle *s = QStyleFactory::create(settings->value("Style").toString()); if (s != NULL) QApplication::setStyle(s); else settings->remove("Style"); } loadLanguage(); setupUi(); setAcceptDrops(true); initDocStyleSheet(); #ifndef QT_NO_PRINTER printer = new QPrinter(QPrinter::HighResolution); settings->beginGroup("Printer"); QPrinter::PaperSize size = qvariant_cast(settings->value("PaperSize", DEF_PAGE_SIZE)); if (size != QPrinter::Custom) { printer->setPaperSize(size); } else { printer->setPaperSize(QSizeF(settings->value("PaperWidth").toReal(), settings->value("PaperHeight").toReal()), QPrinter::Millimeter); } printer->setOrientation(qvariant_cast(settings->value("PageOrientation", DEF_PAGE_ORIENTATION))); printer->setPageMargins( settings->value("MarginLeft", DEF_MARGIN_LEFT).toReal(), settings->value("MarginTop", DEF_MARGIN_TOP).toReal(), settings->value("MarginRight", DEF_MARGIN_RIGHT).toReal(), settings->value("MarginBottom", DEF_MARGIN_BOTTOM).toReal(), QPrinter::Millimeter); settings->endGroup(); #endif // QT_NO_PRINTER #ifdef Q_OS_WINCE_WM currentGeometry = QApplication::desktop()->availableGeometry(0); // We need to react to SIP show/hide and resize the window appropriately connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), SLOT(desktopResized(int))); #endif // Q_OS_WINCE_WM connect(actionFileNew, SIGNAL(triggered()), SLOT(actionFileNewTriggered())); connect(actionFileOpen, SIGNAL(triggered()), SLOT(actionFileOpenTriggered())); connect(actionFileSave, SIGNAL(triggered()), SLOT(actionFileSaveTriggered())); connect(actionFileSaveAsTask, SIGNAL(triggered()), SLOT(actionFileSaveAsTaskTriggered())); connect(actionFileSaveAsSolution, SIGNAL(triggered()), SLOT(actionFileSaveAsSolutionTriggered())); #ifndef QT_NO_PRINTER connect(actionFilePrintPreview, SIGNAL(triggered()), SLOT(actionFilePrintPreviewTriggered())); connect(actionFilePageSetup, SIGNAL(triggered()), SLOT(actionFilePageSetupTriggered())); connect(actionFilePrint, SIGNAL(triggered()), SLOT(actionFilePrintTriggered())); #endif // QT_NO_PRINTER #ifndef HANDHELD connect(actionSettingsToolbarsConfigure, SIGNAL(triggered()), SLOT(actionSettingsToolbarsConfigureTriggered())); #endif // HANDHELD connect(actionSettingsPreferences, SIGNAL(triggered()), SLOT(actionSettingsPreferencesTriggered())); if (actionHelpCheck4Updates != NULL) connect(actionHelpCheck4Updates, SIGNAL(triggered()), SLOT(actionHelpCheck4UpdatesTriggered())); connect(actionSettingsLanguageAutodetect, SIGNAL(triggered(bool)), SLOT(actionSettingsLanguageAutodetectTriggered(bool))); connect(groupSettingsLanguageList, SIGNAL(triggered(QAction *)), SLOT(groupSettingsLanguageListTriggered(QAction *))); connect(actionSettingsStyleSystem, SIGNAL(triggered(bool)), SLOT(actionSettingsStyleSystemTriggered(bool))); connect(groupSettingsStyleList, SIGNAL(triggered(QAction*)), SLOT(groupSettingsStyleListTriggered(QAction*))); connect(actionHelpOnlineSupport, SIGNAL(triggered()), SLOT(actionHelpOnlineSupportTriggered())); connect(actionHelpReportBug, SIGNAL(triggered()), SLOT(actionHelpReportBugTriggered())); connect(actionHelpAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); connect(actionHelpAbout, SIGNAL(triggered()), SLOT(actionHelpAboutTriggered())); connect(buttonSolve, SIGNAL(clicked()), SLOT(buttonSolveClicked())); connect(buttonRandom, SIGNAL(clicked()), SLOT(buttonRandomClicked())); connect(buttonBackToTask, SIGNAL(clicked()), SLOT(buttonBackToTaskClicked())); connect(spinCities, SIGNAL(valueChanged(int)), SLOT(spinCitiesValueChanged(int))); #ifndef HANDHELD // Centering main window QRect rect = geometry(); rect.moveCenter(QApplication::desktop()->availableGeometry(this).center()); setGeometry(rect); if (settings->value("SavePos", DEF_SAVEPOS).toBool()) { // Loading of saved window state settings->beginGroup("MainWindow"); restoreGeometry(settings->value("Geometry").toByteArray()); restoreState(settings->value("State").toByteArray()); settings->endGroup(); } #endif // HANDHELD tspmodel = new CTSPModel(this); taskView->setModel(tspmodel); connect(tspmodel, SIGNAL(numCitiesChanged(int)), SLOT(numCitiesChanged(int))); connect(tspmodel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), SLOT(dataChanged(const QModelIndex &, const QModelIndex &))); connect(tspmodel, SIGNAL(layoutChanged()), SLOT(dataChanged())); if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1)))) setFileName(QCoreApplication::arguments().at(1)); else { setFileName(); spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt()); spinCitiesValueChanged(spinCities->value()); } setWindowModified(false); if (actionHelpCheck4Updates != NULL) { if (!settings->contains("Check4Updates/Enabled")) { QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); settings->setValue("Check4Updates/Enabled", QMessageBox::question(this, QCoreApplication::applicationName(), tr("Would you like %1 to automatically check for updates every %n day(s)?", "", settings->value("Check4Updates/Interval", DEF_UPDATE_CHECK_INTERVAL).toInt()).arg(QCoreApplication::applicationName()), QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes ); QApplication::restoreOverrideCursor(); } if ((settings->value("Check4Updates/Enabled", DEF_CHECK_FOR_UPDATES).toBool()) && (QDate(qvariant_cast(settings->value("Check4Updates/LastAttempt"))).daysTo(QDate::currentDate()) >= settings->value("Check4Updates/Interval", DEF_UPDATE_CHECK_INTERVAL).toInt())) { check4Updates(true); } } } MainWindow::~MainWindow() { #ifndef QT_NO_PRINTER delete printer; #endif } /* Privates **********************************************************/ void MainWindow::actionFileNewTriggered() { if (!maybeSave()) return; QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); tspmodel->clear(); setFileName(); setWindowModified(false); tabWidget->setCurrentIndex(0); solutionText->clear(); graph = QPicture(); toggleSolutionActions(false); QApplication::restoreOverrideCursor(); } void MainWindow::actionFileOpenTriggered() { if (!maybeSave()) return; QStringList filters(tr("All Supported Formats") + " (*.tspt *.zkt)"); filters.append(tr("%1 Task Files").arg("TSPSG") + " (*.tspt)"); filters.append(tr("%1 Task Files").arg("ZKomModRd") + " (*.zkt)"); filters.append(tr("All Files") + " (*)"); QString file; if ((fileName == tr("Untitled") + ".tspt") && settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) file = settings->value(OS"/LastUsed/TaskLoadPath").toString(); else file = QFileInfo(fileName).path(); QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog; file = QFileDialog::getOpenFileName(this, tr("Task Load"), file, filters.join(";;"), NULL, opts); if (file.isEmpty() || !QFileInfo(file).isFile()) return; if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) settings->setValue(OS"/LastUsed/TaskLoadPath", QFileInfo(file).path()); if (!tspmodel->loadTask(file)) return; setFileName(file); tabWidget->setCurrentIndex(0); setWindowModified(false); solutionText->clear(); toggleSolutionActions(false); } bool MainWindow::actionFileSaveTriggered() { if ((fileName == tr("Untitled") + ".tspt") || !fileName.endsWith(".tspt", Qt::CaseInsensitive)) return saveTask(); else if (tspmodel->saveTask(fileName)) { setWindowModified(false); return true; } else return false; } void MainWindow::actionFileSaveAsTaskTriggered() { saveTask(); } void MainWindow::actionFileSaveAsSolutionTriggered() { static QString selectedFile; if (selectedFile.isEmpty()) { if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) { selectedFile = settings->value(OS"/LastUsed/SolutionSavePath").toString(); } } else selectedFile = QFileInfo(selectedFile).path(); if (!selectedFile.isEmpty()) selectedFile.append("/"); if (fileName == tr("Untitled") + ".tspt") { #ifndef QT_NO_PRINTER selectedFile += "solution.pdf"; #else selectedFile += "solution.html"; #endif // QT_NO_PRINTER } else { #ifndef QT_NO_PRINTER selectedFile += QFileInfo(fileName).completeBaseName() + ".pdf"; #else selectedFile += QFileInfo(fileName).completeBaseName() + ".html"; #endif // QT_NO_PRINTER } QStringList filters; #ifndef QT_NO_PRINTER filters.append(tr("PDF Files") + " (*.pdf)"); #endif filters.append(tr("HTML Files") + " (*.html *.htm)"); filters.append(tr("Web Archive Files") + " (*.mht *.mhtml)"); filters.append(tr("OpenDocument Files") + " (*.odt)"); filters.append(tr("All Files") + " (*)"); QFileDialog::Options opts(settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog); QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"), NULL, opts); if (file.isEmpty()) return; selectedFile = file; if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) settings->setValue(OS"/LastUsed/SolutionSavePath", QFileInfo(selectedFile).path()); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); #ifndef QT_NO_PRINTER if (selectedFile.endsWith(".pdf", Qt::CaseInsensitive)) { printer->setOutputFileName(selectedFile); solutionText->document()->print(printer); printer->setOutputFileName(QString()); QApplication::restoreOverrideCursor(); return; } #endif QByteArray imgdata; bool mhtml = selectedFile.contains(QRegExp("\\.mht(ml)?$", Qt::CaseInsensitive)); bool embed = !mhtml && settings->value("Output/EmbedGraphIntoHTML", DEF_EMBED_GRAPH_INTO_HTML).toBool(); if (selectedFile.contains(QRegExp("\\.(html?|mht(ml)?)$", Qt::CaseInsensitive))) { QFile file(selectedFile); if (!file.open(QFile::WriteOnly | QFile::Text)) { QApplication::restoreOverrideCursor(); QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(file.errorString())); return; } QString html = solutionText->document()->toHtml("UTF-8"); html.replace(QRegExp("font-family:([^;]*);"), "font-family:\\1, 'DejaVu Sans Mono', 'Courier New', Courier, monospace;"); html.replace(QRegExp("