00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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];
00176 splitPath.pop_back();
00177
m_formPath =
"/" + splitPath.join(
"/");
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
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
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
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
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
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 }