56 cfg (String, prog_ytruder, ""); |
57 cfg (String, prog_ytruder, ""); |
57 cfg (String, prog_rectifier, ""); |
58 cfg (String, prog_rectifier, ""); |
58 cfg (String, prog_edger2, ""); |
59 cfg (String, prog_edger2, ""); |
59 |
60 |
60 str* const g_extProgPaths[] = |
61 str* const g_extProgPaths[] = |
61 { &prog_isecalc, |
62 { |
|
63 &prog_isecalc, |
62 &prog_intersector, |
64 &prog_intersector, |
63 &prog_coverer, |
65 &prog_coverer, |
64 &prog_ytruder, |
66 &prog_ytruder, |
65 &prog_rectifier, |
67 &prog_rectifier, |
66 &prog_edger2, |
68 &prog_edger2, |
73 cfg (Bool, prog_ytruder_wine, false); |
75 cfg (Bool, prog_ytruder_wine, false); |
74 cfg (Bool, prog_rectifier_wine, false); |
76 cfg (Bool, prog_rectifier_wine, false); |
75 cfg (Bool, prog_edger2_wine, false); |
77 cfg (Bool, prog_edger2_wine, false); |
76 |
78 |
77 bool* const g_extProgWine[] = |
79 bool* const g_extProgWine[] = |
78 { &prog_isecalc_wine, |
80 { |
|
81 &prog_isecalc_wine, |
79 &prog_intersector_wine, |
82 &prog_intersector_wine, |
80 &prog_coverer_wine, |
83 &prog_coverer_wine, |
81 &prog_ytruder_wine, |
84 &prog_ytruder_wine, |
82 &prog_rectifier_wine, |
85 &prog_rectifier_wine, |
83 &prog_edger2_wine, |
86 &prog_edger2_wine, |
84 }; |
87 }; |
85 #endif // _WIN32 |
88 #endif // _WIN32 |
86 |
89 |
87 const char* g_extProgNames[] = |
90 const char* g_extProgNames[] = |
88 { "Isecalc", |
91 { |
|
92 "Isecalc", |
89 "Intersector", |
93 "Intersector", |
90 "Coverer", |
94 "Coverer", |
91 "Ytruder", |
95 "Ytruder", |
92 "Rectifier", |
96 "Rectifier", |
93 "Edger2" |
97 "Edger2" |
94 }; |
98 }; |
95 |
99 |
96 // ============================================================================= |
100 // ============================================================================= |
97 // ----------------------------------------------------------------------------- |
101 // ----------------------------------------------------------------------------- |
98 static bool checkProgPath (const extprog prog) |
102 static bool checkProgPath (const extprog prog) |
99 { str& path = *g_extProgPaths[prog]; |
103 { |
|
104 str& path = *g_extProgPaths[prog]; |
100 |
105 |
101 if (path.length() > 0) |
106 if (path.length() > 0) |
102 return true; |
107 return true; |
103 |
108 |
104 ExtProgPathPrompt* dlg = new ExtProgPathPrompt (g_extProgNames[prog]); |
109 ExtProgPathPrompt* dlg = new ExtProgPathPrompt (g_extProgNames[prog]); |
105 |
110 |
106 if (dlg->exec() && !dlg->getPath().isEmpty()) |
111 if (dlg->exec() && !dlg->getPath().isEmpty()) |
107 { path = dlg->getPath(); |
112 { |
|
113 path = dlg->getPath(); |
108 return true; |
114 return true; |
109 } |
115 } |
110 |
116 |
111 return false; |
117 return false; |
112 } |
118 } |
113 |
119 |
114 // ============================================================================= |
120 // ============================================================================= |
115 // ----------------------------------------------------------------------------- |
121 // ----------------------------------------------------------------------------- |
116 static str processErrorString (extprog prog, QProcess& proc) |
122 static str processErrorString (extprog prog, QProcess& proc) |
117 { switch (proc.error()) |
123 { |
118 { case QProcess::FailedToStart: |
124 switch (proc.error()) |
119 { str wineblurb; |
125 { |
|
126 case QProcess::FailedToStart: |
|
127 { |
|
128 str wineblurb; |
120 |
129 |
121 #ifndef _WIN32 |
130 #ifndef _WIN32 |
122 if (*g_extProgWine[prog]) |
131 if (*g_extProgWine[prog]) |
123 wineblurb = "make sure Wine is installed and "; |
132 wineblurb = "make sure Wine is installed and "; |
124 #endif |
133 #endif |
144 } |
153 } |
145 |
154 |
146 // ============================================================================= |
155 // ============================================================================= |
147 // ----------------------------------------------------------------------------- |
156 // ----------------------------------------------------------------------------- |
148 static bool mkTempFile (QTemporaryFile& tmp, str& fname) |
157 static bool mkTempFile (QTemporaryFile& tmp, str& fname) |
149 { if (!tmp.open()) |
158 { |
|
159 if (!tmp.open()) |
150 return false; |
160 return false; |
151 |
161 |
152 fname = tmp.fileName(); |
162 fname = tmp.fileName(); |
153 tmp.close(); |
163 tmp.close(); |
154 return true; |
164 return true; |
155 } |
165 } |
156 |
166 |
157 // ============================================================================= |
167 // ============================================================================= |
158 // ----------------------------------------------------------------------------- |
168 // ----------------------------------------------------------------------------- |
159 static void writeObjects (const QList<LDObject*>& objects, File& f) |
169 static void writeObjects (const QList<LDObject*>& objects, File& f) |
160 { for (LDObject* obj : objects) |
170 { |
161 { if (obj->getType() == LDObject::Subfile) |
171 for (LDObject* obj : objects) |
162 { LDSubfile* ref = static_cast<LDSubfile*> (obj); |
172 { |
|
173 if (obj->getType() == LDObject::Subfile) |
|
174 { |
|
175 LDSubfile* ref = static_cast<LDSubfile*> (obj); |
163 QList<LDObject*> objs = ref->inlineContents (LDSubfile::DeepInline); |
176 QList<LDObject*> objs = ref->inlineContents (LDSubfile::DeepInline); |
164 |
177 |
165 writeObjects (objs, f); |
178 writeObjects (objs, f); |
166 |
179 |
167 for (LDObject* obj : objs) |
180 for (LDObject* obj : objs) |
173 } |
186 } |
174 |
187 |
175 // ============================================================================= |
188 // ============================================================================= |
176 // ----------------------------------------------------------------------------- |
189 // ----------------------------------------------------------------------------- |
177 static void writeObjects (const QList<LDObject*>& objects, str fname) |
190 static void writeObjects (const QList<LDObject*>& objects, str fname) |
178 { // Write the input file |
191 { |
|
192 // Write the input file |
179 File f (fname, File::Write); |
193 File f (fname, File::Write); |
180 |
194 |
181 if (!f) |
195 if (!f) |
182 { critical (fmt ("Couldn't open temporary file %1 for writing.\n", fname)); |
196 { |
|
197 critical (fmt ("Couldn't open temporary file %1 for writing.\n", fname)); |
183 return; |
198 return; |
184 } |
199 } |
185 |
200 |
186 writeObjects (objects, f); |
201 writeObjects (objects, f); |
187 f.close(); |
202 f.close(); |
192 } |
207 } |
193 |
208 |
194 // ============================================================================= |
209 // ============================================================================= |
195 // ----------------------------------------------------------------------------- |
210 // ----------------------------------------------------------------------------- |
196 void writeSelection (str fname) |
211 void writeSelection (str fname) |
197 { writeObjects (selection(), fname); |
212 { |
|
213 writeObjects (selection(), fname); |
198 } |
214 } |
199 |
215 |
200 // ============================================================================= |
216 // ============================================================================= |
201 // ----------------------------------------------------------------------------- |
217 // ----------------------------------------------------------------------------- |
202 void writeColorGroup (const int colnum, str fname) |
218 void writeColorGroup (const int colnum, str fname) |
203 { QList<LDObject*> objects; |
219 { |
|
220 QList<LDObject*> objects; |
204 |
221 |
205 for (LDObject* obj : getCurrentDocument()->getObjects()) |
222 for (LDObject* obj : getCurrentDocument()->getObjects()) |
206 { if (obj->isColored() == false || obj->getColor() != colnum) |
223 { |
|
224 if (obj->isColored() == false || obj->getColor() != colnum) |
207 continue; |
225 continue; |
208 |
226 |
209 objects << obj; |
227 objects << obj; |
210 } |
228 } |
211 |
229 |
213 } |
231 } |
214 |
232 |
215 // ============================================================================= |
233 // ============================================================================= |
216 // ----------------------------------------------------------------------------- |
234 // ----------------------------------------------------------------------------- |
217 bool runUtilityProcess (extprog prog, str path, str argvstr) |
235 bool runUtilityProcess (extprog prog, str path, str argvstr) |
218 { QTemporaryFile input, output; |
236 { |
|
237 QTemporaryFile input, output; |
219 str inputname, outputname; |
238 str inputname, outputname; |
220 QStringList argv = argvstr.split (" ", QString::SkipEmptyParts); |
239 QStringList argv = argvstr.split (" ", QString::SkipEmptyParts); |
221 |
240 |
222 #ifndef _WIN32 |
241 #ifndef _WIN32 |
223 if (*g_extProgWine[prog]) |
242 if (*g_extProgWine[prog]) |
224 { argv.insert (0, path); |
243 { |
|
244 argv.insert (0, path); |
225 path = "wine"; |
245 path = "wine"; |
226 } |
246 } |
227 #endif // _WIN32 |
247 #endif // _WIN32 |
228 |
248 |
229 log ("cmdline: %1 %2\n", path, argv.join (" ")); |
249 log ("cmdline: %1 %2\n", path, argv.join (" ")); |
240 // Begin! |
260 // Begin! |
241 proc.setStandardInputFile (inputname); |
261 proc.setStandardInputFile (inputname); |
242 proc.start (path, argv); |
262 proc.start (path, argv); |
243 |
263 |
244 if (!proc.waitForStarted()) |
264 if (!proc.waitForStarted()) |
245 { critical (fmt ("Couldn't start %1: %2\n", g_extProgNames[prog], processErrorString (prog, proc))); |
265 { |
|
266 critical (fmt ("Couldn't start %1: %2\n", g_extProgNames[prog], processErrorString (prog, proc))); |
246 return false; |
267 return false; |
247 } |
268 } |
248 |
269 |
249 // Write an enter, the utility tools all expect one |
270 // Write an enter, the utility tools all expect one |
250 stdinfp.write ("\n"); |
271 stdinfp.write ("\n"); |
260 // Check the return code |
281 // Check the return code |
261 if (proc.exitCode() != 0) |
282 if (proc.exitCode() != 0) |
262 err = fmt ("Program exited abnormally (return code %1).", proc.exitCode()); |
283 err = fmt ("Program exited abnormally (return code %1).", proc.exitCode()); |
263 |
284 |
264 if (!err.isEmpty()) |
285 if (!err.isEmpty()) |
265 { critical (fmt ("%1 failed: %2\n", g_extProgNames[prog], err)); |
286 { |
|
287 critical (fmt ("%1 failed: %2\n", g_extProgNames[prog], err)); |
266 return false; |
288 return false; |
267 } |
289 } |
268 |
290 |
269 return true; |
291 return true; |
270 } |
292 } |
279 |
301 |
280 // Read the output file |
302 // Read the output file |
281 File f (fname, File::Read); |
303 File f (fname, File::Read); |
282 |
304 |
283 if (!f) |
305 if (!f) |
284 { critical (fmt ("Couldn't open temporary file %1 for reading.\n", fname)); |
306 { |
|
307 critical (fmt ("Couldn't open temporary file %1 for reading.\n", fname)); |
285 return; |
308 return; |
286 } |
309 } |
287 |
310 |
288 QList<LDObject*> objs = loadFileContents (&f, null); |
311 QList<LDObject*> objs = loadFileContents (&f, null); |
289 |
312 |
312 |
337 |
313 // ============================================================================= |
338 // ============================================================================= |
314 // Interface for Ytruder |
339 // Interface for Ytruder |
315 // ----------------------------------------------------------------------------- |
340 // ----------------------------------------------------------------------------- |
316 DEFINE_ACTION (Ytruder, 0) |
341 DEFINE_ACTION (Ytruder, 0) |
317 { setlocale (LC_ALL, "C"); |
342 { |
|
343 setlocale (LC_ALL, "C"); |
318 |
344 |
319 if (!checkProgPath (Ytruder)) |
345 if (!checkProgPath (Ytruder)) |
320 return; |
346 return; |
321 |
347 |
322 QDialog* dlg = new QDialog; |
348 QDialog* dlg = new QDialog; |
346 if (!mkTempFile (indat, inDATName) || !mkTempFile (outdat, outDATName)) |
372 if (!mkTempFile (indat, inDATName) || !mkTempFile (outdat, outDATName)) |
347 return; |
373 return; |
348 |
374 |
349 // Compose the command-line arguments |
375 // Compose the command-line arguments |
350 str argv = join ( |
376 str argv = join ( |
351 { (axis == X) ? "-x" : (axis == Y) ? "-y" : "-z", |
377 { |
|
378 (axis == X) ? "-x" : (axis == Y) ? "-y" : "-z", |
352 (mode == Distance) ? "-d" : (mode == Symmetry) ? "-s" : (mode == Projection) ? "-p" : "-r", |
379 (mode == Distance) ? "-d" : (mode == Symmetry) ? "-s" : (mode == Projection) ? "-p" : "-r", |
353 depth, |
380 depth, |
354 "-a", |
381 "-a", |
355 condAngle, |
382 condAngle, |
356 inDATName, |
383 inDATName, |
367 |
394 |
368 // ============================================================================= |
395 // ============================================================================= |
369 // Rectifier interface |
396 // Rectifier interface |
370 // ----------------------------------------------------------------------------- |
397 // ----------------------------------------------------------------------------- |
371 DEFINE_ACTION (Rectifier, 0) |
398 DEFINE_ACTION (Rectifier, 0) |
372 { setlocale (LC_ALL, "C"); |
399 { |
|
400 setlocale (LC_ALL, "C"); |
373 |
401 |
374 if (!checkProgPath (Rectifier)) |
402 if (!checkProgPath (Rectifier)) |
375 return; |
403 return; |
376 |
404 |
377 QDialog* dlg = new QDialog; |
405 QDialog* dlg = new QDialog; |
388 if (!mkTempFile (indat, inDATName) || !mkTempFile (outdat, outDATName)) |
416 if (!mkTempFile (indat, inDATName) || !mkTempFile (outdat, outDATName)) |
389 return; |
417 return; |
390 |
418 |
391 // Compose arguments |
419 // Compose arguments |
392 str argv = join ( |
420 str argv = join ( |
393 { (!ui.cb_condense->isChecked()) ? "-q" : "", |
421 { |
|
422 (!ui.cb_condense->isChecked()) ? "-q" : "", |
394 (!ui.cb_subst->isChecked()) ? "-r" : "", |
423 (!ui.cb_subst->isChecked()) ? "-r" : "", |
395 (ui.cb_condlineCheck->isChecked()) ? "-a" : "", |
424 (ui.cb_condlineCheck->isChecked()) ? "-a" : "", |
396 (ui.cb_colorize->isChecked()) ? "-c" : "", |
425 (ui.cb_colorize->isChecked()) ? "-c" : "", |
397 "-t", |
426 "-t", |
398 ui.dsb_coplthres->value(), |
427 ui.dsb_coplthres->value(), |
410 |
439 |
411 // ============================================================================= |
440 // ============================================================================= |
412 // Intersector interface |
441 // Intersector interface |
413 // ----------------------------------------------------------------------------- |
442 // ----------------------------------------------------------------------------- |
414 DEFINE_ACTION (Intersector, 0) |
443 DEFINE_ACTION (Intersector, 0) |
415 { setlocale (LC_ALL, "C"); |
444 { |
|
445 setlocale (LC_ALL, "C"); |
416 |
446 |
417 if (!checkProgPath (Intersector)) |
447 if (!checkProgPath (Intersector)) |
418 return; |
448 return; |
419 |
449 |
420 QDialog* dlg = new QDialog; |
450 QDialog* dlg = new QDialog; |
455 str inDATName, cutDATName, outDATName, outDAT2Name, edgesDATName; |
487 str inDATName, cutDATName, outDATName, outDAT2Name, edgesDATName; |
456 |
488 |
457 if (!mkTempFile (indat, inDATName) || !mkTempFile (cutdat, cutDATName) || |
489 if (!mkTempFile (indat, inDATName) || !mkTempFile (cutdat, cutDATName) || |
458 !mkTempFile (outdat, outDATName) || !mkTempFile (outdat2, outDAT2Name) || |
490 !mkTempFile (outdat, outDATName) || !mkTempFile (outdat2, outDAT2Name) || |
459 !mkTempFile (edgesdat, edgesDATName)) |
491 !mkTempFile (edgesdat, edgesDATName)) |
460 { return; |
492 { |
|
493 return; |
461 } |
494 } |
462 |
495 |
463 str parms = join ( |
496 str parms = join ( |
464 { (ui.cb_colorize->isChecked()) ? "-c" : "", |
497 { |
|
498 (ui.cb_colorize->isChecked()) ? "-c" : "", |
465 (ui.cb_nocondense->isChecked()) ? "-t" : "", |
499 (ui.cb_nocondense->isChecked()) ? "-t" : "", |
466 "-s", |
500 "-s", |
467 ui.dsb_prescale->value() |
501 ui.dsb_prescale->value() |
468 }); |
502 }); |
469 |
503 |
470 str argv_normal = join ( |
504 str argv_normal = join ( |
471 { parms, |
505 { |
|
506 parms, |
472 inDATName, |
507 inDATName, |
473 cutDATName, |
508 cutDATName, |
474 outDATName |
509 outDATName |
475 }); |
510 }); |
476 |
511 |
477 str argv_inverse = join ( |
512 str argv_inverse = join ( |
478 { parms, |
513 { |
|
514 parms, |
479 cutDATName, |
515 cutDATName, |
480 inDATName, |
516 inDATName, |
481 outDAT2Name |
517 outDAT2Name |
482 }); |
518 }); |
483 |
519 |
501 } |
537 } |
502 |
538 |
503 // ============================================================================= |
539 // ============================================================================= |
504 // ----------------------------------------------------------------------------- |
540 // ----------------------------------------------------------------------------- |
505 DEFINE_ACTION (Coverer, 0) |
541 DEFINE_ACTION (Coverer, 0) |
506 { setlocale (LC_ALL, "C"); |
542 { |
|
543 setlocale (LC_ALL, "C"); |
507 |
544 |
508 if (!checkProgPath (Coverer)) |
545 if (!checkProgPath (Coverer)) |
509 return; |
546 return; |
510 |
547 |
511 QDialog* dlg = new QDialog; |
548 QDialog* dlg = new QDialog; |
515 makeColorComboBox (ui.cmb_col2); |
552 makeColorComboBox (ui.cmb_col2); |
516 |
553 |
517 int in1Col, in2Col; |
554 int in1Col, in2Col; |
518 |
555 |
519 forever |
556 forever |
520 { if (!dlg->exec()) |
557 { |
|
558 if (!dlg->exec()) |
521 return; |
559 return; |
522 |
560 |
523 in1Col = ui.cmb_col1->itemData (ui.cmb_col1->currentIndex()).toInt(); |
561 in1Col = ui.cmb_col1->itemData (ui.cmb_col1->currentIndex()).toInt(); |
524 in2Col = ui.cmb_col2->itemData (ui.cmb_col2->currentIndex()).toInt(); |
562 in2Col = ui.cmb_col2->itemData (ui.cmb_col2->currentIndex()).toInt(); |
525 |
563 |
526 if (in1Col == in2Col) |
564 if (in1Col == in2Col) |
527 { critical ("Cannot use the same color group for both input and cutter!"); |
565 { |
|
566 critical ("Cannot use the same color group for both input and cutter!"); |
528 continue; |
567 continue; |
529 } |
568 } |
530 |
569 |
531 break; |
570 break; |
532 } |
571 } |
536 |
575 |
537 if (!mkTempFile (in1dat, in1DATName) || !mkTempFile (in2dat, in2DATName) || !mkTempFile (outdat, outDATName)) |
576 if (!mkTempFile (in1dat, in1DATName) || !mkTempFile (in2dat, in2DATName) || !mkTempFile (outdat, outDATName)) |
538 return; |
577 return; |
539 |
578 |
540 str argv = join ( |
579 str argv = join ( |
541 { (ui.cb_oldsweep->isChecked() ? "-s" : ""), |
580 { |
|
581 (ui.cb_oldsweep->isChecked() ? "-s" : ""), |
542 (ui.cb_reverse->isChecked() ? "-r" : ""), |
582 (ui.cb_reverse->isChecked() ? "-r" : ""), |
543 (ui.dsb_segsplit->value() != 0 ? fmt ("-l %1", ui.dsb_segsplit->value()) : ""), |
583 (ui.dsb_segsplit->value() != 0 ? fmt ("-l %1", ui.dsb_segsplit->value()) : ""), |
544 (ui.sb_bias->value() != 0 ? fmt ("-s %1", ui.sb_bias->value()) : ""), |
584 (ui.sb_bias->value() != 0 ? fmt ("-s %1", ui.sb_bias->value()) : ""), |
545 in1DATName, |
585 in1DATName, |
546 in2DATName, |
586 in2DATName, |
557 } |
597 } |
558 |
598 |
559 // ============================================================================= |
599 // ============================================================================= |
560 // ----------------------------------------------------------------------------- |
600 // ----------------------------------------------------------------------------- |
561 DEFINE_ACTION (Isecalc, 0) |
601 DEFINE_ACTION (Isecalc, 0) |
562 { setlocale (LC_ALL, "C"); |
602 { |
|
603 setlocale (LC_ALL, "C"); |
563 |
604 |
564 if (!checkProgPath (Isecalc)) |
605 if (!checkProgPath (Isecalc)) |
565 return; |
606 return; |
566 |
607 |
567 Ui::IsecalcUI ui; |
608 Ui::IsecalcUI ui; |
573 |
614 |
574 int in1Col, in2Col; |
615 int in1Col, in2Col; |
575 |
616 |
576 // Run the dialog and validate input |
617 // Run the dialog and validate input |
577 forever |
618 forever |
578 { if (!dlg->exec()) |
619 { |
|
620 if (!dlg->exec()) |
579 return; |
621 return; |
580 |
622 |
581 in1Col = ui.cmb_col1->itemData (ui.cmb_col1->currentIndex()).toInt(), |
623 in1Col = ui.cmb_col1->itemData (ui.cmb_col1->currentIndex()).toInt(), |
582 in2Col = ui.cmb_col1->itemData (ui.cmb_col2->currentIndex()).toInt(); |
624 in2Col = ui.cmb_col1->itemData (ui.cmb_col2->currentIndex()).toInt(); |
583 |
625 |
584 if (in1Col == in2Col) |
626 if (in1Col == in2Col) |
585 { critical ("Cannot use the same color group for both input and cutter!"); |
627 { |
|
628 critical ("Cannot use the same color group for both input and cutter!"); |
586 continue; |
629 continue; |
587 } |
630 } |
588 |
631 |
589 break; |
632 break; |
590 } |
633 } |
608 } |
652 } |
609 |
653 |
610 // ============================================================================= |
654 // ============================================================================= |
611 // ----------------------------------------------------------------------------- |
655 // ----------------------------------------------------------------------------- |
612 DEFINE_ACTION (Edger2, 0) |
656 DEFINE_ACTION (Edger2, 0) |
613 { setlocale (LC_ALL, "C"); |
657 { |
|
658 setlocale (LC_ALL, "C"); |
614 |
659 |
615 if (!checkProgPath (Edger2)) |
660 if (!checkProgPath (Edger2)) |
616 return; |
661 return; |
617 |
662 |
618 QDialog* dlg = new QDialog; |
663 QDialog* dlg = new QDialog; |
629 return; |
674 return; |
630 |
675 |
631 int unmatched = ui.unmatched->currentIndex(); |
676 int unmatched = ui.unmatched->currentIndex(); |
632 |
677 |
633 str argv = join ( |
678 str argv = join ( |
634 { fmt ("-p %1", ui.precision->value()), |
679 { |
|
680 fmt ("-p %1", ui.precision->value()), |
635 fmt ("-af %1", ui.flatAngle->value()), |
681 fmt ("-af %1", ui.flatAngle->value()), |
636 fmt ("-ac %1", ui.condAngle->value()), |
682 fmt ("-ac %1", ui.condAngle->value()), |
637 fmt ("-ae %1", ui.edgeAngle->value()), |
683 fmt ("-ae %1", ui.edgeAngle->value()), |
638 ui.delLines->isChecked() ? "-de" : "", |
684 ui.delLines->isChecked() ? "-de" : "", |
639 ui.delCondLines->isChecked() ? "-dc" : "", |
685 ui.delCondLines->isChecked() ? "-dc" : "", |