00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "katefiletype.h"
00020 #include "katefiletype.moc"
00021
00022 #include "katedocument.h"
00023 #include "kateconfig.h"
00024 #include "kateview.h"
00025 #include "katefactory.h"
00026
00027 #include <kconfig.h>
00028 #include <kmimemagic.h>
00029 #include <kmimetype.h>
00030 #include <kmimetypechooser.h>
00031 #include <kdebug.h>
00032 #include <kiconloader.h>
00033 #include <knuminput.h>
00034 #include <klocale.h>
00035 #include <kpopupmenu.h>
00036
00037 #include <qregexp.h>
00038 #include <qcheckbox.h>
00039 #include <qcombobox.h>
00040 #include <qgroupbox.h>
00041 #include <qhbox.h>
00042 #include <qheader.h>
00043 #include <qhgroupbox.h>
00044 #include <qlabel.h>
00045 #include <qlayout.h>
00046 #include <qlineedit.h>
00047 #include <qpushbutton.h>
00048 #include <qtoolbutton.h>
00049 #include <qvbox.h>
00050 #include <qvgroupbox.h>
00051 #include <qwhatsthis.h>
00052 #include <qwidgetstack.h>
00053
00054 #define KATE_FT_HOWMANY 1024
00055
00056 KateFileTypeManager::KateFileTypeManager ()
00057 {
00058 m_types.setAutoDelete (true);
00059
00060 update ();
00061 }
00062
00063 KateFileTypeManager::~KateFileTypeManager ()
00064 {
00065 }
00066
00067
00068
00069
00070 void KateFileTypeManager::update ()
00071 {
00072 KConfig config ("katefiletyperc", false, false);
00073
00074 QStringList g (config.groupList());
00075 g.sort ();
00076
00077 m_types.clear ();
00078 for (uint z=0; z < g.count(); z++)
00079 {
00080 config.setGroup (g[z]);
00081
00082 KateFileType *type = new KateFileType ();
00083
00084 type->number = z;
00085 type->name = g[z];
00086 type->section = config.readEntry ("Section");
00087 type->wildcards = config.readListEntry ("Wildcards", ';');
00088 type->mimetypes = config.readListEntry ("Mimetypes", ';');
00089 type->priority = config.readNumEntry ("Priority");
00090 type->varLine = config.readEntry ("Variables");
00091
00092 m_types.append (type);
00093
00094 kdDebug(13020) << "INIT LIST: " << type->name << endl;
00095 }
00096 }
00097
00098
00099
00100
00101 void KateFileTypeManager::save (QPtrList<KateFileType> *v)
00102 {
00103 KConfig config ("katefiletyperc", false, false);
00104
00105 QStringList newg;
00106 for (uint z=0; z < v->count(); z++)
00107 {
00108 config.setGroup (v->at(z)->name);
00109
00110 config.writeEntry ("Section", v->at(z)->section);
00111 config.writeEntry ("Wildcards", v->at(z)->wildcards, ';');
00112 config.writeEntry ("Mimetypes", v->at(z)->mimetypes, ';');
00113 config.writeEntry ("Priority", v->at(z)->priority);
00114
00115 QString varLine = v->at(z)->varLine;
00116 if (QRegExp("kate:(.*)").search(varLine) < 0)
00117 varLine.prepend ("kate: ");
00118
00119 config.writeEntry ("Variables", varLine);
00120
00121 newg << v->at(z)->name;
00122 }
00123
00124 QStringList g (config.groupList());
00125
00126 for (uint z=0; z < g.count(); z++)
00127 {
00128 if (newg.findIndex (g[z]) == -1)
00129 config.deleteGroup (g[z]);
00130 }
00131
00132 config.sync ();
00133
00134 update ();
00135 }
00136
00137 int KateFileTypeManager::fileType (KateDocument *doc)
00138 {
00139 if (!doc)
00140 return -1;
00141
00142 if (m_types.isEmpty())
00143 return -1;
00144
00145 QString fileName = doc->url().prettyURL();
00146 int length = doc->url().prettyURL().length();
00147
00148
00149
00150
00151 static QStringList commonSuffixes = QStringList::split (";", ".orig;.new;~;.bak;.BAK");
00152
00153 int result;
00154 if ((result = wildcardsFind(fileName)) != -1)
00155 return result;
00156
00157 QString backupSuffix = KateDocumentConfig::global()->backupSuffix();
00158 if (fileName.endsWith(backupSuffix)) {
00159 if ((result = wildcardsFind(fileName.left(length - backupSuffix.length()))) != -1)
00160 return result;
00161 }
00162
00163 for (QStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) {
00164 if (*it != backupSuffix && fileName.endsWith(*it)) {
00165 if ((result = wildcardsFind(fileName.left(length - (*it).length()))) != -1)
00166 return result;
00167 }
00168 }
00169
00170 KMimeType::Ptr mt = doc->mimeTypeForContent();
00171
00172 QPtrList<KateFileType> types;
00173
00174 for (uint z=0; z < m_types.count(); z++)
00175 {
00176 if (m_types.at(z)->mimetypes.findIndex (mt->name()) > -1)
00177 types.append (m_types.at(z));
00178 }
00179
00180 if ( !types.isEmpty() )
00181 {
00182 int pri = -1;
00183 int hl = -1;
00184
00185 for (KateFileType *type = types.first(); type != 0L; type = types.next())
00186 {
00187 if (type->priority > pri)
00188 {
00189 pri = type->priority;
00190 hl = type->number;
00191 }
00192 }
00193
00194 return hl;
00195 }
00196
00197 return -1;
00198 }
00199
00200 int KateFileTypeManager::wildcardsFind (const QString &fileName)
00201 {
00202 QPtrList<KateFileType> types;
00203
00204 for (uint z=0; z < m_types.count(); z++)
00205 {
00206 for( QStringList::Iterator it = m_types.at(z)->wildcards.begin(); it != m_types.at(z)->wildcards.end(); ++it )
00207 {
00208
00209
00210 QRegExp re(*it, true, true);
00211 if ( ( re.search( fileName ) > -1 ) && ( re.matchedLength() == (int)fileName.length() ) )
00212 types.append (m_types.at(z));
00213 }
00214 }
00215
00216 if ( !types.isEmpty() )
00217 {
00218 int pri = -1;
00219 int hl = -1;
00220
00221 for (KateFileType *type = types.first(); type != 0L; type = types.next())
00222 {
00223 if (type->priority > pri)
00224 {
00225 pri = type->priority;
00226 hl = type->number;
00227 }
00228 }
00229
00230 return hl;
00231 }
00232
00233 return -1;
00234 }
00235
00236 const KateFileType *KateFileTypeManager::fileType (uint number)
00237 {
00238 if (number < m_types.count())
00239 return m_types.at(number);
00240
00241 return 0;
00242 }
00243
00244 KateFileTypeConfigTab::KateFileTypeConfigTab( QWidget *parent )
00245 : KateConfigPage( parent )
00246 {
00247 m_types.setAutoDelete (true);
00248 m_lastType = 0;
00249
00250 QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
00251
00252
00253 QHBox *hbHl = new QHBox( this );
00254 layout->add (hbHl);
00255 hbHl->setSpacing( KDialog::spacingHint() );
00256 QLabel *lHl = new QLabel( i18n("&Filetype:"), hbHl );
00257 typeCombo = new QComboBox( false, hbHl );
00258 lHl->setBuddy( typeCombo );
00259 connect( typeCombo, SIGNAL(activated(int)),
00260 this, SLOT(typeChanged(int)) );
00261
00262 QPushButton *btnnew = new QPushButton( i18n("&New"), hbHl );
00263 connect( btnnew, SIGNAL(clicked()), this, SLOT(newType()) );
00264
00265 btndel = new QPushButton( i18n("&Delete"), hbHl );
00266 connect( btndel, SIGNAL(clicked()), this, SLOT(deleteType()) );
00267
00268 gbProps = new QGroupBox( 2, Qt::Horizontal, i18n("Properties"), this );
00269 layout->add (gbProps);
00270
00271
00272 QLabel *lname = new QLabel( i18n("N&ame:"), gbProps );
00273 name = new QLineEdit( gbProps );
00274 lname->setBuddy( name );
00275
00276
00277 QLabel *lsec = new QLabel( i18n("&Section:"), gbProps );
00278 section = new QLineEdit( gbProps );
00279 lsec->setBuddy( section );
00280
00281
00282 QLabel *lvar = new QLabel( i18n("&Variables:"), gbProps );
00283 varLine = new QLineEdit( gbProps );
00284 lvar->setBuddy( varLine );
00285
00286
00287 QLabel *lFileExts = new QLabel( i18n("File e&xtensions:"), gbProps );
00288 wildcards = new QLineEdit( gbProps );
00289 lFileExts->setBuddy( wildcards );
00290
00291 QLabel *lMimeTypes = new QLabel( i18n("MIME &types:"), gbProps);
00292 QHBox *hbMT = new QHBox (gbProps);
00293 mimetypes = new QLineEdit( hbMT );
00294 lMimeTypes->setBuddy( mimetypes );
00295
00296 QToolButton *btnMTW = new QToolButton(hbMT);
00297 btnMTW->setIconSet(QIconSet(SmallIcon("wizard")));
00298 connect(btnMTW, SIGNAL(clicked()), this, SLOT(showMTDlg()));
00299
00300 QLabel *lprio = new QLabel( i18n("Prio&rity:"), gbProps);
00301 priority = new KIntNumInput( gbProps );
00302 lprio->setBuddy( priority );
00303
00304 layout->addStretch();
00305
00306 reload();
00307
00308 connect( name, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00309 connect( section, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00310 connect( varLine, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00311 connect( wildcards, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00312 connect( mimetypes, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00313 connect( priority, SIGNAL( valueChanged ( int ) ), this, SLOT( slotChanged() ) );
00314 }
00315
00316 void KateFileTypeConfigTab::apply()
00317 {
00318 if (!changed())
00319 return;
00320
00321 save ();
00322
00323 KateFactory::self()->fileTypeManager()->save(&m_types);
00324 }
00325
00326 void KateFileTypeConfigTab::reload()
00327 {
00328 m_types.clear();
00329 for (uint z=0; z < KateFactory::self()->fileTypeManager()->list()->count(); z++)
00330 {
00331 KateFileType *type = new KateFileType ();
00332
00333 *type = *KateFactory::self()->fileTypeManager()->list()->at(z);
00334
00335 m_types.append (type);
00336 }
00337
00338 update ();
00339 }
00340
00341 void KateFileTypeConfigTab::reset()
00342 {
00343 reload ();
00344 }
00345
00346 void KateFileTypeConfigTab::defaults()
00347 {
00348 reload ();
00349 }
00350
00351 void KateFileTypeConfigTab::update ()
00352 {
00353 m_lastType = 0;
00354
00355 typeCombo->clear ();
00356
00357 for( uint i = 0; i < m_types.count(); i++) {
00358 if (m_types.at(i)->section.length() > 0)
00359 typeCombo->insertItem(m_types.at(i)->section + QString ("/") + m_types.at(i)->name);
00360 else
00361 typeCombo->insertItem(m_types.at(i)->name);
00362 }
00363
00364 typeCombo->setCurrentItem (0);
00365
00366 typeChanged (0);
00367
00368 typeCombo->setEnabled (typeCombo->count() > 0);
00369 }
00370
00371 void KateFileTypeConfigTab::deleteType ()
00372 {
00373 int type = typeCombo->currentItem ();
00374
00375 if ((type > -1) && ((uint)type < m_types.count()))
00376 {
00377 m_types.remove (type);
00378 update ();
00379 }
00380 }
00381
00382 void KateFileTypeConfigTab::newType ()
00383 {
00384 QString newN = i18n("New Filetype");
00385
00386 for( uint i = 0; i < m_types.count(); i++) {
00387 if (m_types.at(i)->name == newN)
00388 {
00389 typeCombo->setCurrentItem (i);
00390 typeChanged (i);
00391 return;
00392 }
00393 }
00394
00395 KateFileType *newT = new KateFileType ();
00396 newT->priority = 0;
00397 newT->name = newN;
00398
00399 m_types.prepend (newT);
00400
00401 update ();
00402 }
00403
00404 void KateFileTypeConfigTab::save ()
00405 {
00406 if (m_lastType)
00407 {
00408 m_lastType->name = name->text ();
00409 m_lastType->section = section->text ();
00410 m_lastType->varLine = varLine->text ();
00411 m_lastType->wildcards = QStringList::split (";", wildcards->text ());
00412 m_lastType->mimetypes = QStringList::split (";", mimetypes->text ());
00413 m_lastType->priority = priority->value();
00414 }
00415 }
00416
00417 void KateFileTypeConfigTab::typeChanged (int type)
00418 {
00419 save ();
00420
00421 KateFileType *t = 0;
00422
00423 if ((type > -1) && ((uint)type < m_types.count()))
00424 t = m_types.at(type);
00425
00426 if (t)
00427 {
00428 gbProps->setTitle (i18n("Properties of %1").arg (typeCombo->currentText()));
00429
00430 gbProps->setEnabled (true);
00431 btndel->setEnabled (true);
00432
00433 name->setText(t->name);
00434 section->setText(t->section);
00435 varLine->setText(t->varLine);
00436 wildcards->setText(t->wildcards.join (";"));
00437 mimetypes->setText(t->mimetypes.join (";"));
00438 priority->setValue(t->priority);
00439 }
00440 else
00441 {
00442 gbProps->setTitle (i18n("Properties"));
00443
00444 gbProps->setEnabled (false);
00445 btndel->setEnabled (false);
00446
00447 name->clear();
00448 section->clear();
00449 varLine->clear();
00450 wildcards->clear();
00451 mimetypes->clear();
00452 priority->setValue(0);
00453 }
00454
00455 m_lastType = t;
00456 }
00457
00458 void KateFileTypeConfigTab::showMTDlg()
00459 {
00460
00461 QString text = i18n("Select the MimeTypes you want for this file type.\nPlease note that this will automatically edit the associated file extensions as well.");
00462 QStringList list = QStringList::split( QRegExp("\\s*;\\s*"), mimetypes->text() );
00463 KMimeTypeChooserDialog *d = new KMimeTypeChooserDialog( i18n("Select Mime Types"), text, list, "text", this );
00464 if ( d->exec() == KDialogBase::Accepted ) {
00465
00466
00467 wildcards->setText( d->chooser()->patterns().join(";") );
00468 mimetypes->setText( d->chooser()->mimeTypes().join(";") );
00469 }
00470 }
00471
00472 void KateViewFileTypeAction::init()
00473 {
00474 m_doc = 0;
00475 subMenus.setAutoDelete( true );
00476
00477 popupMenu()->insertItem ( i18n("None"), this, SLOT(setType(int)), 0, 0);
00478
00479 connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
00480 }
00481
00482 void KateViewFileTypeAction::updateMenu (Kate::Document *doc)
00483 {
00484 m_doc = (KateDocument *)doc;
00485 }
00486
00487 void KateViewFileTypeAction::slotAboutToShow()
00488 {
00489 KateDocument *doc=m_doc;
00490 int count = KateFactory::self()->fileTypeManager()->list()->count();
00491
00492 for (int z=0; z<count; z++)
00493 {
00494 QString hlName = KateFactory::self()->fileTypeManager()->list()->at(z)->name;
00495 QString hlSection = KateFactory::self()->fileTypeManager()->list()->at(z)->section;
00496
00497 if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) )
00498 {
00499 if (subMenusName.contains(hlSection) < 1)
00500 {
00501 subMenusName << hlSection;
00502 QPopupMenu *menu = new QPopupMenu ();
00503 subMenus.append(menu);
00504 popupMenu()->insertItem (hlSection, menu);
00505 }
00506
00507 int m = subMenusName.findIndex (hlSection);
00508 names << hlName;
00509 subMenus.at(m)->insertItem ( hlName, this, SLOT(setType(int)), 0, z+1);
00510 }
00511 else if (names.contains(hlName) < 1)
00512 {
00513 names << hlName;
00514 popupMenu()->insertItem ( hlName, this, SLOT(setType(int)), 0, z+1);
00515 }
00516 }
00517
00518 if (!doc) return;
00519
00520 for (uint i=0;i<subMenus.count();i++)
00521 {
00522 for (uint i2=0;i2<subMenus.at(i)->count();i2++)
00523 subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false);
00524 }
00525 popupMenu()->setItemChecked (0, false);
00526
00527 if (doc->fileType() == -1)
00528 popupMenu()->setItemChecked (0, true);
00529 else
00530 {
00531 const KateFileType *t = 0;
00532 if ((t = KateFactory::self()->fileTypeManager()->fileType (doc->fileType())))
00533 {
00534 int i = subMenusName.findIndex (t->section);
00535 if (i >= 0 && subMenus.at(i))
00536 subMenus.at(i)->setItemChecked (doc->fileType()+1, true);
00537 else
00538 popupMenu()->setItemChecked (0, true);
00539 }
00540 }
00541 }
00542
00543 void KateViewFileTypeAction::setType (int mode)
00544 {
00545 KateDocument *doc=m_doc;
00546
00547 if (doc)
00548 doc->updateFileType(mode-1, true);
00549 }
00550
00551