TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

katefiletype.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /* This file is part of the KDE libraries
  2. Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License version 2 as published by the Free Software Foundation.
  6. This library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. Library General Public License for more details.
  10. You should have received a copy of the GNU Library General Public License
  11. along with this library; see the file COPYING.LIB. If not, write to
  12. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  13. Boston, MA 02110-1301, USA.
  14. */
  15. //BEGIN Includes
  16. #include "katefiletype.h"
  17. #include "katefiletype.moc"
  18. #include "katedocument.h"
  19. #include "kateconfig.h"
  20. #include "kateview.h"
  21. #include "katefactory.h"
  22. #include <tdeconfig.h>
  23. #include <kmimemagic.h>
  24. #include <kmimetype.h>
  25. #include <kmimetypechooser.h>
  26. #include <kdebug.h>
  27. #include <kiconloader.h>
  28. #include <knuminput.h>
  29. #include <tdelocale.h>
  30. #include <tdepopupmenu.h>
  31. #include <tqregexp.h>
  32. #include <tqcheckbox.h>
  33. #include <tqcombobox.h>
  34. #include <tqgroupbox.h>
  35. #include <tqhbox.h>
  36. #include <tqheader.h>
  37. #include <tqhgroupbox.h>
  38. #include <tqlabel.h>
  39. #include <tqlayout.h>
  40. #include <tqlineedit.h>
  41. #include <tqpushbutton.h>
  42. #include <tqtoolbutton.h>
  43. #include <tqvbox.h>
  44. #include <tqvgroupbox.h>
  45. #include <tqwhatsthis.h>
  46. #include <tqwidgetstack.h>
  47. #define KATE_FT_HOWMANY 1024
  48. //END Includes
  49. //BEGIN KateFileTypeManager
  50. KateFileTypeManager::KateFileTypeManager ()
  51. {
  52. m_types.setAutoDelete (true);
  53. update ();
  54. }
  55. KateFileTypeManager::~KateFileTypeManager ()
  56. {
  57. }
  58. //
  59. // read the types from config file and update the internal list
  60. //
  61. void KateFileTypeManager::update ()
  62. {
  63. TDEConfig config ("katefiletyperc", false, false);
  64. TQStringList g (config.groupList());
  65. g.sort ();
  66. m_types.clear ();
  67. for (uint z=0; z < g.count(); z++)
  68. {
  69. config.setGroup (g[z]);
  70. KateFileType *type = new KateFileType ();
  71. type->number = z;
  72. type->name = g[z];
  73. type->section = config.readEntry ("Section");
  74. type->wildcards = config.readListEntry ("Wildcards", ';');
  75. type->mimetypes = config.readListEntry ("Mimetypes", ';');
  76. type->priority = config.readNumEntry ("Priority");
  77. type->varLine = config.readEntry ("Variables");
  78. m_types.append (type);
  79. }
  80. }
  81. //
  82. // save the given list to config file + update
  83. //
  84. void KateFileTypeManager::save (TQPtrList<KateFileType> *v)
  85. {
  86. TDEConfig config ("katefiletyperc", false, false);
  87. TQStringList newg;
  88. for (uint z=0; z < v->count(); z++)
  89. {
  90. config.setGroup (v->at(z)->name);
  91. config.writeEntry ("Section", v->at(z)->section);
  92. config.writeEntry ("Wildcards", v->at(z)->wildcards, ';');
  93. config.writeEntry ("Mimetypes", v->at(z)->mimetypes, ';');
  94. config.writeEntry ("Priority", v->at(z)->priority);
  95. TQString varLine = v->at(z)->varLine;
  96. if (TQRegExp("kate:(.*)").search(varLine) < 0)
  97. varLine.prepend ("kate: ");
  98. config.writeEntry ("Variables", varLine);
  99. newg << v->at(z)->name;
  100. }
  101. TQStringList g (config.groupList());
  102. for (uint z=0; z < g.count(); z++)
  103. {
  104. if (newg.findIndex (g[z]) == -1)
  105. config.deleteGroup (g[z]);
  106. }
  107. config.sync ();
  108. update ();
  109. }
  110. int KateFileTypeManager::fileType (KateDocument *doc)
  111. {
  112. kdDebug(13020)<<k_funcinfo<<endl;
  113. if (!doc)
  114. return -1;
  115. if (m_types.isEmpty())
  116. return -1;
  117. TQString fileName = doc->url().prettyURL();
  118. int length = doc->url().prettyURL().length();
  119. int result;
  120. // Try wildcards
  121. if ( ! fileName.isEmpty() )
  122. {
  123. static TQStringList commonSuffixes = TQStringList::split (";", ".orig;.new;~;.bak;.BAK");
  124. if ((result = wildcardsFind(fileName)) != -1)
  125. return result;
  126. TQString backupSuffix = KateDocumentConfig::global()->backupSuffix();
  127. if (fileName.endsWith(backupSuffix)) {
  128. if ((result = wildcardsFind(fileName.left(length - backupSuffix.length()))) != -1)
  129. return result;
  130. }
  131. for (TQStringList::Iterator it = commonSuffixes.begin(); it != commonSuffixes.end(); ++it) {
  132. if (*it != backupSuffix && fileName.endsWith(*it)) {
  133. if ((result = wildcardsFind(fileName.left(length - (*it).length()))) != -1)
  134. return result;
  135. }
  136. }
  137. }
  138. // Even try the document name, if the URL is empty
  139. // This is usefull if the document name is set for example by a plugin which
  140. // created the document
  141. else if ( (result = wildcardsFind(doc->docName())) != -1)
  142. {
  143. kdDebug(13020)<<"KateFiletype::filetype(): got type "<<result<<" using docName '"<<doc->docName()<<"'"<<endl;
  144. return result;
  145. }
  146. // Try content-based mimetype
  147. KMimeType::Ptr mt = doc->mimeTypeForContent();
  148. TQPtrList<KateFileType> types;
  149. for (uint z=0; z < m_types.count(); z++)
  150. {
  151. if (m_types.at(z)->mimetypes.findIndex (mt->name()) > -1)
  152. types.append (m_types.at(z));
  153. }
  154. if ( !types.isEmpty() )
  155. {
  156. int pri = -1;
  157. int hl = -1;
  158. for (KateFileType *type = types.first(); type != 0L; type = types.next())
  159. {
  160. if (type->priority > pri)
  161. {
  162. pri = type->priority;
  163. hl = type->number;
  164. }
  165. }
  166. return hl;
  167. }
  168. return -1;
  169. }
  170. int KateFileTypeManager::wildcardsFind (const TQString &fileName)
  171. {
  172. TQPtrList<KateFileType> types;
  173. for (uint z=0; z < m_types.count(); z++)
  174. {
  175. for( TQStringList::Iterator it = m_types.at(z)->wildcards.begin(); it != m_types.at(z)->wildcards.end(); ++it )
  176. {
  177. // anders: we need to be sure to match the end of string, as eg a css file
  178. // would otherwise end up with the c hl
  179. TQRegExp re(*it, true, true);
  180. if ( ( re.search( fileName ) > -1 ) && ( re.matchedLength() == (int)fileName.length() ) )
  181. types.append (m_types.at(z));
  182. }
  183. }
  184. if ( !types.isEmpty() )
  185. {
  186. int pri = -1;
  187. int hl = -1;
  188. for (KateFileType *type = types.first(); type != 0L; type = types.next())
  189. {
  190. if (type->priority > pri)
  191. {
  192. pri = type->priority;
  193. hl = type->number;
  194. }
  195. }
  196. return hl;
  197. }
  198. return -1;
  199. }
  200. const KateFileType *KateFileTypeManager::fileType (uint number)
  201. {
  202. if (number < m_types.count())
  203. return m_types.at(number);
  204. return 0;
  205. }
  206. //END KateFileTypeManager
  207. //BEGIN KateFileTypeConfigTab
  208. KateFileTypeConfigTab::KateFileTypeConfigTab( TQWidget *parent )
  209. : KateConfigPage( parent )
  210. {
  211. m_types.setAutoDelete (true);
  212. m_lastType = 0;
  213. TQVBoxLayout *layout = new TQVBoxLayout(this, 0, KDialog::spacingHint() );
  214. // hl chooser
  215. TQHBox *hbHl = new TQHBox( this );
  216. layout->add (hbHl);
  217. hbHl->setSpacing( KDialog::spacingHint() );
  218. TQLabel *lHl = new TQLabel( i18n("&Filetype:"), hbHl );
  219. typeCombo = new TQComboBox( false, hbHl );
  220. lHl->setBuddy( typeCombo );
  221. connect( typeCombo, TQT_SIGNAL(activated(int)),
  222. this, TQT_SLOT(typeChanged(int)) );
  223. TQPushButton *btnnew = new TQPushButton( i18n("&New"), hbHl );
  224. connect( btnnew, TQT_SIGNAL(clicked()), this, TQT_SLOT(newType()) );
  225. btndel = new TQPushButton( i18n("&Delete"), hbHl );
  226. connect( btndel, TQT_SIGNAL(clicked()), this, TQT_SLOT(deleteType()) );
  227. gbProps = new TQGroupBox( 2, Qt::Horizontal, i18n("Properties"), this );
  228. layout->add (gbProps);
  229. // file & mime types
  230. TQLabel *lname = new TQLabel( i18n("N&ame:"), gbProps );
  231. name = new TQLineEdit( gbProps );
  232. lname->setBuddy( name );
  233. // file & mime types
  234. TQLabel *lsec = new TQLabel( i18n("&Section:"), gbProps );
  235. section = new TQLineEdit( gbProps );
  236. lsec->setBuddy( section );
  237. // file & mime types
  238. TQLabel *lvar = new TQLabel( i18n("&Variables:"), gbProps );
  239. varLine = new TQLineEdit( gbProps );
  240. lvar->setBuddy( varLine );
  241. // file & mime types
  242. TQLabel *lFileExts = new TQLabel( i18n("File e&xtensions:"), gbProps );
  243. wildcards = new TQLineEdit( gbProps );
  244. lFileExts->setBuddy( wildcards );
  245. TQLabel *lMimeTypes = new TQLabel( i18n("MIME &types:"), gbProps);
  246. TQHBox *hbMT = new TQHBox (gbProps);
  247. mimetypes = new TQLineEdit( hbMT );
  248. lMimeTypes->setBuddy( mimetypes );
  249. TQToolButton *btnMTW = new TQToolButton(hbMT);
  250. btnMTW->setIconSet(TQIconSet(SmallIcon("wizard")));
  251. connect(btnMTW, TQT_SIGNAL(clicked()), this, TQT_SLOT(showMTDlg()));
  252. TQLabel *lprio = new TQLabel( i18n("Prio&rity:"), gbProps);
  253. priority = new KIntNumInput( gbProps );
  254. lprio->setBuddy( priority );
  255. layout->addStretch();
  256. reload();
  257. connect( name, TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotChanged() ) );
  258. connect( section, TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotChanged() ) );
  259. connect( varLine, TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotChanged() ) );
  260. connect( wildcards, TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotChanged() ) );
  261. connect( mimetypes, TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotChanged() ) );
  262. connect( priority, TQT_SIGNAL( valueChanged ( int ) ), this, TQT_SLOT( slotChanged() ) );
  263. TQWhatsThis::add( btnnew, i18n("Create a new file type.") );
  264. TQWhatsThis::add( btndel, i18n("Delete the current file type.") );
  265. TQWhatsThis::add( name, i18n(
  266. "The name of the filetype will be the text of the corresponding menu item.") );
  267. TQWhatsThis::add( section, i18n(
  268. "The section name is used to organize the file types in menus.") );
  269. TQWhatsThis::add( varLine, i18n(
  270. "<p>This string allows you to configure Kate's settings for the files "
  271. "selected by this mimetype using Kate variables. You can set almost any "
  272. "configuration option, such as highlight, indent-mode, encoding, etc.</p>"
  273. "<p>For a full list of known variables, see the manual.</p>") );
  274. TQWhatsThis::add( wildcards, i18n(
  275. "The wildcards mask allows you to select files by filename. A typical "
  276. "mask uses an asterisk and the file extension, for example "
  277. "<code>*.txt; *.text</code>. The string is a semicolon-separated list "
  278. "of masks.") );
  279. TQWhatsThis::add( mimetypes, i18n(
  280. "The mime type mask allows you to select files by mimetype. The string is "
  281. "a semicolon-separated list of mimetypes, for example "
  282. "<code>text/plain; text/english</code>.") );
  283. TQWhatsThis::add( btnMTW, i18n(
  284. "Displays a wizard that helps you easily select mimetypes.") );
  285. TQWhatsThis::add( priority, i18n(
  286. "Sets a priority for this file type. If more than one file type selects the same "
  287. "file, the one with the highest priority will be used." ) );
  288. }
  289. void KateFileTypeConfigTab::apply()
  290. {
  291. if (!changed())
  292. return;
  293. save ();
  294. KateFactory::self()->fileTypeManager()->save(&m_types);
  295. }
  296. void KateFileTypeConfigTab::reload()
  297. {
  298. m_types.clear();
  299. for (uint z=0; z < KateFactory::self()->fileTypeManager()->list()->count(); z++)
  300. {
  301. KateFileType *type = new KateFileType ();
  302. *type = *KateFactory::self()->fileTypeManager()->list()->at(z);
  303. m_types.append (type);
  304. }
  305. update ();
  306. }
  307. void KateFileTypeConfigTab::reset()
  308. {
  309. reload ();
  310. }
  311. void KateFileTypeConfigTab::defaults()
  312. {
  313. reload ();
  314. }
  315. void KateFileTypeConfigTab::update ()
  316. {
  317. m_lastType = 0;
  318. typeCombo->clear ();
  319. for( uint i = 0; i < m_types.count(); i++) {
  320. if (m_types.at(i)->section.length() > 0)
  321. typeCombo->insertItem(m_types.at(i)->section + TQString ("/") + m_types.at(i)->name);
  322. else
  323. typeCombo->insertItem(m_types.at(i)->name);
  324. }
  325. typeCombo->setCurrentItem (0);
  326. typeChanged (0);
  327. typeCombo->setEnabled (typeCombo->count() > 0);
  328. }
  329. void KateFileTypeConfigTab::deleteType ()
  330. {
  331. int type = typeCombo->currentItem ();
  332. if ((type > -1) && ((uint)type < m_types.count()))
  333. {
  334. m_types.remove (type);
  335. update ();
  336. }
  337. }
  338. void KateFileTypeConfigTab::newType ()
  339. {
  340. TQString newN = i18n("New Filetype");
  341. for( uint i = 0; i < m_types.count(); i++) {
  342. if (m_types.at(i)->name == newN)
  343. {
  344. typeCombo->setCurrentItem (i);
  345. typeChanged (i);
  346. return;
  347. }
  348. }
  349. KateFileType *newT = new KateFileType ();
  350. newT->priority = 0;
  351. newT->name = newN;
  352. m_types.prepend (newT);
  353. update ();
  354. }
  355. void KateFileTypeConfigTab::save ()
  356. {
  357. if (m_lastType)
  358. {
  359. m_lastType->name = name->text ();
  360. m_lastType->section = section->text ();
  361. m_lastType->varLine = varLine->text ();
  362. m_lastType->wildcards = TQStringList::split (";", wildcards->text ());
  363. m_lastType->mimetypes = TQStringList::split (";", mimetypes->text ());
  364. m_lastType->priority = priority->value();
  365. }
  366. }
  367. void KateFileTypeConfigTab::typeChanged (int type)
  368. {
  369. save ();
  370. KateFileType *t = 0;
  371. if ((type > -1) && ((uint)type < m_types.count()))
  372. t = m_types.at(type);
  373. if (t)
  374. {
  375. gbProps->setTitle (i18n("Properties of %1").arg (typeCombo->currentText()));
  376. gbProps->setEnabled (true);
  377. btndel->setEnabled (true);
  378. name->setText(t->name);
  379. section->setText(t->section);
  380. varLine->setText(t->varLine);
  381. wildcards->setText(t->wildcards.join (";"));
  382. mimetypes->setText(t->mimetypes.join (";"));
  383. priority->setValue(t->priority);
  384. }
  385. else
  386. {
  387. gbProps->setTitle (i18n("Properties"));
  388. gbProps->setEnabled (false);
  389. btndel->setEnabled (false);
  390. name->clear();
  391. section->clear();
  392. varLine->clear();
  393. wildcards->clear();
  394. mimetypes->clear();
  395. priority->setValue(0);
  396. }
  397. m_lastType = t;
  398. }
  399. void KateFileTypeConfigTab::showMTDlg()
  400. {
  401. TQString text = i18n("Select the MimeTypes you want for this file type.\nPlease note that this will automatically edit the associated file extensions as well.");
  402. TQStringList list = TQStringList::split( TQRegExp("\\s*;\\s*"), mimetypes->text() );
  403. KMimeTypeChooserDialog d( i18n("Select Mime Types"), text, list, "text", this );
  404. if ( d.exec() == KDialogBase::Accepted ) {
  405. // do some checking, warn user if mime types or patterns are removed.
  406. // if the lists are empty, and the fields not, warn.
  407. wildcards->setText( d.chooser()->patterns().join(";") );
  408. mimetypes->setText( d.chooser()->mimeTypes().join(";") );
  409. }
  410. }
  411. //END KateFileTypeConfigTab
  412. //BEGIN KateViewFileTypeAction
  413. void KateViewFileTypeAction::init()
  414. {
  415. m_doc = 0;
  416. subMenus.setAutoDelete( true );
  417. popupMenu()->insertItem ( i18n("None"), this, TQT_SLOT(setType(int)), 0, 0);
  418. connect(popupMenu(),TQT_SIGNAL(aboutToShow()),this,TQT_SLOT(slotAboutToShow()));
  419. }
  420. void KateViewFileTypeAction::updateMenu (Kate::Document *doc)
  421. {
  422. m_doc = (KateDocument *)doc;
  423. }
  424. void KateViewFileTypeAction::slotAboutToShow()
  425. {
  426. KateDocument *doc=m_doc;
  427. int count = KateFactory::self()->fileTypeManager()->list()->count();
  428. for (int z=0; z<count; z++)
  429. {
  430. TQString hlName = KateFactory::self()->fileTypeManager()->list()->at(z)->name;
  431. TQString hlSection = KateFactory::self()->fileTypeManager()->list()->at(z)->section;
  432. if ( !hlSection.isEmpty() && (names.contains(hlName) < 1) )
  433. {
  434. if (subMenusName.contains(hlSection) < 1)
  435. {
  436. subMenusName << hlSection;
  437. TQPopupMenu *menu = new TQPopupMenu ();
  438. subMenus.append(menu);
  439. popupMenu()->insertItem (hlSection, menu);
  440. }
  441. int m = subMenusName.findIndex (hlSection);
  442. names << hlName;
  443. subMenus.at(m)->insertItem ( hlName, this, TQT_SLOT(setType(int)), 0, z+1);
  444. }
  445. else if (names.contains(hlName) < 1)
  446. {
  447. names << hlName;
  448. popupMenu()->insertItem ( hlName, this, TQT_SLOT(setType(int)), 0, z+1);
  449. }
  450. }
  451. if (!doc) return;
  452. for (uint i=0;i<subMenus.count();i++)
  453. {
  454. for (uint i2=0;i2<subMenus.at(i)->count();i2++)
  455. subMenus.at(i)->setItemChecked(subMenus.at(i)->idAt(i2),false);
  456. }
  457. popupMenu()->setItemChecked (0, false);
  458. if (doc->fileType() == -1)
  459. popupMenu()->setItemChecked (0, true);
  460. else
  461. {
  462. const KateFileType *t = 0;
  463. if ((t = KateFactory::self()->fileTypeManager()->fileType (doc->fileType())))
  464. {
  465. int i = subMenusName.findIndex (t->section);
  466. if (i >= 0 && subMenus.at(i))
  467. subMenus.at(i)->setItemChecked (doc->fileType()+1, true);
  468. else
  469. popupMenu()->setItemChecked (0, true);
  470. }
  471. }
  472. }
  473. void KateViewFileTypeAction::setType (int mode)
  474. {
  475. KateDocument *doc=m_doc;
  476. if (doc)
  477. doc->updateFileType(mode-1, true);
  478. }
  479. //END KateViewFileTypeAction
  480. // kate: space-indent on; indent-width 2; replace-tabs on;