diff -r ab77deb851fa -r 8d98ee0dc917 src/actionsEdit.cc
--- a/src/actionsEdit.cc Tue Mar 03 16:50:39 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,738 +0,0 @@
-/*
- * LDForge: LDraw parts authoring CAD
- * Copyright (C) 2013 - 2015 Teemu Piippo
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include "mainWindow.h"
-#include "main.h"
-#include "ldDocument.h"
-#include "colorSelector.h"
-#include "miscallenous.h"
-#include "radioGroup.h"
-#include "glRenderer.h"
-#include "dialogs.h"
-#include "colors.h"
-#include "ldObjectMath.h"
-#include "ui_replcoords.h"
-#include "ui_editraw.h"
-#include "ui_flip.h"
-#include "ui_addhistoryline.h"
-
-EXTERN_CFGENTRY (String, DefaultUser)
-
-CFGENTRY (Int, RoundPosition, 3)
-CFGENTRY (Int, RoundMatrix, 4)
-CFGENTRY (Int, SplitLinesSegments, 5)
-
-// =============================================================================
-//
-static int CopyToClipboard()
-{
- LDObjectList objs = Selection();
- int num = 0;
-
- // Clear the clipboard first.
- qApp->clipboard()->clear();
-
- // Now, copy the contents into the clipboard.
- QString data;
-
- for (LDObjectPtr obj : objs)
- {
- if (not data.isEmpty())
- data += "\n";
-
- data += obj->asText();
- ++num;
- }
-
- qApp->clipboard()->setText (data);
- return num;
-}
-
-// =============================================================================
-//
-void MainWindow::actionCut()
-{
- int num = CopyToClipboard();
- deleteSelection();
- print (tr ("%1 objects cut"), num);
-}
-
-// =============================================================================
-//
-void MainWindow::actionCopy()
-{
- int num = CopyToClipboard();
- print (tr ("%1 objects copied"), num);
-}
-
-// =============================================================================
-//
-void MainWindow::actionPaste()
-{
- const QString clipboardText = qApp->clipboard()->text();
- int idx = getInsertionPoint();
- CurrentDocument()->clearSelection();
- int num = 0;
-
- for (QString line : clipboardText.split ("\n"))
- {
- LDObjectPtr pasted = ParseLine (line);
- CurrentDocument()->insertObj (idx++, pasted);
- pasted->select();
- ++num;
- }
-
- print (tr ("%1 objects pasted"), num);
- refresh();
- scrollToSelection();
-}
-
-// =============================================================================
-//
-void MainWindow::actionDelete()
-{
- int num = deleteSelection();
- print (tr ("%1 objects deleted"), num);
-}
-
-// =============================================================================
-//
-static void DoInline (bool deep)
-{
- LDObjectList sel = Selection();
-
- LDIterate (Selection(), [&](LDSubfilePtr const& ref)
- {
- // Get the index of the subfile so we know where to insert the
- // inlined contents.
- long idx = ref->lineNumber();
-
- assert (idx != -1);
- LDObjectList objs = ref->inlineContents (deep, false);
-
- // Merge in the inlined objects
- for (LDObjectPtr inlineobj : objs)
- {
- QString line = inlineobj->asText();
- inlineobj->destroy();
- LDObjectPtr newobj = ParseLine (line);
- CurrentDocument()->insertObj (idx++, newobj);
- newobj->select();
- }
-
- // Delete the subfile now as it's been inlined.
- ref->destroy();
- });
-
- g_win->refresh();
-}
-
-void MainWindow::actionInline()
-{
- DoInline (false);
-}
-
-void MainWindow::actionInlineDeep()
-{
- DoInline (true);
-}
-
-// =============================================================================
-//
-void MainWindow::actionSplitQuads()
-{
- int num = 0;
-
- LDIterate (Selection(), [&](LDQuadPtr const& quad)
- {
- // Find the index of this quad
- long index = quad->lineNumber();
-
- if (index == -1)
- return;
-
- QList triangles = quad->splitToTriangles();
-
- // Replace the quad with the first triangle and add the second triangle
- // after the first one.
- CurrentDocument()->setObject (index, triangles[0]);
- CurrentDocument()->insertObj (index + 1, triangles[1]);
- num++;
- });
-
- print ("%1 quadrilaterals split", num);
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionEditRaw()
-{
- if (Selection().size() != 1)
- return;
-
- LDObjectPtr obj = Selection()[0];
- QDialog* dlg = new QDialog;
- Ui::EditRawUI ui;
-
- ui.setupUi (dlg);
- ui.code->setText (obj->asText());
-
- if (obj->type() == OBJ_Error)
- ui.errorDescription->setText (obj.staticCast()->reason());
- else
- {
- ui.errorDescription->hide();
- ui.errorIcon->hide();
- }
-
- if (dlg->exec() == QDialog::Rejected)
- return;
-
- // Reinterpret it from the text of the input field
- LDObjectPtr newobj = ParseLine (ui.code->text());
- obj->replace (newobj);
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionSetColor()
-{
- if (Selection().isEmpty())
- return;
-
- LDObjectList objs = Selection();
-
- // If all selected objects have the same color, said color is our default
- // value to the color selection dialog.
- LDColor color;
- LDColor defaultcol = getSelectedColor();
-
- // Show the dialog to the user now and ask for a color.
- if (ColorSelector::selectColor (color, defaultcol, g_win))
- {
- for (LDObjectPtr obj : objs)
- {
- if (obj->isColored())
- obj->setColor (color);
- }
-
- refresh();
- }
-}
-
-// =============================================================================
-//
-void MainWindow::actionBorders()
-{
- LDObjectList objs = Selection();
- int num = 0;
-
- for (LDObjectPtr obj : objs)
- {
- const LDObjectType type = obj->type();
-
- if (type != OBJ_Quad and type != OBJ_Triangle)
- continue;
-
- LDLinePtr lines[4];
-
- if (type == OBJ_Quad)
- {
- LDQuadPtr quad = obj.staticCast();
- lines[0] = LDSpawn (quad->vertex (0), quad->vertex (1));
- lines[1] = LDSpawn (quad->vertex (1), quad->vertex (2));
- lines[2] = LDSpawn (quad->vertex (2), quad->vertex (3));
- lines[3] = LDSpawn (quad->vertex (3), quad->vertex (0));
- }
- else
- {
- LDTrianglePtr tri = obj.staticCast();
- lines[0] = LDSpawn (tri->vertex (0), tri->vertex (1));
- lines[1] = LDSpawn (tri->vertex (1), tri->vertex (2));
- lines[2] = LDSpawn (tri->vertex (2), tri->vertex (0));
- }
-
- for (int i = 0; i < countof (lines); ++i)
- {
- if (lines[i] == null)
- continue;
-
- long idx = obj->lineNumber() + i + 1;
- CurrentDocument()->insertObj (idx, lines[i]);
- }
-
- num += countof (lines);
- }
-
- print (tr ("Added %1 border lines"), num);
- refresh();
-}
-
-// =============================================================================
-//
-static void MoveSelection (const bool up)
-{
- LDObjectList objs = Selection();
- LDObject::moveObjects (objs, up);
- g_win->buildObjList();
-}
-
-// =============================================================================
-//
-void MainWindow::actionMoveUp()
-{
- MoveSelection (true);
-}
-
-void MainWindow::actionMoveDown()
-{
- MoveSelection (false);
-}
-
-// =============================================================================
-//
-void MainWindow::actionUndo()
-{
- CurrentDocument()->undo();
-}
-
-void MainWindow::actionRedo()
-{
- CurrentDocument()->redo();
-}
-
-// =============================================================================
-//
-static void MoveObjects (Vertex vect)
-{
- // Apply the grid values
- vect *= *CurrentGrid().coordinateSnap;
-
- for (LDObjectPtr obj : Selection())
- obj->move (vect);
-
- g_win->refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionMoveXNeg()
-{
- MoveObjects ({-1, 0, 0});
-}
-
-void MainWindow::actionMoveYNeg()
-{
- MoveObjects ({0, -1, 0});
-}
-
-void MainWindow::actionMoveZNeg()
-{
- MoveObjects ({0, 0, -1});
-}
-
-void MainWindow::actionMoveXPos()
-{
- MoveObjects ({1, 0, 0});
-}
-
-void MainWindow::actionMoveYPos()
-{
- MoveObjects ({0, 1, 0});
-}
-
-void MainWindow::actionMoveZPos()
-{
- MoveObjects ({0, 0, 1});
-}
-
-// =============================================================================
-//
-void MainWindow::actionInvert()
-{
- for (LDObjectPtr obj : Selection())
- obj->invert();
-
- refresh();
-}
-
-// =============================================================================
-//
-static double GetRotateActionAngle()
-{
- return (Pi * *CurrentGrid().angleSnap) / 180;
-}
-
-void MainWindow::actionRotateXPos()
-{
- RotateObjects (1, 0, 0, GetRotateActionAngle(), Selection());
-}
-void MainWindow::actionRotateYPos()
-{
- RotateObjects (0, 1, 0, GetRotateActionAngle(), Selection());
-}
-void MainWindow::actionRotateZPos()
-{
- RotateObjects (0, 0, 1, GetRotateActionAngle(), Selection());
-}
-void MainWindow::actionRotateXNeg()
-{
- RotateObjects (-1, 0, 0, GetRotateActionAngle(), Selection());
-}
-void MainWindow::actionRotateYNeg()
-{
- RotateObjects (0, -1, 0, GetRotateActionAngle(), Selection());
-}
-void MainWindow::actionRotateZNeg()
-{
- RotateObjects (0, 0, -1, GetRotateActionAngle(), Selection());
-}
-
-void MainWindow::actionRotationPoint()
-{
- ConfigureRotationPoint();
-}
-
-// =============================================================================
-//
-void MainWindow::actionRoundCoordinates()
-{
- setlocale (LC_ALL, "C");
- int num = 0;
-
- for (LDObjectPtr obj : Selection())
- {
- LDMatrixObjectPtr mo = obj.dynamicCast();
-
- if (mo != null)
- {
- Vertex v = mo->position();
- Matrix t = mo->transform();
-
- // Note: matrix values are to be rounded to 4 decimals.
- v.apply ([](Axis, double& a) { RoundToDecimals (a, cfg::RoundPosition); });
- ApplyToMatrix (t, [](int, double& a) { RoundToDecimals (a, cfg::RoundMatrix); });
-
- mo->setPosition (v);
- mo->setTransform (t);
- num += 12;
- }
- else
- {
- for (int i = 0; i < obj->numVertices(); ++i)
- {
- Vertex v = obj->vertex (i);
- v.apply ([](Axis, double& a) { RoundToDecimals (a, cfg::RoundPosition); });
- obj->setVertex (i, v);
- num += 3;
- }
- }
- }
-
- print (tr ("Rounded %1 values"), num);
- refreshObjectList();
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionUncolor()
-{
- int num = 0;
-
- for (LDObjectPtr obj : Selection())
- {
- if (not obj->isColored())
- continue;
-
- obj->setColor (obj->defaultColor());
- num++;
- }
-
- print (tr ("%1 objects uncolored"), num);
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionReplaceCoords()
-{
- QDialog* dlg = new QDialog (g_win);
- Ui::ReplaceCoordsUI ui;
- ui.setupUi (dlg);
-
- if (not dlg->exec())
- return;
-
- const double search = ui.search->value(),
- replacement = ui.replacement->value();
- const bool any = ui.any->isChecked(),
- rel = ui.relative->isChecked();
-
- QList sel;
- int num = 0;
-
- if (ui.x->isChecked()) sel << X;
- if (ui.y->isChecked()) sel << Y;
- if (ui.z->isChecked()) sel << Z;
-
- for (LDObjectPtr obj : Selection())
- {
- for (int i = 0; i < obj->numVertices(); ++i)
- {
- Vertex v = obj->vertex (i);
-
- v.apply ([&](Axis ax, double& coord)
- {
- if (not sel.contains (ax) or
- (not any and coord != search))
- {
- return;
- }
-
- if (not rel)
- coord = 0;
-
- coord += replacement;
- num++;
- });
-
- obj->setVertex (i, v);
- }
- }
-
- print (tr ("Altered %1 values"), num);
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionFlip()
-{
- QDialog* dlg = new QDialog;
- Ui::FlipUI ui;
- ui.setupUi (dlg);
-
- if (not dlg->exec())
- return;
-
- QList sel;
-
- if (ui.x->isChecked()) sel << X;
- if (ui.y->isChecked()) sel << Y;
- if (ui.z->isChecked()) sel << Z;
-
- for (LDObjectPtr obj : Selection())
- {
- for (int i = 0; i < obj->numVertices(); ++i)
- {
- Vertex v = obj->vertex (i);
-
- v.apply ([&](Axis ax, double& a)
- {
- if (sel.contains (ax))
- a = -a;
- });
-
- obj->setVertex (i, v);
- }
- }
-
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionDemote()
-{
- int num = 0;
-
- LDIterate (Selection(), [&](LDCondLinePtr const& cnd)
- {
- cnd->toEdgeLine();
- ++num;
- });
-
- print (tr ("Demoted %1 conditional lines"), num);
- refresh();
-}
-
-// =============================================================================
-//
-static bool IsColorUsed (LDColor color)
-{
- for (LDObjectPtr obj : CurrentDocument()->objects())
- {
- if (obj->isColored() and obj->color() == color)
- return true;
- }
-
- return false;
-}
-
-// =============================================================================
-//
-void MainWindow::actionAutocolor()
-{
- int colnum = 0;
- LDColor color;
-
- for (colnum = 0;
- colnum < CountLDConfigColors() and
- ((color = LDColor::fromIndex (colnum)) == null or
- IsColorUsed (color));
- colnum++) {}
-
- if (colnum >= CountLDConfigColors())
- {
- print (tr ("Cannot auto-color: all colors are in use!"));
- return;
- }
-
- for (LDObjectPtr obj : Selection())
- {
- if (not obj->isColored())
- continue;
-
- obj->setColor (color);
- }
-
- print (tr ("Auto-colored: new color is [%1] %2"), colnum, color.name());
- refresh();
-}
-
-// =============================================================================
-//
-void MainWindow::actionAddHistoryLine()
-{
- LDObjectPtr obj;
- bool ishistory = false,
- prevIsHistory = false;
-
- QDialog* dlg = new QDialog;
- Ui_AddHistoryLine* ui = new Ui_AddHistoryLine;
- ui->setupUi (dlg);
- ui->m_username->setText (cfg::DefaultUser);
- ui->m_date->setDate (QDate::currentDate());
- ui->m_comment->setFocus();
-
- if (not dlg->exec())
- return;
-
- // Create the comment object based on input
- QString commentText = format ("!HISTORY %1 [%2] %3",
- ui->m_date->date().toString ("yyyy-MM-dd"),
- ui->m_username->text(),
- ui->m_comment->text());
-
- LDCommentPtr comm (LDSpawn (commentText));
-
- // Find a spot to place the new comment
- for (obj = CurrentDocument()->getObject (0);
- obj != null and obj->next() != null and not obj->next()->isScemantic();
- obj = obj->next())
- {
- LDCommentPtr comm = obj.dynamicCast();
-
- if (comm != null and comm->text().startsWith ("!HISTORY "))
- ishistory = true;
-
- if (prevIsHistory and not ishistory)
- {
- // Last line was history, this isn't, thus insert the new history
- // line here.
- break;
- }
-
- prevIsHistory = ishistory;
- }
-
- int idx = obj ? obj->lineNumber() : 0;
- CurrentDocument()->insertObj (idx++, comm);
-
- // If we're adding a history line right before a scemantic object, pad it
- // an empty line
- if (obj and obj->next() and obj->next()->isScemantic())
- CurrentDocument()->insertObj (idx, LDEmptyPtr (LDSpawn()));
-
- buildObjList();
- delete ui;
-}
-
-void MainWindow::actionSplitLines()
-{
- bool ok;
- int segments = QInputDialog::getInt (g_win, APPNAME, "Amount of segments:", cfg::SplitLinesSegments, 0,
- std::numeric_limits::max(), 1, &ok);
-
- if (not ok)
- return;
-
- cfg::SplitLinesSegments = segments;
-
- for (LDObjectPtr obj : Selection())
- {
- if (not Eq (obj->type(), OBJ_Line, OBJ_CondLine))
- continue;
-
- QVector newsegs;
-
- for (int i = 0; i < segments; ++i)
- {
- LDObjectPtr segment;
- Vertex v0, v1;
-
- v0.apply ([&](Axis ax, double& a)
- {
- double len = obj->vertex (1)[ax] - obj->vertex (0)[ax];
- a = (obj->vertex (0)[ax] + ((len * i) / segments));
- });
-
- v1.apply ([&](Axis ax, double& a)
- {
- double len = obj->vertex (1)[ax] - obj->vertex (0)[ax];
- a = (obj->vertex (0)[ax] + ((len * (i + 1)) / segments));
- });
-
- if (obj->type() == OBJ_Line)
- segment = LDSpawn (v0, v1);
- else
- segment = LDSpawn (v0, v1, obj->vertex (2), obj->vertex (3));
-
- newsegs << segment;
- }
-
- int ln = obj->lineNumber();
-
- for (LDObjectPtr seg : newsegs)
- CurrentDocument()->insertObj (ln++, seg);
-
- obj->destroy();
- }
-
- buildObjList();
- g_win->refresh();
-}