Skip to content

Commit 49a45f7

Browse files
committed
WIP: Fix reordering of elements in the model tree
1 parent 393fb1b commit 49a45f7

18 files changed

Lines changed: 293 additions & 26 deletions

File tree

gui/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ add_executable(
214214
source/post/StressPlot.cpp
215215
source/post/StressPlot.hpp
216216
source/pre/Main.cpp
217+
source/pre/utils/ListUtils.hpp
217218
)
218219

219220
target_compile_definitions(virtualbow-gui PRIVATE JSON_HAS_CPP_17)

gui/source/pre/models/LayerModel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "LayerModel.hpp"
22
#include "solver/BowModel.hpp"
33

4-
LayerModel::LayerModel(Layer& layer, const std::vector<Material>& materials) {
4+
LayerModel::LayerModel(Layer& layer, const std::list<Material>& materials) {
55
NAME = addString(layer.name);
66
MATERIAL = addString(layer.material);
77

gui/source/pre/models/LayerModel.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class LayerModel: public PropertyListModel {
99
QPersistentModelIndex NAME;
1010
QPersistentModelIndex MATERIAL;
1111

12-
LayerModel(Layer& layer, const std::vector<Material>& materials);
12+
LayerModel(Layer& layer, const std::list<Material>& materials);
1313
const QStringList& materialOptions() const;
1414

1515
private:

gui/source/pre/models/MainModel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ DimensionsModel* MainModel::getDimensionsModel() {
133133

134134
MaterialModel* MainModel::getMaterialModel(int index) {
135135
if(bow.has_value() && index >= 0 && index < bow->section.materials.size()) {
136-
auto model = new MaterialModel(bow->section.materials[index]);
136+
auto model = new MaterialModel(*std::next(bow->section.materials.begin(), index));
137137
connectSubModel(model);
138138
return model;
139139
}

gui/source/pre/models/MainTreeModel.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "MainTreeModel.hpp"
2+
#include "pre/utils/ListUtils.hpp"
23
#include <QModelIndex>
34
#include <QIcon>
45
#include <algorithm>
@@ -49,7 +50,7 @@ void MainTreeModel::insertMaterial(int row) {
4950
QModelIndex parent = createIndex(TopLevelItem::MATERIALS, 0, ItemType::TOPLEVEL);
5051
beginInsertRows(parent, row, row);
5152

52-
auto position = bow->section.materials.begin() + row;
53+
auto position = std::next(bow->section.materials.begin(), row);
5354
bow->section.materials.insert(position, material);
5455

5556
endInsertRows();
@@ -80,7 +81,7 @@ void MainTreeModel::insertLayer(int row) {
8081

8182
Layer layer {
8283
.name = bow->generateLayerName(),
83-
.material = bow->section.materials.empty() ? "" : bow->section.materials[0].name,
84+
.material = bow->section.materials.empty() ? "" : bow->section.materials.front().name,
8485
.height = {{0.0, 0.01}, {1.0, 0.01}}
8586
};
8687

@@ -171,7 +172,7 @@ void MainTreeModel::removeMaterial(int row) {
171172

172173
// Remove material
173174
// Layers that refer to the material will become invalid
174-
auto position = bow->section.materials.begin() + row;
175+
auto position = std::next(bow->section.materials.begin(), row);
175176
bow->section.materials.erase(position);
176177

177178
endRemoveRows();
@@ -310,13 +311,29 @@ void MainTreeModel::swapMaterials(int i, int j) {
310311
throw std::invalid_argument("Invalid material indices for swapping");
311312
}
312313

314+
// Indices must be in ascending order
315+
if(i > j) {
316+
std::swap(i, j);
317+
}
318+
313319
QModelIndex parent = createIndex(TopLevelItem::MATERIALS, 0, ItemType::TOPLEVEL);
314320
beginMoveRows(parent, i, i, parent, j);
315321
beginMoveRows(parent, j, j, parent, i);
316322

317323
// Swap the two materials
318324
// Layers that refer to the materials stay valid since they refer to them by name
319-
std::swap(bow->section.materials[i], bow->section.materials[j]);
325+
swapListNodes(bow->section.materials, i, j);
326+
327+
/*
328+
auto it1 = std::next(bow->section.materials.begin(), i);
329+
auto it2 = std::next(bow->section.materials.begin(), j);
330+
//std::swap(*it1, *it2);
331+
332+
333+
auto after2 = std::next(it2);
334+
bow->section.materials.splice(it1, bow->section.materials, it2); // Move it2 before it1
335+
bow->section.materials.splice(after2, bow->section.materials, it1); // Move it1 (now after it2) to afterIt2
336+
*/
320337

321338
endMoveRows();
322339
}
@@ -452,7 +469,7 @@ QVariant MainTreeModel::data(const QModelIndex &index, int role) const {
452469
}
453470

454471
if(index.parent().row() == TopLevelItem::MATERIALS) {
455-
auto& material = bow->section.materials[index.row()];
472+
auto& material = *std::next(bow->section.materials.begin(), index.row());
456473
switch(role) {
457474
case Qt::DisplayRole: case Qt::EditRole: return QString::fromStdString(material.name);
458475
case Qt::ToolTipRole: return "User-defined material \"" + QString::fromStdString(material.name) + "\"";
@@ -496,10 +513,11 @@ bool MainTreeModel::setData(const QModelIndex &index, const QVariant &value, int
496513
}
497514

498515
// Rename material
499-
std::string oldName = bow->section.materials[index.row()].name;
500-
bow->section.materials[index.row()].name = newName;
516+
Material& material = *std::next(bow->section.materials.begin(), index.row());
517+
std::string oldName = material.name;
518+
material.name = newName;
501519

502-
// Change name in layers that use the material
520+
// Change the name also in layers that use the material
503521
for(auto& layer: bow->section.layers) {
504522
if(layer.material == oldName) {
505523
layer.material = newName;

gui/source/pre/utils/ListUtils.hpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
#include <list>
3+
#include <stdexcept>
4+
5+
// Swaps two elementy (given by their indices) of a std::list by reordering the underlying nodes,
6+
// so that references to the values stay valid.
7+
template<typename T>
8+
void swapListNodes(std::list<T>& list, size_t i, size_t j) {
9+
if(i >= list.size() || j >= list.size()) {
10+
throw std::invalid_argument("Invalid indices for swapping");
11+
}
12+
13+
// Nothing to do if source = target
14+
if(i == j) {
15+
return;
16+
}
17+
18+
// Indices must be in ascending order
19+
if(i > j) {
20+
std::swap(i, j);
21+
}
22+
23+
// Iterators of the nodes to be swapped + one after the second node
24+
auto it1 = std::next(list.begin(), i);
25+
auto it2 = std::next(list.begin(), j);
26+
auto after2 = std::next(it2);
27+
28+
// Move it2 before it1
29+
list.splice(it1, list, it2);
30+
31+
// Move it1 (now after it2) to after2
32+
list.splice(after2, list, it1);
33+
}

gui/source/pre/views/limb3d/LayerColors.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <QPainter>
66
#include <QPixmap>
77

8-
QColor getLayerColor(const Layer& layer, const std::vector<Material>& materials) {
8+
QColor getLayerColor(const Layer& layer, const std::list<Material>& materials) {
99
for(auto& material: materials) {
1010
if(material.name == layer.material) {
1111
return QColor(QString::fromStdString(material.color));
@@ -15,7 +15,7 @@ QColor getLayerColor(const Layer& layer, const std::vector<Material>& materials)
1515
return QColor();
1616
}
1717

18-
QPixmap getLayerPixmap(const Layer& layer, const std::vector<Material>& materials, int size) {
18+
QPixmap getLayerPixmap(const Layer& layer, const std::list<Material>& materials, int size) {
1919
QColor color = getLayerColor(layer, materials);
2020
return getColorPixmap(color, size);
2121
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#pragma once
22
#include <QColor>
33
#include <QPixmap>
4+
#include <list>
45

56
class Layer;
67
class Material;
78
class LayerProperties;
89

9-
QColor getLayerColor(const Layer& layer, const std::vector<Material>& materials);
10-
QPixmap getLayerPixmap(const Layer& layer, const std::vector<Material>& materials, int size);
10+
QColor getLayerColor(const Layer& layer, const std::list<Material>& materials);
11+
QPixmap getLayerPixmap(const Layer& layer, const std::list<Material>& materials, int size);
1112
QPixmap getColorPixmap(const QColor& color, int size);

gui/source/pre/views/limb3d/MaterialLegend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ MaterialLegend::MaterialLegend()
3333
this->setLayout(vbox);
3434
}
3535

36-
void MaterialLegend::setData(const std::vector<Material>& materials) {
36+
void MaterialLegend::setData(const std::list<Material>& materials) {
3737
while(vbox->count() < materials.size()) {
3838
vbox->addWidget(new MaterialEntry());
3939
}
@@ -46,7 +46,7 @@ void MaterialLegend::setData(const std::vector<Material>& materials) {
4646

4747
for(int i = 0; i < vbox->count(); ++i) {
4848
MaterialEntry* entry = dynamic_cast<MaterialEntry*>(vbox->itemAt(i)->widget());
49-
entry->setData(materials[i]);
49+
entry->setData(*std::next(materials.begin(), i)); // TODO: More efficient iteration?
5050
}
5151

5252
vbox->update();

gui/source/pre/views/limb3d/MaterialLegend.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class MaterialLegend: public QWidget
2020
{
2121
public:
2222
MaterialLegend();
23-
void setData(const std::vector<Material>& materials);
23+
void setData(const std::list<Material>& materials);
2424

2525
private:
2626
QVBoxLayout* vbox;

0 commit comments

Comments
 (0)