56 // ============================================================================= |
56 // ============================================================================= |
57 // |
57 // |
58 void LoadPrimitives() |
58 void LoadPrimitives() |
59 { |
59 { |
60 // Try to load prims.cfg |
60 // Try to load prims.cfg |
61 QFile conf (getPrimitivesCfgPath()); |
61 QFile conf(getPrimitivesCfgPath()); |
62 |
62 |
63 if (not conf.open (QIODevice::ReadOnly)) |
63 if (not conf.open(QIODevice::ReadOnly)) |
64 { |
64 { |
65 // No prims.cfg, build it |
65 // No prims.cfg, build it |
66 PrimitiveScanner::start(); |
66 PrimitiveScanner::start(); |
67 } |
67 } |
68 else |
68 else |
69 { |
69 { |
70 while (not conf.atEnd()) |
70 while (not conf.atEnd()) |
71 { |
71 { |
72 QString line = conf.readLine(); |
72 QString line = conf.readLine(); |
73 |
73 |
74 if (line.endsWith ("\n")) |
74 if (line.endsWith("\n")) |
75 line.chop (1); |
75 line.chop(1); |
76 |
76 |
77 if (line.endsWith ("\r")) |
77 if (line.endsWith("\r")) |
78 line.chop (1); |
78 line.chop(1); |
79 |
79 |
80 int space = line.indexOf (" "); |
80 int space = line.indexOf(" "); |
81 |
81 |
82 if (space == -1) |
82 if (space == -1) |
83 continue; |
83 continue; |
84 |
84 |
85 Primitive info; |
85 Primitive info; |
86 info.name = line.left (space); |
86 info.name = line.left(space); |
87 info.title = line.mid (space + 1); |
87 info.title = line.mid(space + 1); |
88 g_primitives << info; |
88 g_primitives << info; |
89 } |
89 } |
90 |
90 |
91 PrimitiveCategory::populateCategories(); |
91 PrimitiveCategory::populateCategories(); |
92 print ("%1 primitives loaded.\n", g_primitives.size()); |
92 print("%1 primitives loaded.\n", g_primitives.size()); |
93 } |
93 } |
94 } |
94 } |
95 |
95 |
96 // ============================================================================= |
96 // ============================================================================= |
97 // |
97 // |
98 static void GetRecursiveFilenames (QDir dir, QList<QString>& fnames) |
98 static void GetRecursiveFilenames(QDir dir, QList<QString>& fnames) |
99 { |
99 { |
100 QFileInfoList flist = dir.entryInfoList (QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); |
100 QFileInfoList flist = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); |
101 |
101 |
102 for (const QFileInfo& info : flist) |
102 for (const QFileInfo& info : flist) |
103 { |
103 { |
104 if (info.isDir()) |
104 if (info.isDir()) |
105 GetRecursiveFilenames (QDir (info.absoluteFilePath()), fnames); |
105 GetRecursiveFilenames(QDir(info.absoluteFilePath()), fnames); |
106 else |
106 else |
107 fnames << info.absoluteFilePath(); |
107 fnames << info.absoluteFilePath(); |
108 } |
108 } |
109 } |
109 } |
110 |
110 |
111 // ============================================================================= |
111 // ============================================================================= |
112 // |
112 // |
113 PrimitiveScanner::PrimitiveScanner (QObject* parent) : |
113 PrimitiveScanner::PrimitiveScanner(QObject* parent) : |
114 QObject (parent), |
114 QObject(parent), |
115 m_i (0) |
115 m_i(0) |
116 { |
116 { |
117 g_activeScanner = this; |
117 g_activeScanner = this; |
118 QDir dir = LDPaths::primitivesDir(); |
118 QDir dir = LDPaths::primitivesDir(); |
119 m_baselen = dir.absolutePath().length(); |
119 m_baselen = dir.absolutePath().length(); |
120 GetRecursiveFilenames (dir, m_files); |
120 GetRecursiveFilenames(dir, m_files); |
121 emit starting (m_files.size()); |
121 emit starting(m_files.size()); |
122 print ("Scanning primitives..."); |
122 print("Scanning primitives..."); |
123 } |
123 } |
124 |
124 |
125 // ============================================================================= |
125 // ============================================================================= |
126 // |
126 // |
127 PrimitiveScanner::~PrimitiveScanner() |
127 PrimitiveScanner::~PrimitiveScanner() |
131 |
131 |
132 // ============================================================================= |
132 // ============================================================================= |
133 // |
133 // |
134 void PrimitiveScanner::work() |
134 void PrimitiveScanner::work() |
135 { |
135 { |
136 int j = qMin (m_i + 100, m_files.size()); |
136 int j = qMin(m_i + 100, m_files.size()); |
137 |
137 |
138 for (; m_i < j; ++m_i) |
138 for (; m_i < j; ++m_i) |
139 { |
139 { |
140 QString fname = m_files[m_i]; |
140 QString fname = m_files[m_i]; |
141 QFile f (fname); |
141 QFile f(fname); |
142 |
142 |
143 if (not f.open (QIODevice::ReadOnly)) |
143 if (not f.open(QIODevice::ReadOnly)) |
144 continue; |
144 continue; |
145 |
145 |
146 Primitive info; |
146 Primitive info; |
147 info.name = fname.mid (m_baselen + 1); // make full path relative |
147 info.name = fname.mid(m_baselen + 1); // make full path relative |
148 info.name.replace ('/', '\\'); // use DOS backslashes, they're expected |
148 info.name.replace('/', '\\'); // use DOS backslashes, they're expected |
149 info.category = nullptr; |
149 info.category = nullptr; |
150 QByteArray titledata = f.readLine(); |
150 QByteArray titledata = f.readLine(); |
151 |
151 |
152 if (titledata != QByteArray()) |
152 if (titledata != QByteArray()) |
153 info.title = QString::fromUtf8 (titledata); |
153 info.title = QString::fromUtf8(titledata); |
154 |
154 |
155 info.title = info.title.simplified(); |
155 info.title = info.title.simplified(); |
156 |
156 |
157 if (Q_LIKELY (info.title[0] == '0')) |
157 if (Q_LIKELY(info.title[0] == '0')) |
158 { |
158 { |
159 info.title.remove (0, 1); // remove 0 |
159 info.title.remove(0, 1); // remove 0 |
160 info.title = info.title.simplified(); |
160 info.title = info.title.simplified(); |
161 } |
161 } |
162 |
162 |
163 m_prims << info; |
163 m_prims << info; |
164 } |
164 } |
165 |
165 |
166 if (m_i == m_files.size()) |
166 if (m_i == m_files.size()) |
167 { |
167 { |
168 // Done with primitives, now save to a config file |
168 // Done with primitives, now save to a config file |
169 QString path = getPrimitivesCfgPath(); |
169 QString path = getPrimitivesCfgPath(); |
170 QFile conf (path); |
170 QFile conf(path); |
171 |
171 |
172 if (not conf.open (QIODevice::WriteOnly | QIODevice::Text)) |
172 if (not conf.open(QIODevice::WriteOnly | QIODevice::Text)) |
173 Critical (format ("Couldn't write primitive list %1: %2", |
173 Critical(format("Couldn't write primitive list %1: %2", |
174 path, conf.errorString())); |
174 path, conf.errorString())); |
175 else |
175 else |
176 { |
176 { |
177 for (Primitive& info : m_prims) |
177 for (Primitive& info : m_prims) |
178 fprint (conf, "%1 %2\r\n", info.name, info.title); |
178 fprint(conf, "%1 %2\r\n", info.name, info.title); |
179 |
179 |
180 conf.close(); |
180 conf.close(); |
181 } |
181 } |
182 |
182 |
183 g_primitives = m_prims; |
183 g_primitives = m_prims; |
184 PrimitiveCategory::populateCategories(); |
184 PrimitiveCategory::populateCategories(); |
185 print ("%1 primitives scanned", g_primitives.size()); |
185 print("%1 primitives scanned", g_primitives.size()); |
186 g_activeScanner = nullptr; |
186 g_activeScanner = nullptr; |
187 emit workDone(); |
187 emit workDone(); |
188 deleteLater(); |
188 deleteLater(); |
189 } |
189 } |
190 else |
190 else |
191 { |
191 { |
192 // Defer to event loop, pick up the work later |
192 // Defer to event loop, pick up the work later |
193 emit update (m_i); |
193 emit update(m_i); |
194 QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection); |
194 QMetaObject::invokeMethod(this, "work", Qt::QueuedConnection); |
195 } |
195 } |
196 } |
196 } |
197 |
197 |
198 // ============================================================================= |
198 // ============================================================================= |
199 // |
199 // |
284 for (PrimitiveCategory* cat : g_PrimitiveCategories) |
284 for (PrimitiveCategory* cat : g_PrimitiveCategories) |
285 delete cat; |
285 delete cat; |
286 |
286 |
287 g_PrimitiveCategories.clear(); |
287 g_PrimitiveCategories.clear(); |
288 QString path = ":/data/primitive-categories.cfg"; |
288 QString path = ":/data/primitive-categories.cfg"; |
289 QFile f (path); |
289 QFile f(path); |
290 |
290 |
291 if (not f.open (QIODevice::ReadOnly)) |
291 if (not f.open(QIODevice::ReadOnly)) |
292 { |
292 { |
293 Critical (format (QObject::tr ("Failed to open primitive categories: %1"), f.errorString())); |
293 Critical(format(QObject::tr("Failed to open primitive categories: %1"), f.errorString())); |
294 return; |
294 return; |
295 } |
295 } |
296 |
296 |
297 PrimitiveCategory* cat = nullptr; |
297 PrimitiveCategory* cat = nullptr; |
298 |
298 |
299 while (not f.atEnd()) |
299 while (not f.atEnd()) |
300 { |
300 { |
301 QString line = f.readLine(); |
301 QString line = f.readLine(); |
302 int colon; |
302 int colon; |
303 |
303 |
304 if (line.endsWith ("\n")) |
304 if (line.endsWith("\n")) |
305 line.chop (1); |
305 line.chop(1); |
306 |
306 |
307 if (line.length() == 0 or line[0] == '#') |
307 if (line.length() == 0 or line[0] == '#') |
308 continue; |
308 continue; |
309 |
309 |
310 if ((colon = line.indexOf (":")) == -1) |
310 if ((colon = line.indexOf(":")) == -1) |
311 { |
311 { |
312 if (cat and cat->isValidToInclude()) |
312 if (cat and cat->isValidToInclude()) |
313 g_PrimitiveCategories << cat; |
313 g_PrimitiveCategories << cat; |
314 |
314 |
315 cat = new PrimitiveCategory (line); |
315 cat = new PrimitiveCategory(line); |
316 } |
316 } |
317 else if (cat) |
317 else if (cat) |
318 { |
318 { |
319 QString cmd = line.left (colon); |
319 QString cmd = line.left(colon); |
320 RegexType type = EFilenameRegex; |
320 RegexType type = EFilenameRegex; |
321 |
321 |
322 if (cmd == "f") |
322 if (cmd == "f") |
323 type = EFilenameRegex; |
323 type = EFilenameRegex; |
324 else if (cmd == "t") |
324 else if (cmd == "t") |
325 type = ETitleRegex; |
325 type = ETitleRegex; |
326 else |
326 else |
327 { |
327 { |
328 print (tr ("Warning: unknown command \"%1\" on line \"%2\""), cmd, line); |
328 print(tr("Warning: unknown command \"%1\" on line \"%2\""), cmd, line); |
329 continue; |
329 continue; |
330 } |
330 } |
331 |
331 |
332 QRegExp regex (line.mid (colon + 1)); |
332 QRegExp regex(line.mid(colon + 1)); |
333 RegexEntry entry = { regex, type }; |
333 RegexEntry entry = { regex, type }; |
334 cat->regexes << entry; |
334 cat->regexes << entry; |
335 } |
335 } |
336 else |
336 else |
337 print ("Warning: Rules given before the first category name"); |
337 print("Warning: Rules given before the first category name"); |
338 } |
338 } |
339 |
339 |
340 if (cat->isValidToInclude()) |
340 if (cat->isValidToInclude()) |
341 g_PrimitiveCategories << cat; |
341 g_PrimitiveCategories << cat; |
342 |
342 |
343 // Add a category for unmatched primitives. |
343 // Add a category for unmatched primitives. |
344 // Note: if this function is called the second time, g_unmatched has been |
344 // Note: if this function is called the second time, g_unmatched has been |
345 // deleted at the beginning of the function and is dangling at this point. |
345 // deleted at the beginning of the function and is dangling at this point. |
346 g_unmatched = new PrimitiveCategory (tr ("Other")); |
346 g_unmatched = new PrimitiveCategory(tr("Other")); |
347 g_PrimitiveCategories << g_unmatched; |
347 g_PrimitiveCategories << g_unmatched; |
348 f.close(); |
348 f.close(); |
349 } |
349 } |
350 |
350 |
351 // ============================================================================= |
351 // ============================================================================= |
352 // |
352 // |
353 bool PrimitiveCategory::isValidToInclude() |
353 bool PrimitiveCategory::isValidToInclude() |
354 { |
354 { |
355 if (regexes.isEmpty()) |
355 if (regexes.isEmpty()) |
356 { |
356 { |
357 print (tr ("Warning: category \"%1\" left without patterns"), name()); |
357 print(tr("Warning: category \"%1\" left without patterns"), name()); |
358 deleteLater(); |
358 deleteLater(); |
359 return false; |
359 return false; |
360 } |
360 } |
361 |
361 |
362 return true; |
362 return true; |
374 return g_activeScanner; |
374 return g_activeScanner; |
375 } |
375 } |
376 |
376 |
377 // ============================================================================= |
377 // ============================================================================= |
378 // |
378 // |
379 static double GetRadialPoint (int i, int divs, double (*func) (double)) |
379 static double GetRadialPoint(int i, int divs, double(*func)(double)) |
380 { |
380 { |
381 return (*func) ((i * 2 * Pi) / divs); |
381 return (*func)((i * 2 * Pi) / divs); |
382 } |
382 } |
383 |
383 |
384 // ============================================================================= |
384 // ============================================================================= |
385 // |
385 // |
386 void MakeCircle (int segs, int divs, double radius, QList<QLineF>& lines) |
386 void MakeCircle(int segs, int divs, double radius, QList<QLineF>& lines) |
387 { |
387 { |
388 for (int i = 0; i < segs; ++i) |
388 for (int i = 0; i < segs; ++i) |
389 { |
389 { |
390 double x0 = radius * GetRadialPoint (i, divs, cos), |
390 double x0 = radius * GetRadialPoint(i, divs, cos), |
391 x1 = radius * GetRadialPoint (i + 1, divs, cos), |
391 x1 = radius * GetRadialPoint(i + 1, divs, cos), |
392 z0 = radius * GetRadialPoint (i, divs, sin), |
392 z0 = radius * GetRadialPoint(i, divs, sin), |
393 z1 = radius * GetRadialPoint (i + 1, divs, sin); |
393 z1 = radius * GetRadialPoint(i + 1, divs, sin); |
394 |
394 |
395 lines << QLineF (QPointF (x0, z0), QPointF (x1, z1)); |
395 lines << QLineF(QPointF(x0, z0), QPointF(x1, z1)); |
396 } |
396 } |
397 } |
397 } |
398 |
398 |
399 // ============================================================================= |
399 // ============================================================================= |
400 // |
400 // |
401 LDObjectList MakePrimitive (PrimitiveType type, int segs, int divs, int num) |
401 LDObjectList MakePrimitive(PrimitiveType type, int segs, int divs, int num) |
402 { |
402 { |
403 LDObjectList objs; |
403 LDObjectList objs; |
404 QList<int> condLineSegs; |
404 QList<int> condLineSegs; |
405 QList<QLineF> circle; |
405 QList<QLineF> circle; |
406 |
406 |
407 MakeCircle (segs, divs, 1, circle); |
407 MakeCircle(segs, divs, 1, circle); |
408 |
408 |
409 for (int i = 0; i < segs; ++i) |
409 for (int i = 0; i < segs; ++i) |
410 { |
410 { |
411 double x0 = circle[i].x1(), |
411 double x0 = circle[i].x1(), |
412 x1 = circle[i].x2(), |
412 x1 = circle[i].x2(), |
413 z0 = circle[i].y1(), |
413 z0 = circle[i].y1(), |
414 z1 = circle[i].y2(); |
414 z1 = circle[i].y2(); |
415 |
415 |
416 switch (type) |
416 switch(type) |
417 { |
417 { |
418 case Circle: |
418 case Circle: |
419 { |
419 { |
420 Vertex v0 (x0, 0.0f, z0), |
420 Vertex v0(x0, 0.0f, z0), |
421 v1 (x1, 0.0f, z1); |
421 v1(x1, 0.0f, z1); |
422 |
422 |
423 LDLine* line (LDSpawn<LDLine>()); |
423 LDLine* line(LDSpawn<LDLine>()); |
424 line->setVertex (0, v0); |
424 line->setVertex(0, v0); |
425 line->setVertex (1, v1); |
425 line->setVertex(1, v1); |
426 line->setColor (EdgeColor); |
426 line->setColor(EdgeColor); |
427 objs << line; |
427 objs << line; |
428 } break; |
428 } break; |
429 |
429 |
430 case Cylinder: |
430 case Cylinder: |
431 case Ring: |
431 case Ring: |
516 if (segs < divs and condLineSegs.size() != 0) |
516 if (segs < divs and condLineSegs.size() != 0) |
517 condLineSegs << segs; |
517 condLineSegs << segs; |
518 |
518 |
519 for (int i : condLineSegs) |
519 for (int i : condLineSegs) |
520 { |
520 { |
521 Vertex v0 (GetRadialPoint (i, divs, cos), 0.0f, GetRadialPoint (i, divs, sin)), |
521 Vertex v0(GetRadialPoint(i, divs, cos), 0.0f, GetRadialPoint(i, divs, sin)), |
522 v1, |
522 v1, |
523 v2 (GetRadialPoint (i + 1, divs, cos), 0.0f, GetRadialPoint (i + 1, divs, sin)), |
523 v2(GetRadialPoint(i + 1, divs, cos), 0.0f, GetRadialPoint(i + 1, divs, sin)), |
524 v3 (GetRadialPoint (i - 1, divs, cos), 0.0f, GetRadialPoint (i - 1, divs, sin)); |
524 v3(GetRadialPoint(i - 1, divs, cos), 0.0f, GetRadialPoint(i - 1, divs, sin)); |
525 |
525 |
526 if (type == Cylinder) |
526 if (type == Cylinder) |
527 { |
527 { |
528 v1 = Vertex (v0[X], 1.0f, v0[Z]); |
528 v1 = Vertex(v0[X], 1.0f, v0[Z]); |
529 } |
529 } |
530 else if (type == Cone) |
530 else if (type == Cone) |
531 { |
531 { |
532 v1 = Vertex (v0[X] * (num + 1), 0.0f, v0[Z] * (num + 1)); |
532 v1 = Vertex(v0[X] *(num + 1), 0.0f, v0[Z] *(num + 1)); |
533 v0.setX (v0.x() * num); |
533 v0.setX(v0.x() * num); |
534 v0.setY (1.0); |
534 v0.setY(1.0); |
535 v0.setZ (v0.z() * num); |
535 v0.setZ(v0.z() * num); |
536 } |
536 } |
537 |
537 |
538 LDCondLine* line = (LDSpawn<LDCondLine>()); |
538 LDCondLine* line = (LDSpawn<LDCondLine>()); |
539 line->setColor (EdgeColor); |
539 line->setColor(EdgeColor); |
540 line->setVertex (0, v0); |
540 line->setVertex(0, v0); |
541 line->setVertex (1, v1); |
541 line->setVertex(1, v1); |
542 line->setVertex (2, v2); |
542 line->setVertex(2, v2); |
543 line->setVertex (3, v3); |
543 line->setVertex(3, v3); |
544 objs << line; |
544 objs << line; |
545 } |
545 } |
546 |
546 |
547 return objs; |
547 return objs; |
548 } |
548 } |
549 |
549 |
550 // ============================================================================= |
550 // ============================================================================= |
551 // |
551 // |
552 static QString PrimitiveTypeName (PrimitiveType type) |
552 static QString PrimitiveTypeName(PrimitiveType type) |
553 { |
553 { |
554 // Not translated as primitives are in English. |
554 // Not translated as primitives are in English. |
555 return type == Circle ? "Circle" : |
555 return type == Circle ? "Circle" : |
556 type == Cylinder ? "Cylinder" : |
556 type == Cylinder ? "Cylinder" : |
557 type == Disc ? "Disc" : |
557 type == Disc ? "Disc" : |
559 type == Ring ? "Ring" : "Cone"; |
559 type == Ring ? "Ring" : "Cone"; |
560 } |
560 } |
561 |
561 |
562 // ============================================================================= |
562 // ============================================================================= |
563 // |
563 // |
564 QString MakeRadialFileName (PrimitiveType type, int segs, int divs, int num) |
564 QString MakeRadialFileName(PrimitiveType type, int segs, int divs, int num) |
565 { |
565 { |
566 int numer = segs, |
566 int numer = segs, |
567 denom = divs; |
567 denom = divs; |
568 |
568 |
569 // Simplify the fractional part, but the denominator must be at least 4. |
569 // Simplify the fractional part, but the denominator must be at least 4. |
570 Simplify (numer, denom); |
570 Simplify(numer, denom); |
571 |
571 |
572 if (denom < 4) |
572 if (denom < 4) |
573 { |
573 { |
574 const int factor = 4 / denom; |
574 const int factor = 4 / denom; |
575 numer *= factor; |
575 numer *= factor; |
576 denom *= factor; |
576 denom *= factor; |
577 } |
577 } |
578 |
578 |
579 // Compose some general information: prefix, fraction, root, ring number |
579 // Compose some general information: prefix, fraction, root, ring number |
580 QString prefix = (divs == LowResolution) ? "" : format ("%1/", divs); |
580 QString prefix = (divs == LowResolution) ? "" : format("%1/", divs); |
581 QString frac = format ("%1-%2", numer, denom); |
581 QString frac = format("%1-%2", numer, denom); |
582 QString root = g_radialNameRoots[type]; |
582 QString root = g_radialNameRoots[type]; |
583 QString numstr = (type == Ring or type == Cone) ? format ("%1", num) : ""; |
583 QString numstr = (type == Ring or type == Cone) ? format("%1", num) : ""; |
584 |
584 |
585 // Truncate the root if necessary (7-16rin4.dat for instance). |
585 // Truncate the root if necessary(7-16rin4.dat for instance). |
586 // However, always keep the root at least 2 characters. |
586 // However, always keep the root at least 2 characters. |
587 int extra = (frac.length() + numstr.length() + root.length()) - 8; |
587 int extra = (frac.length() + numstr.length() + root.length()) - 8; |
588 root.chop (qBound (0, extra, 2)); |
588 root.chop(qBound(0, extra, 2)); |
589 |
589 |
590 // Stick them all together and return the result. |
590 // Stick them all together and return the result. |
591 return prefix + frac + root + numstr + ".dat"; |
591 return prefix + frac + root + numstr + ".dat"; |
592 } |
592 } |
593 |
593 |
594 // ============================================================================= |
594 // ============================================================================= |
595 // |
595 // |
596 LDDocument* GeneratePrimitive (PrimitiveType type, int segs, int divs, int num) |
596 LDDocument* GeneratePrimitive(PrimitiveType type, int segs, int divs, int num) |
597 { |
597 { |
598 // Make the description |
598 // Make the description |
599 QString frac = QString::number ((float) segs / divs); |
599 QString frac = QString::number((float) segs / divs); |
600 QString name = MakeRadialFileName (type, segs, divs, num); |
600 QString name = MakeRadialFileName(type, segs, divs, num); |
601 QString descr; |
601 QString descr; |
602 |
602 |
603 // Ensure that there's decimals, even if they're 0. |
603 // Ensure that there's decimals, even if they're 0. |
604 if (frac.indexOf (".") == -1) |
604 if (frac.indexOf(".") == -1) |
605 frac += ".0"; |
605 frac += ".0"; |
606 |
606 |
607 if (type == Ring or type == Cone) |
607 if (type == Ring or type == Cone) |
608 { |
608 { |
609 QString spacing = |
609 QString spacing = |
610 (num < 10) ? " " : |
610 (num < 10) ? " " : |
611 (num < 100) ? " " : ""; |
611 (num < 100) ? " " : ""; |
612 |
612 |
613 descr = format ("%1 %2%3 x %4", PrimitiveTypeName (type), spacing, num, frac); |
613 descr = format("%1 %2%3 x %4", PrimitiveTypeName(type), spacing, num, frac); |
614 } |
614 } |
615 else |
615 else |
616 descr = format ("%1 %2", PrimitiveTypeName (type), frac); |
616 descr = format("%1 %2", PrimitiveTypeName(type), frac); |
617 |
617 |
618 // Prepend "Hi-Res" if 48/ primitive. |
618 // Prepend "Hi-Res" if 48/ primitive. |
619 if (divs == HighResolution) |
619 if (divs == HighResolution) |
620 descr.insert (0, "Hi-Res "); |
620 descr.insert(0, "Hi-Res "); |
621 |
621 |
622 LDDocument* document = g_win->newDocument(); |
622 LDDocument* document = g_win->newDocument(); |
623 document->setDefaultName (name); |
623 document->setDefaultName(name); |
624 |
624 |
625 QString author = APPNAME; |
625 QString author = APPNAME; |
626 QString license = ""; |
626 QString license = ""; |
627 |
627 |
628 if (not config.defaultName().isEmpty()) |
628 if (not config.defaultName().isEmpty()) |
629 { |
629 { |
630 license = PreferredLicenseText(); |
630 license = PreferredLicenseText(); |
631 author = format ("%1 [%2]", config.defaultName(), config.defaultUser()); |
631 author = format("%1 [%2]", config.defaultName(), config.defaultUser()); |
632 } |
632 } |
633 |
633 |
634 LDObjectList objs; |
634 LDObjectList objs; |
635 |
635 |
636 objs << LDSpawn<LDComment> (descr) |
636 objs << LDSpawn<LDComment>(descr) |
637 << LDSpawn<LDComment> (format ("Name: %1", name)) |
637 << LDSpawn<LDComment>(format("Name: %1", name)) |
638 << LDSpawn<LDComment> (format ("Author: %1", author)) |
638 << LDSpawn<LDComment>(format("Author: %1", author)) |
639 << LDSpawn<LDComment> (format ("!LDRAW_ORG Unofficial_%1Primitive", |
639 << LDSpawn<LDComment>(format("!LDRAW_ORG Unofficial_%1Primitive", |
640 divs == HighResolution ? "48_" : "")) |
640 divs == HighResolution ? "48_" : "")) |
641 << LDSpawn<LDComment> (license) |
641 << LDSpawn<LDComment>(license) |
642 << LDSpawn<LDEmpty>() |
642 << LDSpawn<LDEmpty>() |
643 << LDSpawn<LDBfc> (BfcStatement::CertifyCCW) |
643 << LDSpawn<LDBfc>(BfcStatement::CertifyCCW) |
644 << LDSpawn<LDEmpty>(); |
644 << LDSpawn<LDEmpty>(); |
645 |
645 |
646 document->openForEditing(); |
646 document->openForEditing(); |
647 document->history()->setIgnoring (false); |
647 document->history()->setIgnoring(false); |
648 document->addObjects (objs); |
648 document->addObjects(objs); |
649 document->addObjects (MakePrimitive (type, segs, divs, num)); |
649 document->addObjects(MakePrimitive(type, segs, divs, num)); |
650 document->addHistoryStep(); |
650 document->addHistoryStep(); |
651 return document; |
651 return document; |
652 } |
652 } |
653 |
653 |
654 // ============================================================================= |
654 // ============================================================================= |
655 // |
655 // |
656 LDDocument* GetPrimitive (PrimitiveType type, int segs, int divs, int num) |
656 LDDocument* GetPrimitive(PrimitiveType type, int segs, int divs, int num) |
657 { |
657 { |
658 QString name = MakeRadialFileName (type, segs, divs, num); |
658 QString name = MakeRadialFileName(type, segs, divs, num); |
659 LDDocument* f = g_win->documents()->getDocumentByName (name); |
659 LDDocument* f = g_win->documents()->getDocumentByName(name); |
660 |
660 |
661 if (f) |
661 if (f) |
662 return f; |
662 return f; |
663 |
663 |
664 return GeneratePrimitive (type, segs, divs, num); |
664 return GeneratePrimitive(type, segs, divs, num); |
665 } |
665 } |
666 |
666 |
667 // ============================================================================= |
667 // ============================================================================= |
668 // |
668 // |
669 PrimitivePrompt::PrimitivePrompt (QWidget* parent, Qt::WindowFlags f) : |
669 PrimitivePrompt::PrimitivePrompt(QWidget* parent, Qt::WindowFlags f) : |
670 QDialog (parent, f) |
670 QDialog(parent, f) |
671 { |
671 { |
672 ui = new Ui_MakePrimUI; |
672 ui = new Ui_MakePrimUI; |
673 ui->setupUi (this); |
673 ui->setupUi(this); |
674 connect (ui->cb_hires, SIGNAL (toggled (bool)), this, SLOT (hiResToggled (bool))); |
674 connect(ui->cb_hires, SIGNAL(toggled(bool)), this, SLOT(hiResToggled(bool))); |
675 } |
675 } |
676 |
676 |
677 // ============================================================================= |
677 // ============================================================================= |
678 // |
678 // |
679 PrimitivePrompt::~PrimitivePrompt() |
679 PrimitivePrompt::~PrimitivePrompt() |