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 "dimension.h"
34 #include "drawingview.h"
35 #include "drawarcaction.h"
36 #include "drawcircleaction.h"
37 #include "drawdimensionaction.h"
38 #include "drawlineaction.h"
40 #include "generaltab.h"
42 #include "layerwidget.h"
44 #include "mirroraction.h"
46 #include "rotateaction.h"
47 #include "settingsdialog.h"
51 DrawingView * ApplicationWindow::drawing;
54 ApplicationWindow::ApplicationWindow():
55 baseUnitInput(new QLineEdit),
56 dimensionSizeInput(new QLineEdit),
57 settings("Underground Software", "Architektonas")
59 drawing = new DrawingView(this);
60 drawing->setMouseTracking(true); // We want *all* mouse events...!
61 drawing->setFocusPolicy(Qt::StrongFocus);
62 setCentralWidget(drawing);
64 aboutWin = new AboutWindow(this);
66 // ((TTEdit *)qApp)->charWnd = new CharWindow(this);
68 setWindowIcon(QIcon(":/res/atns-icon.png"));
69 setWindowTitle("Architektonas");
75 // Create Dock widgets
76 QDockWidget * dock1 = new QDockWidget(tr("Layers"), this);
77 LayerWidget * lw = new LayerWidget;
79 addDockWidget(Qt::RightDockWidgetArea, dock1);
80 QDockWidget * dock2 = new QDockWidget(tr("Blocks"), this);
81 BlockWidget * bw = new BlockWidget;
83 addDockWidget(Qt::RightDockWidgetArea, dock2);
84 // Needed for saveState()
85 dock1->setObjectName("Layers");
86 dock2->setObjectName("Blocks");
89 zoomIndicator = new QLabel("Grid: 12.0\" Zoom: 12.5%");
90 statusBar()->addPermanentWidget(zoomIndicator);
91 statusBar()->showMessage(tr("Ready"));
94 setUnifiedTitleAndToolBarOnMac(true);
95 Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
97 connect(lw, SIGNAL(LayerSelected(int)), drawing, SLOT(SetCurrentLayer(int)));
101 void ApplicationWindow::closeEvent(QCloseEvent * event)
104 event->accept(); // Use ignore() if can't close for some reason
105 //Do we have a memory leak here if we don't delete the font in the Object???
109 void ApplicationWindow::FileNew(void)
111 // Should warn the user if drawing hasn't been saved...
112 drawing->document.Clear();
114 documentName.clear();
115 setWindowTitle("Architektonas - Untitled");
116 statusBar()->showMessage(tr("New drawing is ready."));
120 void ApplicationWindow::FileOpen(void)
122 QString filename = QFileDialog::getOpenFileName(this, tr("Open Drawing"),
123 "", tr("Architektonas files (*.drawing)"));
124 FILE * file = fopen(filename.toAscii().data(), "r");
129 msg.setText(QString(tr("Could not open file \"%1\" for loading!")).arg(filename));
130 msg.setIcon(QMessageBox::Critical);
135 Container container(Vector(0, 0));
136 bool successful = FileIO::LoadAtnsFile(file, &container);
142 msg.setText(QString(tr("Could not load file \"%1\"!")).arg(filename));
143 msg.setIcon(QMessageBox::Critical);
148 printf("FileOpen: container size = %li\n", container.objects.size());
149 drawing->document = container;
151 documentName = filename;
152 setWindowTitle(QString("Architektonas - %1").arg(documentName));
153 statusBar()->showMessage(tr("Drawing loaded."));
157 void ApplicationWindow::FileSave(void)
159 if (documentName.isEmpty())
160 documentName = QFileDialog::getSaveFileName(this, tr("Save Drawing"),
161 "", tr("Architektonas drawings (*.drawing)"));
163 FILE * file = fopen(documentName.toAscii().data(), "w");
168 msg.setText(QString(tr("Could not open file \"%1\" for saving!")).arg(documentName));
169 msg.setIcon(QMessageBox::Critical);
174 bool successful = FileIO::SaveAtnsFile(file, &drawing->document);
180 msg.setText(QString(tr("Could not save file \"%1\"!")).arg(documentName));
181 msg.setIcon(QMessageBox::Critical);
183 // In this case, we should unlink the created file, since it's not right...
184 // unlink(documentName.toAscii().data());
185 QFile::remove(documentName);
189 setWindowTitle(QString("Architektonas - %1").arg(documentName));
190 statusBar()->showMessage(tr("Drawing saved."));
194 void ApplicationWindow::FileSaveAs(void)
196 QString filename = QFileDialog::getSaveFileName(this, tr("Save Drawing As"),
197 documentName, tr("Architektonas drawings (*.drawing)"));
199 if (!filename.isEmpty())
201 documentName = filename;
207 void ApplicationWindow::SnapToGridTool(void)
209 Object::SetSnapMode(snapToGridAct->isChecked());
213 void ApplicationWindow::FixAngle(void)
215 Object::SetFixedAngle(fixAngleAct->isChecked());
219 void ApplicationWindow::FixLength(void)
221 Object::SetFixedLength(fixLengthAct->isChecked());
225 // We want certain tools to be exclusive, and this approach isn't working correctly...
226 void ApplicationWindow::DeleteTool(void)
228 // For this tool, we check first to see if anything is selected. If so, we
229 // delete those and *don't* select the delete tool.
230 if (drawing->document.ItemsSelected() > 0)
232 drawing->document.DeleteSelectedItems();
234 deleteAct->setChecked(false);
238 // Otherwise, toggle the state of the tool
239 ClearUIToolStatesExcept(deleteAct);
240 SetInternalToolStates();
244 void ApplicationWindow::DimensionTool(void)
246 ClearUIToolStatesExcept(addDimensionAct);
247 SetInternalToolStates();
251 void ApplicationWindow::RotateTool(void)
253 ClearUIToolStatesExcept(rotateAct);
254 SetInternalToolStates();
258 void ApplicationWindow::MirrorTool(void)
260 ClearUIToolStatesExcept(mirrorAct);
261 SetInternalToolStates();
265 void ApplicationWindow::AddLineTool(void)
267 ClearUIToolStatesExcept(addLineAct);
268 SetInternalToolStates();
272 void ApplicationWindow::AddCircleTool(void)
274 ClearUIToolStatesExcept(addCircleAct);
275 SetInternalToolStates();
279 void ApplicationWindow::AddArcTool(void)
281 ClearUIToolStatesExcept(addArcAct);
282 SetInternalToolStates();
286 void ApplicationWindow::AddPolygonTool(void)
288 ClearUIToolStatesExcept(addPolygonAct);
289 SetInternalToolStates();
293 void ApplicationWindow::ZoomInTool(void)
295 double zoomFactor = 2.0;
297 We need to find the center of the screen, then figure out where the new corner
298 will be in the zoomed in window.
300 So we know in Qt coords, the center is found via:
301 size.width() / 2 --> xCenter
302 size.height() / 2 --> yCenter
304 transform x/yCenter to Cartesian coordinates. So far, so good.
306 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
307 (after subtracting from center, that is...)
309 QSize size = drawing->size();
310 Vector center(size.width() / 2.0, size.height() / 2.0);
311 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
312 center = Painter::QtToCartesianCoords(center);
313 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
314 Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
315 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
316 Painter::origin = newOrigin;
318 //printf("Zoom in... level going from %02f to ", Painter::zoom);
319 // This just zooms leaving origin intact... should zoom in at the current
321 Painter::zoom *= zoomFactor;
322 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
323 drawing->UpdateGridBackground();
326 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
327 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
331 void ApplicationWindow::ZoomOutTool(void)
336 origin = (223, 160.5)
337 newOrigin should be (-10, -10)
340 center - origin = (213, 150.5)
341 origin - center = (-213, -150.5)
343 + center = (-10, -10)
346 double zoomFactor = 2.0;
347 QSize size = drawing->size();
348 Vector center(size.width() / 2.0, size.height() / 2.0);
349 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
350 center = Painter::QtToCartesianCoords(center);
351 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
352 // Vector newOrigin = (center - Painter::origin) * zoomFactor;
353 // Vector newOrigin = center - (Painter::origin * zoomFactor);
354 Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
355 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
356 Painter::origin = newOrigin;
357 //printf("Zoom out...\n");
358 // This just zooms leaving origin intact... should zoom out at the current
360 Painter::zoom /= zoomFactor;
361 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
362 drawing->UpdateGridBackground();
365 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
366 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
370 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
372 if (exception != addArcAct)
373 addArcAct->setChecked(false);
375 if (exception != addCircleAct)
376 addCircleAct->setChecked(false);
378 if (exception != addDimensionAct)
379 addDimensionAct->setChecked(false);
381 if (exception != addLineAct)
382 addLineAct->setChecked(false);
384 if (exception != addPolygonAct)
385 addPolygonAct->setChecked(false);
387 if (exception != deleteAct)
388 deleteAct->setChecked(false);
390 if (exception != rotateAct)
391 rotateAct->setChecked(false);
393 if (exception != mirrorAct)
394 mirrorAct->setChecked(false);
398 void ApplicationWindow::SetInternalToolStates(void)
400 Object::SetDeleteActive(deleteAct->isChecked());
401 Object::SetDimensionActive(addDimensionAct->isChecked());
403 // We can be sure that if we've come here, then either an active tool is
404 // being deactivated, or a new tool is being created. In either case, the
405 // old tool needs to be deleted.
406 if (drawing->toolAction)
408 delete drawing->toolAction;
409 drawing->toolAction = NULL;
410 Object::ignoreClicks = false;
413 drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL);
414 drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL);
415 drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL);
416 drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL);
417 drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
418 drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL);
420 if (drawing->toolAction)
421 Object::ignoreClicks = true;
427 void ApplicationWindow::HelpAbout(void)
433 void ApplicationWindow::Settings(void)
435 SettingsDialog dlg(this);
436 dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
438 if (dlg.exec() == false)
441 // Deal with stuff here (since user hit "OK" button...)
442 drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
448 // Group a bunch of selected objects (which can include other groups) together
449 // or ungroup a selected group.
451 void ApplicationWindow::HandleGrouping(void)
453 int itemsSelected = drawing->document.ItemsSelected();
455 // If nothing selected, do nothing
456 if (itemsSelected == 0)
458 statusBar()->showMessage(tr("No objects selected to make a group from."));
462 // If it's a group that's selected, ungroup it and leave the objects in a
464 if (itemsSelected == 1)
466 Object * object = drawing->document.SelectedItem(0);
470 printf("SelectedItem = NULL!\n");
472 printf("SelectedItem = %08X, type = %i\n", object, object->type);
475 if (object == NULL || object->type != OTContainer)
477 statusBar()->showMessage(tr("A group requires two or more selected objects."));
481 // Need the parent of the group, we're assuming here that the parent is
482 // the drawing's document. Does it matter? Maybe...
483 // Could just stipulate that grouping like this only takes place where the
484 // parent of the group is the drawing's document. Makes life much simpler.
485 ((Container *)object)->SelectAll();
486 ((Container *)object)->MoveContentsTo(&(drawing->document));
487 drawing->document.Delete(object);
488 statusBar()->showMessage(tr("Objects ungrouped."));
490 // Otherwise, if it's a group of 2 or more objects (which can be groups too)
491 // group them and select the group
492 else if (itemsSelected > 1)
494 Container * container = new Container(Vector(), &(drawing->document));
495 drawing->document.MoveSelectedContentsTo(container);
496 drawing->document.Add(container);
497 container->DeselectAll();
498 container->state = OSSelected;
499 statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected));
506 void ApplicationWindow::HandleConnection(void)
508 //double tt = Geometry::ParameterOfLineAndPoint(Vector(0, 0), Vector(10, 0), Vector(8, 2));
509 //printf("Parameter of point @ (8,2) of line (0,0), (10,0): %lf\n", tt);
510 int itemsSelected = drawing->document.ItemsSelected();
512 // If nothing selected, do nothing
513 if (itemsSelected == 0)
515 statusBar()->showMessage(tr("No objects selected to connect."));
519 // If one thing selected, do nothing
520 if (itemsSelected == 1)
522 statusBar()->showMessage(tr("Nothing to connect object to."));
526 // This is O(n^2 / 2) :-P
527 for(int i=0; i<itemsSelected; i++)
529 Object * obj1 = drawing->document.SelectedItem(i);
531 for(int j=i+1; j<itemsSelected; j++)
533 Object * obj2 = drawing->document.SelectedItem(j);
536 // if ((obj1->type != OTLine) || (obj2->type != OTLine))
539 if ((obj1->type == OTLine) && (obj2->type == OTLine))
541 //printf("Testing objects for intersection (%X, %X)...\n", obj1, obj2);
542 int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
543 //printf(" (%s) --> t=%lf, u=%lf\n", (intersects ? "true" : "FALSE"), t, u);
547 //printf("Connecting objects (%X, %X)...\n", obj1, obj2);
548 obj1->Connect(obj2, u);
549 obj2->Connect(obj1, t);
552 else if (((obj1->type == OTLine) && (obj2->type == OTDimension))
553 || ((obj2->type == OTLine) && (obj1->type == OTDimension)))
555 printf("Testing Line<->Dimension intersection...\n");
556 Line * line = (Line *)(obj1->type == OTLine ? obj1 : obj2);
557 Dimension * dim = (Dimension *)(obj1->type == OTDimension ? obj1 : obj2);
559 int intersects = Geometry::Intersects(line, dim, &t, &u);
560 printf(" -> intersects = %i, t=%lf, u=%lf\n", intersects, t, u);
564 obj1->Connect(obj2, u);
565 obj2->Connect(obj1, t);
573 void ApplicationWindow::HandleDisconnection(void)
578 void ApplicationWindow::HandleGridSizeInPixels(int size)
580 drawing->SetGridSize(size);
585 void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
589 double value = text.toDouble(&ok);
591 // Nothing parsable to a double, so quit...
592 if (!ok || value == 0)
595 // drawing->gridSpacing = value;
596 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
597 Object::gridSpacing = value;
598 Painter::zoom = drawing->gridPixels / Object::gridSpacing;
599 drawing->UpdateGridBackground();
604 void ApplicationWindow::HandleDimensionSize(QString text)
608 double value = text.toDouble(&ok);
610 // Nothing parsable to a double, so quit...
611 if (!ok || value == 0)
614 drawing->document.ResizeAllDimensions(value);
615 // drawing->gridSpacing = value;
616 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
617 // drawing->UpdateGridBackground();
622 void ApplicationWindow::CreateActions(void)
624 exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
625 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
626 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
628 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);
629 connect(snapToGridAct, SIGNAL(triggered()), this, SLOT(SnapToGridTool()));
631 fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
632 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
633 connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
635 fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
636 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
637 connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
639 deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(tr("Delete")), true);
640 connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
642 addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
643 connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
645 addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
646 connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
648 addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
649 connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
651 addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
652 connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool()));
654 addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
655 connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool()));
657 aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
658 connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
660 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);
661 connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
663 zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
664 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
666 zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
667 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
669 fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/file-new.png"), QKeySequence(tr("Ctrl+n")));
670 connect(fileNewAct, SIGNAL(triggered()), this, SLOT(FileNew()));
672 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")));
673 connect(fileOpenAct, SIGNAL(triggered()), this, SLOT(FileOpen()));
675 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")));
676 connect(fileSaveAct, SIGNAL(triggered()), this, SLOT(FileSave()));
678 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")));
679 connect(fileSaveAsAct, SIGNAL(triggered()), this, SLOT(FileSaveAs()));
681 fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/file-close.png"), QKeySequence(tr("Ctrl+w")));
683 settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/settings.png"), QKeySequence());
684 connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
686 groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/group-tool.png"), QKeySequence("g"));
687 connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping()));
689 connectAct = CreateAction(tr("&Connect"), tr("Connect"), tr("Connect objects at point."), QIcon(":/res/connect-tool.png"), QKeySequence("c,c"));
690 connect(connectAct, SIGNAL(triggered()), this, SLOT(HandleConnection()));
692 disconnectAct = CreateAction(tr("&Disconnect"), tr("Disconnect"), tr("Disconnect objects joined at point."), QIcon(":/res/disconnect-tool.png"), QKeySequence("d,d"));
693 connect(disconnectAct, SIGNAL(triggered()), this, SLOT(HandleDisconnection()));
695 mirrorAct = CreateAction(tr("&Mirror"), tr("Mirror"), tr("Mirror selected objects around a line."), QIcon(":/res/mirror-tool.png"), QKeySequence("m,i"), true);
696 connect(mirrorAct, SIGNAL(triggered()), this, SLOT(MirrorTool()));
699 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
700 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
701 /* QActionGroup * group = new QActionGroup(this);
702 group->addAction(deleteAct);
703 group->addAction(addDimensionAct);
704 group->addAction(addLineAct);
705 group->addAction(addCircleAct);
706 group->addAction(addArcAct);//*/
711 // Consolidates action creation from a multi-step process to a single-step one.
713 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
714 QIcon icon, QKeySequence key, bool checkable/*= false*/)
716 QAction * action = new QAction(icon, name, this);
717 action->setToolTip(tooltip);
718 action->setStatusTip(statustip);
719 action->setShortcut(key);
720 action->setCheckable(checkable);
727 // This is essentially the same as the previous function, but this allows more
728 // than one key sequence to be added as key shortcuts.
730 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
731 QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
733 QAction * action = new QAction(icon, name, this);
734 action->setToolTip(tooltip);
735 action->setStatusTip(statustip);
736 QList<QKeySequence> keyList;
737 keyList.append(key1);
738 keyList.append(key2);
739 action->setShortcuts(keyList);
740 action->setCheckable(checkable);
746 void ApplicationWindow::CreateMenus(void)
748 QMenu * menu = menuBar()->addMenu(tr("&File"));
749 menu->addAction(fileNewAct);
750 menu->addAction(fileOpenAct);
751 menu->addAction(fileSaveAct);
752 menu->addAction(fileSaveAsAct);
753 menu->addAction(fileCloseAct);
754 menu->addSeparator();
755 menu->addAction(exitAct);
757 menu = menuBar()->addMenu(tr("&View"));
758 menu->addAction(zoomInAct);
759 menu->addAction(zoomOutAct);
761 menu = menuBar()->addMenu(tr("&Edit"));
762 menu->addAction(snapToGridAct);
763 menu->addAction(groupAct);
764 menu->addAction(fixAngleAct);
765 menu->addAction(fixLengthAct);
766 menu->addAction(rotateAct);
767 menu->addAction(mirrorAct);
768 menu->addAction(connectAct);
769 menu->addAction(disconnectAct);
770 menu->addSeparator();
771 menu->addAction(deleteAct);
772 menu->addSeparator();
773 menu->addAction(addLineAct);
774 menu->addAction(addCircleAct);
775 menu->addAction(addArcAct);
776 menu->addAction(addPolygonAct);
777 menu->addAction(addDimensionAct);
778 menu->addSeparator();
779 menu->addAction(settingsAct);
781 menu = menuBar()->addMenu(tr("&Help"));
782 menu->addAction(aboutAct);
786 void ApplicationWindow::CreateToolbars(void)
788 QToolBar * toolbar = addToolBar(tr("File"));
789 toolbar->setObjectName("File"); // Needed for saveState()
790 toolbar->addAction(fileNewAct);
791 toolbar->addAction(fileOpenAct);
792 toolbar->addAction(fileSaveAct);
793 toolbar->addAction(fileSaveAsAct);
794 toolbar->addAction(fileCloseAct);
795 // toolbar->addAction(exitAct);
797 toolbar = addToolBar(tr("View"));
798 toolbar->setObjectName("View");
799 toolbar->addAction(zoomInAct);
800 toolbar->addAction(zoomOutAct);
802 QSpinBox * spinbox = new QSpinBox;
803 toolbar->addWidget(spinbox);
804 // QLineEdit * lineedit = new QLineEdit;
805 toolbar->addWidget(baseUnitInput);
806 toolbar->addWidget(dimensionSizeInput);
808 toolbar = addToolBar(tr("Edit"));
809 toolbar->setObjectName("Edit");
810 toolbar->addAction(snapToGridAct);
811 toolbar->addAction(groupAct);
812 toolbar->addAction(fixAngleAct);
813 toolbar->addAction(fixLengthAct);
814 toolbar->addAction(rotateAct);
815 toolbar->addAction(mirrorAct);
816 toolbar->addAction(deleteAct);
817 toolbar->addAction(connectAct);
818 toolbar->addAction(disconnectAct);
819 toolbar->addSeparator();
820 toolbar->addAction(addLineAct);
821 toolbar->addAction(addCircleAct);
822 toolbar->addAction(addArcAct);
823 toolbar->addAction(addPolygonAct);
824 toolbar->addAction(addDimensionAct);
826 spinbox->setRange(4, 256);
827 spinbox->setValue(12);
828 baseUnitInput->setText("12");
829 connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int)));
830 connect(baseUnitInput, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString)));
831 connect(dimensionSizeInput, SIGNAL(textChanged(QString)), this, SLOT(HandleDimensionSize(QString)));
835 void ApplicationWindow::ReadSettings(void)
837 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
838 QSize size = settings.value("size", QSize(400, 400)).toSize();
839 drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
840 snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool());
843 restoreState(settings.value("windowState").toByteArray());
847 void ApplicationWindow::WriteSettings(void)
849 settings.setValue("pos", pos());
850 settings.setValue("size", size());
851 settings.setValue("windowState", saveState());
852 settings.setValue("useAntialiasing", drawing->useAntialiasing);
853 settings.setValue("snapToGrid", snapToGridAct->isChecked());