1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "textedittabbar.h" |
6 | #include "common/common.h" |
7 | #include <QFileInfo> |
8 | #include <QDebug> |
9 | #include <QMessageBox> |
10 | #include <QVBoxLayout> |
11 | #include <QToolButton> |
12 | |
13 | class TextEditTabBarPrivate |
14 | { |
15 | friend class TextEditTabBar; |
16 | QTabBar *tab = nullptr; |
17 | QHBoxLayout * hBoxLayout = nullptr; |
18 | QToolButton *pbtHorizontal = nullptr; |
19 | QToolButton *pbtVertical = nullptr; |
20 | QToolButton *pbtClose = nullptr; |
21 | }; |
22 | |
23 | TextEditTabBar::TextEditTabBar(QWidget *parent) |
24 | : QWidget (parent) |
25 | , d(new TextEditTabBarPrivate) |
26 | { |
27 | d->tab = new QTabBar(this); |
28 | d->hBoxLayout = new QHBoxLayout(); |
29 | d->pbtHorizontal = new QToolButton(); |
30 | d->pbtVertical = new QToolButton(); |
31 | d->pbtClose = new QToolButton(this); |
32 | d->hBoxLayout->setSpacing(5); |
33 | d->hBoxLayout->setMargin(0); |
34 | |
35 | d->pbtHorizontal->setIcon(QIcon(":/core/images/splitbutton_horizontal.png" )); |
36 | d->pbtVertical->setIcon(QIcon(":/core/images/splitbutton_vertical.png" )); |
37 | d->pbtClose->setIcon(QIcon(":/core/images/close_button_selected.png" )); |
38 | d->hBoxLayout->addWidget(d->tab); |
39 | d->hBoxLayout->addStretch(10); |
40 | d->hBoxLayout->addWidget(d->pbtHorizontal); |
41 | d->hBoxLayout->addWidget(d->pbtVertical); |
42 | d->hBoxLayout->addWidget(d->pbtClose); |
43 | d->tab->setTabsClosable(true); |
44 | |
45 | this->setLayout(d->hBoxLayout); |
46 | |
47 | QObject::connect(d->tab, &QTabBar::currentChanged, |
48 | this, [=](int index){ |
49 | QString filePath = indexFile(index); |
50 | emit this->fileSwitched(filePath); |
51 | editor.switchedFile(filePath); |
52 | }); |
53 | |
54 | QObject::connect(d->tab, &QTabBar::tabCloseRequested, |
55 | this, [=](int index) { |
56 | this->removeTab(this->indexFile(index)); |
57 | }); |
58 | |
59 | QObject::connect(d->pbtHorizontal, &QToolButton::clicked, |
60 | this, [=]() { |
61 | emit splitClicked(Qt::Horizontal); |
62 | }); |
63 | |
64 | QObject::connect(d->pbtVertical, &QToolButton::clicked, |
65 | this, [=]() { |
66 | emit splitClicked(Qt::Vertical); |
67 | }); |
68 | |
69 | QObject::connect(d->pbtClose, &QToolButton::clicked, |
70 | this, [=]() { |
71 | emit closeClicked(); |
72 | }); |
73 | } |
74 | |
75 | TextEditTabBar::~TextEditTabBar() |
76 | { |
77 | if (d) { |
78 | if (d->tab) |
79 | delete d->tab; |
80 | if (d->pbtClose) |
81 | delete d->pbtClose; |
82 | if (d->pbtHorizontal) |
83 | delete d->pbtHorizontal; |
84 | if (d->pbtVertical) |
85 | delete d->pbtVertical; |
86 | if (d->hBoxLayout) |
87 | delete d->hBoxLayout; |
88 | delete d; |
89 | } |
90 | } |
91 | |
92 | void TextEditTabBar::setFile(const QString &file) |
93 | { |
94 | if (!QFile::exists(file)) { |
95 | return; |
96 | } |
97 | |
98 | int index = fileIndex(file); |
99 | if (index != -1) { |
100 | d->tab->setCurrentIndex(index); |
101 | return; |
102 | } |
103 | |
104 | // should emit index changed, to use addTab method with tab is empty |
105 | QFileInfo info(file); |
106 | int addIndex = d->tab->addTab(info.fileName()); |
107 | d->tab->setTabToolTip(addIndex, file); |
108 | |
109 | editor.openedFile(file); // plugin interface |
110 | } |
111 | |
112 | void TextEditTabBar::switchFile(const QString &file) |
113 | { |
114 | int index = fileIndex(file); |
115 | if (index != -1) { |
116 | d->tab->setCurrentIndex(index); |
117 | } |
118 | } |
119 | |
120 | int TextEditTabBar::fileIndex(const QString &file) const |
121 | { |
122 | int index = -1; |
123 | for (int i = 0; i < d->tab->count(); i++) { |
124 | if (d->tab->tabToolTip(i) == file) |
125 | index = i; |
126 | } |
127 | return index; |
128 | } |
129 | |
130 | QString TextEditTabBar::indexFile(int index) const |
131 | { |
132 | return d->tab->tabToolTip(index); |
133 | } |
134 | |
135 | void TextEditTabBar::doFileChanged(const QString &file) |
136 | { |
137 | int index = fileIndex(file); |
138 | if (index == -1) |
139 | return; |
140 | |
141 | QString changedFileName = "*" + QFileInfo(file).fileName(); |
142 | if (d->tab->tabText(index) == changedFileName) { |
143 | return; |
144 | } |
145 | |
146 | d->tab->setTabText(index , "*" + d->tab->tabText(index)); |
147 | qInfo() << d->tab->tabText(index); |
148 | } |
149 | |
150 | void TextEditTabBar::doFileSaved(const QString &file) |
151 | { |
152 | int index = fileIndex(file); |
153 | if (index == -1) |
154 | return; |
155 | |
156 | QString text = d->tab->tabText(index); |
157 | if (QFileInfo(file).fileName() == text){ |
158 | return; |
159 | } |
160 | |
161 | text = text.remove(0, 1); |
162 | d->tab->setTabText(index, text); |
163 | } |
164 | |
165 | void TextEditTabBar::removeTab(const QString &file) |
166 | { |
167 | int index = fileIndex(file); |
168 | if (index != -1){ |
169 | QString text = d->tab->tabText(index); |
170 | QFileInfo info(file); |
171 | if (info.exists() && text.length() > 0 && text.at(0) == "*" ) { |
172 | int ret = QMessageBox::question(this, QMessageBox::tr("Save Changes" ), |
173 | QMessageBox::tr("The file has unsaved changes, will save?" ), |
174 | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, |
175 | QMessageBox::Cancel); |
176 | if (QMessageBox::Yes != ret && QMessageBox::No != ret) { |
177 | return; |
178 | } else if (QMessageBox::Yes == ret) { |
179 | emit saveFile(file); |
180 | } |
181 | } |
182 | emit fileClosed(file); |
183 | editor.closedFile(file); |
184 | d->tab->removeTab(index); |
185 | } |
186 | } |
187 | |
188 | int TextEditTabBar::count() const |
189 | { |
190 | return d->tab->count(); |
191 | } |
192 | |
193 | int TextEditTabBar::currentIndex() const |
194 | { |
195 | return d->tab->currentIndex(); |
196 | } |
197 | |
198 | QString TextEditTabBar::currentFile() const |
199 | { |
200 | return indexFile(currentIndex()); |
201 | } |
202 | |
203 | void TextEditTabBar::setCurrentIndex(int idx) |
204 | { |
205 | return d->tab->setCurrentIndex(idx); |
206 | } |
207 | |
208 | void TextEditTabBar::setCloseButtonVisible(bool flag) |
209 | { |
210 | d->pbtClose->setVisible(flag); |
211 | } |
212 | |
213 | void TextEditTabBar::setSplitButtonVisible(bool flag) |
214 | { |
215 | d->pbtHorizontal->setVisible(flag); |
216 | d->pbtVertical->setVisible(flag); |
217 | } |
218 | |
219 | void TextEditTabBar::tabCloseRequested(int idx) |
220 | { |
221 | return d->tab->tabCloseRequested(idx); |
222 | } |
223 | |