Fri, 09 May 2014 12:06:56 +0300
- initial overhaul with smart pointers
--- a/src/actions.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/actions.cc Fri May 09 12:06:56 2014 +0300 @@ -86,7 +86,7 @@ newFile(); - const LDBFC::Statement BFCType = + const LDBFC::Statement bfctype = ui.rb_bfc_ccw->isChecked() ? LDBFC::CertifyCCW : ui.rb_bfc_cw->isChecked() ? LDBFC::CertifyCW : LDBFC::NoCertify; @@ -94,17 +94,20 @@ ui.rb_license_ca->isChecked() ? g_CALicense : ui.rb_license_nonca->isChecked() ? g_nonCALicense : ""; - getCurrentDocument()->addObjects ( - { - new LDComment (ui.le_title->text()), - new LDComment ("Name: <untitled>.dat"), - new LDComment (format ("Author: %1", ui.le_author->text())), - new LDComment (format ("!LDRAW_ORG Unofficial_Part")), - (license != "" ? new LDComment (license) : null), - new LDEmpty, - new LDBFC (BFCType), - new LDEmpty, - }); + LDObjectList objs; + objs << spawn<LDComment> (ui.le_title->text()); + objs << spawn<LDComment> ("Name: <untitled>.dat"); + objs << spawn<LDComment> (format ("Author: %1", ui.le_author->text())); + objs << spawn<LDComment> (format ("!LDRAW_ORG Unofficial_Part")); + + if (not license.isEmpty()) + objs << spawn<LDComment> (license); + + objs << spawn<LDEmpty>(); + objs << spawn<LDBFC> (bfctype); + objs << spawn<LDEmpty>(); + + getCurrentDocument()->addObjects (objs); doFullRefresh(); } @@ -122,7 +125,7 @@ { String name = QFileDialog::getOpenFileName (g_win, "Open File", "", "LDraw files (*.dat *.ldr)"); - if (name.length() == 0) + if (name.isEmpty()) return; openMainFile (name); @@ -200,56 +203,56 @@ // DEFINE_ACTION (NewSubfile, 0) { - AddObjectDialog::staticDialog (LDObject::ESubfile, null); + AddObjectDialog::staticDialog (LDObject::ESubfile, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewLine, 0) { - AddObjectDialog::staticDialog (LDObject::ELine, null); + AddObjectDialog::staticDialog (LDObject::ELine, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewTriangle, 0) { - AddObjectDialog::staticDialog (LDObject::ETriangle, null); + AddObjectDialog::staticDialog (LDObject::ETriangle, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewQuad, 0) { - AddObjectDialog::staticDialog (LDObject::EQuad, null); + AddObjectDialog::staticDialog (LDObject::EQuad, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewCLine, 0) { - AddObjectDialog::staticDialog (LDObject::ECondLine, null); + AddObjectDialog::staticDialog (LDObject::ECondLine, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewComment, 0) { - AddObjectDialog::staticDialog (LDObject::EComment, null); + AddObjectDialog::staticDialog (LDObject::EComment, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewBFC, 0) { - AddObjectDialog::staticDialog (LDObject::EBFC, null); + AddObjectDialog::staticDialog (LDObject::EBFC, LDObjectPtr()); } // ============================================================================= // DEFINE_ACTION (NewVertex, 0) { - AddObjectDialog::staticDialog (LDObject::EVertex, null); + AddObjectDialog::staticDialog (LDObject::EVertex, LDObjectPtr()); } // ============================================================================= @@ -259,7 +262,7 @@ if (selection().size() != 1) return; - LDObject* obj = selection() [0]; + LDObjectPtr obj = selection() [0]; AddObjectDialog::staticDialog (obj->type(), obj); } @@ -287,7 +290,7 @@ // DEFINE_ACTION (SelectAll, CTRL (A)) { - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) obj->select(); ui->objectList->selectAll(); @@ -304,7 +307,7 @@ getCurrentDocument()->clearSelection(); - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) if (obj->color() == colnum) obj->select(); @@ -329,21 +332,21 @@ if (type == LDObject::ESubfile) { - refName = static_cast<LDSubfile*> (selection()[0])->fileInfo()->name(); + refName = selection()[0].staticCast<LDSubfile>()->fileInfo()->name(); - for (LDObject* obj : selection()) - if (static_cast<LDSubfile*> (obj)->fileInfo()->name() != refName) + for (LDObjectPtr obj : selection()) + if (obj.staticCast<LDSubfile>()->fileInfo()->name() != refName) return; } getCurrentDocument()->clearSelection(); - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { if (obj->type() != type) continue; - if (type == LDObject::ESubfile && static_cast<LDSubfile*> (obj)->fileInfo()->name() != refName) + if (type == LDObject::ESubfile && obj.staticCast<LDSubfile>()->fileInfo()->name() != refName) continue; obj->select(); @@ -402,7 +405,7 @@ getCurrentDocument()->clearSelection(); - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { getCurrentDocument()->insertObj (idx, obj); obj->select(); @@ -435,7 +438,7 @@ return; } - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { String contents = obj->asText(); QByteArray data = contents.toUtf8(); @@ -469,7 +472,7 @@ for (String line : String (te_edit->toPlainText()).split ("\n")) { - LDObject* obj = parseLine (line); + LDObjectPtr obj = parseLine (line); getCurrentDocument()->insertObj (idx, obj); obj->select(); @@ -519,7 +522,7 @@ // DEFINE_ACTION (VisibilityToggle, 0) { - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) obj->setHidden (not obj->isHidden()); refresh(); @@ -529,7 +532,7 @@ // DEFINE_ACTION (VisibilityHide, 0) { - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) obj->setHidden (true); refresh(); @@ -539,7 +542,7 @@ // DEFINE_ACTION (VisibilityReveal, 0) { - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) obj->setHidden (false); refresh(); } @@ -688,7 +691,7 @@ { bool ok; int defval = 0; - LDObject* obj; + LDObjectPtr obj; if (selection().size() == 1) defval = selection()[0]->lineNumber(); @@ -723,7 +726,7 @@ String subtitle; // Comment containing the title of the parent document - LDComment* titleobj = dynamic_cast<LDComment*> (getCurrentDocument()->getObject (0)); + LDCommentPtr titleobj = getCurrentDocument()->getObject (0).dynamicCast<LDComment>(); // License text for the subfile String license = getLicenseText (cfg::defaultLicense); @@ -744,7 +747,7 @@ subtitle = "~subfile"; // Remove duplicate tildes - while (subtitle[0] == '~' && subtitle[1] == '~') + while (subtitle.startsWith ("~~")) subtitle.remove (0, 1); // If this the parent document isn't already in s/, we need to stuff it into @@ -763,11 +766,14 @@ subdirname = desiredPath; QDir().mkpath (subdirname); } + else + return; } // Determine the body of the name of the subfile if (not parentpath.isEmpty()) { + // Chop existing '.dat' suffix if (parentpath.endsWith (".dat")) parentpath.chop (4); @@ -782,6 +788,8 @@ QFile f; String testfname; + // Now find the appropriate filename. Increase the number of the subfile + // until we find a name which isn't already taken. do { digits.setNum (subidx++); @@ -796,14 +804,12 @@ // Determine the BFC winding type used in the main document - it is to // be carried over to the subfile. - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { - LDBFC* bfc = dynamic_cast<LDBFC*> (obj); - - if (not bfc) + if (obj->type() != LDObject::EBFC) continue; - LDBFC::Statement a = bfc->statement(); + LDBFC::Statement a = obj.staticCast<LDBFC>()->statement(); if (a == LDBFC::CertifyCCW || a == LDBFC::CertifyCW || a == LDBFC::NoCertify) { @@ -813,7 +819,7 @@ } // Get the body of the document in LDraw code - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) code << obj->asText(); // Create the new subfile document @@ -821,38 +827,41 @@ doc->setImplicit (false); doc->setFullPath (fullsubname); doc->setName (LDDocument::shortenName (fullsubname)); - doc->addObjects ( - { - new LDComment (subtitle), - new LDComment ("Name: "), - new LDComment (format ("Author: %1 [%2]", cfg::defaultName, cfg::defaultUser)), - new LDComment (format ("!LDRAW_ORG Unofficial_Subpart")), - (license != "" ? new LDComment (license) : null), - new LDEmpty, - new LDBFC (bfctype), - new LDEmpty, - }); + + LDObjectList objs; + objs << spawn<LDComment> (subtitle); + objs << spawn<LDComment> ("Name: "); // This gets filled in when the subfile is saved + objs << spawn<LDComment> (format ("Author: %1 [%2]", cfg::defaultName, cfg::defaultUser)); + objs << spawn<LDComment> ("!LDRAW_ORG Unofficial_Subpart"); + + if (not license.isEmpty()) + objs << spawn<LDComment> (license); + + objs << spawn<LDEmpty>(); + objs << spawn<LDBFC> (bfctype); + objs << spawn<LDEmpty>(); + + doc->addObjects (objs); // Add the actual subfile code to the new document for (String line : code) { - LDObject* obj = parseLine (line); + LDObjectPtr obj = parseLine (line); doc->addObject (obj); } // Try save it if (save (doc, true)) { - // Remove the selection now - for (LDObject* obj : selection()) + // Save was successful. Delete the original selection now from the + // main document. + for (LDObjectPtr obj : selection()) obj->destroy(); - // Compile all objects in the new subfile - R()->compiler()->compileDocument (doc); g_loadedFiles << doc; // Add a reference to the new subfile to where the selection was - LDSubfile* ref = new LDSubfile(); + LDSubfilePtr ref (spawn<LDSubfile>()); ref->setColor (maincolor); ref->setFileInfo (doc); ref->setPosition (g_origin);
--- a/src/actionsEdit.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/actionsEdit.cc Fri May 09 12:06:56 2014 +0300 @@ -49,7 +49,7 @@ // Now, copy the contents into the clipboard. String data; - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { if (data.length() > 0) data += "\n"; @@ -90,7 +90,7 @@ for (String line : clipboardText.split ("\n")) { - LDObject* pasted = parseLine (line); + LDObjectPtr pasted = parseLine (line); getCurrentDocument()->insertObj (idx++, pasted); pasted->select(); ++num; @@ -115,7 +115,7 @@ { LDObjectList sel = selection(); - for (LDObject* obj : sel) + for (LDObjectPtr obj : sel) { // Get the index of the subfile so we know where to insert the // inlined contents. @@ -124,14 +124,14 @@ if (idx == -1 || obj->type() != LDObject::ESubfile) continue; - LDObjectList objs = static_cast<LDSubfile*> (obj)->inlineContents (deep, false); + LDObjectList objs = obj.staticCast<LDSubfile>()->inlineContents (deep, false); // Merge in the inlined objects - for (LDObject* inlineobj : objs) + for (LDObjectPtr inlineobj : objs) { String line = inlineobj->asText(); inlineobj->destroy(); - LDObject* newobj = parseLine (line); + LDObjectPtr newobj = parseLine (line); getCurrentDocument()->insertObj (idx++, newobj); newobj->select(); } @@ -160,7 +160,7 @@ LDObjectList objs = selection(); int num = 0; - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { if (obj->type() != LDObject::EQuad) continue; @@ -171,7 +171,7 @@ if (index == -1) return; - QList<LDTriangle*> triangles = static_cast<LDQuad*> (obj)->splitToTriangles(); + QList<LDTrianglePtr> triangles = obj.staticCast<LDQuad>()->splitToTriangles(); // Replace the quad with the first triangle and add the second triangle // after the first one. @@ -192,7 +192,7 @@ if (selection().size() != 1) return; - LDObject* obj = selection()[0]; + LDObjectPtr obj = selection()[0]; QDialog* dlg = new QDialog; Ui::EditRawUI ui; @@ -200,7 +200,7 @@ ui.code->setText (obj->asText()); if (obj->type() == LDObject::EError) - ui.errorDescription->setText (static_cast<LDError*> (obj)->reason()); + ui.errorDescription->setText (obj.staticCast<LDError>()->reason()); else { ui.errorDescription->hide(); @@ -211,7 +211,7 @@ return; // Reinterpret it from the text of the input field - LDObject* newobj = parseLine (ui.code->text()); + LDObjectPtr newobj = parseLine (ui.code->text()); obj->replace (newobj); refresh(); } @@ -235,7 +235,7 @@ // Show the dialog to the user now and ask for a color. if (ColorSelector::selectColor (colnum, defcol, g_win)) { - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { if (not obj->isColored()) continue; @@ -254,44 +254,41 @@ LDObjectList objs = selection(); int num = 0; - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { const LDObject::Type type = obj->type(); if (type != LDObject::EQuad && type != LDObject::ETriangle) continue; - int numLines; - LDLine* lines[4]; + LDLinePtr lines[4]; if (type == LDObject::EQuad) { - numLines = 4; - - LDQuad* quad = static_cast<LDQuad*> (obj); - lines[0] = new LDLine (quad->vertex (0), quad->vertex (1)); - lines[1] = new LDLine (quad->vertex (1), quad->vertex (2)); - lines[2] = new LDLine (quad->vertex (2), quad->vertex (3)); - lines[3] = new LDLine (quad->vertex (3), quad->vertex (0)); + LDQuadPtr quad = obj.staticCast<LDQuad>(); + lines[0] = spawn<LDLine> (quad->vertex (0), quad->vertex (1)); + lines[1] = spawn<LDLine> (quad->vertex (1), quad->vertex (2)); + lines[2] = spawn<LDLine> (quad->vertex (2), quad->vertex (3)); + lines[3] = spawn<LDLine> (quad->vertex (3), quad->vertex (0)); } else { - numLines = 3; - - LDTriangle* tri = static_cast<LDTriangle*> (obj); - lines[0] = new LDLine (tri->vertex (0), tri->vertex (1)); - lines[1] = new LDLine (tri->vertex (1), tri->vertex (2)); - lines[2] = new LDLine (tri->vertex (2), tri->vertex (0)); + LDTrianglePtr tri = obj.staticCast<LDTriangle>(); + lines[0] = spawn<LDLine> (tri->vertex (0), tri->vertex (1)); + lines[1] = spawn<LDLine> (tri->vertex (1), tri->vertex (2)); + lines[2] = spawn<LDLine> (tri->vertex (2), tri->vertex (0)); } - for (int i = 0; i < numLines; ++i) + for (int i = 0; i < countof (lines); ++i) { + if (lines[i] == null) + continue; + long idx = obj->lineNumber() + i + 1; - lines[i]->setColor (edgecolor); getCurrentDocument()->insertObj (idx, lines[i]); } - num += numLines; + num += countof (lines); } print (tr ("Added %1 border lines"), num); @@ -304,7 +301,7 @@ { int num = 0; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (obj->numVertices() < 2) continue; @@ -313,7 +310,7 @@ for (int i = 0; i < obj->numVertices(); ++i) { - LDVertex* vert = new LDVertex; + QSharedPointer<LDVertex> vert (spawn<LDVertex>()); vert->pos = obj->vertex (i); vert->setColor (obj->color()); getCurrentDocument()->insertObj (++ln, vert); @@ -365,7 +362,7 @@ // Apply the grid values vect *= *currentGrid().coordsnap; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) obj->move (vect); g_win->refresh(); @@ -409,7 +406,7 @@ { LDObjectList sel = selection(); - for (LDObject* obj : sel) + for (LDObjectPtr obj : sel) obj->invert(); refresh(); @@ -452,7 +449,7 @@ }); // Apply the above matrix to everything - for (LDObject* obj : sel) + for (LDObjectPtr obj : sel) { if (obj->numVertices()) { @@ -465,7 +462,7 @@ } elif (obj->hasMatrix()) { - LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); + LDMatrixObjectPtr mo = obj.dynamicCast<LDMatrixObject>(); // Transform the position Vertex v = mo->position(); @@ -477,7 +474,7 @@ } elif (obj->type() == LDObject::EVertex) { - LDVertex* vert = static_cast<LDVertex*> (obj); + LDVertexPtr vert = obj.staticCast<LDVertex>(); Vertex v = vert->pos; rotateVertex (v, rotpoint, transform); vert->pos = v; @@ -526,9 +523,9 @@ setlocale (LC_ALL, "C"); int num = 0; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { - LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); + LDMatrixObjectPtr mo = obj.dynamicCast<LDMatrixObject>(); if (mo != null) { @@ -566,7 +563,7 @@ { int num = 0; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (not obj->isColored()) continue; @@ -607,7 +604,7 @@ if (ui.y->isChecked()) sel << Y; if (ui.z->isChecked()) sel << Z; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { for (int i = 0; i < obj->numVertices(); ++i) { @@ -653,7 +650,7 @@ if (ui.y->isChecked()) sel << Y; if (ui.z->isChecked()) sel << Z; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { for (int i = 0; i < obj->numVertices(); ++i) { @@ -679,12 +676,12 @@ LDObjectList sel = selection(); int num = 0; - for (LDObject* obj : sel) + for (LDObjectPtr obj : sel) { if (obj->type() != LDObject::ECondLine) continue; - static_cast<LDCondLine*> (obj)->demote(); + obj.staticCast<LDCondLine>()->demote(); ++num; } @@ -696,7 +693,7 @@ // static bool isColorUsed (int colnum) { - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) if (obj->isColored() && obj->color() == colnum) return true; @@ -718,7 +715,7 @@ return; } - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (not obj->isColored()) continue; @@ -734,7 +731,7 @@ // DEFINE_ACTION (AddHistoryLine, 0) { - LDObject* obj; + LDObjectPtr obj; bool ishistory = false, prevIsHistory = false; @@ -754,14 +751,14 @@ ui->m_username->text(), ui->m_comment->text()); - LDComment* comm = new LDComment (commentText); + LDCommentPtr comm (spawn<LDComment> (commentText)); // Find a spot to place the new comment for (obj = getCurrentDocument()->getObject (0); obj != null && obj->next() != null && not obj->next()->isScemantic(); obj = obj->next()) { - LDComment* comm = dynamic_cast<LDComment*> (obj); + LDCommentPtr comm = obj.dynamicCast<LDComment>(); if (comm != null && comm->text().startsWith ("!HISTORY ")) ishistory = true; @@ -782,7 +779,7 @@ // If we're adding a history line right before a scemantic object, pad it // an empty line if (obj && obj->next() && obj->next()->isScemantic()) - getCurrentDocument()->insertObj (idx, new LDEmpty); + getCurrentDocument()->insertObj (idx, LDEmptyPtr (spawn<LDEmpty>())); buildObjList(); delete ui;
--- a/src/addObjectDialog.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/addObjectDialog.cc Fri May 09 12:06:56 2014 +0300 @@ -53,7 +53,7 @@ // ============================================================================= // -AddObjectDialog::AddObjectDialog (const LDObject::Type type, LDObject* obj, QWidget* parent) : +AddObjectDialog::AddObjectDialog (const LDObject::Type type, LDObjectPtr obj, QWidget* parent) : QDialog (parent) { setlocale (LC_ALL, "C"); @@ -68,7 +68,7 @@ le_comment = new QLineEdit; if (obj) - le_comment->setText (static_cast<LDComment*> (obj)->text()); + le_comment->setText (obj.staticCast<LDComment>()->text()); le_comment->setMinimumWidth (384); } break; @@ -108,7 +108,7 @@ } if (obj) - rb_bfcType->setValue ( (int) static_cast<LDBFC*> (obj)->statement()); + rb_bfcType->setValue ((int) obj.staticCast<LDBFC>()->statement()); } break; case LDObject::ESubfile: @@ -131,7 +131,7 @@ // If this primitive is the one the current object points to, // select it by default - if (obj && static_cast<LDSubfile*> (obj)->fileInfo()->name() == prim.name) + if (obj && obj.staticCast<LDSubfile>()->fileInfo()->name() == prim.name) tw_subfileList->setCurrentItem (item); } @@ -145,7 +145,7 @@ if (obj) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); le_subfileName->setText (ref->fileInfo()->name()); } } break; @@ -157,7 +157,7 @@ } QPixmap icon = getIcon (format ("add-%1", typeName)); - LDObject* defaults = LDObject::getDefault (type); + LDObjectPtr defaults = LDObject::getDefault (type); lb_typeIcon = new QLabel; lb_typeIcon->setPixmap (icon); @@ -225,8 +225,7 @@ if (defaults->hasMatrix()) { - LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); - + LDMatrixObjectPtr mo = obj.dynamicCast<LDMatrixObject>(); QLabel* lb_matrix = new QLabel ("Matrix:"); le_matrix = new QLineEdit; // le_matrix->setValidator (new QDoubleValidator); @@ -317,17 +316,17 @@ // ============================================================================= // ============================================================================= template<typename T> -static T* initObj (LDObject*& obj) +static QSharedPointer<T> initObj (LDObjectPtr& obj) { if (obj == null) - obj = new T; + obj = LDObjectPtr (new T); - return static_cast<T*> (obj); + return obj.staticCast<T>(); } // ============================================================================= // ============================================================================= -void AddObjectDialog::staticDialog (const LDObject::Type type, LDObject* obj) +void AddObjectDialog::staticDialog (const LDObject::Type type, LDObjectPtr obj) { setlocale (LC_ALL, "C"); @@ -367,7 +366,7 @@ { case LDObject::EComment: { - LDComment* comm = initObj<LDComment> (obj); + LDCommentPtr comm = initObj<LDComment> (obj); comm->setText (dlg.le_comment->text()); } break; @@ -395,13 +394,13 @@ case LDObject::EBFC: { - LDBFC* bfc = initObj<LDBFC> (obj); + LDBFCPtr bfc = initObj<LDBFC> (obj); bfc->setStatement ((LDBFC::Statement) dlg.rb_bfcType->value()); } break; case LDObject::EVertex: { - LDVertex* vert = initObj<LDVertex> (obj); + LDVertexPtr vert = initObj<LDVertex> (obj); vert->pos.apply ([&](Axis ax, double& value) { value = dlg.dsb_coords[ax]->value(); }); } break; @@ -421,7 +420,7 @@ return; } - LDSubfile* ref = initObj<LDSubfile> (obj); + LDSubfilePtr ref = initObj<LDSubfile> (obj); assert (ref); for_axes (ax)
--- a/src/addObjectDialog.h Mon May 05 17:18:01 2014 +0300 +++ b/src/addObjectDialog.h Fri May 09 12:06:56 2014 +0300 @@ -34,8 +34,8 @@ Q_OBJECT public: - AddObjectDialog (const LDObject::Type type, LDObject* obj, QWidget* parent = null); - static void staticDialog (const LDObject::Type type, LDObject* obj); + AddObjectDialog (const LDObject::Type type, LDObjectPtr obj, QWidget* parent = null); + static void staticDialog (const LDObject::Type type, LDObjectPtr obj); QLabel* lb_typeIcon;
--- a/src/basics.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/basics.cc Fri May 09 12:06:56 2014 +0300 @@ -225,13 +225,13 @@ if (not getCurrentDocument()) return; - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) calcObject (obj); } // ============================================================================= // -void LDBoundingBox::calcObject (LDObject* obj) +void LDBoundingBox::calcObject (LDObjectPtr obj) { switch (obj->type()) { @@ -246,10 +246,10 @@ case LDObject::ESubfile: { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); LDObjectList objs = ref->inlineContents (true, false); - for (LDObject * obj : objs) + for (LDObjectPtr obj : objs) { calcObject (obj); obj->destroy(); @@ -272,7 +272,7 @@ // ============================================================================= // -LDBoundingBox& LDBoundingBox::operator<< (LDObject* obj) +LDBoundingBox& LDBoundingBox::operator<< (LDObjectPtr obj) { calcObject (obj); return *this;
--- a/src/basics.h Mon May 05 17:18:01 2014 +0300 +++ b/src/basics.h Fri May 09 12:06:56 2014 +0300 @@ -22,11 +22,13 @@ #include <QStringList> #include <QMetaType> #include <QVector3D> +#include <QSharedPointer> #include "macros.h" class LDObject; class QFile; class QTextStream; +class Matrix; using int8 = qint8; using int16 = qint16; @@ -37,6 +39,10 @@ using uint32 = quint32; using uint64 = quint64; using String = QString; +using LDObjectPtr = QSharedPointer<LDObject>; +using LDObjectList = QList<LDObjectPtr>; +using LDObjectWeakPtr = QWeakPointer<LDObject>; +using LDObjectWeakList = QList<LDObjectWeakPtr>; template<typename T, typename R> using Pair = std::pair<T, R>; @@ -48,12 +54,6 @@ Z }; -// ============================================================================= -// -class LDObject; -class Matrix; -using LDObjectList = QList<LDObject*>; - //! //! Derivative of QVector3D: this class is used for the vertices. //! @@ -192,7 +192,7 @@ //! Calculates the given \c obj to the bounding box, adjusting //! extremas if necessary. - void calcObject (LDObject* obj); + void calcObject (LDObjectPtr obj); //! Calculates the given \c vertex to the bounding box, adjusting //! extremas if necessary. @@ -202,7 +202,7 @@ Vertex center() const; //! An operator overload for \c calcObject() - LDBoundingBox& operator<< (LDObject* obj); + LDBoundingBox& operator<< (LDObjectPtr obj); //! An operator overload for \c calcVertex() LDBoundingBox& operator<< (const Vertex& v);
--- a/src/editHistory.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/editHistory.cc Fri May 09 12:06:56 2014 +0300 @@ -130,7 +130,7 @@ // void AddHistory::undo() const { - LDObject* obj = parent()->document()->getObject (index()); + LDObjectPtr obj = parent()->document()->getObject (index()); obj->destroy(); } @@ -138,14 +138,14 @@ // void AddHistory::redo() const { - LDObject* obj = parseLine (code()); + LDObjectPtr obj = parseLine (code()); parent()->document()->insertObj (index(), obj); g_win->R()->compileObject (obj); } // ============================================================================= // -DelHistory::DelHistory (int idx, LDObject* obj) : +DelHistory::DelHistory (int idx, LDObjectPtr obj) : m_index (idx), m_code (obj->asText()) {} @@ -154,7 +154,7 @@ // void DelHistory::undo() const { - LDObject* obj = parseLine (code()); + LDObjectPtr obj = parseLine (code()); parent()->document()->insertObj (index(), obj); g_win->R()->compileObject (obj); } @@ -163,7 +163,7 @@ // void DelHistory::redo() const { - LDObject* obj = parent()->document()->getObject (index()); + LDObjectPtr obj = parent()->document()->getObject (index()); obj->destroy(); } @@ -171,8 +171,8 @@ // void EditHistory::undo() const { - LDObject* obj = getCurrentDocument()->getObject (index()); - LDObject* newobj = parseLine (oldCode()); + LDObjectPtr obj = getCurrentDocument()->getObject (index()); + LDObjectPtr newobj = parseLine (oldCode()); obj->replace (newobj); g_win->R()->compileObject (newobj); } @@ -181,8 +181,8 @@ // void EditHistory::redo() const { - LDObject* obj = getCurrentDocument()->getObject (index()); - LDObject* newobj = parseLine (newCode()); + LDObjectPtr obj = getCurrentDocument()->getObject (index()); + LDObjectPtr newobj = parseLine (newCode()); obj->replace (newobj); g_win->R()->compileObject (newobj); }
--- a/src/editHistory.h Mon May 05 17:18:01 2014 +0300 +++ b/src/editHistory.h Fri May 09 12:06:56 2014 +0300 @@ -108,7 +108,7 @@ public: IMPLEMENT_HISTORY_TYPE (Del) - DelHistory (int idx, LDObject* obj); + DelHistory (int idx, LDObjectPtr obj); }; // ============================================================================= @@ -139,7 +139,7 @@ public: IMPLEMENT_HISTORY_TYPE (Add) - AddHistory (int idx, LDObject* obj) : + AddHistory (int idx, LDObjectPtr obj) : m_index (idx), m_code (obj->asText()) {} };
--- a/src/extPrograms.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/extPrograms.cc Fri May 09 12:06:56 2014 +0300 @@ -168,16 +168,16 @@ // static void writeObjects (const LDObjectList& objects, QFile& f) { - for (LDObject* obj : objects) + for (LDObjectPtr obj : objects) { if (obj->type() == LDObject::ESubfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); LDObjectList objs = ref->inlineContents (true, false); writeObjects (objs, f); - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) obj->destroy(); } else @@ -219,7 +219,7 @@ { LDObjectList objects; - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { if (not obj->isColored() || obj->color() != colnum) continue; @@ -315,7 +315,7 @@ // Insert the new objects getCurrentDocument()->clearSelection(); - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { if (not obj->isScemantic()) {
--- a/src/glCompiler.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/glCompiler.cc Fri May 09 12:06:56 2014 +0300 @@ -53,7 +53,7 @@ static const QColor g_BFCFrontColor (64, 192, 80); static const QColor g_BFCBackColor (208, 64, 64); -// static QMap<LDObject*, String> g_objectOrigins; +// static QMap<LDObjectPtr, String> g_objectOrigins; // ============================================================================= // @@ -128,7 +128,7 @@ // ============================================================================= // -QColor GLCompiler::getColorForPolygon (LDPolygon& poly, LDObject* topobj, +QColor GLCompiler::getColorForPolygon (LDPolygon& poly, LDObjectPtr topobj, EVBOComplement complement) const { QColor qcol; @@ -224,21 +224,21 @@ // ============================================================================= // -void GLCompiler::stageForCompilation (LDObject* obj) +void GLCompiler::stageForCompilation (LDObjectPtr obj) { /* g_objectOrigins[obj] = format ("%1:%2 (%3)", obj->document()->getDisplayName(), obj->lineNumber(), obj->typeName()); */ - m_staged << obj; + m_staged << LDObjectWeakPtr (obj); } // ============================================================================= // -void GLCompiler::unstage (LDObject* obj) +void GLCompiler::unstage (LDObjectPtr obj) { - m_staged.removeOne (obj); + m_staged.removeOne (LDObjectWeakPtr (obj)); } // ============================================================================= @@ -248,7 +248,7 @@ if (doc == null) return; - for (LDObject* obj : doc->objects()) + for (LDObjectPtr obj : doc->objects()) compileObject (obj); } @@ -258,7 +258,7 @@ { removeDuplicates (m_staged); - for (LDObject* obj : m_staged) + for (LDObjectPtr obj : m_staged) compileObject (obj); m_staged.clear(); @@ -292,7 +292,7 @@ // ============================================================================= // -void GLCompiler::dropObject (LDObject* obj) +void GLCompiler::dropObject (LDObjectPtr obj) { auto it = m_objectInfo.find (obj); @@ -307,7 +307,7 @@ // ============================================================================= // -void GLCompiler::compileObject (LDObject* obj) +void GLCompiler::compileObject (LDObjectPtr obj) { // print ("Compile %1\n", g_objectOrigins[obj]); @@ -336,7 +336,7 @@ case LDObject::ESubfile: { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); auto data = ref->inlinePolygons(); for (LDPolygon& poly : data) @@ -357,7 +357,7 @@ // ============================================================================= // -void GLCompiler::compilePolygon (LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo) +void GLCompiler::compilePolygon (LDPolygon& poly, LDObjectPtr topobj, ObjectVBOInfo* objinfo) { EVBOSurface surface; int numverts;
--- a/src/glCompiler.h Mon May 05 17:18:01 2014 +0300 +++ b/src/glCompiler.h Fri May 09 12:06:56 2014 +0300 @@ -36,15 +36,15 @@ GLCompiler (GLRenderer* renderer); ~GLCompiler(); void compileDocument (LDDocument* doc); - void dropObject (LDObject* obj); + void dropObject (LDObjectPtr obj); void initialize(); - QColor getColorForPolygon (LDPolygon& poly, LDObject* topobj, + QColor getColorForPolygon (LDPolygon& poly, LDObjectPtr topobj, EVBOComplement complement) const; QColor indexColorForID (int id) const; void needMerge(); void prepareVBO (int vbonum); - void stageForCompilation (LDObject* obj); - void unstage (LDObject* obj); + void stageForCompilation (LDObjectPtr obj); + void unstage (LDObjectPtr obj); static uint32 colorToRGB (const QColor& color); @@ -65,11 +65,11 @@ private: void compileStaged(); - void compileObject (LDObject* obj); - void compilePolygon (LDPolygon& poly, LDObject* topobj, GLCompiler::ObjectVBOInfo* objinfo); + void compileObject (LDObjectPtr obj); + void compilePolygon (LDPolygon& poly, LDObjectPtr topobj, GLCompiler::ObjectVBOInfo* objinfo); - QMap<LDObject*, ObjectVBOInfo> m_objectInfo; - LDObjectList m_staged; // Objects that need to be compiled + QMap<LDObjectPtr, ObjectVBOInfo> m_objectInfo; + LDObjectWeakList m_staged; // Objects that need to be compiled GLuint m_vbo[g_numVBOs]; bool m_vboChanged[g_numVBOs]; int m_vboSizes[g_numVBOs];
--- a/src/glRenderer.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/glRenderer.cc Fri May 09 12:06:56 2014 +0300 @@ -126,7 +126,6 @@ m_position3D = g_origin; m_toolTipTimer = new QTimer (this); m_toolTipTimer->setSingleShot (true); - m_objectAtCursor = null; m_isCameraMoving = false; connect (m_toolTipTimer, SIGNAL (timeout()), this, SLOT (slot_toolTipTimer())); @@ -1225,7 +1224,7 @@ LDObjectList oldsel = selection(); getCurrentDocument()->clearSelection(); - for (LDObject* obj : oldsel) + for (LDObjectPtr obj : oldsel) compileObject (obj); } @@ -1273,7 +1272,7 @@ // Read pixels from the color buffer. glReadPixels (x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); - LDObject* removedObj = null; + LDObjectPtr removedObj; QList<qint32> indices; // Go through each pixel read and add them to the selection. @@ -1294,7 +1293,7 @@ for (qint32 idx : indices) { - LDObject* obj = LDObject::fromID (idx); + LDObjectPtr obj = LDObject::fromID (idx); assert (obj != null); // If this is an additive single pick and the object is currently selected, @@ -1318,7 +1317,7 @@ g_win->updateSelection(); // Recompile the objects now to update their color - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) compileObject (obj); if (removedObj) @@ -1364,7 +1363,7 @@ LDObjectList priorsel = selection(); getCurrentDocument()->clearSelection(); - for (LDObject* obj : priorsel) + for (LDObjectPtr obj : priorsel) compileObject (obj); g_win->updateSelection(); @@ -1442,7 +1441,7 @@ { if (m_rectdraw) { - LDQuad* quad = new LDQuad; + LDQuadPtr quad (spawn<LDQuad>()); // Copy the vertices from m_rectverts updateRectVerts(); @@ -1460,7 +1459,7 @@ case 1: { // 1 vertex - add a vertex object - LDVertex* obj = new LDVertex; + LDVertexPtr obj = spawn<LDVertex>(); obj->pos = verts[0]; obj->setColor (maincolor); objs << obj; @@ -1469,7 +1468,7 @@ case 2: { // 2 verts - make a line - LDLine* obj = new LDLine (verts[0], verts[1]); + LDLinePtr obj = spawn<LDLine> (verts[0], verts[1]); obj->setColor (edgecolor); objs << obj; } break; @@ -1477,9 +1476,9 @@ case 3: case 4: { - LDObject* obj = (verts.size() == 3) ? - static_cast<LDObject*> (new LDTriangle) : - static_cast<LDObject*> (new LDQuad); + LDObjectPtr obj = (verts.size() == 3) ? + static_cast<LDObjectPtr> (spawn<LDTriangle>()) : + static_cast<LDObjectPtr> (spawn<LDQuad>()); obj->setColor (maincolor); @@ -1531,7 +1530,7 @@ refFile->setImplicit (false); } - LDSubfile* ref = new LDSubfile; + LDSubfilePtr ref = spawn<LDSubfile>(); ref->setFileInfo (refFile); ref->setTransform (getCircleDrawMatrix (cmp.scale)); ref->setPosition (m_drawedVerts[0]); @@ -1571,20 +1570,20 @@ v3.setCoordinate (relX, v3[relX] + c1[i].x1()); v3.setCoordinate (relY, v3[relY] + c1[i].y1()); - LDQuad* q = new LDQuad (v0, v1, v2, v3); - q->setColor (maincolor); + LDQuadPtr quad (spawn<LDQuad> (v0, v1, v2, v3)); + quad->setColor (maincolor); // Ensure the quads always are BFC-front towards the camera if (camera() % 3 <= 0) - q->invert(); + quad->invert(); - objs << q; + objs << quad; } } if (circleOrDisc) { - LDSubfile* ref = new LDSubfile; + LDSubfilePtr ref = spawn<LDSubfile>(); ref->setFileInfo (refFile); ref->setTransform (transform); ref->setPosition (m_drawedVerts[0]); @@ -1603,7 +1602,7 @@ if (objs.size() > 0) { - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { document()->addObject (obj); compileObject (obj); @@ -1649,7 +1648,7 @@ // ============================================================================= // -static QList<Vertex> getVertices (LDObject* obj) +static QList<Vertex> getVertices (LDObjectPtr obj) { QList<Vertex> verts; @@ -1660,10 +1659,10 @@ } elif (obj->type() == LDObject::ESubfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); LDObjectList objs = ref->inlineContents (true, false); - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { verts << getVertices (obj); obj->destroy(); @@ -1675,14 +1674,14 @@ // ============================================================================= // -void GLRenderer::compileObject (LDObject* obj) +void GLRenderer::compileObject (LDObjectPtr obj) { compiler()->stageForCompilation (obj); } // ============================================================================= // -void GLRenderer::forgetObject (LDObject* obj) +void GLRenderer::forgetObject (LDObjectPtr obj) { compiler()->dropObject (obj); } @@ -2003,7 +2002,7 @@ if (selection().isEmpty()) return; - LDObject* obj = selection().first(); + LDObjectPtr obj = selection().first(); AddObjectDialog::staticDialog (obj->type(), obj); g_win->endAction(); ev->accept(); @@ -2011,20 +2010,17 @@ // ============================================================================= // -LDOverlay* GLRenderer::findOverlayObject (ECamera cam) +LDOverlayPtr GLRenderer::findOverlayObject (ECamera cam) { - LDOverlay* ovlobj = null; - - for (LDObject* obj : document()->objects()) + for (LDObjectPtr obj : document()->objects()) { - if (obj->type() == LDObject::EOverlay && static_cast<LDOverlay*> (obj)->camera() == cam) - { - ovlobj = static_cast<LDOverlay*> (obj); - break; - } + LDOverlayPtr ovlobj = obj.dynamicCast<LDOverlay>(); + + if (ovlobj != null && obj.staticCast<LDOverlay>()->camera() == cam) + return ovlobj; } - return ovlobj; + return LDOverlayPtr(); } // ============================================================================= @@ -2039,16 +2035,20 @@ continue; LDGLOverlay& meta = currentDocumentData().overlays[cam]; - LDOverlay* ovlobj = findOverlayObject (cam); + LDOverlayPtr ovlobj = findOverlayObject (cam); - if (not ovlobj && meta.img) + if (ovlobj == null && meta.img != null) { delete meta.img; meta.img = null; } - elif (ovlobj && (meta.img == null || meta.fname != ovlobj->fileName()) && meta.invalid == false) + elif (ovlobj != null && + (meta.img == null || meta.fname != ovlobj->fileName()) && + not meta.invalid) + { setupOverlay (cam, ovlobj->fileName(), ovlobj->x(), ovlobj->y(), ovlobj->width(), ovlobj->height()); + } } } @@ -2062,12 +2062,12 @@ continue; LDGLOverlay& meta = currentDocumentData().overlays[cam]; - LDOverlay* ovlobj = findOverlayObject (cam); + LDOverlayPtr ovlobj = findOverlayObject (cam); if (meta.img == null && ovlobj != null) { // If this is the last overlay image, we need to remove the empty space after it as well. - LDObject* nextobj = ovlobj->next(); + LDObjectPtr nextobj = ovlobj->next(); if (nextobj && nextobj->type() == LDObject::EEmpty) nextobj->destroy(); @@ -2080,7 +2080,7 @@ { // Inverse case: image is there but the overlay object is // not, thus create the object. - ovlobj = new LDOverlay; + ovlobj = spawn<LDOverlay>(); // Find a suitable position to place this object. We want to place // this into the header, which is everything up to the first scemantic @@ -2093,7 +2093,7 @@ for (i = 0; i < document()->getObjectCount(); ++i) { - LDObject* obj = document()->getObject (i); + LDObjectPtr obj = document()->getObject (i); if (obj->isScemantic()) { @@ -2112,7 +2112,7 @@ document()->insertObj (i, ovlobj); if (found) - document()->insertObj (i + 1, new LDEmpty); + document()->insertObj (i + 1, spawn<LDEmpty>()); } } @@ -2138,8 +2138,8 @@ if (not cfg::highlightObjectBelowCursor && objectAtCursor() == null) return; - LDObject* newObject = null; - LDObject* oldObject = objectAtCursor(); + LDObjectWeakPtr newObject; + LDObjectWeakPtr oldObject = objectAtCursor(); qint32 newIndex; if (isCameraMoving() || not cfg::highlightObjectBelowCursor) @@ -2157,7 +2157,7 @@ newIndex = pixel[0] * 0x10000 | pixel[1] * 0x100 | pixel[2]; } - if (newIndex != (oldObject != null ? oldObject->id() : 0)) + if (newIndex != (oldObject != null ? oldObject.toStrongRef()->id() : 0)) { if (newIndex != 0) newObject = LDObject::fromID (newIndex);
--- a/src/glRenderer.h Mon May 05 17:18:01 2014 +0300 +++ b/src/glRenderer.h Fri May 09 12:06:56 2014 +0300 @@ -146,7 +146,7 @@ PROPERTY (public, LDDocument*, document, setDocument, CUSTOM_WRITE) PROPERTY (public, EditMode, editMode, setEditMode, CUSTOM_WRITE) PROPERTY (private, GLCompiler*, compiler, setCompiler, STOCK_WRITE) - PROPERTY (public, LDObject*, objectAtCursor, setObjectAtCursor, STOCK_WRITE) + PROPERTY (public, LDObjectWeakPtr, objectAtCursor, setObjectAtCursor, STOCK_WRITE) PROPERTY (private, bool, isCameraMoving, setCameraMoving, STOCK_WRITE) public: @@ -159,10 +159,10 @@ } void clearOverlay(); - void compileObject (LDObject* obj); + void compileObject (LDObjectPtr obj); void drawGLScene(); void endDraw (bool accept); - void forgetObject (LDObject* obj); + void forgetObject (LDObjectPtr obj); Axis getCameraAxis (bool y, ECamera camid = (ECamera) -1); const char* getCameraName() const; double getDepthValue() const; @@ -230,7 +230,7 @@ QColor m_bgcolor; void addDrawnVertex (Vertex m_hoverpos); - LDOverlay* findOverlayObject (ECamera cam); + LDOverlayPtr findOverlayObject (ECamera cam); void updateRectVerts(); void getRelativeAxes (Axis& relX, Axis& relY) const; Axis getRelativeZ() const;
--- a/src/ldDocument.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/ldDocument.cc Fri May 09 12:06:56 2014 +0300 @@ -146,7 +146,7 @@ m_history->setIgnoring (true); // Clear everything from the model - for (LDObject* obj : objects()) + for (LDObjectPtr obj : objects()) obj->destroy(); delete history(); @@ -357,7 +357,7 @@ // User wishes to abort, so stop here now. if (isAborted()) { - for (LDObject* obj : m_objects) + for (LDObjectPtr obj : m_objects) obj->destroy(); m_objects.clear(); @@ -378,12 +378,13 @@ while (line.endsWith ("\n") || line.endsWith ("\r")) line.chop (1); - LDObject* obj = parseLine (line); + LDObjectPtr obj = parseLine (line); + fprint (stderr, "got obj: %1\n", obj.data()); // Check for parse errors and warn about tthem if (obj->type() == LDObject::EError) { - print ("Couldn't parse line #%1: %2", progress() + 1, static_cast<LDError*> (obj)->reason()); + print ("Couldn't parse line #%1: %2", progress() + 1, obj.staticCast<LDError>()->reason()); if (warnings() != null) (*warnings())++; @@ -735,11 +736,11 @@ // If the second object in the list holds the file name, update that now. // Only do this if the file is explicitly open. - LDObject* nameObject = getObject (1); + LDObjectPtr nameObject = getObject (1); if (not isImplicit() && nameObject != null && nameObject->type() == LDObject::EComment) { - LDComment* nameComment = static_cast<LDComment*> (nameObject); + LDCommentPtr nameComment = nameObject.staticCast<LDComment>(); if (nameComment->text().left (6) == "Name: ") { @@ -751,7 +752,7 @@ // File is open, now save the model to it. Note that LDraw requires files to // have DOS line endings, so we terminate the lines with \r\n. - for (LDObject* obj : objects()) + for (LDObjectPtr obj : objects()) f.write ((obj->asText() + "\r\n").toUtf8()); // File is saved, now clean up. @@ -828,7 +829,7 @@ // code and returns the object parsed from it. parseLine never returns null, // the object will be LDError if it could not be parsed properly. // ============================================================================= -LDObject* parseLine (String line) +LDObjectPtr parseLine (String line) { try { @@ -837,7 +838,7 @@ if (tokens.size() <= 0) { // Line was empty, or only consisted of whitespace - return new LDEmpty; + return spawn<LDEmpty>(); } if (tokens[0].length() != 1 || not tokens[0][0].isDigit()) @@ -858,17 +859,17 @@ { for (int i = 0; i < LDBFC::NumStatements; ++i) if (commentTextSimplified == format ("BFC %1", LDBFC::k_statementStrings [i])) - return new LDBFC ((LDBFC::Statement) i); + return spawn<LDBFC> ((LDBFC::Statement) i); // MLCAD is notorious for stuffing these statements in parts it // creates. The above block only handles valid statements, so we // need to handle MLCAD-style invertnext, clip and noclip separately. if (commentTextSimplified == "BFC CERTIFY INVERTNEXT") - return new LDBFC (LDBFC::InvertNext); + return spawn<LDBFC> (LDBFC::InvertNext); elif (commentTextSimplified == "BFC CERTIFY CLIP") - return new LDBFC (LDBFC::Clip); + return spawn<LDBFC> (LDBFC::Clip); elif (commentTextSimplified == "BFC CERTIFY NOCLIP") - return new LDBFC (LDBFC::NoClip); + return spawn<LDBFC> (LDBFC::NoClip); } if (tokens.size() > 2 && tokens[1] == "!LDFORGE") @@ -880,7 +881,7 @@ checkTokenCount (line, tokens, 7); checkTokenNumbers (line, tokens, 3, 6); - LDVertex* obj = new LDVertex; + LDVertexPtr obj = spawn<LDVertex>(); obj->setColor (tokens[3].toLong()); obj->pos.apply ([&](Axis ax, double& value) { value = tokens[4 + ax].toDouble(); }); return obj; @@ -890,7 +891,7 @@ checkTokenCount (line, tokens, 9); checkTokenNumbers (line, tokens, 5, 8); - LDOverlay* obj = new LDOverlay; + LDOverlayPtr obj = spawn<LDOverlay>(); obj->setFileName (tokens[3]); obj->setCamera (tokens[4].toLong()); obj->setX (tokens[5].toLong()); @@ -902,7 +903,7 @@ } // Just a regular comment: - LDComment* obj = new LDComment; + LDCommentPtr obj = spawn<LDComment>(); obj->setText (commentText); return obj; } @@ -924,12 +925,12 @@ // here because the error object needs the document reference. if (not load) { - LDError* obj = new LDError (line, format ("Could not open %1", tokens[14])); + LDErrorPtr obj = spawn<LDError> (line, format ("Could not open %1", tokens[14])); obj->setFileReferenced (tokens[14]); return obj; } - LDSubfile* obj = new LDSubfile; + LDSubfilePtr obj = spawn<LDSubfile>(); obj->setColor (tokens[1].toLong()); obj->setPosition (parseVertex (tokens, 2)); // 2 - 4 @@ -949,7 +950,7 @@ checkTokenNumbers (line, tokens, 1, 7); // Line - LDLine* obj = new LDLine; + LDLinePtr obj (spawn<LDLine>()); obj->setColor (tokens[1].toLong()); for (int i = 0; i < 2; ++i) @@ -964,7 +965,7 @@ checkTokenNumbers (line, tokens, 1, 10); // Triangle - LDTriangle* obj = new LDTriangle; + LDTrianglePtr obj (spawn<LDTriangle>()); obj->setColor (tokens[1].toLong()); for (int i = 0; i < 3; ++i) @@ -980,12 +981,12 @@ checkTokenNumbers (line, tokens, 1, 13); // Quadrilateral / Conditional line - LDObject* obj; + LDObjectPtr obj; if (num == 4) - obj = new LDQuad; + obj = spawn<LDQuad>(); else - obj = new LDCondLine; + obj = spawn<LDCondLine>(); obj->setColor (tokens[1].toLong()); @@ -1002,7 +1003,7 @@ catch (LDParseError& e) { // Strange line we couldn't parse - return new LDError (e.line(), e.error()); + return spawn<LDError> (e.line(), e.error()); } } @@ -1031,29 +1032,29 @@ g_loadedFiles << getCurrentDocument(); // Go through all objects in the current file and reload the subfiles - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { if (obj->type() == LDObject::ESubfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); LDDocument* fileInfo = getDocument (ref->fileInfo()->name()); if (fileInfo) ref->setFileInfo (fileInfo); else - ref->replace (new LDError (ref->asText(), format ("Could not open %1", ref->fileInfo()->name()))); + ref->replace (spawn<LDError> (ref->asText(), format ("Could not open %1", ref->fileInfo()->name()))); } // Reparse gibberish files. It could be that they are invalid because // of loading errors. Circumstances may be different now. if (obj->type() == LDObject::EError) - obj->replace (parseLine (static_cast<LDError*> (obj)->contents())); + obj->replace (parseLine (obj.staticCast<LDError>()->contents())); } } // ============================================================================= // -int LDDocument::addObject (LDObject* obj) +int LDDocument::addObject (LDObjectPtr obj) { history()->add (new AddHistory (objects().size(), obj)); m_objects << obj; @@ -1073,14 +1074,14 @@ // void LDDocument::addObjects (const LDObjectList objs) { - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) if (obj) addObject (obj); } // ============================================================================= // -void LDDocument::insertObj (int pos, LDObject* obj) +void LDDocument::insertObj (int pos, LDObjectPtr obj) { history()->add (new AddHistory (pos, obj)); m_objects.insert (pos, obj); @@ -1096,14 +1097,14 @@ // ============================================================================= // -void LDDocument::addKnownVerticesOf (LDObject* obj) +void LDDocument::addKnownVerticesOf (LDObjectPtr obj) { if (isImplicit()) return; if (obj->type() == LDObject::ESubfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); for (Vertex vrt : ref->fileInfo()->inlineVertices()) { @@ -1120,14 +1121,14 @@ // ============================================================================= // -void LDDocument::removeKnownVerticesOf (LDObject* obj) +void LDDocument::removeKnownVerticesOf (LDObjectPtr obj) { if (isImplicit()) return; if (obj->type() == LDObject::ESubfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); for (Vertex vrt : ref->fileInfo()->inlineVertices()) { @@ -1144,7 +1145,7 @@ // ============================================================================= // -void LDDocument::forgetObject (LDObject* obj) +void LDDocument::forgetObject (LDObjectPtr obj) { int idx = obj->lineNumber(); obj->deselect(); @@ -1211,7 +1212,7 @@ // ============================================================================= // -void LDDocument::setObject (int idx, LDObject* obj) +void LDDocument::setObject (int idx, LDObjectPtr obj) { assert (idx >= 0 && idx < m_objects.size()); @@ -1249,10 +1250,10 @@ // ============================================================================= // -LDObject* LDDocument::getObject (int pos) const +LDObjectPtr LDDocument::getObject (int pos) const { if (m_objects.size() <= pos) - return null; + return LDObjectPtr(); return m_objects[pos]; } @@ -1294,7 +1295,7 @@ LDObjectList objs = inlineContents (true, true); m_storedVertices.clear(); - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { assert (obj->type() != LDObject::ESubfile); LDPolygon* data = obj->getPolygon(); @@ -1343,7 +1344,7 @@ LDObjectList objs, objcache; - for (LDObject* obj : objects()) + for (LDObjectPtr obj : objects()) { // Skip those without scemantic meaning if (not obj->isScemantic()) @@ -1353,10 +1354,10 @@ // just add it into the objects normally. Yay, recursion! if (deep == true && obj->type() == LDObject::ESubfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); LDObjectList otherobjs = ref->inlineContents (deep, renderinline); - for (LDObject* otherobj : otherobjs) + for (LDObjectPtr otherobj : otherobjs) objs << otherobj; } else @@ -1448,7 +1449,7 @@ // ============================================================================= // -void LDDocument::addToSelection (LDObject* obj) // [protected] +void LDDocument::addToSelection (LDObjectPtr obj) // [protected] { if (obj->isSelected()) return; @@ -1461,7 +1462,7 @@ // ============================================================================= // -void LDDocument::removeFromSelection (LDObject* obj) // [protected] +void LDDocument::removeFromSelection (LDObjectPtr obj) // [protected] { if (not obj->isSelected()) return; @@ -1476,7 +1477,7 @@ // void LDDocument::clearSelection() { - for (LDObject* obj : m_sel) + for (LDObjectPtr obj : m_sel) removeFromSelection (obj); assert (m_sel.isEmpty()); @@ -1491,7 +1492,7 @@ // ============================================================================= // -void LDDocument::swapObjects (LDObject* one, LDObject* other) +void LDDocument::swapObjects (LDObjectPtr one, LDObjectPtr other) { int a = m_objects.indexOf (one); int b = m_objects.indexOf (other);
--- a/src/ldDocument.h Mon May 05 17:18:01 2014 +0300 +++ b/src/ldDocument.h Fri May 09 12:06:56 2014 +0300 @@ -87,31 +87,31 @@ LDDocument(); ~LDDocument(); - int addObject (LDObject* obj); // Adds an object to this file at the end of the file. + int addObject (LDObjectPtr obj); // Adds an object to this file at the end of the file. void addObjects (const LDObjectList objs); void clearSelection(); - void forgetObject (LDObject* obj); // Deletes the given object from the object chain. + void forgetObject (LDObjectPtr obj); // Deletes the given object from the object chain. String getDisplayName(); const LDObjectList& getSelection() const; bool hasUnsavedChanges() const; // Does this document have unsaved changes? void initializeCachedData(); LDObjectList inlineContents (bool deep, bool renderinline); - void insertObj (int pos, LDObject* obj); + void insertObj (int pos, LDObjectPtr obj); int getObjectCount() const; - LDObject* getObject (int pos) const; + LDObjectPtr getObject (int pos) const; bool save (String path = ""); // Saves this file to disk. - void swapObjects (LDObject* one, LDObject* other); + void swapObjects (LDObjectPtr one, LDObjectPtr other); bool isSafeToClose(); // Perform safety checks. Do this before closing any files! - void setObject (int idx, LDObject* obj); + void setObject (int idx, LDObjectPtr obj); void addReference (LDDocumentPointer* ptr); void removeReference (LDDocumentPointer* ptr); QList<LDPolygon> inlinePolygons(); void vertexChanged (const Vertex& a, const Vertex& b); - void addKnownVerticesOf(LDObject* obj); - void removeKnownVerticesOf (LDObject* sub); + void addKnownVerticesOf(LDObjectPtr obj); + void removeKnownVerticesOf (LDObjectPtr sub); QList<Vertex> inlineVertices(); - inline LDDocument& operator<< (LDObject* obj) + inline LDDocument& operator<< (LDObjectPtr obj) { addObject (obj); return *this; @@ -152,8 +152,8 @@ static String shortenName (String a); protected: - void addToSelection (LDObject* obj); - void removeFromSelection (LDObject* obj); + void addToSelection (LDObjectPtr obj); + void removeFromSelection (LDObjectPtr obj); LDGLData* getGLData() { @@ -203,7 +203,7 @@ void closeAll(); // Parses a string line containing an LDraw object and returns the object parsed. -LDObject* parseLine (String line); +LDObjectPtr parseLine (String line); // Retrieves the pointer to the given document by file name. Document is loaded // from file if necessary. Can return null if neither succeeds.
--- a/src/ldObject.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/ldObject.cc Fri May 09 12:06:56 2014 +0300 @@ -32,7 +32,7 @@ CFGENTRY (Int, defaultLicense, 0); // List of all LDObjects -static LDObjectList g_LDObjects; +static LDObjectWeakList g_LDObjects; // ============================================================================= // LDObject constructors @@ -40,13 +40,12 @@ LDObject::LDObject() : m_isHidden (false), m_isSelected (false), - m_parent (null), m_document (null), qObjListEntry (null) { memset (m_coords, 0, sizeof m_coords); chooseID(); - g_LDObjects << this; + g_LDObjects << LDObjectWeakPtr (thisptr()); setRandomColor (QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128)); } @@ -56,12 +55,13 @@ { int32 id = 1; // 0 shalt be null - for (LDObject* obj : g_LDObjects) + for (LDObjectWeakPtr obj : g_LDObjects) { - assert (obj != this); + LDObjectPtr obj2 = obj.toStrongRef(); + assert (obj2 != this); - if (obj->id() >= id) - id = obj->id() + 1; + if (obj2->id() >= id) + id = obj2->id() + 1; } setID (id); @@ -189,7 +189,7 @@ // ============================================================================= // -QList<LDTriangle*> LDQuad::splitToTriangles() +QList<LDTrianglePtr> LDQuad::splitToTriangles() { // Create the two triangles based on this quadrilateral: // 0---3 0---3 3 @@ -197,22 +197,19 @@ // | | ==> | / / | // | | |/ / | // 1---2 1 1---2 - LDTriangle* tri1 = new LDTriangle (vertex (0), vertex (1), vertex (3)); - LDTriangle* tri2 = new LDTriangle (vertex (1), vertex (2), vertex (3)); + LDTrianglePtr tri1 (spawn<LDTriangle> (vertex (0), vertex (1), vertex (3))); + LDTrianglePtr tri2 (spawn<LDTriangle> (vertex (1), vertex (2), vertex (3))); // The triangles also inherit the quad's color tri1->setColor (color()); tri2->setColor (color()); - QList<LDTriangle*> triangles; - triangles << tri1; - triangles << tri2; - return triangles; + return {tri1, tri2}; } // ============================================================================= // -void LDObject::replace (LDObject* other) +void LDObject::replace (LDObjectPtr other) { long idx = lineNumber(); assert (idx != -1); @@ -226,10 +223,10 @@ // ============================================================================= // -void LDObject::swap (LDObject* other) +void LDObject::swap (LDObjectPtr other) { assert (document() == other->document()); - document()->swapObjects (this, other); + document()->swapObjects (thisptr(), other); } // ============================================================================= @@ -252,6 +249,16 @@ // ============================================================================= // +LDCondLine::LDCondLine (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + setVertex (0, v0); + setVertex (1, v1); + setVertex (2, v2); + setVertex (3, v3); +} + +// ============================================================================= +// LDObject::~LDObject() {} // ============================================================================= @@ -268,25 +275,19 @@ // If this object was associated to a file, remove it off it now if (document()) - document()->forgetObject (this); + document()->forgetObject (thisptr()); // Delete the GL lists - g_win->R()->forgetObject (this); + g_win->R()->forgetObject (thisptr()); // Remove this object from the list of LDObjects - g_LDObjects.removeOne (this); - - // The renderer's mouse-over field also needs to be cleared... - // Remind me to implement smart pointers someday. - if (g_win->R()->objectAtCursor() == this) - g_win->R()->setObjectAtCursor (null); - + g_LDObjects.removeOne (LDObjectWeakPtr (thisptr())); delete this; } // ============================================================================= // -static void transformObject (LDObject* obj, Matrix transform, Vertex pos, int parentcolor) +static void transformObject (LDObjectPtr obj, Matrix transform, Vertex pos, int parentcolor) { switch (obj->type()) { @@ -306,10 +307,9 @@ case LDObject::ESubfile: { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = qSharedPointerCast<LDSubfile> (obj); Matrix newMatrix = transform * ref->transform(); Vertex newpos = ref->position(); - newpos.transform (transform, pos); ref->setPosition (newpos); ref->setTransform (newMatrix); @@ -331,10 +331,10 @@ LDObjectList objs = fileInfo()->inlineContents (deep, render); // Transform the objects - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { // Set the parent now so we know what inlined the object. - obj->setParent (this); + obj->setParent (LDObjectWeakPtr (thisptr())); transformObject (obj, transform(), position(), color()); } @@ -408,7 +408,7 @@ for (long i = start; i != end; i += incr) { - LDObject* obj = objs[i]; + LDObjectPtr obj = objs[i]; const long idx = obj->lineNumber(), target = idx + (up ? -1 : 1); @@ -432,7 +432,7 @@ // The objects need to be recompiled, otherwise their pick lists are left with // the wrong index colors which messes up selection. - for (LDObject* obj : objsToCompile) + for (LDObjectPtr obj : objsToCompile) g_win->R()->compileObject (obj); } @@ -440,7 +440,7 @@ // String LDObject::typeName (LDObject::Type type) { - LDObject* obj = LDObject::getDefault (type); + LDObjectPtr obj = LDObject::getDefault (type); String name = obj->typeName(); obj->destroy(); return name; @@ -459,7 +459,7 @@ { int count = 0; - for (LDObject * obj : objs) + for (LDObjectPtr obj : objs) if (obj->type() == objType) count++; @@ -483,41 +483,41 @@ // ============================================================================= // -LDObject* LDObject::topLevelParent() +LDObjectPtr LDObject::topLevelParent() { if (parent() == null) - return this; + return thisptr(); - LDObject* it = this; + LDObjectWeakPtr it (thisptr()); - while (it->parent() != null) - it = it->parent(); + while (it.toStrongRef()->parent() != null) + it = it.toStrongRef()->parent(); - return it; + return it.toStrongRef(); } // ============================================================================= // -LDObject* LDObject::next() const +LDObjectPtr LDObject::next() const { long idx = lineNumber(); assert (idx != -1); if (idx == (long) document()->getObjectCount() - 1) - return null; + return LDObjectPtr(); return document()->getObject (idx + 1); } // ============================================================================= // -LDObject* LDObject::previous() const +LDObjectPtr LDObject::previous() const { long idx = lineNumber(); assert (idx != -1); if (idx == 0) - return null; + return LDObjectPtr(); return document()->getObject (idx - 1); } @@ -528,13 +528,13 @@ { if (hasMatrix()) { - LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (this); + LDMatrixObjectPtr mo = thisptr().dynamicCast<LDMatrixObject>(); mo->setPosition (mo->position() + vect); } elif (type() == LDObject::EVertex) { // ugh - static_cast<LDVertex*> (this)->pos += vect; + thisptr().staticCast<LDVertex>()->pos += vect; } else { @@ -545,25 +545,25 @@ // ============================================================================= // -#define CHECK_FOR_OBJ(N) \ - if (type == LDObject::E##N) \ - return new LD##N; - -LDObject* LDObject::getDefault (const LDObject::Type type) +LDObjectPtr LDObject::getDefault (const LDObject::Type type) { - CHECK_FOR_OBJ (Comment) - CHECK_FOR_OBJ (BFC) - CHECK_FOR_OBJ (Line) - CHECK_FOR_OBJ (CondLine) - CHECK_FOR_OBJ (Subfile) - CHECK_FOR_OBJ (Triangle) - CHECK_FOR_OBJ (Quad) - CHECK_FOR_OBJ (Empty) - CHECK_FOR_OBJ (BFC) - CHECK_FOR_OBJ (Error) - CHECK_FOR_OBJ (Vertex) - CHECK_FOR_OBJ (Overlay) - return null; + switch (type) + { + case EComment: return spawn<LDComment>(); + case EBFC: return spawn<LDBFC>(); + case ELine: return spawn<LDLine>(); + case ECondLine: return spawn<LDCondLine>(); + case ESubfile: return spawn<LDSubfile>(); + case ETriangle: return spawn<LDTriangle>(); + case EQuad: return spawn<LDQuad>(); + case EEmpty: return spawn<LDEmpty>(); + case EError: return spawn<LDError>(); + case EVertex: return spawn<LDVertex>(); + case EOverlay: return spawn<LDOverlay>(); + case EUnidentified: assert (false); + case ENumTypes: assert (false); + } + return LDObjectPtr(); } // ============================================================================= @@ -613,9 +613,9 @@ if (idx > 0) { - LDBFC* bfc = dynamic_cast<LDBFC*> (previous()); + LDBFCPtr bfc = previous().dynamicCast<LDBFC>(); - if (bfc && bfc->statement() == LDBFC::InvertNext) + if (not bfc.isNull() && bfc->statement() == LDBFC::InvertNext) { // This is prefixed with an invertnext, thus remove it. bfc->destroy(); @@ -624,57 +624,55 @@ } // Not inverted, thus prefix it with a new invertnext. - LDBFC* bfc = new LDBFC (LDBFC::InvertNext); - document()->insertObj (idx, bfc); + document()->insertObj (idx, spawn<LDBFC> (LDBFC::InvertNext)); } // ============================================================================= // -static void invertLine (LDObject* line) +void LDLine::invert() { // For lines, we swap the vertices. I don't think that a // cond-line's control points need to be swapped, do they? - Vertex tmp = line->vertex (0); - line->setVertex (0, line->vertex (1)); - line->setVertex (1, tmp); -} - -void LDLine::invert() -{ - invertLine (this); + Vertex tmp = vertex (0); + setVertex (0, vertex (1)); + setVertex (1, tmp); } void LDCondLine::invert() { - invertLine (this); + static_cast<LDLine*> (this)->invert(); } void LDVertex::invert() {} // ============================================================================= // -LDLine* LDCondLine::demote() +LDLinePtr LDCondLine::demote() { - LDLine* repl = new LDLine; + LDLinePtr replacement (spawn<LDLine>()); - for (int i = 0; i < repl->numVertices(); ++i) - repl->setVertex (i, vertex (i)); + for (int i = 0; i < replacement->numVertices(); ++i) + replacement->setVertex (i, vertex (i)); - repl->setColor (color()); + replacement->setColor (color()); - replace (repl); - return repl; + replace (replacement); + return replacement; } // ============================================================================= // -LDObject* LDObject::fromID (int id) +LDObjectPtr LDObject::fromID (int id) { - for (LDObject* obj : g_LDObjects) - if (obj->id() == id) + for (LDObjectWeakPtr obj : g_LDObjects) + { + LDObjectPtr obj2 = obj.toStrongRef(); + + if (obj2->id() == id) return obj; + } - return null; + return LDObjectPtr(); } // ============================================================================= @@ -693,7 +691,8 @@ // It takes care of history management so we can capture low-level changes, this // makes history stuff work out of the box. // -template<class T> static void changeProperty (LDObject* obj, T* ptr, const T& val) +template<typename T> +static void changeProperty (LDObjectPtr obj, T* ptr, const T& val) { long idx; @@ -720,7 +719,7 @@ // void LDObject::setColor (const int& val) { - changeProperty (this, &m_color, val); + changeProperty (thisptr(), &m_color, val); } // ============================================================================= @@ -737,7 +736,7 @@ if (document() != null) document()->vertexChanged (*m_coords[i], vert); - changeProperty (this, &m_coords[i], LDSharedVertex::getSharedVertex (vert)); + changeProperty (thisptr(), &m_coords[i], LDSharedVertex::getSharedVertex (vert)); } // ============================================================================= @@ -786,14 +785,14 @@ // ============================================================================= // -void LDSharedVertex::addRef (LDObject* a) +void LDSharedVertex::addRef (LDObjectPtr a) { m_refs << a; } // ============================================================================= // -void LDSharedVertex::delRef (LDObject* a) +void LDSharedVertex::delRef (LDObjectPtr a) { m_refs.removeOne (a); @@ -809,7 +808,7 @@ void LDObject::select() { assert (document() != null); - document()->addToSelection (this); + document()->addToSelection (thisptr()); } // ============================================================================= @@ -817,7 +816,7 @@ void LDObject::deselect() { assert (document() != null); - document()->removeFromSelection (this); + document()->removeFromSelection (thisptr()); } // ============================================================================= @@ -842,45 +841,9 @@ // ============================================================================= // -LDObject* LDObject::createCopy() const +LDObjectPtr LDObject::createCopy() const { - /* - LDObject* copy = clone(); - copy->setFile (null); - copy->chooseID(); - copy->setSelected (false); - */ - - /* - LDObject* copy = getDefault (getType()); - copy->setColor (color()); - - if (hasMatrix()) - { - LDMatrixObject* copyMo = static_cast<LDMatrixObject*> (copy); - const LDMatrixObject* mo = static_cast<const LDMatrixObject*> (this); - copyMo->setPosition (mo->getPosition()); - copyMo->setTransform (mo->transform()); - } - else - { - for (int i = 0; i < vertices(); ++i) - copy->setVertex (getVertex (i)); - } - - switch (getType()) - { - case Subfile: - { - LDSubfile* copyRef = static_cast<LDSubfile*> (copy); - const LDSubfile* ref = static_cast<const LDSubfile*> (this); - - copyRef->setFileInfo (ref->fileInfo()); - } - } - */ - - LDObject* copy = parseLine (asText()); + LDObjectPtr copy = parseLine (asText()); return copy; } @@ -889,7 +852,7 @@ void LDSubfile::setFileInfo (const LDDocumentPointer& a) { if (document() != null) - document()->removeKnownVerticesOf (this); + document()->removeKnownVerticesOf (thisptr()); m_fileInfo = a; @@ -904,5 +867,5 @@ } if (document() != null) - document()->addKnownVerticesOf (this); + document()->addKnownVerticesOf (thisptr()); };
--- a/src/ldObject.h Mon May 05 17:18:01 2014 +0300 +++ b/src/ldObject.h Fri May 09 12:06:56 2014 +0300 @@ -17,37 +17,34 @@ */ #pragma once +#include <type_traits> #include "main.h" #include "basics.h" #include "misc/documentPointer.h" #include "glShared.h" -#define LDOBJ(T) \ -protected: \ - virtual LD##T* clone() override \ - { \ - return new LD##T (*this); \ - } \ - \ -public: \ - virtual LDObject::Type type() const override \ - { \ - return LDObject::E##T; \ - } \ - virtual String asText() const override; \ - virtual void invert() override; +#define LDOBJ(T) \ +public: \ + virtual LDObject::Type type() const override \ + { \ + return LDObject::E##T; \ + } \ + virtual String asText() const override; \ + virtual void invert() override; \ +protected: \ + friend class QSharedPointer<LD##T>::ExternalRefCount; \ -#define LDOBJ_NAME(N) virtual String typeName() const override { return #N; } -#define LDOBJ_VERTICES(V) virtual int numVertices() const override { return V; } -#define LDOBJ_SETCOLORED(V) virtual bool isColored() const override { return V; } +#define LDOBJ_NAME(N) public: virtual String typeName() const override { return #N; } +#define LDOBJ_VERTICES(V) public: virtual int numVertices() const override { return V; } +#define LDOBJ_SETCOLORED(V) public: virtual bool isColored() const override { return V; } #define LDOBJ_COLORED LDOBJ_SETCOLORED (true) #define LDOBJ_UNCOLORED LDOBJ_SETCOLORED (false) -#define LDOBJ_CUSTOM_SCEMANTIC virtual bool isScemantic() const override +#define LDOBJ_CUSTOM_SCEMANTIC public: virtual bool isScemantic() const override #define LDOBJ_SCEMANTIC LDOBJ_CUSTOM_SCEMANTIC { return true; } #define LDOBJ_NON_SCEMANTIC LDOBJ_CUSTOM_SCEMANTIC { return false; } -#define LDOBJ_SETMATRIX(V) virtual bool hasMatrix() const override { return V; } +#define LDOBJ_SETMATRIX(V) public: virtual bool hasMatrix() const override { return V; } #define LDOBJ_HAS_MATRIX LDOBJ_SETMATRIX (true) #define LDOBJ_NO_MATRIX LDOBJ_SETMATRIX (false) @@ -66,13 +63,13 @@ // ============================================================================= class LDObject { - PROPERTY (public, bool, isHidden, setHidden, STOCK_WRITE) - PROPERTY (public, bool, isSelected, setSelected, STOCK_WRITE) - PROPERTY (public, LDObject*, parent, setParent, STOCK_WRITE) - PROPERTY (public, LDDocument*, document, setDocument, STOCK_WRITE) - PROPERTY (private, int, id, setID, STOCK_WRITE) - PROPERTY (public, int, color, setColor, CUSTOM_WRITE) - PROPERTY (private, QColor, randomColor, setRandomColor, STOCK_WRITE) + PROPERTY (public, bool, isHidden, setHidden, STOCK_WRITE) + PROPERTY (public, bool, isSelected, setSelected, STOCK_WRITE) + PROPERTY (public, LDObjectWeakPtr, parent, setParent, STOCK_WRITE) + PROPERTY (public, LDDocument*, document, setDocument, STOCK_WRITE) + PROPERTY (private, int, id, setID, STOCK_WRITE) + PROPERTY (public, int, color, setColor, CUSTOM_WRITE) + PROPERTY (private, QColor, randomColor, setRandomColor, STOCK_WRITE) public: // Object type codes. @@ -101,7 +98,7 @@ virtual String asText() const = 0; // Makes a copy of this object - LDObject* createCopy() const; + LDObjectPtr createCopy() const; // Deletes this object void destroy(); @@ -128,16 +125,16 @@ void move (Vertex vect); // Object after this in the current file - LDObject* next() const; + LDObjectPtr next() const; // Number of vertices this object has virtual int numVertices() const = 0; // Object prior to this in the current file - LDObject* previous() const; + LDObjectPtr previous() const; // Replace this LDObject with another LDObject. Object is deleted in the process. - void replace (LDObject* other); + void replace (LDObjectPtr other); // Selects this object. void select(); @@ -149,10 +146,10 @@ void setVertexCoord (int i, Axis ax, double value); // Swap this object with another. - void swap (LDObject* other); + void swap (LDObjectPtr other); // What object in the current file ultimately references this? - LDObject* topLevelParent(); + LDObjectPtr topLevelParent(); // Type enumerator of this object virtual Type type() const = 0; @@ -167,14 +164,14 @@ static String typeName (LDObject::Type type); // Returns a default-constructed LDObject by the given type - static LDObject* getDefault (const LDObject::Type type); + static LDObjectPtr getDefault (const LDObject::Type type); // TODO: move this to LDDocument? static void moveObjects (LDObjectList objs, const bool up); // Get a description of a list of LDObjects static String describeObjects (const LDObjectList& objs); - static LDObject* fromID (int id); + static LDObjectPtr fromID (int id); LDPolygon* getPolygon(); // TODO: make this private! @@ -190,13 +187,44 @@ virtual ~LDObject(); void chooseID(); + // Even though we supply a custom deleter to QSharedPointer, the shared + // pointer's base class still calls operator delete directly in one of + // its methods. The method should never be called but we need to declare + // the class making this delete call a friend anyway. + friend class QSharedPointer<LDObject>::ExternalRefCount; + + inline LDObjectPtr thisptr() + { + return LDObjectPtr (this); + } + private: - virtual LDObject* clone() = 0; LDSharedVertex* m_coords[4]; }; +// +// Makes a new LDObject. This makes the shared pointer always use the custom +// deleter so that all deletions go through destroy(); +// +template<typename T, typename... Args> +inline QSharedPointer<T> spawn (Args... args) +{ + static_assert (std::is_base_of<LDObject, T>::value, "spawn may only be used with LDObject-derivatives"); + return QSharedPointer<T> (new T (args...), [](T* obj){ obj->destroy(); }); +} + NUMERIC_ENUM_OPERATORS (LDObject::Type) +// +// Apparently QWeakPointer doesn't implement operator<. This is a problem when +// some of the code needs to sort and remove duplicates from LDObject lists. +// Adding a specialized version here: +// +inline bool operator< (LDObjectWeakPtr a, LDObjectWeakPtr b) +{ + return a.data() < b.data(); +} + // ============================================================================= // LDSharedVertex // @@ -215,8 +243,8 @@ return m_data; } - void addRef (LDObject* a); - void delRef (LDObject* a); + void addRef (LDObjectPtr a); + void delRef (LDObjectPtr a); static LDSharedVertex* getSharedVertex (const Vertex& a); @@ -243,7 +271,7 @@ // class LDMatrixObject { - PROPERTY (public, LDObject*, linkPointer, setLinkPointer, STOCK_WRITE) + PROPERTY (public, LDObjectPtr, linkPointer, setLinkPointer, STOCK_WRITE) PROPERTY (public, Matrix, transform, setTransform, CUSTOM_WRITE) public: @@ -279,6 +307,9 @@ LDSharedVertex* m_position; }; +using LDMatrixObjectPtr = QSharedPointer<LDMatrixObject>; +using LDMatrixObjectWeakPtr = QWeakPointer<LDMatrixObject>; + // ============================================================================= // // Represents a line in the LDraw file that could not be properly parsed. It is @@ -304,6 +335,9 @@ m_reason (reason) {} }; +using LDErrorPtr = QSharedPointer<LDError>; +using LDErrorWeakPtr = QWeakPointer<LDError>; + // ============================================================================= // // Represents an empty line in the LDraw code file. @@ -318,6 +352,9 @@ LDOBJ_NO_MATRIX }; +using LDEmptyPtr = QSharedPointer<LDEmpty>; +using LDEmptyWeakPtr = QWeakPointer<LDEmpty>; + // ============================================================================= // // Represents a code-0 comment in the LDraw code file. @@ -337,6 +374,9 @@ LDComment (String text) : m_text (text) {} }; +using LDCommentPtr = QSharedPointer<LDComment>; +using LDCommentWeakPtr = QWeakPointer<LDComment>; + // ============================================================================= // // Represents a 0 BFC statement in the LDraw code. eStatement contains the type @@ -377,6 +417,9 @@ static const char* k_statementStrings[]; }; +using LDBFCPtr = QSharedPointer<LDBFC>; +using LDBFCWeakPtr = QWeakPointer<LDBFC>; + // ============================================================================= // LDSubfile // @@ -405,7 +448,7 @@ LDSubfile() { - setLinkPointer (this); + setLinkPointer (QSharedPointer<LDSubfile> (this)); } // Inlines this subfile. Note that return type is an array of heap-allocated @@ -418,6 +461,8 @@ }; Q_DECLARE_OPERATORS_FOR_FLAGS (LDSubfile::InlineFlags) +using LDSubfilePtr = QSharedPointer<LDSubfile>; +using LDSubfileWeakPtr = QWeakPointer<LDSubfile>; // ============================================================================= // LDLine @@ -440,6 +485,9 @@ LDLine (Vertex v1, Vertex v2); }; +using LDLinePtr = QSharedPointer<LDLine>; +using LDLineWeakPtr = QWeakPointer<LDLine>; + // ============================================================================= // LDCondLine // @@ -457,9 +505,13 @@ public: LDCondLine() {} - LDLine* demote(); + LDCondLine (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3); + LDLinePtr demote(); }; +using LDCondLinePtr = QSharedPointer<LDCondLine>; +using LDCondLineWeakPtr = QWeakPointer<LDCondLine>; + // ============================================================================= // LDTriangle // @@ -486,6 +538,9 @@ } }; +using LDTrianglePtr = QSharedPointer<LDTriangle>; +using LDTriangleWeakPtr = QWeakPointer<LDTriangle>; + // ============================================================================= // LDQuad // @@ -506,9 +561,12 @@ LDQuad (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3); // Split this quad into two triangles (note: heap-allocated) - QList<LDTriangle*> splitToTriangles(); + QList<LDTrianglePtr> splitToTriangles(); }; +using LDQuadPtr = QSharedPointer<LDQuad>; +using LDQuadWeakPtr = QWeakPointer<LDQuad>; + // ============================================================================= // LDVertex // @@ -532,6 +590,9 @@ Vertex pos; }; +using LDVertexPtr = QSharedPointer<LDVertex>; +using LDVertexWeakPtr = QWeakPointer<LDVertex>; + // ============================================================================= // LDOverlay // @@ -546,14 +607,17 @@ LDOBJ_UNCOLORED LDOBJ_NON_SCEMANTIC LDOBJ_NO_MATRIX - PROPERTY (public, int, camera, setCamera, STOCK_WRITE) - PROPERTY (public, int, x, setX, STOCK_WRITE) - PROPERTY (public, int, y, setY, STOCK_WRITE) - PROPERTY (public, int, width, setWidth, STOCK_WRITE) - PROPERTY (public, int, height, setHeight, STOCK_WRITE) - PROPERTY (public, String, fileName, setFileName, STOCK_WRITE) + PROPERTY (public, int, camera, setCamera, STOCK_WRITE) + PROPERTY (public, int, x, setX, STOCK_WRITE) + PROPERTY (public, int, y, setY, STOCK_WRITE) + PROPERTY (public, int, width, setWidth, STOCK_WRITE) + PROPERTY (public, int, height, setHeight, STOCK_WRITE) + PROPERTY (public, String, fileName, setFileName, STOCK_WRITE) }; +using LDOverlayPtr = QSharedPointer<LDOverlay>; +using LDOverlayWeakPtr = QWeakPointer<LDOverlay>; + // Other common LDraw stuff static const String g_CALicense ("!LICENSE Redistributable under CCAL version 2.0 : see CAreadme.txt"); static const String g_nonCALicense ("!LICENSE Not redistributable : see NonCAreadme.txt");
--- a/src/main.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/main.cc Fri May 09 12:06:56 2014 +0300 @@ -43,6 +43,12 @@ CFGENTRY (Bool, firstStart, true); +static void deleteline (LDLine* obj) +{ + fprintf (stderr, "delete %p\n", obj); + delete obj; +} + // ============================================================================= // int main (int argc, char* argv[]) @@ -68,7 +74,15 @@ initColors(); MainWindow* win = new MainWindow; newFile(); - win->show(); + //win->show(); + + QSharedPointer<LDLine> obj (new LDLine, &deleteline); + fprint (stderr, "%1: %2\n", obj.data(), obj->type()); + //class A { public: virtual ~A(){} virtual int foo() = 0; void destroy() { delete this; }}; + //class B : public A { public: virtual ~B(){} virtual int foo() override { return 5; }}; + //QSharedPointer<A> a (new B, [](A* p) { p->destroy(); }); + //fprintf (stderr, "%p (%lu bytes)\n", a.data(), sizeof *a); + exit (0); // If this is the first start, get the user to configuration. Especially point // them to the profile tab, it's the most important form to fill in.
--- a/src/mainWindow.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/mainWindow.cc Fri May 09 12:06:56 2014 +0300 @@ -264,7 +264,7 @@ getCurrentDocument()->getObject (0)->type() == LDObject::EComment) { // Append title - LDComment* comm = static_cast<LDComment*> (getCurrentDocument()->getObject (0)); + LDCommentPtr comm = getCurrentDocument()->getObject (0).staticCast<LDComment>(); title += format (": %1", comm->text()); } @@ -294,7 +294,7 @@ LDObjectList selCopy = selection(); // Delete the objects that were being selected - for (LDObject* obj : selCopy) + for (LDObjectPtr obj : selCopy) obj->destroy(); refresh(); @@ -318,7 +318,7 @@ ui->objectList->clear(); - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { String descr; @@ -326,7 +326,7 @@ { case LDObject::EComment: { - descr = static_cast<LDComment*> (obj)->text(); + descr = obj.staticCast<LDComment>()->text(); // Remove leading whitespace while (descr[0] == ' ') @@ -361,13 +361,13 @@ case LDObject::EVertex: { - descr = static_cast<LDVertex*> (obj)->pos.toString (true); + descr = obj.staticCast<LDVertex>()->pos.toString (true); break; } case LDObject::ESubfile: { - LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDSubfilePtr ref = obj.staticCast<LDSubfile>(); descr = format ("%1 %2, (", ref->fileInfo()->getDisplayName(), ref->position().toString (true)); @@ -380,13 +380,13 @@ case LDObject::EBFC: { - descr = LDBFC::k_statementStrings[static_cast<LDBFC*> (obj)->statement()]; + descr = LDBFC::k_statementStrings[obj.staticCast<LDBFC>()->statement()]; break; } case LDObject::EOverlay: { - LDOverlay* ovl = static_cast<LDOverlay*> (obj); + LDOverlayPtr ovl = obj.staticCast<LDOverlay>(); descr = format ("[%1] %2 (%3, %4), %5 x %6", g_CameraNames[ovl->camera()], basename (ovl->fileName()), ovl->x(), ovl->y(), ovl->width(), ovl->height()); @@ -444,7 +444,7 @@ if (selection().isEmpty()) return; - LDObject* obj = selection().last(); + LDObjectPtr obj = selection().last(); ui->objectList->scrollToItem (obj->qObjListEntry); } @@ -461,7 +461,7 @@ getCurrentDocument()->clearSelection(); const QList<QListWidgetItem*> items = ui->objectList->selectedItems(); - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { for (QListWidgetItem* item : items) { @@ -477,7 +477,7 @@ LDObjectList compound = priorSelection + selection(); removeDuplicates (compound); - for (LDObject* obj : compound) + for (LDObjectPtr obj : compound) R()->compileObject (obj); R()->update(); @@ -512,7 +512,7 @@ int newColor = col->index; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (not obj->isColored()) continue; // uncolored object @@ -561,7 +561,7 @@ ui->objectList->clearSelection(); - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (obj->qObjListEntry == null) continue; @@ -578,7 +578,7 @@ { int result = -1; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (not obj->isColored()) continue; // doesn't use color @@ -599,7 +599,7 @@ { LDObject::Type result = LDObject::EUnidentified; - for (LDObject* obj : selection()) + for (LDObjectPtr obj : selection()) { if (result != LDObject::EUnidentified && obj->color() != result) return LDObject::EUnidentified; @@ -634,7 +634,7 @@ void MainWindow::spawnContextMenu (const QPoint pos) { const bool single = (selection().size() == 1); - LDObject* singleObj = (single) ? selection()[0] : null; + LDObjectPtr singleObj = single ? selection().first() : LDObjectPtr(); QMenu* contextMenu = new QMenu; @@ -661,7 +661,7 @@ contextMenu->addAction (ui->actionModeDraw); contextMenu->addAction (ui->actionModeCircle); - if (selection().size() > 0) + if (not selection().isEmpty()) { contextMenu->addSeparator(); contextMenu->addAction (ui->actionSubfileSelection); @@ -682,7 +682,7 @@ { LDObjectList objs; - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { if (not obj->isColored() || obj->color() != colnum) continue; @@ -690,7 +690,7 @@ objs << obj; } - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) obj->destroy(); } @@ -708,18 +708,14 @@ // void MainWindow::slot_editObject (QListWidgetItem* listitem) { - LDObject* obj = null; - - for (LDObject* it : getCurrentDocument()->objects()) + for (LDObjectPtr it : getCurrentDocument()->objects()) { if (it->qObjListEntry == listitem) { - obj = it; + AddObjectDialog::staticDialog (it->type(), it); break; } } - - AddObjectDialog::staticDialog (obj->type(), obj); } // ============================================================================= @@ -852,7 +848,7 @@ { std::map<int, int> counts; - for (LDObject* obj : getCurrentDocument()->objects()) + for (LDObjectPtr obj : getCurrentDocument()->objects()) { if (not obj->isColored()) continue; @@ -970,7 +966,7 @@ ui->objectList->clear(); LDDocument* f = getCurrentDocument(); -for (LDObject* obj : *f) +for (LDObjectPtr obj : *f) ui->objectList->addItem (obj->qObjListEntry); #endif
--- a/src/miscallenous.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/miscallenous.cc Fri May 09 12:06:56 2014 +0300 @@ -210,10 +210,10 @@ LDBoundingBox box; // Calculate center vertex - for (LDObject* obj : objs) + for (LDObjectPtr obj : objs) { if (obj->hasMatrix()) - box << dynamic_cast<LDMatrixObject*> (obj)->position(); + box << obj.dynamicCast<LDMatrixObject>()->position(); else box << obj; }
--- a/src/partDownloader.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/partDownloader.cc Fri May 09 12:06:56 2014 +0300 @@ -455,9 +455,9 @@ // from unknown file references, try resolve that by downloading the reference. // This is why downloading a part may end up downloading multiple files, as // it resolves dependencies. - for (LDObject* obj : f->objects()) + for (LDObjectPtr obj : f->objects()) { - LDError* err = dynamic_cast<LDError*> (obj); + LDErrorPtr err = obj.dynamicCast<LDError>(); if (err == null || err->fileReferenced().isEmpty()) continue;
--- a/src/primitives.cc Mon May 05 17:18:01 2014 +0300 +++ b/src/primitives.cc Fri May 09 12:06:56 2014 +0300 @@ -406,7 +406,7 @@ Vertex v0 (x0, 0.0f, z0), v1 (x1, 0.0f, z1); - LDLine* line = new LDLine; + LDLinePtr line (spawn<LDLine>()); line->setVertex (0, v0); line->setVertex (1, v1); line->setColor (edgecolor); @@ -456,12 +456,8 @@ v2 (x2, y2, z2), v3 (x3, y3, z3); - LDQuad* quad = new LDQuad; + LDQuadPtr quad (spawn<LDQuad> (v0, v1, v2, v3)); quad->setColor (maincolor); - quad->setVertex (0, v0); - quad->setVertex (1, v1); - quad->setVertex (2, v2); - quad->setVertex (3, v3); if (type == Cylinder) quad->invert(); @@ -491,7 +487,7 @@ // Disc negatives need to go the other way around, otherwise // they'll end up upside-down. - LDTriangle* seg = new LDTriangle; + LDTrianglePtr seg (spawn<LDTriangle>()); seg->setColor (maincolor); seg->setVertex (type == Disc ? 0 : 2, v0); seg->setVertex (1, v1); @@ -514,7 +510,9 @@ v3 (radialPoint (i - 1, divs, cos), 0.0f, radialPoint (i - 1, divs, sin)); if (type == Cylinder) + { v1 = Vertex (v0[X], 1.0f, v0[Z]); + } elif (type == Cone) { v1 = Vertex (v0[X] * (num + 1), 0.0f, v0[Z] * (num + 1)); @@ -523,7 +521,7 @@ v0.setZ (v0.z() * num); } - LDCondLine* line = new LDCondLine; + LDCondLinePtr line = (spawn<LDCondLine>()); line->setColor (edgecolor); line->setVertex (0, v0); line->setVertex (1, v1); @@ -619,18 +617,18 @@ author = format ("%1 [%2]", cfg::defaultName, cfg::defaultUser); } - f->addObjects ( - { - new LDComment (descr), - new LDComment (format ("Name: %1", name)), - new LDComment (format ("Author: %1", author)), - new LDComment (format ("!LDRAW_ORG Unofficial_%1Primitive", divs == g_hires ? "48_" : "")), - new LDComment (license), - new LDEmpty, - new LDBFC (LDBFC::CertifyCCW), - new LDEmpty, - }); + LDObjectList objs; + objs << spawn<LDComment> (descr) + << spawn<LDComment> (format ("Name: %1", name)) + << spawn<LDComment> (format ("Author: %1", author)) + << spawn<LDComment> (format ("!LDRAW_ORG Unofficial_%1Primitive", divs == g_hires ? "48_" : "")) + << spawn<LDComment> (license) + << spawn<LDEmpty>() + << spawn<LDBFC> (LDBFC::CertifyCCW) + << spawn<LDEmpty>(); + + f->addObjects (objs); f->addObjects (makePrimitive (type, segs, divs, num)); return f; }