src/gui.cpp

changeset 382
c1642530ea35
parent 379
f5f3faac60cd
child 383
10e60ae9ed58
equal deleted inserted replaced
381:241f65769a57 382:c1642530ea35
45 #include "history.h" 45 #include "history.h"
46 #include "widgets.h" 46 #include "widgets.h"
47 #include "addObjectDialog.h" 47 #include "addObjectDialog.h"
48 #include "messagelog.h" 48 #include "messagelog.h"
49 #include "config.h" 49 #include "config.h"
50 50 #include "ui_ldforge.h"
51 actionmeta g_actionMeta[MAX_ACTIONS];
52 static ushort g_metacursor = 0;
53 51
54 static bool g_bSelectionLocked = false; 52 static bool g_bSelectionLocked = false;
55 53
56 cfg (bool, lv_colorize, true); 54 cfg (bool, lv_colorize, true);
57 cfg (int, gui_toolbar_iconsize, 24); 55 cfg (int, gui_toolbar_iconsize, 24);
69 }; 67 };
70 68
71 // ============================================================================= 69 // =============================================================================
72 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 70 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
73 // ============================================================================= 71 // =============================================================================
74 ForgeWindow::ForgeWindow () { 72 ForgeWindow::ForgeWindow() {
75 g_win = this; 73 g_win = this;
76 m_renderer = new GLRenderer; 74 m_renderer = new GLRenderer;
77 75
78 m_objList = new ObjectList; 76 ui = new Ui_LDForgeUI;
79 m_objList->setSelectionMode (QListWidget::ExtendedSelection); 77 ui->setupUi (this);
80 m_objList->setAlternatingRowColors (true); 78
81 connect (m_objList, SIGNAL (itemSelectionChanged ()), this, SLOT (slot_selectionChanged ())); 79 // Stuff the renderer into its frame
82 connect (m_objList, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (slot_editObject (QListWidgetItem*))); 80 QVBoxLayout* rendererLayout = new QVBoxLayout (ui->rendererFrame);
83 81 rendererLayout->addWidget (R());
82
83 connect (ui->objectList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_selectionChanged()));
84 connect (ui->objectList, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (slot_editObject (QListWidgetItem*)));
85
86 // Init message log manager
84 m_msglog = new MessageManager; 87 m_msglog = new MessageManager;
85 m_msglog->setRenderer( R() ); 88 m_msglog->setRenderer (R());
86 m_renderer->setMessageLog( m_msglog ); 89 m_renderer->setMessageLog (m_msglog);
87 90 m_colorMeta = parseQuickColorMeta();
88 m_splitter = new QSplitter; 91 slot_selectionChanged();
89 m_splitter->addWidget (m_renderer);
90 m_splitter->addWidget (m_objList);
91 setCentralWidget (m_splitter);
92
93 m_colorMeta = parseQuickColorMeta ();
94
95 createMenuActions ();
96 createMenus ();
97 createToolbars ();
98
99 slot_selectionChanged ();
100
101 setStatusBar (new QStatusBar); 92 setStatusBar (new QStatusBar);
102 93
94 // Init primitive loader task stuff
103 m_primLoaderBar = new QProgressBar; 95 m_primLoaderBar = new QProgressBar;
104 m_primLoaderWidget = new QWidget; 96 m_primLoaderWidget = new QWidget;
105 QHBoxLayout* primLoaderLayout = new QHBoxLayout (m_primLoaderWidget); 97 QHBoxLayout* primLoaderLayout = new QHBoxLayout (m_primLoaderWidget);
106 primLoaderLayout->addWidget (new QLabel ("Loading primitives:")); 98 primLoaderLayout->addWidget (new QLabel ("Loading primitives:"));
107 primLoaderLayout->addWidget (m_primLoaderBar); 99 primLoaderLayout->addWidget (m_primLoaderBar);
108 statusBar ()->addPermanentWidget (m_primLoaderWidget); 100 statusBar()->addPermanentWidget (m_primLoaderWidget);
109 m_primLoaderWidget->hide (); 101 m_primLoaderWidget->hide();
110 102
111 setWindowIcon (getIcon ("ldforge")); 103 // Make certain actions checkable
112 updateTitle (); 104 ui->actionAxes->setChecked (gl_axes);
113 setMinimumSize (320, 200); 105 ui->actionWireframe->setChecked (gl_wireframe);
114 resize (800, 600); 106 ui->actionBFCView->setChecked (gl_colorbfc);
115 107 updateGridToolBar();
116 connect (qApp, SIGNAL (aboutToQuit ()), this, SLOT (slot_lastSecondCleanup ())); 108 updateEditModeActions();
117 } 109 updateRecentFilesMenu();
118 110 updateToolBars();
119 // ============================================================================= 111 updateTitle();
120 void ForgeWindow::slot_lastSecondCleanup () { 112
113 setMinimumSize (300, 200);
114
115 connect (qApp, SIGNAL (aboutToQuit()), this, SLOT (slot_lastSecondCleanup()));
116
117 // Connect all actions
118 #define act(N) \
119 connect (ui->action##N, SIGNAL (triggered()), this, SLOT (slot_action()));
120 #include "actions.h"
121 }
122
123 void ForgeWindow::slot_action() {
124 // Find out which action triggered this
125 #define act(N) if (sender() == ui->action##N) invokeAction (ui->action##N, &actiondef_##N);
126 #include "actions.h"
127 }
128
129 void ForgeWindow::invokeAction (QAction* act, void (*func) ()) {
130 // Open the history so we can record the edits done during this action.
131 if (act != ACTION (Undo) && act != ACTION (Redo) && act != ACTION (Open))
132 currentFile()->openHistory();
133
134 // Invoke the function
135 (*func) ();
136
137 // Close the history now.
138 currentFile()->closeHistory();
139 }
140
141 // =============================================================================
142 void ForgeWindow::slot_lastSecondCleanup() {
121 delete m_renderer; 143 delete m_renderer;
122 } 144 delete ui;
123 145 }
124 // ============================================================================= 146
125 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 147 // =============================================================================
126 // ============================================================================= 148 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
127 void ForgeWindow::createMenuActions () { 149 // =============================================================================
128 // Create the actions based on stored meta. 150 void ForgeWindow::updateRecentFilesMenu() {
129 for (actionmeta meta : g_actionMeta) {
130 if (meta.qAct == null)
131 break;
132
133 QAction*& act = *meta.qAct;
134 act = new QAction (getIcon (meta.sIconName), meta.sDisplayName, this);
135 act->setStatusTip (meta.sDescription);
136 act->setShortcut (*meta.conf);
137
138 connect (act, SIGNAL (triggered ()), this, SLOT (slot_action ()));
139 }
140
141 // Make certain actions checkable
142 findAction ("gridCoarse")->setCheckable (true);
143 findAction ("gridMedium")->setCheckable (true);
144 findAction ("gridFine")->setCheckable (true);
145
146 findAction ("axes")->setCheckable (true);
147 findAction ("axes")->setChecked (gl_axes);
148
149 findAction ("wireframe")->setCheckable (true);
150 findAction ("wireframe")->setChecked (gl_wireframe);
151
152 findAction ("colorbfc")->setCheckable (true);
153 findAction ("colorbfc")->setChecked (gl_colorbfc);
154
155 updateEditModeActions ();
156
157 // things not implemented yet
158 findAction ("help")->setEnabled (false);
159 }
160
161 // =============================================================================
162 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
163 // =============================================================================
164 QMenu* g_CurrentMenu;
165
166 QMenu* ForgeWindow::initMenu (const char* name) {
167 return g_CurrentMenu = menuBar ()->addMenu (tr (name));
168 }
169
170 void ForgeWindow::addMenuAction (const char* name) {
171 g_CurrentMenu->addAction (findAction (name));
172 }
173
174
175 // =============================================================================
176 void ForgeWindow::createMenus () {
177 m_recentFilesMenu = new QMenu (tr ("Open &Recent"));
178 m_recentFilesMenu->setIcon (getIcon ("open-recent"));
179 updateRecentFilesMenu ();
180
181 QMenu*& menu = g_CurrentMenu;
182
183 // File menu
184 initMenu ("&File");
185 addMenuAction ("newFile");
186 addMenuAction ("open");
187 menu->addMenu (m_recentFilesMenu);
188 addMenuAction ("save");
189 addMenuAction ("saveAs");
190 menu->addSeparator ();
191 addMenuAction ("insertFrom");
192 addMenuAction ("exportTo");
193 menu->addSeparator ();
194 addMenuAction ("settings");
195 addMenuAction ("setLDrawPath");
196 menu->addSeparator ();
197 #ifndef RELEASE
198 addMenuAction ("testpic");
199 #endif
200 addMenuAction ("reloadPrimitives");
201 menu->addSeparator ();
202 addMenuAction ("exit");
203
204 // View menu
205 initMenu ("&View");
206 addMenuAction ("resetView");
207 addMenuAction ("axes");
208 addMenuAction ("wireframe");
209 addMenuAction ("colorbfc");
210 menu->addSeparator ();
211 addMenuAction ("setOverlay");
212 addMenuAction ("clearOverlay");
213 menu->addSeparator ();
214 addMenuAction ("screencap");
215
216 // Insert menu
217 initMenu ("&Insert");
218 addMenuAction ("insertRaw");
219 menu->addSeparator ();
220 addMenuAction ("newSubfile");
221 addMenuAction ("newLine");
222 addMenuAction ("newTriangle");
223 addMenuAction ("newQuad");
224 addMenuAction ("newCondLine");
225 addMenuAction ("newComment");
226 addMenuAction ("newBFC");
227 addMenuAction ("newVertex");
228
229 // Edit menu
230 initMenu ("&Edit");
231 addMenuAction ("undo");
232 addMenuAction ("redo");
233 menu->addSeparator ();
234 addMenuAction ("cut");
235 addMenuAction ("copy");
236 addMenuAction ("paste");
237 addMenuAction ("del");
238 menu->addSeparator ();
239 addMenuAction ("selectAll");
240 addMenuAction ("selectByColor");
241 addMenuAction ("selectByType");
242 menu->addSeparator ();
243 addMenuAction ("modeSelect");
244 addMenuAction ("modeDraw");
245 menu->addSeparator ();
246 addMenuAction ("setDrawDepth");
247
248 // Move menu
249 initMenu ("&Move");
250 addMenuAction ("moveUp");
251 addMenuAction ("moveDown");
252 menu->addSeparator ();
253 addMenuAction ("gridCoarse");
254 addMenuAction ("gridMedium");
255 addMenuAction ("gridFine");
256 menu->addSeparator ();
257 addMenuAction ("moveXPos");
258 addMenuAction ("moveXNeg");
259 addMenuAction ("moveYPos");
260 addMenuAction ("moveYNeg");
261 addMenuAction ("moveZPos");
262 addMenuAction ("moveZNeg");
263 menu->addSeparator ();
264 addMenuAction ("rotateXPos");
265 addMenuAction ("rotateXNeg");
266 addMenuAction ("rotateYPos");
267 addMenuAction ("rotateYNeg");
268 addMenuAction ("rotateZPos");
269 addMenuAction ("rotateZNeg");
270 addMenuAction ("rotpoint");
271
272 initMenu ("&Tools");
273 addMenuAction ("setColor");
274 addMenuAction ("autoColor");
275 addMenuAction ("uncolorize");
276 menu->addSeparator ();
277 addMenuAction ("invert");
278 addMenuAction ("inlineContents");
279 addMenuAction ("deepInline");
280 addMenuAction ("makePrimitive");
281 menu->addSeparator ();
282 addMenuAction ("splitQuads");
283 addMenuAction ("setContents");
284 addMenuAction ("makeBorders");
285 addMenuAction ("makeCornerVerts");
286 addMenuAction ("roundCoords");
287 addMenuAction ("visibility");
288 addMenuAction ("replaceCoords");
289 addMenuAction ("flip");
290 addMenuAction ("demote");
291
292 initMenu ("E&xternal Programs");
293 addMenuAction ("ytruder");
294 addMenuAction ("rectifier");
295 addMenuAction ("intersector");
296 addMenuAction ("isecalc");
297 addMenuAction ("coverer");
298 addMenuAction ("edger2");
299
300 // Help menu
301 initMenu ("&Help");
302 addMenuAction ("help");
303 menu->addSeparator ();
304 addMenuAction ("about");
305 addMenuAction ("aboutQt");
306 }
307
308 // =============================================================================
309 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
310 // =============================================================================
311 void ForgeWindow::updateRecentFilesMenu () {
312 // First, clear any items in the recent files menu 151 // First, clear any items in the recent files menu
313 for (QAction* recent : m_recentFiles) 152 for (QAction* recent : m_recentFiles)
314 delete recent; 153 delete recent;
315 m_recentFiles.clear (); 154 m_recentFiles.clear();
316 155
317 vector<str> files = container_cast<QStringList, vector<str>> (io_recentfiles.value.split ("@")); 156 vector<str> files = container_cast<QStringList, vector<str>> (io_recentfiles.value.split ("@"));
318 for (str file : c_rev<str> (files)) { 157 for (str file : c_rev<str> (files)) {
319 QAction* recent = new QAction (getIcon ("open-recent"), file, this); 158 QAction* recent = new QAction (getIcon ("open-recent"), file, this);
320 159
321 connect (recent, SIGNAL (triggered ()), this, SLOT (slot_recentFile ())); 160 connect (recent, SIGNAL (triggered()), this, SLOT (slot_recentFile()));
322 m_recentFilesMenu->addAction (recent); 161 ui->menuOpenRecent->addAction (recent);
323 m_recentFiles << recent; 162 m_recentFiles << recent;
324 } 163 }
325 } 164 }
326 165
327 // ============================================================================= 166 // =============================================================================
328 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 167 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
329 // ============================================================================= 168 // =============================================================================
330 static QToolBar* g_CurrentToolBar; 169 vector<quickColor> parseQuickColorMeta() {
331 static Qt::ToolBarArea g_ToolBarArea = Qt::TopToolBarArea;
332
333 void ForgeWindow::initSingleToolBar (const char* name) {
334 QToolBar* toolbar = new QToolBar (name);
335 addToolBar (g_ToolBarArea, toolbar);
336 m_toolBars << toolbar;
337
338 g_CurrentToolBar = toolbar;
339 }
340
341 // =============================================================================
342 void ForgeWindow::addToolBarAction (const char* name) {
343 g_CurrentToolBar->addAction (findAction (name));
344 }
345
346 // =============================================================================
347 void ForgeWindow::createToolbars () {
348 initSingleToolBar ("File");
349 addToolBarAction ("newFile");
350 addToolBarAction ("open");
351 addToolBarAction ("save");
352 addToolBarAction ("saveAs");
353
354 // ==========================================
355 initSingleToolBar ("Insert");
356 addToolBarAction ("newSubfile");
357 addToolBarAction ("newLine");
358 addToolBarAction ("newTriangle");
359 addToolBarAction ("newQuad");
360 addToolBarAction ("newCondLine");
361 addToolBarAction ("newComment");
362 addToolBarAction ("newBFC");
363 addToolBarAction ("newVertex");
364
365 // ==========================================
366 initSingleToolBar ("Edit");
367 addToolBarAction ("undo");
368 addToolBarAction ("redo");
369 addToolBarAction ("cut");
370 addToolBarAction ("copy");
371 addToolBarAction ("paste");
372 addToolBarAction ("del");
373 addToolBarBreak (Qt::TopToolBarArea);
374
375 // ==========================================
376 initSingleToolBar ("Select");
377 addToolBarAction ("selectAll");
378 addToolBarAction ("selectByColor");
379 addToolBarAction ("selectByType");
380
381 // ==========================================
382 initSingleToolBar ("Grids");
383 addToolBarAction ("gridCoarse");
384 addToolBarAction ("gridMedium");
385 addToolBarAction ("gridFine");
386
387 // ==========================================
388 initSingleToolBar ("View");
389 addToolBarAction ("axes");
390 addToolBarAction ("wireframe");
391 addToolBarAction ("colorbfc");
392
393 // ==========================================
394 // Color toolbar
395 m_colorToolBar = new QToolBar ("Quick Colors");
396 addToolBar (Qt::RightToolBarArea, m_colorToolBar);
397
398 // ==========================================
399 initSingleToolBar ("Tools");
400 addToolBarAction ("setColor");
401 addToolBarAction ("autoColor");
402 addToolBarAction ("splitQuads");
403 addToolBarAction ("setContents");
404 addToolBarAction ("makeBorders");
405 addToolBarAction ("replaceCoords");
406 addToolBarAction ("roundCoords");
407 addToolBarAction ("visibility");
408
409 // ==========================================
410 g_ToolBarArea = Qt::LeftToolBarArea;
411 initSingleToolBar ("Modes");
412 addToolBarAction ("modeSelect");
413 addToolBarAction ("modeDraw");
414
415 updateToolBars ();
416 }
417
418 // =============================================================================
419 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
420 // =============================================================================
421 vector<quickColor> parseQuickColorMeta () {
422 vector<quickColor> meta; 170 vector<quickColor> meta;
423 171
424 for (str colorname : gui_colortoolbar.value.split (":")) { 172 for (str colorname : gui_colortoolbar.value.split (":")) {
425 if (colorname == "|") { 173 if (colorname == "|") {
426 meta << quickColor ({null, null, true}); 174 meta << quickColor ({null, null, true});
427 } else { 175 } else {
428 LDColor* col = getColor (colorname.toLong ()); 176 LDColor* col = getColor (colorname.toLong());
429 assert (col != null); 177 assert (col != null);
430 meta << quickColor ({col, null, false}); 178 meta << quickColor ({col, null, false});
431 } 179 }
432 } 180 }
433 181
435 } 183 }
436 184
437 // ============================================================================= 185 // =============================================================================
438 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 186 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
439 // ============================================================================= 187 // =============================================================================
440 void ForgeWindow::updateToolBars () { 188 void ForgeWindow::updateToolBars() {
441 const QSize iconsize (gui_toolbar_iconsize, gui_toolbar_iconsize);
442
443 for (QToolBar* bar : m_toolBars)
444 bar->setIconSize (iconsize);
445
446 // Update the quick color toolbar. 189 // Update the quick color toolbar.
447 for (QToolButton* btn : m_colorButtons) 190 for (QToolButton* btn : m_colorButtons)
448 delete btn; 191 delete btn;
449 192
450 m_colorButtons.clear (); 193 m_colorButtons.clear();
451 194
452 // Clear the toolbar to remove separators 195 // Clear the toolbar - we deleted the buttons but there's still separators
453 m_colorToolBar->clear (); 196 ui->colorToolbar->clear();
454 197
455 for (quickColor& entry : m_colorMeta) { 198 for (quickColor& entry : m_colorMeta) {
456 if (entry.isSeparator) 199 if (entry.isSeparator)
457 m_colorToolBar->addSeparator (); 200 ui->colorToolbar->addSeparator();
458 else { 201 else {
459 QToolButton* colorButton = new QToolButton; 202 QToolButton* colorButton = new QToolButton;
460 colorButton->setIcon (makeColorIcon (entry.col, gui_toolbar_iconsize)); 203 colorButton->setIcon (makeColorIcon (entry.col, gui_toolbar_iconsize));
461 colorButton->setIconSize (iconsize); 204 colorButton->setIconSize (QSize (22, 22));
462 colorButton->setToolTip (entry.col->name); 205 colorButton->setToolTip (entry.col->name);
463 206
464 connect (colorButton, SIGNAL (clicked ()), this, SLOT (slot_quickColor ())); 207 connect (colorButton, SIGNAL (clicked()), this, SLOT (slot_quickColor()));
465 m_colorToolBar->addWidget (colorButton); 208 ui->colorToolbar->addWidget (colorButton);
466 m_colorButtons << colorButton; 209 m_colorButtons << colorButton;
467 210
468 entry.btn = colorButton; 211 entry.btn = colorButton;
469 } 212 }
470 } 213 }
471 214
472 updateGridToolBar (); 215 updateGridToolBar();
473 } 216 }
474 217
475 // ============================================================================= 218 // =============================================================================
476 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 219 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
477 // ============================================================================= 220 // =============================================================================
478 void ForgeWindow::updateGridToolBar () { 221 void ForgeWindow::updateGridToolBar() {
479 // Ensure that the current grid - and only the current grid - is selected. 222 // Ensure that the current grid - and only the current grid - is selected.
480 findAction ("gridCoarse")->setChecked (grid == Grid::Coarse); 223 ui->actionGridCoarse->setChecked (grid == Grid::Coarse);
481 findAction ("gridMedium")->setChecked (grid == Grid::Medium); 224 ui->actionGridMedium->setChecked (grid == Grid::Medium);
482 findAction ("gridFine")->setChecked (grid == Grid::Fine); 225 ui->actionGridFine->setChecked (grid == Grid::Fine);
483 } 226 }
484 227
485 // ============================================================================= 228 // =============================================================================
486 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 229 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
487 // ============================================================================= 230 // =============================================================================
488 void ForgeWindow::updateTitle () { 231 void ForgeWindow::updateTitle() {
489 str title = fmt (APPNAME " %1", fullVersionString()); 232 str title = fmt (APPNAME " %1", fullVersionString());
490 233
491 // Append our current file if we have one 234 // Append our current file if we have one
492 if (currentFile()) { 235 if (currentFile()) {
493 if (currentFile()->name ().length () > 0) 236 if (currentFile()->name().length() > 0)
494 title += fmt (": %1", basename (currentFile()->name ())); 237 title += fmt (": %1", basename (currentFile()->name()));
495 else 238 else
496 title += fmt (": <anonymous>"); 239 title += fmt (": <anonymous>");
497 240
498 if (currentFile()->numObjs () > 0 && 241 if (currentFile()->numObjs() > 0 &&
499 currentFile()->obj (0)->getType () == LDObject::Comment) 242 currentFile()->obj (0)->getType() == LDObject::Comment)
500 { 243 {
501 // Append title 244 // Append title
502 LDCommentObject* comm = static_cast<LDCommentObject*> (currentFile()->obj (0)); 245 LDCommentObject* comm = static_cast<LDCommentObject*> (currentFile()->obj (0));
503 title += fmt (": %1", comm->text); 246 title += fmt (": %1", comm->text);
504 } 247 }
505 248
506 if (currentFile()->history ().pos () != currentFile()->savePos ()) 249 if (currentFile()->history().pos() != currentFile()->savePos())
507 title += '*'; 250 title += '*';
508 } 251 }
509 252
510 setWindowTitle (title); 253 setWindowTitle (title);
511 }
512
513 // =============================================================================
514 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
515 // =============================================================================
516 EXTERN_ACTION( undo );
517 EXTERN_ACTION( redo );
518 EXTERN_ACTION( open );
519 void ForgeWindow::slot_action () {
520 // Open the history so we can record the edits done during this action.
521 if( sender() != ACTION( undo ) && sender() != ACTION( redo ) && sender() != ACTION( open ))
522 currentFile()->openHistory ();
523
524 // Get the action that triggered this slot.
525 QAction* qAct = static_cast<QAction*> (sender ());
526
527 // Find the meta for the action.
528 actionmeta* meta = null;
529
530 for (actionmeta& it : g_actionMeta) {
531 if (it.qAct == null)
532 break;
533
534 if (*it.qAct == qAct) {
535 meta = &it;
536 break;
537 }
538 }
539
540 if (!meta) {
541 log ("Warning: unknown signal sender %p!\n", qAct);
542 return;
543 }
544
545 // We have the meta, now call the handler.
546 (*meta->handler) ();
547
548 currentFile()->closeHistory ();
549 } 254 }
550 255
551 // ============================================================================= 256 // =============================================================================
552 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 257 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
553 // ============================================================================= 258 // =============================================================================
558 263
559 vector<LDObject*> selCopy = m_sel; 264 vector<LDObject*> selCopy = m_sel;
560 int num = 0; 265 int num = 0;
561 266
562 // Delete the objects that were being selected 267 // Delete the objects that were being selected
563 for( LDObject * obj : selCopy ) 268 for (LDObject* obj : selCopy) {
564 { 269 currentFile()->forgetObject (obj);
565 currentFile()->forgetObject( obj );
566 ++num; 270 ++num;
567 delete obj; 271 delete obj;
568 } 272 }
569 273
570 refresh(); 274 refresh();
572 } 276 }
573 277
574 // ============================================================================= 278 // =============================================================================
575 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 279 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
576 // ============================================================================= 280 // =============================================================================
577 void ForgeWindow::buildObjList () { 281 void ForgeWindow::buildObjList() {
578 if (!currentFile()) 282 if (!currentFile())
579 return; 283 return;
580 284
581 // Lock the selection while we do this so that refreshing the object list 285 // Lock the selection while we do this so that refreshing the object list
582 // doesn't trigger selection updating so that the selection doesn't get lost 286 // doesn't trigger selection updating so that the selection doesn't get lost
583 // while this is done. 287 // while this is done.
584 g_bSelectionLocked = true; 288 g_bSelectionLocked = true;
585 289
586 for (int i = 0; i < m_objList->count (); ++i) 290 for (int i = 0; i < ui->objectList->count(); ++i)
587 delete m_objList->item (i); 291 delete ui->objectList->item (i);
588 292
589 m_objList->clear (); 293 ui->objectList->clear();
590 294
591 for (LDObject* obj : currentFile()->objs ()) { 295 for (LDObject* obj : currentFile()->objs()) {
592 str descr; 296 str descr;
593 297
594 switch (obj->getType ()) { 298 switch (obj->getType()) {
595 case LDObject::Comment: 299 case LDObject::Comment:
596 descr = static_cast<LDCommentObject*> (obj)->text; 300 descr = static_cast<LDCommentObject*> (obj)->text;
597 301
598 // Remove leading whitespace 302 // Remove leading whitespace
599 while (descr[0] == ' ') 303 while (descr[0] == ' ')
605 309
606 case LDObject::Line: 310 case LDObject::Line:
607 case LDObject::Triangle: 311 case LDObject::Triangle:
608 case LDObject::Quad: 312 case LDObject::Quad:
609 case LDObject::CondLine: 313 case LDObject::CondLine:
610 for (short i = 0; i < obj->vertices (); ++i) { 314 for (short i = 0; i < obj->vertices(); ++i) {
611 if (i != 0) 315 if (i != 0)
612 descr += ", "; 316 descr += ", ";
613 317
614 descr += obj->getVertex (i).stringRep (true); 318 descr += obj->getVertex (i).stringRep (true);
615 } 319 }
625 329
626 case LDObject::Subfile: 330 case LDObject::Subfile:
627 { 331 {
628 LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); 332 LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj);
629 333
630 descr = fmt ("%1 %2, (", ref->fileInfo ()->name (), 334 descr = fmt ("%1 %2, (", ref->fileInfo()->name(),
631 ref->position ().stringRep (true)); 335 ref->position().stringRep (true));
632 336
633 for (short i = 0; i < 9; ++i) 337 for (short i = 0; i < 9; ++i)
634 descr += fmt ("%1%2", ftoa (ref->transform ()[i]), 338 descr += fmt ("%1%2", ftoa (ref->transform()[i]),
635 (i != 8) ? " " : ""); 339 (i != 8) ? " " : "");
636 340
637 descr += ')'; 341 descr += ')';
638 } 342 }
639 break; 343 break;
654 descr = obj->typeName(); 358 descr = obj->typeName();
655 break; 359 break;
656 } 360 }
657 361
658 // Put it into brackets if it's hidden 362 // Put it into brackets if it's hidden
659 if (obj->hidden ()) { 363 if (obj->hidden()) {
660 descr = fmt ("[[ %1 ]]", descr); 364 descr = fmt ("[[ %1 ]]", descr);
661 } 365 }
662 366
663 QListWidgetItem* item = new QListWidgetItem (descr); 367 QListWidgetItem* item = new QListWidgetItem (descr);
664 item->setIcon( getIcon( obj->typeName() )); 368 item->setIcon( getIcon( obj->typeName() ));
665 369
666 // Color gibberish orange on red so it stands out. 370 // Color gibberish orange on red so it stands out.
667 if (obj->getType() == LDObject::Error) { 371 if (obj->getType() == LDObject::Error) {
668 item->setBackground (QColor ("#AA0000")); 372 item->setBackground (QColor ("#AA0000"));
669 item->setForeground (QColor ("#FFAA00")); 373 item->setForeground (QColor ("#FFAA00"));
670 } elif (lv_colorize && obj->isColored () && 374 } elif (lv_colorize && obj->isColored() &&
671 obj->color () != maincolor && obj->color () != edgecolor) 375 obj->color() != maincolor && obj->color() != edgecolor)
672 { 376 {
673 // If the object isn't in the main or edge color, draw this 377 // If the object isn't in the main or edge color, draw this
674 // list entry in said color. 378 // list entry in said color.
675 LDColor* col = getColor (obj->color ()); 379 LDColor* col = getColor (obj->color());
676 if (col) 380 if (col)
677 item->setForeground (col->faceColor); 381 item->setForeground (col->faceColor);
678 } 382 }
679 383
680 obj->qObjListEntry = item; 384 obj->qObjListEntry = item;
681 m_objList->insertItem (m_objList->count (), item); 385 ui->objectList->insertItem (ui->objectList->count(), item);
682 } 386 }
683 387
684 g_bSelectionLocked = false; 388 g_bSelectionLocked = false;
685 updateSelection (); 389 updateSelection();
686 scrollToSelection (); 390 scrollToSelection();
687 } 391 }
688 392
689 // ============================================================================= 393 // =============================================================================
690 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 394 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
691 // ============================================================================= 395 // =============================================================================
692 void ForgeWindow::scrollToSelection () { 396 void ForgeWindow::scrollToSelection() {
693 if (m_sel.size() == 0) 397 if (m_sel.size() == 0)
694 return; 398 return;
695 399
696 LDObject* obj = m_sel[m_sel.size () - 1]; 400 LDObject* obj = m_sel[m_sel.size() - 1];
697 m_objList->scrollToItem (obj->qObjListEntry); 401 ui->objectList->scrollToItem (obj->qObjListEntry);
698 } 402 }
699 403
700 // ============================================================================= 404 // =============================================================================
701 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 405 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
702 // ============================================================================= 406 // =============================================================================
703 void ForgeWindow::slot_selectionChanged () { 407 void ForgeWindow::slot_selectionChanged() {
704 if (g_bSelectionLocked == true || currentFile() == null) 408 if (g_bSelectionLocked == true || currentFile() == null)
705 return; 409 return;
706
707 /*
708 // If the selection isn't 1 exact, disable setting contents
709 findAction ("setContents")->setEnabled (qObjList->selectedItems().size() == 1);
710
711 // If we have no selection, disable splitting quads
712 findAction ("splitQuads")->setEnabled (qObjList->selectedItems().size() > 0);
713 */
714 410
715 // Update the shared selection array, though don't do this if this was 411 // Update the shared selection array, though don't do this if this was
716 // called during GL picking, in which case the GL renderer takes care 412 // called during GL picking, in which case the GL renderer takes care
717 // of the selection. 413 // of the selection.
718 if (m_renderer->picking ()) 414 if (m_renderer->picking())
719 return; 415 return;
720 416
721 vector<LDObject*> priorSelection = m_sel; 417 vector<LDObject*> priorSelection = m_sel;
722 418
723 // Get the objects from the object list selection 419 // Get the objects from the object list selection
724 m_sel.clear (); 420 m_sel.clear();
725 const QList<QListWidgetItem*> items = m_objList->selectedItems (); 421 const QList<QListWidgetItem*> items = ui->objectList->selectedItems();
726 422
727 for (LDObject* obj : currentFile()->objs ()) 423 for (LDObject* obj : currentFile()->objs())
728 for (QListWidgetItem* item : items) { 424 for (QListWidgetItem* item : items) {
729 if (item == obj->qObjListEntry) { 425 if (item == obj->qObjListEntry) {
730 m_sel << obj; 426 m_sel << obj;
731 break; 427 break;
732 } 428 }
741 for (LDObject* obj : m_sel) { 437 for (LDObject* obj : m_sel) {
742 obj->setSelected (true); 438 obj->setSelected (true);
743 m_renderer->compileObject (obj); 439 m_renderer->compileObject (obj);
744 } 440 }
745 441
746 m_renderer->update (); 442 m_renderer->update();
747 } 443 }
748 444
749 // ============================================================================= 445 // =============================================================================
750 void ForgeWindow::slot_recentFile () { 446 void ForgeWindow::slot_recentFile() {
751 QAction* qAct = static_cast<QAction*> (sender ()); 447 QAction* qAct = static_cast<QAction*> (sender());
752 openMainFile (qAct->text ()); 448 openMainFile (qAct->text());
753 } 449 }
754 450
755 // ============================================================================= 451 // =============================================================================
756 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 452 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
757 // ============================================================================= 453 // =============================================================================
758 void ForgeWindow::slot_quickColor () { 454 void ForgeWindow::slot_quickColor() {
759 currentFile()->openHistory (); 455 currentFile()->openHistory();
760 QToolButton* button = static_cast<QToolButton*> (sender ()); 456 QToolButton* button = static_cast<QToolButton*> (sender());
761 LDColor* col = null; 457 LDColor* col = null;
762 458
763 for (quickColor entry : m_colorMeta) { 459 for (quickColor entry : m_colorMeta) {
764 if (entry.btn == button) { 460 if (entry.btn == button) {
765 col = entry.col; 461 col = entry.col;
771 return; 467 return;
772 468
773 short newColor = col->index; 469 short newColor = col->index;
774 470
775 for (LDObject* obj : m_sel) { 471 for (LDObject* obj : m_sel) {
776 if (obj->isColored () == false) 472 if (obj->isColored() == false)
777 continue; // uncolored object 473 continue; // uncolored object
778 474
779 obj->setColor (newColor); 475 obj->setColor (newColor);
780 } 476 }
781 477
782 fullRefresh (); 478 fullRefresh();
783 currentFile()->closeHistory (); 479 currentFile()->closeHistory();
784 } 480 }
785 481
786 // ============================================================================= 482 // =============================================================================
787 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 483 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
788 // ============================================================================= 484 // =============================================================================
789 ulong ForgeWindow::getInsertionPoint () { 485 ulong ForgeWindow::getInsertionPoint() {
790 if (m_sel.size () > 0) { 486 if (m_sel.size() > 0) {
791 // If we have a selection, put the item after it. 487 // If we have a selection, put the item after it.
792 return (m_sel[m_sel.size() - 1]->getIndex (currentFile())) + 1; 488 return (m_sel[m_sel.size() - 1]->getIndex (currentFile())) + 1;
793 } 489 }
794 490
795 // Otherwise place the object at the end. 491 // Otherwise place the object at the end.
796 return currentFile()->numObjs (); 492 return currentFile()->numObjs();
797 } 493 }
798 494
799 // ============================================================================= 495 // =============================================================================
800 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 496 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
801 // ============================================================================= 497 // =============================================================================
802 void ForgeWindow::fullRefresh () { 498 void ForgeWindow::fullRefresh() {
803 buildObjList (); 499 buildObjList();
804 m_renderer->hardRefresh (); 500 m_renderer->hardRefresh();
805 } 501 }
806 502
807 void ForgeWindow::refresh () { 503 void ForgeWindow::refresh() {
808 buildObjList (); 504 buildObjList();
809 m_renderer->update (); 505 m_renderer->update();
810 } 506 }
811 507
812 // ============================================================================= 508 // =============================================================================
813 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 509 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
814 // ============================================================================= 510 // =============================================================================
815 void ForgeWindow::updateSelection () { 511 void ForgeWindow::updateSelection() {
816 g_bSelectionLocked = true; 512 g_bSelectionLocked = true;
817 513
818 for (LDObject* obj : currentFile()->objs ()) 514 for (LDObject* obj : currentFile()->objs())
819 obj->setSelected (false); 515 obj->setSelected (false);
820 516
821 m_objList->clearSelection (); 517 ui->objectList->clearSelection();
822 for (LDObject* obj : m_sel) { 518 for (LDObject* obj : m_sel) {
823 if( obj->qObjListEntry == null ) 519 if( obj->qObjListEntry == null )
824 continue; 520 continue;
825 521
826 obj->qObjListEntry->setSelected (true); 522 obj->qObjListEntry->setSelected (true);
827 obj->setSelected (true); 523 obj->setSelected (true);
828 } 524 }
829 525
830 g_bSelectionLocked = false; 526 g_bSelectionLocked = false;
831 slot_selectionChanged (); 527 slot_selectionChanged();
832 } 528 }
833 529
834 // ============================================================================= 530 // =============================================================================
835 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 531 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
836 // ============================================================================= 532 // =============================================================================
837 bool ForgeWindow::isSelected (LDObject* obj) { 533 bool ForgeWindow::isSelected (LDObject* obj) {
838 LDObject* needle = obj->topLevelParent (); 534 LDObject* needle = obj->topLevelParent();
839 535
840 for (LDObject* hay : m_sel) 536 for (LDObject* hay : m_sel)
841 if (hay == needle) 537 if (hay == needle)
842 return true; 538 return true;
843 539
844 return false; 540 return false;
845 } 541 }
846 542
847 short ForgeWindow::getSelectedColor () { 543 short ForgeWindow::getSelectedColor() {
848 short result = -1; 544 short result = -1;
849 545
850 for (LDObject* obj : m_sel) { 546 for (LDObject* obj : m_sel) {
851 if (obj->isColored () == false) 547 if (obj->isColored() == false)
852 continue; // doesn't use color 548 continue; // doesn't use color
853 549
854 if (result != -1 && obj->color () != result) 550 if (result != -1 && obj->color() != result)
855 return -1; // No consensus in object color 551 return -1; // No consensus in object color
856 552
857 if (result == -1) 553 if (result == -1)
858 result = obj->color (); 554 result = obj->color();
859 } 555 }
860 556
861 return result; 557 return result;
862 } 558 }
863 559
864 // ============================================================================= 560 // =============================================================================
865 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 561 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
866 // ============================================================================= 562 // =============================================================================
867 LDObject::Type ForgeWindow::uniformSelectedType () { 563 LDObject::Type ForgeWindow::uniformSelectedType() {
868 LDObject::Type result = LDObject::Unidentified; 564 LDObject::Type result = LDObject::Unidentified;
869 565
870 for (LDObject* obj : m_sel) { 566 for (LDObject* obj : m_sel) {
871 if (result != LDObject::Unidentified && obj->color () != result) 567 if (result != LDObject::Unidentified && obj->color() != result)
872 return LDObject::Unidentified; 568 return LDObject::Unidentified;
873 569
874 if (result == LDObject::Unidentified) 570 if (result == LDObject::Unidentified)
875 result = obj->getType (); 571 result = obj->getType();
876 } 572 }
877 573
878 return result; 574 return result;
879 } 575 }
880 576
881 // ============================================================================= 577 // =============================================================================
882 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 578 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
883 // ============================================================================= 579 // =============================================================================
884 void ForgeWindow::closeEvent (QCloseEvent* ev) { 580 void ForgeWindow::closeEvent (QCloseEvent* ev) {
885 // Check whether it's safe to close all files. 581 // Check whether it's safe to close all files.
886 if (!safeToCloseAll ()) { 582 if (!safeToCloseAll()) {
887 ev->ignore (); 583 ev->ignore();
888 return; 584 return;
889 } 585 }
890 586
891 // Save the configuration before leaving so that, for instance, grid choice 587 // Save the configuration before leaving so that, for instance, grid choice
892 // is preserved across instances. 588 // is preserved across instances.
893 config::save (); 589 config::save();
894 590
895 ev->accept (); 591 ev->accept();
896 } 592 }
897 593
898 // ============================================================================= 594 // =============================================================================
899 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 595 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
900 // ============================================================================= 596 // =============================================================================
901 void ForgeWindow::spawnContextMenu (const QPoint pos) { 597 void ForgeWindow::spawnContextMenu (const QPoint pos) {
902 const bool single = (g_win->sel ().size () == 1); 598 const bool single = (g_win->sel().size() == 1);
903 LDObject* singleObj = (single) ? g_win->sel ()[0] : null; 599 LDObject* singleObj = (single) ? g_win->sel()[0] : null;
904 600
905 QMenu* contextMenu = new QMenu; 601 QMenu* contextMenu = new QMenu;
906 602
907 if (single && singleObj->getType () != LDObject::Empty) { 603 if (single && singleObj->getType() != LDObject::Empty) {
908 contextMenu->addAction (findAction ("editObject")); 604 contextMenu->addAction (ACTION (Edit));
909 contextMenu->addSeparator (); 605 contextMenu->addSeparator();
910 } 606 }
911 607
912 contextMenu->addAction (findAction ("cut")); 608 contextMenu->addAction (ACTION (Cut));
913 contextMenu->addAction (findAction ("copy")); 609 contextMenu->addAction (ACTION (Copy));
914 contextMenu->addAction (findAction ("paste")); 610 contextMenu->addAction (ACTION (Paste));
915 contextMenu->addAction (findAction ("del")); 611 contextMenu->addAction (ACTION (Delete));
916 contextMenu->addSeparator (); 612 contextMenu->addSeparator();
917 contextMenu->addAction (findAction ("setColor")); 613 contextMenu->addAction (ACTION (SetColor));
918 614
919 if (single) 615 if (single)
920 contextMenu->addAction (findAction ("setContents")); 616 contextMenu->addAction (ACTION (EditRaw));
921 617
922 contextMenu->addAction (findAction ("makeBorders")); 618 contextMenu->addAction (ACTION (Borders));
923 contextMenu->addAction (findAction ("setOverlay")); 619 contextMenu->addAction (ACTION (SetOverlay));
924 contextMenu->addAction (findAction ("clearOverlay")); 620 contextMenu->addAction (ACTION (ClearOverlay));
925 621 contextMenu->addAction (ACTION (ModeSelect));
926 for (const char* mode : g_modeActionNames) 622 contextMenu->addAction (ACTION (ModeDraw));
927 contextMenu->addAction (findAction (mode)); 623
928 624 if (R()->camera() != GL::Free) {
929 if (R ()->camera () != GL::Free) { 625 contextMenu->addSeparator();
930 contextMenu->addSeparator (); 626 contextMenu->addAction (ACTION (SetDrawDepth));
931 contextMenu->addAction (findAction ("setDrawDepth"));
932 } 627 }
933 628
934 contextMenu->exec (pos); 629 contextMenu->exec (pos);
935 } 630 }
936 631
943 } 638 }
944 639
945 // ============================================================================= 640 // =============================================================================
946 void ForgeWindow::deleteByColor (const short colnum) { 641 void ForgeWindow::deleteByColor (const short colnum) {
947 vector<LDObject*> objs; 642 vector<LDObject*> objs;
948 for (LDObject* obj : currentFile()->objs ()) { 643 for (LDObject* obj : currentFile()->objs()) {
949 if (!obj->isColored () || obj->color () != colnum) 644 if (!obj->isColored() || obj->color() != colnum)
950 continue; 645 continue;
951 646
952 objs << obj; 647 objs << obj;
953 } 648 }
954 649
955 deleteObjVector (objs); 650 deleteObjVector (objs);
956 } 651 }
957 652
958 // ============================================================================= 653 // =============================================================================
959 void ForgeWindow::updateEditModeActions () { 654 void ForgeWindow::updateEditModeActions() {
960 const EditMode mode = R ()->editMode (); 655 const EditMode mode = R()->editMode();
961 const size_t numModeActions = (sizeof g_modeActionNames / sizeof *g_modeActionNames); 656 ACTION (ModeSelect)->setChecked (mode == Select);
962 assert ((size_t) mode < numModeActions); 657 ACTION (ModeDraw)->setChecked (mode == Draw);
963
964 for (size_t i = 0; i < numModeActions; ++i) {
965 QAction* act = findAction (g_modeActionNames[i]);
966
967 act->setCheckable (true);
968 act->setChecked (i == (size_t) mode);
969
970 if (i != Select)
971 act->setEnabled (R ()->camera () != GL::Free);
972 }
973 } 658 }
974 659
975 void ForgeWindow::slot_editObject (QListWidgetItem* listitem) { 660 void ForgeWindow::slot_editObject (QListWidgetItem* listitem) {
976 LDObject* obj = null; 661 LDObject* obj = null;
977 for (LDObject* it : *currentFile()) { 662 for (LDObject* it : *currentFile()) {
979 obj = it; 664 obj = it;
980 break; 665 break;
981 } 666 }
982 } 667 }
983 668
984 AddObjectDialog::staticDialog (obj->getType (), obj); 669 AddObjectDialog::staticDialog (obj->getType(), obj);
985 } 670 }
986 671
987 void ForgeWindow::primitiveLoaderStart (ulong max) { 672 void ForgeWindow::primitiveLoaderStart (ulong max) {
988 m_primLoaderWidget->show (); 673 m_primLoaderWidget->show();
989 m_primLoaderBar->setRange (0, max); 674 m_primLoaderBar->setRange (0, max);
990 m_primLoaderBar->setValue (0); 675 m_primLoaderBar->setValue (0);
991 m_primLoaderBar->setFormat ("%p%"); 676 m_primLoaderBar->setFormat ("%p%");
992 } 677 }
993 678
994 void ForgeWindow::primitiveLoaderUpdate (ulong prog) { 679 void ForgeWindow::primitiveLoaderUpdate (ulong prog) {
995 m_primLoaderBar->setValue (prog); 680 m_primLoaderBar->setValue (prog);
996 } 681 }
997 682
998 void ForgeWindow::primitiveLoaderEnd () { 683 void ForgeWindow::primitiveLoaderEnd() {
999 QTimer* hidetimer = new QTimer; 684 QTimer* hidetimer = new QTimer;
1000 connect (hidetimer, SIGNAL (timeout ()), m_primLoaderWidget, SLOT (hide ())); 685 connect (hidetimer, SIGNAL (timeout()), m_primLoaderWidget, SLOT (hide()));
1001 hidetimer->setSingleShot (true); 686 hidetimer->setSingleShot (true);
1002 hidetimer->start (1500); 687 hidetimer->start (1500);
1003 m_primLoaderBar->setFormat( tr( "Done" )); 688 m_primLoaderBar->setFormat( tr( "Done" ));
1004 log( tr( "Primitives scanned: %1 primitives listed" ), m_primLoaderBar->value() ); 689 log (tr ("Primitives scanned: %1 primitives listed"), m_primLoaderBar->value());
1005 } 690 }
1006 691
1007 // ============================================================================= 692 // =============================================================================
1008 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 693 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1009 // ============================================================================= 694 // =============================================================================
1010 void ForgeWindow::save (LDOpenFile* f, bool saveAs) { 695 void ForgeWindow::save (LDOpenFile* f, bool saveAs) {
1011 str path = f->name (); 696 str path = f->name();
1012 697
1013 if (path.length () == 0 || saveAs) { 698 if (path.length() == 0 || saveAs) {
1014 path = QFileDialog::getSaveFileName (g_win, tr ("Save As"), 699 path = QFileDialog::getSaveFileName (g_win, tr ("Save As"),
1015 currentFile()->name (), tr ("LDraw files (*.dat *.ldr)")); 700 currentFile()->name(), tr ("LDraw files (*.dat *.ldr)"));
1016 701
1017 if (path.length () == 0) { 702 if (path.length() == 0) {
1018 // User didn't give a file name. This happens if the user cancelled 703 // User didn't give a file name. This happens if the user cancelled
1019 // saving in the save file dialog. Abort. 704 // saving in the save file dialog. Abort.
1020 return; 705 return;
1021 } 706 }
1022 } 707 }
1023 708
1024 if (f->save (path)) { 709 if (f->save (path)) {
1025 f->setName (path); 710 f->setName (path);
1026 711
1027 if (f == currentFile()) 712 if (f == currentFile())
1028 g_win->updateTitle (); 713 g_win->updateTitle();
1029 714
1030 log ("Saved to %1.", path); 715 log ("Saved to %1.", path);
1031 716
1032 // Add it to recent files 717 // Add it to recent files
1033 addRecentFile (path); 718 addRecentFile (path);
1034 } else { 719 } else {
1035 setlocale (LC_ALL, "C");
1036
1037 str message = fmt (tr ("Failed to save to %1: %2"), path, strerror (errno)); 720 str message = fmt (tr ("Failed to save to %1: %2"), path, strerror (errno));
1038 721
1039 // Tell the user the save failed, and give the option for saving as with it. 722 // Tell the user the save failed, and give the option for saving as with it.
1040 QMessageBox dlg (QMessageBox::Critical, tr ("Save Failure"), message, 723 QMessageBox dlg (QMessageBox::Critical, tr ("Save Failure"), message, QMessageBox::Close, g_win);
1041 QMessageBox::Close, g_win);
1042 724
1043 // Add a save-as button 725 // Add a save-as button
1044 QPushButton* saveAsBtn = new QPushButton (tr ("Save As")); 726 QPushButton* saveAsBtn = new QPushButton (tr ("Save As"));
1045 saveAsBtn->setIcon (getIcon ("file-save-as")); 727 saveAsBtn->setIcon (getIcon ("file-save-as"));
1046 dlg.addButton (saveAsBtn, QMessageBox::ActionRole); 728 dlg.addButton (saveAsBtn, QMessageBox::ActionRole);
1047 dlg.setDefaultButton (QMessageBox::Close); 729 dlg.setDefaultButton (QMessageBox::Close);
1048 dlg.exec(); 730 dlg.exec();
1049 731
1050 if (dlg.clickedButton () == saveAsBtn) 732 if (dlg.clickedButton() == saveAsBtn)
1051 save (f, true); // yay recursion! 733 save (f, true); // yay recursion!
1052 } 734 }
1053 } 735 }
1054 736
1055 void ForgeWindow::addMessage( str msg ) 737 void ForgeWindow::addMessage (str msg) {
1056 { 738 m_msglog->addLine (msg);
1057 m_msglog->addLine( msg );
1058 } 739 }
1059 740
1060 // ============================================================================ 741 // ============================================================================
1061 void ObjectList::contextMenuEvent (QContextMenuEvent* ev) { 742 void ObjectList::contextMenuEvent (QContextMenuEvent* ev) {
1062 g_win->spawnContextMenu (ev->globalPos ()); 743 g_win->spawnContextMenu (ev->globalPos());
1063 } 744 }
1064 745
1065 // ============================================================================= 746 // =============================================================================
1066 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 747 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1067 // ============================================================================= 748 // =============================================================================
1069 return (QPixmap (fmt (":/icons/%1.png", iconName))); 750 return (QPixmap (fmt (":/icons/%1.png", iconName)));
1070 } 751 }
1071 752
1072 // ============================================================================= 753 // =============================================================================
1073 bool confirm (str msg) { 754 bool confirm (str msg) {
1074 return confirm ("Confirm", msg); 755 return confirm (ForgeWindow::tr ("Confirm"), msg);
1075 } 756 }
1076 757
1077 bool confirm (str title, str msg) { 758 bool confirm (str title, str msg) {
1078 return QMessageBox::question (g_win, title, msg, 759 return QMessageBox::question (g_win, title, msg,
1079 (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes; 760 (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes;
1080 } 761 }
1081 762
1082 // ============================================================================= 763 // =============================================================================
1083 void critical (str msg) { 764 void critical (str msg) {
1084 QMessageBox::critical (g_win, QObject::tr( "Error" ), msg, 765 QMessageBox::critical (g_win, ForgeWindow::tr("Error"), msg,
1085 (QMessageBox::Close), QMessageBox::Close); 766 (QMessageBox::Close), QMessageBox::Close);
1086 }
1087
1088 // =============================================================================
1089 QAction* findAction (str name) {
1090 for (actionmeta& meta : g_actionMeta) {
1091 if (meta.qAct == null)
1092 break;
1093
1094 if (name == meta.name)
1095 return *meta.qAct;
1096 }
1097
1098 fatal (fmt ("Couldn't find action named `%2'!", name));
1099 abort ();
1100 return null;
1101 } 767 }
1102 768
1103 // ============================================================================= 769 // =============================================================================
1104 QIcon makeColorIcon (LDColor* colinfo, const ushort size) { 770 QIcon makeColorIcon (LDColor* colinfo, const ushort size) {
1105 // Create an image object and link a painter to it. 771 // Create an image object and link a painter to it.
1108 774
1109 QColor col = colinfo->faceColor; 775 QColor col = colinfo->faceColor;
1110 if (colinfo->index == maincolor) { 776 if (colinfo->index == maincolor) {
1111 // Use the user preferences for main color here 777 // Use the user preferences for main color here
1112 col = gl_maincolor.value; 778 col = gl_maincolor.value;
1113 col.setAlpha (gl_maincolor_alpha * 255.0f); 779 col.setAlphaF (gl_maincolor_alpha);
1114 } 780 }
1115 781
1116 // Paint the icon 782 // Paint the icon
1117 paint.fillRect (QRect (0, 0, size, size), Qt::black); 783 paint.fillRect (QRect (0, 0, size, size), colinfo->edgeColor);
1118 paint.drawPixmap (QRect (1, 1, size - 2, size - 2), getIcon ("checkerboard"), QRect (0, 0, 8, 8)); 784 paint.drawPixmap (QRect (1, 1, size - 2, size - 2), getIcon ("checkerboard"), QRect (0, 0, 8, 8));
1119 paint.fillRect (QRect (1, 1, size - 2, size - 2), col); 785 paint.fillRect (QRect (1, 1, size - 2, size - 2), col);
1120 return QIcon (QPixmap::fromImage (img)); 786 return QIcon (QPixmap::fromImage (img));
1121 } 787 }
1122 788
1123 // ============================================================================= 789 // =============================================================================
1124 void makeColorSelector (QComboBox* box) { 790 void makeColorSelector (QComboBox* box) {
1125 std::map<short, ulong> counts; 791 std::map<short, ulong> counts;
1126 792
1127 for (LDObject* obj : currentFile()->objs ()) { 793 for (LDObject* obj : currentFile()->objs()) {
1128 if (!obj->isColored ()) 794 if (!obj->isColored())
1129 continue; 795 continue;
1130 796
1131 if (counts.find (obj->color ()) == counts.end ()) 797 if (counts.find (obj->color()) == counts.end())
1132 counts[obj->color ()] = 1; 798 counts[obj->color()] = 1;
1133 else 799 else
1134 counts[obj->color ()]++; 800 counts[obj->color()]++;
1135 } 801 }
1136 802
1137 box->clear (); 803 box->clear();
1138 ulong row = 0; 804 ulong row = 0;
1139 for (const auto& pair : counts) { 805 for (const auto& pair : counts) {
1140 LDColor* col = getColor (pair.first); 806 LDColor* col = getColor (pair.first);
1141 assert (col != null); 807 assert (col != null);
1142 808
1150 } 816 }
1151 817
1152 // ============================================================================= 818 // =============================================================================
1153 QDialogButtonBox* makeButtonBox (QDialog& dlg) { 819 QDialogButtonBox* makeButtonBox (QDialog& dlg) {
1154 QDialogButtonBox* bbx_buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 820 QDialogButtonBox* bbx_buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
1155 QWidget::connect (bbx_buttons, SIGNAL (accepted ()), &dlg, SLOT (accept ())); 821 QWidget::connect (bbx_buttons, SIGNAL (accepted()), &dlg, SLOT (accept()));
1156 QWidget::connect (bbx_buttons, SIGNAL (rejected ()), &dlg, SLOT (reject ())); 822 QWidget::connect (bbx_buttons, SIGNAL (rejected()), &dlg, SLOT (reject()));
1157 return bbx_buttons; 823 return bbx_buttons;
1158 } 824 }
1159 825
1160 CheckBoxGroup* makeAxesBox () { 826 CheckBoxGroup* makeAxesBox() {
1161 CheckBoxGroup* cbg_axes = new CheckBoxGroup ("Axes", Qt::Horizontal); 827 CheckBoxGroup* cbg_axes = new CheckBoxGroup ("Axes", Qt::Horizontal);
1162 cbg_axes->addCheckBox ("X", X); 828 cbg_axes->addCheckBox ("X", X);
1163 cbg_axes->addCheckBox ("Y", Y); 829 cbg_axes->addCheckBox ("Y", Y);
1164 cbg_axes->addCheckBox ("Z", Z); 830 cbg_axes->addCheckBox ("Z", Z);
1165 return cbg_axes; 831 return cbg_axes;
1166 } 832 }
1167 833
1168 void ForgeWindow::setStatusBarText (str text) { 834 void ForgeWindow::setStatusBarText (str text) {
1169 statusBar ()->showMessage (text); 835 statusBar()->showMessage (text);
1170 } 836 }
1171 837
1172 void ForgeWindow::addActionMeta (actionmeta& meta) { 838 void ForgeWindow::clearSelection() {
1173 if (g_metacursor == 0)
1174 memset (g_actionMeta, 0, sizeof g_actionMeta);
1175
1176 assert (g_metacursor < MAX_ACTIONS);
1177 g_actionMeta[g_metacursor++] = meta;
1178 }
1179
1180 void ForgeWindow::clearSelection()
1181 {
1182 m_sel.clear(); 839 m_sel.clear();
1183 } 840 }
841
842 Ui_LDForgeUI* ForgeWindow::interface() const {
843 return ui;
844 }
845
846 #define act(N) QAction* ForgeWindow::action##N() { return ui->action##N; }
847 #include "actions.h"
1184 848
1185 QImage imageFromScreencap (uchar* data, ushort w, ushort h) { 849 QImage imageFromScreencap (uchar* data, ushort w, ushort h) {
1186 // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well. 850 // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well.
1187 return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped ().mirrored (); 851 return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped().mirrored();
1188 } 852 }

mercurial