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 zoomIndicator = new QLabel("Zoom: 12.5%");
57 statusBar()->addPermanentWidget(zoomIndicator);
58 statusBar()->showMessage(tr("Ready"));
62 // connect(textEdit->document(), SIGNAL(contentsChanged()),
63 // this, SLOT(documentWasModified()));
65 // setCurrentFile("");
66 setUnifiedTitleAndToolBarOnMac(true);
68 // ((TTEdit *)qApp)->charWnd->show();//eh?
69 Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
72 void ApplicationWindow::closeEvent(QCloseEvent * event)
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???
79 //void ApplicationWindow::FileOpen(void)
83 void ApplicationWindow::FixAngle(void)
85 Object::SetFixedAngle(fixAngleAct->isChecked());
88 void ApplicationWindow::FixLength(void)
90 Object::SetFixedLength(fixLengthAct->isChecked());
93 // We want certain tools to be exclusive, and this approach isn't working correctly...
94 void ApplicationWindow::DeleteTool(void)
97 ClearUIToolStatesExcept(deleteAct);
98 SetInternalToolStates();
101 void ApplicationWindow::DimensionTool(void)
103 ClearUIToolStatesExcept(addDimensionAct);
104 SetInternalToolStates();
107 void ApplicationWindow::RotateTool(void)
109 ClearUIToolStatesExcept(rotateAct);
110 SetInternalToolStates();
113 void ApplicationWindow::AddLineTool(void)
115 ClearUIToolStatesExcept(addLineAct);
116 SetInternalToolStates();
119 void ApplicationWindow::AddCircleTool(void)
121 ClearUIToolStatesExcept(addCircleAct);
122 SetInternalToolStates();
125 void ApplicationWindow::AddArcTool(void)
127 ClearUIToolStatesExcept(addArcAct);
128 SetInternalToolStates();
131 void ApplicationWindow::AddPolygonTool(void)
133 ClearUIToolStatesExcept(addPolygonAct);
134 SetInternalToolStates();
137 void ApplicationWindow::ZoomInTool(void)
139 double zoomFactor = 2.0;
141 We need to find the center of the screen, then figure out where the new corner
142 will be in the zoomed in window.
144 So we know in Qt coords, the center is found via:
145 size.width() / 2 --> xCenter
146 size.height() / 2 --> yCenter
148 transform x/yCenter to Cartesian coordinates. So far, so good.
150 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
151 (after subtracting from center, that is...)
153 QSize size = drawing->size();
154 Vector center(size.width() / 2.0, size.height() / 2.0);
155 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
156 center = Painter::QtToCartesianCoords(center);
157 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
158 Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
159 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
160 Painter::origin = newOrigin;
162 //printf("Zoom in... level going from %02f to ", Painter::zoom);
163 // This just zooms leaving origin intact... should zoom in at the current center! [DONE]
164 Painter::zoom *= zoomFactor;
165 zoomIndicator->setText(QString("Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM));
169 void ApplicationWindow::ZoomOutTool(void)
174 origin = (223, 160.5)
175 newOrigin should be (-10, -10)
178 center - origin = (213, 150.5)
179 origin - center = (-213, -150.5)
181 + center = (-10, -10)
184 double zoomFactor = 2.0;
185 QSize size = drawing->size();
186 Vector center(size.width() / 2.0, size.height() / 2.0);
187 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
188 center = Painter::QtToCartesianCoords(center);
189 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
190 // Vector newOrigin = (center - Painter::origin) * zoomFactor;
191 // Vector newOrigin = center - (Painter::origin * zoomFactor);
192 Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
193 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
194 Painter::origin = newOrigin;
195 //printf("Zoom out...\n");
196 // This just zooms leaving origin intact... should zoom out at the current center! [DONE]
197 Painter::zoom /= zoomFactor;
198 zoomIndicator->setText(QString("Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM));
202 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
204 if (exception != addArcAct)
205 addArcAct->setChecked(false);
207 if (exception != addCircleAct)
208 addCircleAct->setChecked(false);
210 if (exception != addDimensionAct)
211 addDimensionAct->setChecked(false);
213 if (exception != addLineAct)
214 addLineAct->setChecked(false);
216 if (exception != addPolygonAct)
217 addPolygonAct->setChecked(false);
219 if (exception != deleteAct)
220 deleteAct->setChecked(false);
222 if (exception != rotateAct)
223 rotateAct->setChecked(false);
226 void ApplicationWindow::SetInternalToolStates(void)
228 Object::SetDeleteActive(deleteAct->isChecked());
229 Object::SetDimensionActive(addDimensionAct->isChecked());
230 drawing->SetRotateToolActive(rotateAct->isChecked());
231 drawing->SetAddLineToolActive(addLineAct->isChecked());
232 drawing->SetAddCircleToolActive(addCircleAct->isChecked());
235 void ApplicationWindow::HelpAbout(void)
240 void ApplicationWindow::Settings(void)
242 SettingsDialog dlg(this);
243 dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
245 if (dlg.exec() == false)
248 // Deal with stuff here (since user hit "OK" button...)
249 drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
253 void ApplicationWindow::CreateActions(void)
255 exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
256 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
257 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
259 fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
260 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
261 connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
263 fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
264 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
265 connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
267 deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(), true);
268 connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
270 addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
271 connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
273 addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
274 connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
276 addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
277 connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
279 addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
280 connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool()));
282 addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
283 connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool()));
285 aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
286 connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
288 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);
289 connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
291 zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
292 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
294 zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
295 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
297 fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+n")));
299 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")));
301 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")));
303 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")));
305 fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+w")));
307 settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/generic-tool.png"), QKeySequence());
308 connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
310 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
311 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
312 /* QActionGroup * group = new QActionGroup(this);
313 group->addAction(deleteAct);
314 group->addAction(addDimensionAct);
315 group->addAction(addLineAct);
316 group->addAction(addCircleAct);
317 group->addAction(addArcAct);//*/
321 // Consolidates action creation from a multi-step process to a single-step one.
323 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
324 QIcon icon, QKeySequence key, bool checkable/*= false*/)
326 QAction * action = new QAction(icon, name, this);
327 action->setToolTip(tooltip);
328 action->setStatusTip(statustip);
329 action->setShortcut(key);
330 action->setCheckable(checkable);
336 // This is essentially the same as the previous function, but this allows more
337 // than one key sequence to be added as key shortcuts.
339 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
340 QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
342 QAction * action = new QAction(icon, name, this);
343 action->setToolTip(tooltip);
344 action->setStatusTip(statustip);
345 QList<QKeySequence> keyList;
346 keyList.append(key1);
347 keyList.append(key2);
348 action->setShortcuts(keyList);
349 action->setCheckable(checkable);
354 void ApplicationWindow::CreateMenus(void)
356 QMenu * menu = menuBar()->addMenu(tr("&File"));
357 menu->addAction(fileNewAct);
358 menu->addAction(fileOpenAct);
359 menu->addAction(fileSaveAct);
360 menu->addAction(fileSaveAsAct);
361 menu->addAction(fileCloseAct);
362 menu->addSeparator();
363 menu->addAction(exitAct);
365 menu = menuBar()->addMenu(tr("&View"));
366 menu->addAction(zoomInAct);
367 menu->addAction(zoomOutAct);
369 menu = menuBar()->addMenu(tr("&Edit"));
370 menu->addAction(fixAngleAct);
371 menu->addAction(fixLengthAct);
372 menu->addAction(rotateAct);
373 menu->addSeparator();
374 menu->addAction(deleteAct);
375 menu->addSeparator();
376 menu->addAction(addLineAct);
377 menu->addAction(addCircleAct);
378 menu->addAction(addArcAct);
379 menu->addAction(addPolygonAct);
380 menu->addAction(addDimensionAct);
381 menu->addSeparator();
382 menu->addAction(settingsAct);
384 menu = menuBar()->addMenu(tr("&Help"));
385 menu->addAction(aboutAct);
388 void ApplicationWindow::CreateToolbars(void)
390 QToolBar * toolbar = addToolBar(tr("File"));
391 toolbar->addAction(exitAct);
393 toolbar = addToolBar(tr("View"));
394 toolbar->addAction(zoomInAct);
395 toolbar->addAction(zoomOutAct);
397 toolbar = addToolBar(tr("Edit"));
398 toolbar->addAction(fixAngleAct);
399 toolbar->addAction(fixLengthAct);
400 toolbar->addAction(rotateAct);
401 toolbar->addAction(deleteAct);
402 toolbar->addAction(addLineAct);
403 toolbar->addAction(addCircleAct);
404 toolbar->addAction(addArcAct);
405 toolbar->addAction(addPolygonAct);
406 toolbar->addAction(addDimensionAct);
409 void ApplicationWindow::ReadSettings(void)
411 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
412 QSize size = settings.value("size", QSize(400, 400)).toSize();
413 drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
416 // pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
417 // size = settings.value("charWndSize", QSize(200, 200)).toSize();
418 // ((TTEdit *)qApp)->charWnd->resize(size);
419 // ((TTEdit *)qApp)->charWnd->move(pos);
422 void ApplicationWindow::WriteSettings(void)
424 settings.setValue("pos", pos());
425 settings.setValue("size", size());
426 settings.setValue("useAntialiasing", drawing->useAntialiasing);
427 // settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
428 // settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());