src/actions.cpp

changeset 931
85080f7a1c20
parent 929
66e8453e1768
child 941
f895379d7fab
equal deleted inserted replaced
929:66e8453e1768 931:85080f7a1c20
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2015 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <QFileDialog>
20 #include <QMessageBox>
21 #include <QTextEdit>
22 #include <QBoxLayout>
23 #include <QDialogButtonBox>
24 #include <QPushButton>
25 #include <QInputDialog>
26
27 #include "mainWindow.h"
28 #include "ldDocument.h"
29 #include "editHistory.h"
30 #include "configDialog.h"
31 #include "addObjectDialog.h"
32 #include "miscallenous.h"
33 #include "glRenderer.h"
34 #include "dialogs.h"
35 #include "primitives.h"
36 #include "radioGroup.h"
37 #include "colors.h"
38 #include "glCompiler.h"
39 #include "ui_newpart.h"
40 #include "editmodes/abstractEditMode.h"
41
42 EXTERN_CFGENTRY (Bool, DrawWireframe)
43 EXTERN_CFGENTRY (Bool, BFCRedGreenView)
44 EXTERN_CFGENTRY (String, DefaultName)
45 EXTERN_CFGENTRY (String, DefaultUser)
46 EXTERN_CFGENTRY (Bool, UseCALicense)
47 EXTERN_CFGENTRY (Bool, DrawAngles)
48 EXTERN_CFGENTRY (Bool, RandomColors)
49 EXTERN_CFGENTRY (Bool, DrawSurfaces)
50 EXTERN_CFGENTRY (Bool, DrawEdgeLines)
51 EXTERN_CFGENTRY (Bool, DrawConditionalLines)
52 EXTERN_CFGENTRY (Bool, DrawAxes)
53
54 // =============================================================================
55 //
56 void MainWindow::actionNew()
57 {
58 QDialog* dlg = new QDialog (g_win);
59 Ui::NewPartUI ui;
60 ui.setupUi (dlg);
61
62 QString authortext = cfg::DefaultName;
63
64 if (not cfg::DefaultUser.isEmpty())
65 authortext.append (format (" [%1]", cfg::DefaultUser));
66
67 ui.le_author->setText (authortext);
68 ui.caLicense->setChecked (cfg::UseCALicense);
69
70 if (dlg->exec() == QDialog::Rejected)
71 return;
72
73 newFile();
74
75 BFCStatement const bfctype = ui.rb_bfc_ccw->isChecked() ? BFCStatement::CertifyCCW
76 : ui.rb_bfc_cw->isChecked() ? BFCStatement::CertifyCW
77 : BFCStatement::NoCertify;
78 QString const license = ui.caLicense->isChecked() ? CALicenseText : "";
79
80 LDObjectList objs;
81 objs << LDSpawn<LDComment> (ui.le_title->text());
82 objs << LDSpawn<LDComment> ("Name: <untitled>.dat");
83 objs << LDSpawn<LDComment> (format ("Author: %1", ui.le_author->text()));
84 objs << LDSpawn<LDComment> (format ("!LDRAW_ORG Unofficial_Part"));
85
86 if (not license.isEmpty())
87 objs << LDSpawn<LDComment> (license);
88
89 objs << LDSpawn<LDEmpty>();
90 objs << LDSpawn<LDBFC> (bfctype);
91 objs << LDSpawn<LDEmpty>();
92 CurrentDocument()->addObjects (objs);
93 doFullRefresh();
94 }
95
96 // =============================================================================
97 //
98 void MainWindow::actionNewFile()
99 {
100 newFile();
101 }
102
103 // =============================================================================
104 //
105 void MainWindow::actionOpen()
106 {
107 QString name = QFileDialog::getOpenFileName (g_win, "Open File", "", "LDraw files (*.dat *.ldr)");
108
109 if (name.isEmpty())
110 return;
111
112 OpenMainModel (name);
113 }
114
115 // =============================================================================
116 //
117 void MainWindow::actionSave()
118 {
119 save (CurrentDocument(), false);
120 }
121
122 // =============================================================================
123 //
124 void MainWindow::actionSaveAs()
125 {
126 save (CurrentDocument(), true);
127 }
128
129 // =============================================================================
130 //
131 void MainWindow::actionSaveAll()
132 {
133 for (LDDocumentPtr file : LDDocument::explicitDocuments())
134 save (file, false);
135 }
136
137 // =============================================================================
138 //
139 void MainWindow::actionClose()
140 {
141 if (not CurrentDocument()->isSafeToClose())
142 return;
143
144 CurrentDocument()->dismiss();
145 }
146
147 // =============================================================================
148 //
149 void MainWindow::actionCloseAll()
150 {
151 if (not IsSafeToCloseAll())
152 return;
153
154 CloseAllDocuments();
155 }
156
157 // =============================================================================
158 //
159 void MainWindow::actionSettings()
160 {
161 (new ConfigDialog)->exec();
162 }
163
164 // =============================================================================
165 //
166 void MainWindow::actionSetLDrawPath()
167 {
168 (new LDrawPathDialog (true))->exec();
169 }
170
171 // =============================================================================
172 //
173 void MainWindow::actionExit()
174 {
175 Exit();
176 }
177
178 // =============================================================================
179 //
180 void MainWindow::actionNewSubfile()
181 {
182 AddObjectDialog::staticDialog (OBJ_Subfile, LDObjectPtr());
183 }
184
185 // =============================================================================
186 //
187 void MainWindow::actionNewLine()
188 {
189 AddObjectDialog::staticDialog (OBJ_Line, LDObjectPtr());
190 }
191
192 // =============================================================================
193 //
194 void MainWindow::actionNewTriangle()
195 {
196 AddObjectDialog::staticDialog (OBJ_Triangle, LDObjectPtr());
197 }
198
199 // =============================================================================
200 //
201 void MainWindow::actionNewQuad()
202 {
203 AddObjectDialog::staticDialog (OBJ_Quad, LDObjectPtr());
204 }
205
206 // =============================================================================
207 //
208 void MainWindow::actionNewCLine()
209 {
210 AddObjectDialog::staticDialog (OBJ_CondLine, LDObjectPtr());
211 }
212
213 // =============================================================================
214 //
215 void MainWindow::actionNewComment()
216 {
217 AddObjectDialog::staticDialog (OBJ_Comment, LDObjectPtr());
218 }
219
220 // =============================================================================
221 //
222 void MainWindow::actionNewBFC()
223 {
224 AddObjectDialog::staticDialog (OBJ_BFC, LDObjectPtr());
225 }
226
227 // =============================================================================
228 //
229 void MainWindow::actionEdit()
230 {
231 if (Selection().size() != 1)
232 return;
233
234 LDObjectPtr obj = Selection() [0];
235 AddObjectDialog::staticDialog (obj->type(), obj);
236 }
237
238 // =============================================================================
239 //
240 void MainWindow::actionHelp()
241 {
242 }
243
244 // =============================================================================
245 //
246 void MainWindow::actionAbout()
247 {
248 AboutDialog().exec();
249 }
250
251 // =============================================================================
252 //
253 void MainWindow::actionAboutQt()
254 {
255 QMessageBox::aboutQt (g_win);
256 }
257
258 // =============================================================================
259 //
260 void MainWindow::actionSelectAll()
261 {
262 for (LDObjectPtr obj : CurrentDocument()->objects())
263 obj->select();
264 }
265
266 // =============================================================================
267 //
268 void MainWindow::actionSelectByColor()
269 {
270 if (Selection().isEmpty())
271 return;
272
273 QList<LDColor> colors;
274
275 for (LDObjectPtr obj : Selection())
276 {
277 if (obj->isColored())
278 colors << obj->color();
279 }
280
281 RemoveDuplicates (colors);
282 CurrentDocument()->clearSelection();
283
284 for (LDObjectPtr obj : CurrentDocument()->objects())
285 {
286 if (colors.contains (obj->color()))
287 obj->select();
288 }
289 }
290
291 // =============================================================================
292 //
293 void MainWindow::actionSelectByType()
294 {
295 if (Selection().isEmpty())
296 return;
297
298 QList<LDObjectType> types;
299 QStringList subfilenames;
300
301 for (LDObjectPtr obj : Selection())
302 {
303 types << obj->type();
304
305 if (types.last() == OBJ_Subfile)
306 subfilenames << obj.staticCast<LDSubfile>()->fileInfo()->name();
307 }
308
309 RemoveDuplicates (types);
310 RemoveDuplicates (subfilenames);
311 CurrentDocument()->clearSelection();
312
313 for (LDObjectPtr obj : CurrentDocument()->objects())
314 {
315 LDObjectType type = obj->type();
316
317 if (not types.contains (type))
318 continue;
319
320 // For subfiles, type check is not enough, we check the name of the document as well.
321 if (type == OBJ_Subfile and not subfilenames.contains (obj.staticCast<LDSubfile>()->fileInfo()->name()))
322 continue;
323
324 obj->select();
325 }
326 }
327
328 // =============================================================================
329 //
330 void MainWindow::actionGridCoarse()
331 {
332 cfg::Grid = Grid::Coarse;
333 updateGridToolBar();
334 }
335
336 void MainWindow::actionGridMedium()
337 {
338 cfg::Grid = Grid::Medium;
339 updateGridToolBar();
340 }
341
342 void MainWindow::actionGridFine()
343 {
344 cfg::Grid = Grid::Fine;
345 updateGridToolBar();
346 }
347
348 // =============================================================================
349 //
350 void MainWindow::actionResetView()
351 {
352 R()->resetAngles();
353 R()->update();
354 }
355
356 // =============================================================================
357 //
358 void MainWindow::actionInsertFrom()
359 {
360 QString fname = QFileDialog::getOpenFileName();
361 int idx = getInsertionPoint();
362
363 if (not fname.length())
364 return;
365
366 QFile f (fname);
367
368 if (not f.open (QIODevice::ReadOnly))
369 {
370 Critical (format ("Couldn't open %1 (%2)", fname, f.errorString()));
371 return;
372 }
373
374 LDObjectList objs = LoadFileContents (&f, null);
375
376 CurrentDocument()->clearSelection();
377
378 for (LDObjectPtr obj : objs)
379 {
380 CurrentDocument()->insertObj (idx, obj);
381 obj->select();
382 R()->compileObject (obj);
383
384 idx++;
385 }
386
387 refresh();
388 scrollToSelection();
389 }
390
391 // =============================================================================
392 //
393 void MainWindow::actionExportTo()
394 {
395 if (Selection().isEmpty())
396 return;
397
398 QString fname = QFileDialog::getSaveFileName();
399
400 if (fname.length() == 0)
401 return;
402
403 QFile file (fname);
404
405 if (not file.open (QIODevice::WriteOnly | QIODevice::Text))
406 {
407 Critical (format ("Unable to open %1 for writing (%2)", fname, file.errorString()));
408 return;
409 }
410
411 for (LDObjectPtr obj : Selection())
412 {
413 QString contents = obj->asText();
414 QByteArray data = contents.toUtf8();
415 file.write (data, data.size());
416 file.write ("\r\n", 2);
417 }
418 }
419
420 // =============================================================================
421 //
422 void MainWindow::actionInsertRaw()
423 {
424 int idx = getInsertionPoint();
425
426 QDialog* const dlg = new QDialog;
427 QVBoxLayout* const layout = new QVBoxLayout;
428 QTextEdit* const te_edit = new QTextEdit;
429 QDialogButtonBox* const bbx_buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
430
431 layout->addWidget (te_edit);
432 layout->addWidget (bbx_buttons);
433 dlg->setLayout (layout);
434 dlg->setWindowTitle (APPNAME " - Insert Raw");
435 dlg->connect (bbx_buttons, SIGNAL (accepted()), dlg, SLOT (accept()));
436 dlg->connect (bbx_buttons, SIGNAL (rejected()), dlg, SLOT (reject()));
437
438 if (dlg->exec() == QDialog::Rejected)
439 return;
440
441 CurrentDocument()->clearSelection();
442
443 for (QString line : QString (te_edit->toPlainText()).split ("\n"))
444 {
445 LDObjectPtr obj = ParseLine (line);
446
447 CurrentDocument()->insertObj (idx, obj);
448 obj->select();
449 idx++;
450 }
451
452 refresh();
453 scrollToSelection();
454 }
455
456 // =============================================================================
457 //
458 void MainWindow::actionScreenshot()
459 {
460 setlocale (LC_ALL, "C");
461
462 int w, h;
463 uchar* imgdata = R()->getScreencap (w, h);
464 QImage img = GetImageFromScreencap (imgdata, w, h);
465
466 QString root = Basename (CurrentDocument()->name());
467
468 if (root.right (4) == ".dat")
469 root.chop (4);
470
471 QString defaultname = (root.length() > 0) ? format ("%1.png", root) : "";
472 QString fname = QFileDialog::getSaveFileName (g_win, "Save Screencap", defaultname,
473 "PNG images (*.png);;JPG images (*.jpg);;BMP images (*.bmp);;All Files (*.*)");
474
475 if (not fname.isEmpty() and not img.save (fname))
476 Critical (format ("Couldn't open %1 for writing to save screencap: %2", fname, strerror (errno)));
477
478 delete[] imgdata;
479 }
480
481 // =============================================================================
482 //
483 void MainWindow::actionAxes()
484 {
485 cfg::DrawAxes = not cfg::DrawAxes;
486 updateActions();
487 R()->update();
488 }
489
490 // =============================================================================
491 //
492 void MainWindow::actionVisibilityToggle()
493 {
494 for (LDObjectPtr obj : Selection())
495 obj->setHidden (not obj->isHidden());
496
497 refresh();
498 }
499
500 // =============================================================================
501 //
502 void MainWindow::actionVisibilityHide()
503 {
504 for (LDObjectPtr obj : Selection())
505 obj->setHidden (true);
506
507 refresh();
508 }
509
510 // =============================================================================
511 //
512 void MainWindow::actionVisibilityReveal()
513 {
514 for (LDObjectPtr obj : Selection())
515 obj->setHidden (false);
516 refresh();
517 }
518
519 // =============================================================================
520 //
521 void MainWindow::actionWireframe()
522 {
523 cfg::DrawWireframe = not cfg::DrawWireframe;
524 R()->refresh();
525 }
526
527 // =============================================================================
528 //
529 void MainWindow::actionSetOverlay()
530 {
531 OverlayDialog dlg;
532
533 if (not dlg.exec())
534 return;
535
536 R()->setupOverlay ((ECamera) dlg.camera(), dlg.fpath(), dlg.ofsx(),
537 dlg.ofsy(), dlg.lwidth(), dlg.lheight());
538 }
539
540 // =============================================================================
541 //
542 void MainWindow::actionClearOverlay()
543 {
544 R()->clearOverlay();
545 }
546
547 // =============================================================================
548 //
549 void MainWindow::actionModeSelect()
550 {
551 R()->setEditMode (EditModeType::Select);
552 }
553
554 // =============================================================================
555 //
556 void MainWindow::actionModeDraw()
557 {
558 R()->setEditMode (EditModeType::Draw);
559 }
560
561 // =============================================================================
562 //
563 void MainWindow::actionModeRectangle()
564 {
565 R()->setEditMode (EditModeType::Rectangle);
566 }
567
568 // =============================================================================
569 //
570 void MainWindow::actionModeCircle()
571 {
572 R()->setEditMode (EditModeType::Circle);
573 }
574
575 // =============================================================================
576 //
577 void MainWindow::actionModeMagicWand()
578 {
579 R()->setEditMode (EditModeType::MagicWand);
580 }
581
582 void MainWindow::actionModeLinePath()
583 {
584 R()->setEditMode (EditModeType::LinePath);
585 }
586
587 // =============================================================================
588 //
589 void MainWindow::actionDrawAngles()
590 {
591 cfg::DrawAngles = not cfg::DrawAngles;
592 R()->refresh();
593 }
594
595 // =============================================================================
596 //
597 void MainWindow::actionSetDrawDepth()
598 {
599 if (R()->camera() == EFreeCamera)
600 return;
601
602 bool ok;
603 double depth = QInputDialog::getDouble (g_win, "Set Draw Depth",
604 format ("Depth value for %1 Camera:", R()->getCameraName()),
605 R()->getDepthValue(), -10000.0f, 10000.0f, 3, &ok);
606
607 if (ok)
608 R()->setDepthValue (depth);
609 }
610
611 #if 0
612 // This is a test to draw a dummy axle. Meant to be used as a primitive gallery,
613 // but I can't figure how to generate these pictures properly. Multi-threading
614 // these is an immense pain.
615 void MainWindow::actiontestpic()
616 {
617 LDDocumentPtr file = getFile ("axle.dat");
618 setlocale (LC_ALL, "C");
619
620 if (not file)
621 {
622 critical ("couldn't load axle.dat");
623 return;
624 }
625
626 int w, h;
627
628 GLRenderer* rend = new GLRenderer;
629 rend->resize (64, 64);
630 rend->setAttribute (Qt::WA_DontShowOnScreen);
631 rend->show();
632 rend->setFile (file);
633 rend->setDrawOnly (true);
634 rend->compileAllObjects();
635 rend->initGLData();
636 rend->drawGLScene();
637
638 uchar* imgdata = rend->screencap (w, h);
639 QImage img = imageFromScreencap (imgdata, w, h);
640
641 if (img.isNull())
642 {
643 critical ("Failed to create the image!\n");
644 }
645 else
646 {
647 QLabel* label = new QLabel;
648 QDialog* dlg = new QDialog;
649 label->setPixmap (QPixmap::fromImage (img));
650 QVBoxLayout* layout = new QVBoxLayout (dlg);
651 layout->addWidget (label);
652 dlg->exec();
653 }
654
655 delete[] imgdata;
656 rend->deleteLater();
657 }
658 #endif
659
660 // =============================================================================
661 //
662 void MainWindow::actionScanPrimitives()
663 {
664 PrimitiveScanner::start();
665 }
666
667 // =============================================================================
668 //
669 void MainWindow::actionBFCView()
670 {
671 cfg::BFCRedGreenView = not cfg::BFCRedGreenView;
672
673 if (cfg::BFCRedGreenView)
674 cfg::RandomColors = false;
675
676 updateActions();
677 R()->refresh();
678 }
679
680 // =============================================================================
681 //
682 void MainWindow::actionJumpTo()
683 {
684 bool ok;
685 int defval = 0;
686 LDObjectPtr obj;
687
688 if (Selection().size() == 1)
689 defval = Selection()[0]->lineNumber();
690
691 int idx = QInputDialog::getInt (null, "Go to line", "Go to line:", defval,
692 1, CurrentDocument()->getObjectCount(), 1, &ok);
693
694 if (not ok or (obj = CurrentDocument()->getObject (idx - 1)) == null)
695 return;
696
697 CurrentDocument()->clearSelection();
698 obj->select();
699 updateSelection();
700 }
701
702 // =============================================================================
703 //
704 void MainWindow::actionSubfileSelection()
705 {
706 if (Selection().size() == 0)
707 return;
708
709 QString parentpath (CurrentDocument()->fullPath());
710
711 // BFC type of the new subfile - it shall inherit the BFC type of the parent document
712 BFCStatement bfctype (BFCStatement::NoCertify);
713
714 // Dirname of the new subfile
715 QString subdirname (Dirname (parentpath));
716
717 // Title of the new subfile
718 QString subtitle;
719
720 // Comment containing the title of the parent document
721 LDCommentPtr titleobj (CurrentDocument()->getObject (0).dynamicCast<LDComment>());
722
723 // License text for the subfile
724 QString license (PreferredLicenseText());
725
726 // LDraw code body of the new subfile (i.e. code of the selection)
727 QStringList code;
728
729 // Full path of the subfile to be
730 QString fullsubname;
731
732 // Where to insert the subfile reference?
733 int refidx (Selection()[0]->lineNumber());
734
735 // Determine title of subfile
736 if (titleobj != null)
737 subtitle = "~" + titleobj->text();
738 else
739 subtitle = "~subfile";
740
741 // Remove duplicate tildes
742 while (subtitle.startsWith ("~~"))
743 subtitle.remove (0, 1);
744
745 // If this the parent document isn't already in s/, we need to stuff it into
746 // a subdirectory named s/. Ensure it exists!
747 QString topdirname = Basename (Dirname (CurrentDocument()->fullPath()));
748
749 if (topdirname != "s")
750 {
751 QString desiredPath = subdirname + "/s";
752 QString title = tr ("Create subfile directory?");
753 QString text = format (tr ("The directory <b>%1</b> is suggested for "
754 "subfiles. This directory does not exist, create it?"), desiredPath);
755
756 if (QDir (desiredPath).exists() or Confirm (title, text))
757 {
758 subdirname = desiredPath;
759 QDir().mkpath (subdirname);
760 }
761 else
762 return;
763 }
764
765 // Determine the body of the name of the subfile
766 if (not parentpath.isEmpty())
767 {
768 // Chop existing '.dat' suffix
769 if (parentpath.endsWith (".dat"))
770 parentpath.chop (4);
771
772 // Remove the s?? suffix if it's there, otherwise we'll get filenames
773 // like s01s01.dat when subfiling subfiles.
774 QRegExp subfilesuffix ("s[0-9][0-9]$");
775 if (subfilesuffix.indexIn (parentpath) != -1)
776 parentpath.chop (subfilesuffix.matchedLength());
777
778 int subidx = 1;
779 QString digits;
780 QFile f;
781 QString testfname;
782
783 // Now find the appropriate filename. Increase the number of the subfile
784 // until we find a name which isn't already taken.
785 do
786 {
787 digits.setNum (subidx++);
788
789 // pad it with a zero
790 if (digits.length() == 1)
791 digits.prepend ("0");
792
793 fullsubname = subdirname + "/" + Basename (parentpath) + "s" + digits + ".dat";
794 } while (FindDocument ("s\\" + Basename (fullsubname)) != null or QFile (fullsubname).exists());
795 }
796
797 // Determine the BFC winding type used in the main document - it is to
798 // be carried over to the subfile.
799 LDIterate<LDBFC> (CurrentDocument()->objects(), [&] (LDBFCPtr const& bfc)
800 {
801 if (Eq (bfc->statement(), BFCStatement::CertifyCCW, BFCStatement::CertifyCW,
802 BFCStatement::NoCertify))
803 {
804 bfctype = bfc->statement();
805 Break();
806 }
807 });
808
809 // Get the body of the document in LDraw code
810 for (LDObjectPtr obj : Selection())
811 code << obj->asText();
812
813 // Create the new subfile document
814 LDDocumentPtr doc = LDDocument::createNew();
815 doc->setImplicit (false);
816 doc->setFullPath (fullsubname);
817 doc->setName (LDDocument::shortenName (fullsubname));
818
819 LDObjectList objs;
820 objs << LDSpawn<LDComment> (subtitle);
821 objs << LDSpawn<LDComment> ("Name: "); // This gets filled in when the subfile is saved
822 objs << LDSpawn<LDComment> (format ("Author: %1 [%2]", cfg::DefaultName, cfg::DefaultUser));
823 objs << LDSpawn<LDComment> ("!LDRAW_ORG Unofficial_Subpart");
824
825 if (not license.isEmpty())
826 objs << LDSpawn<LDComment> (license);
827
828 objs << LDSpawn<LDEmpty>();
829 objs << LDSpawn<LDBFC> (bfctype);
830 objs << LDSpawn<LDEmpty>();
831
832 doc->addObjects (objs);
833
834 // Add the actual subfile code to the new document
835 for (QString line : code)
836 {
837 LDObjectPtr obj = ParseLine (line);
838 doc->addObject (obj);
839 }
840
841 // Try save it
842 if (save (doc, true))
843 {
844 // Save was successful. Delete the original selection now from the
845 // main document.
846 for (LDObjectPtr obj : Selection())
847 obj->destroy();
848
849 // Add a reference to the new subfile to where the selection was
850 LDSubfilePtr ref (LDSpawn<LDSubfile>());
851 ref->setColor (MainColor());
852 ref->setFileInfo (doc);
853 ref->setPosition (Origin);
854 ref->setTransform (IdentityMatrix);
855 CurrentDocument()->insertObj (refidx, ref);
856
857 // Refresh stuff
858 updateDocumentList();
859 doFullRefresh();
860 }
861 else
862 {
863 // Failed to save.
864 doc->dismiss();
865 }
866 }
867
868 void MainWindow::actionRandomColors()
869 {
870 cfg::RandomColors = not cfg::RandomColors;
871
872 if (cfg::RandomColors)
873 cfg::BFCRedGreenView = false;
874
875 updateActions();
876 R()->refresh();
877 }
878
879 void MainWindow::actionOpenSubfiles()
880 {
881 for (LDObjectPtr obj : Selection())
882 {
883 LDSubfilePtr ref = obj.dynamicCast<LDSubfile>();
884
885 if (ref == null or not ref->fileInfo()->isImplicit())
886 continue;
887
888 ref->fileInfo()->setImplicit (false);
889 }
890 }
891
892 void MainWindow::actionDrawSurfaces()
893 {
894 cfg::DrawSurfaces = not cfg::DrawSurfaces;
895 updateActions();
896 update();
897 }
898
899 void MainWindow::actionDrawEdgeLines()
900 {
901 cfg::DrawEdgeLines = not cfg::DrawEdgeLines;
902 updateActions();
903 update();
904 }
905
906 void MainWindow::actionDrawConditionalLines()
907 {
908 cfg::DrawConditionalLines = not cfg::DrawConditionalLines;
909 updateActions();
910 update();
911 }

mercurial