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