1 | /* |
2 | SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | // BEGIN Includes |
8 | #include "katemodeconfigpage.h" |
9 | |
10 | #include "kateautoindent.h" |
11 | #include "kateconfig.h" |
12 | #include "katedocument.h" |
13 | #include "kateglobal.h" |
14 | #include "katesyntaxmanager.h" |
15 | #include "kateview.h" |
16 | |
17 | #include "ui_filetypeconfigwidget.h" |
18 | |
19 | #include "katepartdebug.h" |
20 | #include <KMimeTypeChooser> |
21 | |
22 | #include <QCheckBox> |
23 | #include <QComboBox> |
24 | #include <QGroupBox> |
25 | #include <QLabel> |
26 | #include <QLayout> |
27 | #include <QPushButton> |
28 | #include <QRegularExpression> |
29 | #include <QSpinBox> |
30 | #include <QToolButton> |
31 | // END Includes |
32 | |
33 | ModeConfigPage::ModeConfigPage(QWidget *parent) |
34 | : KateConfigPage(parent) |
35 | { |
36 | m_lastType = -1; |
37 | |
38 | // This will let us have more separation between this page and |
39 | // the QTabWidget edge (ereslibre) |
40 | QVBoxLayout *layout = new QVBoxLayout(this); |
41 | QWidget *newWidget = new QWidget(this); |
42 | |
43 | ui = new Ui::FileTypeConfigWidget(); |
44 | ui->setupUi(newWidget); |
45 | |
46 | ui->cmbHl->addItem(i18n("<Unchanged>" ), auserData: QVariant(QString())); |
47 | const auto modeList = KateHlManager::self()->modeList(); |
48 | for (const auto &hl : modeList) { |
49 | const auto section = hl.translatedSection(); |
50 | if (!section.isEmpty()) { |
51 | ui->cmbHl->addItem(atext: section + QLatin1Char('/') + hl.translatedName(), auserData: QVariant(hl.name())); |
52 | } else { |
53 | ui->cmbHl->addItem(atext: hl.translatedName(), auserData: QVariant(hl.name())); |
54 | } |
55 | } |
56 | |
57 | QStringList indentationModes; |
58 | indentationModes << i18n("Use Default" ); |
59 | indentationModes << KateAutoIndent::listModes(); |
60 | ui->cmbIndenter->addItems(texts: indentationModes); |
61 | |
62 | connect(sender: ui->cmbFiletypes, signal: &QComboBox::activated, context: this, slot: &ModeConfigPage::typeChanged); |
63 | connect(sender: ui->btnNew, signal: &QPushButton::clicked, context: this, slot: &ModeConfigPage::newType); |
64 | connect(sender: ui->btnDelete, signal: &QPushButton::clicked, context: this, slot: &ModeConfigPage::deleteType); |
65 | ui->btnMimeTypes->setIcon(QIcon::fromTheme(QStringLiteral("tools-wizard" ))); |
66 | connect(sender: ui->btnMimeTypes, signal: &QToolButton::clicked, context: this, slot: &ModeConfigPage::showMTDlg); |
67 | |
68 | reload(); |
69 | |
70 | connect(sender: ui->edtName, signal: &QLineEdit::textChanged, context: this, slot: &ModeConfigPage::slotChanged); |
71 | connect(sender: ui->edtSection, signal: &QLineEdit::textChanged, context: this, slot: &ModeConfigPage::slotChanged); |
72 | connect(sender: ui->edtVariables, signal: &VariableLineEdit::textChanged, context: this, slot: &ModeConfigPage::slotChanged); |
73 | connect(sender: ui->edtFileExtensions, signal: &QLineEdit::textChanged, context: this, slot: &ModeConfigPage::slotChanged); |
74 | connect(sender: ui->edtMimeTypes, signal: &QLineEdit::textChanged, context: this, slot: &ModeConfigPage::slotChanged); |
75 | connect(sender: ui->sbPriority, signal: &QSpinBox::valueChanged, context: this, slot: &ModeConfigPage::slotChanged); |
76 | connect(sender: ui->cmbHl, signal: &QComboBox::activated, context: this, slot: &ModeConfigPage::slotChanged); |
77 | connect(sender: ui->cmbIndenter, signal: &QComboBox::activated, context: this, slot: &ModeConfigPage::slotChanged); |
78 | |
79 | // make the context help a bit easier to access |
80 | ui->sbPriority->setToolTip(ui->sbPriority->whatsThis()); |
81 | |
82 | layout->addWidget(newWidget); |
83 | } |
84 | |
85 | ModeConfigPage::~ModeConfigPage() |
86 | { |
87 | qDeleteAll(c: m_types); |
88 | delete ui; |
89 | } |
90 | |
91 | void ModeConfigPage::apply() |
92 | { |
93 | if (!hasChanged()) { |
94 | return; |
95 | } |
96 | |
97 | save(); |
98 | if (m_lastType != -1) { |
99 | ui->gbProperties->setTitle(i18n("Properties of %1" , ui->cmbFiletypes->itemText(m_lastType))); |
100 | } |
101 | |
102 | KTextEditor::EditorPrivate::self()->modeManager()->save(v: m_types); |
103 | } |
104 | |
105 | void ModeConfigPage::reload() |
106 | { |
107 | qDeleteAll(c: m_types); |
108 | m_types.clear(); |
109 | |
110 | // deep copy... |
111 | const QList<KateFileType *> &modeList = KTextEditor::EditorPrivate::self()->modeManager()->list(); |
112 | m_types.reserve(asize: modeList.size()); |
113 | for (KateFileType *type : modeList) { |
114 | KateFileType *t = new KateFileType(); |
115 | *t = *type; |
116 | m_types.append(t); |
117 | } |
118 | |
119 | update(); |
120 | } |
121 | |
122 | void ModeConfigPage::reset() |
123 | { |
124 | reload(); |
125 | } |
126 | |
127 | void ModeConfigPage::defaults() |
128 | { |
129 | reload(); |
130 | } |
131 | |
132 | void ModeConfigPage::update() |
133 | { |
134 | m_lastType = -1; |
135 | |
136 | ui->cmbFiletypes->clear(); |
137 | |
138 | for (KateFileType *type : std::as_const(t&: m_types)) { |
139 | if (!type->sectionTranslated().isEmpty()) { |
140 | ui->cmbFiletypes->addItem(atext: type->sectionTranslated() + QLatin1Char('/') + type->nameTranslated()); |
141 | } else { |
142 | ui->cmbFiletypes->addItem(atext: type->nameTranslated()); |
143 | } |
144 | } |
145 | |
146 | // get current filetype from active view via the host application |
147 | int currentIndex = 0; |
148 | KTextEditor::ViewPrivate *kv = |
149 | qobject_cast<KTextEditor::ViewPrivate *>(object: KTextEditor::EditorPrivate::self()->application()->activeMainWindow()->activeView()); |
150 | if (kv) { |
151 | const QString filetypeName = kv->doc()->fileType(); |
152 | for (int i = 0; i < m_types.size(); ++i) { |
153 | if (filetypeName == m_types[i]->name) { |
154 | currentIndex = i; |
155 | break; |
156 | } |
157 | } |
158 | } |
159 | ui->cmbFiletypes->setCurrentIndex(currentIndex); |
160 | typeChanged(type: currentIndex); |
161 | |
162 | ui->cmbFiletypes->setEnabled(ui->cmbFiletypes->count() > 0); |
163 | } |
164 | |
165 | void ModeConfigPage::deleteType() |
166 | { |
167 | int type = ui->cmbFiletypes->currentIndex(); |
168 | |
169 | if (type > -1 && type < m_types.count()) { |
170 | delete m_types[type]; |
171 | m_types.removeAt(i: type); |
172 | update(); |
173 | } |
174 | } |
175 | |
176 | void ModeConfigPage::newType() |
177 | { |
178 | QString newN = i18n("New Filetype" ); |
179 | |
180 | for (int i = 0; i < m_types.count(); ++i) { |
181 | KateFileType *type = m_types.at(i); |
182 | if (type->name == newN) { |
183 | ui->cmbFiletypes->setCurrentIndex(i); |
184 | typeChanged(type: i); |
185 | return; |
186 | } |
187 | } |
188 | |
189 | KateFileType *newT = new KateFileType(); |
190 | newT->priority = 0; |
191 | newT->name = newN; |
192 | newT->hlGenerated = false; |
193 | |
194 | m_types.prepend(t: newT); |
195 | |
196 | update(); |
197 | // show new filetype so that it is immediately available for editing |
198 | ui->cmbFiletypes->setCurrentIndex(0); |
199 | typeChanged(type: 0); |
200 | } |
201 | |
202 | void ModeConfigPage::save() |
203 | { |
204 | if (m_lastType != -1) { |
205 | if (!m_types[m_lastType]->hlGenerated) { |
206 | m_types[m_lastType]->name = ui->edtName->text(); |
207 | m_types[m_lastType]->section = ui->edtSection->text(); |
208 | |
209 | if (!m_types[m_lastType]->sectionTranslated().isEmpty()) { |
210 | ui->cmbFiletypes->setItemText(index: m_lastType, text: m_types[m_lastType]->sectionTranslated() + QLatin1Char('/') + m_types[m_lastType]->nameTranslated()); |
211 | } else { |
212 | ui->cmbFiletypes->setItemText(index: m_lastType, text: m_types[m_lastType]->nameTranslated()); |
213 | } |
214 | } |
215 | m_types[m_lastType]->varLine = ui->edtVariables->text(); |
216 | m_types[m_lastType]->wildcards = ui->edtFileExtensions->text().split(sep: QLatin1Char(';'), behavior: Qt::SkipEmptyParts); |
217 | m_types[m_lastType]->mimetypes = ui->edtMimeTypes->text().split(sep: QLatin1Char(';'), behavior: Qt::SkipEmptyParts); |
218 | m_types[m_lastType]->priority = ui->sbPriority->value(); |
219 | m_types[m_lastType]->hl = ui->cmbHl->itemData(index: ui->cmbHl->currentIndex()).toString(); |
220 | |
221 | if (ui->cmbIndenter->currentIndex() > 0) { |
222 | m_types[m_lastType]->indenter = KateAutoIndent::modeName(mode: ui->cmbIndenter->currentIndex() - 1); |
223 | } else { |
224 | m_types[m_lastType]->indenter = QString(); |
225 | } |
226 | } |
227 | } |
228 | |
229 | void ModeConfigPage::typeChanged(int type) |
230 | { |
231 | save(); |
232 | |
233 | ui->cmbHl->setEnabled(true); |
234 | ui->btnDelete->setEnabled(true); |
235 | ui->edtName->setEnabled(true); |
236 | ui->edtSection->setEnabled(true); |
237 | |
238 | if (type > -1 && type < m_types.count()) { |
239 | KateFileType *t = m_types.at(i: type); |
240 | |
241 | ui->gbProperties->setTitle(i18n("Properties of %1" , ui->cmbFiletypes->itemText(type))); |
242 | |
243 | ui->gbProperties->setEnabled(true); |
244 | ui->btnDelete->setEnabled(true); |
245 | |
246 | ui->edtName->setText(t->nameTranslated()); |
247 | ui->edtSection->setText(t->sectionTranslated()); |
248 | ui->edtVariables->setText(t->varLine); |
249 | ui->edtFileExtensions->setText(t->wildcards.join(sep: QLatin1Char(';'))); |
250 | ui->edtMimeTypes->setText(t->mimetypes.join(sep: QLatin1Char(';'))); |
251 | ui->sbPriority->setValue(t->priority); |
252 | |
253 | ui->cmbHl->setEnabled(!t->hlGenerated); |
254 | ui->btnDelete->setEnabled(!t->hlGenerated); |
255 | ui->edtName->setEnabled(!t->hlGenerated); |
256 | ui->edtSection->setEnabled(!t->hlGenerated); |
257 | |
258 | // activate current hl... |
259 | for (int i = 0; i < ui->cmbHl->count(); ++i) { |
260 | if (ui->cmbHl->itemData(index: i).toString() == t->hl) { |
261 | ui->cmbHl->setCurrentIndex(i); |
262 | } |
263 | } |
264 | |
265 | // activate the right indenter |
266 | int indenterIndex = 0; |
267 | if (!t->indenter.isEmpty()) { |
268 | indenterIndex = KateAutoIndent::modeNumber(name: t->indenter) + 1; |
269 | } |
270 | ui->cmbIndenter->setCurrentIndex(indenterIndex); |
271 | } else { |
272 | ui->gbProperties->setTitle(i18n("Properties" )); |
273 | |
274 | ui->gbProperties->setEnabled(false); |
275 | ui->btnDelete->setEnabled(false); |
276 | |
277 | ui->edtName->clear(); |
278 | ui->edtSection->clear(); |
279 | ui->edtVariables->clear(); |
280 | ui->edtFileExtensions->clear(); |
281 | ui->edtMimeTypes->clear(); |
282 | ui->sbPriority->setValue(0); |
283 | ui->cmbHl->setCurrentIndex(0); |
284 | ui->cmbIndenter->setCurrentIndex(0); |
285 | } |
286 | |
287 | m_lastType = type; |
288 | } |
289 | |
290 | void ModeConfigPage::showMTDlg() |
291 | { |
292 | QString text = |
293 | i18n("Select the MimeTypes you want for this file type.\nPlease note that this will automatically edit the associated file extensions as well." ); |
294 | QStringList list = ui->edtMimeTypes->text().split(sep: QRegularExpression(QStringLiteral("\\s*;\\s*" )), behavior: Qt::SkipEmptyParts); |
295 | KMimeTypeChooserDialog d(i18n("Select Mime Types" ), text, list, QStringLiteral("text" ), this); |
296 | if (d.exec() == QDialog::Accepted) { |
297 | // do some checking, warn user if mime types or patterns are removed. |
298 | // if the lists are empty, and the fields not, warn. |
299 | ui->edtFileExtensions->setText(d.chooser()->patterns().join(sep: QLatin1Char(';'))); |
300 | ui->edtMimeTypes->setText(d.chooser()->mimeTypes().join(sep: QLatin1Char(';'))); |
301 | } |
302 | } |
303 | |
304 | QString ModeConfigPage::name() const |
305 | { |
306 | return i18n("Modes && Filetypes" ); |
307 | } |
308 | |