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 = ⁢ |
|
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 // ============================================================================= |
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 } |
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 |
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 // ============================================================================= |