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
13class 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
23TextEditTabBar::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
75TextEditTabBar::~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
92void 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
112void TextEditTabBar::switchFile(const QString &file)
113{
114 int index = fileIndex(file);
115 if (index != -1) {
116 d->tab->setCurrentIndex(index);
117 }
118}
119
120int 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
130QString TextEditTabBar::indexFile(int index) const
131{
132 return d->tab->tabToolTip(index);
133}
134
135void 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
150void 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
165void 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
188int TextEditTabBar::count() const
189{
190 return d->tab->count();
191}
192
193int TextEditTabBar::currentIndex() const
194{
195 return d->tab->currentIndex();
196}
197
198QString TextEditTabBar::currentFile() const
199{
200 return indexFile(currentIndex());
201}
202
203void TextEditTabBar::setCurrentIndex(int idx)
204{
205 return d->tab->setCurrentIndex(idx);
206}
207
208void TextEditTabBar::setCloseButtonVisible(bool flag)
209{
210 d->pbtClose->setVisible(flag);
211}
212
213void TextEditTabBar::setSplitButtonVisible(bool flag)
214{
215 d->pbtHorizontal->setVisible(flag);
216 d->pbtVertical->setVisible(flag);
217}
218
219void TextEditTabBar::tabCloseRequested(int idx)
220{
221 return d->tab->tabCloseRequested(idx);
222}
223