2 // applicationwindow.cpp: Architektonas
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
8 // JLH = James Hammons <jlhamm@acm.org>
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
24 // Uncomment this for debugging...
26 //#define DEBUGFOO // Various tool debugging...
27 //#define DEBUGTP // Toolpalette debugging...
29 #include "applicationwindow.h"
32 #include "drawingview.h"
33 #include "generaltab.h"
35 #include "settingsdialog.h"
38 ApplicationWindow::ApplicationWindow(): settings("Underground Software", "Architektonas")
40 drawing = new DrawingView(this);
41 drawing->setMouseTracking(true); // We want *all* mouse events...!
42 setCentralWidget(drawing);
44 aboutWin = new AboutWindow(this);
46 // ((TTEdit *)qApp)->charWnd = new CharWindow(this);
48 setWindowIcon(QIcon(":/res/atns-icon.png"));
49 setWindowTitle("Architektonas");
56 statusBar()->showMessage(tr("Ready"));
60 // connect(textEdit->document(), SIGNAL(contentsChanged()),
61 // this, SLOT(documentWasModified()));
63 // setCurrentFile("");
64 setUnifiedTitleAndToolBarOnMac(true);
66 // ((TTEdit *)qApp)->charWnd->show();//eh?
67 Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
70 void ApplicationWindow::closeEvent(QCloseEvent * event)
73 event->accept(); // Use ignore() if can't close for some reason
74 //Do we have a memory leak here if we don't delete the font in the Object???
77 //void ApplicationWindow::FileOpen(void)
81 void ApplicationWindow::FixAngle(void)
83 Object::SetFixedAngle(fixAngleAct->isChecked());
86 void ApplicationWindow::FixLength(void)
88 Object::SetFixedLength(fixLengthAct->isChecked());
91 // We want certain tools to be exclusive, and this approach isn't working correctly...
92 void ApplicationWindow::DeleteTool(void)
95 ClearUIToolStatesExcept(deleteAct);
96 SetInternalToolStates();
99 void ApplicationWindow::DimensionTool(void)
101 ClearUIToolStatesExcept(addDimensionAct);
102 SetInternalToolStates();
105 void ApplicationWindow::RotateTool(void)
107 ClearUIToolStatesExcept(rotateAct);
108 SetInternalToolStates();
111 void ApplicationWindow::AddLineTool(void)
113 ClearUIToolStatesExcept(addLineAct);
114 SetInternalToolStates();
117 void ApplicationWindow::AddCircleTool(void)
119 ClearUIToolStatesExcept(addCircleAct);
120 SetInternalToolStates();
123 void ApplicationWindow::ZoomInTool(void)
125 double zoomFactor = 2.0;
127 We need to find the center of the screen, then figure out where the new corner
128 will be in the zoomed in window.
130 So we know in Qt coords, the center is found via:
131 size.width() / 2 --> xCenter
132 size.height() / 2 --> yCenter
134 transform x/yCenter to Cartesian coordinates. So far, so good.
136 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
137 (after subtracting from center, that is...)
139 QSize size = drawing->size();
140 Vector center(size.width() / 2.0, size.height() / 2.0);
141 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
142 center = Painter::QtToCartesianCoords(center);
143 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
144 Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
145 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
146 Painter::origin = newOrigin;
148 //printf("Zoom in... level going from %02f to ", Painter::zoom);
149 // This just zooms leaving origin intact... should zoom in at the current center! [DONE]
150 Painter::zoom *= zoomFactor;
154 void ApplicationWindow::ZoomOutTool(void)
159 origin = (223, 160.5)
160 newOrigin should be (-10, -10)
163 center - origin = (213, 150.5)
164 origin - center = (-213, -150.5)
166 + center = (-10, -10)
169 double zoomFactor = 2.0;
170 QSize size = drawing->size();
171 Vector center(size.width() / 2.0, size.height() / 2.0);
172 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
173 center = Painter::QtToCartesianCoords(center);
174 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
175 // Vector newOrigin = (center - Painter::origin) * zoomFactor;
176 // Vector newOrigin = center - (Painter::origin * zoomFactor);
177 Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
178 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
179 Painter::origin = newOrigin;
180 //printf("Zoom out...\n");
181 // This just zooms leaving origin intact... should zoom out at the current center! [DONE]
182 Painter::zoom /= zoomFactor;
186 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
188 if (exception != addArcAct)
189 addArcAct->setChecked(false);
191 if (exception != addCircleAct)
192 addCircleAct->setChecked(false);
194 if (exception != addDimensionAct)
195 addDimensionAct->setChecked(false);
197 if (exception != addLineAct)
198 addLineAct->setChecked(false);
200 if (exception != addPolygonAct)
201 addPolygonAct->setChecked(false);
203 if (exception != deleteAct)
204 deleteAct->setChecked(false);
206 if (exception != rotateAct)
207 rotateAct->setChecked(false);
210 void ApplicationWindow::SetInternalToolStates(void)
212 Object::SetDeleteActive(deleteAct->isChecked());
213 Object::SetDimensionActive(addDimensionAct->isChecked());
214 drawing->SetRotateToolActive(rotateAct->isChecked());
215 drawing->SetAddLineToolActive(addLineAct->isChecked());
216 drawing->SetAddCircleToolActive(addCircleAct->isChecked());
219 void ApplicationWindow::HelpAbout(void)
224 void ApplicationWindow::Settings(void)
226 SettingsDialog dlg(this);
227 dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
229 if (dlg.exec() == false)
232 // Deal with stuff here (since user hit "OK" button...)
233 drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
237 void ApplicationWindow::CreateActions(void)
239 exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
240 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
241 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
243 fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
244 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
245 connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
247 fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
248 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
249 connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
251 deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(), true);
252 connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
254 addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
255 connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
257 addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
258 connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
260 addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
261 connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
263 addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
265 addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
267 aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
268 connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
270 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);
271 connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
273 zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
274 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
276 zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
277 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
279 fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+n")));
281 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")));
283 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")));
285 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")));
287 fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+w")));
289 settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/generic-tool.png"), QKeySequence());
290 connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
292 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
293 /* QActionGroup * group = new QActionGroup(this);
294 group->addAction(deleteAct);
295 group->addAction(addDimensionAct);
296 group->addAction(addLineAct);
297 group->addAction(addCircleAct);
298 group->addAction(addArcAct);//*/
302 // Consolidates action creation from a multi-step process to a single-step one.
304 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
305 QIcon icon, QKeySequence key, bool checkable/*= false*/)
307 QAction * action = new QAction(icon, name, this);
308 action->setToolTip(tooltip);
309 action->setStatusTip(statustip);
310 action->setShortcut(key);
311 action->setCheckable(checkable);
317 // This is essentially the same as the previous function, but this allows more
318 // than one key sequence to be added as key shortcuts.
320 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
321 QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
323 QAction * action = new QAction(icon, name, this);
324 action->setToolTip(tooltip);
325 action->setStatusTip(statustip);
326 QList<QKeySequence> keyList;
327 keyList.append(key1);
328 keyList.append(key2);
329 action->setShortcuts(keyList);
330 action->setCheckable(checkable);
335 void ApplicationWindow::CreateMenus(void)
337 QMenu * menu = menuBar()->addMenu(tr("&File"));
338 menu->addAction(fileNewAct);
339 menu->addAction(fileOpenAct);
340 menu->addAction(fileSaveAct);
341 menu->addAction(fileSaveAsAct);
342 menu->addAction(fileCloseAct);
343 menu->addSeparator();
344 menu->addAction(exitAct);
346 menu = menuBar()->addMenu(tr("&View"));
347 menu->addAction(zoomInAct);
348 menu->addAction(zoomOutAct);
350 menu = menuBar()->addMenu(tr("&Edit"));
351 menu->addAction(fixAngleAct);
352 menu->addAction(fixLengthAct);
353 menu->addAction(rotateAct);
354 menu->addSeparator();
355 menu->addAction(deleteAct);
356 menu->addSeparator();
357 menu->addAction(addLineAct);
358 menu->addAction(addCircleAct);
359 menu->addAction(addArcAct);
360 menu->addAction(addPolygonAct);
361 menu->addAction(addDimensionAct);
362 menu->addSeparator();
363 menu->addAction(settingsAct);
365 menu = menuBar()->addMenu(tr("&Help"));
366 menu->addAction(aboutAct);
369 void ApplicationWindow::CreateToolbars(void)
371 QToolBar * toolbar = addToolBar(tr("File"));
372 toolbar->addAction(exitAct);
374 toolbar = addToolBar(tr("View"));
375 toolbar->addAction(zoomInAct);
376 toolbar->addAction(zoomOutAct);
378 toolbar = addToolBar(tr("Edit"));
379 toolbar->addAction(fixAngleAct);
380 toolbar->addAction(fixLengthAct);
381 toolbar->addAction(rotateAct);
382 toolbar->addAction(deleteAct);
383 toolbar->addAction(addLineAct);
384 toolbar->addAction(addCircleAct);
385 toolbar->addAction(addArcAct);
386 toolbar->addAction(addPolygonAct);
387 toolbar->addAction(addDimensionAct);
390 void ApplicationWindow::ReadSettings(void)
392 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
393 QSize size = settings.value("size", QSize(400, 400)).toSize();
394 drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
397 // pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
398 // size = settings.value("charWndSize", QSize(200, 200)).toSize();
399 // ((TTEdit *)qApp)->charWnd->resize(size);
400 // ((TTEdit *)qApp)->charWnd->move(pos);
403 void ApplicationWindow::WriteSettings(void)
405 settings.setValue("pos", pos());
406 settings.setValue("size", size());
407 settings.setValue("useAntialiasing", drawing->useAntialiasing);
408 // settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
409 // settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());