src/gui.cpp

changeset 665
4355e72ffd47
parent 664
e3a32a79a10a
parent 530
f9476dbd87ec
equal deleted inserted replaced
664:e3a32a79a10a 665:4355e72ffd47
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 #include "ui_ldforge.h" 50 #include "ui_ldforge.h"
51 #include "moc_gui.cpp"
51 52
52 static bool g_bSelectionLocked = false; 53 static bool g_bSelectionLocked = false;
53 54
54 cfg (Bool, lv_colorize, true); 55 cfg (Bool, lv_colorize, true);
55 cfg (String, gui_colortoolbar, "16:24:|:1:2:4:14:0:15:|:33:34:36:46"); 56 cfg (String, gui_colortoolbar, "16:24:|:1:2:4:14:0:15:|:33:34:36:46");
62 extern_cfg (Bool, gl_colorbfc); 63 extern_cfg (Bool, gl_colorbfc);
63 64
64 #define act(N) extern_cfg (KeySequence, key_##N); 65 #define act(N) extern_cfg (KeySequence, key_##N);
65 #include "actions.h" 66 #include "actions.h"
66 67
67 const char* g_modeActionNames[] = { 68 // =============================================================================
68 "modeSelect", 69 // -----------------------------------------------------------------------------
69 "modeDraw", 70 ForgeWindow::ForgeWindow()
70 }; 71 { g_win = this;
71
72 // =============================================================================
73 // -----------------------------------------------------------------------------
74 ForgeWindow::ForgeWindow() {
75 g_win = this;
76 m_renderer = new GLRenderer; 72 m_renderer = new GLRenderer;
77 73
78 ui = new Ui_LDForgeUI; 74 ui = new Ui_LDForgeUI;
79 ui->setupUi (this); 75 ui->setupUi (this);
80 76
81 // Stuff the renderer into its frame 77 // Stuff the renderer into its frame
82 QVBoxLayout* rendererLayout = new QVBoxLayout (ui->rendererFrame); 78 QVBoxLayout* rendererLayout = new QVBoxLayout (ui->rendererFrame);
83 rendererLayout->addWidget (R()); 79 rendererLayout->addWidget (R());
84 80
85 connect (ui->objectList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_selectionChanged())); 81 connect (ui->objectList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_selectionChanged()));
86 connect (ui->objectList, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (slot_editObject (QListWidgetItem*))); 82 connect (ui->objectList, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (slot_editObject (QListWidgetItem*)));
87 connect (ui->fileList, SIGNAL (currentItemChanged (QListWidgetItem*, QListWidgetItem*)), this, SLOT (changeCurrentFile())); 83 connect (ui->fileList, SIGNAL (currentItemChanged (QListWidgetItem*, QListWidgetItem*)), this, SLOT (changeCurrentFile()));
88 84
89 // Init message log manager 85 // Init message log manager
90 m_msglog = new MessageManager; 86 m_msglog = new MessageManager;
91 m_msglog->setRenderer (R()); 87 m_msglog->setRenderer (R());
92 m_renderer->setMessageLog (m_msglog); 88 m_renderer->setMessageLog (m_msglog);
93 m_quickColors = quickColorsFromConfig(); 89 m_quickColors = quickColorsFromConfig();
94 slot_selectionChanged(); 90 slot_selectionChanged();
95 setStatusBar (new QStatusBar); 91 setStatusBar (new QStatusBar);
96 92
97 // Init primitive loader task stuff 93 // Init primitive loader task stuff
98 m_primLoaderBar = new QProgressBar; 94 m_primLoaderBar = new QProgressBar;
99 m_primLoaderWidget = new QWidget; 95 m_primLoaderWidget = new QWidget;
100 QHBoxLayout* primLoaderLayout = new QHBoxLayout (m_primLoaderWidget); 96 QHBoxLayout* primLoaderLayout = new QHBoxLayout (m_primLoaderWidget);
101 primLoaderLayout->addWidget (new QLabel ("Loading primitives:")); 97 primLoaderLayout->addWidget (new QLabel ("Loading primitives:"));
102 primLoaderLayout->addWidget (m_primLoaderBar); 98 primLoaderLayout->addWidget (m_primLoaderBar);
103 statusBar()->addPermanentWidget (m_primLoaderWidget); 99 statusBar()->addPermanentWidget (m_primLoaderWidget);
104 m_primLoaderWidget->hide(); 100 m_primLoaderWidget->hide();
105 101
106 // Make certain actions checkable 102 // Make certain actions checkable
107 ui->actionAxes->setChecked (gl_axes); 103 ui->actionAxes->setChecked (gl_axes);
108 ui->actionWireframe->setChecked (gl_wireframe); 104 ui->actionWireframe->setChecked (gl_wireframe);
109 ui->actionBFCView->setChecked (gl_colorbfc); 105 ui->actionBFCView->setChecked (gl_colorbfc);
110 updateGridToolBar(); 106 updateGridToolBar();
111 updateEditModeActions(); 107 updateEditModeActions();
112 updateRecentFilesMenu(); 108 updateRecentFilesMenu();
113 updateToolBars(); 109 updateToolBars();
114 updateTitle(); 110 updateTitle();
115 111
116 setMinimumSize (300, 200); 112 setMinimumSize (300, 200);
117 113
118 connect (qApp, SIGNAL (aboutToQuit()), this, SLOT (slot_lastSecondCleanup())); 114 connect (qApp, SIGNAL (aboutToQuit()), this, SLOT (slot_lastSecondCleanup()));
119 115
120 // Connect all actions and set shortcuts 116 // Connect all actions and set shortcuts
121 #define act(N) \ 117 #define act(N) \
122 connect (ui->action##N, SIGNAL (triggered()), this, SLOT (slot_action())); \ 118 connect (ui->action##N, SIGNAL (triggered()), this, SLOT (slot_action())); \
123 ui->action##N->setShortcut (key_##N); 119 ui->action##N->setShortcut (key_##N);
124 #include "actions.h" 120 #include "actions.h"
125 } 121 }
126 122
127 // ============================================================================= 123 // =============================================================================
128 // ----------------------------------------------------------------------------- 124 // -----------------------------------------------------------------------------
129 void ForgeWindow::slot_action() { 125 void ForgeWindow::slot_action()
130 // Find out which action triggered this 126 { // Find out which action triggered this
131 #define act(N) if (sender() == ui->action##N) invokeAction (ui->action##N, &actiondef_##N); 127 #define act(N) if (sender() == ui->action##N) invokeAction (ui->action##N, &actiondef_##N);
132 #include "actions.h" 128 #include "actions.h"
133 } 129 }
134 130
135 // ============================================================================= 131 // =============================================================================
136 // ----------------------------------------------------------------------------- 132 // -----------------------------------------------------------------------------
137 void ForgeWindow::invokeAction (QAction* act, void (*func)()) { 133 void ForgeWindow::invokeAction (QAction* act, void (*func) ())
138 beginAction (act); 134 { beginAction (act);
139 (*func)(); 135 (*func) ();
140 endAction(); 136 endAction();
141 } 137 }
142 138
143 // ============================================================================= 139 // =============================================================================
144 // ----------------------------------------------------------------------------- 140 // -----------------------------------------------------------------------------
145 void ForgeWindow::slot_lastSecondCleanup() { 141 void ForgeWindow::slot_lastSecondCleanup()
146 delete m_renderer; 142 { delete m_renderer;
147 delete ui; 143 delete ui;
148 } 144 }
149 145
150 // ============================================================================= 146 // =============================================================================
151 // ----------------------------------------------------------------------------- 147 // -----------------------------------------------------------------------------
152 void ForgeWindow::updateRecentFilesMenu() { 148 void ForgeWindow::updateRecentFilesMenu()
153 // First, clear any items in the recent files menu 149 { // First, clear any items in the recent files menu
154 for (QAction* recent : m_recentFiles) 150 for (QAction * recent : m_recentFiles)
155 delete recent; 151 delete recent;
152
156 m_recentFiles.clear(); 153 m_recentFiles.clear();
157 154
158 QAction* first = null; 155 QAction* first = null;
159 156
160 for (const QVariant& it : io_recentfiles) { 157 for (const QVariant & it : io_recentfiles)
161 str file = it.toString(); 158 { str file = it.toString();
162 QAction* recent = new QAction (getIcon ("open-recent"), file, this); 159 QAction* recent = new QAction (getIcon ("open-recent"), file, this);
163 160
164 connect (recent, SIGNAL (triggered()), this, SLOT (slot_recentFile())); 161 connect (recent, SIGNAL (triggered()), this, SLOT (slot_recentFile()));
165 ui->menuOpenRecent->insertAction (first, recent); 162 ui->menuOpenRecent->insertAction (first, recent);
166 m_recentFiles << recent; 163 m_recentFiles << recent;
167 first = recent; 164 first = recent;
168 } 165 }
169 } 166 }
170 167
171 // ============================================================================= 168 // =============================================================================
172 // ----------------------------------------------------------------------------- 169 // -----------------------------------------------------------------------------
173 List<LDQuickColor> quickColorsFromConfig() { 170 QList<LDQuickColor> quickColorsFromConfig()
174 List<LDQuickColor> colors; 171 { QList<LDQuickColor> colors;
175 172
176 for (str colorname : gui_colortoolbar.value.split (":")) { 173 for (str colorname : gui_colortoolbar.value.split (":"))
177 if (colorname == "|") 174 { if (colorname == "|")
178 colors << LDQuickColor::getSeparator(); 175 colors << LDQuickColor::getSeparator();
179 else { 176 else
180 LDColor* col = getColor (colorname.toLong()); 177 { LDColor* col = getColor (colorname.toLong());
181 178
182 if (col != null) 179 if (col != null)
183 colors << LDQuickColor (col, null); 180 colors << LDQuickColor (col, null);
184 } 181 }
185 } 182 }
186 183
187 return colors; 184 return colors;
188 } 185 }
189 186
190 // ============================================================================= 187 // =============================================================================
191 // ----------------------------------------------------------------------------- 188 // -----------------------------------------------------------------------------
192 void ForgeWindow::updateToolBars() { 189 void ForgeWindow::updateToolBars()
193 m_colorButtons.clear(); 190 { m_colorButtons.clear();
194 ui->colorToolbar->clear(); 191 ui->colorToolbar->clear();
195 192
196 for (LDQuickColor& entry : m_quickColors) { 193 for (LDQuickColor & entry : m_quickColors)
197 if (entry.isSeparator()) 194 { if (entry.isSeparator())
198 ui->colorToolbar->addSeparator(); 195 ui->colorToolbar->addSeparator();
199 else { 196 else
200 QToolButton* colorButton = new QToolButton; 197 { QToolButton* colorButton = new QToolButton;
201 colorButton->setIcon (makeColorIcon (entry.color(), 22)); 198 colorButton->setIcon (makeColorIcon (entry.color(), 22));
202 colorButton->setIconSize (QSize (22, 22)); 199 colorButton->setIconSize (QSize (22, 22));
203 colorButton->setToolTip (entry.color()->name); 200 colorButton->setToolTip (entry.color()->name);
204 201
205 connect (colorButton, SIGNAL (clicked()), this, SLOT (slot_quickColor())); 202 connect (colorButton, SIGNAL (clicked()), this, SLOT (slot_quickColor()));
206 ui->colorToolbar->addWidget (colorButton); 203 ui->colorToolbar->addWidget (colorButton);
207 m_colorButtons << colorButton; 204 m_colorButtons << colorButton;
208 205
209 entry.setToolButton (colorButton); 206 entry.setToolButton (colorButton);
210 } 207 }
211 } 208 }
212 209
213 updateGridToolBar(); 210 updateGridToolBar();
214 } 211 }
215 212
216 // ============================================================================= 213 // =============================================================================
217 // ----------------------------------------------------------------------------- 214 // -----------------------------------------------------------------------------
218 void ForgeWindow::updateGridToolBar() { 215 void ForgeWindow::updateGridToolBar()
219 // Ensure that the current grid - and only the current grid - is selected. 216 { // Ensure that the current grid - and only the current grid - is selected.
220 ui->actionGridCoarse->setChecked (grid == Grid::Coarse); 217 ui->actionGridCoarse->setChecked (grid == Grid::Coarse);
221 ui->actionGridMedium->setChecked (grid == Grid::Medium); 218 ui->actionGridMedium->setChecked (grid == Grid::Medium);
222 ui->actionGridFine->setChecked (grid == Grid::Fine); 219 ui->actionGridFine->setChecked (grid == Grid::Fine);
223 } 220 }
224 221
225 // ============================================================================= 222 // =============================================================================
226 // ----------------------------------------------------------------------------- 223 // -----------------------------------------------------------------------------
227 void ForgeWindow::updateTitle() { 224 void ForgeWindow::updateTitle()
228 str title = fmt (APPNAME " %1", fullVersionString()); 225 { str title = fmt (APPNAME " %1", fullVersionString());
229 226
230 // Append our current file if we have one 227 // Append our current file if we have one
231 if (LDFile::current()) { 228 if (LDFile::current())
232 if (LDFile::current()->name().length() > 0) 229 { if (LDFile::current()->name().length() > 0)
233 title += fmt (": %1", basename (LDFile::current()->name())); 230 title += fmt (": %1", basename (LDFile::current()->name()));
234 else 231 else
235 title += fmt (": <anonymous>"); 232 title += fmt (": <anonymous>");
236 233
237 if (LDFile::current()->numObjs() > 0 && 234 if (LDFile::current()->numObjs() > 0 &&
238 LDFile::current()->obj (0)->getType() == LDObject::Comment) 235 LDFile::current()->obj (0)->getType() == LDObject::Comment)
239 { 236 { // Append title
240 // Append title
241 LDComment* comm = static_cast<LDComment*> (LDFile::current()->obj (0)); 237 LDComment* comm = static_cast<LDComment*> (LDFile::current()->obj (0));
242 title += fmt (": %1", comm->text); 238 title += fmt (": %1", comm->text);
243 } 239 }
244 240
245 if (LDFile::current()->history().pos() != LDFile::current()->savePos()) 241 if (LDFile::current()->history().pos() != LDFile::current()->savePos())
246 title += '*'; 242 title += '*';
247 } 243 }
248 244
245 #ifdef DEBUG
246 title += " [debug build]";
247 #elif BUILD_ID != BUILD_RELEASE
248 title += " [release build]";
249 #endif // DEBUG
250
249 setWindowTitle (title); 251 setWindowTitle (title);
250 } 252 }
251 253
252 // ============================================================================= 254 // =============================================================================
253 // ----------------------------------------------------------------------------- 255 // -----------------------------------------------------------------------------
254 int ForgeWindow::deleteSelection() { 256 int ForgeWindow::deleteSelection()
255 if (m_sel.size() == 0) 257 { if (selection().isEmpty())
256 return 0; 258 return 0;
257 259
258 List<LDObject*> selCopy = m_sel; 260 QList<LDObject*> selCopy = selection();
259 int num = 0; 261
260
261 // Delete the objects that were being selected 262 // Delete the objects that were being selected
262 for (LDObject* obj : selCopy) { 263 for (LDObject* obj : selCopy)
263 LDFile::current()->forgetObject (obj);
264 ++num;
265 delete obj; 264 delete obj;
266 } 265
267
268 refresh(); 266 refresh();
269 return num; 267 return selCopy.size();
270 } 268 }
271 269
272 // ============================================================================= 270 // =============================================================================
273 // ----------------------------------------------------------------------------- 271 // -----------------------------------------------------------------------------
274 void ForgeWindow::buildObjList() { 272 void ForgeWindow::buildObjList()
275 if (!LDFile::current()) 273 { if (!LDFile::current())
276 return; 274 return;
277 275
278 // Lock the selection while we do this so that refreshing the object list 276 // Lock the selection while we do this so that refreshing the object list
279 // doesn't trigger selection updating so that the selection doesn't get lost 277 // doesn't trigger selection updating so that the selection doesn't get lost
280 // while this is done. 278 // while this is done.
281 g_bSelectionLocked = true; 279 g_bSelectionLocked = true;
282 280
283 for (int i = 0; i < ui->objectList->count(); ++i) 281 for (int i = 0; i < ui->objectList->count(); ++i)
284 delete ui->objectList->item (i); 282 delete ui->objectList->item (i);
285 283
286 ui->objectList->clear(); 284 ui->objectList->clear();
287 285
288 for (LDObject* obj : LDFile::current()->objects()) { 286 for (LDObject* obj : LDFile::current()->objects())
289 str descr; 287 { str descr;
290 288
291 switch (obj->getType()) { 289 switch (obj->getType())
292 case LDObject::Comment: 290 { case LDObject::Comment:
293 descr = static_cast<LDComment*> (obj)->text; 291 { descr = static_cast<LDComment*> (obj)->text;
294 292
295 // Remove leading whitespace 293 // Remove leading whitespace
296 while (descr[0] == ' ') 294 while (descr[0] == ' ')
297 descr.remove (0, 1); 295 descr.remove (0, 1);
298 break; 296 } break;
299 297
300 case LDObject::Empty: 298 case LDObject::Empty:
301 break; // leave it empty 299 break; // leave it empty
302 300
303 case LDObject::Line: 301 case LDObject::Line:
304 case LDObject::Triangle: 302 case LDObject::Triangle:
305 case LDObject::Quad: 303 case LDObject::Quad:
306 case LDObject::CndLine: 304 case LDObject::CndLine:
307 for (short i = 0; i < obj->vertices(); ++i) { 305 { for (short i = 0; i < obj->vertices(); ++i)
308 if (i != 0) 306 { if (i != 0)
309 descr += ", "; 307 descr += ", ";
310 308
311 descr += obj->getVertex (i).stringRep (true); 309 descr += obj->getVertex (i).stringRep (true);
310 }
311 } break;
312
313 case LDObject::Error:
314 { descr = fmt ("ERROR: %1", obj->raw());
315 } break;
316
317 case LDObject::Vertex:
318 { descr = static_cast<LDVertex*> (obj)->pos.stringRep (true);
319 } break;
320
321 case LDObject::Subfile:
322 { LDSubfile* ref = static_cast<LDSubfile*> (obj);
323
324 descr = fmt ("%1 %2, (", ref->fileInfo()->name(), ref->position().stringRep (true));
325
326 for (int i = 0; i < 9; ++i)
327 descr += fmt ("%1%2", ref->transform()[i], (i != 8) ? " " : "");
328
329 descr += ')';
330 } break;
331
332 case LDObject::BFC:
333 { descr = LDBFC::statements[static_cast<LDBFC*> (obj)->type];
334 } break;
335
336 case LDObject::Overlay:
337 { LDOverlay* ovl = static_cast<LDOverlay*> (obj);
338 descr = fmt ("[%1] %2 (%3, %4), %5 x %6", g_CameraNames[ovl->camera()],
339 basename (ovl->filename()), ovl->x(), ovl->y(), ovl->width(), ovl->height());
312 } 340 }
313 break; 341 break;
314 342
315 case LDObject::Error: 343 default:
316 descr = fmt ("ERROR: %1", obj->raw()); 344 { descr = obj->typeName();
317 break; 345 } break;
318 346 }
319 case LDObject::Vertex: 347
320 descr = static_cast<LDVertex*> (obj)->pos.stringRep (true);
321 break;
322
323 case LDObject::Subfile:
324 {
325 LDSubfile* ref = static_cast<LDSubfile*> (obj);
326
327 descr = fmt ("%1 %2, (", ref->fileInfo()->name(),
328 ref->position().stringRep (true));
329
330 for (short i = 0; i < 9; ++i)
331 descr += fmt ("%1%2", ftoa (ref->transform()[i]),
332 (i != 8) ? " " : "");
333
334 descr += ')';
335 }
336 break;
337
338 case LDObject::BFC:
339 descr = LDBFC::statements[static_cast<LDBFC*> (obj)->type];
340 break;
341
342 case LDObject::Overlay:
343 {
344 LDOverlay* ovl = static_cast<LDOverlay*> (obj);
345 descr = fmt ("[%1] %2 (%3, %4), %5 x %6", g_CameraNames[ovl->camera()],
346 basename (ovl->filename()), ovl->x(), ovl->y(), ovl->width(), ovl->height());
347 }
348 break;
349
350 default:
351 descr = obj->typeName();
352 break;
353 }
354
355 // Put it into brackets if it's hidden
356 if (obj->hidden())
357 descr = fmt ("[[ %1 ]]", descr);
358
359 QListWidgetItem* item = new QListWidgetItem (descr); 348 QListWidgetItem* item = new QListWidgetItem (descr);
360 item->setIcon (getIcon (obj->typeName())); 349 item->setIcon (getIcon (obj->typeName()));
361 350
351 // Use italic font if hidden
352 if (obj->hidden())
353 { QFont font = item->font();
354 font.setItalic (true);
355 item->setFont (font);
356 }
357
362 // Color gibberish orange on red so it stands out. 358 // Color gibberish orange on red so it stands out.
363 if (obj->getType() == LDObject::Error) { 359 if (obj->getType() == LDObject::Error)
364 item->setBackground (QColor ("#AA0000")); 360 { item->setBackground (QColor ("#AA0000"));
365 item->setForeground (QColor ("#FFAA00")); 361 item->setForeground (QColor ("#FFAA00"));
366 } elif (lv_colorize && obj->isColored() && 362 }
367 obj->color() != maincolor && obj->color() != edgecolor) 363 elif (lv_colorize && obj->isColored() && obj->color() != maincolor && obj->color() != edgecolor)
368 { 364 { // If the object isn't in the main or edge color, draw this
369 // If the object isn't in the main or edge color, draw this
370 // list entry in said color. 365 // list entry in said color.
371 LDColor* col = getColor (obj->color()); 366 LDColor* col = getColor (obj->color());
367
372 if (col) 368 if (col)
373 item->setForeground (col->faceColor); 369 item->setForeground (col->faceColor);
374 } 370 }
375 371
376 obj->qObjListEntry = item; 372 obj->qObjListEntry = item;
377 ui->objectList->insertItem (ui->objectList->count(), item); 373 ui->objectList->insertItem (ui->objectList->count(), item);
378 } 374 }
379 375
380 g_bSelectionLocked = false; 376 g_bSelectionLocked = false;
381 updateSelection(); 377 updateSelection();
382 scrollToSelection(); 378 scrollToSelection();
383 } 379 }
384 380
385 // ============================================================================= 381 // =============================================================================
386 // ----------------------------------------------------------------------------- 382 // -----------------------------------------------------------------------------
387 void ForgeWindow::scrollToSelection() { 383 void ForgeWindow::scrollToSelection()
388 if (m_sel.size() == 0) 384 { if (selection().isEmpty())
389 return; 385 return;
390 386
391 LDObject* obj = m_sel[m_sel.size() - 1]; 387 LDObject* obj = selection().last();
392 ui->objectList->scrollToItem (obj->qObjListEntry); 388 ui->objectList->scrollToItem (obj->qObjListEntry);
393 } 389 }
394 390
395 // ============================================================================= 391 // =============================================================================
396 // ----------------------------------------------------------------------------- 392 // -----------------------------------------------------------------------------
397 void ForgeWindow::slot_selectionChanged() { 393 void ForgeWindow::slot_selectionChanged()
398 if (g_bSelectionLocked == true || LDFile::current() == null) 394 { if (g_bSelectionLocked == true || LDFile::current() == null)
399 return; 395 return;
400 396
401 // Update the shared selection array, though don't do this if this was 397 // Update the shared selection array, though don't do this if this was
402 // called during GL picking, in which case the GL renderer takes care 398 // called during GL picking, in which case the GL renderer takes care
403 // of the selection. 399 // of the selection.
404 if (m_renderer->picking()) 400 if (m_renderer->picking())
405 return; 401 return;
406 402
407 List<LDObject*> priorSelection = m_sel; 403 QList<LDObject*> priorSelection = selection();
408 404
409 // Get the objects from the object list selection 405 // Get the objects from the object list selection
410 m_sel.clear(); 406 LDFile::current()->clearSelection();
411 const QList<QListWidgetItem*> items = ui->objectList->selectedItems(); 407 const QList<QListWidgetItem*> items = ui->objectList->selectedItems();
412 408
413 for (LDObject* obj : LDFile::current()->objects()) 409 for (LDObject* obj : LDFile::current()->objects())
414 for (QListWidgetItem* item : items) { 410 { for (QListWidgetItem* item : items)
415 if (item == obj->qObjListEntry) { 411 { if (item == obj->qObjListEntry)
416 m_sel << obj; 412 { obj->select();
417 break; 413 break;
418 } 414 }
419 } 415 }
420 416 }
417
421 // Update the GL renderer 418 // Update the GL renderer
422 for (LDObject* obj : priorSelection) { 419 QList<LDObject*> compound = priorSelection + selection();
423 obj->setSelected (false); 420 removeDuplicates (compound);
421
422 for (LDObject* obj : compound)
424 m_renderer->compileObject (obj); 423 m_renderer->compileObject (obj);
425 } 424
426
427 for (LDObject* obj : m_sel) {
428 obj->setSelected (true);
429 m_renderer->compileObject (obj);
430 }
431
432 m_renderer->update(); 425 m_renderer->update();
433 } 426 }
434 427
435 // ============================================================================= 428 // =============================================================================
436 // ----------------------------------------------------------------------------- 429 // -----------------------------------------------------------------------------
437 void ForgeWindow::slot_recentFile() { 430 void ForgeWindow::slot_recentFile()
438 QAction* qAct = static_cast<QAction*> (sender()); 431 { QAction* qAct = static_cast<QAction*> (sender());
439 openMainFile (qAct->text()); 432 openMainFile (qAct->text());
440 } 433 }
441 434
442 // ============================================================================= 435 // =============================================================================
443 // ----------------------------------------------------------------------------- 436 // -----------------------------------------------------------------------------
444 void ForgeWindow::slot_quickColor() { 437 void ForgeWindow::slot_quickColor()
445 beginAction (null); 438 { beginAction (null);
446 QToolButton* button = static_cast<QToolButton*> (sender()); 439 QToolButton* button = static_cast<QToolButton*> (sender());
447 LDColor* col = null; 440 LDColor* col = null;
448 441
449 for (const LDQuickColor& entry : m_quickColors) { 442 for (const LDQuickColor & entry : m_quickColors)
450 if (entry.toolButton() == button) { 443 { if (entry.toolButton() == button)
451 col = entry.color(); 444 { col = entry.color();
452 break; 445 break;
453 } 446 }
454 } 447 }
455 448
456 if (col == null) 449 if (col == null)
457 return; 450 return;
458 451
459 short newColor = col->index; 452 short newColor = col->index;
460 453
461 for (LDObject* obj : m_sel) { 454 for (LDObject* obj : selection())
462 if (obj->isColored() == false) 455 { if (obj->isColored() == false)
463 continue; // uncolored object 456 continue; // uncolored object
464 457
465 obj->setColor (newColor); 458 obj->setColor (newColor);
466 R()->compileObject (obj); 459 R()->compileObject (obj);
467 } 460 }
468 461
469 refresh(); 462 refresh();
470 endAction(); 463 endAction();
471 } 464 }
472 465
473 // ============================================================================= 466 // =============================================================================
474 // ----------------------------------------------------------------------------- 467 // -----------------------------------------------------------------------------
475 ulong ForgeWindow::getInsertionPoint() { 468 int ForgeWindow::getInsertionPoint()
476 if (m_sel.size() > 0) { 469 { // If we have a selection, put the item after it.
477 // If we have a selection, put the item after it. 470 if (!selection().isEmpty())
478 return (m_sel[m_sel.size() - 1]->getIndex()) + 1; 471 return selection().last()->getIndex() + 1;
479 } 472
480
481 // Otherwise place the object at the end. 473 // Otherwise place the object at the end.
482 return LDFile::current()->numObjs(); 474 return LDFile::current()->numObjs();
483 } 475 }
484 476
485 // ============================================================================= 477 // =============================================================================
486 // ----------------------------------------------------------------------------- 478 // -----------------------------------------------------------------------------
487 void ForgeWindow::fullRefresh() { 479 void ForgeWindow::fullRefresh()
488 buildObjList(); 480 { buildObjList();
489 m_renderer->hardRefresh(); 481 m_renderer->hardRefresh();
490 } 482 }
491 483
492 // ============================================================================= 484 // =============================================================================
493 // ----------------------------------------------------------------------------- 485 // -----------------------------------------------------------------------------
494 void ForgeWindow::refresh() { 486 void ForgeWindow::refresh()
495 buildObjList(); 487 { buildObjList();
496 m_renderer->update(); 488 m_renderer->update();
497 } 489 }
498 490
499 // ============================================================================= 491 // =============================================================================
500 // ----------------------------------------------------------------------------- 492 // -----------------------------------------------------------------------------
501 void ForgeWindow::updateSelection() { 493 void ForgeWindow::updateSelection()
502 g_bSelectionLocked = true; 494 { g_bSelectionLocked = true;
503 495
504 print ("1\n");
505 for (LDObject* obj : LDFile::current()->objects()) 496 for (LDObject* obj : LDFile::current()->objects())
506 obj->setSelected (false); 497 obj->setSelected (false);
507 498
508 print ("2\n");
509 ui->objectList->clearSelection(); 499 ui->objectList->clearSelection();
510 500
511 print ("3\n"); 501 for (LDObject* obj : selection())
512 for (LDObject* obj : m_sel) { 502 { if (obj->qObjListEntry == null)
513 if (obj->qObjListEntry == null)
514 continue; 503 continue;
515 504
516 obj->qObjListEntry->setSelected (true); 505 obj->qObjListEntry->setSelected (true);
517 obj->setSelected (true); 506 obj->setSelected (true);
518 } 507 }
519 508
520 print ("4\n");
521 g_bSelectionLocked = false; 509 g_bSelectionLocked = false;
522 slot_selectionChanged(); 510 slot_selectionChanged();
523 } 511 }
524 512
525 // ============================================================================= 513 // =============================================================================
526 // ----------------------------------------------------------------------------- 514 // -----------------------------------------------------------------------------
527 bool ForgeWindow::isSelected (LDObject* obj) { 515 short ForgeWindow::getSelectedColor()
528 LDObject* needle = obj->topLevelParent(); 516 { short result = -1;
529 517
530 for (LDObject* hay : m_sel) 518 for (LDObject* obj : selection())
531 if (hay == needle) 519 { if (obj->isColored() == false)
532 return true;
533
534 return false;
535 }
536
537 short ForgeWindow::getSelectedColor() {
538 short result = -1;
539
540 for (LDObject* obj : m_sel) {
541 if (obj->isColored() == false)
542 continue; // doesn't use color 520 continue; // doesn't use color
543 521
544 if (result != -1 && obj->color() != result) 522 if (result != -1 && obj->color() != result)
545 return -1; // No consensus in object color 523 return -1; // No consensus in object color
546 524
547 if (result == -1) 525 if (result == -1)
548 result = obj->color(); 526 result = obj->color();
549 } 527 }
550 528
551 return result; 529 return result;
552 } 530 }
553 531
554 // ============================================================================= 532 // =============================================================================
555 // ----------------------------------------------------------------------------- 533 // -----------------------------------------------------------------------------
556 LDObject::Type ForgeWindow::uniformSelectedType() { 534 LDObject::Type ForgeWindow::uniformSelectedType()
557 LDObject::Type result = LDObject::Unidentified; 535 { LDObject::Type result = LDObject::Unidentified;
558 536
559 for (LDObject* obj : m_sel) { 537 for (LDObject * obj : selection())
560 if (result != LDObject::Unidentified && obj->color() != result) 538 { if (result != LDObject::Unidentified && obj->color() != result)
561 return LDObject::Unidentified; 539 return LDObject::Unidentified;
562 540
563 if (result == LDObject::Unidentified) 541 if (result == LDObject::Unidentified)
564 result = obj->getType(); 542 result = obj->getType();
565 } 543 }
566 544
567 return result; 545 return result;
568 } 546 }
569 547
570 // ============================================================================= 548 // =============================================================================
571 // ----------------------------------------------------------------------------- 549 // -----------------------------------------------------------------------------
572 void ForgeWindow::closeEvent (QCloseEvent* ev) { 550 void ForgeWindow::closeEvent (QCloseEvent* ev)
573 // Check whether it's safe to close all files. 551 { // Check whether it's safe to close all files.
574 if (!safeToCloseAll()) { 552 if (!safeToCloseAll())
575 ev->ignore(); 553 { ev->ignore();
576 return; 554 return;
577 } 555 }
578 556
579 // Save the configuration before leaving so that, for instance, grid choice 557 // Save the configuration before leaving so that, for instance, grid choice
580 // is preserved across instances. 558 // is preserved across instances.
581 Config::save(); 559 Config::save();
582 560
583 ev->accept(); 561 ev->accept();
584 } 562 }
585 563
586 // ============================================================================= 564 // =============================================================================
587 // ----------------------------------------------------------------------------- 565 // -----------------------------------------------------------------------------
588 void ForgeWindow::spawnContextMenu (const QPoint pos) { 566 void ForgeWindow::spawnContextMenu (const QPoint pos)
589 const bool single = (g_win->sel().size() == 1); 567 { const bool single = (selection().size() == 1);
590 LDObject* singleObj = (single) ? g_win->sel()[0] : null; 568 LDObject* singleObj = (single) ? selection()[0] : null;
591 569
592 QMenu* contextMenu = new QMenu; 570 QMenu* contextMenu = new QMenu;
593 571
594 if (single && singleObj->getType() != LDObject::Empty) { 572 if (single && singleObj->getType() != LDObject::Empty)
595 contextMenu->addAction (ACTION (Edit)); 573 { contextMenu->addAction (ACTION (Edit));
596 contextMenu->addSeparator(); 574 contextMenu->addSeparator();
597 } 575 }
598 576
599 contextMenu->addAction (ACTION (Cut)); 577 contextMenu->addAction (ACTION (Cut));
600 contextMenu->addAction (ACTION (Copy)); 578 contextMenu->addAction (ACTION (Copy));
601 contextMenu->addAction (ACTION (Paste)); 579 contextMenu->addAction (ACTION (Paste));
602 contextMenu->addAction (ACTION (Delete)); 580 contextMenu->addAction (ACTION (Delete));
603 contextMenu->addSeparator(); 581 contextMenu->addSeparator();
604 contextMenu->addAction (ACTION (SetColor)); 582 contextMenu->addAction (ACTION (SetColor));
605 583
606 if (single) 584 if (single)
607 contextMenu->addAction (ACTION (EditRaw)); 585 contextMenu->addAction (ACTION (EditRaw));
608 586
609 contextMenu->addAction (ACTION (Borders)); 587 contextMenu->addAction (ACTION (Borders));
610 contextMenu->addAction (ACTION (SetOverlay)); 588 contextMenu->addAction (ACTION (SetOverlay));
611 contextMenu->addAction (ACTION (ClearOverlay)); 589 contextMenu->addAction (ACTION (ClearOverlay));
612 contextMenu->addAction (ACTION (ModeSelect)); 590 contextMenu->addAction (ACTION (ModeSelect));
613 contextMenu->addAction (ACTION (ModeDraw)); 591 contextMenu->addAction (ACTION (ModeDraw));
614 592 contextMenu->addAction (ACTION (ModeCircle));
615 if (R()->camera() != GL::Free) { 593
616 contextMenu->addSeparator(); 594 if (R()->camera() != GL::Free)
595 { contextMenu->addSeparator();
617 contextMenu->addAction (ACTION (SetDrawDepth)); 596 contextMenu->addAction (ACTION (SetDrawDepth));
618 } 597 }
619 598
620 contextMenu->exec (pos); 599 contextMenu->exec (pos);
621 } 600 }
622 601
623 // ============================================================================= 602 // =============================================================================
624 // ----------------------------------------------------------------------------- 603 // -----------------------------------------------------------------------------
625 void ForgeWindow::deleteObjVector (List<LDObject*> objs) { 604 void ForgeWindow::deleteObjVector (QList<LDObject*> objs)
626 for (LDObject* obj : objs) { 605 { for (LDObject * obj : objs)
627 LDFile::current()->forgetObject (obj); 606 { LDFile::current()->forgetObject (obj);
628 delete obj; 607 delete obj;
629 } 608 }
630 } 609 }
631 610
632 // ============================================================================= 611 // =============================================================================
633 // ----------------------------------------------------------------------------- 612 // -----------------------------------------------------------------------------
634 void ForgeWindow::deleteByColor (const short colnum) { 613 void ForgeWindow::deleteByColor (const short colnum)
635 List<LDObject*> objs; 614 { QList<LDObject*> objs;
636 for (LDObject* obj : LDFile::current()->objects()) { 615
637 if (!obj->isColored() || obj->color() != colnum) 616 for (LDObject * obj : LDFile::current()->objects())
617 { if (!obj->isColored() || obj->color() != colnum)
638 continue; 618 continue;
639 619
640 objs << obj; 620 objs << obj;
641 } 621 }
642 622
643 deleteObjVector (objs); 623 deleteObjVector (objs);
644 } 624 }
645 625
646 // ============================================================================= 626 // =============================================================================
647 // ----------------------------------------------------------------------------- 627 // -----------------------------------------------------------------------------
648 void ForgeWindow::updateEditModeActions() { 628 void ForgeWindow::updateEditModeActions()
649 const EditMode mode = R()->editMode(); 629 { const EditMode mode = R()->editMode();
650 ACTION (ModeSelect)->setChecked (mode == Select); 630 ACTION (ModeSelect)->setChecked (mode == Select);
651 ACTION (ModeDraw)->setChecked (mode == Draw); 631 ACTION (ModeDraw)->setChecked (mode == Draw);
652 } 632 ACTION (ModeCircle)->setChecked (mode == CircleMode);
653 633 }
654 // ============================================================================= 634
655 // ----------------------------------------------------------------------------- 635 // =============================================================================
656 void ForgeWindow::slot_editObject (QListWidgetItem* listitem) { 636 // -----------------------------------------------------------------------------
657 LDObject* obj = null; 637 void ForgeWindow::slot_editObject (QListWidgetItem* listitem)
658 for (LDObject* it : LDFile::current()->objects()) { 638 { LDObject* obj = null;
659 if (it->qObjListEntry == listitem) { 639
660 obj = it; 640 for (LDObject* it : LDFile::current()->objects())
641 { if (it->qObjListEntry == listitem)
642 { obj = it;
661 break; 643 break;
662 } 644 }
663 } 645 }
664 646
665 AddObjectDialog::staticDialog (obj->getType(), obj); 647 AddObjectDialog::staticDialog (obj->getType(), obj);
666 } 648 }
667 649
668 // ============================================================================= 650 // =============================================================================
669 // ----------------------------------------------------------------------------- 651 // -----------------------------------------------------------------------------
670 void ForgeWindow::primitiveLoaderStart (ulong max) { 652 void ForgeWindow::primitiveLoaderStart (int max)
671 m_primLoaderWidget->show(); 653 { m_primLoaderWidget->show();
672 m_primLoaderBar->setRange (0, max); 654 m_primLoaderBar->setRange (0, max);
673 m_primLoaderBar->setValue (0); 655 m_primLoaderBar->setValue (0);
674 m_primLoaderBar->setFormat ("%p%"); 656 m_primLoaderBar->setFormat ("%p%");
675 } 657 }
676 658
677 // ============================================================================= 659 // =============================================================================
678 // ----------------------------------------------------------------------------- 660 // -----------------------------------------------------------------------------
679 void ForgeWindow::primitiveLoaderUpdate (ulong prog) { 661 void ForgeWindow::primitiveLoaderUpdate (int prog)
680 m_primLoaderBar->setValue (prog); 662 { m_primLoaderBar->setValue (prog);
681 } 663 }
682 664
683 // ============================================================================= 665 // =============================================================================
684 // ----------------------------------------------------------------------------- 666 // -----------------------------------------------------------------------------
685 void ForgeWindow::primitiveLoaderEnd() { 667 void ForgeWindow::primitiveLoaderEnd()
686 QTimer* hidetimer = new QTimer; 668 { QTimer* hidetimer = new QTimer;
687 connect (hidetimer, SIGNAL (timeout()), m_primLoaderWidget, SLOT (hide())); 669 connect (hidetimer, SIGNAL (timeout()), m_primLoaderWidget, SLOT (hide()));
688 hidetimer->setSingleShot (true); 670 hidetimer->setSingleShot (true);
689 hidetimer->start (1500); 671 hidetimer->start (1500);
690 m_primLoaderBar->setFormat (tr ("Done")); 672 m_primLoaderBar->setFormat (tr ("Done"));
691 log (tr ("Primitives scanned: %1 primitives listed"), m_primLoaderBar->value()); 673 log (tr ("Primitives scanned: %1 primitives listed"), m_primLoaderBar->value());
692 } 674 }
693 675
694 // ============================================================================= 676 // =============================================================================
695 // ----------------------------------------------------------------------------- 677 // -----------------------------------------------------------------------------
696 void ForgeWindow::save (LDFile* f, bool saveAs) { 678 void ForgeWindow::save (LDFile* f, bool saveAs)
697 str path = f->name(); 679 { str path = f->name();
698 680
699 if (path.length() == 0 || saveAs) { 681 if (saveAs || path.isEmpty())
700 path = QFileDialog::getSaveFileName (g_win, tr ("Save As"), 682 { path = QFileDialog::getSaveFileName (g_win, tr ("Save As"),
701 LDFile::current()->name(), tr ("LDraw files (*.dat *.ldr)")); 683 (f->name().isEmpty()) ? f->name() : f->defaultName(), tr ("LDraw files (*.dat *.ldr)"));
702 684
703 if (path.length() == 0) { 685 if (path.isEmpty())
704 // User didn't give a file name. This happens if the user cancelled 686 { // User didn't give a file name, abort.
705 // saving in the save file dialog. Abort.
706 return; 687 return;
707 } 688 }
708 } 689 }
709 690
710 if (f->save (path)) { 691 if (f->save (path))
711 f->setName (path); 692 { f->setName (path);
712 693
713 if (f == LDFile::current()) 694 if (f == LDFile::current())
714 g_win->updateTitle(); 695 g_win->updateTitle();
715 696
716 log ("Saved to %1.", path); 697 log ("Saved to %1.", path);
717 698
718 // Add it to recent files 699 // Add it to recent files
719 addRecentFile (path); 700 addRecentFile (path);
720 } else { 701 }
721 str message = fmt (tr ("Failed to save to %1: %2"), path, strerror (errno)); 702 else
722 703 { str message = fmt (tr ("Failed to save to %1: %2"), path, strerror (errno));
704
723 // Tell the user the save failed, and give the option for saving as with it. 705 // Tell the user the save failed, and give the option for saving as with it.
724 QMessageBox dlg (QMessageBox::Critical, tr ("Save Failure"), message, QMessageBox::Close, g_win); 706 QMessageBox dlg (QMessageBox::Critical, tr ("Save Failure"), message, QMessageBox::Close, g_win);
725 707
726 // Add a save-as button 708 // Add a save-as button
727 QPushButton* saveAsBtn = new QPushButton (tr ("Save As")); 709 QPushButton* saveAsBtn = new QPushButton (tr ("Save As"));
728 saveAsBtn->setIcon (getIcon ("file-save-as")); 710 saveAsBtn->setIcon (getIcon ("file-save-as"));
729 dlg.addButton (saveAsBtn, QMessageBox::ActionRole); 711 dlg.addButton (saveAsBtn, QMessageBox::ActionRole);
730 dlg.setDefaultButton (QMessageBox::Close); 712 dlg.setDefaultButton (QMessageBox::Close);
731 dlg.exec(); 713 dlg.exec();
732 714
733 if (dlg.clickedButton() == saveAsBtn) 715 if (dlg.clickedButton() == saveAsBtn)
734 save (f, true); // yay recursion! 716 save (f, true); // yay recursion!
735 } 717 }
736 } 718 }
737 719
738 void ForgeWindow::addMessage (str msg) { 720 void ForgeWindow::addMessage (str msg)
739 m_msglog->addLine (msg); 721 { m_msglog->addLine (msg);
740 } 722 }
741 723
742 // ============================================================================ 724 // ============================================================================
743 void ObjectList::contextMenuEvent (QContextMenuEvent* ev) { 725 void ObjectList::contextMenuEvent (QContextMenuEvent* ev)
744 g_win->spawnContextMenu (ev->globalPos()); 726 { g_win->spawnContextMenu (ev->globalPos());
745 } 727 }
746 728
747 // ============================================================================= 729 // =============================================================================
748 // ----------------------------------------------------------------------------- 730 // -----------------------------------------------------------------------------
749 QPixmap getIcon (str iconName) { 731 QPixmap getIcon (str iconName)
750 return (QPixmap (fmt (":/icons/%1.png", iconName))); 732 { return (QPixmap (fmt (":/icons/%1.png", iconName)));
751 } 733 }
752 734
753 // ============================================================================= 735 // =============================================================================
754 bool confirm (str msg) { 736 bool confirm (str msg)
755 return confirm (ForgeWindow::tr ("Confirm"), msg); 737 { return confirm (ForgeWindow::tr ("Confirm"), msg);
756 } 738 }
757 739
758 bool confirm (str title, str msg) { 740 bool confirm (str title, str msg)
759 return QMessageBox::question (g_win, title, msg, 741 { return QMessageBox::question (g_win, title, msg,
760 (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes; 742 (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes;
761 } 743 }
762 744
763 // ============================================================================= 745 // =============================================================================
764 void critical (str msg) { 746 void critical (str msg)
765 QMessageBox::critical (g_win, ForgeWindow::tr("Error"), msg, 747 { QMessageBox::critical (g_win, ForgeWindow::tr ("Error"), msg,
766 (QMessageBox::Close), QMessageBox::Close); 748 (QMessageBox::Close), QMessageBox::Close);
767 } 749 }
768 750
769 // ============================================================================= 751 // =============================================================================
770 QIcon makeColorIcon (LDColor* colinfo, const ushort size) { 752 QIcon makeColorIcon (LDColor* colinfo, const int size)
771 // Create an image object and link a painter to it. 753 { // Create an image object and link a painter to it.
772 QImage img (size, size, QImage::Format_ARGB32); 754 QImage img (size, size, QImage::Format_ARGB32);
773 QPainter paint (&img); 755 QPainter paint (&img);
774 756
775 QColor col = colinfo->faceColor; 757 QColor col = colinfo->faceColor;
776 if (colinfo->index == maincolor) { 758
777 // Use the user preferences for main color here 759 if (colinfo->index == maincolor)
760 { // Use the user preferences for main color here
778 col = gl_maincolor.value; 761 col = gl_maincolor.value;
779 col.setAlphaF (gl_maincolor_alpha); 762 col.setAlphaF (gl_maincolor_alpha);
780 } 763 }
781 764
782 // Paint the icon 765 // Paint the icon
783 paint.fillRect (QRect (0, 0, size, size), colinfo->edgeColor); 766 paint.fillRect (QRect (0, 0, size, size), colinfo->edgeColor);
784 paint.drawPixmap (QRect (1, 1, size - 2, size - 2), getIcon ("checkerboard"), QRect (0, 0, 8, 8)); 767 paint.drawPixmap (QRect (1, 1, size - 2, size - 2), getIcon ("checkerboard"), QRect (0, 0, 8, 8));
785 paint.fillRect (QRect (1, 1, size - 2, size - 2), col); 768 paint.fillRect (QRect (1, 1, size - 2, size - 2), col);
786 return QIcon (QPixmap::fromImage (img)); 769 return QIcon (QPixmap::fromImage (img));
787 } 770 }
788 771
789 // ============================================================================= 772 // =============================================================================
790 void makeColorSelector (QComboBox* box) { 773 void makeColorSelector (QComboBox* box)
791 std::map<short, ulong> counts; 774 { std::map<int, int> counts;
792 775
793 for (LDObject* obj : LDFile::current()->objects()) { 776 for (LDObject * obj : LDFile::current()->objects())
794 if (!obj->isColored()) 777 { if (!obj->isColored())
795 continue; 778 continue;
796 779
797 if (counts.find (obj->color()) == counts.end()) 780 if (counts.find (obj->color()) == counts.end())
798 counts[obj->color()] = 1; 781 counts[obj->color()] = 1;
799 else 782 else
800 counts[obj->color()]++; 783 counts[obj->color()]++;
801 } 784 }
802 785
803 box->clear(); 786 box->clear();
804 ulong row = 0; 787 int row = 0;
805 for (const auto& pair : counts) { 788
806 LDColor* col = getColor (pair.first); 789 for (const auto & pair : counts)
790 { LDColor* col = getColor (pair.first);
807 assert (col != null); 791 assert (col != null);
808 792
809 QIcon ico = makeColorIcon (col, 16); 793 QIcon ico = makeColorIcon (col, 16);
810 box->addItem (ico, fmt ("[%1] %2 (%3 object%4)", 794 box->addItem (ico, fmt ("[%1] %2 (%3 object%4)",
811 pair.first, col->name, pair.second, plural (pair.second))); 795 pair.first, col->name, pair.second, plural (pair.second)));
812 box->setItemData (row, pair.first); 796 box->setItemData (row, pair.first);
813 797
814 ++row; 798 ++row;
815 } 799 }
816 } 800 }
817 801
818 void ForgeWindow::setStatusBarText (str text) { 802 void ForgeWindow::setStatusBarText (str text)
819 statusBar()->showMessage (text); 803 { statusBar()->showMessage (text);
820 } 804 }
821 805
822 void ForgeWindow::clearSelection() { 806 Ui_LDForgeUI* ForgeWindow::interface() const
823 m_sel.clear(); 807 { return ui;
824 }
825
826 Ui_LDForgeUI* ForgeWindow::interface() const {
827 return ui;
828 } 808 }
829 809
830 #define act(N) QAction* ForgeWindow::action##N() { return ui->action##N; } 810 #define act(N) QAction* ForgeWindow::action##N() { return ui->action##N; }
831 #include "actions.h" 811 #include "actions.h"
832 812
833 void ForgeWindow::updateFileList() { 813 void ForgeWindow::updateFileList()
834 ui->fileList->clear(); 814 { ui->fileList->clear();
835 815
836 for (LDFile* f : g_loadedFiles) { 816 for (LDFile* f : g_loadedFiles)
837 // Don't list implicit files unless explicitly desired. 817 { // Don't list implicit files unless explicitly desired.
838 if (f->implicit() && !gui_implicitfiles) 818 if (f->implicit() && !gui_implicitfiles)
839 continue; 819 continue;
840 820
841 // Add an item to the list for this file and store a pointer to it in 821 // Add an item to the list for this file and store a pointer to it in
842 // the file, so we can find files by the list item. 822 // the file, so we can find files by the list item.
843 ui->fileList->addItem (""); 823 ui->fileList->addItem ("");
844 QListWidgetItem* item = ui->fileList->item (ui->fileList->count() - 1); 824 QListWidgetItem* item = ui->fileList->item (ui->fileList->count() - 1);
845 f->setListItem (item); 825 f->setListItem (item);
846 826
847 updateFileListItem (f); 827 updateFileListItem (f);
848 } 828 }
849 } 829 }
850 830
851 void ForgeWindow::updateFileListItem (LDFile* f) { 831 void ForgeWindow::updateFileListItem (LDFile* f)
852 if (f->listItem() == null) { 832 { if (f->listItem() == null)
853 // We don't have a list item for this file, so the list either doesn't 833 { // We don't have a list item for this file, so the list either doesn't
854 // exist yet or is out of date. Build the list now. 834 // exist yet or is out of date. Build the list now.
855 updateFileList(); 835 updateFileList();
856 return; 836 return;
857 } 837 }
858 838
859 // If this is the current file, it also needs to be the selected item on 839 // If this is the current file, it also needs to be the selected item on
860 // the list. 840 // the list.
861 if (f == LDFile::current()) 841 if (f == LDFile::current())
862 ui->fileList->setCurrentItem (f->listItem()); 842 ui->fileList->setCurrentItem (f->listItem());
863 843
864 // If we list implicit files, draw them with a shade of gray to make them 844 // If we list implicit files, draw them with a shade of gray to make them
865 // distinct. 845 // distinct.
866 if (f->implicit()) 846 if (f->implicit())
867 f->listItem()->setForeground (QColor (96, 96, 96)); 847 f->listItem()->setForeground (QColor (96, 96, 96));
868 848
869 f->listItem()->setText (f->getShortName()); 849 f->listItem()->setText (f->getShortName());
870 850
871 // If the file has unsaved changes, draw a little icon next to it to mark that. 851 // If the file has unsaved changes, draw a little icon next to it to mark that.
872 f->listItem()->setIcon (f->hasUnsavedChanges() ? getIcon ("file-save") : QIcon()); 852 f->listItem()->setIcon (f->hasUnsavedChanges() ? getIcon ("file-save") : QIcon());
873 } 853 }
874 854
875 void ForgeWindow::beginAction (QAction* act) { 855 void ForgeWindow::beginAction (QAction* act)
876 // Open the history so we can record the edits done during this action. 856 { // Open the history so we can record the edits done during this action.
877 if (act != ACTION (Undo) && act != ACTION (Redo) && act != ACTION (Open)) 857 if (act != ACTION (Undo) && act != ACTION (Redo) && act != ACTION (Open))
878 LDFile::current()->openHistory(); 858 LDFile::current()->openHistory();
879 } 859 }
880 860
881 void ForgeWindow::endAction() { 861 void ForgeWindow::endAction()
882 // Close the history now. 862 { // Close the history now.
883 LDFile::current()->closeHistory(); 863 LDFile::current()->closeHistory();
884 864
885 // Update the list item of the current file - we may need to draw an icon 865 // Update the list item of the current file - we may need to draw an icon
886 // now that marks it as having unsaved changes. 866 // now that marks it as having unsaved changes.
887 updateFileListItem (LDFile::current()); 867 updateFileListItem (LDFile::current());
888 } 868 }
889 869
890 // ============================================================================= 870 // =============================================================================
891 // A file is selected from the list of files on the left of the screen. Find out 871 // A file is selected from the list of files on the left of the screen. Find out
892 // which file was picked and change to it. 872 // which file was picked and change to it.
893 void ForgeWindow::changeCurrentFile() { 873 void ForgeWindow::changeCurrentFile()
894 LDFile* f = null; 874 { LDFile* f = null;
895 QListWidgetItem* item = ui->fileList->currentItem(); 875 QListWidgetItem* item = ui->fileList->currentItem();
896 876
897 // Find the file pointer of the item that was selected. 877 // Find the file pointer of the item that was selected.
898 for (LDFile* it : g_loadedFiles) { 878 for (LDFile * it : g_loadedFiles)
899 if (it->listItem() == item) { 879 { if (it->listItem() == item)
900 f = it; 880 { f = it;
901 break; 881 break;
902 } 882 }
903 } 883 }
904 884
905 // If we picked the same file we're currently on, we don't need to do 885 // If we picked the same file we're currently on, we don't need to do
906 // anything. 886 // anything.
907 if (!f || f == LDFile::current()) 887 if (!f || f == LDFile::current())
908 return; 888 return;
909 889
910 LDFile::setCurrent (f); 890 LDFile::setCurrent (f);
911 } 891 }
912 892
913 void ForgeWindow::refreshObjectList() { 893 void ForgeWindow::refreshObjectList()
894 {
914 #if 0 895 #if 0
915 ui->objectList->clear(); 896 ui->objectList->clear();
916 LDFile* f = LDFile::current(); 897 LDFile* f = LDFile::current();
917 898
918 for (LDObject* obj : *f) 899 for (LDObject * obj : *f)
919 ui->objectList->addItem (obj->qObjListEntry); 900 ui->objectList->addItem (obj->qObjListEntry);
901
920 #endif 902 #endif
921 903
922 buildObjList(); 904 buildObjList();
923 } 905 }
924 906
925 QImage imageFromScreencap (uchar* data, ushort w, ushort h) { 907 QImage imageFromScreencap (uchar* data, int w, int h)
926 // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well. 908 { // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well.
927 return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped().mirrored(); 909 return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped().mirrored();
928 } 910 }
929 911
930 // ============================================================================= 912 // =============================================================================
931 // ----------------------------------------------------------------------------- 913 // -----------------------------------------------------------------------------
932 LDQuickColor::LDQuickColor (LDColor* color, QToolButton* toolButton) : 914 LDQuickColor::LDQuickColor (LDColor* color, QToolButton* toolButton) :
933 m_color (color), 915 m_color (color),
934 m_toolButton (toolButton) {} 916 m_toolButton (toolButton) {}
935 917
936 LDQuickColor LDQuickColor::getSeparator() { 918 LDQuickColor LDQuickColor::getSeparator()
937 return LDQuickColor (null, null); 919 { return LDQuickColor (null, null);
938 } 920 }
939 921
940 bool LDQuickColor::isSeparator() const { 922 bool LDQuickColor::isSeparator() const
941 return color() == null; 923 { return color() == null;
942 } 924 }
943 #include "moc_gui.cpp"

mercurial