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"
48 #include "trimaction.h"
52 DrawingView * ApplicationWindow::drawing;
55 ApplicationWindow::ApplicationWindow():
56 baseUnitInput(new QLineEdit),
57 dimensionSizeInput(new QLineEdit),
58 settings("Underground Software", "Architektonas")
60 drawing = new DrawingView(this);
61 drawing->setMouseTracking(true); // We want *all* mouse events...!
62 drawing->setFocusPolicy(Qt::StrongFocus);
63 setCentralWidget(drawing);
65 aboutWin = new AboutWindow(this);
67 // ((TTEdit *)qApp)->charWnd = new CharWindow(this);
69 setWindowIcon(QIcon(":/res/atns-icon.png"));
70 setWindowTitle("Architektonas");
76 // Create Dock widgets
77 QDockWidget * dock1 = new QDockWidget(tr("Layers"), this);
78 LayerWidget * lw = new LayerWidget;
80 addDockWidget(Qt::RightDockWidgetArea, dock1);
81 QDockWidget * dock2 = new QDockWidget(tr("Blocks"), this);
82 BlockWidget * bw = new BlockWidget;
84 addDockWidget(Qt::RightDockWidgetArea, dock2);
85 // Needed for saveState()
86 dock1->setObjectName("Layers");
87 dock2->setObjectName("Blocks");
90 zoomIndicator = new QLabel("Grid: 12.0\" BU: Inch");
91 statusBar()->addPermanentWidget(zoomIndicator);
92 statusBar()->showMessage(tr("Ready"));
95 setUnifiedTitleAndToolBarOnMac(true);
96 Object::SetFont(new QFont("Verdana", 15, QFont::Bold));
98 connect(lw, SIGNAL(LayerSelected(int)), drawing, SLOT(SetCurrentLayer(int)));
102 void ApplicationWindow::closeEvent(QCloseEvent * event)
105 event->accept(); // Use ignore() if can't close for some reason
106 //Do we have a memory leak here if we don't delete the font in the Object???
110 void ApplicationWindow::FileNew(void)
112 // Should warn the user if drawing hasn't been saved...
113 drawing->document.Clear();
115 documentName.clear();
116 setWindowTitle("Architektonas - Untitled");
117 statusBar()->showMessage(tr("New drawing is ready."));
121 void ApplicationWindow::FileOpen(void)
123 QString filename = QFileDialog::getOpenFileName(this, tr("Open Drawing"),
124 "", tr("Architektonas files (*.drawing)"));
126 // User cancelled open
127 if (filename.isEmpty())
130 FILE * file = fopen(filename.toAscii().data(), "r");
135 msg.setText(QString(tr("Could not open file \"%1\" for loading!")).arg(filename));
136 msg.setIcon(QMessageBox::Critical);
141 Container container(Vector(0, 0));
142 bool successful = FileIO::LoadAtnsFile(file, &container);
148 msg.setText(QString(tr("Could not load file \"%1\"!")).arg(filename));
149 msg.setIcon(QMessageBox::Critical);
154 printf("FileOpen: container size = %li\n", container.objects.size());
155 drawing->document = container;
157 documentName = filename;
158 setWindowTitle(QString("Architektonas - %1").arg(documentName));
159 statusBar()->showMessage(tr("Drawing loaded."));
163 void ApplicationWindow::FileSave(void)
165 if (documentName.isEmpty())
166 documentName = QFileDialog::getSaveFileName(this, tr("Save Drawing"),
167 "", tr("Architektonas drawings (*.drawing)"));
169 FILE * file = fopen(documentName.toAscii().data(), "w");
174 msg.setText(QString(tr("Could not open file \"%1\" for saving!")).arg(documentName));
175 msg.setIcon(QMessageBox::Critical);
180 bool successful = FileIO::SaveAtnsFile(file, &drawing->document);
186 msg.setText(QString(tr("Could not save file \"%1\"!")).arg(documentName));
187 msg.setIcon(QMessageBox::Critical);
189 // In this case, we should unlink the created file, since it's not right...
190 // unlink(documentName.toAscii().data());
191 QFile::remove(documentName);
195 setWindowTitle(QString("Architektonas - %1").arg(documentName));
196 statusBar()->showMessage(tr("Drawing saved."));
200 void ApplicationWindow::FileSaveAs(void)
202 QString filename = QFileDialog::getSaveFileName(this, tr("Save Drawing As"),
203 documentName, tr("Architektonas drawings (*.drawing)"));
205 if (!filename.isEmpty())
207 documentName = filename;
213 void ApplicationWindow::SnapToGridTool(void)
215 Object::SetSnapMode(snapToGridAct->isChecked());
219 void ApplicationWindow::FixAngle(void)
221 Object::SetFixedAngle(fixAngleAct->isChecked());
225 void ApplicationWindow::FixLength(void)
227 Object::SetFixedLength(fixLengthAct->isChecked());
231 // We want certain tools to be exclusive, and this approach isn't working correctly...
232 void ApplicationWindow::DeleteTool(void)
234 // For this tool, we check first to see if anything is selected. If so, we
235 // delete those and *don't* select the delete tool.
236 if (drawing->document.ItemsSelected() > 0)
238 drawing->document.DeleteSelectedItems();
240 deleteAct->setChecked(false);
244 // Otherwise, toggle the state of the tool
245 ClearUIToolStatesExcept(deleteAct);
246 SetInternalToolStates();
250 void ApplicationWindow::DimensionTool(void)
252 ClearUIToolStatesExcept(addDimensionAct);
253 SetInternalToolStates();
257 void ApplicationWindow::RotateTool(void)
259 ClearUIToolStatesExcept(rotateAct);
260 SetInternalToolStates();
264 void ApplicationWindow::MirrorTool(void)
266 ClearUIToolStatesExcept(mirrorAct);
267 SetInternalToolStates();
271 void ApplicationWindow::TrimTool(void)
273 ClearUIToolStatesExcept(trimAct);
274 SetInternalToolStates();
278 void ApplicationWindow::AddLineTool(void)
280 ClearUIToolStatesExcept(addLineAct);
281 SetInternalToolStates();
285 void ApplicationWindow::AddCircleTool(void)
287 ClearUIToolStatesExcept(addCircleAct);
288 SetInternalToolStates();
292 void ApplicationWindow::AddArcTool(void)
294 ClearUIToolStatesExcept(addArcAct);
295 SetInternalToolStates();
299 void ApplicationWindow::AddPolygonTool(void)
301 ClearUIToolStatesExcept(addPolygonAct);
302 SetInternalToolStates();
306 void ApplicationWindow::ZoomInTool(void)
308 double zoomFactor = 2.0;
310 We need to find the center of the screen, then figure out where the new corner
311 will be in the zoomed in window.
313 So we know in Qt coords, the center is found via:
314 size.width() / 2 --> xCenter
315 size.height() / 2 --> yCenter
317 transform x/yCenter to Cartesian coordinates. So far, so good.
319 when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
320 (after subtracting from center, that is...)
322 QSize size = drawing->size();
323 Vector center(size.width() / 2.0, size.height() / 2.0);
324 //printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
325 center = Painter::QtToCartesianCoords(center);
326 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
327 Vector newOrigin = center - ((center - Painter::origin) / zoomFactor);
328 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
329 Painter::origin = newOrigin;
331 //printf("Zoom in... level going from %02f to ", Painter::zoom);
332 // This just zooms leaving origin intact... should zoom in at the current
334 Painter::zoom *= zoomFactor;
335 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
336 drawing->UpdateGridBackground();
339 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
340 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
344 void ApplicationWindow::ZoomOutTool(void)
349 origin = (223, 160.5)
350 newOrigin should be (-10, -10)
353 center - origin = (213, 150.5)
354 origin - center = (-213, -150.5)
356 + center = (-10, -10)
359 double zoomFactor = 2.0;
360 QSize size = drawing->size();
361 Vector center(size.width() / 2.0, size.height() / 2.0);
362 //printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
363 center = Painter::QtToCartesianCoords(center);
364 //printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
365 // Vector newOrigin = (center - Painter::origin) * zoomFactor;
366 // Vector newOrigin = center - (Painter::origin * zoomFactor);
367 Vector newOrigin = center + ((Painter::origin - center) * zoomFactor);
368 //printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
369 Painter::origin = newOrigin;
370 //printf("Zoom out...\n");
371 // This just zooms leaving origin intact... should zoom out at the current
373 Painter::zoom /= zoomFactor;
374 Object::gridSpacing = drawing->gridPixels / Painter::zoom;
375 drawing->UpdateGridBackground();
378 zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing));
379 baseUnitInput->setText(QString("%1").arg(Object::gridSpacing));
383 void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
385 if (exception != addArcAct)
386 addArcAct->setChecked(false);
388 if (exception != addCircleAct)
389 addCircleAct->setChecked(false);
391 if (exception != addDimensionAct)
392 addDimensionAct->setChecked(false);
394 if (exception != addLineAct)
395 addLineAct->setChecked(false);
397 if (exception != addPolygonAct)
398 addPolygonAct->setChecked(false);
400 if (exception != deleteAct)
401 deleteAct->setChecked(false);
403 if (exception != rotateAct)
404 rotateAct->setChecked(false);
406 if (exception != mirrorAct)
407 mirrorAct->setChecked(false);
409 if (exception != trimAct)
410 trimAct->setChecked(false);
414 void ApplicationWindow::SetInternalToolStates(void)
416 Object::SetDeleteActive(deleteAct->isChecked());
417 Object::SetDimensionActive(addDimensionAct->isChecked());
419 // We can be sure that if we've come here, then either an active tool is
420 // being deactivated, or a new tool is being created. In either case, the
421 // old tool needs to be deleted.
422 if (drawing->toolAction)
424 delete drawing->toolAction;
425 drawing->toolAction = NULL;
426 Object::ignoreClicks = false;
429 drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL);
430 drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL);
431 drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL);
432 drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL);
433 drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
434 drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL);
435 drawing->SetToolActive(trimAct->isChecked() ? new TrimAction() : NULL);
437 if (drawing->toolAction)
438 Object::ignoreClicks = true;
444 void ApplicationWindow::HelpAbout(void)
450 void ApplicationWindow::Settings(void)
452 SettingsDialog dlg(this);
453 dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
455 if (dlg.exec() == false)
458 // Deal with stuff here (since user hit "OK" button...)
459 drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
465 // Group a bunch of selected objects (which can include other groups) together
466 // or ungroup a selected group.
468 void ApplicationWindow::HandleGrouping(void)
470 int itemsSelected = drawing->document.ItemsSelected();
472 // If nothing selected, do nothing
473 if (itemsSelected == 0)
475 statusBar()->showMessage(tr("No objects selected to make a group from."));
479 // If it's a group that's selected, ungroup it and leave the objects in a
481 if (itemsSelected == 1)
483 Object * object = drawing->document.SelectedItem(0);
487 printf("SelectedItem = NULL!\n");
489 printf("SelectedItem = %08X, type = %i\n", object, object->type);
492 if (object == NULL || object->type != OTContainer)
494 statusBar()->showMessage(tr("A group requires two or more selected objects."));
498 // Need the parent of the group, we're assuming here that the parent is
499 // the drawing's document. Does it matter? Maybe...
500 // Could just stipulate that grouping like this only takes place where the
501 // parent of the group is the drawing's document. Makes life much simpler.
502 ((Container *)object)->SelectAll();
503 ((Container *)object)->MoveContentsTo(&(drawing->document));
504 drawing->document.Delete(object);
505 statusBar()->showMessage(tr("Objects ungrouped."));
507 // Otherwise, if it's a group of 2 or more objects (which can be groups too)
508 // group them and select the group
509 else if (itemsSelected > 1)
511 Container * container = new Container(Vector(), &(drawing->document));
512 drawing->document.MoveSelectedContentsTo(container);
513 drawing->document.Add(container);
514 container->DeselectAll();
515 container->state = OSSelected;
516 statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected));
523 void ApplicationWindow::HandleConnection(void)
525 //double tt = Geometry::ParameterOfLineAndPoint(Vector(0, 0), Vector(10, 0), Vector(8, 2));
526 //printf("Parameter of point @ (8,2) of line (0,0), (10,0): %lf\n", tt);
527 int itemsSelected = drawing->document.ItemsSelected();
529 // If nothing selected, do nothing
530 if (itemsSelected == 0)
532 statusBar()->showMessage(tr("No objects selected to connect."));
536 // If one thing selected, do nothing
537 if (itemsSelected == 1)
539 statusBar()->showMessage(tr("Nothing to connect object to."));
543 // This is O(n^2 / 2) :-P
544 for(int i=0; i<itemsSelected; i++)
546 Object * obj1 = drawing->document.SelectedItem(i);
548 for(int j=i+1; j<itemsSelected; j++)
550 Object * obj2 = drawing->document.SelectedItem(j);
553 // if ((obj1->type != OTLine) || (obj2->type != OTLine))
556 if ((obj1->type == OTLine) && (obj2->type == OTLine))
558 //printf("Testing objects for intersection (%X, %X)...\n", obj1, obj2);
559 int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
560 //printf(" (%s) --> t=%lf, u=%lf\n", (intersects ? "true" : "FALSE"), t, u);
564 //printf("Connecting objects (%X, %X)...\n", obj1, obj2);
565 obj1->Connect(obj2, u);
566 obj2->Connect(obj1, t);
569 else if (((obj1->type == OTLine) && (obj2->type == OTDimension))
570 || ((obj2->type == OTLine) && (obj1->type == OTDimension)))
572 printf("Testing Line<->Dimension intersection...\n");
573 Line * line = (Line *)(obj1->type == OTLine ? obj1 : obj2);
574 Dimension * dim = (Dimension *)(obj1->type == OTDimension ? obj1 : obj2);
576 int intersects = Geometry::Intersects(line, dim, &t, &u);
577 printf(" -> intersects = %i, t=%lf, u=%lf\n", intersects, t, u);
581 obj1->Connect(obj2, u);
582 obj2->Connect(obj1, t);
590 void ApplicationWindow::HandleDisconnection(void)
595 void ApplicationWindow::HandleGridSizeInPixels(int size)
597 drawing->SetGridSize(size);
602 void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
606 double value = text.toDouble(&ok);
608 // Nothing parsable to a double, so quit...
609 if (!ok || value == 0)
612 // drawing->gridSpacing = value;
613 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
614 Object::gridSpacing = value;
615 Painter::zoom = drawing->gridPixels / Object::gridSpacing;
616 drawing->UpdateGridBackground();
621 void ApplicationWindow::HandleDimensionSize(QString text)
625 double value = text.toDouble(&ok);
627 // Nothing parsable to a double, so quit...
628 if (!ok || value == 0)
631 drawing->document.ResizeAllDimensions(value);
632 // drawing->gridSpacing = value;
633 // Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
634 // drawing->UpdateGridBackground();
639 void ApplicationWindow::CreateActions(void)
641 exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
642 QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q")));
643 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
645 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);
646 connect(snapToGridAct, SIGNAL(triggered()), this, SLOT(SnapToGridTool()));
648 fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."),
649 QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true);
650 connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle()));
652 fixLengthAct = CreateAction(tr("Fix &Length"), tr("Fix Length"), tr("Fixes the length of an object."),
653 QIcon(":/res/fix-length.png"), QKeySequence(tr("F,L")), true);
654 connect(fixLengthAct, SIGNAL(triggered()), this, SLOT(FixLength()));
656 deleteAct = CreateAction(tr("&Delete"), tr("Delete Object"), tr("Deletes selected objects."), QIcon(":/res/delete-tool.png"), QKeySequence(tr("Delete")), true);
657 connect(deleteAct, SIGNAL(triggered()), this, SLOT(DeleteTool()));
659 addDimensionAct = CreateAction(tr("Add &Dimension"), tr("Add Dimension"), tr("Adds a dimension to the drawing."), QIcon(":/res/dimension-tool.png"), QKeySequence("D,I"), true);
660 connect(addDimensionAct, SIGNAL(triggered()), this, SLOT(DimensionTool()));
662 addLineAct = CreateAction(tr("Add &Line"), tr("Add Line"), tr("Adds lines to the drawing."), QIcon(":/res/add-line-tool.png"), QKeySequence("A,L"), true);
663 connect(addLineAct, SIGNAL(triggered()), this, SLOT(AddLineTool()));
665 addCircleAct = CreateAction(tr("Add &Circle"), tr("Add Circle"), tr("Adds circles to the drawing."), QIcon(":/res/add-circle-tool.png"), QKeySequence("A,C"), true);
666 connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool()));
668 addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true);
669 connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool()));
671 addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true);
672 connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool()));
674 aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence());
675 connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout()));
677 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);
678 connect(rotateAct, SIGNAL(triggered()), this, SLOT(RotateTool()));
680 zoomInAct = CreateAction(tr("Zoom &In"), tr("Zoom In"), tr("Zoom in on the document."), QIcon(":/res/zoom-in.png"), QKeySequence(tr("+")), QKeySequence(tr("=")));
681 connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomInTool()));
683 zoomOutAct = CreateAction(tr("Zoom &Out"), tr("Zoom Out"), tr("Zoom out of the document."), QIcon(":/res/zoom-out.png"), QKeySequence(tr("-")));
684 connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool()));
686 fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/file-new.png"), QKeySequence(tr("Ctrl+n")));
687 connect(fileNewAct, SIGNAL(triggered()), this, SLOT(FileNew()));
689 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")));
690 connect(fileOpenAct, SIGNAL(triggered()), this, SLOT(FileOpen()));
692 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")));
693 connect(fileSaveAct, SIGNAL(triggered()), this, SLOT(FileSave()));
695 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")));
696 connect(fileSaveAsAct, SIGNAL(triggered()), this, SLOT(FileSaveAs()));
698 fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/file-close.png"), QKeySequence(tr("Ctrl+w")));
700 settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/settings.png"), QKeySequence());
701 connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
703 groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/group-tool.png"), QKeySequence("g"));
704 connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping()));
706 connectAct = CreateAction(tr("&Connect"), tr("Connect"), tr("Connect objects at point."), QIcon(":/res/connect-tool.png"), QKeySequence("c,c"));
707 connect(connectAct, SIGNAL(triggered()), this, SLOT(HandleConnection()));
709 disconnectAct = CreateAction(tr("&Disconnect"), tr("Disconnect"), tr("Disconnect objects joined at point."), QIcon(":/res/disconnect-tool.png"), QKeySequence("d,d"));
710 connect(disconnectAct, SIGNAL(triggered()), this, SLOT(HandleDisconnection()));
712 mirrorAct = CreateAction(tr("&Mirror"), tr("Mirror"), tr("Mirror selected objects around a line."), QIcon(":/res/mirror-tool.png"), QKeySequence("m,i"), true);
713 connect(mirrorAct, SIGNAL(triggered()), this, SLOT(MirrorTool()));
715 trimAct = CreateAction(tr("&Trim"), tr("Trim"), tr("Trim extraneous lines from selected objects."), QIcon(":/res/trim-tool.png"), QKeySequence("t,r"), true);
716 connect(trimAct, SIGNAL(triggered()), this, SLOT(TrimTool()));
719 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
720 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
721 /* QActionGroup * group = new QActionGroup(this);
722 group->addAction(deleteAct);
723 group->addAction(addDimensionAct);
724 group->addAction(addLineAct);
725 group->addAction(addCircleAct);
726 group->addAction(addArcAct);//*/
731 // Consolidates action creation from a multi-step process to a single-step one.
733 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
734 QIcon icon, QKeySequence key, bool checkable/*= false*/)
736 QAction * action = new QAction(icon, name, this);
737 action->setToolTip(tooltip);
738 action->setStatusTip(statustip);
739 action->setShortcut(key);
740 action->setCheckable(checkable);
747 // This is essentially the same as the previous function, but this allows more
748 // than one key sequence to be added as key shortcuts.
750 QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip,
751 QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/)
753 QAction * action = new QAction(icon, name, this);
754 action->setToolTip(tooltip);
755 action->setStatusTip(statustip);
756 QList<QKeySequence> keyList;
757 keyList.append(key1);
758 keyList.append(key2);
759 action->setShortcuts(keyList);
760 action->setCheckable(checkable);
766 void ApplicationWindow::CreateMenus(void)
768 QMenu * menu = menuBar()->addMenu(tr("&File"));
769 menu->addAction(fileNewAct);
770 menu->addAction(fileOpenAct);
771 menu->addAction(fileSaveAct);
772 menu->addAction(fileSaveAsAct);
773 menu->addAction(fileCloseAct);
774 menu->addSeparator();
775 menu->addAction(exitAct);
777 menu = menuBar()->addMenu(tr("&View"));
778 menu->addAction(zoomInAct);
779 menu->addAction(zoomOutAct);
781 menu = menuBar()->addMenu(tr("&Edit"));
782 menu->addAction(snapToGridAct);
783 menu->addAction(groupAct);
784 menu->addAction(fixAngleAct);
785 menu->addAction(fixLengthAct);
786 menu->addAction(rotateAct);
787 menu->addAction(mirrorAct);
788 menu->addAction(trimAct);
789 menu->addAction(connectAct);
790 menu->addAction(disconnectAct);
791 menu->addSeparator();
792 menu->addAction(deleteAct);
793 menu->addSeparator();
794 menu->addAction(addLineAct);
795 menu->addAction(addCircleAct);
796 menu->addAction(addArcAct);
797 menu->addAction(addPolygonAct);
798 menu->addAction(addDimensionAct);
799 menu->addSeparator();
800 menu->addAction(settingsAct);
802 menu = menuBar()->addMenu(tr("&Help"));
803 menu->addAction(aboutAct);
807 void ApplicationWindow::CreateToolbars(void)
809 QToolBar * toolbar = addToolBar(tr("File"));
810 toolbar->setObjectName("File"); // Needed for saveState()
811 toolbar->addAction(fileNewAct);
812 toolbar->addAction(fileOpenAct);
813 toolbar->addAction(fileSaveAct);
814 toolbar->addAction(fileSaveAsAct);
815 toolbar->addAction(fileCloseAct);
816 // toolbar->addAction(exitAct);
818 toolbar = addToolBar(tr("View"));
819 toolbar->setObjectName("View");
820 toolbar->addAction(zoomInAct);
821 toolbar->addAction(zoomOutAct);
823 QSpinBox * spinbox = new QSpinBox;
824 toolbar->addWidget(spinbox);
825 // QLineEdit * lineedit = new QLineEdit;
826 toolbar->addWidget(baseUnitInput);
827 toolbar->addWidget(dimensionSizeInput);
829 toolbar = addToolBar(tr("Edit"));
830 toolbar->setObjectName("Edit");
831 toolbar->addAction(snapToGridAct);
832 toolbar->addAction(groupAct);
833 toolbar->addAction(fixAngleAct);
834 toolbar->addAction(fixLengthAct);
835 toolbar->addAction(rotateAct);
836 toolbar->addAction(mirrorAct);
837 toolbar->addAction(trimAct);
838 toolbar->addAction(deleteAct);
839 toolbar->addAction(connectAct);
840 toolbar->addAction(disconnectAct);
841 toolbar->addSeparator();
842 toolbar->addAction(addLineAct);
843 toolbar->addAction(addCircleAct);
844 toolbar->addAction(addArcAct);
845 toolbar->addAction(addPolygonAct);
846 toolbar->addAction(addDimensionAct);
848 spinbox->setRange(4, 256);
849 spinbox->setValue(12);
850 baseUnitInput->setText("12");
851 connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int)));
852 connect(baseUnitInput, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString)));
853 connect(dimensionSizeInput, SIGNAL(textChanged(QString)), this, SLOT(HandleDimensionSize(QString)));
857 void ApplicationWindow::ReadSettings(void)
859 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
860 QSize size = settings.value("size", QSize(400, 400)).toSize();
861 drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
862 snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool());
865 restoreState(settings.value("windowState").toByteArray());
869 void ApplicationWindow::WriteSettings(void)
871 settings.setValue("pos", pos());
872 settings.setValue("size", size());
873 settings.setValue("windowState", saveState());
874 settings.setValue("useAntialiasing", drawing->useAntialiasing);
875 settings.setValue("snapToGrid", snapToGridAct->isChecked());