KDevelop API Documentation

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.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:30 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003