Skip to content

Commit c97a332

Browse files
committed
Fix crash-prone weak pointers, atomic save, and misc cleanup
- Guard all toStrongRef() calls with null checks to prevent crashes - Save project files atomically (write to .tmp, then rename) - Fix macOS CI workflow typo that broke test discovery - Remove duplicate main.qrc entry in mapmap.pro - Upgrade C++ standard from c++11 to c++17 - Replace NULL with nullptr throughout our code - Remove stale FIXME comment and duplicate #include
1 parent 2372126 commit c97a332

9 files changed

Lines changed: 58 additions & 31 deletions

File tree

.github/workflows/macos-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
3232
- name: Build and run tests
3333
run: |
34-
export PATH="($brew --prefix=qt)/bin:$PATH"
34+
export PATH="$(brew --prefix qt)/bin:$PATH"
3535
cd tests/
3636
qmake6 tests.pro
3737
make -j$(sysctl -n hw.logicalcpu)

mapmap.pro

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CONFIG += qt
22
CONFIG += debug
3-
CONFIG += c++11
3+
CONFIG += c++17
44

55
TEMPLATE = app
66

@@ -27,8 +27,7 @@ RESOURCES = \
2727
main.qrc \
2828
translations/translation.qrc \
2929
docs/documentation.qrc \
30-
resources/interface.qrc \
31-
main.qrc # Main resource file
30+
resources/interface.qrc
3231

