39 QString Parser::readLine() |
39 QString Parser::readLine() |
40 { |
40 { |
41 return QString::fromUtf8(this->device.readLine()).trimmed(); |
41 return QString::fromUtf8(this->device.readLine()).trimmed(); |
42 } |
42 } |
43 |
43 |
44 const QMap<QString, decltype(LDHeader::type)> Parser::typeStrings { |
44 static const QMap<QString, decltype(LDHeader::type)> typeStrings { |
45 {"Part", LDHeader::Part}, |
45 {"Part", LDHeader::Part}, |
46 {"Subpart", LDHeader::Subpart}, |
46 {"Subpart", LDHeader::Subpart}, |
47 {"Shortcut", LDHeader::Shortcut}, |
47 {"Shortcut", LDHeader::Shortcut}, |
48 {"Primitive", LDHeader::Primitive}, |
48 {"Primitive", LDHeader::Primitive}, |
49 {"8_Primitive", LDHeader::Primitive_8}, |
49 {"8_Primitive", LDHeader::Primitive_8}, |
74 else if (line.startsWith("0 !LDRAW_ORG ")) |
74 else if (line.startsWith("0 !LDRAW_ORG ")) |
75 { |
75 { |
76 QStringList tokens = line |
76 QStringList tokens = line |
77 .mid(strlen("0 !LDRAW_ORG ")) |
77 .mid(strlen("0 !LDRAW_ORG ")) |
78 .split(" ", QString::SkipEmptyParts); |
78 .split(" ", QString::SkipEmptyParts); |
79 |
|
80 if (not tokens.isEmpty()) |
79 if (not tokens.isEmpty()) |
81 { |
80 { |
82 QString partTypeString = tokens[0]; |
81 QString partTypeString = tokens[0]; |
83 // Anything that enters LDForge becomes unofficial in any case if saved. |
82 // Anything that enters LDForge becomes unofficial in any case if saved. |
84 // Therefore we don't need to give the Unofficial type any special |
83 // Therefore we don't need to give the Unofficial type any special |
85 // consideration. |
84 // consideration. |
86 if (partTypeString.startsWith("Unofficial_")) |
85 if (partTypeString.startsWith("Unofficial_")) |
87 partTypeString = partTypeString.mid(strlen("Unofficial_")); |
86 partTypeString = partTypeString.mid(strlen("Unofficial_")); |
88 header.type = Parser::typeStrings.value(partTypeString, LDHeader::Part); |
87 header.type = typeStrings.value(partTypeString, LDHeader::Part); |
89 header.qualfiers = 0; |
88 header.qualfiers = 0; |
90 if (tokens.contains("Alias")) |
89 if (tokens.contains("Alias")) |
91 header.qualfiers |= LDHeader::Alias; |
90 header.qualfiers |= LDHeader::Alias; |
92 if (tokens.contains("Physical_Color")) |
91 if (tokens.contains("Physical_Color")) |
93 header.qualfiers |= LDHeader::Physical_Color; |
92 header.qualfiers |= LDHeader::Physical_Color; |
198 * the resulting header structure. |
197 * the resulting header structure. |
199 */ |
198 */ |
200 LDHeader Parser::parseHeader(Winding& winding) |
199 LDHeader Parser::parseHeader(Winding& winding) |
201 { |
200 { |
202 LDHeader header = {}; |
201 LDHeader header = {}; |
203 |
|
204 if (not this->device.atEnd()) |
202 if (not this->device.atEnd()) |
205 { |
203 { |
206 // Parse the description |
204 // Parse the description |
207 QString descriptionLine = this->readLine(); |
205 QString descriptionLine = this->readLine(); |
208 if (descriptionLine.startsWith("0 ")) |
206 if (descriptionLine.startsWith("0 ")) |
209 { |
207 { |
210 header.description = descriptionLine.mid(strlen("0 ")).trimmed(); |
208 header.description = descriptionLine.mid(strlen("0 ")).trimmed(); |
211 |
|
212 // Parse the rest of the header |
209 // Parse the rest of the header |
213 while (not this->device.atEnd()) |
210 while (not this->device.atEnd()) |
214 { |
211 { |
215 const QString& line = this->readLine(); |
212 const QString& line = this->readLine(); |
216 auto result = parseHeaderLine(header, winding, line); |
213 auto result = parseHeaderLine(header, winding, line); |
217 |
|
218 if (result == ParseFailure) |
214 if (result == ParseFailure) |
219 { |
215 { |
220 // Failed to parse this header line, add it as a comment into the body later. |
216 // Failed to parse this header line, add it as a comment into the body later. |
221 this->bag.append(line); |
217 this->bag.append(line); |
222 } |
218 } |
306 R"(\s*$)" // end |
301 R"(\s*$)" // end |
307 }; |
302 }; |
308 } |
303 } |
309 } |
304 } |
310 |
305 |
|
306 static Vertex vertexFromString(const QString& vertex_string) |
|
307 { |
|
308 static const QRegExp pattern {R"(^\s*([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*$)"}; |
|
309 const bool succeeded = pattern.exactMatch(vertex_string); |
|
310 if (succeeded) |
|
311 { |
|
312 const float x = pattern.cap(1).toFloat(nullptr); |
|
313 const float y = pattern.cap(2).toFloat(nullptr); |
|
314 const float z = pattern.cap(3).toFloat(nullptr); |
|
315 return {x, y, z}; |
|
316 } |
|
317 else |
|
318 { |
|
319 return {}; |
|
320 } |
|
321 } |
|
322 |
|
323 static modelobjects::Edge* parseEdgeline( |
|
324 Model::EditContext& editor, |
|
325 const QString& line) |
|
326 { |
|
327 const bool succeeded = regexes::edgeline.exactMatch(line); |
|
328 if (succeeded) |
|
329 { |
|
330 const Color colour = {regexes::edgeline.cap(1).toInt(nullptr)}; |
|
331 const Vertex v_1 = vertexFromString(regexes::edgeline.cap(2)); |
|
332 const Vertex v_2 = vertexFromString(regexes::edgeline.cap(3)); |
|
333 return editor.append<modelobjects::Edge>(v_1, v_2, colour); |
|
334 } |
|
335 else |
|
336 { |
|
337 return nullptr; |
|
338 } |
|
339 } |
|
340 |
311 modelobjects::BaseObject* Parser::parseFromString( |
341 modelobjects::BaseObject* Parser::parseFromString( |
312 Model::EditContext& editor, |
342 Model::EditContext& editor, |
313 const QString& line) |
343 const QString& line) |
314 { |
344 { |
315 return editor.append<modelobjects::Comment>(line); |
345 modelobjects::Edge* edge = parseEdgeline(editor, line); |
316 } |
346 if (edge) |
|
347 { |
|
348 return edge; |
|
349 } |
|
350 return editor.append<modelobjects::ErrorLine>(line); |
|
351 } |