31 QWidget{parent}, |
31 QWidget{parent}, |
32 colorTable{colorTable}, |
32 colorTable{colorTable}, |
33 canvas{new Canvas{model, this, documents, colorTable, this}}, |
33 canvas{new Canvas{model, this, documents, colorTable, this}}, |
34 model{model}, |
34 model{model}, |
35 documents{documents}, |
35 documents{documents}, |
36 vertexMap{model}, |
36 vertexMap{model} |
37 ui{*new Ui_Document}, |
37 { |
38 toolsBar{new QToolBar{this}} |
|
39 { |
|
40 this->ui.setupUi(this); |
|
41 const int listWidth = static_cast<int>(this->width() / 3); |
|
42 this->ui.viewportListSplitter->setSizes({listWidth * 2, listWidth}); |
|
43 this->ui.toolsBarContainer->setLayout(new QVBoxLayout{this->ui.toolsBarContainer}); |
|
44 this->ui.toolsBarContainer->layout()->addWidget(this->toolsBar); |
|
45 this->ui.listView->setModel(model); |
|
46 this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); |
|
47 this->ui.viewportFrame->layout()->addWidget(this->canvas); |
|
48 this->toolsBar->setOrientation(Qt::Vertical); |
|
49 this->setMouseTracking(true); |
38 this->setMouseTracking(true); |
50 connect(this->ui.viewportListSplitter, &QSplitter::splitterMoved, this, &EditorTabWidget::splitterChanged); |
|
51 connect(this->canvas, &Canvas::mouseClick, this, &EditorTabWidget::canvasMouseClick); |
39 connect(this->canvas, &Canvas::mouseClick, this, &EditorTabWidget::canvasMouseClick); |
52 connect(this->canvas, &Canvas::mouseMove, this, &EditorTabWidget::canvasMouseMove); |
40 connect(this->canvas, &Canvas::mouseMove, this, &EditorTabWidget::canvasMouseMove); |
53 connect(this->canvas, &Canvas::newStatusText, this, &EditorTabWidget::newStatusText); |
41 connect(this->canvas, &Canvas::newStatusText, this, &EditorTabWidget::newStatusText); |
54 connect(this->ui.listView->selectionModel(), &QItemSelectionModel::selectionChanged, |
|
55 [&](const QItemSelection& selected, const QItemSelection& deselected) |
|
56 { |
|
57 auto resolveIndex = [this](const QModelIndex& index){ return this->model->idAt(index.row()); }; |
|
58 auto resolve = [resolveIndex](const QItemSelection& selection) |
|
59 { |
|
60 return fn::map<QSet<ModelId>>(selection.indexes(), resolveIndex); |
|
61 }; |
|
62 this->canvas->handleSelectionChange(resolve(selected), resolve(deselected)); |
|
63 }); |
|
64 connect(this->model, &Model::dataChanged, this->canvas, qOverload<>(&Canvas::update)); |
42 connect(this->model, &Model::dataChanged, this->canvas, qOverload<>(&Canvas::update)); |
65 connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() |
43 connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() |
66 { |
44 { |
67 this->canvas->rebuildVertices(this); |
45 this->canvas->rebuildVertices(this); |
68 }); |
46 }); |
69 this->canvas->drawState = &this->drawState; |
47 this->canvas->drawState = &this->drawState; |
70 this->initializeTools(); |
48 QVBoxLayout* layout = new QVBoxLayout{this}; |
|
49 layout->addWidget(this->canvas); |
71 } |
50 } |
72 |
51 |
73 EditorTabWidget::~EditorTabWidget() |
52 EditorTabWidget::~EditorTabWidget() |
74 { |
53 { |
75 delete &this->ui; |
|
76 } |
|
77 |
|
78 QByteArray EditorTabWidget::saveSplitterState() const |
|
79 { |
|
80 return this->ui.viewportListSplitter->saveState(); |
|
81 } |
|
82 |
|
83 void EditorTabWidget::restoreSplitterState(const QByteArray& state) |
|
84 { |
|
85 this->ui.viewportListSplitter->restoreState(state); |
|
86 } |
54 } |
87 |
55 |
88 void EditorTabWidget::applyToVertices(VertexMap::ApplyFunction fn) const |
56 void EditorTabWidget::applyToVertices(VertexMap::ApplyFunction fn) const |
89 { |
57 { |
90 this->vertexMap.apply(fn); |
58 this->vertexMap.apply(fn); |
91 } |
59 } |
92 |
60 |
93 const char INDEX_PROPERTY[] = "_editing_mode_index"; |
61 void EditorTabWidget::setEditMode(EditingMode mode) |
94 |
62 { |
95 void EditorTabWidget::initializeTools() |
63 this->drawState.mode = mode; |
96 { |
|
97 const struct |
|
98 { |
|
99 QString name, tooltip; |
|
100 QPixmap icon; |
|
101 QWidget* widget; |
|
102 } editingModesInfo[] = { |
|
103 { |
|
104 .name = tr("Select"), |
|
105 .tooltip = tr("Select elements from the model."), |
|
106 .icon = {":/icons/navigate-outline.png"}, |
|
107 //.widget = this->objectEditor, |
|
108 }, |
|
109 { |
|
110 .name = tr("Draw"), |
|
111 .tooltip = tr("Draw new elements into the model."), |
|
112 .icon = {":/icons/pencil-outline.png"}, |
|
113 .widget = nullptr, |
|
114 }, |
|
115 }; |
|
116 for (int i = 0; i < countof(editingModesInfo); ++i) { |
|
117 const auto& editingModeInfo = editingModesInfo[i]; |
|
118 QAction* action = new QAction{editingModeInfo.name, this}; |
|
119 action->setCheckable(true); |
|
120 action->setChecked(i == 0); |
|
121 action->setToolTip(editingModeInfo.tooltip); |
|
122 action->setIcon(QPixmap{editingModeInfo.icon}); |
|
123 action->setProperty(INDEX_PROPERTY, i); |
|
124 this->toolsBar->addAction(action); |
|
125 QWidget* widget = editingModeInfo.widget; |
|
126 if (widget == nullptr) { |
|
127 widget = new QWidget{this}; |
|
128 } |
|
129 this->ui.toolWidgetStack->addWidget(widget); |
|
130 this->toolActions.push_back(action); |
|
131 connect(action, &QAction::triggered, this, &EditorTabWidget::editingModeTriggered); |
|
132 } |
|
133 this->ui.listView->selectAll(); |
|
134 } |
|
135 |
|
136 void EditorTabWidget::editingModeTriggered() |
|
137 { |
|
138 QAction* triggeredAction = qobject_cast<QAction*>(this->sender()); |
|
139 if (triggeredAction != nullptr) |
|
140 { |
|
141 const int index = triggeredAction->property(INDEX_PROPERTY).toInt(); |
|
142 this->drawState.mode = static_cast<EditingMode>(index); |
|
143 this->ui.toolWidgetStack->setCurrentIndex(index); |
|
144 for (QAction* action : this->toolActions) { |
|
145 action->setChecked(action == triggeredAction); |
|
146 } |
|
147 } |
|
148 } |
64 } |
149 |
65 |
150 void updatePreviewPolygon(DrawState* drawState) |
66 void updatePreviewPolygon(DrawState* drawState) |
151 { |
67 { |
152 drawState->previewPolygon = drawState->polygon; |
68 drawState->previewPolygon = drawState->polygon; |