3332
# Manage lrelease (for translations)
3433
isEmpty(QMAKE_LRELEASE) {

src/app/main.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "MetaObjectRegistry.h"
1515

1616
#include <stdlib.h>
17-
#include <iostream>
1817

1918
MM_USE_NAMESPACE
2019

src/control/OscInterface.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ class OscInterface {
4141
public:
4242
typedef QSharedPointer<OscInterface> ptr;
4343

44-
// FIXME: change listen_port to a int
4544
OscInterface(int listen_port);
4645
~OscInterface();
4746

src/core/Commands.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,16 @@ TransformShapeCommand::TransformShapeCommand(MapperGLCanvas* canvas, TransformSh
9595
_option = option;
9696

9797
// Clone shape before applying transform.
98-
_originalShape.reset(_shape.toStrongRef()->clone());
98+
auto strong = _shape.toStrongRef();
99+
if (strong)
100+
_originalShape.reset(strong->clone());
99101
}
100102

101103
void TransformShapeCommand::undo() {
102104
// Copy back shape.
103-
_shape.toStrongRef()->copyFrom(*_originalShape);
105+
auto strong = _shape.toStrongRef();
106+
if (!strong) return;
107+
strong->copyFrom(*_originalShape);
104108

105109
// Update everything.
106110
_canvas->currentShapeWasChanged();

src/gui/ConsoleWindow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
namespace mmp {
2424

25-
ConsoleWindow* ConsoleWindow::instance = NULL;
25+
ConsoleWindow* ConsoleWindow::instance = nullptr;
2626

2727
ConsoleWindow::ConsoleWindow(QWidget *parent) : QMainWindow(parent)
2828
{
@@ -142,7 +142,7 @@ void ConsoleWindow::kill()
142142
{
143143
if (instance) {
144144
delete instance;
145-
instance = NULL;
145+
instance = nullptr;
146146
}
147147
}
148148

src/gui/LayerGui.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ namespace mmp {
2525

2626
LayerGui::LayerGui(Layer::ptr layer)
2727
: _layer(layer),
28-
_graphicsItem(NULL),
29-
_inputGraphicsItem(NULL)
28+
_graphicsItem(nullptr),
29+
_inputGraphicsItem(nullptr)
3030
{
3131
outputShape = layer->getShape();
3232
Q_CHECK_PTR(outputShape);
@@ -275,7 +275,7 @@ EllipseColorLayerGui::EllipseColorLayerGui(Layer::ptr layer) : ColorLayerGui(lay
275275

276276
TextureLayerGui::TextureLayerGui(QSharedPointer<TextureLayer> mapping)
277277
: LayerGui(mapping),
278-
_meshItem(NULL)
278+
_meshItem(nullptr)
279279
{
280280
// Assign members pointers.
281281
textureLayer = qSharedPointerCast<TextureLayer>(_layer);

src/gui/MainWindow.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ MainWindow::MainWindow()
5454
// TODO: not sure we need this anymore since we have NULL_UID
5555
_hasCurrentSource = false;
5656
_hasCurrentLayer = false;
57-
currentSelectedItem = NULL;
57+
currentSelectedItem = nullptr;
5858

5959
// Frames per second.
6060
_framesPerSecond = (-1);
@@ -2225,7 +2225,7 @@ void MainWindow::startFullScreen()
22252225

22262226
void MainWindow::createMenus()
22272227
{
2228-
QMenuBar *menuBar = NULL;
2228+
QMenuBar *menuBar = nullptr;
22292229

22302230
#ifdef __MACOSX_CORE__
22312231
menuBar = new QMenuBar(0);
@@ -2624,7 +2624,9 @@ bool MainWindow::loadFile(const QString &fileName)
26242624

26252625
bool MainWindow::saveFile(const QString &fileName)
26262626
{
2627-
QFile file(fileName);
2627+
// Write to a temporary file first, then rename for atomic save.
2628+
QString tmpFileName = fileName + ".tmp";
2629+
QFile file(tmpFileName);
26282630
if (! file.open(QFile::WriteOnly | QFile::Text))
26292631
{
26302632
QMessageBox::warning(this, tr("Error saving mapping project"),
@@ -2637,12 +2639,26 @@ bool MainWindow::saveFile(const QString &fileName)
26372639
ProjectWriter writer(this);
26382640
if (writer.writeFile(&file))
26392641
{
2642+
file.close();
2643+
// Remove original and rename temp file over it.
2644+
QFile::remove(fileName);
2645+
if (!QFile::rename(tmpFileName, fileName))
2646+
{
2647+
QMessageBox::warning(this, tr("Error saving mapping project"),
2648+
tr("Cannot rename temporary file to %1.")
2649+
.arg(fileName));
2650+
return false;
2651+
}
26402652
setCurrentFile(fileName);
26412653
statusBar()->showMessage(tr("File saved"), 2000);
26422654
return true;
26432655
}
26442656
else
2657+
{
2658+
file.close();
2659+
QFile::remove(tmpFileName);
26452660
return false;
2661+
}
26462662
}
26472663

26482664
void MainWindow::setCurrentFile(const QString &fileName)
@@ -2972,7 +2988,7 @@ void MainWindow::addSourceItem(uid sourceId, const QIcon& icon, const QString& n
29722988

29732989
void MainWindow::updateSourceItem(uid sourceId, const QIcon& icon, const QString& name) {
29742990
QListWidgetItem* item = getItemFromId(*sourceList, sourceId);
2975-
if (item == NULL) {
2991+
if (item == nullptr) {
29762992
// FIXME there was an assert that seemed to make MapMap crash, here.
29772993
return;
29782994
}
@@ -3196,7 +3212,7 @@ void MainWindow::removeSourceItem(uid sourceId)
31963212
Q_ASSERT( row >= 0 );
31973213
QListWidgetItem* item = sourceList->takeItem(row);
31983214
if (item == currentSelectedItem)
3199-
currentSelectedItem = NULL;
3215+
currentSelectedItem = nullptr;
32003216
delete item;
32013217

32023218
// Update list.
@@ -3601,7 +3617,7 @@ QListWidgetItem* MainWindow::getItemFromId(const QListWidget& list, uid id) {
36013617
if (row >= 0)
36023618
return list.item( row );
36033619
else
3604-
return NULL;
3620+
return nullptr;
36053621
}
36063622

36073623
int MainWindow::getItemRowFromId(const QListWidget& list, uid id)

src/gui/ShapeGraphicsItem.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,9 @@ PolygonColorGraphicsItem::PolygonColorGraphicsItem(Layer::ptr mapping, bool outp
136136
QPainterPath PolygonColorGraphicsItem::shape() const
137137
{
138138
QPainterPath path;
139-
Polygon* poly = static_cast<Polygon*>(_shape.toStrongRef().data());
140-
Q_ASSERT(poly);
139+
auto strong = _shape.toStrongRef();
140+
if (!strong) return path;
141+
Polygon* poly = static_cast<Polygon*>(strong.data());
141142
path.addPolygon(poly->toPolygon());
142143
return mapFromScene(path);
143144
}
@@ -146,8 +147,9 @@ void PolygonColorGraphicsItem::_doPaint(QPainter *painter,
146147
const QStyleOptionGraphicsItem *option)
147148
{
148149
Q_UNUSED(option);
149-
Polygon* poly = static_cast<Polygon*>(_shape.toStrongRef().data());
150-
Q_ASSERT(poly);
150+
auto strong = _shape.toStrongRef();
151+
if (!strong) return;
152+
Polygon* poly = static_cast<Polygon*>(strong.data());
151153
painter->drawPolygon(mapFromScene(poly->toPolygon()));
152154
}
153155

@@ -162,7 +164,9 @@ void MeshColorGraphicsItem::_doPaint(QPainter *painter,
162164
{
163165
Q_UNUSED(option);
164166

165-
Mesh* mesh = static_cast<Mesh*>(_shape.toStrongRef().data());
167+
auto strong = _shape.toStrongRef();
168+
if (!strong) return;
169+
Mesh* mesh = static_cast<Mesh*>(strong.data());
166170
QVector<QVector<Quad::ptr> > quads = mesh->getQuads2d();
167171

168172
// Go through the mesh quad by quad.
@@ -186,8 +190,9 @@ QPainterPath EllipseColorGraphicsItem::shape() const
186190
{
187191
// Create path for ellipse.
188192
QPainterPath path;
189-
Ellipse* ellipse = static_cast<Ellipse*>(_shape.toStrongRef().data());
190-
Q_ASSERT(ellipse);
193+
auto strong = _shape.toStrongRef();
194+
if (!strong) return path;
195+
Ellipse* ellipse = static_cast<Ellipse*>(strong.data());
191196
QTransform transform;
192197
transform.translate(ellipse->getCenter().x(), ellipse->getCenter().y());
193198
transform.rotate(ellipse->getRotation());
@@ -313,14 +318,17 @@ void TextureGraphicsItem::_postPaint(QPainter* painter,
313318

314319
QSharedPointer<Texture> TextureGraphicsItem::_getTexture()
315320
{
316-
return qSharedPointerCast<Texture>(_textureMapping.toStrongRef()->getSource());
321+
auto strong = _textureMapping.toStrongRef();
322+
if (!strong) return QSharedPointer<Texture>();
323+
return qSharedPointerCast<Texture>(strong->getSource());
317324
}
318325

319326
QPainterPath PolygonTextureGraphicsItem::shape() const
320327
{
321328
QPainterPath path;
322-
Polygon* poly = static_cast<Polygon*>(_shape.toStrongRef().data());
323-
Q_ASSERT(poly);
329+
auto strong = _shape.toStrongRef();
330+
if (!strong) return path;
331+
Polygon* poly = static_cast<Polygon*>(strong.data());
324332
path.addPolygon(poly->toPolygon());
325333
return mapFromScene(path);
326334
}
@@ -335,6 +343,7 @@ void TriangleTextureGraphicsItem::_doDrawOutput(QPainter* painter)
335343
if (isOutput())
336344
{
337345
MShape::ptr inputShape = _inputShape.toStrongRef();
346+
if (!inputShape) return;
338347
glBegin(GL_TRIANGLES);
339348
{
340349
for (int i=0; i<inputShape->nVertices(); i++)
@@ -563,8 +572,9 @@ QPainterPath EllipseTextureGraphicsItem::shape() const
563572
{
564573
// Create path for ellipse.
565574
QPainterPath path;
566-
Ellipse* ellipse = static_cast<Ellipse*>(_shape.toStrongRef().data());
567-
Q_ASSERT(ellipse);
575+
auto strong = _shape.toStrongRef();
576+
if (!strong) return path;
577+
Ellipse* ellipse = static_cast<Ellipse*>(strong.data());
568578
QTransform transform;
569579
transform.translate(ellipse->getCenter().x(), ellipse->getCenter().y());
570580
transform.rotate(ellipse->getRotation());

0 commit comments

Comments
 (0)