1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "texteditsplitter.h" |
6 | #include "transceiver/codeeditorreceiver.h" |
7 | |
8 | #include <QBoxLayout> |
9 | #include <QDebug> |
10 | |
11 | namespace Private { |
12 | static TextEditSplitter *splitter = nullptr; |
13 | } |
14 | |
15 | TextEditSplitter::TextEditSplitter(QWidget *parent) |
16 | : QWidget (parent) |
17 | , vLayout(new QVBoxLayout) |
18 | , mainSplitter(new QSplitter) |
19 | { |
20 | tabWidget = new TextEditTabWidget(mainSplitter); |
21 | mainSplitter->addWidget(tabWidget); |
22 | mainSplitter->setHandleWidth(0); |
23 | tabWidgets.insert(tabWidget, true); |
24 | splitters.insert(mainSplitter, {tabWidget, nullptr}); |
25 | tabWidget->setCloseButtonVisible(false); |
26 | tabWidget->setSplitButtonVisible(false); |
27 | |
28 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toOpenFileWithKey, |
29 | tabWidget, &TextEditTabWidget::openFileWithKey); |
30 | QObject::connect(tabWidget, &TextEditTabWidget::splitClicked, |
31 | this, &TextEditSplitter::doSplit); |
32 | QObject::connect(tabWidget, &TextEditTabWidget::closed, |
33 | this, &TextEditSplitter::doClose); |
34 | QObject::connect(tabWidget, &TextEditTabWidget::selected, |
35 | this, &TextEditSplitter::doSelected); |
36 | QObject::connect(tabWidget, &TextEditTabWidget::closeWidget, |
37 | this, &TextEditSplitter::doClose); |
38 | QObject::connect(tabWidget, &TextEditTabWidget::sigOpenFile, |
39 | this, &TextEditSplitter::doShowSplit); |
40 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toAddDebugPoint, |
41 | tabWidget, &TextEditTabWidget::addDebugPoint); |
42 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toRemoveDebugPoint, |
43 | tabWidget, &TextEditTabWidget::removeDebugPoint); |
44 | |
45 | QHBoxLayout *hLayout = new QHBoxLayout; |
46 | hLayout->addStretch(20); |
47 | |
48 | vLayout->addLayout(hLayout); |
49 | vLayout->addWidget(mainSplitter); |
50 | vLayout->setContentsMargins(0, 0, 0, 0); |
51 | this->setLayout(vLayout); |
52 | |
53 | } |
54 | |
55 | TextEditSplitter::~TextEditSplitter() |
56 | { |
57 | |
58 | } |
59 | |
60 | void TextEditSplitter::updateClose(QSplitter *splitter, TextEditTabWidget *textEditTabWidget) |
61 | { |
62 | QSplitter *parentSplitter; |
63 | if (splitter != mainSplitter) { |
64 | parentSplitter = qobject_cast<QSplitter *>(splitter->parent()); |
65 | } else { |
66 | parentSplitter = mainSplitter; |
67 | } |
68 | |
69 | if (splitters[splitter].first && splitters[splitter].second) { |
70 | if (splitter == mainSplitter) { |
71 | int index = splitter->indexOf(textEditTabWidget); |
72 | if (index) { |
73 | splitters[splitter].second = nullptr; |
74 | } else { |
75 | splitters[splitter].first = nullptr; |
76 | } |
77 | tabWidgets.remove(textEditTabWidget); |
78 | delete textEditTabWidget; |
79 | } else { |
80 | int parentIndex = parentSplitter->indexOf(splitter); |
81 | TextEditTabWidget *textEdit; |
82 | if (splitters[splitter].first == textEditTabWidget) { |
83 | textEdit = splitters[splitter].second; |
84 | } else { |
85 | textEdit = splitters[splitter].first; |
86 | } |
87 | if (parentIndex) { |
88 | splitters[parentSplitter].second = textEdit; |
89 | } else { |
90 | splitters[parentSplitter].first = textEdit; |
91 | } |
92 | textEdit->setParent(parentSplitter); |
93 | parentSplitter->insertWidget(parentIndex, textEdit); |
94 | tabWidgets.remove(textEditTabWidget); |
95 | delete textEditTabWidget; |
96 | splitters.remove(splitter); |
97 | delete splitter; |
98 | } |
99 | } else { |
100 | tabWidgets.remove(textEditTabWidget); |
101 | delete textEditTabWidget; |
102 | for (auto it = splitters.begin(); it != splitters.end(); ++it) { |
103 | if (!it->first && !it->second) { |
104 | splitter->setOrientation(it.key()->orientation()); |
105 | it->first->setParent(splitter); |
106 | it->second->setParent(splitter); |
107 | splitter->insertWidget(0, it->first); |
108 | splitter->insertWidget(1, it->second); |
109 | splitters[splitter] = {it->first, it->second}; |
110 | splitters.remove(it.key()); |
111 | delete it.key(); |
112 | break; |
113 | } |
114 | } |
115 | } |
116 | |
117 | for (auto it = tabWidgets.begin(); it != tabWidgets.end(); ++it) { |
118 | it.key()->setSplitButtonVisible(true); |
119 | } |
120 | if (tabWidgets.size() == 1) { |
121 | auto it = tabWidgets.begin(); |
122 | it.key()->setCloseButtonVisible(false); |
123 | } |
124 | } |
125 | |
126 | void TextEditSplitter::doSplit(Qt::Orientation orientation, const newlsp::ProjectKey &key, const QString &file) |
127 | { |
128 | auto oldEditWidget = qobject_cast<TextEditTabWidget*>(sender()); |
129 | if (!oldEditWidget) |
130 | return; |
131 | auto splitter = qobject_cast<QSplitter *>(oldEditWidget->parent()); |
132 | QSplitter *newSplitter; |
133 | if (tabWidgets.size() == 1) { |
134 | newSplitter = mainSplitter; |
135 | } else { |
136 | newSplitter = new QSplitter(splitter); |
137 | } |
138 | newSplitter->setOrientation(orientation); |
139 | newSplitter->setHandleWidth(0); |
140 | newSplitter->setOpaqueResize(true); |
141 | newSplitter->setChildrenCollapsible(false); |
142 | int index = splitter->indexOf(oldEditWidget); |
143 | oldEditWidget->setParent(newSplitter); |
144 | oldEditWidget->setCloseButtonVisible(true); |
145 | |
146 | TextEditTabWidget *newEditWidget = new TextEditTabWidget(newSplitter); |
147 | if (oldEditWidget == splitters[splitter].first) { |
148 | splitters[splitter].first = nullptr; |
149 | } else { |
150 | splitters[splitter].second = nullptr; |
151 | } |
152 | splitters[newSplitter] = {oldEditWidget, newEditWidget}; |
153 | tabWidgets.insert(newEditWidget, true); |
154 | tabWidgets[oldEditWidget] = false; |
155 | if (tabWidgets.size() >= 4) { |
156 | for (auto it = tabWidgets.begin(); it != tabWidgets.end(); ++it) { |
157 | it.key()->setSplitButtonVisible(false); |
158 | } |
159 | } |
160 | if (key.isValid()) { |
161 | newEditWidget->openFileWithKey(key, file); |
162 | } |
163 | if (tabWidgets.size() == 2) { |
164 | splitter->addWidget(newEditWidget); |
165 | } else { |
166 | splitter->insertWidget(index, newSplitter); |
167 | } |
168 | |
169 | // cancel all open file sig-slot from texteditwidget |
170 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toOpenFileWithKey, |
171 | oldEditWidget, &TextEditTabWidget::openFileWithKey); |
172 | |
173 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toJumpFileLineWithKey, |
174 | oldEditWidget, &TextEditTabWidget::jumpToLineWithKey); |
175 | |
176 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toRunFileLineWithKey, |
177 | oldEditWidget, &TextEditTabWidget::runningToLineWithKey); |
178 | |
179 | // connect new texteditwidget openfile slot |
180 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toOpenFileWithKey, |
181 | newEditWidget, &TextEditTabWidget::openFileWithKey); |
182 | |
183 | // connect selected texteditwidget sig-slot bind, from texteditwidget focus |
184 | QObject::connect(newEditWidget, &TextEditTabWidget::splitClicked, |
185 | this, &TextEditSplitter::doSplit); |
186 | |
187 | QObject::connect(newEditWidget, &TextEditTabWidget::selected, |
188 | this, &TextEditSplitter::doSelected); |
189 | |
190 | QObject::connect(newEditWidget, &TextEditTabWidget::closed, |
191 | this, &TextEditSplitter::doClose); |
192 | QObject::connect(newEditWidget, &TextEditTabWidget::closeWidget, |
193 | this, &TextEditSplitter::doClose); |
194 | QObject::connect(newEditWidget, &TextEditTabWidget::sigOpenFile, |
195 | this, &TextEditSplitter::doShowSplit); |
196 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toAddDebugPoint, |
197 | newEditWidget, &TextEditTabWidget::addDebugPoint); |
198 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toRemoveDebugPoint, |
199 | newEditWidget, &TextEditTabWidget::removeDebugPoint); |
200 | } |
201 | |
202 | void TextEditSplitter::doSelected(bool state) |
203 | { |
204 | auto textEditTabWidget = qobject_cast<TextEditTabWidget*>(sender()); |
205 | if (!textEditTabWidget) |
206 | return; |
207 | |
208 | auto findIsConnEdit = [=]() -> TextEditTabWidget* |
209 | { |
210 | for(auto it = tabWidgets.begin(); it != tabWidgets.end(); ++it) { |
211 | if (it.value() == true) |
212 | return it.key(); |
213 | } |
214 | return nullptr; |
215 | }; |
216 | |
217 | if (tabWidgets.values().contains(true)) { |
218 | if (state) { |
219 | while (tabWidgets.values().contains(true)) { |
220 | auto edit = findIsConnEdit(); |
221 | if (edit) { |
222 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toOpenFileWithKey, |
223 | edit, &TextEditTabWidget::openFileWithKey); |
224 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toJumpFileLineWithKey, |
225 | edit, &TextEditTabWidget::jumpToLineWithKey); |
226 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toRunFileLineWithKey, |
227 | edit, &TextEditTabWidget::runningToLineWithKey); |
228 | QObject::disconnect(EditorCallProxy::instance(), &EditorCallProxy::toSetModifiedAutoReload, |
229 | edit, &TextEditTabWidget::setModifiedAutoReload); |
230 | tabWidgets[edit] = false; |
231 | } |
232 | } |
233 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toAddDebugPoint, |
234 | textEditTabWidget, &TextEditTabWidget::addDebugPoint); |
235 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toRemoveDebugPoint, |
236 | textEditTabWidget, &TextEditTabWidget::removeDebugPoint); |
237 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toOpenFileWithKey, |
238 | textEditTabWidget, &TextEditTabWidget::openFileWithKey); |
239 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toJumpFileLineWithKey, |
240 | textEditTabWidget, &TextEditTabWidget::jumpToLineWithKey); |
241 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toRunFileLineWithKey, |
242 | textEditTabWidget, &TextEditTabWidget::runningToLineWithKey); |
243 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toSetModifiedAutoReload, |
244 | textEditTabWidget, &TextEditTabWidget::setModifiedAutoReload); |
245 | tabWidgets[textEditTabWidget] = state; |
246 | } |
247 | } |
248 | } |
249 | |
250 | void TextEditSplitter::doShowSplit() |
251 | { |
252 | if (tabWidgets.size() > 1) |
253 | return; |
254 | auto textEditTabWidget = qobject_cast<TextEditTabWidget*>(sender()); |
255 | textEditTabWidget->setSplitButtonVisible(true); |
256 | } |
257 | |
258 | TextEditSplitter *TextEditSplitter::instance() |
259 | { |
260 | if (!Private::splitter) |
261 | Private::splitter = new TextEditSplitter; |
262 | return Private::splitter; |
263 | } |
264 | |
265 | void TextEditSplitter::doClose() |
266 | { |
267 | auto textEditTabWidget = qobject_cast<TextEditTabWidget*>(sender()); |
268 | if (tabWidgets.size() == 1) { |
269 | textEditTabWidget->setCloseButtonVisible(false); |
270 | textEditTabWidget->setSplitButtonVisible(false); |
271 | return; |
272 | } |
273 | auto splitter = qobject_cast<QSplitter *>(textEditTabWidget->parent()); |
274 | if (tabWidgets[textEditTabWidget]) { |
275 | auto it = tabWidgets.begin(); |
276 | if (it.key() == textEditTabWidget) |
277 | ++it; |
278 | it.value() = true; |
279 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toAddDebugPoint, |
280 | textEditTabWidget, &TextEditTabWidget::addDebugPoint); |
281 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toRemoveDebugPoint, |
282 | textEditTabWidget, &TextEditTabWidget::removeDebugPoint); |
283 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toOpenFileWithKey, |
284 | it.key(), &TextEditTabWidget::openFileWithKey); |
285 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toJumpFileLineWithKey, |
286 | it.key(), &TextEditTabWidget::jumpToLineWithKey); |
287 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toRunFileLineWithKey, |
288 | it.key(), &TextEditTabWidget::runningToLineWithKey); |
289 | QObject::connect(EditorCallProxy::instance(), &EditorCallProxy::toSetModifiedAutoReload, |
290 | it.key(), &TextEditTabWidget::setModifiedAutoReload); |
291 | } |
292 | |
293 | updateClose(splitter, textEditTabWidget); |
294 | } |
295 | |
296 | |