• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Kate

katesyntaxdocument.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
00003    Copyright (C) 2000 Scott Manson <sdmanson@alltel.net>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "katesyntaxdocument.h"
00021 
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <unistd.h>
00025 #include <time.h>
00026 #include <sys/time.h>
00027 
00028 #include <kdebug.h>
00029 #include <kstandarddirs.h>
00030 #include <klocale.h>
00031 #include <kmessagebox.h>
00032 #include <kconfiggroup.h>
00033 
00034 #include <QtGui/QApplication>
00035 #include <QtCore/QFile>
00036 
00037 // use this to turn on over verbose debug output...
00038 #undef KSD_OVER_VERBOSE
00039 
00040 KateSyntaxDocument::KateSyntaxDocument(KConfig *config, bool force)
00041   : QDomDocument()
00042   , m_config (config)
00043 {
00044   // Let's build the Mode List (katesyntaxhighlightingrc)
00045   setupModeList(force);
00046 }
00047 
00048 KateSyntaxDocument::~KateSyntaxDocument()
00049 {
00050   for (int i=0; i < myModeList.size(); i++)
00051     delete myModeList[i];
00052 }
00053 
00058 bool KateSyntaxDocument::setIdentifier(const QString& identifier)
00059 {
00060   // if the current file is the same as the new one don't do anything.
00061   if(currentFile != identifier)
00062   {
00063     // let's open the new file
00064     QFile f( identifier );
00065 
00066     if ( f.open(QIODevice::ReadOnly) )
00067     {
00068       // Let's parse the contets of the xml file
00069       /* The result of this function should be check for robustness,
00070          a false returned means a parse error */
00071       QString errorMsg;
00072       int line, col;
00073       bool success=setContent(&f,&errorMsg,&line,&col);
00074 
00075       // Ok, now the current file is the pretended one (identifier)
00076       currentFile = identifier;
00077 
00078       // Close the file, is not longer needed
00079       f.close();
00080 
00081       if (!success)
00082       {
00083         KMessageBox::error(QApplication::activeWindow(),i18n("<qt>The error <b>%4</b><br /> has been detected in the file %1 at %2/%3</qt>", identifier,
00084              line, col, i18nc("QXml",errorMsg.toUtf8())));
00085         return false;
00086       }
00087     }
00088     else
00089     {
00090       // Oh o, we couldn't open the file.
00091       KMessageBox::error(QApplication::activeWindow(), i18n("Unable to open %1", identifier) );
00092       return false;
00093     }
00094   }
00095   return true;
00096 }
00097 
00101 bool KateSyntaxDocument::nextGroup( KateSyntaxContextData* data)
00102 {
00103   if(!data)
00104     return false;
00105 
00106   // No group yet so go to first child
00107   if (data->currentGroup.isNull())
00108   {
00109     // Skip over non-elements. So far non-elements are just comments
00110     QDomNode node = data->parent.firstChild();
00111     while (node.isComment())
00112       node = node.nextSibling();
00113 
00114     data->currentGroup = node.toElement();
00115   }
00116   else
00117   {
00118     // common case, iterate over siblings, skipping comments as we go
00119     QDomNode node = data->currentGroup.nextSibling();
00120     while (node.isComment())
00121       node = node.nextSibling();
00122 
00123     data->currentGroup = node.toElement();
00124   }
00125 
00126   return !data->currentGroup.isNull();
00127 }
00128 
00132 bool KateSyntaxDocument::nextItem( KateSyntaxContextData* data)
00133 {
00134   if(!data)
00135     return false;
00136 
00137   if (data->item.isNull())
00138   {
00139     QDomNode node = data->currentGroup.firstChild();
00140     while (node.isComment())
00141       node = node.nextSibling();
00142 
00143     data->item = node.toElement();
00144   }
00145   else
00146   {
00147     QDomNode node = data->item.nextSibling();
00148     while (node.isComment())
00149       node = node.nextSibling();
00150 
00151     data->item = node.toElement();
00152   }
00153 
00154   return !data->item.isNull();
00155 }
00156 
00160 QString KateSyntaxDocument::groupItemData( const KateSyntaxContextData* data, const QString& name){
00161   if(!data)
00162     return QString();
00163 
00164   // If there's no name just return the tag name of data->item
00165   if ( (!data->item.isNull()) && (name.isEmpty()))
00166   {
00167     return data->item.tagName();
00168   }
00169 
00170   // if name is not empty return the value of the attribute name
00171   if (!data->item.isNull())
00172   {
00173     return data->item.attribute(name);
00174   }
00175 
00176   return QString();
00177 
00178 }
00179 
00180 QString KateSyntaxDocument::groupData( const KateSyntaxContextData* data,const QString& name)
00181 {
00182   if(!data)
00183     return QString();
00184 
00185   if (!data->currentGroup.isNull())
00186   {
00187     return data->currentGroup.attribute(name);
00188   }
00189   else
00190   {
00191     return QString();
00192   }
00193 }
00194 
00195 void KateSyntaxDocument::freeGroupInfo( KateSyntaxContextData* data)
00196 {
00197   if (data)
00198     delete data;
00199 }
00200 
00201 KateSyntaxContextData* KateSyntaxDocument::getSubItems(KateSyntaxContextData* data)
00202 {
00203   KateSyntaxContextData *retval = new KateSyntaxContextData;
00204 
00205   if (data != 0)
00206   {
00207     retval->parent = data->currentGroup;
00208     retval->currentGroup = data->item;
00209   }
00210 
00211   return retval;
00212 }
00213 
00214 bool KateSyntaxDocument::getElement (QDomElement &element, const QString &mainGroupName, const QString &config)
00215 {
00216 #ifdef KSD_OVER_VERBOSE
00217   kDebug(13010) << "Looking for \"" << mainGroupName << "\" -> \"" << config << "\".";
00218 #endif
00219 
00220   QDomNodeList nodes = documentElement().childNodes();
00221 
00222   // Loop over all these child nodes looking for mainGroupName
00223   for (int i=0; i<nodes.count(); i++)
00224   {
00225     QDomElement elem = nodes.item(i).toElement();
00226     if (elem.tagName() == mainGroupName)
00227     {
00228       // Found mainGroupName ...
00229       QDomNodeList subNodes = elem.childNodes();
00230 
00231       // ... so now loop looking for config
00232       for (int j=0; j<subNodes.count(); j++)
00233       {
00234         QDomElement subElem = subNodes.item(j).toElement();
00235         if (subElem.tagName() == config)
00236         {
00237           // Found it!
00238           element = subElem;
00239           return true;
00240         }
00241       }
00242 
00243 #ifdef KSD_OVER_VERBOSE
00244       kDebug(13010) << "WARNING: \""<< config <<"\" wasn't found!";
00245 #endif
00246 
00247       return false;
00248     }
00249   }
00250 
00251 #ifdef KSD_OVER_VERBOSE
00252   kDebug(13010) << "WARNING: \""<< mainGroupName <<"\" wasn't found!";
00253 #endif
00254 
00255   return false;
00256 }
00257 
00262 KateSyntaxContextData* KateSyntaxDocument::getConfig(const QString& mainGroupName, const QString &config)
00263 {
00264   QDomElement element;
00265   if (getElement(element, mainGroupName, config))
00266   {
00267     KateSyntaxContextData *data = new KateSyntaxContextData;
00268     data->item = element;
00269     return data;
00270   }
00271   return 0;
00272 }
00273 
00278 KateSyntaxContextData* KateSyntaxDocument::getGroupInfo(const QString& mainGroupName, const QString &group)
00279 {
00280   QDomElement element;
00281   if (getElement(element, mainGroupName, group+'s'))
00282   {
00283     KateSyntaxContextData *data = new KateSyntaxContextData;
00284     data->parent = element;
00285     return data;
00286   }
00287   return 0;
00288 }
00289 
00293 QStringList& KateSyntaxDocument::finddata(const QString& mainGroup, const QString& type, bool clearList)
00294 {
00295 #ifdef KSD_OVER_VERBOSE
00296   kDebug(13010)<<"Create a list of keywords \""<<type<<"\" from \""<<mainGroup<<"\".";
00297 #endif
00298 
00299   if (clearList)
00300     m_data.clear();
00301 
00302   for(QDomNode node = documentElement().firstChild(); !node.isNull(); node = node.nextSibling())
00303   {
00304     QDomElement elem = node.toElement();
00305     if (elem.tagName() == mainGroup)
00306     {
00307 #ifdef KSD_OVER_VERBOSE
00308       kDebug(13010)<<"\""<<mainGroup<<"\" found.";
00309 #endif
00310 
00311       QDomNodeList nodelist1 = elem.elementsByTagName("list");
00312 
00313       for (int l=0; l<nodelist1.count(); l++)
00314       {
00315         if (nodelist1.item(l).toElement().attribute("name") == type)
00316         {
00317 #ifdef KSD_OVER_VERBOSE
00318           kDebug(13010)<<"List with attribute name=\""<<type<<"\" found.";
00319 #endif
00320           
00321           QDomNodeList childlist = nodelist1.item(l).toElement().childNodes();
00322 
00323           for (int i=0; i<childlist.count(); i++)
00324           {
00325             QString element = childlist.item(i).toElement().text().trimmed();
00326             if (element.isEmpty())
00327               continue;
00328 
00329 #ifdef KSD_OVER_VERBOSE
00330             if (i<6)
00331             {
00332               kDebug(13010)<<"\""<<element<<"\" added to the list \""<<type<<"\"";
00333             }
00334             else if(i==6)
00335             {
00336               kDebug(13010)<<"... The list continues ...";
00337             }
00338 #endif
00339 
00340             m_data += element;
00341           }
00342 
00343           break;
00344         }
00345       }
00346       break;
00347     }
00348   }
00349 
00350   return m_data;
00351 }
00352 
00353 // Private
00357 void KateSyntaxDocument::setupModeList (bool force)
00358 {
00359   // If there's something in myModeList the Mode List was already built so, don't do it again
00360   if (!myModeList.isEmpty())
00361     return;
00362 
00363   // We'll store the ModeList in katesyntaxhighlightingrc
00364   KConfigGroup generalConfig(m_config, "General");
00365 
00366   // figure our if the kate install is too new
00367   if (generalConfig.readEntry ("Version",0) > generalConfig.readEntry ("CachedVersion",0))
00368   {
00369     generalConfig.writeEntry ("CachedVersion", generalConfig.readEntry ("Version",0));
00370     force = true;
00371   }
00372 
00373   // Let's get a list of all the xml files for hl
00374   const QStringList list = KGlobal::dirs()->findAllResources("data","katepart/syntax/*.xml",
00375                                                        KStandardDirs::NoDuplicates);
00376 
00377   // Let's iterate through the list and build the Mode List
00378   for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
00379   {
00380     // Each file has a group called:
00381     QString Group="Cache "+ *it;
00382 
00383     // Let's go to this group
00384     KConfigGroup config(m_config, Group);
00385 
00386     // stat the file
00387     struct stat sbuf;
00388     memset (&sbuf, 0, sizeof(sbuf));
00389     stat(QFile::encodeName(*it), &sbuf);
00390 
00391     // If the group exist and we're not forced to read the xml file, let's build myModeList for katesyntax..rc
00392     if (!force && config.exists() && (sbuf.st_mtime == config.readEntry("lastModified",0)))
00393     {
00394       // Let's make a new KateSyntaxModeListItem to instert in myModeList from the information in katesyntax..rc
00395       KateSyntaxModeListItem *mli=new KateSyntaxModeListItem;
00396       mli->name       = config.readEntry("name");
00397       mli->nameTranslated = i18nc("Language",mli->name.toUtf8());
00398       mli->section    = i18nc("Language Section",config.readEntry("section").toUtf8());
00399       mli->mimetype   = config.readEntry("mimetype");
00400       mli->extension  = config.readEntry("extension");
00401       mli->version    = config.readEntry("version");
00402       mli->priority   = config.readEntry("priority");
00403       mli->style      = config.readEntry("style");
00404       mli->author    = config.readEntry("author");
00405       mli->license   = config.readEntry("license");
00406       mli->hidden   =  config.readEntry("hidden", false);
00407       mli->identifier = *it;
00408 
00409       // Apend the item to the list
00410       myModeList.append(mli);
00411     }
00412     else
00413     {
00414 #ifdef KSD_OVER_VERBOSE
00415       kDebug (13010) << "UPDATE hl cache for: " << *it;
00416 #endif
00417 
00418       // We're forced to read the xml files or the mode doesn't exist in the katesyntax...rc
00419       QFile f(*it);
00420 
00421       if (f.open(QIODevice::ReadOnly))
00422       {
00423         // Ok we opened the file, let's read the contents and close the file
00424         /* the return of setContent should be checked because a false return shows a parsing error */
00425         QString errMsg;
00426         int line, col;
00427 
00428         bool success = setContent(&f,&errMsg,&line,&col);
00429 
00430         f.close();
00431 
00432         if (success)
00433         {
00434           QDomElement root = documentElement();
00435 
00436           if (!root.isNull())
00437           {
00438             // If the 'first' tag is language, go on
00439             if (root.tagName()=="language")
00440             {
00441               // let's make the mode list item.
00442               KateSyntaxModeListItem *mli = new KateSyntaxModeListItem;
00443 
00444               mli->name      = root.attribute("name");
00445               mli->section   = root.attribute("section");
00446               mli->mimetype  = root.attribute("mimetype");
00447               mli->extension = root.attribute("extensions");
00448               mli->version   = root.attribute("version");
00449               mli->priority  = root.attribute("priority");
00450               mli->style     = root.attribute("style");
00451               mli->author    = root.attribute("author");
00452               mli->license   = root.attribute("license");
00453 
00454               QString hidden = root.attribute("hidden");
00455               mli->hidden    = (hidden == "true" || hidden == "TRUE");
00456 
00457               mli->identifier = *it;
00458 
00459               // Now let's write or overwrite (if force==true) the entry in katesyntax...rc
00460               config = KConfigGroup(m_config, Group);
00461               config.writeEntry("name",mli->name);
00462               config.writeEntry("section",mli->section);
00463               config.writeEntry("mimetype",mli->mimetype);
00464               config.writeEntry("extension",mli->extension);
00465               config.writeEntry("version",mli->version);
00466               config.writeEntry("priority",mli->priority);
00467               config.writeEntry("style",mli->style);
00468               config.writeEntry("author",mli->author);
00469               config.writeEntry("license",mli->license);
00470               config.writeEntry("hidden",mli->hidden);
00471 
00472               // modified time to keep cache in sync
00473               config.writeEntry("lastModified", int(sbuf.st_mtime));
00474 
00475               // Now that the data is in the config file, translate section
00476               mli->section    = i18nc("Language Section",mli->section.toUtf8());
00477               mli->nameTranslated = i18nc("Language",mli->name.toUtf8());
00478 
00479               // Append the new item to the list.
00480               myModeList.append(mli);
00481             }
00482           }
00483         }
00484         else
00485         {
00486           KateSyntaxModeListItem *emli=new KateSyntaxModeListItem;
00487 
00488           emli->section=i18n("Errors!");
00489           emli->mimetype="invalid_file/invalid_file";
00490           emli->extension="invalid_file.invalid_file";
00491           emli->version="1.";
00492           emli->name=QString ("Error: %1").arg(*it); // internal
00493           emli->nameTranslated=i18n("Error: %1", *it); // translated
00494           emli->identifier=(*it);
00495 
00496           myModeList.append(emli);
00497         }
00498       }
00499     }
00500   }
00501 
00502   // Synchronize with the file katesyntax...rc
00503   generalConfig.sync();
00504 }
00505 
00506 // kate: space-indent on; indent-width 2; replace-tabs on;

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal