X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fapplicationwindow.cpp;h=cbb96362521aff7e37a2da3851551026eedde5a7;hb=97cfdecd62ced6cb1237a9ac6c7cbce2092fde99;hp=5a435a21ae3e6bfe8d82cffdf3408afaa9181f82;hpb=8d80165e3ab9173b8689b3b3420b40bf3020161f;p=architektonas diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index 5a435a2..cbb9636 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -8,7 +8,7 @@ // JLH = James Hammons // // Who When What -// --- ---------- ------------------------------------------------------------- +// --- ---------- ------------------------------------------------------------ // JLH 03/22/2011 Created this file // JLH 09/29/2011 Added simple zoom in/out functionality // JLH 10/03/2011 Fixed zoom tool to zoom in/out from center of screen @@ -30,26 +30,17 @@ #include "about.h" #include "blockwidget.h" -//#include "dimension.h" #include "drawingview.h" -//#include "drawarcaction.h" -//#include "drawcircleaction.h" -//#include "drawdimensionaction.h" -//#include "drawlineaction.h" -//#include "drawsplineaction.h" #include "fileio.h" #include "generaltab.h" -//#include "geometry.h" #include "global.h" #include "layerwidget.h" -//#include "line.h" -//#include "mirroraction.h" +#include "objectwidget.h" #include "painter.h" -//#include "rotateaction.h" +#include "penwidget.h" #include "settingsdialog.h" #include "structs.h" -//#include "triangulateaction.h" -//#include "trimaction.h" +#include "utils.h" // Class variables @@ -86,11 +77,16 @@ ApplicationWindow::ApplicationWindow(): BlockWidget * bw = new BlockWidget; dock2->setWidget(bw); addDockWidget(Qt::RightDockWidgetArea, dock2); + QDockWidget * dock3 = new QDockWidget(tr("Object"), this); + ObjectWidget * ow = new ObjectWidget; + dock3->setWidget(ow); + addDockWidget(Qt::RightDockWidgetArea, dock3); // Needed for saveState() dock1->setObjectName("Layers"); dock2->setObjectName("Blocks"); + dock3->setObjectName("Object"); - // Create status bar + // Create status bar zoomIndicator = new QLabel("Grid: 12.0\" BU: Inch"); statusBar()->addPermanentWidget(zoomIndicator); statusBar()->showMessage(tr("Ready")); @@ -99,7 +95,12 @@ ApplicationWindow::ApplicationWindow(): setUnifiedTitleAndToolBarOnMac(true); Global::font = new QFont("Verdana", 15, QFont::Bold); - connect(lw, SIGNAL(LayerSelected(int)), drawing, SLOT(SetCurrentLayer(int))); + connect(lw, SIGNAL(LayerDeleted(int)), drawing, SLOT(DeleteCurrentLayer(int))); + connect(lw, SIGNAL(LayerToggled()), drawing, SLOT(HandleLayerToggle())); + connect(lw, SIGNAL(LayersSwapped(int, int)), drawing, SLOT(HandleLayerSwap(int, int))); + connect(this, SIGNAL(ReloadLayers()), lw, SLOT(Reload())); + + connect(drawing, SIGNAL(ObjectHovered(Object *)), ow, SLOT(ShowInfo(Object *))); } @@ -113,8 +114,38 @@ void ApplicationWindow::closeEvent(QCloseEvent * event) void ApplicationWindow::FileNew(void) { - // Should warn the user if drawing hasn't been saved... - drawing->document.objects.empty(); + // Warn the user if drawing has changed and hasn't been saved... + if (drawing->dirty) + { + QMessageBox msg; + + msg.setText("The document has been modified."); + msg.setInformativeText("Do you want to save your changes?"); + msg.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + msg.setDefaultButton(QMessageBox::Save); + int response = msg.exec(); + + switch (response) + { + case QMessageBox::Save: + // Save was clicked + FileSave(); + break; + case QMessageBox::Discard: + // Don't Save was clicked + break; + case QMessageBox::Cancel: + // Cancel was clicked + return; +// break; + } + } + + FileIO::ResetLayerVectors(); + emit ReloadLayers(); + DeleteContents(drawing->document.objects); + drawing->document.objects.clear(); + drawing->dirty = false; drawing->update(); documentName.clear(); setWindowTitle("Architektonas - Untitled"); @@ -142,7 +173,7 @@ void ApplicationWindow::FileOpen(void) return; } - Container container;//(Vector(0, 0)); + Container container(true); // Make sure it's a top level container... bool successful = FileIO::LoadAtnsFile(file, &container); fclose(file); @@ -152,11 +183,20 @@ void ApplicationWindow::FileOpen(void) msg.setText(QString(tr("Could not load file \"%1\"!")).arg(filename)); msg.setIcon(QMessageBox::Critical); msg.exec(); + // Make sure to delete any hanging objects in the container... + DeleteContents(container.objects); return; } -printf("FileOpen: container size = %li\n", container.objects.size()); +//printf("FileOpen: container size = %li\n", container.objects.size()); + // Keep memory leaks from happening by getting rid of the old document + DeleteContents(drawing->document.objects); + emit ReloadLayers(); + // We can do this because the vector is just a bunch of pointers to our + // Objects, and the Containers (non-empty) can be moved this way with no + // problem. drawing->document = container; + drawing->dirty = false; drawing->update(); documentName = filename; setWindowTitle(QString("Architektonas - %1").arg(documentName)); @@ -190,12 +230,14 @@ void ApplicationWindow::FileSave(void) msg.setText(QString(tr("Could not save file \"%1\"!")).arg(documentName)); msg.setIcon(QMessageBox::Critical); msg.exec(); - // In this case, we should unlink the created file, since it's not right... + // In this case, we should unlink the created file, since it's not + // right... // unlink(documentName.toUtf8().data()); QFile::remove(documentName); return; } + drawing->dirty = false; setWindowTitle(QString("Architektonas - %1").arg(documentName)); statusBar()->showMessage(tr("Drawing saved.")); } @@ -214,6 +256,16 @@ void ApplicationWindow::FileSaveAs(void) } +void ApplicationWindow::contextMenuEvent(QContextMenuEvent * event) +{ + QMenu menu(this); + menu.addAction(mirrorAct); + menu.addAction(rotateAct); + menu.addAction(trimAct); + menu.exec(event->globalPos()); +} + + void ApplicationWindow::SnapToGridTool(void) { Global::snapToGrid = snapToGridAct->isChecked(); @@ -236,9 +288,10 @@ void ApplicationWindow::DeleteTool(void) { // For this tool, we check first to see if anything is selected. If so, we // delete those and *don't* select the delete tool. - if (drawing->numSelected > 0) +// if (drawing->numSelected > 0) + if (drawing->select.size() > 0) { - drawing->DeleteSelectedItems(); + DeleteSelectedObjects(drawing->document.objects); drawing->update(); deleteAct->setChecked(false); return; @@ -260,6 +313,11 @@ void ApplicationWindow::DimensionTool(void) void ApplicationWindow::RotateTool(void) { ClearUIToolStatesExcept(rotateAct); + + // Do tear-down if Rotate tool has been turned off + if (!rotateAct->isChecked()) + drawing->RotateHandler(ToolCleanup, Point(0, 0)); + SetInternalToolStates(); } @@ -267,6 +325,11 @@ void ApplicationWindow::RotateTool(void) void ApplicationWindow::MirrorTool(void) { ClearUIToolStatesExcept(mirrorAct); + + // Do tear-down if Rotate tool has been turned off + if (!mirrorAct->isChecked()) + drawing->MirrorHandler(ToolCleanup, Point(0, 0)); + SetInternalToolStates(); } @@ -414,33 +477,11 @@ void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception) void ApplicationWindow::SetInternalToolStates(void) { -// Global::deleteActive = deleteAct->isChecked(); -// Global::dimensionActive = addDimensionAct->isChecked(); - // We can be sure that if we've come here, then either an active tool is // being deactivated, or a new tool is being created. In either case, the // old tool needs to be deleted. -#if 0 - if (drawing->toolAction) - { - delete drawing->toolAction; - drawing->toolAction = NULL; - Global::ignoreClicks = false; - } + Global::toolState = TSNone; - drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL); - drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL); - drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL); - drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL); - drawing->SetToolActive(addSplineAct->isChecked() ? new DrawSplineAction() : NULL); - drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL); - drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL); - drawing->SetToolActive(trimAct->isChecked() ? new TrimAction() : NULL); - drawing->SetToolActive(triangulateAct->isChecked() ? new TriangulateAction() : NULL); - - if (drawing->toolAction) - Global::ignoreClicks = true; -#else if (addLineAct->isChecked()) Global::tool = TTLine; else if (addCircleAct->isChecked()) @@ -465,7 +506,6 @@ void ApplicationWindow::SetInternalToolStates(void) Global::tool = TTTriangulate; else Global::tool = TTNone; -#endif drawing->update(); } @@ -497,11 +537,10 @@ void ApplicationWindow::Settings(void) // void ApplicationWindow::HandleGrouping(void) { -#if 0 - int itemsSelected = drawing->document.ItemsSelected(); + int numSelected = drawing->select.size(); // If nothing selected, do nothing - if (itemsSelected == 0) + if (numSelected == 0) { statusBar()->showMessage(tr("No objects selected to make a group from.")); return; @@ -509,18 +548,11 @@ void ApplicationWindow::HandleGrouping(void) // If it's a group that's selected, ungroup it and leave the objects in a // selected state - if (itemsSelected == 1) + if (numSelected == 1) { - Object * object = drawing->document.SelectedItem(0); + Object * obj = (Object *)drawing->select[0]; -#if 0 -if (object == NULL) - printf("SelectedItem = NULL!\n"); -else - printf("SelectedItem = %08X, type = %i\n", object, object->type); -#endif - - if (object == NULL || object->type != OTContainer) + if (obj->type != OTContainer) { statusBar()->showMessage(tr("A group requires two or more selected objects.")); return; @@ -528,25 +560,39 @@ else // Need the parent of the group, we're assuming here that the parent is // the drawing's document. Does it matter? Maybe... - // Could just stipulate that grouping like this only takes place where the - // parent of the group is the drawing's document. Makes life much simpler. - ((Container *)object)->SelectAll(); - ((Container *)object)->MoveContentsTo(&(drawing->document)); - drawing->document.Delete(object); + // Could just stipulate that grouping like this only takes place where + // the parent of the group is the drawing's document. Makes life much + // simpler. + Container * c = (Container *)obj; + SelectAll(c->objects); + RemoveSelectedObjects(drawing->document.objects); + AddObjectsTo(drawing->document.objects, c->objects); + drawing->select.clear(); + AddObjectsTo(drawing->select, c->objects); + delete c; statusBar()->showMessage(tr("Objects ungrouped.")); +//printf("Ungroup: document size = %li\n", drawing->document.objects.size()); } // Otherwise, if it's a group of 2 or more objects (which can be groups too) // group them and select the group - else if (itemsSelected > 1) + else if (numSelected > 1) { - Container * container = new Container(Vector(), &(drawing->document)); - drawing->document.MoveSelectedContentsTo(container); - drawing->document.Add(container); - container->DeselectAll(); - container->state = OSSelected; - statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected)); + Container * c = new Container(); + MoveSelectedObjectsTo(c->objects, drawing->document.objects); + drawing->document.objects.push_back(c); + ClearSelected(c->objects); + c->selected = true; + c->layer = Global::activeLayer; + + Rect r = drawing->GetObjectExtents((Object *)c); + c->p[0] = r.TopLeft(); + c->p[1] = r.BottomRight(); + + drawing->select.clear(); + drawing->select.push_back(c); + statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(numSelected)); +//printf("Group: document size = %li\n", drawing->document.objects.size()); } -#endif drawing->update(); } @@ -617,6 +663,7 @@ printf(" -> intersects = %i, t=%lf, u=%lf\n", intersects, t, u); } } } +#else #endif } @@ -654,6 +701,9 @@ void ApplicationWindow::HandleGridSizeInBaseUnits(QString text) void ApplicationWindow::HandleDimensionSize(QString text) { +/* +This is the third input on the view toolbar; not sure what it was supposed to do... +*/ // Parse the text... bool ok; double value = text.toDouble(&ok); @@ -666,6 +716,39 @@ void ApplicationWindow::HandleDimensionSize(QString text) drawing->update(); } +void ApplicationWindow::EditCopy(void) +{ + if (drawing->select.size() > 0) + { + DeleteContents(clipboard); + CopySelectedObjectsTo(clipboard, drawing->document.objects); + } +} + + +void ApplicationWindow::EditCut(void) +{ + if (drawing->select.size() > 0) + { + DeleteContents(clipboard); + MoveSelectedObjectsTo(clipboard, drawing->document.objects); + drawing->update(); + } +} + + +void ApplicationWindow::EditPaste(void) +{ + if (clipboard.size() > 0) + { + // We want to maybe make it so that the pasted objects are being moved in a "mouse drag" state... + // This only moves the cut/copied from the clipboard to the drawing. +// AddObjectsTo(drawing->document.objects, clipboard); + CopyObjects(clipboard, drawing->document.objects); + drawing->update(); + } +} + void ApplicationWindow::CreateActions(void) { @@ -752,6 +835,14 @@ void ApplicationWindow::CreateActions(void) triangulateAct = CreateAction(tr("&Triangulate"), tr("Triangulate"), tr("Make triangles from selected lines, preserving their lengths."), QIcon(":/res/triangulate-tool.png"), QKeySequence("t,g"), true); connect(triangulateAct, SIGNAL(triggered()), this, SLOT(TriangulateTool())); + editCutAct = CreateAction(tr("&Cut Objects"), tr("Cut Objects"), tr("Cut objects from the drawing to the clipboard."), QIcon(":/res/editcut2.png"), QKeySequence(tr("Ctrl+x"))); + connect(editCutAct, SIGNAL(triggered()), this, SLOT(EditCut())); + + editCopyAct = CreateAction(tr("&Copy Objects"), tr("Copy Objects"), tr("Copy objects from the drawing to the clipboard."), QIcon(":/res/editcopy2.png"), QKeySequence(tr("Ctrl+c"))); + connect(editCopyAct, SIGNAL(triggered()), this, SLOT(EditCopy())); + + editPasteAct = CreateAction(tr("&Paste Objects"), tr("Paste Objects"), tr("Paste objects from the clipboard to the drawing."), QIcon(":/res/editpaste2.png"), QKeySequence(tr("Ctrl+v"))); + connect(editPasteAct, SIGNAL(triggered()), this, SLOT(EditPaste())); //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing... // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick. @@ -767,8 +858,8 @@ void ApplicationWindow::CreateActions(void) // // Consolidates action creation from a multi-step process to a single-step one. // -QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip, - QIcon icon, QKeySequence key, bool checkable/*= false*/) +QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, + QString statustip, QIcon icon, QKeySequence key, bool checkable/*= false*/) { QAction * action = new QAction(icon, name, this); action->setToolTip(tooltip); @@ -784,8 +875,9 @@ QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString // This is essentially the same as the previous function, but this allows more // than one key sequence to be added as key shortcuts. // -QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString statustip, - QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/) +QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, + QString statustip, QIcon icon, QKeySequence key1, QKeySequence key2, + bool checkable/*= false*/) { QAction * action = new QAction(icon, name, this); action->setToolTip(tooltip); @@ -827,6 +919,9 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(connectAct); menu->addAction(disconnectAct); menu->addSeparator(); + menu->addAction(editCutAct); + menu->addAction(editCopyAct); + menu->addAction(editPasteAct); menu->addAction(deleteAct); menu->addSeparator(); menu->addAction(addLineAct); @@ -875,6 +970,9 @@ void ApplicationWindow::CreateToolbars(void) toolbar->addAction(mirrorAct); toolbar->addAction(trimAct); toolbar->addAction(triangulateAct); + toolbar->addAction(editCutAct); + toolbar->addAction(editCopyAct); + toolbar->addAction(editPasteAct); toolbar->addAction(deleteAct); toolbar->addAction(connectAct); toolbar->addAction(disconnectAct); @@ -892,6 +990,15 @@ void ApplicationWindow::CreateToolbars(void) connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int))); connect(baseUnitInput, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString))); connect(dimensionSizeInput, SIGNAL(textChanged(QString)), this, SLOT(HandleDimensionSize(QString))); + + PenWidget * pw = new PenWidget(); + toolbar = addToolBar(tr("Pen")); + toolbar->setObjectName(tr("Pen")); + toolbar->addWidget(pw); + connect(drawing, SIGNAL(ObjectSelected(Object *)), pw, SLOT(SetFields(Object *))); + connect(pw, SIGNAL(WidthSelected(float)), drawing, SLOT(HandlePenWidth(float))); + connect(pw, SIGNAL(StyleSelected(int)), drawing, SLOT(HandlePenStyle(int))); + connect(pw, SIGNAL(ColorSelected(uint32_t)), drawing, SLOT(HandlePenColor(uint32_t))); }