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
33ModeConfigPage::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
85ModeConfigPage::~ModeConfigPage()
86{
87 qDeleteAll(c: m_types);
88 delete ui;
89}
90
91void 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
105void 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
122void ModeConfigPage::reset()
123{
124 reload();
125}
126
127void ModeConfigPage::defaults()
128{
129 reload();
130}
131
132void 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
165void 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
176void 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
202void 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
229void 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
290void 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
304QString ModeConfigPage::name() const
305{
306 return i18n("Modes && Filetypes");
307}
308

source code of ktexteditor/src/mode/katemodeconfigpage.cpp