src/document.cpp

changeset 200
ca23936b455b
parent 198
eb9d900dc79a
child 201
5d201ee4a9c3
equal deleted inserted replaced
199:6988973515d2 200:ca23936b455b
19 #include <QMouseEvent> 19 #include <QMouseEvent>
20 #include <QMessageBox> 20 #include <QMessageBox>
21 #include "document.h" 21 #include "document.h"
22 #include "ui_document.h" 22 #include "ui_document.h"
23 #include "model.h" 23 #include "model.h"
24 #include "modeleditor.h"
25 #include "ui/objecteditor.h" 24 #include "ui/objecteditor.h"
26 #include "linetypes/edge.h" 25
27 #include "linetypes/triangle.h" 26 EditorTabWidget::EditorTabWidget(
28 #include "linetypes/quadrilateral.h"
29
30 Document::Document(
31 Model* model, 27 Model* model,
32 DocumentManager* documents, 28 DocumentManager* documents,
33 const ldraw::ColorTable& colorTable, 29 const ldraw::ColorTable& colorTable,
34 QWidget* parent) : 30 QWidget* parent) :
35 QWidget{parent}, 31 QWidget{parent},
37 canvas{new Canvas{model, this, documents, colorTable, this}}, 33 canvas{new Canvas{model, this, documents, colorTable, this}},
38 model{model}, 34 model{model},
39 documents{documents}, 35 documents{documents},
40 vertexMap{model}, 36 vertexMap{model},
41 ui{*new Ui_Document}, 37 ui{*new Ui_Document},
42 toolsBar{new QToolBar{this}}, 38 toolsBar{new QToolBar{this}}
43 objectEditor{new ObjectEditor{this}}
44 { 39 {
45 this->ui.setupUi(this); 40 this->ui.setupUi(this);
46 const int listWidth = static_cast<int>(this->width() / 3); 41 const int listWidth = static_cast<int>(this->width() / 3);
47 this->ui.viewportListSplitter->setSizes({listWidth * 2, listWidth}); 42 this->ui.viewportListSplitter->setSizes({listWidth * 2, listWidth});
48 this->ui.toolsBarContainer->setLayout(new QVBoxLayout{this->ui.toolsBarContainer}); 43 this->ui.toolsBarContainer->setLayout(new QVBoxLayout{this->ui.toolsBarContainer});
50 this->ui.listView->setModel(model); 45 this->ui.listView->setModel(model);
51 this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); 46 this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView});
52 this->ui.viewportFrame->layout()->addWidget(this->canvas); 47 this->ui.viewportFrame->layout()->addWidget(this->canvas);
53 this->toolsBar->setOrientation(Qt::Vertical); 48 this->toolsBar->setOrientation(Qt::Vertical);
54 this->setMouseTracking(true); 49 this->setMouseTracking(true);
55 connect(this->ui.viewportListSplitter, &QSplitter::splitterMoved, this, &Document::splitterChanged); 50 connect(this->ui.viewportListSplitter, &QSplitter::splitterMoved, this, &EditorTabWidget::splitterChanged);
56 connect(this->canvas, &Canvas::mouseClick, this, &Document::canvasMouseClick); 51 connect(this->canvas, &Canvas::mouseClick, this, &EditorTabWidget::canvasMouseClick);
57 connect(this->canvas, &Canvas::mouseMove, this, &Document::canvasMouseMove); 52 connect(this->canvas, &Canvas::mouseMove, this, &EditorTabWidget::canvasMouseMove);
58 connect(this->canvas, &Canvas::newStatusText, this, &Document::newStatusText); 53 connect(this->canvas, &Canvas::newStatusText, this, &EditorTabWidget::newStatusText);
59 connect(this->ui.listView->selectionModel(), &QItemSelectionModel::selectionChanged, 54 connect(this->ui.listView->selectionModel(), &QItemSelectionModel::selectionChanged,
60 [&](const QItemSelection& selected, const QItemSelection& deselected) 55 [&](const QItemSelection& selected, const QItemSelection& deselected)
61 { 56 {
62 auto resolveIndex = [this](const QModelIndex& index){ return (*this->model)[index.row()]->id; }; 57 auto resolveIndex = [this](const QModelIndex& index){ return this->model->idAt(index.row()); };
63 auto resolve = [resolveIndex](const QItemSelection& selection) 58 auto resolve = [resolveIndex](const QItemSelection& selection)
64 { 59 {
65 return fn::map<QSet<ldraw::id_t>>(selection.indexes(), resolveIndex); 60 return fn::map<QSet<ModelId>>(selection.indexes(), resolveIndex);
66 }; 61 };
67 this->canvas->handleSelectionChange(resolve(selected), resolve(deselected)); 62 this->canvas->handleSelectionChange(resolve(selected), resolve(deselected));
68 }); 63 });
69 connect(this->model, &Model::dataChanged, this->canvas, qOverload<>(&Canvas::update)); 64 connect(this->model, &Model::dataChanged, this->canvas, qOverload<>(&Canvas::update));
70 connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() 65 connect(&this->vertexMap, &VertexMap::verticesChanged, [&]()
73 }); 68 });
74 this->canvas->drawState = &this->drawState; 69 this->canvas->drawState = &this->drawState;
75 this->initializeTools(); 70 this->initializeTools();
76 } 71 }
77 72
78 Document::~Document() 73 EditorTabWidget::~EditorTabWidget()
79 { 74 {
80 delete &this->ui; 75 delete &this->ui;
81 } 76 }
82 77
83 QByteArray Document::saveSplitterState() const 78 QByteArray EditorTabWidget::saveSplitterState() const
84 { 79 {
85 return this->ui.viewportListSplitter->saveState(); 80 return this->ui.viewportListSplitter->saveState();
86 } 81 }
87 82
88 void Document::restoreSplitterState(const QByteArray& state) 83 void EditorTabWidget::restoreSplitterState(const QByteArray& state)
89 { 84 {
90 this->ui.viewportListSplitter->restoreState(state); 85 this->ui.viewportListSplitter->restoreState(state);
91 } 86 }
92 87
93 std::unique_ptr<ModelEditor> Document::editModel() 88 void EditorTabWidget::applyToVertices(VertexMap::ApplyFunction fn) const
94 {
95 std::unique_ptr<ModelEditor> editorPointer = std::make_unique<ModelEditor>(*this->model);
96 connect(editorPointer.get(), &ModelEditor::objectModified, [&](int position){
97 this->model->emitDataChangedSignal(position);
98 });
99 return editorPointer;
100 }
101
102 void Document::applyToVertices(VertexMap::ApplyFunction fn) const
103 { 89 {
104 this->vertexMap.apply(fn); 90 this->vertexMap.apply(fn);
105 } 91 }
106 92
107 const char INDEX_PROPERTY[] = "_editing_mode_index"; 93 const char INDEX_PROPERTY[] = "_editing_mode_index";
108 94
109 void Document::initializeTools() 95 void EditorTabWidget::initializeTools()
110 { 96 {
111 const struct 97 const struct
112 { 98 {
113 QString name, tooltip; 99 QString name, tooltip;
114 QPixmap icon; 100 QPixmap icon;
116 } editingModesInfo[] = { 102 } editingModesInfo[] = {
117 { 103 {
118 .name = tr("Select"), 104 .name = tr("Select"),
119 .tooltip = tr("Select elements from the model."), 105 .tooltip = tr("Select elements from the model."),
120 .icon = {":/icons/navigate-outline.png"}, 106 .icon = {":/icons/navigate-outline.png"},
121 .widget = this->objectEditor, 107 //.widget = this->objectEditor,
122 }, 108 },
123 { 109 {
124 .name = tr("Draw"), 110 .name = tr("Draw"),
125 .tooltip = tr("Draw new elements into the model."), 111 .tooltip = tr("Draw new elements into the model."),
126 .icon = {":/icons/pencil-outline.png"}, 112 .icon = {":/icons/pencil-outline.png"},
140 if (widget == nullptr) { 126 if (widget == nullptr) {
141 widget = new QWidget{this}; 127 widget = new QWidget{this};
142 } 128 }
143 this->ui.toolWidgetStack->addWidget(widget); 129 this->ui.toolWidgetStack->addWidget(widget);
144 this->toolActions.push_back(action); 130 this->toolActions.push_back(action);
145 connect(action, &QAction::triggered, this, &Document::editingModeTriggered); 131 connect(action, &QAction::triggered, this, &EditorTabWidget::editingModeTriggered);
146 } 132 }
147 this->ui.listView->selectAll(); 133 this->ui.listView->selectAll();
148 } 134 }
149 135
150 void Document::editingModeTriggered() 136 void EditorTabWidget::editingModeTriggered()
151 { 137 {
152 QAction* triggeredAction = qobject_cast<QAction*>(this->sender()); 138 QAction* triggeredAction = qobject_cast<QAction*>(this->sender());
153 if (triggeredAction != nullptr) 139 if (triggeredAction != nullptr)
154 { 140 {
155 const int index = triggeredAction->property(INDEX_PROPERTY).toInt(); 141 const int index = triggeredAction->property(INDEX_PROPERTY).toInt();
184 bool isCloseToExistingPoints(const std::vector<glm::vec3>& points, const glm::vec3 &pos) 170 bool isCloseToExistingPoints(const std::vector<glm::vec3>& points, const glm::vec3 &pos)
185 { 171 {
186 return any(points, std::bind(geom::isclose, std::placeholders::_1, pos)); 172 return any(points, std::bind(geom::isclose, std::placeholders::_1, pos));
187 } 173 }
188 174
189 void Document::canvasMouseClick(QMouseEvent *event) 175 void EditorTabWidget::canvasMouseClick(QMouseEvent *event)
190 { 176 {
191 switch(this->drawState.mode) 177 switch(this->drawState.mode)
192 { 178 {
193 case SelectMode: 179 case SelectMode:
194 if (event->button() == Qt::LeftButton) 180 if (event->button() == Qt::LeftButton)
195 { 181 {
196 const ldraw::id_t highlighted = this->canvas->getHighlightedObject(); 182 const ModelId highlighted = this->canvas->getHighlightedObject();
197 QSet<ldraw::id_t> selected; 183 QSet<ModelId> selected;
198 if (highlighted != ldraw::NULL_ID) { 184 if (highlighted != ModelId{0}) {
199 selected.insert(highlighted); 185 selected.insert(highlighted);
200 } 186 }
201 this->select(selected); 187 this->select(selected);
202 event->accept(); 188 event->accept();
203 } 189 }
227 } 213 }
228 break; 214 break;
229 } 215 }
230 } 216 }
231 217
232 void Document::canvasMouseMove(QMouseEvent *event) 218 void EditorTabWidget::canvasMouseMove(QMouseEvent *event)
233 { 219 {
234 switch(this->drawState.mode) 220 switch(this->drawState.mode)
235 { 221 {
236 case SelectMode: 222 case SelectMode:
237 break; 223 break;
245 event->accept(); 231 event->accept();
246 break; 232 break;
247 } 233 }
248 } 234 }
249 235
250 void Document::select(const QSet<ldraw::id_t> &selected) 236 void EditorTabWidget::select(const QSet<ModelId> &selected)
251 { 237 {
252 QItemSelectionModel* selectionModel = this->ui.listView->selectionModel(); 238 QItemSelectionModel* selectionModel = this->ui.listView->selectionModel();
253 QItemSelection itemSelection; 239 QItemSelection itemSelection;
254 for (const ldraw::id_t id : selected) 240 for (const ModelId id : selected)
255 { 241 {
256 QModelIndex index = this->model->find(id); 242 const std::optional<int> row = this->model->find(id);
257 if (index != QModelIndex{}) 243 if (row.has_value())
258 { 244 {
259 itemSelection.select(index, index); 245 const QModelIndex qindex = this->model->index(*row);
246 itemSelection.select(qindex, qindex);
260 } 247 }
261 } 248 }
262 selectionModel->select(itemSelection, QItemSelectionModel::ClearAndSelect); 249 selectionModel->select(itemSelection, QItemSelectionModel::ClearAndSelect);
263 } 250 }
264 251
265 const Model &Document::getModel() const 252 const QSet<ModelId> EditorTabWidget::selectedObjects() const
266 {
267 return *this->model;
268 }
269
270 const QSet<ldraw::id_t> Document::selectedObjects() const
271 { 253 {
272 return this->canvas->selectedObjects(); 254 return this->canvas->selectedObjects();
273 } 255 }
274 256
275 void Document::closeShape() 257 void EditorTabWidget::closeShape()
276 { 258 {
277 if (this->drawState.polygon.size() >= 2 and this->drawState.polygon.size() <= 4) 259 if (this->drawState.polygon.size() >= 2 and this->drawState.polygon.size() <= 4)
278 { 260 {
279 std::unique_ptr<ModelEditor> modelEditor = this->editModel();
280 switch (this->drawState.polygon.size()) 261 switch (this->drawState.polygon.size())
281 { 262 {
282 case 2: 263 case 2:
283 modelEditor->append<ldraw::Edge>( 264 this->model->append(Colored<LineSegment>{
284 vectorToArray<2>(this->drawState.polygon), 265 LineSegment{
285 ldraw::EDGE_COLOR); 266 .p1 = this->drawState.polygon[0],
267 .p2 = this->drawState.polygon[1],
268 },
269 ldraw::EDGE_COLOR});
286 break; 270 break;
287 case 3: 271 case 3:
288 modelEditor->append<ldraw::Triangle>( 272 this->model->append(Colored<Triangle>{
289 vectorToArray<3>(this->drawState.polygon), 273 Triangle{
290 ldraw::MAIN_COLOR); 274 .p1 = this->drawState.polygon[0],
275 .p2 = this->drawState.polygon[1],
276 .p3 = this->drawState.polygon[2],
277 },
278 ldraw::MAIN_COLOR});
291 break; 279 break;
292 case 4: 280 case 4:
293 modelEditor->append<ldraw::Quadrilateral>( 281 this->model->append(Colored<Quadrilateral>{
294 vectorToArray<4>(this->drawState.polygon), 282 Quadrilateral{
295 ldraw::MAIN_COLOR); 283 .p1 = this->drawState.polygon[0],
284 .p2 = this->drawState.polygon[1],
285 .p3 = this->drawState.polygon[2],
286 .p4 = this->drawState.polygon[3],
287 },
288 ldraw::MAIN_COLOR});
296 break; 289 break;
297 } 290 }
298 } 291 }
299 this->drawState.polygon.clear(); 292 this->drawState.polygon.clear();
300 updatePreviewPolygon(&this->drawState); 293 updatePreviewPolygon(&this->drawState);

mercurial