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\" BU: Inch");
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)"));
125 // User cancelled open
126 if (filename.isEmpty())
129 FILE * file = fopen(filename.toAscii().data(), "r");
134 msg.setText(QString(tr("Could not open file \"%1\" for loading!")).arg(filename));
135 msg.setIcon(QMessageBox::Critical);
140 Container container(Vector(0, 0));
141 bool successful = FileIO::LoadAtnsFile(file, &container);
147 msg.setText(QString(tr("Could not load file \"%1\"!")).arg(filename));
148 msg.setIcon(QMessageBox::Critical);
153 printf("FileOpen: container size = %li\n", container.objects.size());
154 drawing->document = container;
156 documentName = filename;
157 setWindowTitle(QString("Architektonas - %1").arg(documentName));
158 statusBar()->showMessage(tr("Drawing loaded."));
162 void ApplicationWindow::FileSave(void)
164 if (documentName.isEmpty())
165 documentName = QFileDialog::getSaveFileName(this, tr("Save Drawing"),
166 "", tr("Architektonas drawings (*.drawing)"));
168 FILE * file = fopen(documentName.toAscii().data(), "w");
173 msg.setText(QString(tr("Could not open file \"%1\" for saving!")).arg(documentName));
174 msg.setIcon(QMessageBox::Critical);
179 bool successful = FileIO::SaveAtnsFile(file, &drawing->document);
185 msg.setText(QString(tr("Could not save file \"%1\"!")).arg(documentName));
186 msg.setIcon(QMessageBox::Critical);
188 // In this case, we should unlink the created file, since it's not right...
189 // unlink(documentName.toAscii().data());
190 QFile::remove(documentName);
194 setWindowTitle(QString("Architektonas - %1").arg(documentName));
195 statusBar()->showMessage(tr("Drawing saved."));
199 void ApplicationWindow::FileSaveAs(void)
201 QString filename = QFileDialog::getSaveFileName(this, tr("Save Drawing As"),
202 documentName, tr("Architektonas drawings (*.drawing)"));
204 if (!filename.isEmpty())
206 documentName = filename;
212 void ApplicationWindow::SnapToGridTool(void)
214 Object::SetSnapMode(snapToGridAct->isChecked());
218 void ApplicationWindow::FixAngle(void)
220 Object::SetFixedAngle(fixAngleAct->isChecked());
224 void ApplicationWindow::FixLength(void)
226 Object::SetFixedLength(fixLengthAct->isChecked());
230 // We want certain tools to be exclusive, and this approach isn't working correctly...
231 void ApplicationWindow::DeleteTool(void)
233 // For this tool, we check first to see if anything is selected. If so, we
234 // delete those and *don't* select the delete tool.
235 if (drawing->document.ItemsSelected() > 0)
237 drawing->document.DeleteSelectedItems();
239 deleteAct->setChecked(false);
243 // Otherwise, toggle the state of the tool
244 ClearUIToolStatesExcept(deleteAct);
245 SetInternalToolStates();
249 void ApplicationWindow::DimensionTool(void)
251 ClearUIToolStatesExcept(addDimensionAct);
252 SetInternalToolStates();
256 void ApplicationWindow::RotateTool(void)
258 ClearUIToolStatesExcept(rotateAct);
259 SetInternalToolStates();
263 void ApplicationWindow::MirrorTool(void)
265 ClearUIToolStatesExcept(mirrorAct);
266 SetInternalToolStates();
270 void ApplicationWindow::AddLineTool(void)
272 ClearUIToolStatesExcept(addLineAct);
273 SetInternalToolStates();
277 void ApplicationWindow::AddCircleTool(void)
279 ClearUIToolStatesExcept(addCircleAct);
280 SetInternalToolStates();
284 void ApplicationWindow::AddArcTool(void)
286 ClearUIToolStatesExcept(addArcAct);
287 SetInternalToolStates();
291 void ApplicationWindow::AddPolygonTool(void)
293 ClearUIToolStatesExcept(addPolygonAct);
294 SetInternalToolStates();
298 void ApplicationWindow::ZoomInTool(void)
300 double zoomFactor = 2.0;
302 We need to find the center of the screen, then figure out where the new corner
303 will be in the zoomed in window.
305 So we know in Qt coords, the center is found via:
306 size.width() / 2 --> xCenter
307 size.height() / 2 --> yCenter
309 transform x/yCenter to Cartesian coordinates. So far, so good.
311 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
312 (after subtracting from center, that is...)
314 QSize size = drawing->size();
315 Vector center(size.width() / 2.0, size.height() / 2.0);
316 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
317 center = Painter::QtToCartesianCoords(center);
318 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
319 Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
320 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
321 Painter::origin = newOrigin;
323 //printf("Zoom in... level going from %02f to ", Painter::zoom);
324 // This just zooms leaving origin intact... should zoom in at the current
326 Painter::zoom *= zoomFactor;
327 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
328 drawing->UpdateGridBackground();
331 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
332 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
336 void ApplicationWindow::ZoomOutTool(void)
341 origin = (223, 160.5)
342 newOrigin should be (-10, -10)
345 center - origin = (213, 150.5)
346 origin - center = (-213, -150.5)
348 + center = (-10, -10)
351 double zoomFactor = 2.0;
352 QSize size = drawing->size();
353 Vector center(size.width() / 2.0, size.height() / 2.0);
354 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
355 center = Painter::QtToCartesianCoords(center);
356 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
357 // Vector newOrigin = (center - Painter::origin) * zoomFactor;
358 // Vector newOrigin = center - (Painter::origin * zoomFactor);
359 Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
360 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
361 Painter::origin = newOrigin;
362 //printf("Zoom out...\n");
363 // This just zooms leaving origin intact... should zoom out at the current
365 Painter::zoom /= zoomFactor;
366 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
367 drawing->UpdateGridBackground();
370 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
371 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
375 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
377 if (exception != addArcAct)
378 addArcAct->setChecked(false);
380 if (exception != addCircleAct)
381 addCircleAct->setChecked(false);
383 if (exception != addDimensionAct)
384 addDimensionAct->setChecked(false);
386 if (exception != addLineAct)
387 addLineAct->setChecked(false);
389 if (exception != addPolygonAct)
390 addPolygonAct->setChecked(false);
392 if (exception != deleteAct)
393 deleteAct->setChecked(false);
395 if (exception != rotateAct)
396 rotateAct->setChecked(false);
398 if (exception != mirrorAct)
399 mirrorAct->setChecked(false);
403 void ApplicationWindow::SetInternalToolStates(void)
405 Object::SetDeleteActive(deleteAct->isChecked());
406 Object::SetDimensionActive(addDimensionAct->isChecked());
408 // We can be sure that if we've come here, then either an active tool is
409 // being deactivated, or a new tool is being created. In either case, the
410 // old tool needs to be deleted.
411 if (drawing->toolAction)
413 delete drawing->toolAction;
414 drawing->toolAction = NULL;
415 Object::ignoreClicks = false;
418 drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL);
419 drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL);
420 drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL);
421 drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL);
422 drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
423 drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL);
425 if (drawing->toolAction)
426 Object::ignoreClicks = true;
432 void ApplicationWindow::HelpAbout(void)
438 void ApplicationWindow::Settings(void)
440 SettingsDialog dlg(this);
441 dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
443 if (dlg.exec() == false)
446 // Deal with stuff here (since user hit "OK" button...)
447 drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
453 // Group a bunch of selected objects (which can include other groups) together
454 // or ungroup a selected group.
456 void ApplicationWindow::HandleGrouping(void)
458 int itemsSelected = drawing->document.ItemsSelected();
460 // If nothing selected, do nothing
461 if (itemsSelected == 0)
463 statusBar()->showMessage(tr("No objects selected to make a group from."));
467 // If it's a group that's selected, ungroup it and leave the objects in a
469 if (itemsSelected == 1)
471 Object * object = drawing->document.SelectedItem(0);
475 printf("SelectedItem = NULL!\n");
477 printf("SelectedItem = %08X, type = %i\n", object, object->type);
480 if (object == NULL || object->type != OTContainer)
482 statusBar()->showMessage(tr("A group requires two or more selected objects."));
486 // Need the parent of the group, we're assuming here that the parent is
487 // the drawing's document. Does it matter? Maybe...
488 // Could just stipulate that grouping like this only takes place where the
489 // parent of the group is the drawing's document. Makes life much simpler.
490 ((Container *)object)->SelectAll();
491 ((Container *)object)->MoveContentsTo(&(drawing->document));
492 drawing->document.Delete(object);
493 statusBar()->showMessage(tr("Objects ungrouped."));
495 // Otherwise, if it's a group of 2 or more objects (which can be groups too)
496 // group them and select the group
497 else if (itemsSelected > 1)
499 Container * container = new Container(Vector(), &(drawing->document));
500 drawing->document.MoveSelectedContentsTo(container);
501 drawing->document.Add(container);
502 container->DeselectAll();
503 container->state = OSSelected;
504 statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected));
511 void ApplicationWindow::HandleConnection(void)
513 //double tt = Geometry::ParameterOfLineAndPoint(Vector(0, 0), Vector(10, 0), Vector(8, 2));
514 //printf("Parameter of point @ (8,2) of line (0,0), (10,0): %lf\n", tt);
515 int itemsSelected = drawing->document.ItemsSelected();
517 // If nothing selected, do nothing
518 if (itemsSelected == 0)
520 statusBar()->showMessage(tr("No objects selected to connect."));
524 // If one thing selected, do nothing
525 if (itemsSelected == 1)
527 statusBar()->showMessage(tr("Nothing to connect object to."));
531 // This is O(n^2 / 2) :-P
532 for(int i=0; i<itemsSelected; i++)
534 Object * obj1 = drawing->document.SelectedItem(i);
536 for(int j=i+1; j<itemsSelected; j++)
538 Object * obj2 = drawing->document.SelectedItem(j);
541 // if ((obj1->type != OTLine) || (obj2->type != OTLine))
544 if ((obj1->type == OTLine) && (obj2->type == OTLine))
546 //printf("Testing objects for intersection (%X, %X)...\n", obj1, obj2);
547 int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
548 //printf(" (%s) --> t=%lf, u=%lf\n", (intersects ? "true" : "FALSE"), t, u);
552 //printf("Connecting objects (%X, %X)...\n", obj1, obj2);
553 obj1->Connect(obj2, u);
554 obj2->Connect(obj1, t);
557 else if (((obj1->type == OTLine) && (obj2->type == OTDimension))
558 || ((obj2->type == OTLine) && (obj1->type == OTDimension)))
560 printf("Testing Line<->Dimension intersection...\n");
561 Line * line = (Line *)(obj1->type == OTLine ? obj1 : obj2);
562 Dimension * dim = (Dimension *)(obj1->type == OTDimension ? obj1 : obj2);
564 int intersects = Geometry::Intersects(line, dim, &t, &u);
565 printf(" -> intersects = %i, t=%lf, u=%lf\n", intersects, t, u);
569 obj1->Connect(obj2, u);
570 obj2->Connect(obj1, t);
578 void ApplicationWindow::HandleDisconnection(void)
583 void ApplicationWindow::HandleGridSizeInPixels(int size)
585 drawing->SetGridSize(size);
590 void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
594 double value = text.toDouble(&ok);
596 // Nothing parsable to a double, so quit...
597 if (!ok || value == 0)
600 // drawing->gridSpacing = value;
601 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
602 Object::gridSpacing = value;
603 Painter::zoom = drawing->gridPixels / Object::gridSpacing;
604 drawing->UpdateGridBackground();
609 void ApplicationWindow::HandleDimensionSize(QString text)
613 double value = text.toDouble(&ok);
615 // Nothing parsable to a double, so quit...
616 if (!ok || value == 0)
619 drawing->document.ResizeAllDimensions(value);
620 // drawing->gridSpacing = value;
621 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
622 // drawing->UpdateGridBackground();
627 void ApplicationWindow::CreateActions(void)
629 exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
630 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
631 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
633 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);
634 connect(snapToGridAct, SIGNAL(triggered()), this, SLOT(SnapToGridTool()));
636 fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
637 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
638 connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
640 fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
641 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
642 connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
644 deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(tr("Delete")), true);
645 connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
647 addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
648 connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
650 addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
651 connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
653 addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
654 connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
656 addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
657 connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool()));
659 addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
660 connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool()));
662 aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
663 connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
665 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);
666 connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
668 zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
669 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
671 zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
672 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
674 fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/file-new.png"), QKeySequence(tr("Ctrl+n")));
675 connect(fileNewAct, SIGNAL(triggered()), this, SLOT(FileNew()));
677 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")));
678 connect(fileOpenAct, SIGNAL(triggered()), this, SLOT(FileOpen()));
680 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")));
681 connect(fileSaveAct, SIGNAL(triggered()), this, SLOT(FileSave()));
683 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")));
684 connect(fileSaveAsAct, SIGNAL(triggered()), this, SLOT(FileSaveAs()));
686 fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/file-close.png"), QKeySequence(tr("Ctrl+w")));
688 settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/settings.png"), QKeySequence());
689 connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
691 groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/group-tool.png"), QKeySequence("g"));
692 connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping()));
694 connectAct = CreateAction(tr("&Connect"), tr("Connect"), tr("Connect objects at point."), QIcon(":/res/connect-tool.png"), QKeySequence("c,c"));
695 connect(connectAct, SIGNAL(triggered()), this, SLOT(HandleConnection()));
697 disconnectAct = CreateAction(tr("&Disconnect"), tr("Disconnect"), tr("Disconnect objects joined at point."), QIcon(":/res/disconnect-tool.png"), QKeySequence("d,d"));
698 connect(disconnectAct, SIGNAL(triggered()), this, SLOT(HandleDisconnection()));
700 mirrorAct = CreateAction(tr("&Mirror"), tr("Mirror"), tr("Mirror selected objects around a line."), QIcon(":/res/mirror-tool.png"), QKeySequence("m,i"), true);
701 connect(mirrorAct, SIGNAL(triggered()), this, SLOT(MirrorTool()));
704 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
705 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
706 /* QActionGroup * group = new QActionGroup(this);
707 group->addAction(deleteAct);
708 group->addAction(addDimensionAct);
709 group->addAction(addLineAct);
710 group->addAction(addCircleAct);
711 group->addAction(addArcAct);//*/
716 // Consolidates action creation from a multi-step process to a single-step one.
718 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
719 QIcon icon, QKeySequence key, bool checkable/*= false*/)
721 QAction * action = new QAction(icon, name, this);
722 action->setToolTip(tooltip);
723 action->setStatusTip(statustip);
724 action->setShortcut(key);
725 action->setCheckable(checkable);
732 // This is essentially the same as the previous function, but this allows more
733 // than one key sequence to be added as key shortcuts.
735 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
736 QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
738 QAction * action = new QAction(icon, name, this);
739 action->setToolTip(tooltip);
740 action->setStatusTip(statustip);
741 QList<QKeySequence> keyList;
742 keyList.append(key1);
743 keyList.append(key2);
744 action->setShortcuts(keyList);
745 action->setCheckable(checkable);
751 void ApplicationWindow::CreateMenus(void)
753 QMenu * menu = menuBar()->addMenu(tr("&File"));
754 menu->addAction(fileNewAct);
755 menu->addAction(fileOpenAct);
756 menu->addAction(fileSaveAct);
757 menu->addAction(fileSaveAsAct);
758 menu->addAction(fileCloseAct);
759 menu->addSeparator();
760 menu->addAction(exitAct);
762 menu = menuBar()->addMenu(tr("&View"));
763 menu->addAction(zoomInAct);
764 menu->addAction(zoomOutAct);
766 menu = menuBar()->addMenu(tr("&Edit"));
767 menu->addAction(snapToGridAct);
768 menu->addAction(groupAct);
769 menu->addAction(fixAngleAct);
770 menu->addAction(fixLengthAct);
771 menu->addAction(rotateAct);
772 menu->addAction(mirrorAct);
773 menu->addAction(connectAct);
774 menu->addAction(disconnectAct);
775 menu->addSeparator();
776 menu->addAction(deleteAct);
777 menu->addSeparator();
778 menu->addAction(addLineAct);
779 menu->addAction(addCircleAct);
780 menu->addAction(addArcAct);
781 menu->addAction(addPolygonAct);
782 menu->addAction(addDimensionAct);
783 menu->addSeparator();
784 menu->addAction(settingsAct);
786 menu = menuBar()->addMenu(tr("&Help"));
787 menu->addAction(aboutAct);
791 void ApplicationWindow::CreateToolbars(void)
793 QToolBar * toolbar = addToolBar(tr("File"));
794 toolbar->setObjectName("File"); // Needed for saveState()
795 toolbar->addAction(fileNewAct);
796 toolbar->addAction(fileOpenAct);
797 toolbar->addAction(fileSaveAct);
798 toolbar->addAction(fileSaveAsAct);
799 toolbar->addAction(fileCloseAct);
800 // toolbar->addAction(exitAct);
802 toolbar = addToolBar(tr("View"));
803 toolbar->setObjectName("View");
804 toolbar->addAction(zoomInAct);
805 toolbar->addAction(zoomOutAct);
807 QSpinBox * spinbox = new QSpinBox;
808 toolbar->addWidget(spinbox);
809 // QLineEdit * lineedit = new QLineEdit;
810 toolbar->addWidget(baseUnitInput);
811 toolbar->addWidget(dimensionSizeInput);
813 toolbar = addToolBar(tr("Edit"));
814 toolbar->setObjectName("Edit");
815 toolbar->addAction(snapToGridAct);
816 toolbar->addAction(groupAct);
817 toolbar->addAction(fixAngleAct);
818 toolbar->addAction(fixLengthAct);
819 toolbar->addAction(rotateAct);
820 toolbar->addAction(mirrorAct);
821 toolbar->addAction(deleteAct);
822 toolbar->addAction(connectAct);
823 toolbar->addAction(disconnectAct);
824 toolbar->addSeparator();
825 toolbar->addAction(addLineAct);
826 toolbar->addAction(addCircleAct);
827 toolbar->addAction(addArcAct);
828 toolbar->addAction(addPolygonAct);
829 toolbar->addAction(addDimensionAct);
831 spinbox->setRange(4, 256);
832 spinbox->setValue(12);
833 baseUnitInput->setText("12");
834 connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int)));
835 connect(baseUnitInput, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString)));
836 connect(dimensionSizeInput, SIGNAL(textChanged(QString)), this, SLOT(HandleDimensionSize(QString)));
840 void ApplicationWindow::ReadSettings(void)
842 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
843 QSize size = settings.value("size", QSize(400, 400)).toSize();
844 drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
845 snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool());
848 restoreState(settings.value("windowState").toByteArray());
852 void ApplicationWindow::WriteSettings(void)
854 settings.setValue("pos", pos());
855 settings.setValue("size", size());
856 settings.setValue("windowState", saveState());
857 settings.setValue("useAntialiasing", drawing->useAntialiasing);
858 settings.setValue("snapToGrid", snapToGridAct->isChecked());