]> Shamusworld >> Repos - architektonas/blob - src/applicationwindow.cpp
Fix for missing ampersand in QApplication.
[architektonas] / src / applicationwindow.cpp
1 //
2 // applicationwindow.cpp: Architektonas
3 //
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -------------------------------------------------------------
12 // JLH  03/22/2011  Created this file
13 // JLH  09/29/2011  Added simple zoom in/out functionality
14 // JLH  10/03/2011  Fixed zoom tool to zoom in/out from center of screen
15 //
16
17 // FIXED:
18 //
19 //
20 // STILL TO BE DONE:
21 //
22 //
23
24 // Uncomment this for debugging...
25 //#define DEBUG
26 //#define DEBUGFOO                      // Various tool debugging...
27 //#define DEBUGTP                               // Toolpalette debugging...
28
29 #include "applicationwindow.h"
30
31 #include "about.h"
32 #include "drawingview.h"
33 #include "generaltab.h"
34 #include "painter.h"
35 #include "settingsdialog.h"
36
37
38 ApplicationWindow::ApplicationWindow(): settings("Underground Software", "Architektonas")
39 {
40         drawing = new DrawingView(this);
41         drawing->setMouseTracking(true);                // We want *all* mouse events...!
42         setCentralWidget(drawing);
43
44         aboutWin = new AboutWindow(this);
45
46 //      ((TTEdit *)qApp)->charWnd = new CharWindow(this);
47
48         setWindowIcon(QIcon(":/res/atns-icon.png"));
49         setWindowTitle("Architektonas");
50
51         CreateActions();
52         CreateMenus();
53         CreateToolbars();
54
55         //      Create status bar
56         zoomIndicator = new QLabel("Grid: 12.0\" Zoom: 12.5%");
57         statusBar()->addPermanentWidget(zoomIndicator);
58         statusBar()->showMessage(tr("Ready"));
59
60         ReadSettings();
61
62 //      connect(textEdit->document(), SIGNAL(contentsChanged()),
63 //                      this, SLOT(documentWasModified()));
64
65 //      setCurrentFile("");
66         setUnifiedTitleAndToolBarOnMac(true);
67
68 //      ((TTEdit *)qApp)->charWnd->show();//eh?
69         Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
70 }
71
72 void ApplicationWindow::closeEvent(QCloseEvent * event)
73 {
74         WriteSettings();
75         event->accept();                                                        // Use ignore() if can't close for some reason
76         //Do we have a memory leak here if we don't delete the font in the Object???
77 }
78
79 //void ApplicationWindow::FileOpen(void)
80 //{
81 //}
82
83 void ApplicationWindow::SnapToGridTool(void)
84 {
85         Object::SetSnapMode(snapToGridAct->isChecked());
86 }
87
88 void ApplicationWindow::FixAngle(void)
89 {
90         Object::SetFixedAngle(fixAngleAct->isChecked());
91 }
92
93 void ApplicationWindow::FixLength(void)
94 {
95         Object::SetFixedLength(fixLengthAct->isChecked());
96 }
97
98 // We want certain tools to be exclusive, and this approach isn't working correctly...
99 void ApplicationWindow::DeleteTool(void)
100 {
101         
102         ClearUIToolStatesExcept(deleteAct);
103         SetInternalToolStates();
104 }
105
106 void ApplicationWindow::DimensionTool(void)
107 {
108         ClearUIToolStatesExcept(addDimensionAct);
109         SetInternalToolStates();
110 }
111
112 void ApplicationWindow::RotateTool(void)
113 {
114         ClearUIToolStatesExcept(rotateAct);
115         SetInternalToolStates();
116 }
117
118 void ApplicationWindow::AddLineTool(void)
119 {
120         ClearUIToolStatesExcept(addLineAct);
121         SetInternalToolStates();
122 }
123
124 void ApplicationWindow::AddCircleTool(void)
125 {
126         ClearUIToolStatesExcept(addCircleAct);
127         SetInternalToolStates();
128 }
129
130 void ApplicationWindow::AddArcTool(void)
131 {
132         ClearUIToolStatesExcept(addArcAct);
133         SetInternalToolStates();
134 }
135
136 void ApplicationWindow::AddPolygonTool(void)
137 {
138         ClearUIToolStatesExcept(addPolygonAct);
139         SetInternalToolStates();
140 }
141
142 void ApplicationWindow::ZoomInTool(void)
143 {
144         double zoomFactor = 2.0;
145 /*
146 We need to find the center of the screen, then figure out where the new corner
147 will be in the zoomed in window.
148
149 So we know in Qt coords, the center is found via:
150 size.width()  / 2 --> xCenter
151 size.height() / 2 --> yCenter
152
153 transform x/yCenter to Cartesian coordinates. So far, so good.
154
155 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
156 (after subtracting from center, that is...)
157 */
158         QSize size = drawing->size();
159         Vector center(size.width() / 2.0, size.height() / 2.0);
160 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
161         center = Painter::QtToCartesianCoords(center);
162 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
163         Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
164 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
165         Painter::origin = newOrigin;
166
167 //printf("Zoom in... level going from %02f to ", Painter::zoom);
168         // This just zooms leaving origin intact... should zoom in at the current center! [DONE]
169         Painter::zoom *= zoomFactor;
170         drawing->gridSpacing = 12.0 / Painter::zoom;
171         zoomIndicator->setText(QString("Grid: %2\" Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM).arg(drawing->gridSpacing));
172         drawing->UpdateGridBackground();
173         drawing->update();
174 }
175
176 void ApplicationWindow::ZoomOutTool(void)
177 {
178 /*
179 Ok, real example.
180 center = (436, 311)
181 origin = (223, 160.5)
182 newOrigin should be (-10, -10)
183 Why isn't it?
184
185 center - origin = (213, 150.5)
186 origin - center = (-213, -150.5)
187 x 2 = (-426, -301)
188 + center = (-10, -10)
189
190 */
191         double zoomFactor = 2.0;
192         QSize size = drawing->size();
193         Vector center(size.width() / 2.0, size.height() / 2.0);
194 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
195         center = Painter::QtToCartesianCoords(center);
196 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
197 //      Vector newOrigin = (center - Painter::origin) * zoomFactor;
198 //      Vector newOrigin = center - (Painter::origin * zoomFactor);
199         Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
200 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
201         Painter::origin = newOrigin;
202 //printf("Zoom out...\n");
203         // This just zooms leaving origin intact... should zoom out at the current center! [DONE]
204         Painter::zoom /= zoomFactor;
205         drawing->gridSpacing = 12.0 / Painter::zoom;
206         zoomIndicator->setText(QString("Grid: %2\" Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM).arg(drawing->gridSpacing));
207         drawing->UpdateGridBackground();
208         drawing->update();
209 }
210
211 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
212 {
213         if (exception != addArcAct)
214                 addArcAct->setChecked(false);
215
216         if (exception != addCircleAct)
217                 addCircleAct->setChecked(false);
218
219         if (exception != addDimensionAct)
220                 addDimensionAct->setChecked(false);
221
222         if (exception != addLineAct)
223                 addLineAct->setChecked(false);
224
225         if (exception != addPolygonAct)
226                 addPolygonAct->setChecked(false);
227
228         if (exception != deleteAct)
229                 deleteAct->setChecked(false);
230
231         if (exception != rotateAct)
232                 rotateAct->setChecked(false);
233 }
234
235 void ApplicationWindow::SetInternalToolStates(void)
236 {
237         Object::SetDeleteActive(deleteAct->isChecked());
238         Object::SetDimensionActive(addDimensionAct->isChecked());
239         drawing->SetRotateToolActive(rotateAct->isChecked());
240         drawing->SetAddLineToolActive(addLineAct->isChecked());
241         drawing->SetAddCircleToolActive(addCircleAct->isChecked());
242 }
243
244 void ApplicationWindow::HelpAbout(void)
245 {
246         aboutWin->show();
247 }
248
249 void ApplicationWindow::Settings(void)
250 {
251         SettingsDialog dlg(this);
252         dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
253
254         if (dlg.exec() == false)
255                 return;
256
257         // Deal with stuff here (since user hit "OK" button...)
258         drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
259         WriteSettings();
260 }
261
262 void ApplicationWindow::CreateActions(void)
263 {
264         exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
265                 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
266         connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
267
268         snapToGridAct = CreateAction(tr("Snap To &Grid"), tr("Snap To Grid"), tr("Snaps mouse cursor to the visible grid when moving/creating objects."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("S")), true);
269         connect(snapToGridAct, SIGNAL(triggered()), this, SLOT(SnapToGridTool()));
270
271         fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
272                 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
273         connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
274
275         fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
276                 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
277         connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
278
279         deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(), true);
280         connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
281
282         addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
283         connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
284
285         addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
286         connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
287
288         addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
289         connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
290
291         addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
292         connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool()));
293
294         addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
295         connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool()));
296
297         aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
298         connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
299
300         rotateAct = CreateAction(tr("&Rotate Objects"), tr("Rotate"), tr("Rotate object(s) around an arbitrary center."), QIcon(":/res/rotate-tool.png"), QKeySequence(tr("R,O")), true);
301         connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
302
303         zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
304         connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
305
306         zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
307         connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
308
309         fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+n")));
310
311         fileOpenAct = CreateAction(tr("&Open Drawing"), tr("Open Drawing"), tr("Opens an existing drawing from a file."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+o")));
312
313         fileSaveAct = CreateAction(tr("&Save Drawing"), tr("Save Drawing"), tr("Saves the current drawing to a file."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+s")));
314
315         fileSaveAsAct = CreateAction(tr("Save Drawing &As"), tr("Save As"), tr("Saves the current drawing to a file with a different name."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+Shift+s")));
316
317         fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+w")));
318
319         settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/generic-tool.png"), QKeySequence());
320         connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
321
322 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
323 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
324 /*      QActionGroup * group = new QActionGroup(this);
325         group->addAction(deleteAct);
326         group->addAction(addDimensionAct);
327         group->addAction(addLineAct);
328         group->addAction(addCircleAct);
329         group->addAction(addArcAct);//*/
330 }
331
332 //
333 // Consolidates action creation from a multi-step process to a single-step one.
334 //
335 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
336         QIcon icon, QKeySequence key, bool checkable/*= false*/)
337 {
338         QAction * action = new QAction(icon, name, this);
339         action->setToolTip(tooltip);
340         action->setStatusTip(statustip);
341         action->setShortcut(key);
342         action->setCheckable(checkable);
343
344         return action;
345 }
346
347 //
348 // This is essentially the same as the previous function, but this allows more
349 // than one key sequence to be added as key shortcuts.
350 //
351 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
352         QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
353 {
354         QAction * action = new QAction(icon, name, this);
355         action->setToolTip(tooltip);
356         action->setStatusTip(statustip);
357         QList<QKeySequence> keyList;
358         keyList.append(key1);
359         keyList.append(key2);
360         action->setShortcuts(keyList);
361         action->setCheckable(checkable);
362
363         return action;
364 }
365
366 void ApplicationWindow::CreateMenus(void)
367 {
368         QMenu * menu = menuBar()->addMenu(tr("&File"));
369         menu->addAction(fileNewAct);
370         menu->addAction(fileOpenAct);
371         menu->addAction(fileSaveAct);
372         menu->addAction(fileSaveAsAct);
373         menu->addAction(fileCloseAct);
374         menu->addSeparator();
375         menu->addAction(exitAct);
376
377         menu = menuBar()->addMenu(tr("&View"));
378         menu->addAction(zoomInAct);
379         menu->addAction(zoomOutAct);
380
381         menu = menuBar()->addMenu(tr("&Edit"));
382         menu->addAction(snapToGridAct);
383         menu->addAction(fixAngleAct);
384         menu->addAction(fixLengthAct);
385         menu->addAction(rotateAct);
386         menu->addSeparator();
387         menu->addAction(deleteAct);
388         menu->addSeparator();
389         menu->addAction(addLineAct);
390         menu->addAction(addCircleAct);
391         menu->addAction(addArcAct);
392         menu->addAction(addPolygonAct);
393         menu->addAction(addDimensionAct);
394         menu->addSeparator();
395         menu->addAction(settingsAct);
396
397         menu = menuBar()->addMenu(tr("&Help"));
398         menu->addAction(aboutAct);
399 }
400
401 void ApplicationWindow::CreateToolbars(void)
402 {
403         QToolBar * toolbar = addToolBar(tr("File"));
404         toolbar->addAction(exitAct);
405
406         toolbar = addToolBar(tr("View"));
407         toolbar->addAction(zoomInAct);
408         toolbar->addAction(zoomOutAct);
409
410         toolbar = addToolBar(tr("Edit"));
411         toolbar->addAction(snapToGridAct);
412         toolbar->addAction(fixAngleAct);
413         toolbar->addAction(fixLengthAct);
414         toolbar->addAction(rotateAct);
415         toolbar->addAction(deleteAct);
416         toolbar->addSeparator();
417         toolbar->addAction(addLineAct);
418         toolbar->addAction(addCircleAct);
419         toolbar->addAction(addArcAct);
420         toolbar->addAction(addPolygonAct);
421         toolbar->addAction(addDimensionAct);
422 }
423
424 void ApplicationWindow::ReadSettings(void)
425 {
426         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
427         QSize size = settings.value("size", QSize(400, 400)).toSize();
428         drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
429         snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool());
430         resize(size);
431         move(pos);
432 //      pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
433 //      size = settings.value("charWndSize", QSize(200, 200)).toSize();
434 //      ((TTEdit *)qApp)->charWnd->resize(size);
435 //      ((TTEdit *)qApp)->charWnd->move(pos);
436 }
437
438 void ApplicationWindow::WriteSettings(void)
439 {
440         settings.setValue("pos", pos());
441         settings.setValue("size", size());
442         settings.setValue("useAntialiasing", drawing->useAntialiasing);
443         settings.setValue("snapToGrid", snapToGridAct->isChecked());
444 //      settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
445 //      settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());
446 }