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 "blockwidget.h"
33 #include "drawingview.h"
34 #include "drawarcaction.h"
35 #include "drawcircleaction.h"
36 #include "drawdimensionaction.h"
37 #include "drawlineaction.h"
39 #include "generaltab.h"
41 #include "layerwidget.h"
42 #include "mirroraction.h"
44 #include "rotateaction.h"
45 #include "settingsdialog.h"
49 DrawingView * ApplicationWindow::drawing;
52 ApplicationWindow::ApplicationWindow():
53 baseUnitInput(new QLineEdit),
54 dimensionSizeInput(new QLineEdit),
55 settings("Underground Software", "Architektonas")
57 drawing = new DrawingView(this);
58 drawing->setMouseTracking(true); // We want *all* mouse events...!
59 drawing->setFocusPolicy(Qt::StrongFocus);
60 setCentralWidget(drawing);
62 aboutWin = new AboutWindow(this);
64 // ((TTEdit *)qApp)->charWnd = new CharWindow(this);
66 setWindowIcon(QIcon(":/res/atns-icon.png"));
67 setWindowTitle("Architektonas");
73 // Create Dock widgets
74 QDockWidget * dock1 = new QDockWidget(tr("Layers"), this);
75 LayerWidget * lw = new LayerWidget;
77 addDockWidget(Qt::RightDockWidgetArea, dock1);
78 QDockWidget * dock2 = new QDockWidget(tr("Blocks"), this);
79 BlockWidget * bw = new BlockWidget;
81 addDockWidget(Qt::RightDockWidgetArea, dock2);
82 // Needed for saveState()
83 dock1->setObjectName("Layers");
84 dock2->setObjectName("Blocks");
87 zoomIndicator = new QLabel("Grid: 12.0\" Zoom: 12.5%");
88 statusBar()->addPermanentWidget(zoomIndicator);
89 statusBar()->showMessage(tr("Ready"));
92 setUnifiedTitleAndToolBarOnMac(true);
93 Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
95 connect(lw, SIGNAL(LayerSelected(int)), drawing, SLOT(SetCurrentLayer(int)));
99 void ApplicationWindow::closeEvent(QCloseEvent * event)
102 event->accept(); // Use ignore() if can't close for some reason
103 //Do we have a memory leak here if we don't delete the font in the Object???
107 void ApplicationWindow::FileNew(void)
109 // Should warn the user if drawing hasn't been saved...
110 drawing->document.Clear();
112 documentName.clear();
113 setWindowTitle("Architektonas - Untitled");
114 statusBar()->showMessage(tr("New drawing is ready."));
118 void ApplicationWindow::FileOpen(void)
120 QString filename = QFileDialog::getOpenFileName(this, tr("Open Drawing"),
121 "", tr("Architektonas files (*.drawing)"));
122 FILE * file = fopen(filename.toAscii().data(), "r");
127 msg.setText(QString(tr("Could not open file \"%1\" for loading!")).arg(filename));
128 msg.setIcon(QMessageBox::Critical);
133 Container container(Vector(0, 0));
134 bool successful = FileIO::LoadAtnsFile(file, &container);
140 msg.setText(QString(tr("Could not load file \"%1\"!")).arg(filename));
141 msg.setIcon(QMessageBox::Critical);
146 printf("FileOpen: container size = %li\n", container.objects.size());
147 drawing->document = container;
149 documentName = filename;
150 setWindowTitle(QString("Architektonas - %1").arg(documentName));
151 statusBar()->showMessage(tr("Drawing loaded."));
155 void ApplicationWindow::FileSave(void)
157 if (documentName.isEmpty())
158 documentName = QFileDialog::getSaveFileName(this, tr("Save Drawing"),
159 "", tr("Architektonas drawings (*.drawing)"));
161 FILE * file = fopen(documentName.toAscii().data(), "w");
166 msg.setText(QString(tr("Could not open file \"%1\" for saving!")).arg(documentName));
167 msg.setIcon(QMessageBox::Critical);
172 bool successful = FileIO::SaveAtnsFile(file, &drawing->document);
178 msg.setText(QString(tr("Could not save file \"%1\"!")).arg(documentName));
179 msg.setIcon(QMessageBox::Critical);
181 // In this case, we should unlink the created file, since it's not right...
182 // unlink(documentName.toAscii().data());
183 QFile::remove(documentName);
187 setWindowTitle(QString("Architektonas - %1").arg(documentName));
188 statusBar()->showMessage(tr("Drawing saved."));
192 void ApplicationWindow::FileSaveAs(void)
194 QString filename = QFileDialog::getSaveFileName(this, tr("Save Drawing As"),
195 documentName, tr("Architektonas drawings (*.drawing)"));
197 if (!filename.isEmpty())
199 documentName = filename;
205 void ApplicationWindow::SnapToGridTool(void)
207 Object::SetSnapMode(snapToGridAct->isChecked());
211 void ApplicationWindow::FixAngle(void)
213 Object::SetFixedAngle(fixAngleAct->isChecked());
217 void ApplicationWindow::FixLength(void)
219 Object::SetFixedLength(fixLengthAct->isChecked());
223 // We want certain tools to be exclusive, and this approach isn't working correctly...
224 void ApplicationWindow::DeleteTool(void)
226 // For this tool, we check first to see if anything is selected. If so, we
227 // delete those and *don't* select the delete tool.
228 if (drawing->document.ItemsSelected() > 0)
230 drawing->document.DeleteSelectedItems();
232 deleteAct->setChecked(false);
236 // Otherwise, toggle the state of the tool
237 ClearUIToolStatesExcept(deleteAct);
238 SetInternalToolStates();
242 void ApplicationWindow::DimensionTool(void)
244 ClearUIToolStatesExcept(addDimensionAct);
245 SetInternalToolStates();
249 void ApplicationWindow::RotateTool(void)
251 ClearUIToolStatesExcept(rotateAct);
252 SetInternalToolStates();
256 void ApplicationWindow::MirrorTool(void)
258 ClearUIToolStatesExcept(mirrorAct);
259 SetInternalToolStates();
263 void ApplicationWindow::AddLineTool(void)
265 ClearUIToolStatesExcept(addLineAct);
266 SetInternalToolStates();
270 void ApplicationWindow::AddCircleTool(void)
272 ClearUIToolStatesExcept(addCircleAct);
273 SetInternalToolStates();
277 void ApplicationWindow::AddArcTool(void)
279 ClearUIToolStatesExcept(addArcAct);
280 SetInternalToolStates();
284 void ApplicationWindow::AddPolygonTool(void)
286 ClearUIToolStatesExcept(addPolygonAct);
287 SetInternalToolStates();
291 void ApplicationWindow::ZoomInTool(void)
293 double zoomFactor = 2.0;
295 We need to find the center of the screen, then figure out where the new corner
296 will be in the zoomed in window.
298 So we know in Qt coords, the center is found via:
299 size.width() / 2 --> xCenter
300 size.height() / 2 --> yCenter
302 transform x/yCenter to Cartesian coordinates. So far, so good.
304 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
305 (after subtracting from center, that is...)
307 QSize size = drawing->size();
308 Vector center(size.width() / 2.0, size.height() / 2.0);
309 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
310 center = Painter::QtToCartesianCoords(center);
311 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
312 Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
313 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
314 Painter::origin = newOrigin;
316 //printf("Zoom in... level going from %02f to ", Painter::zoom);
317 // This just zooms leaving origin intact... should zoom in at the current
319 Painter::zoom *= zoomFactor;
320 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
321 drawing->UpdateGridBackground();
324 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
325 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
329 void ApplicationWindow::ZoomOutTool(void)
334 origin = (223, 160.5)
335 newOrigin should be (-10, -10)
338 center - origin = (213, 150.5)
339 origin - center = (-213, -150.5)
341 + center = (-10, -10)
344 double zoomFactor = 2.0;
345 QSize size = drawing->size();
346 Vector center(size.width() / 2.0, size.height() / 2.0);
347 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
348 center = Painter::QtToCartesianCoords(center);
349 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
350 // Vector newOrigin = (center - Painter::origin) * zoomFactor;
351 // Vector newOrigin = center - (Painter::origin * zoomFactor);
352 Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
353 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
354 Painter::origin = newOrigin;
355 //printf("Zoom out...\n");
356 // This just zooms leaving origin intact... should zoom out at the current
358 Painter::zoom /= zoomFactor;
359 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
360 drawing->UpdateGridBackground();
363 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
364 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
368 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
370 if (exception != addArcAct)
371 addArcAct->setChecked(false);
373 if (exception != addCircleAct)
374 addCircleAct->setChecked(false);
376 if (exception != addDimensionAct)
377 addDimensionAct->setChecked(false);
379 if (exception != addLineAct)
380 addLineAct->setChecked(false);
382 if (exception != addPolygonAct)
383 addPolygonAct->setChecked(false);
385 if (exception != deleteAct)
386 deleteAct->setChecked(false);
388 if (exception != rotateAct)
389 rotateAct->setChecked(false);
391 if (exception != mirrorAct)
392 mirrorAct->setChecked(false);
396 void ApplicationWindow::SetInternalToolStates(void)
398 Object::SetDeleteActive(deleteAct->isChecked());
399 Object::SetDimensionActive(addDimensionAct->isChecked());
401 // We can be sure that if we've come here, then either an active tool is
402 // being deactivated, or a new tool is being created. In either case, the
403 // old tool needs to be deleted.
404 if (drawing->toolAction)
406 delete drawing->toolAction;
407 drawing->toolAction = NULL;
408 Object::ignoreClicks = false;
411 drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL);
412 drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL);
413 drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL);
414 drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL);
415 drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
416 drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL);
418 if (drawing->toolAction)
419 Object::ignoreClicks = true;
425 void ApplicationWindow::HelpAbout(void)
431 void ApplicationWindow::Settings(void)
433 SettingsDialog dlg(this);
434 dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
436 if (dlg.exec() == false)
439 // Deal with stuff here (since user hit "OK" button...)
440 drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
446 // Group a bunch of selected objects (which can include other groups) together
447 // or ungroup a selected group.
449 void ApplicationWindow::HandleGrouping(void)
451 int itemsSelected = drawing->document.ItemsSelected();
453 // If nothing selected, do nothing
454 if (itemsSelected == 0)
456 statusBar()->showMessage(tr("No objects selected to make a group from."));
460 // If it's a group that's selected, ungroup it and leave the objects in a
462 if (itemsSelected == 1)
464 Object * object = drawing->document.SelectedItem(0);
468 printf("SelectedItem = NULL!\n");
470 printf("SelectedItem = %08X, type = %i\n", object, object->type);
473 if (object == NULL || object->type != OTContainer)
475 statusBar()->showMessage(tr("A group requires two or more selected objects."));
479 // Need the parent of the group, we're assuming here that the parent is
480 // the drawing's document. Does it matter? Maybe...
481 // Could just stipulate that grouping like this only takes place where the
482 // parent of the group is the drawing's document. Makes life much simpler.
483 ((Container *)object)->SelectAll();
484 ((Container *)object)->MoveContentsTo(&(drawing->document));
485 drawing->document.Delete(object);
486 statusBar()->showMessage(tr("Objects ungrouped."));
488 // Otherwise, if it's a group of 2 or more objects (which can be groups too)
489 // group them and select the group
490 else if (itemsSelected > 1)
492 Container * container = new Container(Vector(), &(drawing->document));
493 drawing->document.MoveSelectedContentsTo(container);
494 drawing->document.Add(container);
495 container->DeselectAll();
496 container->state = OSSelected;
497 statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected));
504 void ApplicationWindow::HandleConnection(void)
506 //double tt = Geometry::ParameterOfLineAndPoint(Vector(0, 0), Vector(10, 0), Vector(8, 2));
507 //printf("Parameter of point @ (8,2) of line (0,0), (10,0): %lf\n", tt);
508 int itemsSelected = drawing->document.ItemsSelected();
510 // If nothing selected, do nothing
511 if (itemsSelected == 0)
513 statusBar()->showMessage(tr("No objects selected to connect."));
517 // If one thing selected, do nothing
518 if (itemsSelected == 1)
520 statusBar()->showMessage(tr("Nothing to connect object to."));
524 // This is O(n^2 / 2) :-P
525 for(int i=0; i<itemsSelected; i++)
527 Object * obj1 = drawing->document.SelectedItem(i);
529 for(int j=i+1; j<itemsSelected; j++)
531 Object * obj2 = drawing->document.SelectedItem(j);
534 if ((obj1->type != OTLine) || (obj2->type != OTLine))
537 //printf("Testing objects for intersection (%X, %X)...\n", obj1, obj2);
538 int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
539 //printf(" (%s) --> t=%lf, u=%lf\n", (intersects ? "true" : "FALSE"), t, u);
543 printf("Connecting objects (%X, %X)...\n", obj1, obj2);
544 obj1->Connect(obj2, u);
545 obj2->Connect(obj1, t);
552 void ApplicationWindow::HandleDisconnection(void)
557 void ApplicationWindow::HandleGridSizeInPixels(int size)
559 drawing->SetGridSize(size);
564 void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
568 double value = text.toDouble(&ok);
570 // Nothing parsable to a double, so quit...
571 if (!ok || value == 0)
574 // drawing->gridSpacing = value;
575 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
576 Object::gridSpacing = value;
577 Painter::zoom = drawing->gridPixels / Object::gridSpacing;
578 drawing->UpdateGridBackground();
583 void ApplicationWindow::HandleDimensionSize(QString text)
587 double value = text.toDouble(&ok);
589 // Nothing parsable to a double, so quit...
590 if (!ok || value == 0)
593 drawing->document.ResizeAllDimensions(value);
594 // drawing->gridSpacing = value;
595 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
596 // drawing->UpdateGridBackground();
601 void ApplicationWindow::CreateActions(void)
603 exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
604 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
605 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
607 snapToGridAct = CreateAction(tr("Snap To &Grid"), tr("Snap To Grid"), tr("Snaps mouse cursor to the visible grid when moving/creating objects."), QIcon(":/res/snap-to-grid-tool.png"), QKeySequence(tr("S")), true);
608 connect(snapToGridAct, SIGNAL(triggered()), this, SLOT(SnapToGridTool()));
610 fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
611 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
612 connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
614 fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
615 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
616 connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
618 deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(tr("Delete")), true);
619 connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
621 addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
622 connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
624 addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
625 connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
627 addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
628 connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
630 addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
631 connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool()));
633 addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
634 connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool()));
636 aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
637 connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
639 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);
640 connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
642 zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
643 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
645 zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
646 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
648 fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/file-new.png"), QKeySequence(tr("Ctrl+n")));
649 connect(fileNewAct, SIGNAL(triggered()), this, SLOT(FileNew()));
651 fileOpenAct = CreateAction(tr("&Open Drawing"), tr("Open Drawing"), tr("Opens an existing drawing from a file."), QIcon(":/res/file-open.png"), QKeySequence(tr("Ctrl+o")));
652 connect(fileOpenAct, SIGNAL(triggered()), this, SLOT(FileOpen()));
654 fileSaveAct = CreateAction(tr("&Save Drawing"), tr("Save Drawing"), tr("Saves the current drawing to a file."), QIcon(":/res/file-save.png"), QKeySequence(tr("Ctrl+s")));
655 connect(fileSaveAct, SIGNAL(triggered()), this, SLOT(FileSave()));
657 fileSaveAsAct = CreateAction(tr("Save Drawing &As"), tr("Save As"), tr("Saves the current drawing to a file with a different name."), QIcon(":/res/file-save-as.png"), QKeySequence(tr("Ctrl+Shift+s")));
658 connect(fileSaveAsAct, SIGNAL(triggered()), this, SLOT(FileSaveAs()));
660 fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/file-close.png"), QKeySequence(tr("Ctrl+w")));
662 settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/settings.png"), QKeySequence());
663 connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
665 groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/group-tool.png"), QKeySequence("g"));
666 connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping()));
668 connectAct = CreateAction(tr("&Connect"), tr("Connect"), tr("Connect objects at point."), QIcon(":/res/connect-tool.png"), QKeySequence("c,c"));
669 connect(connectAct, SIGNAL(triggered()), this, SLOT(HandleConnection()));
671 disconnectAct = CreateAction(tr("&Disconnect"), tr("Disconnect"), tr("Disconnect objects joined at point."), QIcon(":/res/disconnect-tool.png"), QKeySequence("d,d"));
672 connect(disconnectAct, SIGNAL(triggered()), this, SLOT(HandleDisconnection()));
674 mirrorAct = CreateAction(tr("&Mirror"), tr("Mirror"), tr("Mirror selected objects around a line."), QIcon(":/res/mirror-tool.png"), QKeySequence("m,i"), true);
675 connect(mirrorAct, SIGNAL(triggered()), this, SLOT(MirrorTool()));
678 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
679 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
680 /* QActionGroup * group = new QActionGroup(this);
681 group->addAction(deleteAct);
682 group->addAction(addDimensionAct);
683 group->addAction(addLineAct);
684 group->addAction(addCircleAct);
685 group->addAction(addArcAct);//*/
690 // Consolidates action creation from a multi-step process to a single-step one.
692 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
693 QIcon icon, QKeySequence key, bool checkable/*= false*/)
695 QAction * action = new QAction(icon, name, this);
696 action->setToolTip(tooltip);
697 action->setStatusTip(statustip);
698 action->setShortcut(key);
699 action->setCheckable(checkable);
706 // This is essentially the same as the previous function, but this allows more
707 // than one key sequence to be added as key shortcuts.
709 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
710 QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
712 QAction * action = new QAction(icon, name, this);
713 action->setToolTip(tooltip);
714 action->setStatusTip(statustip);
715 QList<QKeySequence> keyList;
716 keyList.append(key1);
717 keyList.append(key2);
718 action->setShortcuts(keyList);
719 action->setCheckable(checkable);
725 void ApplicationWindow::CreateMenus(void)
727 QMenu * menu = menuBar()->addMenu(tr("&File"));
728 menu->addAction(fileNewAct);
729 menu->addAction(fileOpenAct);
730 menu->addAction(fileSaveAct);
731 menu->addAction(fileSaveAsAct);
732 menu->addAction(fileCloseAct);
733 menu->addSeparator();
734 menu->addAction(exitAct);
736 menu = menuBar()->addMenu(tr("&View"));
737 menu->addAction(zoomInAct);
738 menu->addAction(zoomOutAct);
740 menu = menuBar()->addMenu(tr("&Edit"));
741 menu->addAction(snapToGridAct);
742 menu->addAction(groupAct);
743 menu->addAction(fixAngleAct);
744 menu->addAction(fixLengthAct);
745 menu->addAction(rotateAct);
746 menu->addAction(mirrorAct);
747 menu->addAction(connectAct);
748 menu->addAction(disconnectAct);
749 menu->addSeparator();
750 menu->addAction(deleteAct);
751 menu->addSeparator();
752 menu->addAction(addLineAct);
753 menu->addAction(addCircleAct);
754 menu->addAction(addArcAct);
755 menu->addAction(addPolygonAct);
756 menu->addAction(addDimensionAct);
757 menu->addSeparator();
758 menu->addAction(settingsAct);
760 menu = menuBar()->addMenu(tr("&Help"));
761 menu->addAction(aboutAct);
765 void ApplicationWindow::CreateToolbars(void)
767 QToolBar * toolbar = addToolBar(tr("File"));
768 toolbar->setObjectName("File"); // Needed for saveState()
769 toolbar->addAction(fileNewAct);
770 toolbar->addAction(fileOpenAct);
771 toolbar->addAction(fileSaveAct);
772 toolbar->addAction(fileSaveAsAct);
773 toolbar->addAction(fileCloseAct);
774 // toolbar->addAction(exitAct);
776 toolbar = addToolBar(tr("View"));
777 toolbar->setObjectName("View");
778 toolbar->addAction(zoomInAct);
779 toolbar->addAction(zoomOutAct);
781 QSpinBox * spinbox = new QSpinBox;
782 toolbar->addWidget(spinbox);
783 // QLineEdit * lineedit = new QLineEdit;
784 toolbar->addWidget(baseUnitInput);
785 toolbar->addWidget(dimensionSizeInput);
787 toolbar = addToolBar(tr("Edit"));
788 toolbar->setObjectName("Edit");
789 toolbar->addAction(snapToGridAct);
790 toolbar->addAction(groupAct);
791 toolbar->addAction(fixAngleAct);
792 toolbar->addAction(fixLengthAct);
793 toolbar->addAction(rotateAct);
794 toolbar->addAction(mirrorAct);
795 toolbar->addAction(deleteAct);
796 toolbar->addAction(connectAct);
797 toolbar->addAction(disconnectAct);
798 toolbar->addSeparator();
799 toolbar->addAction(addLineAct);
800 toolbar->addAction(addCircleAct);
801 toolbar->addAction(addArcAct);
802 toolbar->addAction(addPolygonAct);
803 toolbar->addAction(addDimensionAct);
805 spinbox->setRange(4, 256);
806 spinbox->setValue(12);
807 baseUnitInput->setText("12");
808 connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int)));
809 connect(baseUnitInput, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString)));
810 connect(dimensionSizeInput, SIGNAL(textChanged(QString)), this, SLOT(HandleDimensionSize(QString)));
814 void ApplicationWindow::ReadSettings(void)
816 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
817 QSize size = settings.value("size", QSize(400, 400)).toSize();
818 drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
819 snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool());
822 restoreState(settings.value("windowState").toByteArray());
826 void ApplicationWindow::WriteSettings(void)
828 settings.setValue("pos", pos());
829 settings.setValue("size", size());
830 settings.setValue("windowState", saveState());
831 settings.setValue("useAntialiasing", drawing->useAntialiasing);
832 settings.setValue("snapToGrid", snapToGridAct->isChecked());