KDevelop API Documentation

languages/cpp/subclassingdlg.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2002 by Jakob Simon-Gaarde * 00003 * jsgaarde@tdcspace.dk * 00004 * Copyright (C) 2003 by Alexander Dymo * 00005 * cloudtemple@mksat.net * 00006 * * 00007 * This program is free software; you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation; either version 2 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 ***************************************************************************/ 00013 00014 #include "subclassingdlg.h" 00015 #include "cppsupportpart.h" 00016 #include "backgroundparser.h" 00017 #include "store_walker.h" 00018 #include "cppsupportfactory.h" 00019 #include "kdevsourceformatter.h" 00020 #include "kdevproject.h" 00021 #include "filetemplate.h" 00022 #include "codemodel.h" 00023 00024 #include <qradiobutton.h> 00025 #include <qstringlist.h> 00026 #include <qcheckbox.h> 00027 #include <qmessagebox.h> 00028 #include <kfiledialog.h> 00029 #include <klineedit.h> 00030 #include <qpushbutton.h> 00031 #include <domutil.h> 00032 #include <qdom.h> 00033 #include <kstandarddirs.h> 00034 #include <kdebug.h> 00035 #include <klocale.h> 00036 #include <qfile.h> 00037 #include <qregexp.h> 00038 #include <kconfig.h> 00039 00040 00041 #define WIDGET_CAPTION_NAME "widget/property|name=caption/string" 00042 #define WIDGET_CLASS_NAME "class" 00043 #define WIDGET_SLOTS "slots" 00044 #define WIDGET_FUNCTIONS "functions" 00045 00046 // All widgets 00047 #define SLOT_ACCEPT SlotItem(m_slotView,"accept()","virtual","protected","void",false,true) 00048 #define SLOT_REJECT SlotItem(m_slotView,"reject()","virtual","protected","void",false,true) 00049 00050 // Wizards 00051 #define SLOT_BACK SlotItem(m_slotView,"back()","virtual","protected","void",false,true) 00052 #define SLOT_NEXT SlotItem(m_slotView,"next()","virtual","protected","void",false,true) 00053 #define SLOT_HELP SlotItem(m_slotView,"help()","virtual","protected","void",false,true) 00054 00055 00056 SlotItem::SlotItem(QListView *parent,const QString &methodName, 00057 const QString &specifier, 00058 const QString &access, const QString &returnType, 00059 bool isFunc,bool callBaseClass) 00060 : QCheckListItem(parent,methodName,QCheckListItem::CheckBox) 00061 { 00062 setOn(true); 00063 m_methodName = methodName; 00064 m_access = access.isEmpty() ? (const QString) "public" : access; 00065 m_specifier = specifier.isEmpty() ? (const QString) "virtual" : specifier; 00066 m_returnType = returnType.isEmpty() ? (const QString) "void" : returnType; 00067 m_isFunc = isFunc; 00068 m_callBaseClass = callBaseClass; 00069 setText(0,m_methodName); 00070 setText(1,m_access); 00071 setText(2,m_specifier); 00072 setText(3,m_returnType); 00073 setText(4,m_isFunc ? "Function" : "Slot"); 00074 if (m_access=="private" || 00075 m_specifier=="non virtual") 00076 { 00077 setOn(false); 00078 setEnabled(false); 00079 } 00080 if (m_specifier=="pure virtual") 00081 { 00082 setOn(true); 00083 setEnabled(false); 00084 } 00085 m_alreadyInSubclass = false; 00086 } 00087 00088 void SlotItem::setAllreadyInSubclass() 00089 { 00090 setOn(true); 00091 setEnabled(false); 00092 m_alreadyInSubclass = true; 00093 } 00094 00095 00096 SubclassingDlg::SubclassingDlg(CppSupportPart* cppSupport, const QString &formFile,QStringList &newFileNames, 00097 QWidget* parent, const char* name,bool modal, WFlags fl) 00098 : SubclassingDlgBase(parent,name,modal,fl), 00099 m_newFileNames(newFileNames), m_cppSupport( cppSupport ) 00100 //================================================= 00101 { 00102 m_formFile = formFile; 00103 readUiFile(); 00104 m_creatingNewSubclass = true; 00105 00106 KConfig *config = CppSupportFactory::instance()->config(); 00107 if (config) 00108 { 00109 config->setGroup("Subclassing"); 00110 reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0)); 00111 if (reformatDefault_box->isChecked()) 00112 reformat_box->setChecked(true); 00113 } 00114 } 00115 00116 00117 SubclassingDlg::SubclassingDlg(CppSupportPart* cppSupport, const QString &formFile,const QString &filename,QStringList &dummy, 00118 QWidget* parent, const char* name,bool modal, WFlags fl) 00119 : SubclassingDlgBase(parent,name,modal,fl), 00120 m_newFileNames(dummy), m_cppSupport( cppSupport ) 00121 //================================================= 00122 { 00123 m_formFile = formFile; 00124 m_creatingNewSubclass = false; 00125 m_filename = filename; 00126 00127 KConfig *config = CppSupportFactory::instance()->config(); 00128 if (config) 00129 { 00130 config->setGroup("Subclassing"); 00131 reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0)); 00132 if (reformatDefault_box->isChecked()) 00133 reformat_box->setChecked(true); 00134 } 00135 00136 QStringList pathsplit(QStringList::split('/',filename)); 00137 00138 QString baseClass = readBaseClassName(); 00139 if (!cppSupport->codeModel()->hasFile(filename+QString(".h"))) 00140 return; 00141 ClassList myClasses = cppSupport->codeModel()->fileByName(filename+QString(".h"))->classList(); 00142 for (ClassList::const_iterator classIt = myClasses.begin(); classIt != myClasses.end(); ++classIt) 00143 { 00144 kdDebug() << "base class " << baseClass << " class " << (*classIt)->name() 00145 << " parents " << (*classIt)->baseClassList().join(",") << endl; 00146 if ( (*classIt)->baseClassList().findIndex(baseClass) != -1 ) 00147 { 00148 kdDebug() << "base class matched " << endl; 00149 m_edClassName->setText((*classIt)->name()); 00150 m_edFileName->setText(pathsplit[pathsplit.count()-1]); 00151 00152 FunctionList functionList = (*classIt)->functionList(); 00153 for (FunctionList::const_iterator methodIt = functionList.begin(); 00154 methodIt != functionList.end(); ++methodIt) 00155 { 00156 m_parsedMethods << (*methodIt)->name() + "("; 00157 } 00158 } 00159 } 00160 readUiFile(); 00161 m_btnOk->setEnabled(true); 00162 } 00163 00164 bool SubclassingDlg::alreadyInSubclass(const QString &method) 00165 { 00166 for (uint i=0;i<m_parsedMethods.count();i++) 00167 if (method.find(m_parsedMethods[i])==0) 00168 return true; 00169 return false; 00170 } 00171 00172 void SubclassingDlg::readUiFile() 00173 { 00174 QStringList splitPath = QStringList::split('/',m_formFile); 00175 m_formName = QStringList::split('.',splitPath[splitPath.count()-1])[0]; // "somedlg.ui" = "somedlg" 00176 splitPath.pop_back(); 00177 m_formPath = "/" + splitPath.join("/"); // join path to ui-file 00178 00179 m_btnOk->setEnabled(false); 00180 QDomDocument doc; 00181 00182 DomUtil::openDOMFile(doc,m_formFile); 00183 m_baseClassName = DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text(); 00184 00185 m_baseCaption = DomUtil::elementByPathExt(doc,WIDGET_CAPTION_NAME).text(); 00186 setCaption(i18n("Create Subclass of ")+m_baseClassName); 00187 00188 // Special widget specific slots 00189 SlotItem *newSlot; 00190 m_qtBaseClassName = DomUtil::elementByPathExt(doc,"widget").attribute("class","QDialog"); 00191 00192 if ( (m_qtBaseClassName=="QMainWindow") || (m_qtBaseClassName=="QWidget") ) 00193 m_canBeModal = false; 00194 else 00195 m_canBeModal = true; 00196 if (m_qtBaseClassName != "QWidget") 00197 { 00198 newSlot = new SLOT_ACCEPT; 00199 newSlot->setOn(false); 00200 if (alreadyInSubclass("accept()")) 00201 newSlot->setAllreadyInSubclass(); 00202 m_slotView->insertItem(newSlot); 00203 m_slots << newSlot; 00204 00205 newSlot = new SLOT_REJECT; 00206 newSlot->setOn(false); 00207 if (alreadyInSubclass("reject()")) 00208 newSlot->setAllreadyInSubclass(); 00209 m_slotView->insertItem(newSlot); 00210 m_slots << newSlot; 00211 } 00212 00213 if (m_qtBaseClassName == "QWizard") 00214 { 00215 newSlot = new SLOT_NEXT; 00216 m_slotView->insertItem(newSlot); 00217 if (alreadyInSubclass("next()")) 00218 newSlot->setAllreadyInSubclass(); 00219 m_slots << newSlot; 00220 newSlot = new SLOT_BACK; 00221 m_slotView->insertItem(newSlot); 00222 if (alreadyInSubclass("back()")) 00223 newSlot->setAllreadyInSubclass(); 00224 m_slots << newSlot; 00225 newSlot = new SLOT_HELP; 00226 newSlot->setOn(false); 00227 if (alreadyInSubclass("help()")) 00228 newSlot->setAllreadyInSubclass(); 00229 m_slotView->insertItem(newSlot); 00230 m_slots << newSlot; 00231 } 00232 00233 QDomElement slotsElem = DomUtil::elementByPathExt(doc,WIDGET_SLOTS); 00234 QDomNodeList slotnodes = slotsElem.childNodes(); 00235 00236 for (unsigned int i=0; i<slotnodes.count();i++) 00237 { 00238 QDomElement slotelem = slotnodes.item(i).toElement(); 00239 newSlot = new SlotItem(m_slotView,slotelem.text(), 00240 slotelem.attributeNode("specifier").value(), 00241 slotelem.attributeNode("access").value(), 00242 slotelem.attributeNode("returnType").value(),false); 00243 m_slotView->insertItem(newSlot); 00244 if (alreadyInSubclass(slotelem.text())) 00245 newSlot->setAllreadyInSubclass(); 00246 m_slots << newSlot; 00247 } 00248 00249 QDomElement funcsElem = DomUtil::elementByPathExt(doc,WIDGET_FUNCTIONS); 00250 QDomNodeList funcnodes = funcsElem.childNodes(); 00251 SlotItem *newFunc; 00252 for (unsigned int i=0; i<funcnodes.count();i++) 00253 { 00254 QDomElement funcelem = funcnodes.item(i).toElement(); 00255 newFunc = new SlotItem(m_slotView,funcelem.text(), 00256 funcelem.attributeNode("specifier").value(), 00257 funcelem.attributeNode("access").value(), 00258 funcelem.attributeNode("returnType").value(),true); 00259 m_slotView->insertItem(newFunc); 00260 if (alreadyInSubclass(funcelem.text())) 00261 newFunc->setAllreadyInSubclass(); 00262 m_slots << newFunc; 00263 } 00264 } 00265 00266 SubclassingDlg::~SubclassingDlg() 00267 //=============================== 00268 { 00269 } 00270 00271 00272 void SubclassingDlg::updateDlg() 00273 //============================== 00274 { 00275 } 00276 00277 void SubclassingDlg::replace(QString &string, const QString& search, const QString& replace) 00278 //========================================================================================== 00279 { 00280 int nextPos = string.find(search); 00281 unsigned int searchLength = search.length(); 00282 while (nextPos>-1) 00283 { 00284 string = string.replace(nextPos,searchLength,replace); 00285 nextPos = string.find(search,nextPos+replace.length()); 00286 } 00287 } 00288 00289 bool SubclassingDlg::loadBuffer(QString &buffer, const QString& filename) 00290 //====================================================================== 00291 { 00292 // open file and buffer it 00293 QFile dataFile(filename); 00294 if (!dataFile.open(IO_ReadOnly)) 00295 return false; 00296 char *temp = new char[dataFile.size()+1]; 00297 dataFile.readBlock(temp,dataFile.size()); 00298 temp[dataFile.size()]='\0'; 00299 buffer = temp; 00300 delete temp; 00301 dataFile.close(); 00302 return true; 00303 } 00304 00305 bool SubclassingDlg::replaceKeywords(QString &buffer,bool canBeModal) 00306 //=================================================================== 00307 { 00308 replace(buffer,"$NEWFILENAMEUC$",m_edFileName->text().upper()); 00309 replace(buffer,"$BASEFILENAMELC$",m_formName.lower()); 00310 replace(buffer,"$BASEFILENAME$",m_formName); 00311 replace(buffer,"$NEWCLASS$",m_edClassName->text()); 00312 replace(buffer,"$BASECLASS$",m_baseClassName); 00313 replace(buffer,"$NEWFILENAMELC$",m_edFileName->text().lower()); 00314 if (canBeModal) 00315 { 00316 replace(buffer,"$CAN_BE_MODAL_H$",", bool modal = FALSE"); 00317 replace(buffer,"$CAN_BE_MODAL_CPP1$",", bool modal"); 00318 replace(buffer,"$CAN_BE_MODAL_CPP2$",", modal"); 00319 } 00320 else 00321 { 00322 replace(buffer,"$CAN_BE_MODAL_H$",""); 00323 replace(buffer,"$CAN_BE_MODAL_CPP1$",""); 00324 replace(buffer,"$CAN_BE_MODAL_CPP2$",""); 00325 } 00326 00327 return true; 00328 } 00329 00330 bool SubclassingDlg::saveBuffer(QString &buffer, const QString& filename) 00331 //======================================================================= 00332 { 00333 // save buffer 00334 00335 QFile dataFile(filename); 00336 if (!dataFile.open(IO_WriteOnly | IO_Truncate)) 00337 return false; 00338 dataFile.writeBlock((buffer+"\n").ascii(),(buffer+"\n").length()); 00339 dataFile.close(); 00340 return true; 00341 } 00342 00343 00344 void SubclassingDlg::accept() 00345 //=========================== 00346 { 00347 KConfig *config = CppSupportFactory::instance()->config(); 00348 if (config) 00349 { 00350 config->setGroup("Subclassing"); 00351 config->writeEntry("Reformat Source", reformatDefault_box->isChecked()); 00352 } 00353 00354 unsigned int i; 00355 00356 // h - file 00357 00358 QString public_slot = 00359 "/*$PUBLIC_SLOTS$*/\n "; 00360 00361 QString protected_slot = 00362 "/*$PROTECTED_SLOTS$*/\n "; 00363 00364 QString public_func = 00365 "/*$PUBLIC_FUNCTIONS$*/\n "; 00366 00367 QString protected_func = 00368 "/*$PROTECTED_FUNCTIONS$*/\n "; 00369 00370 QString buffer; 00371 if (m_creatingNewSubclass) 00372 { 00373 loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_template.h")); 00374 buffer = FileTemplate::read(m_cppSupport, "h") + buffer; 00375 QFileInfo fi(m_filename + ".h"); 00376 QString module = fi.baseName(); 00377 QString basefilename = fi.baseName(true); 00378 buffer.replace(QRegExp("\\$MODULE\\$"),module); 00379 buffer.replace(QRegExp("\\$FILENAME\\$"),basefilename); 00380 } 00381 else 00382 loadBuffer(buffer,m_filename+".h"); 00383 replaceKeywords(buffer,m_canBeModal); 00384 for (i=0; i<m_slots.count(); i++) 00385 { 00386 SlotItem *slitem = m_slots[i]; 00387 if (!slitem->isOn() || 00388 slitem->m_alreadyInSubclass) 00389 continue; 00390 QString declBuild; 00391 if (slitem->m_access=="public") 00392 if (!slitem->m_isFunc) 00393 declBuild = public_slot; 00394 else 00395 declBuild = public_func; 00396 if (slitem->m_access=="protected") 00397 if (!slitem->m_isFunc) 00398 declBuild = protected_slot; 00399 else 00400 declBuild = protected_func; 00401 if (!(slitem->m_specifier=="non virtual")) 00402 declBuild += "virtual "; 00403 declBuild += slitem->m_returnType + " "; 00404 QString spacer; 00405 if (slitem->m_access=="public") 00406 { 00407 if (!slitem->m_isFunc) 00408 { 00409 declBuild += spacer.fill(' ',43-declBuild.length()) + slitem->m_methodName + ";"; 00410 replace(buffer,"/*$PUBLIC_SLOTS$*/",declBuild); 00411 } 00412 else 00413 { 00414 declBuild += spacer.fill(' ',47-declBuild.length()) + slitem->m_methodName + ";"; 00415 replace(buffer,"/*$PUBLIC_FUNCTIONS$*/",declBuild); 00416 } 00417 } 00418 if (slitem->m_access=="protected") 00419 { 00420 if (!slitem->m_isFunc) 00421 { 00422 declBuild += spacer.fill(' ',46-declBuild.length()) + slitem->m_methodName + ";"; 00423 replace(buffer,"/*$PROTECTED_SLOTS$*/",declBuild); 00424 } 00425 else 00426 { 00427 declBuild += spacer.fill(' ',50-declBuild.length()) + slitem->m_methodName + ";"; 00428 replace(buffer,"/*$PROTECTED_FUNCTIONS$*/",declBuild); 00429 } 00430 } 00431 } 00432 00433 if (reformat_box->isChecked()) 00434 buffer = m_cppSupport->sourceFormatter()->formatSource(buffer); 00435 00436 if (m_creatingNewSubclass) 00437 saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".h"); 00438 else 00439 saveBuffer(buffer,m_filename+".h"); 00440 00441 // cpp - file 00442 00443 QString implementation = 00444 "/*$SPECIALIZATION$*/\n" 00445 "$RETURNTYPE$ $NEWCLASS$::$METHOD$\n" 00446 "{\n" 00447 "}\n"; 00448 00449 QString implementation_callbase = 00450 "/*$SPECIALIZATION$*/\n" 00451 "$RETURNTYPE$ $NEWCLASS$::$METHOD$\n" 00452 "{\n" 00453 " $QTBASECLASS$::$METHOD$;\n" 00454 "}\n"; 00455 00456 00457 if (m_creatingNewSubclass) 00458 { 00459 loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_template.cpp")); 00460 buffer = FileTemplate::read(m_cppSupport, "cpp") + buffer; 00461 QFileInfo fi(m_filename + ".cpp"); 00462 QString module = fi.baseName(); 00463 QString basefilename = fi.baseName(true); 00464 buffer.replace(QRegExp("\\$MODULE\\$"),module); 00465 buffer.replace(QRegExp("\\$FILENAME\\$"),basefilename); 00466 if ( (m_cppSupport->project()) && (m_cppSupport->project()->options() & KDevProject::UsesAutotoolsBuildSystem)) 00467 { 00468 buffer += "\n#include \"$NEWFILENAMELC$.moc\"\n"; 00469 } 00470 } 00471 else 00472 loadBuffer(buffer,m_filename+".cpp"); 00473 replaceKeywords(buffer,m_canBeModal); 00474 for (i=0; i<m_slots.count(); i++) 00475 { 00476 SlotItem *slitem = m_slots[i]; 00477 if (!slitem->isOn() || 00478 slitem->m_alreadyInSubclass) 00479 continue; 00480 QString impl = slitem->m_callBaseClass ? implementation_callbase : implementation; 00481 replace(impl,"$RETURNTYPE$",slitem->m_returnType); 00482 replace(impl,"$NEWCLASS$",m_edClassName->text()); 00483 replace(impl,"$METHOD$", slitem->m_methodName); 00484 replace(impl,"$QTBASECLASS$", m_qtBaseClassName); 00485 replace(buffer,"/*$SPECIALIZATION$*/",impl); 00486 } 00487 00488 if (reformat_box->isChecked()) 00489 buffer = m_cppSupport->sourceFormatter()->formatSource(buffer); 00490 00491 if (m_creatingNewSubclass) 00492 saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".cpp"); 00493 else 00494 saveBuffer(buffer,m_filename+".cpp"); 00495 00496 if (m_creatingNewSubclass) 00497 { 00498 m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".cpp"); 00499 m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".h"); 00500 } 00501 SubclassingDlgBase::accept(); 00502 } 00503 00504 void SubclassingDlg::onChangedClassName() 00505 //======================================= 00506 { 00507 m_edFileName->setText(m_edClassName->text().lower()); 00508 if (m_edFileName->text().isEmpty() || 00509 m_edClassName->text().isEmpty()) 00510 m_btnOk->setEnabled(false); 00511 else 00512 m_btnOk->setEnabled(true); 00513 } 00514 00515 QString SubclassingDlg::readBaseClassName( ) 00516 { 00517 QDomDocument doc; 00518 DomUtil::openDOMFile(doc,m_formFile); 00519 return DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text(); 00520 }
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:43 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003