- Timestamp:
- Dec 20, 2010, 9:53:45 PM (14 years ago)
- Location:
- trunk/src
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/defaults.h
r141 r149 43 43 */ 44 44 #ifdef Q_WS_WINCE_WM 45 #define DEF_USE_NATIVE_DIALOGS false45 # define DEF_USE_NATIVE_DIALOGS false 46 46 #else 47 #define DEF_USE_NATIVE_DIALOGS true47 # define DEF_USE_NATIVE_DIALOGS true 48 48 #endif // Q_WS_WINCE_WM 49 49 //! Default for "Save main window state and position" … … 92 92 */ 93 93 #ifdef Q_WS_S60 94 #define DEF_FONT_SIZE 894 # define DEF_FONT_SIZE 8 95 95 #else 96 #define DEF_FONT_SIZE 1096 # define DEF_FONT_SIZE 10 97 97 #endif // Q_WS_S60 98 98 //! Default text color -
trunk/src/globals.cpp
r141 r149 27 27 void toggleStyle(QWidget *widget, bool enable) 28 28 { 29 30 31 32 33 29 if (enable) { 30 widget->setStyleSheet(QString("%1 {background-color: %2; border-color: %3; border-width: 1px; border-style: solid; border-radius: 3px;}").arg(widget->metaObject()->className(), widget->palette().window().color().name(), widget->palette().shadow().color().name())); 31 } else { 32 widget->setStyleSheet(QString()); 33 } 34 34 } 35 35 #endif // Q_WS_WIN32 -
trunk/src/globals.h
r143 r149 32 32 #include <QtCore> 33 33 #if QT_VERSION < 0x040500 34 #error You are using Qt version < 4.5 but minimum required version is 4.5.0. Compilation aborted.34 # error You are using Qt version < 4.5 but minimum required version is 4.5.0. Compilation aborted. 35 35 #endif 36 36 #if defined(Q_WS_WINCE_WM) || defined(Q_WS_S60) || defined(Q_WS_MAEMO_5) || defined(Q_WS_SIMULATOR) 37 38 #define HANDHELD39 #define QT_NO_STATUSTIP37 //! This is defined on handheld devices (e.g., Windows Mobile, Symbian). 38 # define HANDHELD 39 # define QT_NO_STATUSTIP 40 40 #endif 41 41 #include <QtGui> 42 42 #if defined(QT_NO_SVG) && !defined(NOSVG) 43 #define NOSVG43 # define NOSVG 44 44 #endif 45 45 #if !defined(NOSVG) 46 #include <QtSvg>46 # include <QtSvg> 47 47 #endif // NOSVG 48 48 49 49 #ifndef HANDHELD 50 #include "qttoolbardialog.h"50 # include "qttoolbardialog.h" 51 51 #endif 52 52 … … 60 60 #include "tspsolver.h" 61 61 #ifdef Q_WS_WIN32 62 63 #include "qtwin.h"62 // Vista/7 Eyecandy 63 # include "qtwin.h" 64 64 #endif // Q_WS_WIN32 65 65 … … 76 76 */ 77 77 #ifndef PATH_L10N 78 #define PATH_L10N "l10n"78 # define PATH_L10N "l10n" 79 79 #endif // PATH_L10N 80 80 /*! … … 83 83 */ 84 84 #ifndef PATH_DOCS 85 #define PATH_DOCS "help"85 # define PATH_DOCS "help" 86 86 #endif // PATH_DOCS 87 87 … … 111 111 { 112 112 double i; 113 113 return (modf(x, &i) == 0.0); 114 114 } 115 115 … … 123 123 { 124 124 #ifdef Q_WS_WIN32 125 125 return QFile::exists("updater/Update.exe"); 126 126 #else // Q_WS_WIN32 127 127 return false; 128 128 #endif // Q_WS_WIN32 129 129 } … … 143 143 144 144 #ifdef HANDHELD 145 #define ICON_SIZE "32x32"146 #define ICON_FORMAT "png"145 # define ICON_SIZE "32x32" 146 # define ICON_FORMAT "png" 147 147 #else 148 #define ICON_SIZE "128x128"149 #define ICON_FORMAT "png"148 # define ICON_SIZE "128x128" 149 # define ICON_FORMAT "png" 150 150 #endif 151 151 152 152 #if QT_VERSION >= 0x040600 153 #define GET_ICON(x) QIcon::fromTheme(x, QIcon(":/images/icons/"ICON_SIZE"/"x"."ICON_FORMAT))153 # define GET_ICON(x) QIcon::fromTheme(x, QIcon(":/images/icons/"ICON_SIZE"/"x"."ICON_FORMAT)) 154 154 #else 155 #define GET_ICON(x) QIcon(":/images/icons/"ICON_SIZE"/"x"."ICON_FORMAT)155 # define GET_ICON(x) QIcon(":/images/icons/"ICON_SIZE"/"x"."ICON_FORMAT) 156 156 #endif 157 157 … … 159 159 // Check that default number of cities is sane (<= MAX_NUM_CITIES) 160 160 #if DEF_NUM_CITIES > MAX_NUM_CITIES 161 #undef DEF_NUM_CITIES162 #define DEF_NUM_CITIES MAX_NUM_CITIES161 # undef DEF_NUM_CITIES 162 # define DEF_NUM_CITIES MAX_NUM_CITIES 163 163 #endif 164 164 // Check that maximum for random generation is sane (<= MAX_RAND_VALUE) 165 165 #if DEF_RAND_MAX > MAX_RAND_VALUE 166 #undef DEF_RAND_MAX167 #define DEF_RAND_MAX MAX_RAND_VALUE166 # undef DEF_RAND_MAX 167 # define DEF_RAND_MAX MAX_RAND_VALUE 168 168 #endif 169 169 // Check that DEF_RAND_MIN <= DEF_RAND_MAX 170 170 #if DEF_RAND_MIN > DEF_RAND_MAX 171 #undef DEF_RAND_MIN172 #define DEF_RAND_MIN DEF_RAND_MAX171 # undef DEF_RAND_MIN 172 # define DEF_RAND_MIN DEF_RAND_MAX 173 173 #endif 174 174 -
trunk/src/main.cpp
r141 r149 24 24 #include "mainwindow.h" 25 25 #if QT_VERSION < 0x040600 26 #ifdef Q_CC_MSVC27 #pragma message("WARNING: You are using Qt version < 4.6. Application will not support some non-critical features.")28 #elif defined(Q_CC_GNU)29 #warning WARNING: You are using Qt version < 4.6. Application will not support some non-critical features.30 #else31 #error You are using Qt version < 4.6. Application will not support some non-critical features. To continue, please, comment line 31 at main.cpp.32 #endif26 # ifdef Q_CC_MSVC 27 # pragma message("WARNING: You are using Qt version < 4.6. Application will not support some non-critical features.") 28 # elif defined(Q_CC_GNU) 29 # warning WARNING: You are using Qt version < 4.6. Application will not support some non-critical features. 30 # else 31 # error You are using Qt version < 4.6. Application will not support some non-critical features. To continue, please, comment line 31 at main.cpp. 32 # endif 33 33 #endif 34 34 … … 42 42 { 43 43 QApplication app(argc, argv); 44 45 46 47 48 49 50 51 44 app.setOverrideCursor(QCursor(Qt::WaitCursor)); 45 QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf8")); 46 QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8")); 47 QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8")); 48 app.setOrganizationName("Oleksii \"Lёppa\" Serdiuk"); 49 app.setOrganizationDomain("oleksii.name"); 50 app.setApplicationName("TSP Solver and Generator"); 51 app.setApplicationVersion(BUILD_VERSION); 52 52 53 54 53 // Seeding random number generator 54 qsrand(QDateTime::currentDateTime().toTime_t() ^ QCursor::pos().x() ^ QCursor::pos().y()); 55 55 56 56 #ifdef Q_WS_WINCE_WM 57 57 // Qt "leaves" unpacked .ttf files after running - let's try to delete them. 58 58 QStringList files = QDir(app.applicationDirPath(), "*.ttf").entryList(); 59 60 61 59 foreach (QString file, files) { 60 QFile::remove(file); 61 } 62 62 #endif 63 64 65 63 // Don't load the font if it is already available 64 if (!QFontDatabase().families().contains(DEF_FONT_FACE)) 65 QFontDatabase::addApplicationFont(":/files/DejaVuLGCSansMono.ttf"); 66 66 67 67 QTranslator en; 68 69 70 71 68 if (en.load("tspsg_en", PATH_L10N)) 69 app.installTranslator(&en); 70 else if (en.load("tspsg_en", ":/l10n")) 71 app.installTranslator(&en); 72 72 73 73 MainWindow mainwindow; 74 74 #ifdef HANDHELD 75 75 mainwindow.showMaximized(); 76 76 #else // HANDHELD 77 77 mainwindow.show(); 78 78 #endif // HANDHELD 79 80 79 app.restoreOverrideCursor(); 80 return app.exec(); 81 81 } -
trunk/src/mainwindow.cpp
r148 r149 25 25 26 26 #ifdef Q_WS_WIN32 27 27 #include "shobjidl.h" 28 28 #endif 29 29 … … 41 41 */ 42 42 MainWindow::MainWindow(QWidget *parent) 43 44 { 45 46 47 43 : QMainWindow(parent) 44 { 45 settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this); 46 47 if (settings->contains("Style")) { 48 48 QStyle *s = QStyleFactory::create(settings->value("Style").toString()); 49 50 51 52 53 54 55 56 57 58 59 49 if (s != NULL) 50 QApplication::setStyle(s); 51 else 52 settings->remove("Style"); 53 } 54 55 loadLanguage(); 56 setupUi(); 57 setAcceptDrops(true); 58 59 initDocStyleSheet(); 60 60 61 61 #ifndef QT_NO_PRINTER 62 62 printer = new QPrinter(QPrinter::HighResolution); 63 63 #endif // QT_NO_PRINTER 64 64 65 65 #ifdef Q_WS_WINCE_WM 66 67 68 66 currentGeometry = QApplication::desktop()->availableGeometry(0); 67 // We need to react to SIP show/hide and resize the window appropriately 68 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), SLOT(desktopResized(int))); 69 69 #endif // Q_WS_WINCE_WM 70 71 72 73 74 70 connect(actionFileNew, SIGNAL(triggered()), SLOT(actionFileNewTriggered())); 71 connect(actionFileOpen, SIGNAL(triggered()), SLOT(actionFileOpenTriggered())); 72 connect(actionFileSave, SIGNAL(triggered()), SLOT(actionFileSaveTriggered())); 73 connect(actionFileSaveAsTask, SIGNAL(triggered()), SLOT(actionFileSaveAsTaskTriggered())); 74 connect(actionFileSaveAsSolution, SIGNAL(triggered()), SLOT(actionFileSaveAsSolutionTriggered())); 75 75 #ifndef QT_NO_PRINTER 76 77 76 connect(actionFilePrintPreview, SIGNAL(triggered()), SLOT(actionFilePrintPreviewTriggered())); 77 connect(actionFilePrint, SIGNAL(triggered()), SLOT(actionFilePrintTriggered())); 78 78 #endif // QT_NO_PRINTER 79 79 #ifndef HANDHELD 80 80 connect(actionSettingsToolbarsConfigure, SIGNAL(triggered()), SLOT(actionSettingsToolbarsConfigureTriggered())); 81 81 #endif // HANDHELD 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 82 connect(actionSettingsPreferences, SIGNAL(triggered()), SLOT(actionSettingsPreferencesTriggered())); 83 if (actionHelpCheck4Updates != NULL) 84 connect(actionHelpCheck4Updates, SIGNAL(triggered()), SLOT(actionHelpCheck4UpdatesTriggered())); 85 connect(actionSettingsLanguageAutodetect, SIGNAL(triggered(bool)), SLOT(actionSettingsLanguageAutodetectTriggered(bool))); 86 connect(groupSettingsLanguageList, SIGNAL(triggered(QAction *)), SLOT(groupSettingsLanguageListTriggered(QAction *))); 87 connect(actionSettingsStyleSystem, SIGNAL(triggered(bool)), SLOT(actionSettingsStyleSystemTriggered(bool))); 88 connect(groupSettingsStyleList, SIGNAL(triggered(QAction*)), SLOT(groupSettingsStyleListTriggered(QAction*))); 89 connect(actionHelpOnlineSupport, SIGNAL(triggered()), SLOT(actionHelpOnlineSupportTriggered())); 90 connect(actionHelpReportBug, SIGNAL(triggered()), SLOT(actionHelpReportBugTriggered())); 91 connect(actionHelpAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); 92 connect(actionHelpAbout, SIGNAL(triggered()), SLOT(actionHelpAboutTriggered())); 93 94 connect(buttonSolve, SIGNAL(clicked()), SLOT(buttonSolveClicked())); 95 connect(buttonRandom, SIGNAL(clicked()), SLOT(buttonRandomClicked())); 96 connect(buttonBackToTask, SIGNAL(clicked()), SLOT(buttonBackToTaskClicked())); 97 connect(spinCities, SIGNAL(valueChanged(int)), SLOT(spinCitiesValueChanged(int))); 98 98 99 99 #ifndef HANDHELD 100 100 // Centering main window 101 101 QRect rect = geometry(); 102 103 104 105 106 107 108 109 110 102 rect.moveCenter(QApplication::desktop()->availableGeometry(this).center()); 103 setGeometry(rect); 104 if (settings->value("SavePos", DEF_SAVEPOS).toBool()) { 105 // Loading of saved window state 106 settings->beginGroup("MainWindow"); 107 restoreGeometry(settings->value("Geometry").toByteArray()); 108 restoreState(settings->value("State").toByteArray()); 109 settings->endGroup(); 110 } 111 111 #endif // HANDHELD 112 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 113 tspmodel = new CTSPModel(this); 114 taskView->setModel(tspmodel); 115 connect(tspmodel, SIGNAL(numCitiesChanged(int)), SLOT(numCitiesChanged(int))); 116 connect(tspmodel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), SLOT(dataChanged(const QModelIndex &, const QModelIndex &))); 117 connect(tspmodel, SIGNAL(layoutChanged()), SLOT(dataChanged())); 118 if ((QCoreApplication::arguments().count() > 1) && (tspmodel->loadTask(QCoreApplication::arguments().at(1)))) 119 setFileName(QCoreApplication::arguments().at(1)); 120 else { 121 setFileName(); 122 spinCities->setValue(settings->value("NumCities",DEF_NUM_CITIES).toInt()); 123 spinCitiesValueChanged(spinCities->value()); 124 } 125 setWindowModified(false); 126 127 if (actionHelpCheck4Updates != NULL) { 128 if (!settings->contains("Check4Updates/Enabled")) { 129 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 130 settings->setValue("Check4Updates/Enabled", 131 QMessageBox::question(this, QCoreApplication::applicationName(), 132 tr("Would you like %1 to automatically check for updates every %n day(s)?", "", settings->value("Check4Updates/Interval", DEF_UPDATE_CHECK_INTERVAL).toInt()).arg(QCoreApplication::applicationName()), 133 QMessageBox::Yes | QMessageBox::No 134 ) == QMessageBox::Yes 135 ); 136 QApplication::restoreOverrideCursor(); 137 } 138 if ((settings->value("Check4Updates/Enabled", DEF_CHECK_FOR_UPDATES).toBool()) 139 && (QDate(qvariant_cast<QDate>(settings->value("Check4Updates/LastAttempt"))).daysTo(QDate::currentDate()) >= settings->value("Check4Updates/Interval", DEF_UPDATE_CHECK_INTERVAL).toInt())) { 140 check4Updates(true); 141 } 142 } 143 143 } 144 144 … … 146 146 { 147 147 #ifndef QT_NO_PRINTER 148 148 delete printer; 149 149 #endif 150 150 } … … 154 154 void MainWindow::actionFileNewTriggered() 155 155 { 156 157 158 159 160 161 162 163 164 165 156 if (!maybeSave()) 157 return; 158 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 159 tspmodel->clear(); 160 setFileName(); 161 setWindowModified(false); 162 tabWidget->setCurrentIndex(0); 163 solutionText->clear(); 164 toggleSolutionActions(false); 165 QApplication::restoreOverrideCursor(); 166 166 } 167 167 168 168 void MainWindow::actionFileOpenTriggered() 169 169 { 170 171 170 if (!maybeSave()) 171 return; 172 172 173 173 QStringList filters(tr("All Supported Formats") + " (*.tspt *.zkt)"); 174 175 176 174 filters.append(tr("%1 Task Files").arg("TSPSG") + " (*.tspt)"); 175 filters.append(tr("%1 Task Files").arg("ZKomModRd") + " (*.zkt)"); 176 filters.append(tr("All Files") + " (*)"); 177 177 178 178 QString file; 179 180 181 182 179 if ((fileName == tr("Untitled") + ".tspt") && settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) 180 file = settings->value(OS"/LastUsed/TaskLoadPath").toString(); 181 else 182 file = QFileInfo(fileName).path(); 183 183 QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog; 184 185 186 187 188 189 190 191 192 193 194 195 196 184 file = QFileDialog::getOpenFileName(this, tr("Task Load"), file, filters.join(";;"), NULL, opts); 185 if (file.isEmpty() || !QFileInfo(file).isFile()) 186 return; 187 if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) 188 settings->setValue(OS"/LastUsed/TaskLoadPath", QFileInfo(file).path()); 189 190 if (!tspmodel->loadTask(file)) 191 return; 192 setFileName(file); 193 tabWidget->setCurrentIndex(0); 194 setWindowModified(false); 195 solutionText->clear(); 196 toggleSolutionActions(false); 197 197 } 198 198 199 199 bool MainWindow::actionFileSaveTriggered() 200 200 { 201 202 203 204 205 206 207 208 201 if ((fileName == tr("Untitled") + ".tspt") || !fileName.endsWith(".tspt", Qt::CaseInsensitive)) 202 return saveTask(); 203 else 204 if (tspmodel->saveTask(fileName)) { 205 setWindowModified(false); 206 return true; 207 } else 208 return false; 209 209 } 210 210 211 211 void MainWindow::actionFileSaveAsTaskTriggered() 212 212 { 213 213 saveTask(); 214 214 } 215 215 … … 217 217 { 218 218 static QString selectedFile; 219 220 221 222 223 224 225 226 227 219 if (selectedFile.isEmpty()) { 220 if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) { 221 selectedFile = settings->value(OS"/LastUsed/SolutionSavePath").toString(); 222 } 223 } else 224 selectedFile = QFileInfo(selectedFile).path(); 225 if (!selectedFile.isEmpty()) 226 selectedFile.append("/"); 227 if (fileName == tr("Untitled") + ".tspt") { 228 228 #ifndef QT_NO_PRINTER 229 229 selectedFile += "solution.pdf"; 230 230 #else 231 231 selectedFile += "solution.html"; 232 232 #endif // QT_NO_PRINTER 233 233 } else { 234 234 #ifndef QT_NO_PRINTER 235 235 selectedFile += QFileInfo(fileName).completeBaseName() + ".pdf"; 236 236 #else 237 237 selectedFile += QFileInfo(fileName).completeBaseName() + ".html"; 238 238 #endif // QT_NO_PRINTER 239 239 } 240 240 241 241 QStringList filters; 242 242 #ifndef QT_NO_PRINTER 243 244 #endif 245 246 247 243 filters.append(tr("PDF Files") + " (*.pdf)"); 244 #endif 245 filters.append(tr("HTML Files") + " (*.html *.htm)"); 246 filters.append(tr("OpenDocument Files") + " (*.odt)"); 247 filters.append(tr("All Files") + " (*)"); 248 248 249 249 QFileDialog::Options opts(settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog); 250 250 QString file = QFileDialog::getSaveFileName(this, QString(), selectedFile, filters.join(";;"), NULL, opts); 251 252 253 254 255 256 251 if (file.isEmpty()) 252 return; 253 selectedFile = file; 254 if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) 255 settings->setValue(OS"/LastUsed/SolutionSavePath", QFileInfo(selectedFile).path()); 256 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 257 257 #ifndef QT_NO_PRINTER 258 258 if (selectedFile.endsWith(".pdf",Qt::CaseInsensitive)) { 259 259 QPrinter printer(QPrinter::HighResolution); 260 261 262 263 264 265 266 #endif 267 260 printer.setOutputFormat(QPrinter::PdfFormat); 261 printer.setOutputFileName(selectedFile); 262 solutionText->document()->print(&printer); 263 QApplication::restoreOverrideCursor(); 264 return; 265 } 266 #endif 267 if (selectedFile.endsWith(".htm", Qt::CaseInsensitive) || selectedFile.endsWith(".html", Qt::CaseInsensitive)) { 268 268 QFile file(selectedFile); 269 270 271 272 273 269 if (!file.open(QFile::WriteOnly)) { 270 QApplication::restoreOverrideCursor(); 271 QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(file.errorString())); 272 return; 273 } 274 274 QFileInfo fi(selectedFile); 275 275 QString format = settings->value("Output/GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT).toString(); 276 276 #if !defined(NOSVG) 277 277 if (!QImageWriter::supportedImageFormats().contains(format.toAscii()) && (format != "svg")) { 278 278 #else // NOSVG 279 279 if (!QImageWriter::supportedImageFormats().contains(format.toAscii())) { 280 280 #endif // NOSVG 281 282 283 281 format = DEF_GRAPH_IMAGE_FORMAT; 282 settings->remove("Output/GraphImageFormat"); 283 } 284 284 QString html = solutionText->document()->toHtml("UTF-8"), 285 286 287 288 289 285 img = fi.completeBaseName() + "." + format; 286 html.replace(QRegExp("font-family:([^;]*);"), "font-family:\\1, 'DejaVu Sans Mono', 'Courier New', Courier, monospace;"); 287 html.replace(QRegExp("<img\\s+src=\"tspsg://graph.pic\""), QString("<img src=\"%1\" alt=\"%2\"").arg(img, tr("Solution Graph"))); 288 289 // Saving solution text as HTML 290 290 QTextStream ts(&file); 291 292 293 294 295 291 ts.setCodec(QTextCodec::codecForName("UTF-8")); 292 ts << html; 293 file.close(); 294 295 // Saving solution graph as SVG or PNG (depending on settings and SVG support) 296 296 #if !defined(NOSVG) 297 297 if (format == "svg") { 298 298 QSvgGenerator svg; 299 300 301 302 303 299 svg.setSize(QSize(graph.width() + 2, graph.height() + 2)); 300 svg.setResolution(graph.logicalDpiX()); 301 svg.setFileName(fi.path() + "/" + img); 302 svg.setTitle(tr("Solution Graph")); 303 svg.setDescription(tr("Generated with %1").arg(QCoreApplication::applicationName())); 304 304 QPainter p; 305 306 307 308 305 p.begin(&svg); 306 p.drawPicture(1, 1, graph); 307 p.end(); 308 } else { 309 309 #endif // NOSVG 310 310 QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_ARGB32); 311 311 i.fill(0x00FFFFFF); 312 312 QPainter p; 313 314 315 313 p.begin(&i); 314 p.drawPicture(1, 1, graph); 315 p.end(); 316 316 QImageWriter pic(fi.path() + "/" + img); 317 318 319 320 321 322 323 324 325 326 327 328 329 317 if (pic.supportsOption(QImageIOHandler::Description)) { 318 pic.setText("Title", "Solution Graph"); 319 pic.setText("Software", QCoreApplication::applicationName()); 320 } 321 if (format == "png") 322 pic.setQuality(5); 323 else if (format == "jpeg") 324 pic.setQuality(80); 325 if (!pic.write(i)) { 326 QApplication::restoreOverrideCursor(); 327 QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution graph.\nError: %1").arg(pic.errorString())); 328 return; 329 } 330 330 #if !defined(NOSVG) 331 331 } 332 332 #endif // NOSVG 333 333 } else { 334 334 QTextDocumentWriter dw(selectedFile); 335 336 337 338 339 340 335 if (!selectedFile.endsWith(".odt",Qt::CaseInsensitive)) 336 dw.setFormat("plaintext"); 337 if (!dw.write(solutionText->document())) 338 QMessageBox::critical(this, tr("Solution Save"), tr("Unable to save the solution.\nError: %1").arg(dw.device()->errorString())); 339 } 340 QApplication::restoreOverrideCursor(); 341 341 } 342 342 … … 345 345 { 346 346 QPrintPreviewDialog ppd(printer, this); 347 348 347 connect(&ppd,SIGNAL(paintRequested(QPrinter *)),SLOT(printPreview(QPrinter *))); 348 ppd.exec(); 349 349 } 350 350 … … 352 352 { 353 353 QPrintDialog pd(printer,this); 354 355 356 357 358 354 if (pd.exec() != QDialog::Accepted) 355 return; 356 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 357 solutionText->print(printer); 358 QApplication::restoreOverrideCursor(); 359 359 } 360 360 #endif // QT_NO_PRINTER … … 363 363 { 364 364 SettingsDialog sd(this); 365 366 367 368 369 370 371 372 373 365 if (sd.exec() != QDialog::Accepted) 366 return; 367 if (sd.colorChanged() || sd.fontChanged()) { 368 if (!solutionText->document()->isEmpty() && sd.colorChanged()) 369 QMessageBox::information(this, tr("Settings Changed"), tr("You have changed color settings.\nThey will be applied to the next solution output.")); 370 initDocStyleSheet(); 371 } 372 if (sd.translucencyChanged() != 0) 373 toggleTranclucency(sd.translucencyChanged() == 1); 374 374 } 375 375 376 376 void MainWindow::actionSettingsLanguageAutodetectTriggered(bool checked) 377 377 { 378 379 380 381 382 378 if (checked) { 379 settings->remove("Language"); 380 QMessageBox::information(this, tr("Language change"), tr("Language will be autodetected on the next %1 start.").arg(QCoreApplication::applicationName())); 381 } else 382 settings->setValue("Language", groupSettingsLanguageList->checkedAction()->data().toString()); 383 383 } 384 384 … … 386 386 { 387 387 #ifndef Q_WS_MAEMO_5 388 389 388 if (actionSettingsLanguageAutodetect->isChecked()) 389 actionSettingsLanguageAutodetect->trigger(); 390 390 #endif 391 391 bool untitled = (fileName == tr("Untitled") + ".tspt"); 392 393 394 395 396 397 398 #ifdef Q_WS_WIN32 399 400 401 402 403 #endif 404 405 406 407 392 if (loadLanguage(action->data().toString())) { 393 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 394 settings->setValue("Language",action->data().toString()); 395 retranslateUi(); 396 if (untitled) 397 setFileName(); 398 #ifdef Q_WS_WIN32 399 if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool()) { 400 toggleStyle(labelVariant, true); 401 toggleStyle(labelCities, true); 402 } 403 #endif 404 QApplication::restoreOverrideCursor(); 405 if (!solutionText->document()->isEmpty()) 406 QMessageBox::information(this, tr("Settings Changed"), tr("You have changed the application language.\nTo get current solution output in the new language\nyou need to re-run the solution process.")); 407 } 408 408 } 409 409 410 410 void MainWindow::actionSettingsStyleSystemTriggered(bool checked) 411 411 { 412 413 414 415 416 417 412 if (checked) { 413 settings->remove("Style"); 414 QMessageBox::information(this, tr("Style Change"), tr("To apply the default style you need to restart %1.").arg(QCoreApplication::applicationName())); 415 } else { 416 settings->setValue("Style", groupSettingsStyleList->checkedAction()->text()); 417 } 418 418 } 419 419 … … 421 421 { 422 422 QStyle *s = QStyleFactory::create(action->text()); 423 424 425 426 427 423 if (s != NULL) { 424 QApplication::setStyle(s); 425 settings->setValue("Style", action->text()); 426 actionSettingsStyleSystem->setChecked(false); 427 } 428 428 } 429 429 … … 432 432 { 433 433 QtToolBarDialog dlg(this); 434 435 434 dlg.setToolBarManager(toolBarManager); 435 dlg.exec(); 436 436 QToolButton *tb = static_cast<QToolButton *>(toolBarMain->widgetForAction(actionFileSave)); 437 438 439 440 441 442 443 437 if (tb != NULL) { 438 tb->setMenu(menuFileSaveAs); 439 tb->setPopupMode(QToolButton::MenuButtonPopup); 440 tb->resize(tb->sizeHint()); 441 } 442 443 loadToolbarList(); 444 444 } 445 445 #endif // HANDHELD … … 447 447 void MainWindow::actionHelpCheck4UpdatesTriggered() 448 448 { 449 450 451 452 453 454 449 if (!hasUpdater()) { 450 QMessageBox::warning(this, tr("Unsupported Feature"), tr("Sorry, but this feature is not supported on your platform\nor support for this feature was not installed.")); 451 return; 452 } 453 454 check4Updates(); 455 455 } 456 456 457 457 void MainWindow::actionHelpAboutTriggered() 458 458 { 459 459 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 460 460 461 461 QString title; 462 463 462 title += QString("<b>%1</b><br>").arg(QCoreApplication::applicationName()); 463 title += QString("%1: <b>%2</b><br>").arg(tr("Version"), QCoreApplication::applicationVersion()); 464 464 #ifndef HANDHELD 465 465 title += QString("<b>© 2007-%1 <a href=\"http://%2/\">%3</a></b><br>").arg(QDate::currentDate().toString("yyyy"), QCoreApplication::organizationDomain(), QCoreApplication::organizationName()); 466 466 #endif // HANDHELD 467 467 title += QString("<b><a href=\"http://tspsg.info/\">http://tspsg.info/</a></b>"); 468 468 469 469 QString about; 470 470 about += QString("%1: <b>%2</b><br>").arg(tr("Target OS (ARCH)"), PLATFROM); 471 471 #ifndef STATIC_BUILD 472 473 474 472 about += QString("%1 (%2):<br>").arg(tr("Qt library"), tr("shared")); 473 about += QString(" %1: <b>%2</b><br>").arg(tr("Build time"), QT_VERSION_STR); 474 about += QString(" %1: <b>%2</b><br>").arg(tr("Runtime"), qVersion()); 475 475 #else 476 476 about += QString("%1: <b>%2</b> (%3)<br>").arg(tr("Qt library"), QT_VERSION_STR, tr("static")); 477 477 #endif // STATIC_BUILD 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 478 about += tr("Buid <b>%1</b>, built on <b>%2</b> at <b>%3</b> with <b>%4</b> compiler.").arg(BUILD_NUMBER).arg(__DATE__).arg(__TIME__).arg(COMPILER) + "<br>"; 479 about += QString("%1: <b>%2</b><br>").arg(tr("Algorithm"), CTSPSolver::getVersionId()); 480 about += "<br>"; 481 about += tr("This program is free software: you can redistribute it and/or modify<br>\n" 482 "it under the terms of the GNU General Public License as published by<br>\n" 483 "the Free Software Foundation, either version 3 of the License, or<br>\n" 484 "(at your option) any later version.<br>\n" 485 "<br>\n" 486 "This program is distributed in the hope that it will be useful,<br>\n" 487 "but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\n" 488 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>\n" 489 "GNU General Public License for more details.<br>\n" 490 "<br>\n" 491 "You should have received a copy of the GNU General Public License<br>\n" 492 "along with TSPSG. If not, see <a href=\"http://www.gnu.org/licenses/\">www.gnu.org/licenses/</a>."); 493 493 494 494 QString credits; 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 495 credits += tr("%1 was created using <b>Qt framework</b> licensed " 496 "under the terms of the GNU Lesser General Public License,<br>\n" 497 "see <a href=\"http://qt.nokia.com/\">qt.nokia.com</a><br>\n" 498 "<br>\n" 499 "Most icons used in %1 are part of <b>Oxygen Icons</b> project " 500 "licensed according to the GNU Lesser General Public License,<br>\n" 501 "see <a href=\"http://www.oxygen-icons.org/\">www.oxygen-icons.org</a><br>\n" 502 "<br>\n" 503 "Country flag icons used in %1 are part of the free " 504 "<b>Flag Icons</b> collection created by <b>IconDrawer</b>,<br>\n" 505 "see <a href=\"http://www.icondrawer.com/\">www.icondrawer.com</a><br>\n" 506 "<br>\n" 507 "%1 comes with the default \"embedded\" font <b>DejaVu LGC Sans " 508 "Mono</b> from the <b>DejaVu fonts</b> licensed under a Free license</a>,<br>\n" 509 "see <a href=\"http://dejavu-fonts.org/\">dejavu-fonts.org</a>") 510 .arg("TSPSG"); 511 511 512 512 QFile f(":/files/COPYING"); 513 513 f.open(QIODevice::ReadOnly); 514 514 515 515 QString translation = QCoreApplication::translate("--------", "AUTHORS %1", "Please, provide translator credits here. %1 will be replaced with VERSION"); 516 516 if ((translation != "AUTHORS %1") && (translation.contains("%1"))) { 517 517 QString about = QCoreApplication::translate("--------", "VERSION", "Please, provide your translation version here."); 518 519 520 518 if (about != "VERSION") 519 translation = translation.arg(about); 520 } 521 521 522 522 QDialog *dlg = new QDialog(this); 523 523 QLabel *lblIcon = new QLabel(dlg), 524 524 *lblTitle = new QLabel(dlg); 525 525 #ifdef HANDHELD 526 526 QLabel *lblSubTitle = new QLabel(QString("<b>© 2007-%1 <a href=\"http://%2/\">%3</a></b>").arg(QDate::currentDate().toString("yyyy"), QCoreApplication::organizationDomain(), QCoreApplication::organizationName()), dlg); … … 532 532 QVBoxLayout *vb = new QVBoxLayout(); 533 533 QHBoxLayout *hb1 = new QHBoxLayout(), 534 534 *hb2 = new QHBoxLayout(); 535 535 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dlg); 536 536 537 538 539 540 537 lblTitle->setOpenExternalLinks(true); 538 lblTitle->setText(title); 539 lblTitle->setAlignment(Qt::AlignTop); 540 lblTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); 541 541 #ifndef HANDHELD 542 542 lblTitle->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 4px; padding: 1px;}").arg(palette().alternateBase().color().name(), palette().shadow().color().name())); 543 543 #endif // HANDHELD 544 544 545 546 545 lblIcon->setPixmap(QPixmap(":/images/tspsg.png").scaledToHeight(lblTitle->sizeHint().height(), Qt::SmoothTransformation)); 546 lblIcon->setAlignment(Qt::AlignVCenter); 547 547 #ifndef HANDHELD 548 548 lblIcon->setStyleSheet(QString("QLabel {background-color: white; border-color: %1; border-width: 1px; border-style: solid; border-radius: 4px; padding: 1px;}").arg(palette().windowText().color().name())); 549 549 #endif // HANDHELD 550 550 551 552 553 554 555 556 557 558 551 hb1->addWidget(lblIcon); 552 hb1->addWidget(lblTitle); 553 554 txtAbout->setWordWrapMode(QTextOption::NoWrap); 555 txtAbout->setOpenExternalLinks(true); 556 txtAbout->setHtml(about); 557 txtAbout->moveCursor(QTextCursor::Start); 558 txtAbout->setFrameShape(QFrame::NoFrame); 559 559 560 560 // txtCredits->setWordWrapMode(QTextOption::NoWrap); 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 561 txtCredits->setOpenExternalLinks(true); 562 txtCredits->setHtml(credits); 563 txtCredits->moveCursor(QTextCursor::Start); 564 txtCredits->setFrameShape(QFrame::NoFrame); 565 566 txtLicense->setWordWrapMode(QTextOption::NoWrap); 567 txtLicense->setOpenExternalLinks(true); 568 txtLicense->setText(f.readAll()); 569 txtLicense->moveCursor(QTextCursor::Start); 570 txtLicense->setFrameShape(QFrame::NoFrame); 571 572 bb->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor)); 573 bb->button(QDialogButtonBox::Ok)->setIcon(GET_ICON("dialog-ok")); 574 575 hb2->addWidget(bb); 576 576 577 577 #ifdef Q_WS_WINCE_WM 578 578 vb->setMargin(3); 579 579 #endif // Q_WS_WINCE_WM 580 580 vb->addLayout(hb1); 581 581 #ifdef HANDHELD 582 582 vb->addWidget(lblSubTitle); 583 583 #endif // HANDHELD 584 584 585 586 587 588 585 tabs->addTab(txtAbout, tr("About")); 586 tabs->addTab(txtLicense, tr("License")); 587 tabs->addTab(txtCredits, tr("Credits")); 588 if (translation != "AUTHORS %1") { 589 589 QTextBrowser *txtTranslation = new QTextBrowser(dlg); 590 590 // txtTranslation->setWordWrapMode(QTextOption::NoWrap); 591 592 593 594 595 596 597 591 txtTranslation->setOpenExternalLinks(true); 592 txtTranslation->setText(translation); 593 txtTranslation->moveCursor(QTextCursor::Start); 594 txtTranslation->setFrameShape(QFrame::NoFrame); 595 596 tabs->addTab(txtTranslation, tr("Translation")); 597 } 598 598 #ifndef HANDHELD 599 599 tabs->setStyleSheet(QString("QTabWidget::pane {background-color: %1; border-color: %3; border-width: 1px; border-style: solid; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; padding: 1px;} QTabBar::tab {background-color: %2; border-color: %3; border-width: 1px; border-style: solid; border-bottom: none; border-top-left-radius: 4px; border-top-right-radius: 4px; padding: 2px 6px;} QTabBar::tab:selected {background-color: %4;} QTabBar::tab:!selected {margin-top: 1px;}").arg(palette().base().color().name(), palette().button().color().name(), palette().shadow().color().name(), palette().light().color().name())); 600 600 #endif // HANDHELD 601 601 602 603 604 605 606 607 608 609 610 611 612 #ifdef Q_WS_WIN32 613 614 615 616 602 vb->addWidget(tabs); 603 vb->addLayout(hb2); 604 605 dlg->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); 606 dlg->setWindowTitle(tr("About %1").arg(QCoreApplication::applicationName())); 607 dlg->setWindowIcon(GET_ICON("help-about")); 608 dlg->setLayout(vb); 609 610 connect(bb, SIGNAL(accepted()), dlg, SLOT(accept())); 611 612 #ifdef Q_WS_WIN32 613 // Adding some eyecandy in Vista and 7 :-) 614 if (QtWin::isCompositionEnabled()) { 615 QtWin::enableBlurBehindWindow(dlg, true); 616 } 617 617 #endif // Q_WS_WIN32 618 618 619 620 621 622 623 624 619 dlg->resize(450, 350); 620 QApplication::restoreOverrideCursor(); 621 622 dlg->exec(); 623 624 delete dlg; 625 625 } 626 626 627 627 void MainWindow::buttonBackToTaskClicked() 628 628 { 629 629 tabWidget->setCurrentIndex(0); 630 630 } 631 631 632 632 void MainWindow::buttonRandomClicked() 633 633 { 634 635 636 634 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 635 tspmodel->randomize(); 636 QApplication::restoreOverrideCursor(); 637 637 } 638 638 … … 643 643 int n = spinCities->value(); 644 644 bool ok; 645 646 647 648 649 650 651 652 653 654 655 645 for (int r = 0; r < n; r++) { 646 row.clear(); 647 for (int c = 0; c < n; c++) { 648 row.append(tspmodel->index(r,c).data(Qt::UserRole).toDouble(&ok)); 649 if (!ok) { 650 QMessageBox::critical(this, tr("Data error"), tr("Error in cell [Row %1; Column %2]: Invalid data format.").arg(r + 1).arg(c + 1)); 651 return; 652 } 653 } 654 matrix.append(row); 655 } 656 656 657 657 QProgressDialog pd(this); 658 658 QProgressBar *pb = new QProgressBar(&pd); 659 660 661 659 pb->setAlignment(Qt::AlignCenter); 660 pb->setFormat(tr("%v of %1 parts found").arg(n)); 661 pd.setBar(pb); 662 662 QPushButton *cancel = new QPushButton(&pd); 663 664 665 666 667 668 669 670 671 672 663 cancel->setIcon(GET_ICON("dialog-cancel")); 664 cancel->setText(QCoreApplication::translate("QProgressDialog", "Cancel", "No need to translate this. This translation will be taken from Qt translation files.")); 665 pd.setCancelButton(cancel); 666 pd.setMaximum(n); 667 pd.setAutoReset(false); 668 pd.setLabelText(tr("Calculating optimal route...")); 669 pd.setWindowTitle(tr("Solution Progress")); 670 pd.setWindowModality(Qt::ApplicationModal); 671 pd.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); 672 pd.show(); 673 673 674 674 #ifdef Q_WS_WIN32 675 675 HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID*)&tl); 676 677 678 679 680 681 676 if (SUCCEEDED(hr)) { 677 hr = tl->HrInit(); 678 if (FAILED(hr)) { 679 tl->Release(); 680 tl = NULL; 681 } else { 682 682 // tl->SetProgressState(winId(), TBPF_INDETERMINATE); 683 684 685 683 tl->SetProgressValue(winId(), 0, n * 2); 684 } 685 } 686 686 #endif 687 687 688 688 CTSPSolver solver; 689 690 691 692 #ifdef Q_WS_WIN32 693 694 689 solver.setCleanupOnCancel(false); 690 connect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int))); 691 connect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel())); 692 #ifdef Q_WS_WIN32 693 if (tl != NULL) 694 connect(&solver, SIGNAL(routePartFound(int)), SLOT(solverRoutePartFound(int))); 695 695 #endif 696 696 SStep *root = solver.solve(n, matrix); 697 697 #ifdef Q_WS_WIN32 698 699 700 #endif 701 702 703 704 705 706 #ifdef Q_WS_WIN32 707 698 if (tl != NULL) 699 disconnect(&solver, SIGNAL(routePartFound(int)), this, SLOT(solverRoutePartFound(int))); 700 #endif 701 disconnect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int))); 702 disconnect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel())); 703 if (!root) { 704 pd.reset(); 705 if (!solver.wasCanceled()) { 706 #ifdef Q_WS_WIN32 707 if (tl != NULL) { 708 708 // tl->SetProgressValue(winId(), n, n * 2); 709 710 711 #endif 712 713 714 715 716 717 718 719 #ifdef Q_WS_WIN32 720 721 722 #endif 723 709 tl->SetProgressState(winId(), TBPF_ERROR); 710 } 711 #endif 712 QApplication::alert(this); 713 QMessageBox::warning(this, tr("Solution Result"), tr("Unable to find a solution.\nMaybe, this task has no solution.")); 714 } 715 pd.setLabelText(tr("Cleaning up...")); 716 pd.setMaximum(0); 717 pd.setCancelButton(NULL); 718 pd.show(); 719 #ifdef Q_WS_WIN32 720 if (tl != NULL) 721 tl->SetProgressState(winId(), TBPF_INDETERMINATE); 722 #endif 723 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 724 724 725 725 #ifndef QT_NO_CONCURRENT 726 726 QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false); 727 728 729 727 while (!f.isFinished()) { 728 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 729 } 730 730 #else 731 732 #endif 733 734 #ifdef Q_WS_WIN32 735 736 737 738 739 740 #endif 741 742 743 744 745 746 747 748 #ifdef Q_WS_WIN32 749 750 751 #endif 752 753 754 731 solver.cleanup(true); 732 #endif 733 pd.reset(); 734 #ifdef Q_WS_WIN32 735 if (tl != NULL) { 736 tl->SetProgressState(winId(), TBPF_NOPROGRESS); 737 tl->Release(); 738 tl = NULL; 739 } 740 #endif 741 return; 742 } 743 pb->setFormat(tr("Generating header")); 744 pd.setLabelText(tr("Generating solution output...")); 745 pd.setMaximum(solver.getTotalSteps() + 1); 746 pd.setValue(0); 747 748 #ifdef Q_WS_WIN32 749 if (tl != NULL) 750 tl->SetProgressValue(winId(), spinCities->value(), spinCities->value() + solver.getTotalSteps() + 1); 751 #endif 752 753 solutionText->clear(); 754 solutionText->setDocumentTitle(tr("Solution of Variant #%1 Task").arg(spinVariant->value())); 755 755 756 756 QPainter pic; 757 758 759 757 if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) { 758 pic.begin(&graph); 759 pic.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); 760 760 QFont font = qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE, 9))); 761 762 763 764 765 766 767 761 if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) { 762 font.setWeight(QFont::DemiBold); 763 font.setPointSizeF(font.pointSizeF() * 2); 764 } 765 pic.setFont(font); 766 pic.setBrush(QBrush(QColor(Qt::white))); 767 if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) { 768 768 QPen pen = pic.pen(); 769 770 771 772 773 769 pen.setWidth(2); 770 pic.setPen(pen); 771 } 772 pic.setBackgroundMode(Qt::OpaqueMode); 773 } 774 774 775 775 QTextDocument *doc = solutionText->document(); 776 776 QTextCursor cur(doc); 777 777 778 779 780 781 782 783 784 778 cur.beginEditBlock(); 779 cur.setBlockFormat(fmt_paragraph); 780 cur.insertText(tr("Variant #%1 Task").arg(spinVariant->value()), fmt_default); 781 cur.insertBlock(fmt_paragraph); 782 cur.insertText(tr("Task:")); 783 outputMatrix(cur, matrix); 784 if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) { 785 785 #ifdef _T_T_L_ 786 787 #endif 788 789 790 791 786 _b_ _i_ _z_ _a_ _r_ _r_ _e_ 787 #endif 788 drawNode(pic, 0); 789 } 790 cur.insertHtml("<hr>"); 791 cur.insertBlock(fmt_paragraph); 792 792 int imgpos = cur.position(); 793 794 793 cur.insertText(tr("Variant #%1 Solution").arg(spinVariant->value()), fmt_default); 794 cur.endEditBlock(); 795 795 796 796 SStep *step = root; 797 797 int c = n = 1; 798 799 800 801 802 803 804 805 806 #ifdef Q_WS_WIN32 807 808 798 pb->setFormat(tr("Generating step %v")); 799 while ((step->next != SStep::NoNextStep) && (c < spinCities->value())) { 800 if (pd.wasCanceled()) { 801 pd.setLabelText(tr("Cleaning up...")); 802 pd.setMaximum(0); 803 pd.setCancelButton(NULL); 804 pd.show(); 805 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 806 #ifdef Q_WS_WIN32 807 if (tl != NULL) 808 tl->SetProgressState(winId(), TBPF_INDETERMINATE); 809 809 #endif 810 810 #ifndef QT_NO_CONCURRENT 811 811 QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false); 812 813 814 812 while (!f.isFinished()) { 813 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 814 } 815 815 #else 816 817 #endif 818 819 820 #ifdef Q_WS_WIN32 821 822 823 824 825 826 #endif 827 828 829 830 #ifdef Q_WS_WIN32 831 832 833 #endif 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 #ifdef Q_WS_WIN32 877 878 879 #endif 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 816 solver.cleanup(true); 817 #endif 818 solutionText->clear(); 819 toggleSolutionActions(false); 820 #ifdef Q_WS_WIN32 821 if (tl != NULL) { 822 tl->SetProgressState(winId(), TBPF_NOPROGRESS); 823 tl->Release(); 824 tl = NULL; 825 } 826 #endif 827 return; 828 } 829 pd.setValue(n); 830 #ifdef Q_WS_WIN32 831 if (tl != NULL) 832 tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1); 833 #endif 834 835 cur.beginEditBlock(); 836 cur.insertBlock(fmt_paragraph); 837 cur.insertText(tr("Step #%1").arg(n)); 838 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())))) { 839 outputMatrix(cur, *step); 840 } 841 cur.insertBlock(fmt_paragraph); 842 cur.insertText(tr("Selected route %1 %2 part.").arg((step->next == SStep::RightBranch) ? tr("with") : tr("without")).arg(tr("(%1;%2)").arg(step->candidate.nRow + 1).arg(step->candidate.nCol + 1)), fmt_default); 843 if (!step->alts.empty()) { 844 SStep::SCandidate cand; 845 QString alts; 846 foreach(cand, step->alts) { 847 if (!alts.isEmpty()) 848 alts += ", "; 849 alts += tr("(%1;%2)").arg(cand.nRow + 1).arg(cand.nCol + 1); 850 } 851 cur.insertBlock(fmt_paragraph); 852 cur.insertText(tr("%n alternate candidate(s) for branching: %1.", "", step->alts.count()).arg(alts), fmt_altlist); 853 } 854 cur.insertBlock(fmt_paragraph); 855 cur.insertText(" ", fmt_default); 856 cur.endEditBlock(); 857 858 if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) { 859 if (step->prNode != NULL) 860 drawNode(pic, n, false, step->prNode); 861 if (step->plNode != NULL) 862 drawNode(pic, n, true, step->plNode); 863 } 864 n++; 865 866 if (step->next == SStep::RightBranch) { 867 c++; 868 step = step->prNode; 869 } else if (step->next == SStep::LeftBranch) { 870 step = step->plNode; 871 } else 872 break; 873 } 874 pb->setFormat(tr("Generating footer")); 875 pd.setValue(n); 876 #ifdef Q_WS_WIN32 877 if (tl != NULL) 878 tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1); 879 #endif 880 881 cur.beginEditBlock(); 882 cur.insertBlock(fmt_paragraph); 883 if (solver.isOptimal()) 884 cur.insertText(tr("Optimal path:")); 885 else 886 cur.insertText(tr("Resulting path:")); 887 888 cur.insertBlock(fmt_paragraph); 889 cur.insertText(" " + solver.getSortedPath(tr("City %1"))); 890 891 cur.insertBlock(fmt_paragraph); 892 if (isInteger(step->price)) 893 cur.insertHtml("<p>" + tr("The price is <b>%n</b> unit(s).", "", qRound(step->price)) + "</p>"); 894 else 895 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>"); 896 if (!solver.isOptimal()) { 897 cur.insertBlock(fmt_paragraph); 898 cur.insertText(" "); 899 cur.insertBlock(fmt_paragraph); 900 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>"); 901 } 902 cur.endEditBlock(); 903 904 if (settings->value("Output/ShowGraph", DEF_SHOW_GRAPH).toBool()) { 905 pic.end(); 906 906 907 907 QImage i(graph.width() + 2, graph.height() + 2, QImage::Format_RGB32); 908 909 910 911 912 908 i.fill(0xFFFFFF); 909 pic.begin(&i); 910 pic.drawPicture(1, 1, graph); 911 pic.end(); 912 doc->addResource(QTextDocument::ImageResource, QUrl("tspsg://graph.pic"), i); 913 913 914 914 QTextImageFormat img; 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 #ifdef Q_WS_WIN32 939 940 915 img.setName("tspsg://graph.pic"); 916 if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) { 917 img.setWidth(i.width() / 2); 918 img.setHeight(i.height() / 2); 919 } else { 920 img.setWidth(i.width()); 921 img.setHeight(i.height()); 922 } 923 924 cur.setPosition(imgpos); 925 cur.insertImage(img, QTextFrameFormat::FloatRight); 926 } 927 928 if (settings->value("Output/ScrollToEnd", DEF_SCROLL_TO_END).toBool()) { 929 // Scrolling to the end of the text. 930 solutionText->moveCursor(QTextCursor::End); 931 } else 932 solutionText->moveCursor(QTextCursor::Start); 933 934 pd.setLabelText(tr("Cleaning up...")); 935 pd.setMaximum(0); 936 pd.setCancelButton(NULL); 937 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 938 #ifdef Q_WS_WIN32 939 if (tl != NULL) 940 tl->SetProgressState(winId(), TBPF_INDETERMINATE); 941 941 #endif 942 942 #ifndef QT_NO_CONCURRENT 943 943 QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false); 944 945 946 944 while (!f.isFinished()) { 945 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 946 } 947 947 #else 948 949 #endif 950 951 952 #ifdef Q_WS_WIN32 953 954 955 956 957 958 #endif 959 960 961 948 solver.cleanup(true); 949 #endif 950 toggleSolutionActions(); 951 tabWidget->setCurrentIndex(1); 952 #ifdef Q_WS_WIN32 953 if (tl != NULL) { 954 tl->SetProgressState(winId(), TBPF_NOPROGRESS); 955 tl->Release(); 956 tl = NULL; 957 } 958 #endif 959 960 pd.reset(); 961 QApplication::alert(this, 3000); 962 962 } 963 963 964 964 void MainWindow::dataChanged() 965 965 { 966 966 setWindowModified(true); 967 967 } 968 968 969 969 void MainWindow::dataChanged(const QModelIndex &tl, const QModelIndex &br) 970 970 { 971 972 973 974 975 976 977 971 setWindowModified(true); 972 if (settings->value("Autosize", DEF_AUTOSIZE).toBool()) { 973 for (int k = tl.row(); k <= br.row(); k++) 974 taskView->resizeRowToContents(k); 975 for (int k = tl.column(); k <= br.column(); k++) 976 taskView->resizeColumnToContents(k); 977 } 978 978 } 979 979 … … 981 981 void MainWindow::changeEvent(QEvent *ev) 982 982 { 983 984 985 986 983 if ((ev->type() == QEvent::ActivationChange) && isActiveWindow()) 984 desktopResized(0); 985 986 QWidget::changeEvent(ev); 987 987 } 988 988 989 989 void MainWindow::desktopResized(int screen) 990 990 { 991 992 991 if ((screen != 0) || !isActiveWindow()) 992 return; 993 993 994 994 QRect availableGeometry = QApplication::desktop()->availableGeometry(0); 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 995 if (currentGeometry != availableGeometry) { 996 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 997 /*! 998 * \hack HACK: This hack checks whether \link QDesktopWidget::availableGeometry() availableGeometry()\endlink's \c top + \c hegiht = \link QDesktopWidget::screenGeometry() screenGeometry()\endlink's \c height. 999 * If \c true, the window gets maximized. If we used \c setGeometry() in this case, the bottom of the 1000 * window would end up being behind the soft buttons. Is this a bug in Qt or Windows Mobile? 1001 */ 1002 if ((availableGeometry.top() + availableGeometry.height()) == QApplication::desktop()->screenGeometry().height()) { 1003 setWindowState(windowState() | Qt::WindowMaximized); 1004 } else { 1005 if (windowState() & Qt::WindowMaximized) 1006 setWindowState(windowState() ^ Qt::WindowMaximized); 1007 setGeometry(availableGeometry); 1008 } 1009 currentGeometry = availableGeometry; 1010 QApplication::restoreOverrideCursor(); 1011 } 1012 1012 } 1013 1013 #endif // Q_WS_WINCE_WM … … 1015 1015 void MainWindow::numCitiesChanged(int nCities) 1016 1016 { 1017 1018 1019 1017 blockSignals(true); 1018 spinCities->setValue(nCities); 1019 blockSignals(false); 1020 1020 } 1021 1021 … … 1023 1023 void MainWindow::printPreview(QPrinter *printer) 1024 1024 { 1025 1025 solutionText->print(printer); 1026 1026 } 1027 1027 #endif // QT_NO_PRINTER … … 1031 1031 { 1032 1032 #ifdef Q_WS_WIN32 1033 1033 tl->SetProgressValue(winId(), n, spinCities->value() * 2); 1034 1034 #else 1035 1035 Q_UNUSED(n); 1036 1036 #endif // Q_WS_WIN32 1037 1037 } … … 1040 1040 void MainWindow::spinCitiesValueChanged(int n) 1041 1041 { 1042 1042 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 1043 1043 int count = tspmodel->numCities(); 1044 1045 1046 1047 1048 1049 1050 1044 tspmodel->setNumCities(n); 1045 if ((n > count) && settings->value("Autosize", DEF_AUTOSIZE).toBool()) 1046 for (int k = count; k < n; k++) { 1047 taskView->resizeColumnToContents(k); 1048 taskView->resizeRowToContents(k); 1049 } 1050 QApplication::restoreOverrideCursor(); 1051 1051 } 1052 1052 … … 1054 1054 { 1055 1055 #ifdef Q_WS_WIN32 1056 1057 1058 1059 1060 1061 1062 1056 if (silent) 1057 QProcess::startDetached("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\" -silentcheck"); 1058 else { 1059 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 1060 QProcess::execute("updater/Update.exe -name=\"TSPSG: TSP Solver and Generator\" -check=\"freeupdate\""); 1061 QApplication::restoreOverrideCursor(); 1062 } 1063 1063 #else 1064 1065 #endif 1066 1064 Q_UNUSED(silent) 1065 #endif 1066 settings->setValue("Check4Updates/LastAttempt", QDate::currentDate().toString(Qt::ISODate)); 1067 1067 } 1068 1068 1069 1069 void MainWindow::closeEvent(QCloseEvent *ev) 1070 1070 { 1071 1072 1073 1074 1075 1076 1077 1078 1071 if (!maybeSave()) { 1072 ev->ignore(); 1073 return; 1074 } 1075 if (!settings->value("SettingsReset", false).toBool()) { 1076 settings->setValue("NumCities", spinCities->value()); 1077 1078 // Saving Main Window state 1079 1079 #ifndef HANDHELD 1080 1081 1082 1083 1084 1085 1086 1080 if (settings->value("SavePos", DEF_SAVEPOS).toBool()) { 1081 settings->beginGroup("MainWindow"); 1082 settings->setValue("Geometry", saveGeometry()); 1083 settings->setValue("State", saveState()); 1084 settings->setValue("Toolbars", toolBarManager->saveState()); 1085 settings->endGroup(); 1086 } 1087 1087 #else 1088 1088 settings->setValue("MainWindow/ToolbarVisible", toolBarMain->isVisible()); 1089 1089 #endif // HANDHELD 1090 1091 1092 1093 1094 1090 } else { 1091 settings->remove("SettingsReset"); 1092 } 1093 1094 QMainWindow::closeEvent(ev); 1095 1095 } 1096 1096 1097 1097 void MainWindow::dragEnterEvent(QDragEnterEvent *ev) 1098 1098 { 1099 1099 if (ev->mimeData()->hasUrls() && (ev->mimeData()->urls().count() == 1)) { 1100 1100 QFileInfo fi(ev->mimeData()->urls().first().toLocalFile()); 1101 1102 1103 1101 if ((fi.suffix() == "tspt") || (fi.suffix() == "zkt")) 1102 ev->acceptProposedAction(); 1103 } 1104 1104 } 1105 1105 … … 1107 1107 { 1108 1108 int r; 1109 1110 1111 1112 1109 if (settings->value("Output/HQGraph", DEF_HQ_GRAPH).toBool()) 1110 r = 70; 1111 else 1112 r = 35; 1113 1113 qreal x, y; 1114 1115 1116 1117 1118 1114 if (step != NULL) 1115 x = left ? r : r * 3.5; 1116 else 1117 x = r * 2.25; 1118 y = r * (3 * nstep + 1); 1119 1119 1120 1120 #ifdef _T_T_L_ 1121 1122 1123 1124 1125 #endif 1126 1127 1128 1129 1121 if (nstep == -481124) { 1122 _t_t_l_(pic, r, x); 1123 return; 1124 } 1125 #endif 1126 1127 pic.drawEllipse(QPointF(x, y), r, r); 1128 1129 if (step != NULL) { 1130 1130 QFont font; 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1131 if (left) { 1132 font = pic.font(); 1133 font.setStrikeOut(true); 1134 pic.setFont(font); 1135 } 1136 pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, tr("(%1;%2)").arg(step->pNode->candidate.nRow + 1).arg(step->pNode->candidate.nCol + 1) + "\n"); 1137 if (left) { 1138 font.setStrikeOut(false); 1139 pic.setFont(font); 1140 } 1141 if (step->price != INFINITY) { 1142 pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, isInteger(step->price) ? QString("\n%1").arg(step->price) : QString("\n%1").arg(step->price, 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt())); 1143 } else { 1144 pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, "\n"INFSTR); 1145 } 1146 } else { 1147 pic.drawText(QRectF(x - r, y - r, r * 2, r * 2), Qt::AlignCenter, tr("Root")); 1148 } 1149 1150 if (nstep == 1) { 1151 pic.drawLine(QPointF(x, y - r), QPointF(r * 2.25, y - 2 * r)); 1152 } else if (nstep > 1) { 1153 pic.drawLine(QPointF(x, y - r), QPointF((step->pNode->pNode->next == SStep::RightBranch) ? r * 3.5 : r, y - 2 * r)); 1154 } 1155 1155 1156 1156 } … … 1158 1158 void MainWindow::dropEvent(QDropEvent *ev) 1159 1159 { 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1160 if (maybeSave() && tspmodel->loadTask(ev->mimeData()->urls().first().toLocalFile())) { 1161 setFileName(ev->mimeData()->urls().first().toLocalFile()); 1162 tabWidget->setCurrentIndex(0); 1163 setWindowModified(false); 1164 solutionText->clear(); 1165 toggleSolutionActions(false); 1166 1167 ev->setDropAction(Qt::CopyAction); 1168 ev->accept(); 1169 } 1170 1170 } 1171 1171 1172 1172 void MainWindow::initDocStyleSheet() 1173 1173 { 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1174 solutionText->document()->setDefaultFont(qvariant_cast<QFont>(settings->value("Output/Font", QFont(DEF_FONT_FACE, DEF_FONT_SIZE)))); 1175 1176 fmt_paragraph.setTopMargin(0); 1177 fmt_paragraph.setRightMargin(10); 1178 fmt_paragraph.setBottomMargin(0); 1179 fmt_paragraph.setLeftMargin(10); 1180 1181 fmt_table.setTopMargin(5); 1182 fmt_table.setRightMargin(10); 1183 fmt_table.setBottomMargin(5); 1184 fmt_table.setLeftMargin(10); 1185 fmt_table.setBorder(0); 1186 fmt_table.setBorderStyle(QTextFrameFormat::BorderStyle_None); 1187 fmt_table.setCellSpacing(5); 1188 1189 fmt_cell.setAlignment(Qt::AlignHCenter); 1190 1191 settings->beginGroup("Output/Colors"); 1192 1192 1193 1193 QColor color = qvariant_cast<QColor>(settings->value("Text", DEF_TEXT_COLOR)); 1194 1194 QColor hilight; 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1195 if (color.value() < 192) 1196 hilight.setHsv(color.hue(), color.saturation(), 127 + qRound(color.value() / 2)); 1197 else 1198 hilight.setHsv(color.hue(), color.saturation(), color.value() / 2); 1199 1200 solutionText->document()->setDefaultStyleSheet(QString("* {color: %1;}").arg(color.name())); 1201 fmt_default.setForeground(QBrush(color)); 1202 1203 fmt_selected.setForeground(QBrush(qvariant_cast<QColor>(settings->value("Selected", DEF_SELECTED_COLOR)))); 1204 fmt_selected.setFontWeight(QFont::Bold); 1205 1206 fmt_alternate.setForeground(QBrush(qvariant_cast<QColor>(settings->value("Alternate", DEF_ALTERNATE_COLOR)))); 1207 fmt_alternate.setFontWeight(QFont::Bold); 1208 fmt_altlist.setForeground(QBrush(hilight)); 1209 1210 settings->endGroup(); 1211 1212 solutionText->setTextColor(color); 1213 1213 } 1214 1214 … … 1221 1221 QTranslator t; 1222 1222 QDir dir; 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1223 dir.setFilter(QDir::Files); 1224 dir.setNameFilters(QStringList("tspsg_*.qm")); 1225 dir.setSorting(QDir::NoSort); 1226 1227 dirs << PATH_L10N << ":/l10n"; 1228 foreach (QString dirname, dirs) { 1229 dir.setPath(dirname); 1230 if (dir.exists()) { 1231 langs = dir.entryInfoList(); 1232 for (int k = 0; k < langs.size(); k++) { 1233 lang = langs.at(k); 1234 if (lang.completeBaseName().compare("tspsg_en", Qt::CaseInsensitive) && !langlist.contains(lang.completeBaseName().mid(6)) && t.load(lang.completeBaseName(), dirname)) { 1235 1236 language.clear(); 1237 language.append(lang.completeBaseName().mid(6)); 1238 language.append(t.translate("--------", "COUNTRY", "Please, provide an ISO 3166-1 alpha-2 country code for this translation language here (eg., UA).").toLower()); 1239 language.append(t.translate("--------", "LANGNAME", "Please, provide a native name of your translation language here.")); 1240 language.append(t.translate("MainWindow", "Set application language to %1", "").arg(language.at(2))); 1241 1242 langlist.insert(language.at(0), language); 1243 } 1244 } 1245 } 1246 } 1247 1247 1248 1248 QAction *a; 1249 1250 1249 foreach (language, langlist) { 1250 a = menuSettingsLanguage->addAction(language.at(2)); 1251 1251 #ifndef QT_NO_STATUSTIP 1252 1252 a->setStatusTip(language.at(3)); 1253 1253 #endif 1254 1254 #if QT_VERSION >= 0x040600 1255 1255 a->setIcon(QIcon::fromTheme(QString("flag-%1").arg(language.at(1)), QIcon(QString(":/images/icons/l10n/flag-%1.png").arg(language.at(1))))); 1256 1256 #else 1257 1258 #endif 1259 1260 1261 1262 1263 1264 1257 a->setIcon(QIcon(QString(":/images/icons/l10n/flag-%1.png").arg(language.at(1)))); 1258 #endif 1259 a->setData(language.at(0)); 1260 a->setCheckable(true); 1261 a->setActionGroup(groupSettingsLanguageList); 1262 if (settings->value("Language", QLocale::system().name()).toString().startsWith(language.at(0))) 1263 a->setChecked(true); 1264 } 1265 1265 } 1266 1266 … … 1270 1270 bool ad = false; 1271 1271 QString lng = lang; 1272 1273 1274 1275 1272 if (lng.isEmpty()) { 1273 ad = settings->value("Language").toString().isEmpty(); 1274 lng = settings->value("Language", QLocale::system().name()).toString(); 1275 } 1276 1276 static QTranslator *qtTranslator; // Qt library translator 1277 1278 1279 1280 1281 1277 if (qtTranslator) { 1278 qApp->removeTranslator(qtTranslator); 1279 delete qtTranslator; 1280 qtTranslator = NULL; 1281 } 1282 1282 static QTranslator *translator; // Application translator 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1283 if (translator) { 1284 qApp->removeTranslator(translator); 1285 delete translator; 1286 translator = NULL; 1287 } 1288 1289 if (lng == "en") 1290 return true; 1291 1292 // Trying to load system Qt library translation... 1293 qtTranslator = new QTranslator(this); 1294 if (qtTranslator->load("qt_" + lng, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) 1295 qApp->installTranslator(qtTranslator); 1296 else { 1297 // No luck. Let's try to load a bundled one. 1298 if (qtTranslator->load("qt_" + lng, PATH_L10N)) { 1299 // We have a translation in the localization direcotry. 1300 qApp->installTranslator(qtTranslator); 1301 } else if (qtTranslator->load("qt_" + lng, ":/l10n")) { 1302 // We have a translation "built-in" into application resources. 1303 qApp->installTranslator(qtTranslator); 1304 } else { 1305 // Qt library translation unavailable for this language. 1306 delete qtTranslator; 1307 qtTranslator = NULL; 1308 } 1309 } 1310 1311 // Now let's load application translation. 1312 translator = new QTranslator(this); 1313 if (translator->load("tspsg_" + lng, PATH_L10N)) { 1314 // We have a translation in the localization directory. 1315 qApp->installTranslator(translator); 1316 } else if (translator->load("tspsg_" + lng, ":/l10n")) { 1317 // We have a translation "built-in" into application resources. 1318 qApp->installTranslator(translator); 1319 } else { 1320 delete translator; 1321 translator = NULL; 1322 if (!ad) { 1323 settings->remove("Language"); 1324 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 1325 QMessageBox::warning(isVisible() ? this : NULL, tr("Language Change"), tr("Unable to load the translation language.\nFalling back to autodetection.")); 1326 QApplication::restoreOverrideCursor(); 1327 } 1328 return false; 1329 } 1330 return true; 1331 1331 } 1332 1332 1333 1333 void MainWindow::loadStyleList() 1334 1334 { 1335 1335 menuSettingsStyle->clear(); 1336 1336 QStringList styles = QStyleFactory::keys(); 1337 1338 1339 1337 menuSettingsStyle->insertAction(NULL, actionSettingsStyleSystem); 1338 actionSettingsStyleSystem->setChecked(!settings->contains("Style")); 1339 menuSettingsStyle->addSeparator(); 1340 1340 QAction *a; 1341 1342 1343 1341 foreach (QString style, styles) { 1342 a = menuSettingsStyle->addAction(style); 1343 a->setData(false); 1344 1344 #ifndef QT_NO_STATUSTIP 1345 1346 #endif 1347 1348 1349 1345 a->setStatusTip(tr("Set application style to %1").arg(style)); 1346 #endif 1347 a->setCheckable(true); 1348 a->setActionGroup(groupSettingsStyleList); 1349 if ((style == settings->value("Stlye").toString()) 1350 1350 #ifndef Q_WS_MAEMO_5 1351 1352 #endif 1353 1354 1355 1356 1351 || QString(QApplication::style()->metaObject()->className()).contains(QRegExp(QString("^Q?%1(Style)?$").arg(QRegExp::escape(style)), Qt::CaseInsensitive)) 1352 #endif 1353 ) { 1354 a->setChecked(true); 1355 } 1356 } 1357 1357 } 1358 1358 1359 1359 void MainWindow::loadToolbarList() 1360 1360 { 1361 1361 menuSettingsToolbars->clear(); 1362 1362 #ifndef HANDHELD 1363 1364 1363 menuSettingsToolbars->insertAction(NULL, actionSettingsToolbarsConfigure); 1364 menuSettingsToolbars->addSeparator(); 1365 1365 QList<QToolBar *> list = toolBarManager->toolBars(); 1366 1367 1368 1366 foreach (QToolBar *t, list) { 1367 menuSettingsToolbars->insertAction(NULL, t->toggleViewAction()); 1368 } 1369 1369 #else // HANDHELD 1370 1370 menuSettingsToolbars->insertAction(NULL, toolBarMain->toggleViewAction()); 1371 1371 #endif // HANDHELD 1372 1372 } … … 1374 1374 bool MainWindow::maybeSave() 1375 1375 { 1376 1377 1376 if (!isWindowModified()) 1377 return true; 1378 1378 int res = QMessageBox::warning(this, tr("Unsaved Changes"), tr("Would you like to save changes in the current task?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); 1379 1380 1381 1382 1383 1384 1379 if (res == QMessageBox::Save) 1380 return actionFileSaveTriggered(); 1381 else if (res == QMessageBox::Cancel) 1382 return false; 1383 else 1384 return true; 1385 1385 } 1386 1386 … … 1390 1390 QTextTable *table = cur.insertTable(n, n, fmt_table); 1391 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1392 for (int r = 0; r < n; r++) { 1393 for (int c = 0; c < n; c++) { 1394 cur = table->cellAt(r, c).firstCursorPosition(); 1395 cur.setBlockFormat(fmt_cell); 1396 cur.setBlockCharFormat(fmt_default); 1397 if (matrix.at(r).at(c) == INFINITY) 1398 cur.insertText(INFSTR); 1399 else 1400 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())); 1401 } 1402 QCoreApplication::processEvents(); 1403 } 1404 cur.movePosition(QTextCursor::End); 1405 1405 } 1406 1406 … … 1410 1410 QTextTable *table = cur.insertTable(n, n, fmt_table); 1411 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1412 for (int r = 0; r < n; r++) { 1413 for (int c = 0; c < n; c++) { 1414 cur = table->cellAt(r, c).firstCursorPosition(); 1415 cur.setBlockFormat(fmt_cell); 1416 if (step.matrix.at(r).at(c) == INFINITY) 1417 cur.insertText(INFSTR, fmt_default); 1418 else if ((r == step.candidate.nRow) && (c == step.candidate.nCol)) 1419 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); 1420 else { 1421 1421 SStep::SCandidate cand; 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1422 cand.nRow = r; 1423 cand.nCol = c; 1424 if (step.alts.contains(cand)) 1425 cur.insertText(isInteger(step.matrix.at(r).at(c)) ? QString("%1").arg(step.matrix.at(r).at(c)) : QString("%1").arg(step.matrix.at(r).at(c), 0, 'f', settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()), fmt_alternate); 1426 else 1427 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); 1428 } 1429 } 1430 QCoreApplication::processEvents(); 1431 } 1432 1433 cur.movePosition(QTextCursor::End); 1434 1434 } 1435 1435 1436 1436 void MainWindow::retranslateUi(bool all) 1437 1437 { 1438 1439 1440 1441 1442 1438 if (all) 1439 Ui_MainWindow::retranslateUi(this); 1440 1441 loadStyleList(); 1442 loadToolbarList(); 1443 1443 1444 1444 #ifndef QT_NO_PRINTER 1445 1445 actionFilePrintPreview->setText(tr("P&rint Preview...")); 1446 1446 #ifndef QT_NO_TOOLTIP 1447 1447 actionFilePrintPreview->setToolTip(tr("Preview solution results")); 1448 1448 #endif // QT_NO_TOOLTIP 1449 1449 #ifndef QT_NO_STATUSTIP 1450 1451 1450 actionFilePrintPreview->setStatusTip(tr("Preview current solution results before printing")); 1451 actionFileExit->setStatusTip(tr("Exit %1").arg(QCoreApplication::applicationName())); 1452 1452 #endif // QT_NO_STATUSTIP 1453 1453 1454 1454 actionFilePrint->setText(tr("&Print...")); 1455 1455 #ifndef QT_NO_TOOLTIP 1456 1456 actionFilePrint->setToolTip(tr("Print solution")); 1457 1457 #endif // QT_NO_TOOLTIP 1458 1458 #ifndef QT_NO_STATUSTIP 1459 1459 actionFilePrint->setStatusTip(tr("Print current solution results")); 1460 1460 #endif // QT_NO_STATUSTIP 1461 1461 actionFilePrint->setShortcut(tr("Ctrl+P")); 1462 1462 #endif // QT_NO_PRINTER 1463 1463 1464 1464 #ifndef HANDHELD 1465 1465 actionSettingsToolbarsConfigure->setText(tr("Configure...")); 1466 1466 #ifndef QT_NO_STATUSTIP 1467 1467 actionSettingsToolbarsConfigure->setStatusTip(tr("Customize toolbars")); 1468 1468 #endif // QT_NO_STATUSTIP 1469 1469 #endif // HANDHELD 1470 1470 1471 1471 #ifndef QT_NO_STATUSTIP 1472 1472 actionHelpReportBug->setStatusTip(tr("Report about a bug in %1").arg(QCoreApplication::applicationName())); 1473 1473 #endif // QT_NO_STATUSTIP 1474 1475 1474 if (actionHelpCheck4Updates != NULL) { 1475 actionHelpCheck4Updates->setText(tr("Check for &Updates...")); 1476 1476 #ifndef QT_NO_STATUSTIP 1477 1477 actionHelpCheck4Updates->setStatusTip(tr("Check for %1 updates").arg(QCoreApplication::applicationName())); 1478 1478 #endif // QT_NO_STATUSTIP 1479 1479 } 1480 1480 #ifndef QT_NO_STATUSTIP 1481 1481 actionHelpAbout->setStatusTip(tr("About %1").arg(QCoreApplication::applicationName())); 1482 1482 #endif // QT_NO_STATUSTIP 1483 1483 } … … 1485 1485 bool MainWindow::saveTask() { 1486 1486 QStringList filters(tr("%1 Task File").arg("TSPSG") + " (*.tspt)"); 1487 1487 filters.append(tr("All Files") + " (*)"); 1488 1488 QString file; 1489 1490 1491 1492 1493 1494 1495 1496 1497 1489 if ((fileName == tr("Untitled") + ".tspt") && settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) { 1490 file = settings->value(OS"/LastUsed/TaskSavePath").toString(); 1491 if (!file.isEmpty()) 1492 file.append("/"); 1493 file.append(fileName); 1494 } else if (fileName.endsWith(".tspt", Qt::CaseInsensitive)) 1495 file = fileName; 1496 else 1497 file = QFileInfo(fileName).path() + "/" + QFileInfo(fileName).completeBaseName() + ".tspt"; 1498 1498 1499 1499 QFileDialog::Options opts = settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool() ? QFileDialog::Options() : QFileDialog::DontUseNativeDialog; 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1500 file = QFileDialog::getSaveFileName(this, tr("Task Save"), file, filters.join(";;"), NULL, opts); 1501 if (file.isEmpty()) 1502 return false; 1503 else if (settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()) 1504 settings->setValue(OS"/LastUsed/TaskSavePath", QFileInfo(file).path()); 1505 1506 if (tspmodel->saveTask(file)) { 1507 setFileName(file); 1508 setWindowModified(false); 1509 return true; 1510 } 1511 return false; 1512 1512 } 1513 1513 1514 1514 void MainWindow::setFileName(const QString &fileName) 1515 1515 { 1516 1517 1516 this->fileName = fileName; 1517 setWindowTitle(QString("%1[*] - %2").arg(QFileInfo(fileName).completeBaseName()).arg(QCoreApplication::applicationName())); 1518 1518 } 1519 1519 1520 1520 void MainWindow::setupUi() 1521 1521 { 1522 1523 1524 1525 1526 1527 1522 Ui_MainWindow::setupUi(this); 1523 1524 // File Menu 1525 actionFileNew->setIcon(GET_ICON("document-new")); 1526 actionFileOpen->setIcon(GET_ICON("document-open")); 1527 actionFileSave->setIcon(GET_ICON("document-save")); 1528 1528 #ifndef HANDHELD 1529 1530 #endif 1531 1532 1529 menuFileSaveAs->setIcon(GET_ICON("document-save-as")); 1530 #endif 1531 actionFileExit->setIcon(GET_ICON("application-exit")); 1532 // Settings Menu 1533 1533 #ifndef HANDHELD 1534 1534 menuSettingsLanguage->setIcon(GET_ICON("preferences-desktop-locale")); 1535 1535 #if QT_VERSION >= 0x040600 1536 1536 actionSettingsLanguageEnglish->setIcon(QIcon::fromTheme("flag-gb", QIcon(":/images/icons/l10n/flag-gb.png"))); 1537 1537 #else // QT_VERSION >= 0x040600 1538 1538 actionSettingsLanguageEnglish->setIcon(QIcon(":/images/icons/l10n/flag-gb.png")); 1539 1539 #endif // QT_VERSION >= 0x040600 1540 1540 menuSettingsStyle->setIcon(GET_ICON("preferences-desktop-theme")); 1541 1541 #endif // HANDHELD 1542 1543 1542 actionSettingsPreferences->setIcon(GET_ICON("preferences-system")); 1543 // Help Menu 1544 1544 #ifndef HANDHELD 1545 1546 1547 1548 1549 1550 1551 #endif 1552 1553 1554 1555 1556 1545 actionHelpContents->setIcon(GET_ICON("help-contents")); 1546 actionHelpContextual->setIcon(GET_ICON("help-contextual")); 1547 actionHelpOnlineSupport->setIcon(GET_ICON("applications-internet")); 1548 actionHelpReportBug->setIcon(GET_ICON("tools-report-bug")); 1549 actionHelpAbout->setIcon(GET_ICON("help-about")); 1550 actionHelpAboutQt->setIcon(QIcon(":/images/icons/"ICON_SIZE"/qtlogo."ICON_FORMAT)); 1551 #endif 1552 // Buttons 1553 buttonRandom->setIcon(GET_ICON("roll")); 1554 buttonSolve->setIcon(GET_ICON("dialog-ok")); 1555 buttonSaveSolution->setIcon(GET_ICON("document-save-as")); 1556 buttonBackToTask->setIcon(GET_ICON("go-previous")); 1557 1557 1558 1558 // action->setIcon(GET_ICON("")); 1559 1559 1560 1560 #if QT_VERSION >= 0x040600 1561 1561 setToolButtonStyle(Qt::ToolButtonFollowStyle); 1562 1562 #endif 1563 1563 1564 1564 #ifndef HANDHELD 1565 1565 QStatusBar *statusbar = new QStatusBar(this); 1566 1567 1566 statusbar->setObjectName("statusbar"); 1567 setStatusBar(statusbar); 1568 1568 #endif // HANDHELD 1569 1569 1570 1570 #ifdef Q_WS_WINCE_WM 1571 1571 menuBar()->setDefaultAction(menuFile->menuAction()); 1572 1572 1573 1573 QScrollArea *scrollArea = new QScrollArea(this); 1574 1575 1576 1577 1578 1574 scrollArea->setFrameShape(QFrame::NoFrame); 1575 scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 1576 scrollArea->setWidgetResizable(true); 1577 scrollArea->setWidget(tabWidget); 1578 setCentralWidget(scrollArea); 1579 1579 #else 1580 1580 setCentralWidget(tabWidget); 1581 1581 #endif // Q_WS_WINCE_WM 1582 1582 1583 1583 //! \hack HACK: A little hack for toolbar icons to have a sane size. 1584 1584 #if defined(HANDHELD) && !defined(Q_WS_MAEMO_5) 1585 1585 toolBarMain->setIconSize(QSize(logicalDpiX() / 4, logicalDpiY() / 4)); 1586 1586 #endif // HANDHELD 1587 1587 QToolButton *tb = static_cast<QToolButton *>(toolBarMain->widgetForAction(actionFileSave)); 1588 1589 1590 1591 1588 if (tb != NULL) { 1589 tb->setMenu(menuFileSaveAs); 1590 tb->setPopupMode(QToolButton::MenuButtonPopup); 1591 } 1592 1592 1593 1593 // solutionText->document()->setDefaultFont(settings->value("Output/Font", QFont(DEF_FONT_FAMILY, DEF_FONT_SIZE)).value<QFont>()); 1594 1594 solutionText->setWordWrapMode(QTextOption::WordWrap); 1595 1595 1596 1596 #ifndef QT_NO_PRINTER 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1597 actionFilePrintPreview = new QAction(this); 1598 actionFilePrintPreview->setObjectName("actionFilePrintPreview"); 1599 actionFilePrintPreview->setEnabled(false); 1600 actionFilePrintPreview->setIcon(GET_ICON("document-print-preview")); 1601 1602 actionFilePrint = new QAction(this); 1603 actionFilePrint->setObjectName("actionFilePrint"); 1604 actionFilePrint->setEnabled(false); 1605 actionFilePrint->setIcon(GET_ICON("document-print")); 1606 1607 menuFile->insertAction(actionFileExit,actionFilePrintPreview); 1608 menuFile->insertAction(actionFileExit,actionFilePrint); 1609 menuFile->insertSeparator(actionFileExit); 1610 1611 toolBarMain->insertAction(actionSettingsPreferences, actionFilePrint); 1612 1612 #endif // QT_NO_PRINTER 1613 1613 1614 1614 groupSettingsLanguageList = new QActionGroup(this); 1615 1615 #ifdef Q_WS_MAEMO_5 1616 1617 #endif 1618 1619 1620 1621 1622 1623 1624 1616 groupSettingsLanguageList->addAction(actionSettingsLanguageAutodetect); 1617 #endif 1618 actionSettingsLanguageEnglish->setData("en"); 1619 actionSettingsLanguageEnglish->setActionGroup(groupSettingsLanguageList); 1620 loadLangList(); 1621 actionSettingsLanguageAutodetect->setChecked(settings->value("Language", "").toString().isEmpty()); 1622 1623 actionSettingsStyleSystem->setData(true); 1624 groupSettingsStyleList = new QActionGroup(this); 1625 1625 #ifdef Q_WS_MAEMO_5 1626 1626 groupSettingsStyleList->addAction(actionSettingsStyleSystem); 1627 1627 #endif 1628 1628 1629 1629 #ifndef HANDHELD 1630 1631 1630 actionSettingsToolbarsConfigure = new QAction(this); 1631 actionSettingsToolbarsConfigure->setIcon(GET_ICON("configure-toolbars")); 1632 1632 #endif // HANDHELD 1633 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1634 if (hasUpdater()) { 1635 actionHelpCheck4Updates = new QAction(this); 1636 actionHelpCheck4Updates->setIcon(GET_ICON("system-software-update")); 1637 actionHelpCheck4Updates->setEnabled(hasUpdater()); 1638 menuHelp->insertAction(actionHelpAboutQt, actionHelpCheck4Updates); 1639 menuHelp->insertSeparator(actionHelpAboutQt); 1640 } else 1641 actionHelpCheck4Updates = NULL; 1642 1643 spinCities->setMaximum(MAX_NUM_CITIES); 1644 1644 1645 1645 #ifndef HANDHELD 1646 1647 1646 toolBarManager = new QtToolBarManager; 1647 toolBarManager->setMainWindow(this); 1648 1648 QString cat = toolBarMain->windowTitle(); 1649 1649 toolBarManager->addToolBar(toolBarMain, cat); 1650 1650 #ifndef QT_NO_PRINTER 1651 1651 toolBarManager->addAction(actionFilePrintPreview, cat); 1652 1652 #endif // QT_NO_PRINTER 1653 1654 1653 toolBarManager->addAction(actionHelpContents, cat); 1654 toolBarManager->addAction(actionHelpContextual, cat); 1655 1655 // toolBarManager->addAction(action, cat); 1656 1656 toolBarManager->restoreState(settings->value("MainWindow/Toolbars").toByteArray()); 1657 1657 #else 1658 1658 toolBarMain->setVisible(settings->value("MainWindow/ToolbarVisible", true).toBool()); 1659 1659 #endif // HANDHELD 1660 1660 1661 1662 1663 #ifdef Q_WS_WIN32 1664 1665 1666 1667 1661 retranslateUi(false); 1662 1663 #ifdef Q_WS_WIN32 1664 // Adding some eyecandy in Vista and 7 :-) 1665 if (QtWin::isCompositionEnabled() && settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool()) { 1666 toggleTranclucency(true); 1667 } 1668 1668 #endif // Q_WS_WIN32 1669 1669 } … … 1671 1671 void MainWindow::toggleSolutionActions(bool enable) 1672 1672 { 1673 1674 1675 1673 buttonSaveSolution->setEnabled(enable); 1674 actionFileSaveAsSolution->setEnabled(enable); 1675 solutionText->setEnabled(enable); 1676 1676 #ifndef QT_NO_PRINTER 1677 1678 1677 actionFilePrint->setEnabled(enable); 1678 actionFilePrintPreview->setEnabled(enable); 1679 1679 #endif // QT_NO_PRINTER 1680 1680 } … … 1683 1683 { 1684 1684 #ifdef Q_WS_WIN32 1685 1686 1687 1688 1689 1685 toggleStyle(labelVariant, enable); 1686 toggleStyle(labelCities, enable); 1687 toggleStyle(statusBar(), enable); 1688 tabWidget->setDocumentMode(enable); 1689 QtWin::enableBlurBehindWindow(this, enable); 1690 1690 #else 1691 1691 Q_UNUSED(enable); 1692 1692 #endif // Q_WS_WIN32 1693 1693 } … … 1695 1695 void MainWindow::actionHelpOnlineSupportTriggered() 1696 1696 { 1697 1697 QDesktopServices::openUrl(QUrl("http://tspsg.info/goto/support")); 1698 1698 } 1699 1699 1700 1700 void MainWindow::actionHelpReportBugTriggered() 1701 1701 { 1702 1703 } 1702 QDesktopServices::openUrl(QUrl("http://tspsg.info/goto/bugtracker")); 1703 } -
trunk/src/mainwindow.h
r142 r149 37 37 38 38 #ifdef Q_WS_WIN32 39 40 39 // Forward declaration. A real one is in shobjidl.h 40 struct ITaskbarList3; 41 41 #endif 42 42 … … 49 49 class MainWindow: public QMainWindow, Ui::MainWindow 50 50 { 51 51 Q_OBJECT 52 52 53 53 public: 54 55 54 MainWindow(QWidget *parent = 0); 55 ~MainWindow(); 56 56 57 57 private slots: 58 58 // Actions 59 60 61 62 63 59 void actionFileNewTriggered(); 60 void actionFileOpenTriggered(); 61 bool actionFileSaveTriggered(); 62 void actionFileSaveAsTaskTriggered(); 63 void actionFileSaveAsSolutionTriggered(); 64 64 #ifndef QT_NO_PRINTER 65 66 65 void actionFilePrintPreviewTriggered(); 66 void actionFilePrintTriggered(); 67 67 #endif // QT_NO_PRINTER 68 69 70 71 72 68 void actionSettingsPreferencesTriggered(); 69 void actionSettingsLanguageAutodetectTriggered(bool checked); 70 void groupSettingsLanguageListTriggered(QAction *action); 71 void actionSettingsStyleSystemTriggered(bool checked); 72 void groupSettingsStyleListTriggered(QAction *action); 73 73 #ifndef HANDHELD 74 74 void actionSettingsToolbarsConfigureTriggered(); 75 75 #endif // HANDHELD 76 77 78 79 76 void actionHelpOnlineSupportTriggered(); 77 void actionHelpReportBugTriggered(); 78 void actionHelpCheck4UpdatesTriggered(); 79 void actionHelpAboutTriggered(); 80 80 // Buttons 81 82 83 81 void buttonBackToTaskClicked(); 82 void buttonRandomClicked(); 83 void buttonSolveClicked(); 84 84 85 86 85 void dataChanged(); 86 void dataChanged(const QModelIndex &tl, const QModelIndex &br); 87 87 #ifdef Q_WS_WINCE_WM 88 89 88 void changeEvent(QEvent *ev); 89 void desktopResized(int screen); 90 90 #endif // Q_WS_WINCE_WM 91 91 void numCitiesChanged(int nCities); 92 92 #ifndef QT_NO_PRINTER 93 93 void printPreview(QPrinter *printer); 94 94 #endif // QT_NO_PRINTER 95 95 #ifdef Q_WS_WIN32 96 96 void solverRoutePartFound(int n); 97 97 #endif // Q_WS_WIN32 98 98 void spinCitiesValueChanged(int nCities); 99 99 100 100 private: 101 102 103 101 QString fileName; 102 QActionGroup *groupSettingsLanguageList; 103 QActionGroup *groupSettingsStyleList; 104 104 #ifndef HANDHELD 105 106 105 QAction *actionSettingsToolbarsConfigure; 106 QtToolBarManager *toolBarManager; 107 107 #endif // HANDHELD 108 108 #ifndef QT_NO_PRINTER 109 110 111 109 QPrinter *printer; 110 QAction *actionFilePrintPreview; 111 QAction *actionFilePrint; 112 112 #endif // QT_NO_PRINTER 113 114 115 113 QAction *actionHelpCheck4Updates; 114 QSettings *settings; 115 CTSPModel *tspmodel; 116 116 #ifdef Q_WS_WINCE_WM 117 117 QRect currentGeometry; 118 118 #endif // Q_WS_WINCE_WM 119 119 120 120 #ifdef Q_WS_WIN32 121 121 ITaskbarList3 *tl; 122 122 #endif // Q_WS_WIN32 123 123 124 125 124 // The solution graph SVG 125 QPicture graph; 126 126 127 128 129 130 131 132 133 134 127 // Formats 128 QTextTableFormat fmt_table; 129 QTextBlockFormat fmt_paragraph, 130 fmt_cell; 131 QTextCharFormat fmt_default, 132 fmt_selected, 133 fmt_alternate, 134 fmt_altlist; 135 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 136 void check4Updates(bool silent = false); 137 void closeEvent(QCloseEvent *ev); 138 void dragEnterEvent(QDragEnterEvent *ev); 139 void drawNode(QPainter &pic, int nstep, bool left = false, SStep *step = NULL); 140 void dropEvent(QDropEvent *ev); 141 void initDocStyleSheet(); 142 void loadLangList(); 143 bool loadLanguage(const QString &lang = QString()); 144 void loadStyleList(); 145 void loadToolbarList(); 146 bool maybeSave(); 147 void outputMatrix(QTextCursor &cur, const TMatrix &matrix); 148 void outputMatrix(QTextCursor &cur, const SStep &step); 149 void retranslateUi(bool all = true); 150 bool saveTask(); 151 void setFileName(const QString &fileName = tr("Untitled") + ".tspt"); 152 void setupUi(); 153 void toggleSolutionActions(bool enable = true); 154 void toggleTranclucency(bool enable); 155 155 }; 156 156 -
trunk/src/os.h
r141 r149 39 39 */ 40 40 #if defined(__amd64__) || defined(_M_X64) 41 # 41 # define ARCH " (AMD 64-bit)" 42 42 #elif defined(__ia64__) || defined(_M_IA64) 43 # 43 # define ARCH " (Intel 64-bit)" 44 44 #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) 45 # 45 # define ARCH " (Intel x86)" 46 46 #elif defined(__powerpc__) || defined(_M_PPC) 47 # 47 # define ARCH " (PowerPC)" 48 48 #elif defined(__arm__) || defined(_M_ARM) 49 # 49 # define ARCH " (ARM)" 50 50 #elif defined(__mips__) || defined(_M_MRX000) 51 # 51 # define ARCH " (MIPS)" 52 52 #else 53 # 53 # define ARCH "" 54 54 #endif // ARCH 55 55 … … 66 66 */ 67 67 #ifdef Q_OS_AIX 68 # 69 # 68 # define OS "AIX" 69 # define OSID quint8(1) 70 70 #elif defined(Q_OS_BSDI) 71 # 72 # 71 # define OS "BSD/OS" 72 # define OSID quint8(2) 73 73 #elif defined(Q_OS_CYGWIN) 74 # 75 # 74 # define OS "Cygwin" 75 # define OSID quint8(3) 76 76 #elif defined(Q_OS_DARWIN) 77 # 78 # 77 # define OS "Mac OS (Darwin)" 78 # define OSID quint8(4) 79 79 #elif defined(Q_OS_DGUX) 80 # 81 # 80 # define OS "DG/UX" 81 # define OSID quint8(5) 82 82 #elif defined(Q_OS_DYNIX) 83 # 84 # 83 # define OS "DYNIX/ptx" 84 # define OSID quint8(6) 85 85 #elif defined(Q_OS_FREEBSD) 86 # 87 # 86 # define OS "FreeBSD" 87 # define OSID quint8(7) 88 88 #elif defined(Q_OS_HPUX) 89 # 90 # 89 # define OS "HP-UX" 90 # define OSID quint8(8) 91 91 #elif defined(Q_OS_HURD) 92 # 93 # 92 # define OS "GNU Hurd" 93 # define OSID quint8(9) 94 94 #elif defined(Q_OS_IRIX) 95 # 96 # 95 # define OS "SGI Irix" 96 # define OSID quint8(10) 97 97 #elif defined(Q_OS_LINUX) 98 # 99 # 98 # define OS "Linux" 99 # define OSID quint8(11) 100 100 #elif defined(Q_OS_LYNX) 101 # 102 # 101 # define OS "LynxOS" 102 # define OSID quint8(12) 103 103 #elif defined(Q_OS_NETBSD) 104 # 105 # 104 # define OS "NetBSD" 105 # define OSID quint8(13) 106 106 #elif defined(Q_OS_OPENBSD) 107 # 108 # 107 # define OS "OpenBSD" 108 # define OSID quint8(14) 109 109 #elif defined(Q_OS_OS2EMX) 110 # 111 # 110 # define OS "OS/2" 111 # define OSID quint8(15) 112 112 #elif defined(Q_OS_OSF) 113 # 114 # 113 # define OS "HP Tru64 UNIX" 114 # define OSID quint8(16) 115 115 #elif defined(Q_OS_QNX) 116 # 117 # 116 # define OS "QNX Neutrino" 117 # define OSID quint8(17) 118 118 #elif defined(Q_OS_RELIANT) 119 # 120 # 119 # define OS "Reliant UNIX" 120 # define OSID quint8(18) 121 121 #elif defined(Q_OS_SCO) 122 # 123 # 122 # define OS "SCO OpenServer 5" 123 # define OSID quint8(19) 124 124 #elif defined(Q_OS_SOLARIS) 125 # 126 # 125 # define OS "Sun Solaris" 126 # define OSID quint8(20) 127 127 #elif defined(Q_OS_SYMBIAN) 128 # 129 # 128 # define OS "Symbian" 129 # define OSID quint8(21) 130 130 #elif defined(Q_OS_ULTRIX) 131 # 132 # 131 # define OS "DEC Ultrix" 132 # define OSID quint8(22) 133 133 #elif defined(Q_OS_UNIXWARE) 134 # 135 # 134 # define OS "UnixWare 7/Open UNIX 8" 135 # define OSID quint8(23) 136 136 #elif defined(Q_OS_WIN32) 137 # 138 # 137 # define OS "Windows" 138 # define OSID quint8(24) 139 139 #elif defined(Q_OS_WINCE_WM) 140 # 141 # 140 # define OS "Windows Mobile" 141 # define OSID quint8(25) 142 142 #elif defined(Q_OS_WINCE) 143 # 144 # 143 # define OS "Windows CE" 144 # define OSID quint8(26) 145 145 #elif defined(Q_OS_BSD4) 146 # 147 # 146 # define OS "BSD 4.4" 147 # define OSID quint8(253) 148 148 #elif defined(Q_OS_UNIX) 149 # 150 # 149 # define OS "UNIX BSD/SYSV" 150 # define OSID quint8(254) 151 151 #else 152 # 153 # 152 # define OS "Unknown" 153 # define OSID quint8(255) 154 154 #endif // OS 155 155 … … 162 162 */ 163 163 #ifdef Q_CC_INTEL 164 # 164 # define COMPILER "Intel C++" 165 165 #elif defined(Q_CC_MSVC) 166 # 166 # define COMPILER "Microsoft Visual C/C++" 167 167 #elif defined(Q_CC_MINGW) 168 # 168 # define COMPILER "MinGW GCC" 169 169 #elif defined(Q_CC_GNU) 170 # 170 # define COMPILER "GNU C++" 171 171 #elif defined(Q_CC_GCCE) 172 # 172 # define COMPILER "GCCE (Symbian GCCE builds)" 173 173 #elif defined(Q_CC_RVCT) 174 # 174 # define COMPILER "ARM Realview Compiler Suite" 175 175 #elif defined(Q_CC_NOKIAX86) 176 # 176 # define COMPILER "Nokia x86 (Symbian WINSCW builds)" 177 177 #else 178 # 178 # define COMPILER "Unknown" 179 179 #endif 180 180 -
trunk/src/settingsdialog.cpp
r143 r149 31 31 */ 32 32 SettingsDialog::SettingsDialog(QWidget *parent) 33 34 { 35 36 37 38 39 40 #ifndef QT_NO_STATUSTIP 41 33 : QDialog(parent), _newFont(false), _newColor(false), _translucency(0) 34 { 35 setupUi(this); 36 37 setWindowIcon(GET_ICON("preferences-system")); 38 39 buttonBox->button(QDialogButtonBox::Ok)->setIcon(GET_ICON("dialog-ok")); 40 #ifndef QT_NO_STATUSTIP 41 buttonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Save new preferences")); 42 42 #endif 43 44 45 #ifndef QT_NO_STATUSTIP 46 43 buttonBox->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor)); 44 buttonBox->button(QDialogButtonBox::Cancel)->setIcon(GET_ICON("dialog-cancel")); 45 #ifndef QT_NO_STATUSTIP 46 buttonBox->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Close without saving preferences")); 47 47 #endif 48 49 50 51 52 48 buttonBox->button(QDialogButtonBox::Cancel)->setCursor(QCursor(Qt::PointingHandCursor)); 49 50 buttonColor->setIcon(GET_ICON("format-text-color")); 51 buttonFont->setIcon(GET_ICON("preferences-desktop-font")); 52 buttonHelp->setIcon(GET_ICON("help-hint")); 53 53 54 54 QPalette p = bgWhite->palette(); 55 56 57 58 59 60 55 p.setColor(QPalette::Window, p.color(QPalette::Base)); 56 bgWhite->setPalette(p); 57 58 p = lineHorizontal->palette(); 59 p.setColor(QPalette::Window, p.color(QPalette::Text)); 60 lineHorizontal->setPalette(p); 61 61 62 62 // Layout helpers … … 64 64 QHBoxLayout *hbox; 65 65 #ifndef QT_NO_PRINTER 66 67 68 #ifndef QT_NO_STATUSTIP 69 70 #endif // QT_NO_STATUSTIP 71 72 73 74 75 76 77 78 79 66 cbHQGraph = new QCheckBox(bgWhite); 67 cbHQGraph->setObjectName("cbHQGraph"); 68 #ifndef QT_NO_STATUSTIP 69 cbHQGraph->setStatusTip(tr("Higher quality graph looks much better when printing but uglier on the screen")); 70 #endif // QT_NO_STATUSTIP 71 cbHQGraph->setText(tr("Draw solution graph in higher quality")); 72 cbHQGraph->setCursor(QCursor(Qt::PointingHandCursor)); 73 74 box = static_cast<QBoxLayout *>(tabOutput->layout()); 75 hbox = new QHBoxLayout(); 76 hbox->addSpacing(10); 77 hbox->addWidget(cbHQGraph); 78 box->insertLayout(box->indexOf(cbShowGraph) + 1, hbox); 79 connect(cbShowGraph, SIGNAL(toggled(bool)), cbHQGraph, SLOT(setEnabled(bool))); 80 80 #endif 81 81 82 83 84 85 #ifndef QT_NO_STATUSTIP 86 87 #endif // QT_NO_STATUSTIP 88 89 90 91 92 93 #ifndef QT_NO_STATUSTIP 94 95 #endif // QT_NO_STATUSTIP 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 82 if (hasUpdater()) { 83 cbCheck4Updates = new QCheckBox(bgWhite); 84 cbCheck4Updates->setObjectName("cbCheck4Updates"); 85 #ifndef QT_NO_STATUSTIP 86 cbCheck4Updates->setStatusTip(tr("Automatically check for updates at the given interval")); 87 #endif // QT_NO_STATUSTIP 88 cbCheck4Updates->setText(tr("Check for updates every")); 89 cbCheck4Updates->setCursor(QCursor(Qt::PointingHandCursor)); 90 91 spinUpdateCheckInterval = new QSpinBox(bgWhite); 92 spinUpdateCheckInterval->setObjectName("spinUpdateCheckInterval"); 93 #ifndef QT_NO_STATUSTIP 94 spinUpdateCheckInterval->setStatusTip(tr("Minimal interval at which to check for updates")); 95 #endif // QT_NO_STATUSTIP 96 spinUpdateCheckInterval->setSuffix(tr(" days", "Don't forget a space at the beginning!")); 97 spinUpdateCheckInterval->setRange(1, 365); 98 spinUpdateCheckInterval->setCursor(QCursor(Qt::PointingHandCursor)); 99 100 connect(cbCheck4Updates, SIGNAL(toggled(bool)), spinUpdateCheckInterval, SLOT(setEnabled(bool))); 101 102 box = static_cast<QBoxLayout *>(tabGeneral->layout()); 103 hbox = new QHBoxLayout(); 104 hbox->setSpacing(0); 105 hbox->addWidget(cbCheck4Updates); 106 hbox->addWidget(spinUpdateCheckInterval); 107 hbox->addStretch(); 108 box->insertLayout(box->indexOf(cbUseNativeDialogs) + 1, hbox); 109 } else 110 cbCheck4Updates = NULL; 111 111 112 112 #ifdef HANDHELD … … 114 114 115 115 #ifdef Q_WS_WINCE_WM 116 117 118 116 // On screens with small height when SIP is shown and the window is resized 117 // there is not enought space for all elements. 118 // So we show the scrollbars to be able to access them. 119 119 QScrollArea *scrollArea = new QScrollArea(this); 120 121 122 123 120 scrollArea->setFrameShape(QFrame::NoFrame); 121 scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 122 scrollArea->setWidgetResizable(true); 123 scrollArea->setWidget(bgWhite); 124 124 #else 125 125 buttons->insertStretch(buttons->indexOf(buttonHelp) + 1); 126 126 #endif // Q_WS_WINCE_WM 127 127 128 129 130 131 132 133 128 bgWhite->layout()->setMargin(0); 129 130 // Central layout 131 vbox1 = new QVBoxLayout(this); 132 vbox1->setMargin(0); 133 vbox1->setSpacing(0); 134 134 #ifdef Q_WS_WINCE_WM 135 135 vbox1->addWidget(scrollArea); 136 136 #else 137 137 vbox1->addWidget(bgWhite); 138 138 #endif // Q_WS_WINCE_WM 139 140 139 vbox1->addWidget(bgGrey); 140 setLayout(vbox1); 141 141 #else // HANDHELD 142 142 QVBoxLayout *vbox; // Layout helper 143 143 144 144 #ifdef Q_WS_WIN32 145 146 147 148 #ifndef QT_NO_STATUSTIP 149 150 #endif // QT_NO_STATUSTIP 151 152 153 145 if (QtWin::isCompositionEnabled()) { 146 cbUseTranslucency = new QCheckBox(bgWhite); 147 cbUseTranslucency->setObjectName("cbUseTranslucency"); 148 #ifndef QT_NO_STATUSTIP 149 cbUseTranslucency->setStatusTip(tr("Use translucent effect on the Main Window under Windows Vista and 7")); 150 #endif // QT_NO_STATUSTIP 151 cbUseTranslucency->setText(tr("Use translucency effects")); 152 cbUseTranslucency->setCursor(QCursor(Qt::PointingHandCursor)); 153 } 154 154 #endif // Q_WS_WIN32 155 155 156 157 158 #ifndef QT_NO_STATUSTIP 159 160 #endif // QT_NO_STATUSTIP 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 156 cbSaveState = new QCheckBox(bgWhite); 157 cbSaveState->setObjectName("cbSaveState"); 158 #ifndef QT_NO_STATUSTIP 159 cbSaveState->setStatusTip(tr("Restore main window state and position on application restart")); 160 #endif // QT_NO_STATUSTIP 161 cbSaveState->setText(tr("Save main window state and position")); 162 cbSaveState->setCursor(QCursor(Qt::PointingHandCursor)); 163 164 imgIcon = new QLabel(this); 165 imgIcon->setObjectName("imgIcon"); 166 imgIcon->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Expanding); 167 imgIcon->setFrameShape(QFrame::NoFrame); 168 imgIcon->setPixmap(GET_ICON("preferences-system").pixmap(128, 128)); 169 imgIcon->setStyleSheet("background-color: #0080C0; padding-top: 11px;"); 170 imgIcon->setAlignment(Qt::AlignTop | Qt::AlignHCenter); 171 imgIcon->setMinimumWidth(150); 172 173 labelHint = new QLabel(bgGrey); 174 labelHint->setObjectName("labelHint"); 175 labelHint->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); 176 176 // labelHint->setMinimumSize(QSize(190,28)); 177 178 179 177 labelHint->setMinimumSize(QSize(0,28)); 178 labelHint->setMaximumSize(QSize(QWIDGETSIZE_MAX,28)); 179 labelHint->setTextFormat(Qt::PlainText); 180 180 // labelHint->setAlignment(Qt::AlignLeft | Qt::AlignTop); 181 182 #ifndef QT_NO_STATUSTIP 183 184 #endif // QT_NO_STATUSTIP 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 181 labelHint->setWordWrap(true); 182 #ifndef QT_NO_STATUSTIP 183 labelHint->setStatusTip(tr("Hover mouse pointer over dialog elements to get additional help")); 184 #endif // QT_NO_STATUSTIP 185 186 lineVertical = new QFrame(this); 187 lineVertical->setObjectName("lineVertical"); 188 lineVertical->setFrameShadow(QFrame::Plain); 189 lineVertical->setFrameShape(QFrame::VLine); 190 lineVertical->setLineWidth(2); 191 192 // Top line 193 hbox = new QHBoxLayout(); 194 hbox->addWidget(imgIcon); 195 hbox->addWidget(lineVertical); 196 hbox->addWidget(bgWhite); 197 198 box = static_cast<QBoxLayout *>(tabGeneral->layout()); 199 box->insertWidget(box->indexOf(cbUseNativeDialogs) + 1, cbSaveState); 200 200 #ifdef Q_WS_WIN32 201 202 201 if (QtWin::isCompositionEnabled()) 202 box->insertWidget(box->indexOf(cbUseNativeDialogs) + 1, cbUseTranslucency); 203 203 #endif // Q_WS_WIN32 204 204 205 206 207 208 209 210 211 212 213 214 205 // Inserting label for hints to the bottom part (with grey bg) 206 buttons->insertWidget(buttons->indexOf(buttonHelp) + 1, labelHint, 1); 207 208 // Central layout 209 vbox = new QVBoxLayout(this); 210 vbox->setMargin(0); 211 vbox->setSpacing(0); 212 vbox->addLayout(hbox); 213 vbox->addWidget(bgGrey); 214 setLayout(vbox); 215 215 #endif // HANDHELD 216 216 217 217 #ifdef Q_WS_WINCE_WM 218 219 218 // We need to react to SIP show/hide and resize the window appropriately 219 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), SLOT(desktopResized(int))); 220 220 #endif // Q_WS_WINCE_WM 221 222 223 224 221 connect(spinRandMin, SIGNAL(valueChanged(int)), SLOT(spinRandMinValueChanged(int))); 222 connect(buttonFont, SIGNAL(clicked()), SLOT(buttonFontClicked())); 223 connect(buttonColor, SIGNAL(clicked()), SLOT(buttonColorClicked())); 224 setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint); 225 225 #if !defined(QT_NO_STATUSTIP) && !defined(HANDHELD) 226 227 226 // Setting initial text of dialog hint label to own status tip text. 227 labelHint->setText(labelHint->statusTip()); 228 228 #endif // HANDHELD 229 229 230 231 232 233 234 235 230 settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this); 231 settings->remove("SettingsReset"); 232 233 cbAutosize->setChecked(settings->value("Autosize", DEF_AUTOSIZE).toBool()); 234 cbSaveLastUsed->setChecked(settings->value("SaveLastUsed", DEF_SAVE_LAST_USED).toBool()); 235 cbUseNativeDialogs->setChecked(settings->value("UseNativeDialogs", DEF_USE_NATIVE_DIALOGS).toBool()); 236 236 #ifdef Q_WS_WIN32 237 238 237 if (QtWin::isCompositionEnabled()) 238 cbUseTranslucency->setChecked(settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool()); 239 239 #endif // Q_WS_WIN32 240 240 #ifndef HANDHELD 241 241 cbSaveState->setChecked(settings->value("SavePos", DEF_SAVEPOS).toBool()); 242 242 #endif // HANDHELD 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 243 if (cbCheck4Updates != NULL) { 244 settings->beginGroup("Check4Updates"); 245 cbCheck4Updates->setChecked(settings->value("Enabled", DEF_CHECK_FOR_UPDATES).toBool()); 246 spinUpdateCheckInterval->setValue(settings->value("Interval", DEF_UPDATE_CHECK_INTERVAL).toInt()); 247 settings->endGroup(); 248 spinUpdateCheckInterval->setEnabled(cbCheck4Updates->isChecked()); 249 } 250 251 settings->beginGroup("Task"); 252 cbSymmetricMode->setChecked(settings->value("SymmetricMode", DEF_SYMMETRIC_MODE).toBool()); 253 spinFractionalAccuracy->setValue(settings->value("FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()); 254 spinRandMin->setMaximum(MAX_RAND_VALUE); 255 spinRandMin->setValue(settings->value("RandMin",DEF_RAND_MIN).toInt()); 256 spinRandMax->setMaximum(MAX_RAND_VALUE); 257 spinRandMax->setValue(settings->value("RandMax",DEF_RAND_MAX).toInt()); 258 cbFractionalRandom->setChecked(settings->value("FractionalRandom", DEF_FRACTIONAL_RANDOM).toBool()); 259 settings->endGroup(); 260 261 settings->beginGroup("Output"); 262 cbShowGraph->setChecked(settings->value("ShowGraph", DEF_SHOW_GRAPH).toBool()); 263 263 264 264 #ifndef QT_NO_PRINTER 265 266 265 cbHQGraph->setEnabled(cbShowGraph->isChecked()); 266 cbHQGraph->setChecked(settings->value("HQGraph", DEF_HQ_GRAPH && cbShowGraph->isChecked()).toBool()); 267 267 #endif 268 268 269 269 #if !defined(NOSVG) && (QT_VERSION >= 0x040500) 270 270 comboGraphImageFormat->addItem("svg"); 271 271 #endif // NOSVG && QT_VERSION >= 0x040500 272 273 274 272 // We create whitelist of formats, supported by the most popular web browsers according to 273 // http://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support 274 // + TIFF format (there are plugins to support it). 275 275 QStringList whitelist; 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 276 whitelist << "bmp" << "jpeg" << "png" << "tiff" << "xbm"; 277 foreach (QByteArray format, QImageWriter::supportedImageFormats()) { 278 if (whitelist.contains(format)) 279 comboGraphImageFormat->addItem(format); 280 } 281 comboGraphImageFormat->model()->sort(0); 282 comboGraphImageFormat->setCurrentIndex(comboGraphImageFormat->findText(settings->value("GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT).toString(), Qt::MatchFixedString)); 283 if (comboGraphImageFormat->currentIndex() < 0) 284 comboGraphImageFormat->setCurrentIndex(comboGraphImageFormat->findText(DEF_GRAPH_IMAGE_FORMAT, Qt::MatchFixedString)); 285 labelGraphImageFormat->setEnabled(cbShowGraph->isChecked()); 286 comboGraphImageFormat->setEnabled(cbShowGraph->isChecked()); 287 288 cbShowMatrix->setChecked(settings->value("ShowMatrix", DEF_SHOW_MATRIX).toBool()); 289 cbCitiesLimit->setEnabled(cbShowMatrix->isChecked()); 290 cbCitiesLimit->setChecked(settings->value("UseShowMatrixLimit", DEF_USE_SHOW_MATRIX_LIMIT && cbShowMatrix->isChecked()).toBool()); 291 spinCitiesLimit->setEnabled(cbShowMatrix->isChecked() && cbCitiesLimit->isChecked()); 292 spinCitiesLimit->setValue(settings->value("ShowMatrixLimit", DEF_SHOW_MATRIX_LIMIT).toInt()); 293 spinCitiesLimit->setMaximum(MAX_NUM_CITIES); 294 cbScrollToEnd->setChecked(settings->value("ScrollToEnd", DEF_SCROLL_TO_END).toBool()); 295 296 font = qvariant_cast<QFont>(settings->value("Font", QFont(DEF_FONT_FACE, DEF_FONT_SIZE))); 297 color = qvariant_cast<QColor>(settings->value("Colors/Text", DEF_TEXT_COLOR)); 298 settings->endGroup(); 299 299 300 300 #ifdef HANDHELD 301 301 setWindowState(Qt::WindowMaximized); 302 302 #else 303 303 adjustSize(); 304 304 #endif // Q_WS_WINCE_WM 305 305 } … … 311 311 bool SettingsDialog::colorChanged() const 312 312 { 313 313 return _newColor; 314 314 } 315 315 … … 320 320 bool SettingsDialog::fontChanged() const 321 321 { 322 322 return _newFont; 323 323 } 324 324 … … 331 331 qint8 SettingsDialog::translucencyChanged() const 332 332 { 333 333 return _translucency; 334 334 } 335 335 … … 338 338 void SettingsDialog::accept() 339 339 { 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 340 if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { 341 if (QMessageBox::question(this, tr("Settings Reset"), tr("Do you really want to <b>reset all application settings to their defaults</b>?"), QMessageBox::RestoreDefaults | QMessageBox::Cancel) == QMessageBox::RestoreDefaults) { 342 _newFont = (font != QFont(DEF_FONT_FACE, DEF_FONT_SIZE)); 343 _newColor = (color != DEF_TEXT_COLOR); 344 settings->remove(""); 345 settings->setValue("SettingsReset", true); 346 QDialog::accept(); 347 QMessageBox::information(this->parentWidget(), tr("Settings Reset"), tr("All settings where successfully reset to their defaults.\nIt is recommended to restart the application now.")); 348 return; 349 } else 350 return; 351 } 352 settings->setValue("Autosize", cbAutosize->isChecked()); 353 settings->setValue("SaveLastUsed", cbSaveLastUsed->isChecked()); 354 settings->setValue("UseNativeDialogs", cbUseNativeDialogs->isChecked()); 355 355 #ifdef Q_WS_WIN32 356 356 if (QtWin::isCompositionEnabled()) { 357 357 bool old = settings->value("UseTranslucency", DEF_USE_TRANSLUCENCY).toBool(); 358 359 360 361 362 363 358 if ((!old && cbUseTranslucency->isChecked()) || (old && !cbUseTranslucency->isChecked())) { 359 _translucency = old ? -1 : 1; 360 } else 361 _translucency = 0; 362 settings->setValue("UseTranslucency", cbUseTranslucency->isChecked()); 363 } 364 364 #endif // Q_WS_WIN32 365 365 #ifndef HANDHELD 366 366 settings->setValue("SavePos", cbSaveState->isChecked()); 367 367 #endif // HANDHELD 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 368 if (cbCheck4Updates != NULL) { 369 settings->beginGroup("Check4Updates"); 370 settings->setValue("Enabled", cbCheck4Updates->isChecked()); 371 if (cbCheck4Updates->isChecked()) 372 settings->setValue("Interval", spinUpdateCheckInterval->value()); 373 settings->endGroup(); 374 } 375 376 settings->beginGroup("Task"); 377 settings->setValue("SymmetricMode", cbSymmetricMode->isChecked()); 378 settings->setValue("FractionalAccuracy", spinFractionalAccuracy->value()); 379 settings->setValue("RandMin", spinRandMin->value()); 380 settings->setValue("RandMax", spinRandMax->value()); 381 settings->setValue("FractionalRandom", cbFractionalRandom->isChecked()); 382 settings->endGroup(); 383 384 settings->beginGroup("Output"); 385 settings->setValue("ShowGraph", cbShowGraph->isChecked()); 386 386 #ifndef QT_NO_PRINTER 387 387 settings->setValue("HQGraph", cbShowGraph->isChecked() && cbHQGraph->isChecked()); 388 388 #endif 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 389 if (cbShowGraph->isChecked()) { 390 if (comboGraphImageFormat->currentIndex() >= 0) 391 settings->setValue("GraphImageFormat", comboGraphImageFormat->currentText()); 392 else 393 settings->setValue("GraphImageFormat", DEF_GRAPH_IMAGE_FORMAT); 394 } 395 settings->setValue("ShowMatrix", cbShowMatrix->isChecked()); 396 settings->setValue("UseShowMatrixLimit", cbShowMatrix->isChecked() && cbCitiesLimit->isChecked()); 397 if (cbCitiesLimit->isChecked()) 398 settings->setValue("ShowMatrixLimit", spinCitiesLimit->value()); 399 settings->setValue("ScrollToEnd", cbScrollToEnd->isChecked()); 400 if (_newFont) 401 settings->setValue("Font", font); 402 if (_newColor) 403 settings->setValue("Colors/Text", color); 404 settings->endGroup(); 405 QDialog::accept(); 406 406 } 407 407 … … 409 409 { 410 410 QColor color = QColorDialog::getColor(this->color,this); 411 412 413 414 411 if (color.isValid() && (this->color != color)) { 412 this->color = color; 413 _newColor = true; 414 } 415 415 } 416 416 … … 419 419 bool ok; 420 420 QFont font = QFontDialog::getFont(&ok,this->font,this); 421 422 423 424 421 if (ok && (this->font != font)) { 422 this->font = font; 423 _newFont = true; 424 } 425 425 } 426 426 … … 428 428 void SettingsDialog::desktopResized(int screen) 429 429 { 430 431 430 if (screen != 0) 431 return; 432 432 433 433 QRect availableGeometry = QApplication::desktop()->availableGeometry(0); 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 434 if (currentGeometry != availableGeometry) { 435 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 436 /*! 437 * \hack HACK: This hack checks whether \link QDesktopWidget::availableGeometry() availableGeometry()\endlink's \c top + \c hegiht = \link QDesktopWidget::screenGeometry() screenGeometry()\endlink's \c height. 438 * If \c true, the window gets maximized. If we used \c setGeometry() in this case, the bottom of the 439 * window would end up being behind the soft buttons. Is this a bug in Qt or Windows Mobile? 440 */ 441 if ((availableGeometry.top() + availableGeometry.height()) == QApplication::desktop()->screenGeometry().height()) { 442 setWindowState(windowState() | Qt::WindowMaximized); 443 } else { 444 if (windowState() & Qt::WindowMaximized) 445 setWindowState(windowState() ^ Qt::WindowMaximized); 446 setGeometry(availableGeometry); 447 } 448 currentGeometry = availableGeometry; 449 QApplication::restoreOverrideCursor(); 450 } 451 451 } 452 452 453 453 void SettingsDialog::showEvent(QShowEvent *ev) 454 454 { 455 456 457 455 desktopResized(0); 456 457 QWidget::showEvent(ev); 458 458 } 459 459 #endif // Q_WS_WINCE_WM 460 460 461 461 void SettingsDialog::spinRandMinValueChanged(int val) { 462 462 spinRandMax->setMinimum(val); 463 463 } 464 464 … … 466 466 bool SettingsDialog::event(QEvent *ev) 467 467 { 468 469 470 471 468 // Checking for StatusTip event and if tip text is not empty string 469 // setting it as text of the dialog hint label. Otherwise, setting 470 // dialog hint label text to own status tip text. 471 if (ev->type() == QEvent::StatusTip) { 472 472 QString tip = static_cast<QStatusTipEvent *>(ev)->tip(); 473 474 475 476 477 478 479 473 if (tip.length() != 0) 474 labelHint->setText(tip); 475 else 476 labelHint->setText(labelHint->statusTip()); 477 return true; 478 } else 479 return QDialog::event(ev); 480 480 } 481 481 #endif // HANDHELD -
trunk/src/settingsdialog.h
r143 r149 39 39 class SettingsDialog: public QDialog, Ui::SettingsDialog 40 40 { 41 41 Q_OBJECT 42 42 public: 43 44 45 46 43 SettingsDialog(QWidget *parent = 0); 44 bool colorChanged() const; 45 bool fontChanged() const; 46 qint8 translucencyChanged() const; 47 47 48 48 private: 49 50 51 49 bool _newFont; 50 bool _newColor; 51 qint8 _translucency; 52 52 53 54 53 QColor color; 54 QFont font; 55 55 56 57 56 QSettings *settings; 57 QHBoxLayout *layoutCitiesLimit; 58 58 #ifdef Q_WS_WIN32 59 59 QCheckBox *cbUseTranslucency; 60 60 #endif // Q_WS_WIN32 61 62 61 QCheckBox *cbCheck4Updates; 62 QSpinBox *spinUpdateCheckInterval; 63 63 #ifndef QT_NO_PRINTER 64 64 QCheckBox *cbHQGraph; 65 65 #endif 66 66 #ifdef Q_WS_WINCE_WM 67 67 QRect currentGeometry; 68 68 #elif !defined(HANDHELD) 69 70 71 72 69 QCheckBox *cbSaveState; 70 QLabel *imgIcon; 71 QFrame *lineVertical; 72 QLabel *labelHint; 73 73 74 74 #ifndef QT_NO_STATUSTIP 75 75 bool event(QEvent *ev); 76 76 #endif // QT_NO_STATUSTIP 77 77 #endif // Q_WS_WINCE_WM 78 78 79 79 private slots: 80 81 82 80 void accept(); 81 void buttonColorClicked(); 82 void buttonFontClicked(); 83 83 #ifdef Q_WS_WINCE_WM 84 85 84 void desktopResized(int screen); 85 void showEvent(QShowEvent *ev); 86 86 #endif // Q_WS_WINCE_WM 87 87 void spinRandMinValueChanged(int val); 88 88 }; 89 89 -
trunk/src/tspmodel.cpp
r116 r149 29 29 */ 30 30 CTSPModel::CTSPModel(QObject *parent) 31 32 { 33 31 : QAbstractTableModel(parent), nCities(0) 32 { 33 settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TSPSG", "tspsg", this); 34 34 } 35 35 … … 41 41 void CTSPModel::clear() 42 42 { 43 44 45 46 47 43 for (int r = 0; r < nCities; r++) 44 for (int c = 0; c < nCities; c++) 45 if (r != c) 46 table[r][c] = 0; 47 emit dataChanged(index(0,0),index(nCities - 1,nCities - 1)); 48 48 } 49 49 … … 58 58 int CTSPModel::columnCount(const QModelIndex &) const 59 59 { 60 60 return nCities; 61 61 } 62 62 … … 71 71 QVariant CTSPModel::data(const QModelIndex &index, int role) const 72 72 { 73 74 75 76 77 73 if (!index.isValid()) 74 return QVariant(); 75 if (role == Qt::TextAlignmentRole) 76 return int(Qt::AlignCenter); 77 else if (role == Qt::FontRole) { 78 78 QFont font; 79 80 81 82 83 84 85 86 87 88 89 90 91 92 79 font.setBold(true); 80 return font; 81 } else if (role == Qt::DisplayRole || role == Qt::EditRole) { 82 if (index.row() < nCities && index.column() < nCities) 83 if (table.at(index.row()).at(index.column()) == INFINITY) 84 return tr(INFSTR); 85 else 86 //! \hack HACK: Converting to string to prevent spinbox in edit mode 87 return QVariant(table.at(index.row()).at(index.column())).toString(); 88 else 89 return QVariant(); 90 } else if (role == Qt::UserRole) 91 return table[index.row()][index.column()]; 92 return QVariant(); 93 93 } 94 94 … … 101 101 { 102 102 Qt::ItemFlags flags = QAbstractItemModel::flags(index); 103 104 105 103 if (index.row() != index.column()) 104 flags |= Qt::ItemIsEditable; 105 return flags; 106 106 } 107 107 … … 117 117 QVariant CTSPModel::headerData(int section, Qt::Orientation orientation, int role) const 118 118 { 119 120 121 122 123 124 125 119 if (role == Qt::DisplayRole) { 120 if (orientation == Qt::Vertical) 121 return tr("City %1").arg(section + 1); 122 else 123 return tr("%1").arg(section + 1); 124 } 125 return QVariant(); 126 126 } 127 127 … … 135 135 bool CTSPModel::loadTask(const QString &fname) 136 136 { 137 137 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 138 138 QFile f(fname); 139 140 141 142 143 144 145 139 if (!f.open(QIODevice::ReadOnly)) { 140 QApplication::restoreOverrideCursor(); 141 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 142 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), QString(tr("Unable to open task file.\nError: %1")).arg(f.errorString())); 143 QApplication::restoreOverrideCursor(); 144 return false; 145 } 146 146 QDataStream ds(&f); 147 147 ds.setVersion(QDataStream::Qt_4_4); 148 148 quint32 sig; 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 149 ds >> sig; 150 if (loadError(ds.status())) { 151 return false; 152 } 153 ds.device()->reset(); 154 if (sig == TSPT) { 155 if (!loadTSPT(&ds)) { 156 f.close(); 157 return false; 158 } 159 } else if ((sig >> 16) == ZKT) { 160 if (!loadZKT(&ds)) { 161 f.close(); 162 return false; 163 } 164 } else { 165 f.close(); 166 QApplication::restoreOverrideCursor(); 167 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 168 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), tr("Unable to load task:") + "\n" + tr("Unknown file format or file is corrupted.")); 169 QApplication::restoreOverrideCursor(); 170 return false; 171 } 172 f.close(); 173 QApplication::restoreOverrideCursor(); 174 return true; 175 175 } 176 176 … … 183 183 quint16 CTSPModel::numCities() const 184 184 { 185 185 return nCities; 186 186 } 187 187 … … 197 197 int randMin = settings->value("Task/RandMin", DEF_RAND_MIN).toInt(); 198 198 int randMax = settings->value("Task/RandMax", DEF_RAND_MAX).toInt(); 199 200 201 202 203 204 205 206 207 208 209 199 if (settings->value("Task/SymmetricMode", DEF_SYMMETRIC_MODE).toBool()) { 200 for (int r = 0; r < nCities; r++) 201 for (int c = 0; c < r; c++) 202 table[c][r] = table[r][c] = rand(randMin, randMax); 203 } else { 204 for (int r = 0; r < nCities; r++) 205 for (int c = 0; c < nCities; c++) 206 if (r != c) 207 table[r][c] = rand(randMin, randMax); 208 } 209 emit dataChanged(index(0,0), index(nCities - 1, nCities - 1)); 210 210 } 211 211 … … 220 220 int CTSPModel::rowCount(const QModelIndex &) const 221 221 { 222 222 return nCities; 223 223 } 224 224 … … 232 232 bool CTSPModel::saveTask(const QString &fname) 233 233 { 234 234 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 235 235 QFile f(fname); 236 237 238 239 240 241 236 if (!f.open(QIODevice::WriteOnly)) { 237 QApplication::restoreOverrideCursor(); 238 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), QString(tr("Unable to create task file.\nError: %1\nMaybe, file is read-only?")).arg(f.errorString())); 239 f.remove(); 240 return false; 241 } 242 242 QDataStream ds(&f); 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 243 ds.setVersion(QDataStream::Qt_4_4); 244 if (f.error() != QFile::NoError) { 245 QApplication::restoreOverrideCursor(); 246 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 247 f.close(); 248 f.remove(); 249 return false; 250 } 251 // File signature 252 ds << TSPT; 253 if (f.error() != QFile::NoError) { 254 QApplication::restoreOverrideCursor(); 255 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 256 f.close(); 257 f.remove(); 258 return false; 259 } 260 // File version 261 ds << TSPT_VERSION; 262 if (f.error() != QFile::NoError) { 263 QApplication::restoreOverrideCursor(); 264 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 265 f.close(); 266 f.remove(); 267 return false; 268 } 269 // File metadata version 270 ds << TSPT_META_VERSION; 271 if (f.error() != QFile::NoError) { 272 QApplication::restoreOverrideCursor(); 273 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 274 f.close(); 275 f.remove(); 276 return false; 277 } 278 // Metadata 279 ds << OSID; 280 if (f.error() != QFile::NoError) { 281 QApplication::restoreOverrideCursor(); 282 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 283 f.close(); 284 f.remove(); 285 return false; 286 } 287 // Number of cities 288 ds << nCities; 289 if (f.error() != QFile::NoError) { 290 QApplication::restoreOverrideCursor(); 291 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 292 f.close(); 293 f.remove(); 294 return false; 295 } 296 // Costs 297 for (int r = 0; r < nCities; r++) 298 for (int c = 0; c < nCities; c++) 299 if (r != c) { 300 ds << static_cast<double>(table[r][c]); // We cast to double because double may be float on some platforms and we store double values in file 301 if (f.error() != QFile::NoError) { 302 QApplication::restoreOverrideCursor(); 303 QMessageBox::critical(QApplication::activeWindow(), tr("Task Save"), tr("Unable to save task.\nError: %1").arg(f.errorString())); 304 f.close(); 305 f.remove(); 306 return false; 307 } 308 } 309 f.close(); 310 QApplication::restoreOverrideCursor(); 311 return true; 312 312 } 313 313 … … 323 323 bool CTSPModel::setData(const QModelIndex &index, const QVariant &value, int role) 324 324 { 325 326 327 328 329 330 325 if (!index.isValid()) 326 return false; 327 if (role == Qt::EditRole && index.row() != index.column()) { 328 if (value.toString().compare(INFSTR) == 0) 329 table[index.row()][index.column()] = INFINITY; 330 else { 331 331 bool ok; 332 332 double tmp = value.toDouble(&ok); 333 334 335 336 337 338 339 340 341 342 343 344 333 if (!ok || tmp < 0) 334 return false; 335 else { 336 table[index.row()][index.column()] = tmp; 337 if (settings->value("Task/SymmetricMode", DEF_SYMMETRIC_MODE).toBool()) 338 table[index.column()][index.row()] = tmp; 339 } 340 } 341 emit dataChanged(index,index); 342 return true; 343 } 344 return false; 345 345 } 346 346 … … 353 353 void CTSPModel::setNumCities(int n) 354 354 { 355 356 357 358 359 360 361 362 363 364 365 366 355 if (n == nCities) 356 return; 357 emit layoutAboutToBeChanged(); 358 table.resize(n); 359 for (int k = 0; k < n; k++) { 360 table[k].resize(n); 361 } 362 if (n > nCities) 363 for (int k = nCities; k < n; k++) 364 table[k][k] = INFINITY; 365 nCities = n; 366 emit layoutChanged(); 367 367 } 368 368 … … 372 372 { 373 373 QString err; 374 375 376 377 378 379 380 381 382 383 384 385 386 374 if (status == QDataStream::Ok) 375 return false; 376 else if (status == QDataStream::ReadPastEnd) 377 err = tr("Unexpected end of file."); 378 else if (status == QDataStream::ReadCorruptData) 379 err = tr("Corrupt data read. File possibly corrupted."); 380 else 381 err = tr("Unknown error."); 382 QApplication::restoreOverrideCursor(); 383 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 384 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), tr("Unable to load task:") + "\n" + err); 385 QApplication::restoreOverrideCursor(); 386 return true; 387 387 } 388 388 389 389 bool CTSPModel::loadTSPT(QDataStream *ds) 390 390 { 391 392 393 394 395 391 // Skipping signature 392 ds->skipRawData(sizeof(TSPT)); 393 if (loadError(ds->status())) 394 return false; 395 // File version 396 396 quint8 version; 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 397 *ds >> version; 398 if (loadError(ds->status())) 399 return false; 400 if (version > TSPT_VERSION) { 401 QApplication::restoreOverrideCursor(); 402 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 403 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), tr("Unable to load task:") + "\n" + tr("File version is newer than application supports.\nPlease, try to update application.")); 404 QApplication::restoreOverrideCursor(); 405 return false; 406 } 407 // Skipping metadata 408 ds->skipRawData(TSPT_META_SIZE); 409 if (loadError(ds->status())) 410 return false; 411 // Number of cities 412 412 quint16 size; 413 414 415 416 417 418 419 420 421 422 423 424 425 426 413 *ds >> size; 414 if (loadError(ds->status())) 415 return false; 416 if ((size < 3) || (size > MAX_NUM_CITIES)) { 417 QApplication::restoreOverrideCursor(); 418 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 419 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), tr("Unable to load task:") + "\n" + tr("Unexpected data read.\nFile is possibly corrupted.")); 420 QApplication::restoreOverrideCursor(); 421 return false; 422 } 423 if (nCities != size) { 424 setNumCities(size); 425 emit numCitiesChanged(size); 426 } 427 427 428 428 double x; // We need this as double may be float on some platforms and we store double values in file 429 430 431 432 433 434 435 436 437 438 439 440 441 442 429 // Travel costs 430 for (int r = 0; r < size; r++) 431 for (int c = 0; c < size; c++) 432 if (r != c) { 433 *ds >> x; 434 table[r][c] = x; 435 if (loadError(ds->status())) { 436 clear(); 437 return false; 438 } 439 } 440 emit dataChanged(index(0,0),index(nCities - 1,nCities - 1)); 441 QApplication::restoreOverrideCursor(); 442 return true; 443 443 } 444 444 445 445 bool CTSPModel::loadZKT(QDataStream *ds) 446 446 { 447 448 449 450 451 447 // Skipping signature 448 ds->skipRawData(sizeof(ZKT)); 449 if (loadError(ds->status())) 450 return false; 451 // File version 452 452 quint16 version; 453 454 455 456 457 458 459 460 461 462 463 453 ds->readRawData(reinterpret_cast<char *>(&version),2); 454 if (loadError(ds->status())) 455 return false; 456 if (version > ZKT_VERSION) { 457 QApplication::restoreOverrideCursor(); 458 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 459 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), tr("Unable to load task:") + "\n" + tr("File version is newer than application supports.\nPlease, try to update application.")); 460 QApplication::restoreOverrideCursor(); 461 return false; 462 } 463 // Number of cities 464 464 quint8 size; 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 465 ds->readRawData(reinterpret_cast<char *>(&size),1); 466 if (loadError(ds->status())) 467 return false; 468 if ((size < 3) || (size > 5)) { 469 QApplication::restoreOverrideCursor(); 470 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 471 QMessageBox::critical(QApplication::activeWindow(), tr("Task Load"), tr("Unable to load task:") + "\n" + tr("Unexpected data read.\nFile is possibly corrupted.")); 472 QApplication::restoreOverrideCursor(); 473 return false; 474 } 475 if (nCities != size) { 476 setNumCities(size); 477 emit numCitiesChanged(size); 478 } 479 // Travel costs 480 480 double val; 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 481 for (int r = 0; r < 5; r++) 482 for (int c = 0; c < 5; c++) 483 if ((r != c) && (r < size) && (c < size)) { 484 ds->readRawData(reinterpret_cast<char *>(&val),8); 485 if (loadError(ds->status())) { 486 clear(); 487 return false; 488 } 489 table[r][c] = val; 490 } else { 491 ds->skipRawData(8); 492 if (loadError(ds->status())) { 493 clear(); 494 return false; 495 } 496 } 497 emit dataChanged(index(0,0),index(nCities - 1,nCities - 1)); 498 QApplication::restoreOverrideCursor(); 499 return true; 500 500 } 501 501 … … 503 503 { 504 504 double r; 505 505 if (settings->value("Task/FractionalRandom", DEF_FRACTIONAL_RANDOM).toBool()) { 506 506 double x = qPow(10, settings->value("Task/FractionalAccuracy", DEF_FRACTIONAL_ACCURACY).toInt()); 507 508 509 510 511 } 507 r = (double)qRound((double)qrand() / RAND_MAX * (max - min) * x) / x; 508 } else 509 r = qRound((double)qrand() / RAND_MAX * (max - min)); 510 return min + r; 511 } -
trunk/src/tspmodel.h
r116 r149 37 37 class CTSPModel: public QAbstractTableModel 38 38 { 39 39 Q_OBJECT 40 40 41 41 public: 42 43 44 45 46 47 48 49 50 51 52 53 54 42 CTSPModel(QObject *parent = 0); 43 void clear(); 44 int columnCount(const QModelIndex &parent = QModelIndex()) const; 45 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 46 Qt::ItemFlags flags(const QModelIndex &index) const; 47 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 48 bool loadTask(const QString &fname); 49 quint16 numCities() const; 50 void randomize(); 51 int rowCount(const QModelIndex &parent = QModelIndex()) const; 52 bool saveTask(const QString &fname); 53 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); 54 void setNumCities(int n); 55 55 56 56 signals: 57 58 59 60 61 62 57 /*! 58 * \brief This signal is emitted whenever the number of cities in the task changes. 59 * 60 * \sa setNumCities() 61 */ 62 void numCitiesChanged(int); 63 63 64 64 private: 65 66 67 68 69 70 71 65 QSettings *settings; 66 QVector<QVector<double> > table; 67 quint16 nCities; 68 bool loadError(QDataStream::Status); 69 bool loadTSPT(QDataStream *); 70 bool loadZKT(QDataStream *); 71 double rand(int, int) const; 72 72 }; 73 73 -
trunk/src/tspsolver.cpp
r124 r149 35 35 QString CTSPSolver::getVersionId() 36 36 { 37 37 return QString("$Id$"); 38 38 } 39 39 … … 43 43 */ 44 44 CTSPSolver::CTSPSolver(QObject *parent) 45 45 : QObject(parent), cc(true), nCities(0), total(0), root(NULL) {} 46 46 47 47 /*! … … 55 55 void CTSPSolver::cleanup(bool processEvents) 56 56 { 57 58 59 60 57 route.clear(); 58 mayNotBeOptimal = false; 59 if (root != NULL) 60 deleteTree(root, processEvents); 61 61 } 62 62 … … 72 72 QString CTSPSolver::getSortedPath(const QString &city, const QString &separator) const 73 73 { 74 75 74 if (!root || route.isEmpty() || (route.size() != nCities)) 75 return QString(); 76 76 77 77 int i = 0; // We start from City 1 78 78 QStringList path; 79 80 81 82 83 84 85 86 79 path << city.arg(1); 80 while ((i = route[i]) != 0) { 81 path << city.arg(i + 1); 82 } 83 // And finish in City 1, too 84 path << city.arg(1); 85 86 return path.join(separator); 87 87 } 88 88 … … 94 94 int CTSPSolver::getTotalSteps() const 95 95 { 96 96 return total; 97 97 } 98 98 … … 106 106 bool CTSPSolver::isOptimal() const 107 107 { 108 108 return !mayNotBeOptimal; 109 109 } 110 110 … … 121 121 void CTSPSolver::setCleanupOnCancel(bool enable) 122 122 { 123 123 cc = enable; 124 124 } 125 125 … … 134 134 SStep *CTSPSolver::solve(int numCities, const TMatrix &task) 135 135 { 136 137 136 if (numCities < 3) 137 return NULL; 138 138 139 139 QMutexLocker locker(&mutex); 140 141 142 143 144 140 cleanup(); 141 canceled = false; 142 locker.unlock(); 143 144 nCities = numCities; 145 145 146 146 SStep *step = new SStep(); 147 148 149 150 151 147 step->matrix = task; 148 // We need to distinguish the values forbidden by the user 149 // from the values forbidden by the algorithm. 150 // So we replace user's infinities by the maximum available double value. 151 normalize(step->matrix); 152 152 #ifdef DEBUG 153 153 qDebug() << step->matrix; 154 154 #endif // DEBUG 155 156 155 step->price = align(step->matrix); 156 root = step; 157 157 158 158 SStep *left, *right; … … 160 160 bool firstStep = true; 161 161 double check = INFINITY; 162 163 164 165 166 162 total = 0; 163 while (route.size() < nCities) { 164 step->alts = findCandidate(step->matrix,nRow,nCol); 165 166 while (hasSubCycles(nRow,nCol)) { 167 167 #ifdef DEBUG 168 168 qDebug() << "Forbidden: (" << nRow << ";" << nCol << ")"; 169 169 #endif // DEBUG 170 171 172 173 170 step->matrix[nRow][nCol] = INFINITY; 171 step->price += align(step->matrix); 172 step->alts = findCandidate(step->matrix,nRow,nCol); 173 } 174 174 175 175 #ifdef DEBUG 176 177 178 176 qDebug() /*<< step->matrix*/ << "Selected: (" << nRow << ";" << nCol << ")"; 177 qDebug() << "Alternate:" << step->alts; 178 qDebug() << "Step price:" << step->price << endl; 179 179 #endif // DEBUG 180 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 181 locker.relock(); 182 if ((nRow == -1) || (nCol == -1) || canceled) { 183 if (canceled && cc) 184 cleanup(); 185 return NULL; 186 } 187 locker.unlock(); 188 189 // Route with (nRow,nCol) path 190 right = new SStep(); 191 right->pNode = step; 192 right->matrix = step->matrix; 193 for (int k = 0; k < nCities; k++) { 194 if (k != nCol) 195 right->matrix[nRow][k] = INFINITY; 196 if (k != nRow) 197 right->matrix[k][nCol] = INFINITY; 198 } 199 right->price = step->price + align(right->matrix); 200 // Forbid the selected route to exclude its reuse in next steps. 201 right->matrix[nCol][nRow] = INFINITY; 202 right->matrix[nRow][nCol] = INFINITY; 203 204 // Route without (nRow,nCol) path 205 left = new SStep(); 206 left->pNode = step; 207 left->matrix = step->matrix; 208 left->matrix[nRow][nCol] = INFINITY; 209 left->price = step->price + align(left->matrix); 210 211 step->candidate.nRow = nRow; 212 step->candidate.nCol = nCol; 213 step->plNode = left; 214 step->prNode = right; 215 216 // This matrix is not used anymore. Restoring infinities back. 217 denormalize(step->matrix); 218 219 if (right->price <= left->price) { 220 // Route with (nRow,nCol) path is cheaper 221 step->next = SStep::RightBranch; 222 step = right; 223 route[nRow] = nCol; 224 emit routePartFound(route.size()); 225 if (firstStep) { 226 check = left->price; 227 firstStep = false; 228 } 229 } else { 230 // Route without (nRow,nCol) path is cheaper 231 step->next = SStep::LeftBranch; 232 step = left; 233 QCoreApplication::processEvents(); 234 if (firstStep) { 235 check = right->price; 236 firstStep = false; 237 } 238 } 239 total++; 240 } 241 242 mayNotBeOptimal = (check < step->price); 243 244 return root; 245 245 } 246 246 … … 252 252 { 253 253 QMutexLocker locker(&mutex); 254 254 return canceled; 255 255 } 256 256 … … 261 261 { 262 262 QMutexLocker locker(&mutex); 263 263 canceled = true; 264 264 } 265 265 266 266 CTSPSolver::~CTSPSolver() 267 267 { 268 269 268 if (root != NULL) 269 deleteTree(root); 270 270 } 271 271 … … 276 276 double r = 0; 277 277 double min; 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 278 for (int k = 0; k < nCities; k++) { 279 min = findMinInRow(k,matrix); 280 if (min > 0) { 281 r += min; 282 if (min < MAX_DOUBLE) 283 subRow(matrix,k,min); 284 } 285 } 286 for (int k = 0; k < nCities; k++) { 287 min = findMinInCol(k,matrix); 288 if (min > 0) { 289 r += min; 290 if (min < MAX_DOUBLE) 291 subCol(matrix,k,min); 292 } 293 } 294 return (r != MAX_DOUBLE) ? r : INFINITY; 295 295 } 296 296 297 297 void CTSPSolver::deleteTree(SStep *&root, bool processEvents) 298 298 { 299 300 299 if (root == NULL) 300 return; 301 301 SStep *step = root; 302 302 SStep *parent; 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 303 forever { 304 if (processEvents) 305 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 306 if (step->plNode != NULL) { 307 // We have left child node - going inside it 308 step = step->plNode; 309 step->pNode->plNode = NULL; 310 continue; 311 } else if (step->prNode != NULL) { 312 // We have right child node - going inside it 313 step = step->prNode; 314 step->pNode->prNode = NULL; 315 continue; 316 } else { 317 // We have no child nodes. Deleting the current one. 318 parent = step->pNode; 319 delete step; 320 if (parent != NULL) { 321 // Going back to the parent node. 322 step = parent; 323 } else { 324 // We came back to the root node. Finishing. 325 root = NULL; 326 break; 327 } 328 } 329 } 330 330 } 331 331 332 332 void CTSPSolver::denormalize(TMatrix &matrix) const 333 333 { 334 335 336 337 334 for (int r = 0; r < nCities; r++) 335 for (int c = 0; c < nCities; c++) 336 if ((r != c) && (matrix.at(r).at(c) == MAX_DOUBLE)) 337 matrix[r][c] = INFINITY; 338 338 } 339 339 340 340 QList<SStep::SCandidate> CTSPSolver::findCandidate(const TMatrix &matrix, int &nRow, int &nCol) const 341 341 { 342 343 342 nRow = -1; 343 nCol = -1; 344 344 QList<SStep::SCandidate> alts; 345 345 SStep::SCandidate cand; 346 346 double h = -1; 347 347 double sum; 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 348 for (int r = 0; r < nCities; r++) 349 for (int c = 0; c < nCities; c++) 350 if (matrix.at(r).at(c) == 0) { 351 sum = findMinInRow(r,matrix,c) + findMinInCol(c,matrix,r); 352 if (sum > h) { 353 h = sum; 354 nRow = r; 355 nCol = c; 356 alts.clear(); 357 } else if ((sum == h) && !hasSubCycles(r,c)) { 358 cand.nRow = r; 359 cand.nCol = c; 360 alts.append(cand); 361 } 362 } 363 return alts; 364 364 } 365 365 … … 367 367 { 368 368 double min = INFINITY; 369 370 371 372 369 for (int k = 0; k < nCities; k++) 370 if ((k != exr) && (min > matrix.at(k).at(nCol))) 371 min = matrix.at(k).at(nCol); 372 return (min == INFINITY) ? 0 : min; 373 373 } 374 374 … … 376 376 { 377 377 double min = INFINITY; 378 379 380 381 382 378 for (int k = 0; k < nCities; k++) { 379 if (((k != exc)) && (min > matrix.at(nRow).at(k))) 380 min = matrix.at(nRow).at(k); 381 } 382 return (min == INFINITY) ? 0 : min; 383 383 } 384 384 385 385 bool CTSPSolver::hasSubCycles(int nRow, int nCol) const 386 386 { 387 388 387 if ((nRow < 0) || (nCol < 0) || route.isEmpty() || !(route.size() < nCities - 1) || !route.contains(nCol)) 388 return false; 389 389 int i = nCol; 390 391 392 393 394 395 396 390 forever { 391 if ((i = route.value(i)) == nRow) 392 return true; 393 if (!route.contains(i)) 394 return false; 395 } 396 return false; 397 397 } 398 398 399 399 void CTSPSolver::normalize(TMatrix &matrix) const 400 400 { 401 402 403 404 401 for (int r = 0; r < nCities; r++) 402 for (int c = 0; c < nCities; c++) 403 if ((r != c) && (matrix.at(r).at(c) == INFINITY)) 404 matrix[r][c] = MAX_DOUBLE; 405 405 } 406 406 407 407 void CTSPSolver::subCol(TMatrix &matrix, int nCol, double val) 408 408 { 409 410 411 409 for (int k = 0; k < nCities; k++) 410 if (k != nCol) 411 matrix[k][nCol] -= val; 412 412 } 413 413 414 414 void CTSPSolver::subRow(TMatrix &matrix, int nRow, double val) 415 415 { 416 417 418 416 for (int k = 0; k < nCities; k++) 417 if (k != nRow) 418 matrix[nRow][k] -= val; 419 419 } 420 420 … … 424 424 QDebug operator<<(QDebug dbg, const TSPSolver::TMatrix &matrix) 425 425 { 426 427 428 429 430 431 426 for (int r = 0; r < matrix.count(); r++) { 427 for (int c = 0; c < matrix.at(r).count(); c++) 428 dbg.space() << QString::number(matrix.at(r).at(c)).leftJustified(5); 429 dbg << endl; 430 } 431 return dbg; 432 432 } 433 433 434 434 QDebug operator<<(QDebug dbg, const TSPSolver::SStep::SCandidate &cand) 435 435 { 436 437 436 dbg.nospace() << "(" << cand.nRow << ";" << cand.nCol << ")"; 437 return dbg; 438 438 } 439 439 #endif // DEBUG -
trunk/src/tspsolver.h
r124 r149 40 40 */ 41 41 #ifdef INFINITY 42 #undef INFINITY42 # undef INFINITY 43 43 #endif 44 44 #define INFINITY std::numeric_limits<double>::infinity() … … 60 60 */ 61 61 struct SStep { 62 63 64 65 62 //! A structure that represents a candidate for branching 63 struct SCandidate { 64 int nRow; //!< A zero-based row number of the candidate 65 int nCol; //!< A zero-based column number of the candidate 66 66 67 68 69 70 71 72 73 74 75 67 //! Assigns default values 68 SCandidate() { 69 nCol = nRow = -1; 70 } 71 //! An operator == implementation 72 bool operator ==(const SCandidate &cand) const { 73 return ((cand.nRow == nRow) && (cand.nCol == nCol)); 74 } 75 }; 76 76 77 78 79 80 81 82 77 //! An enum that describes possible selection of the next step 78 enum NextStep { 79 NoNextStep, //!< No next step (end of solution) 80 LeftBranch, //!< Left branch was selected for the next step 81 RightBranch //!< Right branch was selected for the next step 82 }; 83 83 84 85 84 TMatrix matrix; //!< This step's matrix 85 double price; //!< The price of travel to this step 86 86 87 88 89 90 91 92 87 SCandidate candidate; //!< A candiadate for branching in the current step 88 QList<SCandidate> alts; //!< A list of alternative branching candidates 89 SStep *pNode; //!< Pointer to the parent step 90 SStep *plNode; //!< Pointer to the left branch step 91 SStep *prNode; //!< Pointer to the right branch step 92 NextStep next; //!< Indicates what branch was selected for the next step 93 93 94 95 96 97 98 99 94 //! Assigns default values 95 SStep() { 96 price = -1; 97 pNode = plNode = prNode = NULL; 98 next = NoNextStep; 99 } 100 100 }; 101 101 … … 106 106 class CTSPSolver: public QObject 107 107 { 108 108 Q_OBJECT 109 109 110 110 public: 111 111 static QString getVersionId(); 112 112 113 114 115 116 117 118 119 120 121 113 CTSPSolver(QObject *parent = NULL); 114 void cleanup(bool processEvents = false); 115 QString getSortedPath(const QString &city, const QString &separator = QString(" -> ")) const; 116 int getTotalSteps() const; 117 bool isOptimal() const; 118 void setCleanupOnCancel(bool enable = true); 119 SStep *solve(int numCities, const TMatrix &task); 120 bool wasCanceled() const; 121 ~CTSPSolver(); 122 122 123 123 public slots: 124 124 void cancel(); 125 125 126 126 signals: 127 128 129 130 131 127 /*! 128 * \brief This signal is emitted once every time a part of the route is found. 129 * \param n Indicates the number of the route parts found. 130 */ 131 void routePartFound(int n); 132 132 133 133 private: 134 135 136 137 138 134 bool mayNotBeOptimal, canceled, cc; 135 int nCities, total; 136 SStep *root; 137 QHash<int,int> route; 138 mutable QMutex mutex; 139 139 140 141 142 143 144 145 146 147 148 149 150 140 double align(TMatrix &matrix); 141 void deleteTree(SStep *&root, bool processEvents = false); 142 void denormalize(TMatrix &matrix) const; 143 QList<SStep::SCandidate> findCandidate(const TMatrix &matrix, int &nRow, int &nCol) const; 144 double findMinInCol(int nCol, const TMatrix &matrix, int exr = -1) const; 145 double findMinInRow(int nRow, const TMatrix &matrix, int exc = -1) const; 146 void finishRoute(); 147 bool hasSubCycles(int nRow, int nCol) const; 148 void normalize(TMatrix &matrix) const; 149 void subCol(TMatrix &matrix, int nCol, double val); 150 void subRow(TMatrix &matrix, int nRow, double val); 151 151 }; 152 152 -
trunk/src/version.h
r147 r149 30 30 31 31 #ifndef BUILD_VERSION_MAJOR 32 33 #define BUILD_VERSION_MAJOR 032 //! Major version of current TSPSG build 33 # define BUILD_VERSION_MAJOR 0 34 34 #endif // BUILD_VERSION_MAJOR 35 35 #ifndef BUILD_VERSION_MINOR 36 37 #define BUILD_VERSION_MINOR 036 //! Minor version of current TSPSG build 37 # define BUILD_VERSION_MINOR 0 38 38 #endif // BUILD_VERSION_MINOR 39 39 #ifndef BUILD_RELEASE 40 41 #define BUILD_RELEASE 040 //! TSPSG release number 41 # define BUILD_RELEASE 0 42 42 #endif // BUILD_RELEASE 43 43 44 44 #ifndef BUILD_NUMBER 45 46 #define BUILD_NUMBER 045 //! Current TSPSG build number 46 # define BUILD_NUMBER 0 47 47 #endif // BUILD_NUMBER 48 48 … … 52 52 */ 53 53 #ifdef DEBUG 54 #ifndef BUILD_STATUS_TYPE55 #define BUILD_STATUS (debug build BUILD_NUMBER)56 #else57 #define BUILD_STATUS (debug BUILD_STATUS_TYPE BUILD_STATUS_NUMBER)58 #endif54 # ifndef BUILD_STATUS_TYPE 55 # define BUILD_STATUS (debug build BUILD_NUMBER) 56 # else 57 # define BUILD_STATUS (debug BUILD_STATUS_TYPE BUILD_STATUS_NUMBER) 58 # endif 59 59 #else 60 #if !defined(TSPSG_RELEASE_BUILD)61 #define BUILD_STATUS (nightly build)62 #elif !defined(BUILD_STATUS_TYPE)63 #define BUILD_STATUS (build BUILD_NUMBER)64 #else65 #define BUILD_STATUS (BUILD_STATUS_TYPE BUILD_STATUS_NUMBER)66 #endif // TSPSG_RELEASE_BUILD60 # if !defined(TSPSG_RELEASE_BUILD) 61 # define BUILD_STATUS (nightly build) 62 # elif !defined(BUILD_STATUS_TYPE) 63 # define BUILD_STATUS (build BUILD_NUMBER) 64 # else 65 # define BUILD_STATUS (BUILD_STATUS_TYPE BUILD_STATUS_NUMBER) 66 # endif // TSPSG_RELEASE_BUILD 67 67 #endif // DEBUG 68 68
Note: See TracChangeset
for help on using the changeset viewer.