src/ldDocument.cc

changeset 662
2f1bd9112408
parent 656
2a1c204df14d
child 714
b4a990f59a5e
equal deleted inserted replaced
661:577bc177a06f 662:2f1bd9112408
57 QString partsPath, primsPath; 57 QString partsPath, primsPath;
58 } pathInfo; 58 } pathInfo;
59 59
60 void initPaths() 60 void initPaths()
61 { 61 {
62 if (!tryConfigure (io_ldpath)) 62 if (not tryConfigure (io_ldpath))
63 { 63 {
64 LDrawPathDialog dlg (false); 64 LDrawPathDialog dlg (false);
65 65
66 if (!dlg.exec()) 66 if (not dlg.exec())
67 exit (0); 67 exit (0);
68 68
69 io_ldpath = dlg.filename(); 69 io_ldpath = dlg.filename();
70 } 70 }
71 } 71 }
72 72
73 bool tryConfigure (QString path) 73 bool tryConfigure (QString path)
74 { 74 {
75 QDir dir; 75 QDir dir;
76 76
77 if (!dir.cd (path)) 77 if (not dir.cd (path))
78 { 78 {
79 pathError = "Directory does not exist."; 79 pathError = "Directory does not exist.";
80 return false; 80 return false;
81 } 81 }
82 82
159 159
160 // Try find an explicitly loaded file - if we can't find one, 160 // Try find an explicitly loaded file - if we can't find one,
161 // we need to create a new file to switch to. 161 // we need to create a new file to switch to.
162 for (LDDocument* file : g_loadedFiles) 162 for (LDDocument* file : g_loadedFiles)
163 { 163 {
164 if (!file->isImplicit()) 164 if (not file->isImplicit())
165 { 165 {
166 LDDocument::setCurrent (file); 166 LDDocument::setCurrent (file);
167 found = true; 167 found = true;
168 break; 168 break;
169 } 169 }
170 } 170 }
171 171
172 if (!found) 172 if (not found)
173 newFile(); 173 newFile();
174 } 174 }
175 175
176 if (this == g_logoedStud) 176 if (this == g_logoedStud)
177 g_logoedStud = null; 177 g_logoedStud = null;
185 // ============================================================================= 185 // =============================================================================
186 // 186 //
187 LDDocument* findDocument (QString name) 187 LDDocument* findDocument (QString name)
188 { 188 {
189 for (LDDocument * file : g_loadedFiles) 189 for (LDDocument * file : g_loadedFiles)
190 if (!file->name().isEmpty() && file->name() == name) 190 if (not file->name().isEmpty() && file->name() == name)
191 return file; 191 return file;
192 192
193 return null; 193 return null;
194 } 194 }
195 195
261 bogus = true; 261 bogus = true;
262 break; 262 break;
263 } 263 }
264 } 264 }
265 265
266 if (!bogus) 266 if (not bogus)
267 return partpath; 267 return partpath;
268 } 268 }
269 } 269 }
270 270
271 if (QFile::exists (relpath)) 271 if (QFile::exists (relpath))
403 setDone (true); 403 setDone (true);
404 return; 404 return;
405 } 405 }
406 406
407 // Otherwise, continue, by recursing back. 407 // Otherwise, continue, by recursing back.
408 if (!isDone()) 408 if (not isDone())
409 { 409 {
410 // If we have a dialog to show progress output to, we cannot just call 410 // If we have a dialog to show progress output to, we cannot just call
411 // work() again immediately as the dialog needs some processor cycles as 411 // work() again immediately as the dialog needs some processor cycles as
412 // well. Thus, take a detour through the event loop by using the 412 // well. Thus, take a detour through the event loop by using the
413 // meta-object system. 413 // meta-object system.
443 443
444 if (numWarnings) 444 if (numWarnings)
445 *numWarnings = 0; 445 *numWarnings = 0;
446 446
447 // Read in the lines 447 // Read in the lines
448 while (fp->atEnd() == false) 448 while (not fp->atEnd())
449 lines << QString::fromUtf8 (fp->readLine()); 449 lines << QString::fromUtf8 (fp->readLine());
450 450
451 LDFileLoader* loader = new LDFileLoader; 451 LDFileLoader* loader = new LDFileLoader;
452 loader->setWarnings (numWarnings); 452 loader->setWarnings (numWarnings);
453 loader->setLines (lines); 453 loader->setLines (lines);
456 456
457 // After start() returns, if the loader isn't done yet, it's delaying 457 // After start() returns, if the loader isn't done yet, it's delaying
458 // its next iteration through the event loop. We need to catch this here 458 // its next iteration through the event loop. We need to catch this here
459 // by telling the event loop to tick, which will tick the file loader again. 459 // by telling the event loop to tick, which will tick the file loader again.
460 // We keep doing this until the file loader is ready. 460 // We keep doing this until the file loader is ready.
461 while (loader->isDone() == false) 461 while (not loader->isDone())
462 qApp->processEvents(); 462 qApp->processEvents();
463 463
464 // If we wanted the success value, supply that now 464 // If we wanted the success value, supply that now
465 if (ok) 465 if (ok)
466 *ok = !loader->isAborted(); 466 *ok = not loader->isAborted();
467 467
468 objs = loader->objects(); 468 objs = loader->objects();
469 return objs; 469 return objs;
470 } 470 }
471 471
484 else 484 else
485 { 485 {
486 fp = new QFile (path); 486 fp = new QFile (path);
487 fullpath = path; 487 fullpath = path;
488 488
489 if (!fp->open (QIODevice::ReadOnly)) 489 if (not fp->open (QIODevice::ReadOnly))
490 { 490 {
491 delete fp; 491 delete fp;
492 return null; 492 return null;
493 } 493 }
494 } 494 }
495 495
496 if (!fp) 496 if (not fp)
497 return null; 497 return null;
498 498
499 LDDocument* load = new LDDocument; 499 LDDocument* load = new LDDocument;
500 load->setFullPath (fullpath); 500 load->setFullPath (fullpath);
501 load->setName (LDDocument::shortenName (load->fullPath())); 501 load->setName (LDDocument::shortenName (load->fullPath()));
509 bool ok; 509 bool ok;
510 LDObjectList objs = loadFileContents (fp, &numWarnings, &ok); 510 LDObjectList objs = loadFileContents (fp, &numWarnings, &ok);
511 fp->close(); 511 fp->close();
512 fp->deleteLater(); 512 fp->deleteLater();
513 513
514 if (!ok) 514 if (not ok)
515 { 515 {
516 g_loadedFiles.removeOne (load); 516 g_loadedFiles.removeOne (load);
517 delete load; 517 delete load;
518 return null; 518 return null;
519 } 519 }
561 return false; 561 return false;
562 562
563 setName (newpath); 563 setName (newpath);
564 } 564 }
565 565
566 if (!save()) 566 if (not save())
567 { 567 {
568 message = format (tr ("Failed to save %1 (%2)\nDo you still want to close?"), 568 message = format (tr ("Failed to save %1 (%2)\nDo you still want to close?"),
569 name(), strerror (errno)); 569 name(), strerror (errno));
570 570
571 if (msgbox::critical (g_win, tr ("Save Failure"), message, 571 if (msgbox::critical (g_win, tr ("Save Failure"), message,
663 } 663 }
664 } 664 }
665 665
666 // We cannot open this file if the document this would replace is not 666 // We cannot open this file if the document this would replace is not
667 // safe to close. 667 // safe to close.
668 if (documentToReplace != null && documentToReplace->isSafeToClose() == false) 668 if (documentToReplace != null && not documentToReplace->isSafeToClose())
669 { 669 {
670 g_loadingMainFile = false; 670 g_loadingMainFile = false;
671 return; 671 return;
672 } 672 }
673 673
674 LDDocument* file = openDocument (path, false); 674 LDDocument* file = openDocument (path, false);
675 675
676 if (!file) 676 if (not file)
677 { 677 {
678 // Loading failed, thus drop down to a new file since we 678 // Loading failed, thus drop down to a new file since we
679 // closed everything prior. 679 // closed everything prior.
680 newFile(); 680 newFile();
681 681
682 if (!g_aborted) 682 if (not g_aborted)
683 { 683 {
684 // Tell the user loading failed. 684 // Tell the user loading failed.
685 setlocale (LC_ALL, "C"); 685 setlocale (LC_ALL, "C");
686 critical (format (QObject::tr ("Failed to open %1: %2"), path, strerror (errno))); 686 critical (format (QObject::tr ("Failed to open %1: %2"), path, strerror (errno)));
687 } 687 }
721 721
722 // ============================================================================= 722 // =============================================================================
723 // 723 //
724 bool LDDocument::save (QString savepath) 724 bool LDDocument::save (QString savepath)
725 { 725 {
726 if (!savepath.length()) 726 if (not savepath.length())
727 savepath = fullPath(); 727 savepath = fullPath();
728 728
729 QFile f (savepath); 729 QFile f (savepath);
730 730
731 if (!f.open (QIODevice::WriteOnly)) 731 if (not f.open (QIODevice::WriteOnly))
732 return false; 732 return false;
733 733
734 // If the second object in the list holds the file name, update that now. 734 // If the second object in the list holds the file name, update that now.
735 // Only do this if the file is explicitly open. 735 // Only do this if the file is explicitly open.
736 LDObject* nameObject = getObject (1); 736 LDObject* nameObject = getObject (1);
737 737
738 if (!isImplicit() && nameObject != null && nameObject->type() == LDObject::EComment) 738 if (not isImplicit() && nameObject != null && nameObject->type() == LDObject::EComment)
739 { 739 {
740 LDComment* nameComment = static_cast<LDComment*> (nameObject); 740 LDComment* nameComment = static_cast<LDComment*> (nameObject);
741 741
742 if (nameComment->text().left (6) == "Name: ") 742 if (nameComment->text().left (6) == "Name: ")
743 { 743 {
802 802
803 for (int i = min; i <= max; ++i) 803 for (int i = min; i <= max; ++i)
804 { 804 {
805 tokens[i].toDouble (&ok); 805 tokens[i].toDouble (&ok);
806 806
807 if (!ok && !scient.exactMatch (tokens[i])) 807 if (not ok && not scient.exactMatch (tokens[i]))
808 throw LDParseError (line, format ("Token #%1 was `%2`, expected a number (matched length: %3)", (i + 1), tokens[i], scient.matchedLength())); 808 {
809 throw LDParseError (line, format ("Token #%1 was `%2`, expected a number (matched length: %3)",
810 (i + 1), tokens[i], scient.matchedLength()));
811 }
809 } 812 }
810 } 813 }
811 814
812 // ============================================================================= 815 // =============================================================================
813 // 816 //
836 { 839 {
837 // Line was empty, or only consisted of whitespace 840 // Line was empty, or only consisted of whitespace
838 return new LDEmpty; 841 return new LDEmpty;
839 } 842 }
840 843
841 if (tokens[0].length() != 1 || tokens[0][0].isDigit() == false) 844 if (tokens[0].length() != 1 || not tokens[0][0].isDigit())
842 throw LDParseError (line, "Illogical line code"); 845 throw LDParseError (line, "Illogical line code");
843 846
844 int num = tokens[0][0].digitValue(); 847 int num = tokens[0][0].digitValue();
845 848
846 switch (num) 849 switch (num)
927 LDDocument* load = getDocument (tokens[14]); 930 LDDocument* load = getDocument (tokens[14]);
928 g_loadingMainFile = tmp; 931 g_loadingMainFile = tmp;
929 932
930 // If we cannot open the file, mark it an error. Note we cannot use LDParseError 933 // If we cannot open the file, mark it an error. Note we cannot use LDParseError
931 // here because the error object needs the document reference. 934 // here because the error object needs the document reference.
932 if (!load) 935 if (not load)
933 { 936 {
934 LDError* obj = new LDError (line, format ("Could not open %1", tokens[14])); 937 LDError* obj = new LDError (line, format ("Could not open %1", tokens[14]));
935 obj->setFileReferenced (tokens[14]); 938 obj->setFileReferenced (tokens[14]);
936 return obj; 939 return obj;
937 } 940 }
1018 { 1021 {
1019 // Try find the file in the list of loaded files 1022 // Try find the file in the list of loaded files
1020 LDDocument* doc = findDocument (filename); 1023 LDDocument* doc = findDocument (filename);
1021 1024
1022 // If it's not loaded, try open it 1025 // If it's not loaded, try open it
1023 if (!doc) 1026 if (not doc)
1024 doc = openDocument (filename, true); 1027 doc = openDocument (filename, true);
1025 1028
1026 return doc; 1029 return doc;
1027 } 1030 }
1028 1031
1029 // ============================================================================= 1032 // =============================================================================
1030 // 1033 //
1031 void reloadAllSubfiles() 1034 void reloadAllSubfiles()
1032 { 1035 {
1033 if (!getCurrentDocument()) 1036 if (not getCurrentDocument())
1034 return; 1037 return;
1035 1038
1036 g_loadedFiles.clear(); 1039 g_loadedFiles.clear();
1037 g_loadedFiles << getCurrentDocument(); 1040 g_loadedFiles << getCurrentDocument();
1038 1041
1066 1069
1067 if (obj->type() == LDObject::EVertex) 1070 if (obj->type() == LDObject::EVertex)
1068 m_vertices << obj; 1071 m_vertices << obj;
1069 1072
1070 #ifdef DEBUG 1073 #ifdef DEBUG
1071 if (!isImplicit()) 1074 if (not isImplicit())
1072 dprint ("Added object #%1 (%2)\n", obj->id(), obj->typeName()); 1075 dprint ("Added object #%1 (%2)\n", obj->id(), obj->typeName());
1073 #endif 1076 #endif
1074 1077
1075 obj->setDocument (this); 1078 obj->setDocument (this);
1076 return getObjectCount() - 1; 1079 return getObjectCount() - 1;
1092 history()->add (new AddHistory (pos, obj)); 1095 history()->add (new AddHistory (pos, obj));
1093 m_objects.insert (pos, obj); 1096 m_objects.insert (pos, obj);
1094 obj->setDocument (this); 1097 obj->setDocument (this);
1095 1098
1096 #ifdef DEBUG 1099 #ifdef DEBUG
1097 if (!isImplicit()) 1100 if (not isImplicit())
1098 dprint ("Inserted object #%1 (%2) at %3\n", obj->id(), obj->typeName(), pos); 1101 dprint ("Inserted object #%1 (%2) at %3\n", obj->id(), obj->typeName(), pos);
1099 #endif 1102 #endif
1100 } 1103 }
1101 1104
1102 // ============================================================================= 1105 // =============================================================================
1105 { 1108 {
1106 int idx = obj->lineNumber(); 1109 int idx = obj->lineNumber();
1107 obj->unselect(); 1110 obj->unselect();
1108 assert (m_objects[idx] == obj); 1111 assert (m_objects[idx] == obj);
1109 1112
1110 if (!history()->isIgnoring()) 1113 if (not history()->isIgnoring())
1111 history()->add (new DelHistory (idx, obj)); 1114 history()->add (new DelHistory (idx, obj));
1112 1115
1113 m_objects.removeAt (idx); 1116 m_objects.removeAt (idx);
1114 obj->setDocument (null); 1117 obj->setDocument (null);
1115 } 1118 }
1117 // ============================================================================= 1120 // =============================================================================
1118 // 1121 //
1119 bool safeToCloseAll() 1122 bool safeToCloseAll()
1120 { 1123 {
1121 for (LDDocument* f : g_loadedFiles) 1124 for (LDDocument* f : g_loadedFiles)
1122 if (!f->isSafeToClose()) 1125 if (not f->isSafeToClose())
1123 return false; 1126 return false;
1124 1127
1125 return true; 1128 return true;
1126 } 1129 }
1127 1130
1130 void LDDocument::setObject (int idx, LDObject* obj) 1133 void LDDocument::setObject (int idx, LDObject* obj)
1131 { 1134 {
1132 assert (idx >= 0 && idx < m_objects.size()); 1135 assert (idx >= 0 && idx < m_objects.size());
1133 1136
1134 // Mark this change to history 1137 // Mark this change to history
1135 if (!m_history->isIgnoring()) 1138 if (not m_history->isIgnoring())
1136 { 1139 {
1137 QString oldcode = getObject (idx)->asText(); 1140 QString oldcode = getObject (idx)->asText();
1138 QString newcode = obj->asText(); 1141 QString newcode = obj->asText();
1139 *m_history << new EditHistory (idx, oldcode, newcode); 1142 *m_history << new EditHistory (idx, oldcode, newcode);
1140 } 1143 }
1186 1189
1187 // ============================================================================= 1190 // =============================================================================
1188 // 1191 //
1189 QString LDDocument::getDisplayName() 1192 QString LDDocument::getDisplayName()
1190 { 1193 {
1191 if (!name().isEmpty()) 1194 if (not name().isEmpty())
1192 return name(); 1195 return name();
1193 1196
1194 if (!defaultName().isEmpty()) 1197 if (not defaultName().isEmpty())
1195 return "[" + defaultName() + "]"; 1198 return "[" + defaultName() + "]";
1196 1199
1197 return tr ("<anonymous>"); 1200 return tr ("<anonymous>");
1198 } 1201 }
1199 1202
1225 m_cache.clear(); 1228 m_cache.clear();
1226 doCache = true; 1229 doCache = true;
1227 } 1230 }
1228 1231
1229 // If we have this cached, just create a copy of that 1232 // If we have this cached, just create a copy of that
1230 if (deep && cache().isEmpty() == false) 1233 if (deep && not cache().isEmpty())
1231 { 1234 {
1232 for (LDObject* obj : cache()) 1235 for (LDObject* obj : cache())
1233 objs << obj->createCopy(); 1236 objs << obj->createCopy();
1234 } 1237 }
1235 else 1238 else
1236 { 1239 {
1237 if (!deep) 1240 if (not deep)
1238 doCache = false; 1241 doCache = false;
1239 1242
1240 for (LDObject* obj : objects()) 1243 for (LDObject* obj : objects())
1241 { 1244 {
1242 // Skip those without scemantic meaning 1245 // Skip those without scemantic meaning
1243 if (!obj->isScemantic()) 1246 if (not obj->isScemantic())
1244 continue; 1247 continue;
1245 1248
1246 // Got another sub-file reference, inline it if we're deep-inlining. If not, 1249 // Got another sub-file reference, inline it if we're deep-inlining. If not,
1247 // just add it into the objects normally. Also, we only cache immediate 1250 // just add it into the objects normally. Also, we only cache immediate
1248 // subfiles and this is not one. Yay, recursion! 1251 // subfiles and this is not one. Yay, recursion!
1318 int LDDocument::countExplicitFiles() 1321 int LDDocument::countExplicitFiles()
1319 { 1322 {
1320 int count = 0; 1323 int count = 0;
1321 1324
1322 for (LDDocument* f : g_loadedFiles) 1325 for (LDDocument* f : g_loadedFiles)
1323 if (f->isImplicit() == false) 1326 {
1324 count++; 1327 if (not f->isImplicit())
1328 ++count;
1329 }
1325 1330
1326 return count; 1331 return count;
1327 } 1332 }
1328 1333
1329 // ============================================================================= 1334 // =============================================================================
1330 // This little beauty closes the initial file that was open at first when opening 1335 // This little beauty closes the initial file that was open at first when opening
1331 // a new file over it. 1336 // a new file over it.
1332 // ============================================================================= 1337 // =============================================================================
1333 void LDDocument::closeInitialFile() 1338 void LDDocument::closeInitialFile()
1334 { 1339 {
1335 if ( 1340 if (countExplicitFiles() == 2 &&
1336 countExplicitFiles() == 2 &&
1337 g_loadedFiles[0]->name().isEmpty() && 1341 g_loadedFiles[0]->name().isEmpty() &&
1338 g_loadedFiles[1]->name().isEmpty() == false && 1342 not g_loadedFiles[1]->name().isEmpty() &&
1339 !g_loadedFiles[0]->hasUnsavedChanges() 1343 not g_loadedFiles[0]->hasUnsavedChanges())
1340 ) 1344 {
1341 delete g_loadedFiles[0]; 1345 delete g_loadedFiles[0];
1346 }
1342 } 1347 }
1343 1348
1344 // ============================================================================= 1349 // =============================================================================
1345 // 1350 //
1346 void loadLogoedStuds() 1351 void loadLogoedStuds()
1371 1376
1372 // ============================================================================= 1377 // =============================================================================
1373 // 1378 //
1374 void LDDocument::removeFromSelection (LDObject* obj) // [protected] 1379 void LDDocument::removeFromSelection (LDObject* obj) // [protected]
1375 { 1380 {
1376 if (!obj->isSelected()) 1381 if (not obj->isSelected())
1377 return; 1382 return;
1378 1383
1379 assert (obj->document() == this); 1384 assert (obj->document() == this);
1380 m_sel.removeOne (obj); 1385 m_sel.removeOne (obj);
1381 obj->setSelected (false); 1386 obj->setSelected (false);

mercurial