kate Library API Documentation

katefiletype.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00016    Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "katefiletype.h"
00020 #include "katefiletype.moc"
00021 
00022 #include "katedocument.h"
00023 #include "kateconfig.h"
00024 #include "katedialogs.h"
00025 #include "kateview.h"
00026 #include "katefactory.h"
00027 
00028 #include <kconfig.h>
00029 #include <kmimemagic.h>
00030 #include <kmimetype.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 // read the types from config file and update the internal list
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 // save the given list to config file + update
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   // first use the wildcards
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   //
00171   // now use the KMimeType POWER ;)
00172   //
00173   QByteArray buf (KATE_FT_HOWMANY);
00174   uint bufpos = 0;
00175   for (uint i=0; i < doc->numLines(); i++)
00176   {
00177     QString line = doc->textLine( i );
00178     uint len = line.length() + 1;
00179     
00180     if (bufpos + len > KATE_FT_HOWMANY)
00181       len = KATE_FT_HOWMANY - bufpos;
00182 
00183     memcpy(&buf[bufpos], (line + "\n").latin1(), len);
00184     
00185     bufpos += len;
00186     
00187     if (bufpos >= KATE_FT_HOWMANY)
00188       break;
00189   }
00190   buf.resize( bufpos );
00191 
00192   int accuracy;
00193   KMimeType::Ptr mt = KMimeType::findByContent( buf, &accuracy );
00194 
00195   QPtrList<KateFileType> types;
00196 
00197   for (uint z=0; z < m_types.count(); z++)
00198   {
00199     if (m_types.at(z)->mimetypes.findIndex (mt->name()) > -1)
00200       types.append (m_types.at(z));
00201   }
00202 
00203   if ( !types.isEmpty() )
00204   {
00205     int pri = -1;
00206     int hl = -1;
00207 
00208     for (KateFileType *type = types.first(); type != 0L; type = types.next())
00209     {
00210       if (type->priority > pri)
00211       {
00212         pri = type->priority;
00213         hl = type->number;
00214       }
00215     }
00216 
00217     return hl;
00218   }
00219 
00220   return -1;
00221 }
00222 
00223 int KateFileTypeManager::wildcardsFind (const QString &fileName)
00224 {
00225   QPtrList<KateFileType> types;
00226 
00227   for (uint z=0; z < m_types.count(); z++)
00228   {
00229     for( QStringList::Iterator it = m_types.at(z)->wildcards.begin(); it != m_types.at(z)->wildcards.end(); ++it )
00230     {
00231       // anders: we need to be sure to match the end of string, as eg a css file
00232       // would otherwise end up with the c hl
00233       QRegExp re(*it, true, true);
00234       if ( ( re.search( fileName ) > -1 ) && ( re.matchedLength() == (int)fileName.length() ) )
00235         types.append (m_types.at(z));
00236     }
00237   }
00238 
00239   if ( !types.isEmpty() )
00240   {
00241     int pri = -1;
00242     int hl = -1;
00243 
00244     for (KateFileType *type = types.first(); type != 0L; type = types.next())
00245     {
00246       if (type->priority > pri)
00247       {
00248         pri = type->priority;
00249         hl = type->number;
00250       }
00251     }
00252 
00253     return hl;
00254   }
00255 
00256   return -1;
00257 }
00258 
00259 const KateFileType *KateFileTypeManager::fileType (uint number)
00260 {
00261   if (number < m_types.count())
00262     return m_types.at(number);
00263 
00264   return 0;
00265 }
00266 
00267 KateFileTypeConfigTab::KateFileTypeConfigTab( QWidget *parent )
00268   : KateConfigPage( parent )
00269 {
00270   m_types.setAutoDelete (true);
00271   m_lastType = 0;
00272 
00273   QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
00274 
00275   // hl chooser
00276   QHBox *hbHl = new QHBox( this );
00277   layout->add (hbHl);
00278   hbHl->setSpacing( KDialog::spacingHint() );
00279   QLabel *lHl = new QLabel( i18n("&Filetype:"), hbHl );
00280   typeCombo = new QComboBox( false, hbHl );
00281   lHl->setBuddy( typeCombo );
00282   connect( typeCombo, SIGNAL(activated(int)),
00283            this, SLOT(typeChanged(int)) );
00284 
00285   btndel = new QPushButton( i18n("&Delete"), hbHl );
00286   connect( btndel, SIGNAL(clicked()), this, SLOT(deleteType()) );
00287 
00288   QPushButton *btnnew = new QPushButton( i18n("&New"), hbHl );
00289   connect( btnnew, SIGNAL(clicked()), this, SLOT(newType()) );
00290 
00291   gbProps = new QGroupBox( 2, Qt::Horizontal, i18n("Properties"), this );
00292   layout->add (gbProps);
00293 
00294   // file & mime types
00295   QLabel *lname = new QLabel( i18n("N&ame:"), gbProps );
00296   name  = new QLineEdit( gbProps );
00297   lname->setBuddy( name );
00298 
00299   // file & mime types
00300   QLabel *lsec = new QLabel( i18n("&Section:"), gbProps );
00301   section  = new QLineEdit( gbProps );
00302   lsec->setBuddy( section );
00303 
00304   // file & mime types
00305   QLabel *lvar = new QLabel( i18n("&Variables:"), gbProps );
00306   varLine  = new QLineEdit( gbProps );
00307   lvar->setBuddy( varLine );
00308 
00309   // file & mime types
00310   QLabel *lFileExts = new QLabel( i18n("File e&xtensions:"), gbProps );
00311   wildcards  = new QLineEdit( gbProps );
00312   lFileExts->setBuddy( wildcards );
00313 
00314   QLabel *lMimeTypes = new QLabel( i18n("MIME &types:"), gbProps);
00315   QHBox *hbMT = new QHBox (gbProps);
00316   mimetypes = new QLineEdit( hbMT );
00317   lMimeTypes->setBuddy( mimetypes );
00318 
00319   QToolButton *btnMTW = new QToolButton(hbMT);
00320   btnMTW->setIconSet(QIconSet(SmallIcon("wizard")));
00321   connect(btnMTW, SIGNAL(clicked()), this, SLOT(showMTDlg()));
00322 
00323   QLabel *lprio = new QLabel( i18n("Prio&rity:"), gbProps);
00324   priority = new KIntNumInput( gbProps );
00325   lprio->setBuddy( priority );
00326 
00327   layout->addStretch();
00328 
00329   reload();
00330   
00331   connect( name, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00332   connect( section, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00333   connect( varLine, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00334   connect( wildcards, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00335   connect( mimetypes, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00336   connect( priority, SIGNAL( valueChanged ( int ) ), this, SLOT( slotChanged() ) );
00337 }
00338 
00339 void KateFileTypeConfigTab::apply()
00340 {
00341   if (!changed())
00342     return;
00343 
00344   save ();
00345 
00346   KateFactory::self()->fileTypeManager()->save(&m_types);
00347 }
00348 
00349 void KateFileTypeConfigTab::reload()
00350 {
00351   m_types.clear();
00352   for (uint z=0; z < KateFactory::self()->fileTypeManager()->list()->count(); z++)
00353   {
00354     KateFileType *type = new KateFileType ();
00355 
00356     *type = *KateFactory::self()->fileTypeManager()->list()->at(z);
00357 
00358     m_types.append (type);
00359   }
00360 
00361   update ();
00362 }
00363 
00364 void KateFileTypeConfigTab::reset()
00365 {
00366   reload ();
00367 }
00368 
00369 void KateFileTypeConfigTab::defaults()
00370 {
00371   reload ();
00372 }
00373 
00374 void KateFileTypeConfigTab::update ()
00375 {
00376   m_lastType = 0;
00377 
00378   typeCombo->clear ();
00379 
00380   for( uint i = 0; i < m_types.count(); i++) {
00381     if (m_types.at(i)->section.length() > 0)
00382       typeCombo->insertItem(m_types.at(i)->section + QString ("/") + m_types.at(i)->name);
00383     else
00384       typeCombo->insertItem(m_types.at(i)->name);
00385   }
00386 
00387   typeCombo->setCurrentItem (0);
00388 
00389   typeChanged (0);
00390 
00391   typeCombo->setEnabled (typeCombo->count() > 0);
00392 }
00393 
00394 void KateFileTypeConfigTab::deleteType ()
00395 {
00396   int type = typeCombo->currentItem ();
00397 
00398   if ((type > -1) && ((uint)type < m_types.count()))
00399   {
00400     m_types.remove (type);
00401     update ();
00402   }
00403 }
00404 
00405 void KateFileTypeConfigTab::newType ()
00406 {
00407   QString newN = i18n("New Filetype");
00408 
00409   for( uint i = 0; i < m_types.count(); i++) {
00410     if (m_types.at(i)->name == newN)
00411     {
00412       typeCombo->setCurrentItem (i);
00413       typeChanged (i);
00414       return;
00415     }
00416   }
00417 
00418   KateFileType *newT = new KateFileType ();
00419   newT->priority = 0;
00420   newT->name = newN;
00421 
00422   m_types.prepend (newT);
00423 
00424   update ();
00425 }
00426 
00427 void KateFileTypeConfigTab::save ()
00428 {
00429   if (m_lastType)
00430   {
00431     m_lastType->name = name->text ();
00432     m_lastType->section = section->text ();
00433     m_lastType->varLine = varLine->text ();
00434     m_lastType->wildcards = QStringList::split (";", wildcards->text ());
00435     m_lastType->mimetypes = QStringList::split (";", mimetypes->text ());
00436     m_lastType->priority = priority->value();
00437   }
00438 }
00439 
00440 void KateFileTypeConfigTab::typeChanged (int type)
00441 {
00442   save ();
00443 
00444   KateFileType *t = 0;
00445 
00446   if ((type > -1) && ((uint)type < m_types.count()))
00447     t = m_types.at(type);
00448 
00449   if (t)
00450   {
00451     gbProps->setTitle (i18n("Properties of %1").arg (typeCombo->currentText()));
00452 
00453     gbProps->setEnabled (true);
00454     btndel->setEnabled (true);
00455 
00456     name->setText(t->name);
00457     section->setText(t->section);
00458     varLine->setText(t->varLine);
00459     wildcards->setText(t->wildcards.join (";"));
00460     mimetypes->setText(t->mimetypes.join (";"));
00461     priority->setValue(t->priority);
00462   }
00463   else
00464   {
00465     gbProps->setTitle (i18n("Properties"));
00466 
00467     gbProps->setEnabled (false);
00468     btndel->setEnabled (false);
00469 
00470     name->clear();
00471     section->clear();
00472     varLine->clear();
00473     wildcards->clear();
00474     mimetypes->clear();
00475     priority->setValue(0);
00476   }
00477 
00478   m_lastType = t;
00479 }
00480 
00481 void KateFileTypeConfigTab::showMTDlg()
00482 {
00483 
00484   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.");
00485   QStringList list = QStringList::split( QRegExp("\\s*;\\s*"), mimetypes->text() );
00486   KMimeTypeChooserDlg *d = new KMimeTypeChooserDlg( this, i18n("Select Mime Types"), text, list );
00487   if ( d->exec() == KDialogBase::Accepted ) {
00488     // do some checking, warn user if mime types or patterns are removed.
00489     // if the lists are empty, and the fields not, warn.
00490     wildcards->setText(d->patterns().join(";"));
00491     mimetypes->setText(d->mimeTypes().join(";"));
00492   }
00493 }
00494 
00495 void KateViewFileTypeAction::init()
00496 {
00497   m_doc = 0;
00498   subMenus.setAutoDelete( true );
00499 
00500   popupMenu()->insertItem ( i18n("None"), this, SLOT(setType(int)), 0,  0);
00501 
00502   connect(popupMenu(),SIGNAL(aboutToShow()),this,SLOT(slotAboutToShow()));
00503 }
00504 
00505 void KateViewFileTypeAction::updateMenu (Kate::Document *doc)
00506 {
00507   m_doc = (KateDocument *)doc;
00508 }
00509 
00510 void KateViewFileTypeAction::slotAboutToShow()
00511 {
00512   KateDocument *doc=m_doc;
00513   int count = KateFactory::self()->fileTypeManager()->list()->count();
00514 
00515   for (int z=0; z<count; z++)
00516   {
00517     QString hlName = KateFactory::self()->fileTypeManager()->list()->at(z)->name;
00518     QString hlSection = KateFactory::self()->fileTypeManager()->list()->at(z)->section;
00519 
00520     if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) )
00521     {
00522       if (subMenusName.contains(hlSection) < 1)
00523       {
00524         subMenusName << hlSection;
00525         QPopupMenu *menu = new QPopupMenu ();
00526         subMenus.append(menu);
00527         popupMenu()->insertItem (hlSection, menu);
00528       }
00529 
00530       int m = subMenusName.findIndex (hlSection);
00531       names << hlName;
00532       subMenus.at(m)->insertItem ( hlName, this, SLOT(setType(int)), 0,  z+1);
00533     }
00534     else if (names.contains(hlName) < 1)
00535     {
00536       names << hlName;
00537       popupMenu()->insertItem ( hlName, this, SLOT(setType(int)), 0,  z+1);
00538     }
00539   }
00540 
00541   if (!doc) return;
00542 
00543   for (uint i=0;i<subMenus.count();i++)
00544   {
00545     for (uint i2=0;i2<subMenus.at(i)->count();i2++)
00546       subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false);
00547   }
00548   popupMenu()->setItemChecked (0, false);
00549 
00550   if (doc->fileType() == -1)
00551     popupMenu()->setItemChecked (0, true);
00552   else
00553   {
00554     const KateFileType *t = 0;
00555     if ((t = KateFactory::self()->fileTypeManager()->fileType (doc->fileType())))
00556     {
00557       int i = subMenusName.findIndex (t->section);
00558       if (i >= 0 && subMenus.at(i))
00559         subMenus.at(i)->setItemChecked (doc->fileType()+1, true);
00560       else
00561         popupMenu()->setItemChecked (0, true);
00562     }
00563   }
00564 }
00565 
00566 void KateViewFileTypeAction::setType (int mode)
00567 {
00568   KateDocument *doc=m_doc;
00569 
00570   if (doc)
00571     doc->updateFileType(mode-1, true);
00572 }
00573 
00574 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun May 16 22:07:06 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003