X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fapplicationwindow.cpp;h=a9108eb5f6d3d2b5d96b5280b99e13652013f6ed;hb=ba6723b86d8dd67ebc7b11b245de3e7ff64f06b1;hp=c580cde948ab4b37535ec2b5f395600fe83cbb0d;hpb=6441dd1283d8a16b9a3a02df407f20434fa9dfa1;p=architektonas diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index c580cde..a9108eb 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -30,6 +30,7 @@ #include "about.h" #include "drawingview.h" +#include "fileio.h" #include "generaltab.h" #include "painter.h" #include "settingsdialog.h" @@ -53,6 +54,8 @@ ApplicationWindow::ApplicationWindow(): settings("Underground Software", "Archit CreateToolbars(); // Create status bar + zoomIndicator = new QLabel("Grid: 12.0\" Zoom: 12.5%"); + statusBar()->addPermanentWidget(zoomIndicator); statusBar()->showMessage(tr("Ready")); ReadSettings(); @@ -67,6 +70,7 @@ ApplicationWindow::ApplicationWindow(): settings("Underground Software", "Archit Object::SetFont(new QFont("Verdana", 15, QFont::Bold)); } + void ApplicationWindow::closeEvent(QCloseEvent * event) { WriteSettings(); @@ -74,53 +78,173 @@ void ApplicationWindow::closeEvent(QCloseEvent * event) //Do we have a memory leak here if we don't delete the font in the Object??? } -//void ApplicationWindow::FileOpen(void) -//{ -//} + +void ApplicationWindow::FileNew(void) +{ + // Should warn the user if drawing hasn't been saved... + drawing->document.Clear(); + drawing->update(); + documentName.clear(); + setWindowTitle("Architektonas - Untitled"); + statusBar()->showMessage(tr("New drawing is ready.")); +} + + +void ApplicationWindow::FileOpen(void) +{ + QString filename = QFileDialog::getOpenFileName(this, tr("Open Drawing"), + "", tr("Architektonas files (*.drawing)")); + FILE * file = fopen(filename.toAscii().data(), "r"); + + if (file == 0) + { + QMessageBox msg; + msg.setText(QString(tr("Could not open file \"%1\" for loading!")).arg(filename)); + msg.setIcon(QMessageBox::Critical); + msg.exec(); + return; + } + + Container container(Vector(0, 0)); + bool successful = FileIO::LoadAtnsFile(file, &container); + fclose(file); + + if (!successful) + { + QMessageBox msg; + msg.setText(QString(tr("Could not load file \"%1\"!")).arg(filename)); + msg.setIcon(QMessageBox::Critical); + msg.exec(); + return; + } + +printf("FileOpen: container size = %li\n", container.objects.size()); + drawing->document = container; + drawing->update(); + documentName = filename; + setWindowTitle(QString("Architektonas - %1").arg(documentName)); + statusBar()->showMessage(tr("Drawing loaded.")); +} + + +void ApplicationWindow::FileSave(void) +{ + if (documentName.isEmpty()) + documentName = QFileDialog::getSaveFileName(this, tr("Save Drawing"), + "", tr("Architektonas drawings (*.drawing)")); + + FILE * file = fopen(documentName.toAscii().data(), "w"); + + if (file == 0) + { + QMessageBox msg; + msg.setText(QString(tr("Could not open file \"%1\" for saving!")).arg(documentName)); + msg.setIcon(QMessageBox::Critical); + msg.exec(); + return; + } + + bool successful = FileIO::SaveAtnsFile(file, &drawing->document); + fclose(file); + + if (!successful) + { + QMessageBox msg; + 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... + unlink(documentName.toAscii().data()); + return; + } + + setWindowTitle(QString("Architektonas - %1").arg(documentName)); + statusBar()->showMessage(tr("Drawing saved.")); +} + + +void ApplicationWindow::FileSaveAs(void) +{ + QString filename = QFileDialog::getSaveFileName(this, tr("Save Drawing As"), + documentName, tr("Architektonas drawings (*.drawing)")); + + if (!filename.isEmpty()) + { + documentName = filename; + FileSave(); + } +} + + +void ApplicationWindow::SnapToGridTool(void) +{ + Object::SetSnapMode(snapToGridAct->isChecked()); +} + void ApplicationWindow::FixAngle(void) { Object::SetFixedAngle(fixAngleAct->isChecked()); } + void ApplicationWindow::FixLength(void) { Object::SetFixedLength(fixLengthAct->isChecked()); } + +// We want certain tools to be exclusive, and this approach isn't working correctly... void ApplicationWindow::DeleteTool(void) { - Object::SetDeleteActive(deleteAct->isChecked()); + + ClearUIToolStatesExcept(deleteAct); + SetInternalToolStates(); } + void ApplicationWindow::DimensionTool(void) { - Object::SetDimensionActive(addDimensionAct->isChecked()); + ClearUIToolStatesExcept(addDimensionAct); + SetInternalToolStates(); } + void ApplicationWindow::RotateTool(void) { - drawing->SetRotateToolActive(rotateAct->isChecked()); + ClearUIToolStatesExcept(rotateAct); + SetInternalToolStates(); } + void ApplicationWindow::AddLineTool(void) { - addCircleAct->setChecked(false); - addArcAct->setChecked(false); - rotateAct->setChecked(false); - RotateTool(); - drawing->SetAddLineToolActive(addLineAct->isChecked()); + ClearUIToolStatesExcept(addLineAct); + SetInternalToolStates(); } + void ApplicationWindow::AddCircleTool(void) { - addLineAct->setChecked(false); - addArcAct->setChecked(false); - rotateAct->setChecked(false); - RotateTool(); - drawing->SetAddCircleToolActive(addCircleAct->isChecked()); + ClearUIToolStatesExcept(addCircleAct); + SetInternalToolStates(); } + +void ApplicationWindow::AddArcTool(void) +{ + ClearUIToolStatesExcept(addArcAct); + SetInternalToolStates(); +} + + +void ApplicationWindow::AddPolygonTool(void) +{ + ClearUIToolStatesExcept(addPolygonAct); + SetInternalToolStates(); +} + + void ApplicationWindow::ZoomInTool(void) { double zoomFactor = 2.0; @@ -149,9 +273,13 @@ when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin. //printf("Zoom in... level going from %02f to ", Painter::zoom); // This just zooms leaving origin intact... should zoom in at the current center! [DONE] Painter::zoom *= zoomFactor; + drawing->gridSpacing = 12.0 / Painter::zoom; + zoomIndicator->setText(QString("Grid: %2\" Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM).arg(drawing->gridSpacing)); + drawing->UpdateGridBackground(); drawing->update(); } + void ApplicationWindow::ZoomOutTool(void) { /* @@ -181,14 +309,65 @@ x 2 = (-426, -301) //printf("Zoom out...\n"); // This just zooms leaving origin intact... should zoom out at the current center! [DONE] Painter::zoom /= zoomFactor; + drawing->gridSpacing = 12.0 / Painter::zoom; + zoomIndicator->setText(QString("Grid: %2\" Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM).arg(drawing->gridSpacing)); + drawing->UpdateGridBackground(); drawing->update(); } + +void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception) +{ + if (exception != addArcAct) + addArcAct->setChecked(false); + + if (exception != addCircleAct) + addCircleAct->setChecked(false); + + if (exception != addDimensionAct) + addDimensionAct->setChecked(false); + + if (exception != addLineAct) + addLineAct->setChecked(false); + + if (exception != addPolygonAct) + addPolygonAct->setChecked(false); + + if (exception != deleteAct) + deleteAct->setChecked(false); + + if (exception != rotateAct) + rotateAct->setChecked(false); +} + + +void ApplicationWindow::SetInternalToolStates(void) +{ + Object::SetDeleteActive(deleteAct->isChecked()); + Object::SetDimensionActive(addDimensionAct->isChecked()); + drawing->SetRotateToolActive(rotateAct->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 (drawing->toolAction) + { + delete drawing->toolAction; + drawing->toolAction = NULL; + } + + drawing->SetAddLineToolActive(addLineAct->isChecked()); + drawing->SetAddCircleToolActive(addCircleAct->isChecked()); + drawing->SetAddDimensionToolActive(addDimensionAct->isChecked()); +} + + void ApplicationWindow::HelpAbout(void) { aboutWin->show(); } + void ApplicationWindow::Settings(void) { SettingsDialog dlg(this); @@ -202,12 +381,68 @@ void ApplicationWindow::Settings(void) WriteSettings(); } + +void ApplicationWindow::HandleGrouping(void) +{ + // Group a bunch of selected objects together or ungroup a selected group. + + if (drawing->document.ItemsSelected() == 0) + { + statusBar()->showMessage(tr("No objects selected to make a group from.")); + return; + } + + // If it's a group that's selected, ungroup it and leave the objects in a + // selected state + if (drawing->document.ItemsSelected() == 1) + { + Object * object = drawing->document.SelectedItem(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) + { + statusBar()->showMessage(tr("A group requires two or more selected objects.")); + return; + } + + // 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); + } + // Otherwise, if it's a group of 2 or more objects (which can be groups too) + // group them and select the group + else if (drawing->document.ItemsSelected() > 1) + { + Container * container = new Container(Vector(), &(drawing->document)); + drawing->document.MoveSelectedContentsTo(container); + drawing->document.Add(container); + container->DeselectAll(); + container->state = OSSelected; + } + + drawing->update(); +} + + void ApplicationWindow::CreateActions(void) { exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."), QIcon(":/res/quit.png"), QKeySequence(tr("Ctrl+q"))); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + snapToGridAct = CreateAction(tr("Snap To &Grid"), tr("Snap To Grid"), tr("Snaps mouse cursor to the visible grid when moving/creating objects."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("S")), true); + connect(snapToGridAct, SIGNAL(triggered()), this, SLOT(SnapToGridTool())); + fixAngleAct = CreateAction(tr("Fix &Angle"), tr("Fix Angle"), tr("Fixes the angle of an object."), QIcon(":/res/fix-angle.png"), QKeySequence(tr("F,A")), true); connect(fixAngleAct, SIGNAL(triggered()), this, SLOT(FixAngle())); @@ -229,8 +464,10 @@ void ApplicationWindow::CreateActions(void) connect(addCircleAct, SIGNAL(triggered()), this, SLOT(AddCircleTool())); addArcAct = CreateAction(tr("Add &Arc"), tr("Add Arc"), tr("Adds arcs to the drawing."), QIcon(":/res/add-arc-tool.png"), QKeySequence("A,A"), true); + connect(addArcAct, SIGNAL(triggered()), this, SLOT(AddArcTool())); addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true); + connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool())); aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence()); connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout())); @@ -245,19 +482,27 @@ void ApplicationWindow::CreateActions(void) connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOutTool())); fileNewAct = CreateAction(tr("&New Drawing"), tr("New Drawing"), tr("Creates a new drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+n"))); + connect(fileNewAct, SIGNAL(triggered()), this, SLOT(FileNew())); fileOpenAct = CreateAction(tr("&Open Drawing"), tr("Open Drawing"), tr("Opens an existing drawing from a file."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+o"))); + connect(fileOpenAct, SIGNAL(triggered()), this, SLOT(FileOpen())); fileSaveAct = CreateAction(tr("&Save Drawing"), tr("Save Drawing"), tr("Saves the current drawing to a file."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+s"))); + connect(fileSaveAct, SIGNAL(triggered()), this, SLOT(FileSave())); fileSaveAsAct = CreateAction(tr("Save Drawing &As"), tr("Save As"), tr("Saves the current drawing to a file with a different name."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+Shift+s"))); + connect(fileSaveAsAct, SIGNAL(triggered()), this, SLOT(FileSaveAs())); fileCloseAct = CreateAction(tr("&Close Drawing"), tr("Close Drawing"), tr("Closes the current drawing."), QIcon(":/res/generic-tool.png"), QKeySequence(tr("Ctrl+w"))); settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/generic-tool.png"), QKeySequence()); connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings())); + groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/generic-tool.png"), QKeySequence("g")); + connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping())); + //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. /* QActionGroup * group = new QActionGroup(this); group->addAction(deleteAct); group->addAction(addDimensionAct); @@ -266,6 +511,7 @@ void ApplicationWindow::CreateActions(void) group->addAction(addArcAct);//*/ } + // // Consolidates action creation from a multi-step process to a single-step one. // @@ -281,6 +527,7 @@ QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString return action; } + // // This is essentially the same as the previous function, but this allows more // than one key sequence to be added as key shortcuts. @@ -300,6 +547,7 @@ QAction * ApplicationWindow::CreateAction(QString name, QString tooltip, QString return action; } + void ApplicationWindow::CreateMenus(void) { QMenu * menu = menuBar()->addMenu(tr("&File")); @@ -316,6 +564,8 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(zoomOutAct); menu = menuBar()->addMenu(tr("&Edit")); + menu->addAction(snapToGridAct); + menu->addAction(groupAct); menu->addAction(fixAngleAct); menu->addAction(fixLengthAct); menu->addAction(rotateAct); @@ -334,6 +584,7 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(aboutAct); } + void ApplicationWindow::CreateToolbars(void) { QToolBar * toolbar = addToolBar(tr("File")); @@ -344,21 +595,27 @@ void ApplicationWindow::CreateToolbars(void) toolbar->addAction(zoomOutAct); toolbar = addToolBar(tr("Edit")); + toolbar->addAction(snapToGridAct); + toolbar->addAction(groupAct); toolbar->addAction(fixAngleAct); toolbar->addAction(fixLengthAct); toolbar->addAction(rotateAct); toolbar->addAction(deleteAct); + toolbar->addSeparator(); toolbar->addAction(addLineAct); toolbar->addAction(addCircleAct); toolbar->addAction(addArcAct); + toolbar->addAction(addPolygonAct); toolbar->addAction(addDimensionAct); } + void ApplicationWindow::ReadSettings(void) { QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); QSize size = settings.value("size", QSize(400, 400)).toSize(); drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool(); + snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool()); resize(size); move(pos); // pos = settings.value("charWndPos", QPoint(0, 0)).toPoint(); @@ -367,11 +624,14 @@ void ApplicationWindow::ReadSettings(void) // ((TTEdit *)qApp)->charWnd->move(pos); } + void ApplicationWindow::WriteSettings(void) { settings.setValue("pos", pos()); settings.setValue("size", size()); settings.setValue("useAntialiasing", drawing->useAntialiasing); + settings.setValue("snapToGrid", snapToGridAct->isChecked()); // settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos()); // settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size()); } +