1
/***************************************************************************
2
* Copyright (C) 2002 by Jakob Simon-Gaarde *
3
* jsgaarde@tdcspace.dk *
4
* Copyright (C) 2003 by Alexander Dymo *
5
* cloudtemple@mksat.net *
7
* This program is free software; you can redistribute it and/or modify *
8
* it under the terms of the GNU General Public License as published by *
9
* the Free Software Foundation; either version 2 of the License, or *
10
* (at your option) any later version. *
12
***************************************************************************/
14
#include "subclassingdlg.h"
15
#include "cppsupportpart.h"
16
#include "backgroundparser.h"
17
#include "store_walker.h"
18
#include "cppsupportfactory.h"
19
#include "kdevsourceformatter.h"
21
#include "kdevproject.h"
22
#include "filetemplate.h"
23
#include "codemodel.h"
25
#include <qradiobutton.h>
26
#include <qstringlist.h>
27
#include <qcheckbox.h>
28
#include <qmessagebox.h>
29
#include <kfiledialog.h>
30
#include <klineedit.h>
31
#include <qpushbutton.h>
34
#include <kstandarddirs.h>
42
#define WIDGET_CAPTION_NAME "widget/property|name=caption/string"
43
#define WIDGET_CLASS_NAME "class"
44
#define WIDGET_SLOTS "slots"
45
#define WIDGET_FUNCTIONS "functions"
48
#define SLOT_ACCEPT SlotItem(m_slotView,"accept()","virtual","protected","void",false,true)
49
#define SLOT_REJECT SlotItem(m_slotView,"reject()","virtual","protected","void",false,true)
52
#define SLOT_BACK SlotItem(m_slotView,"back()","virtual","protected","void",false,true)
53
#define SLOT_NEXT SlotItem(m_slotView,"next()","virtual","protected","void",false,true)
54
#define SLOT_HELP SlotItem(m_slotView,"help()","virtual","protected","void",false,true)
57
SlotItem::SlotItem(QListView *parent,const QString &methodName,
58
const QString &specifier,
59
const QString &access, const QString &returnType,
60
bool isFunc,bool callBaseClass)
61
: QCheckListItem(parent,methodName,QCheckListItem::CheckBox)
64
m_methodName = methodName;
65
m_access = access.isEmpty() ? (const QString) "public" : access;
66
m_specifier = specifier.isEmpty() ? (const QString) "virtual" : specifier;
67
m_returnType = returnType.isEmpty() ? (const QString) "void" : returnType;
69
m_callBaseClass = callBaseClass;
70
setText(0,m_methodName);
72
setText(2,m_specifier);
73
setText(3,m_returnType);
74
setText(4,m_isFunc ? "Function" : "Slot");
75
if (m_access=="private" || m_specifier=="non virtual")
80
if (m_specifier=="pure virtual")
85
m_alreadyInSubclass = false;
88
void SlotItem::setAllreadyInSubclass()
92
m_alreadyInSubclass = true;
96
SubclassingDlg::SubclassingDlg(CppSupportPart* cppSupport, const QString &formFile,
97
QStringList &newFileNames, QWidget* parent,
98
const char* name,bool modal, WFlags fl)
99
: SubclassingDlgBase(parent,name,modal,fl),
100
m_newFileNames(newFileNames), m_cppSupport( cppSupport )
103
m_formFile = formFile;
105
m_creatingNewSubclass = true;
107
KConfig *config = CppSupportFactory::instance()->config();
110
config->setGroup("Subclassing");
111
reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0));
112
if (reformatDefault_box->isChecked())
113
reformat_box->setChecked(true);
118
SubclassingDlg::SubclassingDlg(CppSupportPart* cppSupport, const QString &formFile,
119
const QString &filename, QStringList &dummy,
120
QWidget* parent, const char* name, bool modal, WFlags fl)
121
: SubclassingDlgBase(parent, name, modal, fl),
122
m_newFileNames(dummy), m_cppSupport( cppSupport )
125
m_formFile = formFile;
126
m_creatingNewSubclass = false;
127
m_filename = filename;
129
KConfig *config = CppSupportFactory::instance()->config();
132
config->setGroup("Subclassing");
133
reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0));
134
if (reformatDefault_box->isChecked())
135
reformat_box->setChecked(true);
138
QStringList pathsplit(QStringList::split('/',filename));
140
QString baseClass = readBaseClassName();
141
if (!cppSupport->codeModel()->hasFile(filename+QString(".h")))
143
ClassList myClasses = cppSupport->codeModel()->fileByName(filename+QString(".h"))->classList();
144
for (ClassList::const_iterator classIt = myClasses.begin(); classIt != myClasses.end(); ++classIt)
146
kdDebug() << "base class " << baseClass << " class " << (*classIt)->name()
147
<< " parents " << (*classIt)->baseClassList().join(",") << endl;
148
if ( (*classIt)->baseClassList().findIndex(baseClass) != -1 )
150
kdDebug() << "base class matched " << endl;
151
m_edClassName->setText((*classIt)->name());
152
m_edFileName->setText(pathsplit[pathsplit.count()-1]);
154
FunctionList functionList = (*classIt)->functionList();
155
for (FunctionList::const_iterator methodIt = functionList.begin();
156
methodIt != functionList.end(); ++methodIt)
158
m_parsedMethods << (*methodIt)->name() + "(";
163
m_btnOk->setEnabled(true);
166
bool SubclassingDlg::alreadyInSubclass(const QString &method)
168
for (uint i=0;i<m_parsedMethods.count();i++)
170
if (method.find(m_parsedMethods[i])==0)
176
void SubclassingDlg::readUiFile()
178
QStringList splitPath = QStringList::split('/',m_formFile);
179
m_formName = QStringList::split('.',splitPath[splitPath.count()-1])[0]; // "somedlg.ui" = "somedlg"
180
splitPath.pop_back();
181
m_formPath = "/" + splitPath.join("/"); // join path to ui-file
183
m_btnOk->setEnabled(false);
186
DomUtil::openDOMFile(doc,m_formFile);
187
m_baseClassName = DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text();
189
m_baseCaption = DomUtil::elementByPathExt(doc,WIDGET_CAPTION_NAME).text();
190
setCaption(i18n("Create Subclass of ")+m_baseClassName);
192
// Special widget specific slots
194
m_qtBaseClassName = DomUtil::elementByPathExt(doc,"widget").attribute("class","QDialog");
196
if ( (m_qtBaseClassName=="QMainWindow") || (m_qtBaseClassName=="QWidget") )
197
m_canBeModal = false;
200
if (m_qtBaseClassName != "QWidget")
202
newSlot = new SLOT_ACCEPT;
203
newSlot->setOn(false);
204
if (alreadyInSubclass("accept()"))
205
newSlot->setAllreadyInSubclass();
206
m_slotView->insertItem(newSlot);
209
newSlot = new SLOT_REJECT;
210
newSlot->setOn(false);
211
if (alreadyInSubclass("reject()"))
212
newSlot->setAllreadyInSubclass();
213
m_slotView->insertItem(newSlot);
217
if (m_qtBaseClassName == "QWizard")
219
newSlot = new SLOT_NEXT;
220
m_slotView->insertItem(newSlot);
221
if (alreadyInSubclass("next()"))
222
newSlot->setAllreadyInSubclass();
224
newSlot = new SLOT_BACK;
225
m_slotView->insertItem(newSlot);
226
if (alreadyInSubclass("back()"))
227
newSlot->setAllreadyInSubclass();
229
newSlot = new SLOT_HELP;
230
newSlot->setOn(false);
231
if (alreadyInSubclass("help()"))
232
newSlot->setAllreadyInSubclass();
233
m_slotView->insertItem(newSlot);
237
QDomElement slotsElem = DomUtil::elementByPathExt(doc,WIDGET_SLOTS);
238
QDomNodeList slotnodes = slotsElem.childNodes();
240
for (unsigned int i=0; i<slotnodes.count();i++)
242
QDomElement slotelem = slotnodes.item(i).toElement();
243
newSlot = new SlotItem(m_slotView,slotelem.text(),
244
slotelem.attributeNode("specifier").value(),
245
slotelem.attributeNode("access").value(),
246
slotelem.attributeNode("returnType").value(),false);
247
m_slotView->insertItem(newSlot);
248
if (alreadyInSubclass(slotelem.text()))
249
newSlot->setAllreadyInSubclass();
253
QDomElement funcsElem = DomUtil::elementByPathExt(doc,WIDGET_FUNCTIONS);
254
QDomNodeList funcnodes = funcsElem.childNodes();
256
for (unsigned int i=0; i<funcnodes.count();i++)
258
QDomElement funcelem = funcnodes.item(i).toElement();
259
newFunc = new SlotItem(m_slotView,funcelem.text(),
260
funcelem.attributeNode("specifier").value(),
261
funcelem.attributeNode("access").value(),
262
funcelem.attributeNode("returnType").value(),true);
263
m_slotView->insertItem(newFunc);
264
if (alreadyInSubclass(funcelem.text()))
265
newFunc->setAllreadyInSubclass();
270
SubclassingDlg::~SubclassingDlg()
275
void SubclassingDlg::updateDlg()
279
void SubclassingDlg::replace(QString &string, const QString& search, const QString& replace)
281
int nextPos = string.find(search);
282
unsigned int searchLength = search.length();
285
string = string.replace(nextPos,searchLength,replace);
286
nextPos = string.find(search,nextPos+replace.length());
290
bool SubclassingDlg::loadBuffer(QString &buffer, const QString& filename)
292
// open file and buffer it
293
QFile dataFile(filename);
294
if (!dataFile.open(IO_ReadOnly))
296
char *temp = new char[dataFile.size()+1];
297
dataFile.readBlock(temp,dataFile.size());
298
temp[dataFile.size()]='\0';
305
bool SubclassingDlg::replaceKeywords(QString &buffer,bool canBeModal)
307
replace(buffer,"$NEWFILENAMEUC$",m_edFileName->text().upper());
308
replace(buffer,"$BASEFILENAMELC$",m_formName.lower());
309
replace(buffer,"$BASEFILENAME$",m_formName);
310
replace(buffer,"$NEWCLASS$",m_edClassName->text());
311
replace(buffer,"$BASECLASS$",m_baseClassName);
312
replace(buffer,"$NEWFILENAMELC$",m_edFileName->text().lower());
315
replace(buffer,"$CAN_BE_MODAL_H$",", bool modal = FALSE");
316
replace(buffer,"$CAN_BE_MODAL_CPP1$",", bool modal");
317
replace(buffer,"$CAN_BE_MODAL_CPP2$",", modal");
321
replace(buffer,"$CAN_BE_MODAL_H$","");
322
replace(buffer,"$CAN_BE_MODAL_CPP1$","");
323
replace(buffer,"$CAN_BE_MODAL_CPP2$","");
329
bool SubclassingDlg::saveBuffer(QString &buffer, const QString& filename)
333
QFile dataFile(filename);
334
if (!dataFile.open(IO_WriteOnly | IO_Truncate))
336
dataFile.writeBlock((buffer+"\n").ascii(),(buffer+"\n").length());
342
void SubclassingDlg::accept()
344
KConfig *config = CppSupportFactory::instance()->config();
347
config->setGroup("Subclassing");
348
config->writeEntry("Reformat Source", reformatDefault_box->isChecked());
355
QString public_slot =
356
"/*$PUBLIC_SLOTS$*/\n ";
358
QString protected_slot =
359
"/*$PROTECTED_SLOTS$*/\n ";
361
QString public_func =
362
"/*$PUBLIC_FUNCTIONS$*/\n ";
364
QString protected_func =
365
"/*$PROTECTED_FUNCTIONS$*/\n ";
368
if (m_creatingNewSubclass)
370
loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_template.h"));
371
buffer = FileTemplate::read(m_cppSupport, "h") + buffer;
372
QFileInfo fi(m_filename + ".h");
373
QString module = fi.baseName();
374
QString basefilename = fi.baseName(true);
375
buffer.replace(QRegExp("\\$MODULE\\$"),module);
376
buffer.replace(QRegExp("\\$FILENAME\\$"),basefilename);
379
loadBuffer(buffer,m_filename+".h");
381
replaceKeywords(buffer,m_canBeModal);
382
for (i=0; i<m_slots.count(); i++)
384
SlotItem *slitem = m_slots[i];
385
if (!slitem->isOn() ||
386
slitem->m_alreadyInSubclass)
389
if (slitem->m_access=="public")
390
if (!slitem->m_isFunc)
391
declBuild = public_slot;
393
declBuild = public_func;
394
if (slitem->m_access=="protected")
395
if (!slitem->m_isFunc)
396
declBuild = protected_slot;
398
declBuild = protected_func;
399
if (!(slitem->m_specifier=="non virtual"))
400
declBuild += "virtual ";
401
declBuild += slitem->m_returnType + " ";
403
if (slitem->m_access=="public")
405
if (!slitem->m_isFunc)
407
declBuild += spacer.fill(' ',43-declBuild.length()) + slitem->m_methodName + ";";
408
replace(buffer,"/*$PUBLIC_SLOTS$*/",declBuild);
412
declBuild += spacer.fill(' ',47-declBuild.length()) + slitem->m_methodName + ";";
413
replace(buffer,"/*$PUBLIC_FUNCTIONS$*/",declBuild);
416
if (slitem->m_access=="protected")
418
if (!slitem->m_isFunc)
420
declBuild += spacer.fill(' ',46-declBuild.length()) + slitem->m_methodName + ";";
421
replace(buffer,"/*$PROTECTED_SLOTS$*/",declBuild);
425
declBuild += spacer.fill(' ',50-declBuild.length()) + slitem->m_methodName + ";";
426
replace(buffer,"/*$PROTECTED_FUNCTIONS$*/",declBuild);
431
if (reformat_box->isChecked())
433
KDevSourceFormatter *fmt = m_cppSupport->extension<KDevSourceFormatter>("KDevelop/SourceFormatter");
435
buffer = fmt->formatSource(buffer);
438
if (m_creatingNewSubclass)
439
saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".h");
441
saveBuffer(buffer,m_filename+".h");
445
QString implementation =
446
"/*$SPECIALIZATION$*/\n"
447
"$RETURNTYPE$ $NEWCLASS$::$METHOD$\n"
451
QString implementation_callbase =
452
"/*$SPECIALIZATION$*/\n"
453
"$RETURNTYPE$ $NEWCLASS$::$METHOD$\n"
455
" $QTBASECLASS$::$METHOD$;\n"
459
if (m_creatingNewSubclass)
461
loadBuffer(buffer,::locate("data", "kdevcppsupport/subclassing/subclass_template.cpp"));
462
buffer = FileTemplate::read(m_cppSupport, "cpp") + buffer;
463
QFileInfo fi(m_filename + ".cpp");
464
QString module = fi.baseName();
465
QString basefilename = fi.baseName(true);
466
buffer.replace(QRegExp("\\$MODULE\\$"),module);
467
buffer.replace(QRegExp("\\$FILENAME\\$"),basefilename);
468
if ( (m_cppSupport->project()) && (m_cppSupport->project()->options() & KDevProject::UsesAutotoolsBuildSystem))
469
buffer += "\n#include \"$NEWFILENAMELC$.moc\"\n";
472
loadBuffer(buffer,m_filename+".cpp");
474
replaceKeywords(buffer,m_canBeModal);
475
for (i=0; i<m_slots.count(); i++)
477
SlotItem *slitem = m_slots[i];
478
if (!slitem->isOn() ||
479
slitem->m_alreadyInSubclass)
481
QString impl = slitem->m_callBaseClass ? implementation_callbase : implementation;
482
replace(impl,"$RETURNTYPE$",slitem->m_returnType);
483
replace(impl,"$NEWCLASS$",m_edClassName->text());
484
replace(impl,"$METHOD$", slitem->m_methodName);
485
replace(impl,"$QTBASECLASS$", m_qtBaseClassName);
486
replace(buffer,"/*$SPECIALIZATION$*/",impl);
489
if (reformat_box->isChecked())
491
KDevSourceFormatter *fmt = m_cppSupport->extension<KDevSourceFormatter>("KDevelop/SourceFormatter");
493
buffer = fmt->formatSource(buffer);
496
if (m_creatingNewSubclass)
497
saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".cpp");
499
saveBuffer(buffer,m_filename+".cpp");
501
if (m_creatingNewSubclass)
503
m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".cpp");
504
m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".h");
506
SubclassingDlgBase::accept();
509
void SubclassingDlg::onChangedClassName()
511
m_edFileName->setText(m_edClassName->text().lower());
512
if (m_edFileName->text().isEmpty() ||
513
m_edClassName->text().isEmpty())
514
m_btnOk->setEnabled(false);
516
m_btnOk->setEnabled(true);
519
QString SubclassingDlg::readBaseClassName()
522
DomUtil::openDOMFile(doc,m_formFile);
523
return DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text();
526
//kate: indent-mode csands; tab-width 4; space-indent off;