kate Library API Documentation

katesyntaxdocument.cpp

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., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include "katesyntaxdocument.h" 00021 00022 #include <kdebug.h> 00023 #include <kstandarddirs.h> 00024 #include <klocale.h> 00025 #include <kmessagebox.h> 00026 #include <kconfig.h> 00027 00028 #include <qfile.h> 00029 00033 SyntaxDocument::SyntaxDocument(bool force) 00034 : QDomDocument() 00035 { 00036 // Let's build the Mode List (katesyntaxhighlightingrc) 00037 setupModeList(force); 00038 myModeList.setAutoDelete( true ); 00039 } 00040 00044 SyntaxDocument::~SyntaxDocument() 00045 { 00046 } 00047 00052 bool SyntaxDocument::setIdentifier(const QString& identifier) 00053 { 00054 // if the current file is the same as the new one don't do anything. 00055 if(currentFile != identifier) 00056 { 00057 // let's open the new file 00058 QFile f( identifier ); 00059 00060 if ( f.open(IO_ReadOnly) ) 00061 { 00062 // Let's parse the contets of the xml file 00063 /* The result of this function should be check for robustness, 00064 a false returned means a parse error */ 00065 QString errorMsg; 00066 int line, col; 00067 bool success=setContent(&f,&errorMsg,&line,&col); 00068 00069 // Ok, now the current file is the pretended one (identifier) 00070 currentFile = identifier; 00071 00072 // Close the file, is not longer needed 00073 f.close(); 00074 00075 if (!success) 00076 { 00077 KMessageBox::error(0L,i18n("<qt>The error <b>%4</b><br> has been detected in the file %1 at %2/%3</qt>").arg(identifier) 00078 .arg(line).arg(col).arg(i18n("QXml",errorMsg.utf8()))); 00079 return false; 00080 } 00081 } 00082 else 00083 { 00084 // Oh o, we couldn't open the file. 00085 KMessageBox::error( 0L, i18n("Unable to open %1").arg(identifier) ); 00086 return false; 00087 } 00088 } 00089 return true; 00090 } 00091 00094 SyntaxModeList SyntaxDocument::modeList() 00095 { 00096 return myModeList; 00097 } 00098 00102 bool SyntaxDocument::nextGroup( syntaxContextData* data) 00103 { 00104 if(!data) 00105 return false; 00106 00107 // No group yet so go to first child 00108 if (data->currentGroup.isNull()) 00109 { 00110 // Skip over non-elements. So far non-elements are just comments 00111 QDomNode node = data->parent.firstChild(); 00112 while (node.isComment()) 00113 node = node.nextSibling(); 00114 00115 data->currentGroup = node.toElement(); 00116 } 00117 else 00118 { 00119 // common case, iterate over siblings, skipping comments as we go 00120 QDomNode node = data->currentGroup.nextSibling(); 00121 while (node.isComment()) 00122 node = node.nextSibling(); 00123 00124 data->currentGroup = node.toElement(); 00125 } 00126 00127 return !data->currentGroup.isNull(); 00128 } 00129 00133 bool SyntaxDocument::nextItem( syntaxContextData* data) 00134 { 00135 if(!data) 00136 return false; 00137 00138 if (data->item.isNull()) 00139 { 00140 QDomNode node = data->currentGroup.firstChild(); 00141 while (node.isComment()) 00142 node = node.nextSibling(); 00143 00144 data->item = node.toElement(); 00145 } 00146 else 00147 { 00148 QDomNode node = data->item.nextSibling(); 00149 while (node.isComment()) 00150 node = node.nextSibling(); 00151 00152 data->item = node.toElement(); 00153 } 00154 00155 return !data->item.isNull(); 00156 } 00157 00161 QString SyntaxDocument::groupItemData( const syntaxContextData* data, const QString& name){ 00162 if(!data) 00163 return QString::null; 00164 00165 // If there's no name just return the tag name of data->item 00166 if ( (!data->item.isNull()) && (name.isEmpty())) 00167 { 00168 return data->item.tagName(); 00169 } 00170 00171 // if name is not empty return the value of the attribute name 00172 if (!data->item.isNull()) 00173 { 00174 return data->item.attribute(name); 00175 } 00176 00177 return QString::null; 00178 00179 } 00180 00181 QString SyntaxDocument::groupData( const syntaxContextData* data,const QString& name) 00182 { 00183 if(!data) 00184 return QString::null; 00185 00186 if (!data->currentGroup.isNull()) 00187 { 00188 return data->currentGroup.attribute(name); 00189 } 00190 else 00191 { 00192 return QString::null; 00193 } 00194 } 00195 00196 void SyntaxDocument::freeGroupInfo( syntaxContextData* data) 00197 { 00198 if (data) 00199 delete data; 00200 } 00201 00202 syntaxContextData* SyntaxDocument::getSubItems(syntaxContextData* data) 00203 { 00204 syntaxContextData *retval = new syntaxContextData; 00205 00206 if (data != 0) 00207 { 00208 retval->parent = data->currentGroup; 00209 retval->currentGroup = data->item; 00210 } 00211 00212 return retval; 00213 } 00214 00215 bool SyntaxDocument::getElement (QDomElement &element, const QString &mainGroupName, const QString &config) 00216 { 00217 kdDebug(13010) << "Looking for \"" << mainGroupName << "\" -> \"" << config << "\"." << endl; 00218 00219 QDomNodeList nodes = documentElement().childNodes(); 00220 00221 // Loop over all these child nodes looking for mainGroupName 00222 for (unsigned int i=0; i<nodes.count(); i++) 00223 { 00224 QDomElement elem = nodes.item(i).toElement(); 00225 if (elem.tagName() == mainGroupName) 00226 { 00227 // Found mainGroupName ... 00228 QDomNodeList subNodes = elem.childNodes(); 00229 00230 // ... so now loop looking for config 00231 for (unsigned int j=0; j<subNodes.count(); j++) 00232 { 00233 QDomElement subElem = subNodes.item(j).toElement(); 00234 if (subElem.tagName() == config) 00235 { 00236 // Found it! 00237 element = subElem; 00238 return true; 00239 } 00240 } 00241 00242 kdDebug(13010) << "WARNING: \""<< config <<"\" wasn't found!" << endl; 00243 return false; 00244 } 00245 } 00246 00247 kdDebug(13010) << "WARNING: \""<< mainGroupName <<"\" wasn't found!" << endl; 00248 return false; 00249 } 00250 00255 syntaxContextData* SyntaxDocument::getConfig(const QString& mainGroupName, const QString &config) 00256 { 00257 QDomElement element; 00258 if (getElement(element, mainGroupName, config)) 00259 { 00260 syntaxContextData *data = new syntaxContextData; 00261 data->item = element; 00262 return data; 00263 } 00264 return 0; 00265 } 00266 00271 syntaxContextData* SyntaxDocument::getGroupInfo(const QString& mainGroupName, const QString &group) 00272 { 00273 QDomElement element; 00274 if (getElement(element, mainGroupName, group+"s")) 00275 { 00276 syntaxContextData *data = new syntaxContextData; 00277 data->parent = element; 00278 return data; 00279 } 00280 return 0; 00281 } 00282 00286 QStringList& SyntaxDocument::finddata(const QString& mainGroup, const QString& type, bool clearList) 00287 { 00288 kdDebug(13010)<<"Create a list of keywords \""<<type<<"\" from \""<<mainGroup<<"\"."<<endl; 00289 if (clearList) 00290 m_data.clear(); 00291 00292 for(QDomNode node = documentElement().firstChild(); !node.isNull(); node = node.nextSibling()) 00293 { 00294 QDomElement elem = node.toElement(); 00295 if (elem.tagName() == mainGroup) 00296 { 00297 kdDebug(13010)<<"\""<<mainGroup<<"\" found."<<endl; 00298 QDomNodeList nodelist1 = elem.elementsByTagName("list"); 00299 00300 for (uint l=0; l<nodelist1.count(); l++) 00301 { 00302 if (nodelist1.item(l).toElement().attribute("name") == type) 00303 { 00304 kdDebug(13010)<<"List with attribute name=\""<<type<<"\" found."<<endl; 00305 QDomNodeList childlist = nodelist1.item(l).toElement().childNodes(); 00306 00307 for (uint i=0; i<childlist.count(); i++) 00308 { 00309 QString element = childlist.item(i).toElement().text().stripWhiteSpace(); 00310 if (element.isEmpty()) 00311 continue; 00312 #ifndef NDEBUG 00313 if (i<6) 00314 { 00315 kdDebug(13010)<<"\""<<element<<"\" added to the list \""<<type<<"\""<<endl; 00316 } 00317 else if(i==6) 00318 { 00319 kdDebug(13010)<<"... The list continues ..."<<endl; 00320 } 00321 #endif 00322 m_data += element; 00323 } 00324 00325 break; 00326 } 00327 } 00328 break; 00329 } 00330 } 00331 00332 return m_data; 00333 } 00334 00335 // Private 00339 void SyntaxDocument::setupModeList (bool force) 00340 { 00341 // If there's something in myModeList the Mode List was already built so, don't do it again 00342 if (!myModeList.isEmpty()) 00343 return; 00344 00345 // We'll store the ModeList in katesyntaxhighlightingrc 00346 KConfig config("katesyntaxhighlightingrc", false, false); 00347 00348 // figure our if the kate install is too new 00349 config.setGroup ("General"); 00350 if (config.readNumEntry ("Version") > config.readNumEntry ("CachedVersion")) 00351 { 00352 config.writeEntry ("CachedVersion", config.readNumEntry ("Version")); 00353 force = true; 00354 } 00355 00356 // Let's get a list of all the xml files for hl 00357 QStringList list = KGlobal::dirs()->findAllResources("data","katepart/syntax/*.xml",false,true); 00358 00359 // Let's iterate through the list and build the Mode List 00360 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) 00361 { 00362 // Each file has a group called: 00363 QString Group="Cache "+*it; 00364 00365 // If the group exist and we're not forced to read the xml file, let's build myModeList for katesyntax..rc 00366 if ((config.hasGroup(Group)) && (!force)) 00367 { 00368 // Let's go to this group 00369 config.setGroup(Group); 00370 00371 // Let's make a new syntaxModeListItem to instert in myModeList from the information in katesyntax..rc 00372 syntaxModeListItem *mli=new syntaxModeListItem; 00373 mli->name = config.readEntry("name"); // ### TODO: translation (bug #72220) 00374 mli->section = i18n("Language Section",config.readEntry("section").utf8()); 00375 mli->mimetype = config.readEntry("mimetype"); 00376 mli->extension = config.readEntry("extension"); 00377 mli->version = config.readEntry("version"); 00378 mli->priority = config.readEntry("priority"); 00379 mli->identifier = *it; 00380 00381 // Apend the item to the list 00382 myModeList.append(mli); 00383 } 00384 else 00385 { 00386 // We're forced to read the xml files or the mode doesn't exist in the katesyntax...rc 00387 QFile f(*it); 00388 00389 if (f.open(IO_ReadOnly)) 00390 { 00391 // Ok we opened the file, let's read the contents and close the file 00392 /* the return of setContent should be checked because a false return shows a parsing error */ 00393 QString errMsg; 00394 int line, col; 00395 00396 bool success = setContent(&f,&errMsg,&line,&col); 00397 00398 f.close(); 00399 00400 if (success) 00401 { 00402 QDomElement root = documentElement(); 00403 00404 if (!root.isNull()) 00405 { 00406 // If the 'first' tag is language, go on 00407 if (root.tagName()=="language") 00408 { 00409 // let's make the mode list item. 00410 syntaxModeListItem *mli = new syntaxModeListItem; 00411 00412 mli->name = root.attribute("name"); 00413 mli->section = root.attribute("section"); 00414 mli->mimetype = root.attribute("mimetype"); 00415 mli->extension = root.attribute("extensions"); 00416 mli->version = root.attribute("version"); 00417 mli->priority = root.attribute("priority"); 00418 00419 mli->identifier = *it; 00420 00421 // Now let's write or overwrite (if force==true) the entry in katesyntax...rc 00422 config.setGroup(Group); 00423 config.writeEntry("name",mli->name); 00424 if (mli->section.isEmpty()) // ### TODO: can this happen at all? 00425 config.writeEntry("section","Other"); 00426 else 00427 config.writeEntry("section",mli->section); 00428 config.writeEntry("mimetype",mli->mimetype); 00429 config.writeEntry("extension",mli->extension); 00430 config.writeEntry("version",mli->version); 00431 config.writeEntry("priority",mli->priority); 00432 00433 // Now that the data is in the config file, translate section 00434 if (mli->section.isEmpty()) // ### TODO: can this happen at all? 00435 mli->section = i18n("Language Section",mli->section.utf8()); 00436 else 00437 mli->section = i18n("Language Section","Other"); // We need the i18n context for when reading again the config 00438 00439 // Append the new item to the list. 00440 myModeList.append(mli); 00441 } 00442 } 00443 } 00444 else 00445 { 00446 syntaxModeListItem *emli=new syntaxModeListItem; 00447 00448 emli->section=i18n("Errors!"); 00449 emli->mimetype="invalid_file/invalid_file"; 00450 emli->extension="invalid_file.invalid_file"; 00451 emli->version="1."; 00452 emli->name=i18n("Error: %1").arg(*it); 00453 emli->identifier=(*it); 00454 00455 myModeList.append(emli); 00456 } 00457 } 00458 } 00459 } 00460 // Syncronize with the file katesyntax...rc 00461 config.sync(); 00462 } 00463 00464 // 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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:16:26 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003