src/primitives.cpp

changeset 1217
314e12e23c3a
parent 1215
77a0270352a3
child 1222
34def2630300
equal deleted inserted replaced
1216:12f9ea615cbc 1217:314e12e23c3a
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 //
207 scanner->work(); 207 scanner->work();
208 } 208 }
209 209
210 // ============================================================================= 210 // =============================================================================
211 // 211 //
212 PrimitiveCategory::PrimitiveCategory (QString name, QObject* parent) : 212 PrimitiveCategory::PrimitiveCategory(QString name, QObject* parent) :
213 QObject (parent), 213 QObject(parent),
214 m_name (name) {} 214 m_name(name) {}
215 215
216 // ============================================================================= 216 // =============================================================================
217 // 217 //
218 void PrimitiveCategory::populateCategories() 218 void PrimitiveCategory::populateCategories()
219 { 219 {
231 // the primitive's category is set to the category the regex beloings to. 231 // the primitive's category is set to the category the regex beloings to.
232 for (PrimitiveCategory* cat : g_PrimitiveCategories) 232 for (PrimitiveCategory* cat : g_PrimitiveCategories)
233 { 233 {
234 for (RegexEntry& entry : cat->regexes) 234 for (RegexEntry& entry : cat->regexes)
235 { 235 {
236 switch (entry.type) 236 switch(entry.type)
237 { 237 {
238 case EFilenameRegex: 238 case EFilenameRegex:
239 { 239 {
240 // f-regex, check against filename 240 // f-regex, check against filename
241 matched = entry.regex.exactMatch (prim.name); 241 matched = entry.regex.exactMatch(prim.name);
242 } break; 242 } break;
243 243
244 case ETitleRegex: 244 case ETitleRegex:
245 { 245 {
246 // t-regex, check against title 246 // t-regex, check against title
247 matched = entry.regex.exactMatch (prim.title); 247 matched = entry.regex.exactMatch(prim.title);
248 } break; 248 } break;
249 } 249 }
250 250
251 if (matched) 251 if (matched)
252 { 252 {
268 g_unmatched->prims << prim; 268 g_unmatched->prims << prim;
269 } 269 }
270 270
271 // Sort the categories. Note that we do this here because we need the existing 271 // Sort the categories. Note that we do this here because we need the existing
272 // order for regex matching. 272 // order for regex matching.
273 qSort (g_PrimitiveCategories.begin(), g_PrimitiveCategories.end(), 273 qSort(g_PrimitiveCategories.begin(), g_PrimitiveCategories.end(),
274 [](PrimitiveCategory* const& a, PrimitiveCategory* const& b) -> bool 274 [](PrimitiveCategory* const& a, PrimitiveCategory* const& b) -> bool
275 { 275 {
276 return a->name() < b->name(); 276 return a->name() < b->name();
277 }); 277 });
278 } 278 }
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:
444 y0 = y1 = 0.0f; 444 y0 = y1 = 0.0f;
445 y2 = y3 = 1.0f; 445 y2 = y3 = 1.0f;
446 } 446 }
447 else 447 else
448 { 448 {
449 x2 = x1 * (num + 1); 449 x2 = x1 *(num + 1);
450 x3 = x0 * (num + 1); 450 x3 = x0 *(num + 1);
451 z2 = z1 * (num + 1); 451 z2 = z1 *(num + 1);
452 z3 = z0 * (num + 1); 452 z3 = z0 *(num + 1);
453 453
454 x0 *= num; 454 x0 *= num;
455 x1 *= num; 455 x1 *= num;
456 z0 *= num; 456 z0 *= num;
457 z1 *= num; 457 z1 *= num;
463 y0 = y1 = 1.0f; 463 y0 = y1 = 1.0f;
464 y2 = y3 = 0.0f; 464 y2 = y3 = 0.0f;
465 } 465 }
466 } 466 }
467 467
468 Vertex v0 (x0, y0, z0), 468 Vertex v0(x0, y0, z0),
469 v1 (x1, y1, z1), 469 v1(x1, y1, z1),
470 v2 (x2, y2, z2), 470 v2(x2, y2, z2),
471 v3 (x3, y3, z3); 471 v3(x3, y3, z3);
472 472
473 LDQuad* quad (LDSpawn<LDQuad> (v0, v1, v2, v3)); 473 LDQuad* quad(LDSpawn<LDQuad>(v0, v1, v2, v3));
474 quad->setColor (MainColor); 474 quad->setColor(MainColor);
475 475
476 if (type == Cylinder) 476 if (type == Cylinder)
477 quad->invert(); 477 quad->invert();
478 478
479 objs << quad; 479 objs << quad;
493 { 493 {
494 x2 = (x0 >= 0.0f) ? 1.0f : -1.0f; 494 x2 = (x0 >= 0.0f) ? 1.0f : -1.0f;
495 z2 = (z0 >= 0.0f) ? 1.0f : -1.0f; 495 z2 = (z0 >= 0.0f) ? 1.0f : -1.0f;
496 } 496 }
497 497
498 Vertex v0 (x0, 0.0f, z0), 498 Vertex v0(x0, 0.0f, z0),
499 v1 (x1, 0.0f, z1), 499 v1(x1, 0.0f, z1),
500 v2 (x2, 0.0f, z2); 500 v2(x2, 0.0f, z2);
501 501
502 // Disc negatives need to go the other way around, otherwise 502 // Disc negatives need to go the other way around, otherwise
503 // they'll end up upside-down. 503 // they'll end up upside-down.
504 LDTriangle* seg (LDSpawn<LDTriangle>()); 504 LDTriangle* seg(LDSpawn<LDTriangle>());
505 seg->setColor (MainColor); 505 seg->setColor(MainColor);
506 seg->setVertex (type == Disc ? 0 : 2, v0); 506 seg->setVertex(type == Disc ? 0 : 2, v0);
507 seg->setVertex (1, v1); 507 seg->setVertex(1, v1);
508 seg->setVertex (type == Disc ? 2 : 0, v2); 508 seg->setVertex(type == Disc ? 2 : 0, v2);
509 objs << seg; 509 objs << seg;
510 } break; 510 } break;
511 } 511 }
512 } 512 }
513 513
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()
681 delete ui; 681 delete ui;
682 } 682 }
683 683
684 // ============================================================================= 684 // =============================================================================
685 // 685 //
686 void PrimitivePrompt::hiResToggled (bool on) 686 void PrimitivePrompt::hiResToggled(bool on)
687 { 687 {
688 ui->sb_segs->setMaximum (on ? HighResolution : LowResolution); 688 ui->sb_segs->setMaximum(on ? HighResolution : LowResolution);
689 689
690 // If the current value is 16 and we switch to hi-res, default the 690 // If the current value is 16 and we switch to hi-res, default the
691 // spinbox to 48. 691 // spinbox to 48.
692 if (on and ui->sb_segs->value() == LowResolution) 692 if (on and ui->sb_segs->value() == LowResolution)
693 ui->sb_segs->setValue (HighResolution); 693 ui->sb_segs->setValue(HighResolution);
694 } 694 }

mercurial