Changeset 149 in tspsg-svn for trunk/src/tspmodel.cpp
- Timestamp:
- Dec 20, 2010, 9:53:45 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note: See TracChangeset
for help on using the changeset viewer.