src/ldDocument.cc

changeset 945
c310073e4f22
parent 944
1a6f1997fcbe
child 946
9cbd658b63f9
equal deleted inserted replaced
944:1a6f1997fcbe 945:c310073e4f22
40 EXTERN_CFGENTRY (Bool, UseLogoStuds) 40 EXTERN_CFGENTRY (Bool, UseLogoStuds)
41 41
42 static bool g_loadingMainFile = false; 42 static bool g_loadingMainFile = false;
43 static const int g_maxRecentFiles = 10; 43 static const int g_maxRecentFiles = 10;
44 static bool g_aborted = false; 44 static bool g_aborted = false;
45 static LDDocumentPtr g_logoedStud; 45 static LDDocument* g_logoedStud;
46 static LDDocumentPtr g_logoedStud2; 46 static LDDocument* g_logoedStud2;
47 static QList<LDDocumentWeakPtr> g_allDocuments; 47 static QList<LDDocument*> g_allDocuments;
48 static QList<LDDocumentPtr> g_explicitDocuments; 48 static QList<LDDocument*> g_explicitDocuments;
49 static LDDocumentPtr g_currentDocument; 49 static LDDocument* g_currentDocument;
50 static bool g_loadingLogoedStuds = false; 50 static bool g_loadingLogoedStuds = false;
51 51
52 const QStringList g_specialSubdirectories ({ "s", "48", "8" }); 52 const QStringList g_specialSubdirectories ({ "s", "48", "8" });
53 53
54 // ============================================================================= 54 // =============================================================================
124 } 124 }
125 } 125 }
126 126
127 // ============================================================================= 127 // =============================================================================
128 // 128 //
129 LDDocument::LDDocument (LDDocumentPtr* selfptr) : 129 LDDocument::LDDocument (LDDocument** selfptr) :
130 m_isImplicit (true), 130 m_isImplicit (true),
131 m_flags (0), 131 m_flags (0),
132 m_verticesOutdated (true), 132 m_verticesOutdated (true),
133 m_needVertexMerge (true), 133 m_needVertexMerge (true),
134 m_gldata (new LDGLData) 134 m_gldata (new LDGLData)
135 { 135 {
136 *selfptr = LDDocumentPtr (this); 136 *selfptr = LDDocument* (this);
137 setSelf (*selfptr); 137 setSelf (*selfptr);
138 setSavePosition (-1); 138 setSavePosition (-1);
139 setTabIndex (-1); 139 setTabIndex (-1);
140 setHistory (new History); 140 setHistory (new History);
141 history()->setDocument (*selfptr); 141 history()->setDocument (*selfptr);
143 g_allDocuments << *selfptr; 143 g_allDocuments << *selfptr;
144 } 144 }
145 145
146 // ============================================================================= 146 // =============================================================================
147 // 147 //
148 LDDocumentPtr LDDocument::createNew() 148 LDDocument* LDDocument::createNew()
149 { 149 {
150 LDDocumentPtr ptr; 150 LDDocument* ptr;
151 new LDDocument (&ptr); 151 new LDDocument (&ptr);
152 return ptr; 152 return ptr;
153 } 153 }
154 154
155 // ============================================================================= 155 // =============================================================================
205 } 205 }
206 } 206 }
207 207
208 // ============================================================================= 208 // =============================================================================
209 // 209 //
210 QList<LDDocumentPtr> const& LDDocument::explicitDocuments() 210 QList<LDDocument*> const& LDDocument::explicitDocuments()
211 { 211 {
212 return g_explicitDocuments; 212 return g_explicitDocuments;
213 } 213 }
214 214
215 // ============================================================================= 215 // =============================================================================
216 // 216 //
217 LDDocumentPtr FindDocument (QString name) 217 LDDocument* FindDocument (QString name)
218 { 218 {
219 for (LDDocumentWeakPtr weakfile : g_allDocuments) 219 for (LDDocument* file : g_allDocuments)
220 { 220 {
221 if (weakfile == null) 221 if (file == null)
222 continue; 222 continue;
223 223
224 LDDocumentPtr file (weakfile); 224 LDDocument* file (file);
225 225
226 if (Eq (name, file->name(), file->defaultName())) 226 if (Eq (name, file->name(), file->defaultName()))
227 return file; 227 return file;
228 } 228 }
229 229
230 return LDDocumentPtr(); 230 return nullptr;
231 } 231 }
232 232
233 // ============================================================================= 233 // =============================================================================
234 // 234 //
235 QString Dirname (QString path) 235 QString Dirname (QString path)
274 274
275 // Try find it relative to other currently open documents. We want a file 275 // Try find it relative to other currently open documents. We want a file
276 // in the immediate vicinity of a current model to override stock LDraw stuff. 276 // in the immediate vicinity of a current model to override stock LDraw stuff.
277 QString reltop = Basename (Dirname (relpath)); 277 QString reltop = Basename (Dirname (relpath));
278 278
279 for (LDDocumentWeakPtr doc : g_allDocuments) 279 for (LDDocument* doc : g_allDocuments)
280 { 280 {
281 if (doc == null) 281 if (doc == null)
282 continue; 282 continue;
283 283
284 QString partpath = format ("%1/%2", Dirname (doc->fullPath()), relpath); 284 QString partpath = format ("%1/%2", Dirname (doc->fullPath()), relpath);
510 return objs; 510 return objs;
511 } 511 }
512 512
513 // ============================================================================= 513 // =============================================================================
514 // 514 //
515 LDDocumentPtr OpenDocument (QString path, bool search, bool implicit, LDDocumentPtr fileToOverride) 515 LDDocument* OpenDocument (QString path, bool search, bool implicit, LDDocument* fileToOverride)
516 { 516 {
517 // Convert the file name to lowercase when searching because some parts contain subfile 517 // Convert the file name to lowercase when searching because some parts contain subfile
518 // subfile references with uppercase file names. I'll assume here that the library will always 518 // subfile references with uppercase file names. I'll assume here that the library will always
519 // use lowercase file names for the part files. 519 // use lowercase file names for the part files.
520 QFile* fp; 520 QFile* fp;
530 fullpath = path; 530 fullpath = path;
531 531
532 if (not fp->open (QIODevice::ReadOnly)) 532 if (not fp->open (QIODevice::ReadOnly))
533 { 533 {
534 delete fp; 534 delete fp;
535 return LDDocumentPtr(); 535 return nullptr;
536 } 536 }
537 } 537 }
538 538
539 if (not fp) 539 if (not fp)
540 return LDDocumentPtr(); 540 return nullptr;
541 541
542 LDDocumentPtr load = (fileToOverride != null ? fileToOverride : LDDocument::createNew()); 542 LDDocument* load = (fileToOverride != null ? fileToOverride : LDDocument::createNew());
543 load->setImplicit (implicit); 543 load->setImplicit (implicit);
544 load->setFullPath (fullpath); 544 load->setFullPath (fullpath);
545 load->setName (LDDocument::shortenName (load->fullPath())); 545 load->setName (LDDocument::shortenName (load->fullPath()));
546 546
547 // Loading the file shouldn't count as actual edits to the document. 547 // Loading the file shouldn't count as actual edits to the document.
554 fp->deleteLater(); 554 fp->deleteLater();
555 555
556 if (not ok) 556 if (not ok)
557 { 557 {
558 load->dismiss(); 558 load->dismiss();
559 return LDDocumentPtr(); 559 return nullptr;
560 } 560 }
561 561
562 load->addObjects (objs); 562 load->addObjects (objs);
563 563
564 if (g_loadingMainFile) 564 if (g_loadingMainFile)
631 631
632 // ============================================================================= 632 // =============================================================================
633 // 633 //
634 void CloseAllDocuments() 634 void CloseAllDocuments()
635 { 635 {
636 for (LDDocumentPtr file : g_explicitDocuments) 636 for (LDDocument* file : g_explicitDocuments)
637 file->dismiss(); 637 file->dismiss();
638 } 638 }
639 639
640 // ============================================================================= 640 // =============================================================================
641 // 641 //
642 void newFile() 642 void newFile()
643 { 643 {
644 // Create a new anonymous file and set it to our current 644 // Create a new anonymous file and set it to our current
645 LDDocumentPtr f = LDDocument::createNew(); 645 LDDocument* f = LDDocument::createNew();
646 f->setName (""); 646 f->setName ("");
647 f->setImplicit (false); 647 f->setImplicit (false);
648 LDDocument::setCurrent (f); 648 LDDocument::setCurrent (f);
649 LDDocument::closeInitialFile(); 649 LDDocument::closeInitialFile();
650 g_win->R()->setDocument (f); 650 g_win->R()->setDocument (f);
683 // Open an LDraw file and set it as the main model 683 // Open an LDraw file and set it as the main model
684 // ============================================================================= 684 // =============================================================================
685 void OpenMainModel (QString path) 685 void OpenMainModel (QString path)
686 { 686 {
687 // If there's already a file with the same name, this file must replace it. 687 // If there's already a file with the same name, this file must replace it.
688 LDDocumentPtr documentToReplace; 688 LDDocument* documentToReplace;
689 LDDocumentPtr file; 689 LDDocument* file;
690 QString shortName = LDDocument::shortenName (path); 690 QString shortName = LDDocument::shortenName (path);
691 691
692 for (LDDocumentWeakPtr doc : g_allDocuments) 692 for (LDDocument* doc : g_allDocuments)
693 { 693 {
694 if (doc != null and doc->name() == shortName) 694 if (doc != null and doc->name() == shortName)
695 { 695 {
696 documentToReplace = doc; 696 documentToReplace = doc;
697 break; 697 break;
786 // If the second object in the list holds the file name, update that now. 786 // If the second object in the list holds the file name, update that now.
787 LDObject* nameObject = getObject (1); 787 LDObject* nameObject = getObject (1);
788 788
789 if (nameObject != null and nameObject->type() == OBJ_Comment) 789 if (nameObject != null and nameObject->type() == OBJ_Comment)
790 { 790 {
791 LDCommentPtr nameComment = static_cast<LDComment*> (nameObject); 791 LDComment* nameComment = static_cast<LDComment*> (nameObject);
792 792
793 if (nameComment->text().left (6) == "Name: ") 793 if (nameComment->text().left (6) == "Name: ")
794 { 794 {
795 QString newname = shortenName (path); 795 QString newname = shortenName (path);
796 nameComment->setText (format ("Name: %1", newname)); 796 nameComment->setText (format ("Name: %1", newname));
962 { 962 {
963 // Vertex (0 !LDFORGE VERTEX) 963 // Vertex (0 !LDFORGE VERTEX)
964 CheckTokenCount (tokens, 7); 964 CheckTokenCount (tokens, 7);
965 CheckTokenNumbers (tokens, 3, 6); 965 CheckTokenNumbers (tokens, 3, 6);
966 966
967 LDVertexPtr obj = LDSpawn<LDVertex>(); 967 LDVertex* obj = LDSpawn<LDVertex>();
968 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[3]))); 968 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[3])));
969 obj->pos.apply ([&](Axis ax, double& value) 969 obj->pos.apply ([&](Axis ax, double& value)
970 { value = tokens[4 + ax].toDouble(); }); 970 { value = tokens[4 + ax].toDouble(); });
971 return obj; 971 return obj;
972 } 972 }
973 elif (tokens[2] == "OVERLAY") 973 elif (tokens[2] == "OVERLAY")
974 { 974 {
975 CheckTokenCount (tokens, 9); 975 CheckTokenCount (tokens, 9);
976 CheckTokenNumbers (tokens, 5, 8); 976 CheckTokenNumbers (tokens, 5, 8);
977 977
978 LDOverlayPtr obj = LDSpawn<LDOverlay>(); 978 LDOverlay* obj = LDSpawn<LDOverlay>();
979 obj->setFileName (tokens[3]); 979 obj->setFileName (tokens[3]);
980 obj->setCamera (tokens[4].toLong()); 980 obj->setCamera (tokens[4].toLong());
981 obj->setX (tokens[5].toLong()); 981 obj->setX (tokens[5].toLong());
982 obj->setY (tokens[6].toLong()); 982 obj->setY (tokens[6].toLong());
983 obj->setWidth (tokens[7].toLong()); 983 obj->setWidth (tokens[7].toLong());
985 return obj; 985 return obj;
986 } 986 }
987 } 987 }
988 988
989 // Just a regular comment: 989 // Just a regular comment:
990 LDCommentPtr obj = LDSpawn<LDComment>(); 990 LDComment* obj = LDSpawn<LDComment>();
991 obj->setText (commentText); 991 obj->setText (commentText);
992 return obj; 992 return obj;
993 } 993 }
994 994
995 case 1: 995 case 1:
1000 1000
1001 // Try open the file. Disable g_loadingMainFile temporarily since we're 1001 // Try open the file. Disable g_loadingMainFile temporarily since we're
1002 // not loading the main file now, but the subfile in question. 1002 // not loading the main file now, but the subfile in question.
1003 bool tmp = g_loadingMainFile; 1003 bool tmp = g_loadingMainFile;
1004 g_loadingMainFile = false; 1004 g_loadingMainFile = false;
1005 LDDocumentPtr load = GetDocument (tokens[14]); 1005 LDDocument* load = GetDocument (tokens[14]);
1006 g_loadingMainFile = tmp; 1006 g_loadingMainFile = tmp;
1007 1007
1008 // If we cannot open the file, mark it an error. Note we cannot use LDParseError 1008 // If we cannot open the file, mark it an error. Note we cannot use LDParseError
1009 // here because the error object needs the document reference. 1009 // here because the error object needs the document reference.
1010 if (not load) 1010 if (not load)
1011 { 1011 {
1012 LDErrorPtr obj = LDSpawn<LDError> (line, format ("Could not open %1", tokens[14])); 1012 LDError* obj = LDSpawn<LDError> (line, format ("Could not open %1", tokens[14]));
1013 obj->setFileReferenced (tokens[14]); 1013 obj->setFileReferenced (tokens[14]);
1014 return obj; 1014 return obj;
1015 } 1015 }
1016 1016
1017 LDSubfilePtr obj = LDSpawn<LDSubfile>(); 1017 LDSubfile* obj = LDSpawn<LDSubfile>();
1018 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[1]))); 1018 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[1])));
1019 obj->setPosition (ParseVertex (tokens, 2)); // 2 - 4 1019 obj->setPosition (ParseVertex (tokens, 2)); // 2 - 4
1020 1020
1021 Matrix transform; 1021 Matrix transform;
1022 1022
1032 { 1032 {
1033 CheckTokenCount (tokens, 8); 1033 CheckTokenCount (tokens, 8);
1034 CheckTokenNumbers (tokens, 1, 7); 1034 CheckTokenNumbers (tokens, 1, 7);
1035 1035
1036 // Line 1036 // Line
1037 LDLinePtr obj (LDSpawn<LDLine>()); 1037 LDLine* obj (LDSpawn<LDLine>());
1038 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[1]))); 1038 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[1])));
1039 1039
1040 for (int i = 0; i < 2; ++i) 1040 for (int i = 0; i < 2; ++i)
1041 obj->setVertex (i, ParseVertex (tokens, 2 + (i * 3))); // 2 - 7 1041 obj->setVertex (i, ParseVertex (tokens, 2 + (i * 3))); // 2 - 7
1042 1042
1047 { 1047 {
1048 CheckTokenCount (tokens, 11); 1048 CheckTokenCount (tokens, 11);
1049 CheckTokenNumbers (tokens, 1, 10); 1049 CheckTokenNumbers (tokens, 1, 10);
1050 1050
1051 // Triangle 1051 // Triangle
1052 LDTrianglePtr obj (LDSpawn<LDTriangle>()); 1052 LDTriangle* obj (LDSpawn<LDTriangle>());
1053 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[1]))); 1053 obj->setColor (LDColor::fromIndex (StringToNumber (tokens[1])));
1054 1054
1055 for (int i = 0; i < 3; ++i) 1055 for (int i = 0; i < 3; ++i)
1056 obj->setVertex (i, ParseVertex (tokens, 2 + (i * 3))); // 2 - 10 1056 obj->setVertex (i, ParseVertex (tokens, 2 + (i * 3))); // 2 - 10
1057 1057
1091 } 1091 }
1092 } 1092 }
1093 1093
1094 // ============================================================================= 1094 // =============================================================================
1095 // 1095 //
1096 LDDocumentPtr GetDocument (QString filename) 1096 LDDocument* GetDocument (QString filename)
1097 { 1097 {
1098 // Try find the file in the list of loaded files 1098 // Try find the file in the list of loaded files
1099 LDDocumentPtr doc = FindDocument (filename); 1099 LDDocument* doc = FindDocument (filename);
1100 1100
1101 // If it's not loaded, try open it 1101 // If it's not loaded, try open it
1102 if (not doc) 1102 if (not doc)
1103 doc = OpenDocument (filename, true, true); 1103 doc = OpenDocument (filename, true, true);
1104 1104
1114 // Go through all objects in the current file and reload the subfiles 1114 // Go through all objects in the current file and reload the subfiles
1115 for (LDObject* obj : objects()) 1115 for (LDObject* obj : objects())
1116 { 1116 {
1117 if (obj->type() == OBJ_Subfile) 1117 if (obj->type() == OBJ_Subfile)
1118 { 1118 {
1119 LDSubfilePtr ref = static_cast<LDSubfile*> (obj); 1119 LDSubfile* ref = static_cast<LDSubfile*> (obj);
1120 LDDocumentPtr fileInfo = GetDocument (ref->fileInfo()->name()); 1120 LDDocument* fileInfo = GetDocument (ref->fileInfo()->name());
1121 1121
1122 if (fileInfo != null) 1122 if (fileInfo != null)
1123 { 1123 {
1124 ref->setFileInfo (fileInfo); 1124 ref->setFileInfo (fileInfo);
1125 } 1125 }
1209 history()->add (new DelHistory (idx, obj)); 1209 history()->add (new DelHistory (idx, obj));
1210 m_objectVertices.remove (obj); 1210 m_objectVertices.remove (obj);
1211 } 1211 }
1212 1212
1213 m_objects.removeAt (idx); 1213 m_objects.removeAt (idx);
1214 obj->setDocument (LDDocumentPtr()); 1214 obj->setDocument (nullptr);
1215 } 1215 }
1216 1216
1217 // ============================================================================= 1217 // =============================================================================
1218 // 1218 //
1219 bool IsSafeToCloseAll() 1219 bool IsSafeToCloseAll()
1220 { 1220 {
1221 for (LDDocumentPtr f : LDDocument::explicitDocuments()) 1221 for (LDDocument* f : LDDocument::explicitDocuments())
1222 { 1222 {
1223 if (not f->isSafeToClose()) 1223 if (not f->isSafeToClose())
1224 return false; 1224 return false;
1225 } 1225 }
1226 1226
1241 *m_history << new EditHistory (idx, oldcode, newcode); 1241 *m_history << new EditHistory (idx, oldcode, newcode);
1242 } 1242 }
1243 1243
1244 m_objectVertices.remove (m_objects[idx]); 1244 m_objectVertices.remove (m_objects[idx]);
1245 m_objects[idx]->deselect(); 1245 m_objects[idx]->deselect();
1246 m_objects[idx]->setDocument (LDDocumentPtr()); 1246 m_objects[idx]->setDocument (nullptr);
1247 obj->setDocument (this); 1247 obj->setDocument (this);
1248 addKnownVertices (obj); 1248 addKnownVertices (obj);
1249 g_win->R()->compileObject (obj); 1249 g_win->R()->compileObject (obj);
1250 m_objects[idx] = obj; 1250 m_objects[idx] = obj;
1251 needVertexMerge(); 1251 needVertexMerge();
1394 return objs; 1394 return objs;
1395 } 1395 }
1396 1396
1397 // ============================================================================= 1397 // =============================================================================
1398 // 1398 //
1399 LDDocumentPtr LDDocument::current() 1399 LDDocument* LDDocument::current()
1400 { 1400 {
1401 return g_currentDocument; 1401 return g_currentDocument;
1402 } 1402 }
1403 1403
1404 // ============================================================================= 1404 // =============================================================================
1405 // Sets the given file as the current one on display. At some point in time this 1405 // Sets the given file as the current one on display. At some point in time this
1406 // was an operation completely unheard of. ;) 1406 // was an operation completely unheard of. ;)
1407 // 1407 //
1408 // TODO: f can be temporarily null. This probably should not be the case. 1408 // TODO: f can be temporarily null. This probably should not be the case.
1409 // ============================================================================= 1409 // =============================================================================
1410 void LDDocument::setCurrent (LDDocumentPtr f) 1410 void LDDocument::setCurrent (LDDocument* f)
1411 { 1411 {
1412 // Implicit files were loaded for caching purposes and must never be set 1412 // Implicit files were loaded for caching purposes and must never be set
1413 // current. 1413 // current.
1414 if (f != null and f->isImplicit()) 1414 if (f != null and f->isImplicit())
1415 return; 1415 return;
1444 if (g_explicitDocuments.size() == 2 and 1444 if (g_explicitDocuments.size() == 2 and
1445 g_explicitDocuments[0]->name().isEmpty() and 1445 g_explicitDocuments[0]->name().isEmpty() and
1446 not g_explicitDocuments[1]->name().isEmpty() and 1446 not g_explicitDocuments[1]->name().isEmpty() and
1447 not g_explicitDocuments[0]->hasUnsavedChanges()) 1447 not g_explicitDocuments[0]->hasUnsavedChanges())
1448 { 1448 {
1449 LDDocumentPtr filetoclose = g_explicitDocuments.first(); 1449 LDDocument* filetoclose = g_explicitDocuments.first();
1450 filetoclose->dismiss(); 1450 filetoclose->dismiss();
1451 } 1451 }
1452 } 1452 }
1453 1453
1454 // ============================================================================= 1454 // =============================================================================

mercurial