File indexing completed on 2024-04-21 03:57:30

0001 /*
0002     SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 // BEGIN Includes
0008 #include "katemodeconfigpage.h"
0009 
0010 #include "kateautoindent.h"
0011 #include "kateconfig.h"
0012 #include "katedocument.h"
0013 #include "kateglobal.h"
0014 #include "katesyntaxmanager.h"
0015 #include "kateview.h"
0016 
0017 #include "ui_filetypeconfigwidget.h"
0018 
0019 #include "katepartdebug.h"
0020 #include <KMimeTypeChooser>
0021 
0022 #include <QCheckBox>
0023 #include <QComboBox>
0024 #include <QGroupBox>
0025 #include <QLabel>
0026 #include <QLayout>
0027 #include <QPushButton>
0028 #include <QRegularExpression>
0029 #include <QSpinBox>
0030 #include <QToolButton>
0031 // END Includes
0032 
0033 ModeConfigPage::ModeConfigPage(QWidget *parent)
0034     : KateConfigPage(parent)
0035 {
0036     m_lastType = -1;
0037 
0038     // This will let us have more separation between this page and
0039     // the QTabWidget edge (ereslibre)
0040     QVBoxLayout *layout = new QVBoxLayout(this);
0041     QWidget *newWidget = new QWidget(this);
0042 
0043     ui = new Ui::FileTypeConfigWidget();
0044     ui->setupUi(newWidget);
0045 
0046     ui->cmbHl->addItem(i18n("<Unchanged>"), QVariant(QString()));
0047     const auto modeList = KateHlManager::self()->modeList();
0048     for (const auto &hl : modeList) {
0049         const auto section = hl.translatedSection();
0050         if (!section.isEmpty()) {
0051             ui->cmbHl->addItem(section + QLatin1Char('/') + hl.translatedName(), QVariant(hl.name()));
0052         } else {
0053             ui->cmbHl->addItem(hl.translatedName(), QVariant(hl.name()));
0054         }
0055     }
0056 
0057     QStringList indentationModes;
0058     indentationModes << i18n("Use Default");
0059     indentationModes << KateAutoIndent::listModes();
0060     ui->cmbIndenter->addItems(indentationModes);
0061 
0062     connect(ui->cmbFiletypes, &QComboBox::activated, this, &ModeConfigPage::typeChanged);
0063     connect(ui->btnNew, &QPushButton::clicked, this, &ModeConfigPage::newType);
0064     connect(ui->btnDelete, &QPushButton::clicked, this, &ModeConfigPage::deleteType);
0065     ui->btnMimeTypes->setIcon(QIcon::fromTheme(QStringLiteral("tools-wizard")));
0066     connect(ui->btnMimeTypes, &QToolButton::clicked, this, &ModeConfigPage::showMTDlg);
0067 
0068     reload();
0069 
0070     connect(ui->edtName, &QLineEdit::textChanged, this, &ModeConfigPage::slotChanged);
0071     connect(ui->edtSection, &QLineEdit::textChanged, this, &ModeConfigPage::slotChanged);
0072     connect(ui->edtVariables, &VariableLineEdit::textChanged, this, &ModeConfigPage::slotChanged);
0073     connect(ui->edtFileExtensions, &QLineEdit::textChanged, this, &ModeConfigPage::slotChanged);
0074     connect(ui->edtMimeTypes, &QLineEdit::textChanged, this, &ModeConfigPage::slotChanged);
0075     connect(ui->sbPriority, &QSpinBox::valueChanged, this, &ModeConfigPage::slotChanged);
0076     connect(ui->cmbHl, &QComboBox::activated, this, &ModeConfigPage::slotChanged);
0077     connect(ui->cmbIndenter, &QComboBox::activated, this, &ModeConfigPage::slotChanged);
0078 
0079     // make the context help a bit easier to access
0080     ui->sbPriority->setToolTip(ui->sbPriority->whatsThis());
0081 
0082     layout->addWidget(newWidget);
0083 }
0084 
0085 ModeConfigPage::~ModeConfigPage()
0086 {
0087     qDeleteAll(m_types);
0088     delete ui;
0089 }
0090 
0091 void ModeConfigPage::apply()
0092 {
0093     if (!hasChanged()) {
0094         return;
0095     }
0096 
0097     save();
0098     if (m_lastType != -1) {
0099         ui->gbProperties->setTitle(i18n("Properties of %1", ui->cmbFiletypes->itemText(m_lastType)));
0100     }
0101 
0102     KTextEditor::EditorPrivate::self()->modeManager()->save(m_types);
0103 }
0104 
0105 void ModeConfigPage::reload()
0106 {
0107     qDeleteAll(m_types);
0108     m_types.clear();
0109 
0110     // deep copy...
0111     const QList<KateFileType *> &modeList = KTextEditor::EditorPrivate::self()->modeManager()->list();
0112     m_types.reserve(modeList.size());
0113     for (KateFileType *type : modeList) {
0114         KateFileType *t = new KateFileType();
0115         *t = *type;
0116         m_types.append(t);
0117     }
0118 
0119     update();
0120 }
0121 
0122 void ModeConfigPage::reset()
0123 {
0124     reload();
0125 }
0126 
0127 void ModeConfigPage::defaults()
0128 {
0129     reload();
0130 }
0131 
0132 void ModeConfigPage::update()
0133 {
0134     m_lastType = -1;
0135 
0136     ui->cmbFiletypes->clear();
0137 
0138     for (KateFileType *type : std::as_const(m_types)) {
0139         if (!type->sectionTranslated().isEmpty()) {
0140             ui->cmbFiletypes->addItem(type->sectionTranslated() + QLatin1Char('/') + type->nameTranslated());
0141         } else {
0142             ui->cmbFiletypes->addItem(type->nameTranslated());
0143         }
0144     }
0145 
0146     // get current filetype from active view via the host application
0147     int currentIndex = 0;
0148     KTextEditor::ViewPrivate *kv =
0149         qobject_cast<KTextEditor::ViewPrivate *>(KTextEditor::EditorPrivate::self()->application()->activeMainWindow()->activeView());
0150     if (kv) {
0151         const QString filetypeName = kv->doc()->fileType();
0152         for (int i = 0; i < m_types.size(); ++i) {
0153             if (filetypeName == m_types[i]->name) {
0154                 currentIndex = i;
0155                 break;
0156             }
0157         }
0158     }
0159     ui->cmbFiletypes->setCurrentIndex(currentIndex);
0160     typeChanged(currentIndex);
0161 
0162     ui->cmbFiletypes->setEnabled(ui->cmbFiletypes->count() > 0);
0163 }
0164 
0165 void ModeConfigPage::deleteType()
0166 {
0167     int type = ui->cmbFiletypes->currentIndex();
0168 
0169     if (type > -1 && type < m_types.count()) {
0170         delete m_types[type];
0171         m_types.removeAt(type);
0172         update();
0173     }
0174 }
0175 
0176 void ModeConfigPage::newType()
0177 {
0178     QString newN = i18n("New Filetype");
0179 
0180     for (int i = 0; i < m_types.count(); ++i) {
0181         KateFileType *type = m_types.at(i);
0182         if (type->name == newN) {
0183             ui->cmbFiletypes->setCurrentIndex(i);
0184             typeChanged(i);
0185             return;
0186         }
0187     }
0188 
0189     KateFileType *newT = new KateFileType();
0190     newT->priority = 0;
0191     newT->name = newN;
0192     newT->hlGenerated = false;
0193 
0194     m_types.prepend(newT);
0195 
0196     update();
0197     // show new filetype so that it is immediately available for editing
0198     ui->cmbFiletypes->setCurrentIndex(0);
0199     typeChanged(0);
0200 }
0201 
0202 void ModeConfigPage::save()
0203 {
0204     if (m_lastType != -1) {
0205         if (!m_types[m_lastType]->hlGenerated) {
0206             m_types[m_lastType]->name = ui->edtName->text();
0207             m_types[m_lastType]->section = ui->edtSection->text();
0208 
0209             if (!m_types[m_lastType]->sectionTranslated().isEmpty()) {
0210                 ui->cmbFiletypes->setItemText(m_lastType, m_types[m_lastType]->sectionTranslated() + QLatin1Char('/') + m_types[m_lastType]->nameTranslated());
0211             } else {
0212                 ui->cmbFiletypes->setItemText(m_lastType, m_types[m_lastType]->nameTranslated());
0213             }
0214         }
0215         m_types[m_lastType]->varLine = ui->edtVariables->text();
0216         m_types[m_lastType]->wildcards = ui->edtFileExtensions->text().split(QLatin1Char(';'), Qt::SkipEmptyParts);
0217         m_types[m_lastType]->mimetypes = ui->edtMimeTypes->text().split(QLatin1Char(';'), Qt::SkipEmptyParts);
0218         m_types[m_lastType]->priority = ui->sbPriority->value();
0219         m_types[m_lastType]->hl = ui->cmbHl->itemData(ui->cmbHl->currentIndex()).toString();
0220 
0221         if (ui->cmbIndenter->currentIndex() > 0) {
0222             m_types[m_lastType]->indenter = KateAutoIndent::modeName(ui->cmbIndenter->currentIndex() - 1);
0223         } else {
0224             m_types[m_lastType]->indenter = QString();
0225         }
0226     }
0227 }
0228 
0229 void ModeConfigPage::typeChanged(int type)
0230 {
0231     save();
0232 
0233     ui->cmbHl->setEnabled(true);
0234     ui->btnDelete->setEnabled(true);
0235     ui->edtName->setEnabled(true);
0236     ui->edtSection->setEnabled(true);
0237 
0238     if (type > -1 && type < m_types.count()) {
0239         KateFileType *t = m_types.at(type);
0240 
0241         ui->gbProperties->setTitle(i18n("Properties of %1", ui->cmbFiletypes->itemText(type)));
0242 
0243         ui->gbProperties->setEnabled(true);
0244         ui->btnDelete->setEnabled(true);
0245 
0246         ui->edtName->setText(t->nameTranslated());
0247         ui->edtSection->setText(t->sectionTranslated());
0248         ui->edtVariables->setText(t->varLine);
0249         ui->edtFileExtensions->setText(t->wildcards.join(QLatin1Char(';')));
0250         ui->edtMimeTypes->setText(t->mimetypes.join(QLatin1Char(';')));
0251         ui->sbPriority->setValue(t->priority);
0252 
0253         ui->cmbHl->setEnabled(!t->hlGenerated);
0254         ui->btnDelete->setEnabled(!t->hlGenerated);
0255         ui->edtName->setEnabled(!t->hlGenerated);
0256         ui->edtSection->setEnabled(!t->hlGenerated);
0257 
0258         // activate current hl...
0259         for (int i = 0; i < ui->cmbHl->count(); ++i) {
0260             if (ui->cmbHl->itemData(i).toString() == t->hl) {
0261                 ui->cmbHl->setCurrentIndex(i);
0262             }
0263         }
0264 
0265         // activate the right indenter
0266         int indenterIndex = 0;
0267         if (!t->indenter.isEmpty()) {
0268             indenterIndex = KateAutoIndent::modeNumber(t->indenter) + 1;
0269         }
0270         ui->cmbIndenter->setCurrentIndex(indenterIndex);
0271     } else {
0272         ui->gbProperties->setTitle(i18n("Properties"));
0273 
0274         ui->gbProperties->setEnabled(false);
0275         ui->btnDelete->setEnabled(false);
0276 
0277         ui->edtName->clear();
0278         ui->edtSection->clear();
0279         ui->edtVariables->clear();
0280         ui->edtFileExtensions->clear();
0281         ui->edtMimeTypes->clear();
0282         ui->sbPriority->setValue(0);
0283         ui->cmbHl->setCurrentIndex(0);
0284         ui->cmbIndenter->setCurrentIndex(0);
0285     }
0286 
0287     m_lastType = type;
0288 }
0289 
0290 void ModeConfigPage::showMTDlg()
0291 {
0292     QString text =
0293         i18n("Select the MimeTypes you want for this file type.\nPlease note that this will automatically edit the associated file extensions as well.");
0294     QStringList list = ui->edtMimeTypes->text().split(QRegularExpression(QStringLiteral("\\s*;\\s*")), Qt::SkipEmptyParts);
0295     KMimeTypeChooserDialog d(i18n("Select Mime Types"), text, list, QStringLiteral("text"), this);
0296     if (d.exec() == QDialog::Accepted) {
0297         // do some checking, warn user if mime types or patterns are removed.
0298         // if the lists are empty, and the fields not, warn.
0299         ui->edtFileExtensions->setText(d.chooser()->patterns().join(QLatin1Char(';')));
0300         ui->edtMimeTypes->setText(d.chooser()->mimeTypes().join(QLatin1Char(';')));
0301     }
0302 }
0303 
0304 QString ModeConfigPage::name() const
0305 {
0306     return i18n("Modes && Filetypes");
0307 }