15 * You should have received a copy of the GNU General Public License |
15 * You should have received a copy of the GNU General Public License |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 |
18 |
19 #include <QMouseEvent> |
19 #include <QMouseEvent> |
|
20 #include <QMessageBox> |
20 #include "document.h" |
21 #include "document.h" |
21 #include "ui_document.h" |
22 #include "ui_document.h" |
22 #include "model.h" |
23 #include "model.h" |
23 #include "modeleditcontext.h" |
24 #include "modeleditcontext.h" |
|
25 #include "tools/basetool.h" |
|
26 #include "tools/drawtool.h" |
|
27 #include "tools/selecttool.h" |
|
28 |
|
29 static const QMetaObject* const toolMetaObjects[] = { |
|
30 &SelectTool::staticMetaObject, |
|
31 &DrawTool::staticMetaObject, |
|
32 }; |
24 |
33 |
25 Document::Document( |
34 Document::Document( |
26 Model* model, |
35 Model* model, |
27 DocumentManager* documents, |
36 DocumentManager* documents, |
28 const ldraw::ColorTable& colorTable, |
37 const ldraw::ColorTable& colorTable, |
32 documents{documents}, |
41 documents{documents}, |
33 colorTable{colorTable}, |
42 colorTable{colorTable}, |
34 vertexMap{model}, |
43 vertexMap{model}, |
35 renderer{new Canvas{model, documents, colorTable, this}}, |
44 renderer{new Canvas{model, documents, colorTable, this}}, |
36 ui{*new Ui::Document}, |
45 ui{*new Ui::Document}, |
37 objectEditor{model, ldraw::NULL_ID, this} |
46 objectEditor{model, ldraw::NULL_ID, this}, |
|
47 toolsBar{new QToolBar{this}} |
38 { |
48 { |
39 this->ui.setupUi(this); |
49 this->ui.setupUi(this); |
|
50 this->ui.toolsBarContainer->setLayout(new QVBoxLayout{this->ui.toolsBarContainer}); |
|
51 this->ui.toolsBarContainer->layout()->addWidget(this->toolsBar); |
40 this->ui.listView->setModel(model); |
52 this->ui.listView->setModel(model); |
41 this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); |
53 this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); |
42 this->ui.viewportFrame->layout()->addWidget(this->renderer); |
54 this->ui.viewportFrame->layout()->addWidget(this->renderer); |
43 this->ui.objectEditorFrame->setLayout(new QVBoxLayout{this->ui.objectEditorFrame}); |
55 this->ui.objectEditorFrame->setLayout(new QVBoxLayout{this->ui.objectEditorFrame}); |
44 this->ui.objectEditorFrame->layout()->addWidget(&this->objectEditor); |
56 this->ui.objectEditorFrame->layout()->addWidget(&this->objectEditor); |
|
57 this->toolsBar->setOrientation(Qt::Vertical); |
45 this->setMouseTracking(true); |
58 this->setMouseTracking(true); |
46 connect(this->ui.splitter, &QSplitter::splitterMoved, this, &Document::splitterChanged); |
59 connect(this->ui.splitter, &QSplitter::splitterMoved, this, &Document::splitterChanged); |
47 connect(this->renderer, &Canvas::newStatusText, this, &Document::newStatusText); |
60 connect(this->renderer, &Canvas::newStatusText, this, &Document::newStatusText); |
48 connect(this->renderer, &Canvas::selectionChanged, [&](const QSet<ldraw::id_t>& newSelection) |
61 connect(this->renderer, &Canvas::selectionChanged, [&](const QSet<ldraw::id_t>& newSelection) |
49 { |
62 { |
73 this->selectionChanged(resolve(this->ui.listView->selectionModel()->selection())); |
86 this->selectionChanged(resolve(this->ui.listView->selectionModel()->selection())); |
74 }); |
87 }); |
75 connect(this->model, &Model::dataChanged, this->renderer, qOverload<>(&Canvas::update)); |
88 connect(this->model, &Model::dataChanged, this->renderer, qOverload<>(&Canvas::update)); |
76 connect(this->renderer, &Canvas::mouseClick, this, [this](Canvas* canvas, QMouseEvent* event) |
89 connect(this->renderer, &Canvas::mouseClick, this, [this](Canvas* canvas, QMouseEvent* event) |
77 { |
90 { |
78 Q_EMIT this->mouseClick(this, canvas, event); |
91 if (this->selectedTool != nullptr) |
|
92 { |
|
93 this->selectedTool->mouseClick(this, canvas, event); |
|
94 } |
79 }); |
95 }); |
80 connect(this->renderer, &Canvas::mouseMove, this, [this](Canvas* canvas, QMouseEvent* event) |
96 connect(this->renderer, &Canvas::mouseMove, this, [this](Canvas* canvas, QMouseEvent* event) |
81 { |
97 { |
82 Q_EMIT this->mouseMove(this, canvas, event); |
98 if (this->selectedTool != nullptr) |
83 }); |
99 { |
84 connect(this->renderer, &Canvas::keyReleased, this, [this](Canvas* canvas, QKeyEvent* event) |
100 this->selectedTool->mouseMove(this, canvas, event); |
85 { |
101 } |
86 Q_EMIT this->keyReleased(this, canvas, event); |
|
87 }); |
102 }); |
88 connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() |
103 connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() |
89 { |
104 { |
90 this->renderer->rebuildVertices(this); |
105 this->renderer->rebuildVertices(this); |
91 }); |
106 }); |
|
107 this->setCanvasOverpaintCallback([&](Canvas* canvas, QPainter* painter) |
|
108 { |
|
109 if (this->selectedTool != nullptr) |
|
110 { |
|
111 this->selectedTool->overpaint(canvas, painter); |
|
112 } |
|
113 }); |
|
114 this->initializeTools(); |
92 } |
115 } |
93 |
116 |
94 Document::~Document() |
117 Document::~Document() |
95 { |
118 { |
96 delete &this->ui; |
119 delete &this->ui; |
135 else |
158 else |
136 { |
159 { |
137 this->objectEditor.setObjectId(ldraw::NULL_ID); |
160 this->objectEditor.setObjectId(ldraw::NULL_ID); |
138 } |
161 } |
139 } |
162 } |
|
163 |
|
164 void Document::initializeTools() |
|
165 { |
|
166 for (const QMetaObject* const metaObject : ::toolMetaObjects) |
|
167 { |
|
168 QObject* const objectInstance = metaObject->newInstance(Q_ARG(QObject*, this)); |
|
169 BaseTool* const toolInstance = qobject_cast<BaseTool*>(objectInstance); |
|
170 if (toolInstance) |
|
171 { |
|
172 this->tools.append(toolInstance); |
|
173 QAction* action = new QAction{toolInstance->name(), this}; |
|
174 action->setCheckable(true); |
|
175 this->toolActions[toolInstance] = action; |
|
176 action->setToolTip(toolInstance->toolTip()); |
|
177 connect(action, &QAction::triggered, this, &Document::toolActionTriggered); |
|
178 this->toolsBar->addAction(action); |
|
179 } |
|
180 else |
|
181 { |
|
182 QMessageBox::critical(this, tr("Error"), tr("Unable to construct %1").arg(metaObject->className())); |
|
183 } |
|
184 } |
|
185 this->selectTool(this->tools[0]); |
|
186 } |
|
187 |
|
188 void Document::toolActionTriggered() |
|
189 { |
|
190 QAction* action = qobject_cast<QAction*>(sender()); |
|
191 if (action != nullptr) |
|
192 { |
|
193 BaseTool* tool = nullptr; |
|
194 for (auto&& pair : items(this->toolActions)) |
|
195 { |
|
196 if (pair.value == action) |
|
197 { |
|
198 tool = pair.key; |
|
199 } |
|
200 } |
|
201 this->selectTool(tool); |
|
202 } |
|
203 } |
|
204 |
|
205 void Document::selectTool(BaseTool* tool) |
|
206 { |
|
207 if (tool != nullptr && tool != this->selectedTool) |
|
208 { |
|
209 if (this->selectedTool != nullptr) |
|
210 { |
|
211 this->selectedTool->reset(); |
|
212 } |
|
213 this->selectedTool = tool; |
|
214 for (auto&& pair : items(this->toolActions)) |
|
215 { |
|
216 pair.value->setChecked(pair.key == tool); |
|
217 } |
|
218 } |
|
219 } |
|
220 |
|
221 void Document::handleKeyPress(QKeyEvent* event) |
|
222 { |
|
223 if (this->selectedTool != nullptr) |
|
224 { |
|
225 this->selectedTool->keyReleased(this, this->renderer, event); |
|
226 } |
|
227 } |