/*************************************************************************** * Copyright (C) 2002 by Jakob Simon-Gaarde * * jsgaarde@tdcspace.dk * * Copyright (C) 2003 by Alexander Dymo * * cloudtemple@mksat.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "subclassingdlg.h" #include "cppsupportpart.h" #include "backgroundparser.h" #include "store_walker.h" #include "cppsupportfactory.h" #include "kdevsourceformatter.h" #include "kdevapi.h" #include "kdevproject.h" #include "filetemplate.h" #include "codemodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WIDGET_CAPTION_NAME "widget/property|name=caption/string" #define WIDGET_CLASS_NAME "class" #define WIDGET_SLOTS "slots" #define WIDGET_FUNCTIONS "functions" // All widgets #define SLOT_ACCEPT SlotItem(m_slotView,"accept()","virtual","protected","void",false,true) #define SLOT_REJECT SlotItem(m_slotView,"reject()","virtual","protected","void",false,true) // Wizards #define SLOT_BACK SlotItem(m_slotView,"back()","virtual","protected","void",false,true) #define SLOT_NEXT SlotItem(m_slotView,"next()","virtual","protected","void",false,true) #define SLOT_HELP SlotItem(m_slotView,"help()","virtual","protected","void",false,true) SlotItem::SlotItem(TQListView *parent,const TQString &methodName, const TQString &specifier, const TQString &access, const TQString &returnType, bool isFunc,bool callBaseClass) : TQCheckListItem(parent,methodName,TQCheckListItem::CheckBox) { setOn(true); m_methodName = methodName; m_access = access.isEmpty() ? (const TQString) "public" : access; m_specifier = specifier.isEmpty() ? (const TQString) "virtual" : specifier; m_returnType = returnType.isEmpty() ? (const TQString) "void" : returnType; m_isFunc = isFunc; m_callBaseClass = callBaseClass; setText(0,m_methodName); setText(1,m_access); setText(2,m_specifier); setText(3,m_returnType); setText(4,m_isFunc ? "Function" : "Slot"); if (m_access=="private" || m_specifier=="non virtual") { setOn(false); setEnabled(false); } if (m_specifier=="pure virtual") { setOn(true); setEnabled(false); } m_alreadyInSubclass = false; } void SlotItem::setAllreadyInSubclass() { setOn(true); setEnabled(false); m_alreadyInSubclass = true; } SubclassingDlg::SubclassingDlg(CppSupportPart* cppSupport, const TQString &formFile, TQStringList &newFileNames, TQWidget* parent, const char* name,bool modal, WFlags fl) : SubclassingDlgBase(parent,name,modal,fl), m_newFileNames(newFileNames), m_cppSupport( cppSupport ) { m_formFile = formFile; readUiFile(); m_creatingNewSubclass = true; TDEConfig *config = CppSupportFactory::instance()->config(); if (config) { config->setGroup("Subclassing"); reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0)); if (reformatDefault_box->isChecked()) reformat_box->setChecked(true); } } SubclassingDlg::SubclassingDlg(CppSupportPart* cppSupport, const TQString &formFile, const TQString &filename, TQStringList &dummy, TQWidget* parent, const char* name, bool modal, WFlags fl) : SubclassingDlgBase(parent, name, modal, fl), m_newFileNames(dummy), m_cppSupport( cppSupport ) { m_formFile = formFile; m_creatingNewSubclass = false; m_filename = filename; TDEConfig *config = CppSupportFactory::instance()->config(); if (config) { config->setGroup("Subclassing"); reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0)); if (reformatDefault_box->isChecked()) reformat_box->setChecked(true); } TQStringList pathsplit(TQStringList::split('/',filename)); TQString baseClass = readBaseClassName(); if (!cppSupport->codeModel()->hasFile(filename+TQString(".h"))) return; ClassList myClasses = cppSupport->codeModel()->fileByName(filename+TQString(".h"))->classList(); for (ClassList::const_iterator classIt = myClasses.begin(); classIt != myClasses.end(); ++classIt) { kdDebug() << "base class " << baseClass << " class " << (*classIt)->name() << " parents " << (*classIt)->baseClassList().join(",") << endl; if ( (*classIt)->baseClassList().findIndex(baseClass) != -1 ) { kdDebug() << "base class matched " << endl; m_edClassName->setText((*classIt)->name()); m_edFileName->setText(pathsplit[pathsplit.count()-1]); FunctionList functionList = (*classIt)->functionList(); for (FunctionList::const_iterator methodIt = functionList.begin(); methodIt != functionList.end(); ++methodIt) { m_parsedMethods << (*methodIt)->name() + "("; } } } readUiFile(); m_btnOk->setEnabled(true); } bool SubclassingDlg::alreadyInSubclass(const TQString &method) { for (uint i=0;isetEnabled(false); TQDomDocument doc; DomUtil::openDOMFile(doc,m_formFile); m_baseClassName = DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text(); m_baseCaption = DomUtil::elementByPathExt(doc,WIDGET_CAPTION_NAME).text(); setCaption(i18n("Create Subclass of ")+m_baseClassName); // Special widget specific slots SlotItem *newSlot; m_qtBaseClassName = DomUtil::elementByPathExt(doc,"widget").attribute("class",TQDIALOG_OBJECT_NAME_STRING); if ( (m_qtBaseClassName==TQMAINWINDOW_OBJECT_NAME_STRING) || (m_qtBaseClassName==TQWIDGET_OBJECT_NAME_STRING) ) m_canBeModal = false; else m_canBeModal = true; if (m_qtBaseClassName != TQWIDGET_OBJECT_NAME_STRING) { newSlot = new SLOT_ACCEPT; newSlot->setOn(false); if (alreadyInSubclass("accept()")) newSlot->setAllreadyInSubclass(); m_slotView->insertItem(newSlot); m_slots << newSlot; newSlot = new SLOT_REJECT; newSlot->setOn(false); if (alreadyInSubclass("reject()")) newSlot->setAllreadyInSubclass(); m_slotView->insertItem(newSlot); m_slots << newSlot; } if (m_qtBaseClassName == TQWIZARD_OBJECT_NAME_STRING) { newSlot = new SLOT_NEXT; m_slotView->insertItem(newSlot); if (alreadyInSubclass("next()")) newSlot->setAllreadyInSubclass(); m_slots << newSlot; newSlot = new SLOT_BACK; m_slotView->insertItem(newSlot); if (alreadyInSubclass("back()")) newSlot->setAllreadyInSubclass(); m_slots << newSlot; newSlot = new SLOT_HELP; newSlot->setOn(false); if (alreadyInSubclass("help()")) newSlot->setAllreadyInSubclass(); m_slotView->insertItem(newSlot); m_slots << newSlot; } TQDomElement slotsElem = DomUtil::elementByPathExt(doc,WIDGET_SLOTS); TQDomNodeList slotnodes = slotsElem.childNodes(); for (unsigned int i=0; iinsertItem(newSlot); if (alreadyInSubclass(slotelem.text())) newSlot->setAllreadyInSubclass(); m_slots << newSlot; } TQDomElement funcsElem = DomUtil::elementByPathExt(doc,WIDGET_FUNCTIONS); TQDomNodeList funcnodes = funcsElem.childNodes(); SlotItem *newFunc; for (unsigned int i=0; iinsertItem(newFunc); if (alreadyInSubclass(funcelem.text())) newFunc->setAllreadyInSubclass(); m_slots << newFunc; } } SubclassingDlg::~SubclassingDlg() { } void SubclassingDlg::updateDlg() { } void SubclassingDlg::replace(TQString &string, const TQString& search, const TQString& replace) { int nextPos = string.find(search); unsigned int searchLength = search.length(); while (nextPos>-1) { string = string.replace(nextPos,searchLength,replace); nextPos = string.find(search,nextPos+replace.length()); } } bool SubclassingDlg::loadBuffer(TQString &buffer, const TQString& filename) { // open file and buffer it TQFile dataFile(filename); if (!dataFile.open(IO_ReadOnly)) return false; char *temp = new char[dataFile.size()+1]; dataFile.readBlock(temp,dataFile.size()); temp[dataFile.size()]='\0'; buffer = temp; delete [] temp; dataFile.close(); return true; } bool SubclassingDlg::replaceKeywords(TQString &buffer,bool canBeModal) { replace(buffer,"$NEWFILENAMEUC$",m_edFileName->text().upper()); replace(buffer,"$BASEFILENAMELC$",m_formName.lower()); replace(buffer,"$BASEFILENAME$",m_formName); replace(buffer,"$NEWCLASS$",m_edClassName->text()); replace(buffer,"$TQTBASECLASS$", m_qtBaseClassName ); replace(buffer,"$BASECLASS$",m_baseClassName); replace(buffer,"$NEWFILENAMELC$",m_edFileName->text().lower()); if (canBeModal) { replace(buffer,"$CAN_BE_MODAL_H$",", bool modal = FALSE"); replace(buffer,"$CAN_BE_MODAL_CPP1$",", bool modal"); replace(buffer,"$CAN_BE_MODAL_CPP2$",", modal"); } else { replace(buffer,"$CAN_BE_MODAL_H$",""); replace(buffer,"$CAN_BE_MODAL_CPP1$",""); replace(buffer,"$CAN_BE_MODAL_CPP2$",""); } return true; } bool SubclassingDlg::saveBuffer(TQString &buffer, const TQString& filename) { // save buffer TQFile dataFile(filename); if (!dataFile.open(IO_WriteOnly | IO_Truncate)) return false; dataFile.writeBlock((buffer+"\n").ascii(),(buffer+"\n").length()); dataFile.close(); return true; } void SubclassingDlg::accept() { TDEConfig *config = CppSupportFactory::instance()->config(); if (config) { config->setGroup("Subclassing"); config->writeEntry("Reformat Source", reformatDefault_box->isChecked()); } unsigned int i; // h - file TQString public_slot = "/*$PUBLIC_SLOTS$*/\n "; TQString protected_slot = "/*$PROTECTED_SLOTS$*/\n "; TQString public_func = "/*$PUBLIC_FUNCTIONS$*/\n "; TQString protected_func = "/*$PROTECTED_FUNCTIONS$*/\n "; TQString buffer; int qtVersion = DomUtil::readIntEntry( *m_cppSupport->project()->projectDom(), "/kdevcppsupport/qt/version", 3 ); if (m_creatingNewSubclass) { if ( qtVersion == 3 ) loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_template.h")); else loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_qt4_template.h")); buffer = FileTemplate::read(m_cppSupport, "h") + buffer; TQFileInfo fi(m_filename + ".h"); TQString module = fi.baseName(); TQString basefilename = fi.baseName(true); buffer.replace(TQRegExp("\\$MODULE\\$"),module); buffer.replace(TQRegExp("\\$FILENAME\\$"),basefilename); } else loadBuffer(buffer,m_filename+".h"); replaceKeywords(buffer,m_canBeModal); for (i=0; iisOn() || slitem->m_alreadyInSubclass) continue; TQString declBuild; if (slitem->m_access=="public") if (!slitem->m_isFunc) declBuild = public_slot; else declBuild = public_func; if (slitem->m_access=="protected") if (!slitem->m_isFunc) declBuild = protected_slot; else declBuild = protected_func; if (!(slitem->m_specifier=="non virtual")) declBuild += "virtual "; declBuild += slitem->m_returnType + " "; TQString spacer; if (slitem->m_access=="public") { if (!slitem->m_isFunc) { declBuild += spacer.fill(' ',43-declBuild.length()) + slitem->m_methodName + ";"; replace(buffer,"/*$PUBLIC_SLOTS$*/",declBuild); } else { declBuild += spacer.fill(' ',47-declBuild.length()) + slitem->m_methodName + ";"; replace(buffer,"/*$PUBLIC_FUNCTIONS$*/",declBuild); } } if (slitem->m_access=="protected") { if (!slitem->m_isFunc) { declBuild += spacer.fill(' ',46-declBuild.length()) + slitem->m_methodName + ";"; replace(buffer,"/*$PROTECTED_SLOTS$*/",declBuild); } else { declBuild += spacer.fill(' ',50-declBuild.length()) + slitem->m_methodName + ";"; replace(buffer,"/*$PROTECTED_FUNCTIONS$*/",declBuild); } } } if (reformat_box->isChecked()) { KDevSourceFormatter *fmt = m_cppSupport->extension("TDevelop/SourceFormatter"); if (fmt) buffer = fmt->formatSource(buffer); } if (m_creatingNewSubclass) saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".h"); else saveBuffer(buffer,m_filename+".h"); // cpp - file TQString implementation = "/*$SPECIALIZATION$*/\n" "$RETURNTYPE$ $NEWCLASS$::$METHOD$\n" "{\n" "}\n"; TQString implementation_callbase = "/*$SPECIALIZATION$*/\n" "$RETURNTYPE$ $NEWCLASS$::$METHOD$\n" "{\n" " $TQTBASECLASS$::$METHOD$;\n" "}\n"; if (m_creatingNewSubclass) { if ( qtVersion == 3 ) loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_template.cpp")); else loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_qt4_template.cpp")); buffer = FileTemplate::read(m_cppSupport, "cpp") + buffer; TQFileInfo fi(m_filename + ".cpp"); TQString module = fi.baseName(); TQString basefilename = fi.baseName(true); buffer.replace(TQRegExp("\\$MODULE\\$"),module); buffer.replace(TQRegExp("\\$FILENAME\\$"),basefilename); if ( (m_cppSupport->project()) && (m_cppSupport->project()->options() & KDevProject::UsesAutotoolsBuildSystem)) buffer += "\n#include \"$NEWFILENAMELC$.moc\"\n"; } else loadBuffer(buffer,m_filename+".cpp"); replaceKeywords(buffer,m_canBeModal); for (i=0; iisOn() || slitem->m_alreadyInSubclass) continue; TQString impl = slitem->m_callBaseClass ? implementation_callbase : implementation; replace(impl,"$RETURNTYPE$",slitem->m_returnType); replace(impl,"$NEWCLASS$",m_edClassName->text()); replace(impl,"$METHOD$", slitem->m_methodName); replace(impl,"$TQTBASECLASS$", m_qtBaseClassName); replace(buffer,"/*$SPECIALIZATION$*/",impl); } if (reformat_box->isChecked()) { KDevSourceFormatter *fmt = m_cppSupport->extension("TDevelop/SourceFormatter"); if (fmt) buffer = fmt->formatSource(buffer); } if (m_creatingNewSubclass) saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".cpp"); else saveBuffer(buffer,m_filename+".cpp"); if (m_creatingNewSubclass) { m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".cpp"); m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".h"); } SubclassingDlgBase::accept(); } void SubclassingDlg::onChangedClassName() { m_edFileName->setText(m_edClassName->text().lower()); if (m_edFileName->text().isEmpty() || m_edClassName->text().isEmpty()) m_btnOk->setEnabled(false); else m_btnOk->setEnabled(true); } TQString SubclassingDlg::readBaseClassName() { TQDomDocument doc; DomUtil::openDOMFile(doc,m_formFile); return DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text(); } //kate: indent-mode csands; tab-width 4; space-indent off;