00001
#include <qapplication.h>
00002
#include <qfile.h>
00003
#include <qfileinfo.h>
00004
#include <qpopupmenu.h>
00005
#include <qvbox.h>
00006
#include <qtable.h>
00007
#include <qtextstream.h>
00008
#include <qvaluestack.h>
00009
#include <qdir.h>
00010
00011
00012
#include <kdevgenericfactory.h>
00013
#include <kdebug.h>
00014
#include <kaction.h>
00015
#include <kpopupmenu.h>
00016
#include <kdialogbase.h>
00017
#include <klineedit.h>
00018
#include <kcombobox.h>
00019
#include <keditlistbox.h>
00020
#include <kurlrequester.h>
00021
00022
00023
#include <kdevcore.h>
00024
#include <kdevmakefrontend.h>
00025
00026
00027
#include "antoptionswidget.h"
00028
#include "classpathwidget.h"
00029
00030
00031
#include "antprojectpart.h"
00032
00033
00034 typedef KDevGenericFactory<AntProjectPart> AntProjectFactory;
00035
static const KAboutData data(
"kdevantproject",
I18N_NOOP(
"Build Tool"),
"1.0");
00036 K_EXPORT_COMPONENT_FACTORY(libkdevantproject,
AntProjectFactory( &data ))
00037
00038
00039
AntOptions::
AntOptions()
00040 : m_buildXML("build.xml"), m_verbosity(
AntOptions::Quiet)
00041 {
00042 }
00043
00044
00045 AntProjectPart::AntProjectPart(
QObject *parent,
const char *name,
const QStringList &)
00046 :
KDevProject("AntProject", "antproject", parent, name ? name : "
AntProjectPart")
00047 {
00048 setInstance(AntProjectFactory::instance());
00049
00050 setXMLFile(
"kdevantproject.rc");
00051
00052
m_buildProjectAction =
new KAction(i18n(
"&Build Project"),
"make_kdevelop", Key_F8,
00053
this, SLOT(
slotBuild()),
00054
actionCollection(),
"build_build" );
00055
m_buildProjectAction->
setToolTip(i18n(
"Build project"));
00056
m_buildProjectAction->
setWhatsThis(i18n(
"<b>Build project</b><p>Executes <b>ant dist</b> command to build the project."));
00057
00058
KActionMenu *menu =
new KActionMenu(i18n(
"Build &Target"),
00059
actionCollection(),
"build_target" );
00060 menu->
setToolTip(i18n(
"Build target"));
00061 menu->
setWhatsThis(i18n(
"<b>Build target</b><p>Executes <b>ant target_name</b> command to build the specified target."));
00062
00063
m_targetMenu = menu->
popupMenu();
00064
00065 connect(
m_targetMenu, SIGNAL(activated(
int)),
this, SLOT(
slotTargetMenuActivated(
int)));
00066 connect(
core(), SIGNAL(
projectConfigWidget(
KDialogBase*)),
this, SLOT(
projectConfigWidget(
KDialogBase*)));
00067 connect(
core(), SIGNAL(
contextMenu(
QPopupMenu *,
const Context *)),
this, SLOT(
contextMenu(
QPopupMenu *,
const Context *)));
00068
00069
m_antOptionsWidget = 0;
00070 }
00071
00072
00073 AntProjectPart::~AntProjectPart()
00074 {
00075 }
00076
00077
00078 void AntProjectPart::openProject(
const QString &dirName,
const QString &projectName)
00079 {
00080
m_projectDirectory = dirName;
00081
m_projectName = projectName;
00082
00083
QDomDocument &dom = *
projectDom();
00084
00086
if (DomUtil::readEntry(dom,
"/kdevantproject/run/directoryradio") ==
"" ) {
00087 DomUtil::writeEntry(dom,
"/kdevantproject/run/directoryradio",
"executable");
00088 }
00089
00091
m_antOptions.
m_buildXML =
"build.xml";
00092
00093
parseBuildXML();
00094
00095
fillMenu();
00096
00097
QFile f(dirName +
"/" + projectName +
".filelist");
00098
if (f.open(IO_ReadOnly))
00099 {
00100
QTextStream stream(&f);
00101
while (!stream.atEnd())
00102 {
00103
QString s = stream.readLine();
00104
if (!s.startsWith(
"#"))
00105
m_sourceFiles << s;
00106 }
00107 }
00108
else
00109
populateProject();
00110
00111 KDevProject::openProject( dirName, projectName );
00112 }
00113
00114
00115 void AntProjectPart::populateProject()
00116 {
00117 QApplication::setOverrideCursor(Qt::waitCursor);
00118
00119
QValueStack<QString> s;
00120
int prefixlen =
m_projectDirectory.length()+1;
00121 s.push(
m_projectDirectory);
00122
00123
QDir dir;
00124
do
00125 {
00126 dir.setPath(s.pop());
00127
kdDebug() <<
"Examining: " << dir.path() <<
endl;
00128
const QFileInfoList *dirEntries = dir.entryInfoList();
00129
QPtrListIterator<QFileInfo> it(*dirEntries);
00130
for (; it.current(); ++it)
00131 {
00132
QString fileName = it.current()->fileName();
00133
if (fileName ==
"." || fileName ==
"..")
00134
continue;
00135
QString path = it.current()->absFilePath();
00136
if (it.current()->isDir())
00137 {
00138
kdDebug() <<
"Pushing: " << path <<
endl;
00139 s.push(path);
00140 }
00141
else
00142 {
00143
kdDebug() <<
"Adding: " << path <<
endl;
00144
m_sourceFiles.append(path.mid(prefixlen));
00145 }
00146 }
00147 }
00148
while (!s.isEmpty());
00149
00150 QApplication::restoreOverrideCursor();
00151 }
00152
00153
00154 void AntProjectPart::closeProject()
00155 {
00156
m_projectDirectory =
"";
00157
m_projectName =
"";
00158
m_buildProjectAction->
setEnabled(
false);
00159
00160
m_targetMenu->clear();
00161
00162
m_antOptions =
AntOptions();
00163
00164
QFile f(
m_projectDirectory +
"/" +
m_projectName +
".filelist");
00165
if (!f.open(IO_WriteOnly))
00166
return;
00167
00168
QTextStream stream(&f);
00169 stream <<
"# KDevelop Ant Project File List" <<
endl;
00170
00171 QStringList::ConstIterator it;
00172
for (it =
m_sourceFiles.begin(); it !=
m_sourceFiles.end(); ++it)
00173 stream << (*it) <<
endl;
00174 f.close();
00175 }
00176
00177
00178 QString AntProjectPart::projectDirectory()
const
00179
{
00180
return m_projectDirectory;
00181 }
00182
00183
00184 QString AntProjectPart::buildDirectory()
const
00185
{
00186
return m_projectDirectory;
00187 }
00188
00189 QString AntProjectPart::projectName()
const
00190
{
00191
return m_projectName;
00192 }
00193
00194
00196 DomUtil::PairList AntProjectPart::runEnvironmentVars()
const
00197
{
00199
return DomUtil::readPairListEntry(*
projectDom(),
"/kdevantproject/run/envvars",
"envvar",
"name",
"value");
00200 }
00201
00202
00212 QString AntProjectPart::runDirectory()
const
00213
{
00214
return buildDirectory();
00216
00217
QDomDocument &dom = *
projectDom();
00218
00220
QString directoryRadioString = DomUtil::readEntry(dom,
"/kdevantproject/run/directoryradio");
00221
QString DomMainProgram = DomUtil::readEntry(dom,
"/kdevantproject/run/mainprogram");
00222
00223
if ( directoryRadioString ==
"build" )
00224
return buildDirectory();
00225
00226
if ( directoryRadioString ==
"custom" )
00227
return DomUtil::readEntry(dom,
"/kdevantproject/run/customdirectory");
00228
00229
int pos = DomMainProgram.findRev(
'/');
00230
if (pos != -1)
00231
return buildDirectory() +
"/" + DomMainProgram.left(pos);
00232
00233
return buildDirectory() +
"/" + DomMainProgram;
00234
00235 }
00236
00237
00247 QString AntProjectPart::mainProgram(
bool relative)
const
00248
{
00249
return QString::null;
00250
00252
QDomDocument &dom = *
projectDom();
00253
00255
QString directoryRadioString = DomUtil::readEntry(dom,
"/kdevantproject/run/directoryradio");
00256
QString DomMainProgram = DomUtil::readEntry(dom,
"/kdevantproject/run/mainprogram");
00257
00258
if ( directoryRadioString ==
"custom" )
00259
return DomMainProgram;
00260
00261
if ( relative ==
false )
00262
return buildDirectory() +
"/" + DomMainProgram;
00263
00264
if ( directoryRadioString ==
"executable" ) {
00265
int pos = DomMainProgram.findRev(
'/');
00266
if (pos != -1)
00267
return DomMainProgram.mid(pos+1);
00268
return DomMainProgram;
00269 }
00270
else
00271
return DomMainProgram;
00272 }
00273
00274
00276 QString AntProjectPart::runArguments()
const
00277
{
00279
return DomUtil::readEntry(*
projectDom(),
"/kdevantproject/run/programargs");
00280 }
00281
00282
00283 QString AntProjectPart::activeDirectory()
const
00284
{
00286
00287
00288
00289
00290
00291
return QString(
"");
00292 }
00293
00294
00295 QStringList AntProjectPart::allFiles()
const
00296
{
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
return m_sourceFiles;
00315 }
00316
00317
00318 void AntProjectPart::addFile(
const QString &fileName)
00319 {
00320
QStringList fileList;
00321 fileList.append ( fileName );
00322
00323 this->
addFiles ( fileList );
00324 }
00325
00326 void AntProjectPart::addFiles (
const QStringList& fileList )
00327 {
00328 QStringList::ConstIterator it;
00329
00330
for ( it = fileList.begin(); it != fileList.end(); ++it )
00331 {
00332
m_sourceFiles.append (*it );
00333 }
00334
00335
kdDebug() <<
"Emitting addedFilesToProject" <<
endl;
00336 emit addedFilesToProject(fileList);
00337 }
00338
00339 void AntProjectPart::removeFile(
const QString &fileName)
00340 {
00341
QStringList fileList;
00342 fileList.append ( fileName );
00343
00344 this->
removeFiles ( fileList );
00345 }
00346
00347 void AntProjectPart::removeFiles (
const QStringList& fileList )
00348 {
00349
kdDebug() <<
"Emitting removedFilesFromProject" <<
endl;
00350 emit removedFilesFromProject(fileList);
00351
00352 QStringList::ConstIterator it;
00353
00354
for ( it = fileList.begin(); it != fileList.end(); ++it )
00355 {
00356
m_sourceFiles.remove ( *it );
00357 }
00358 }
00359
00360 void AntProjectPart::parseBuildXML()
00361 {
00362
m_antOptions.
m_targets.clear();
00363
m_antOptions.
m_properties.clear();
00364
m_antOptions.
m_defineProperties.clear();
00365
00366
00367
QFile bf(
m_projectDirectory +
"/" +
m_antOptions.
m_buildXML);
00368
if (!bf.open(IO_ReadOnly))
00369
return;
00370
00371
00372
QDomDocument dom;
00373
if (!dom.setContent(&bf))
00374 {
00375 bf.close();
00376
return;
00377 }
00378 bf.close();
00379
00380
m_projectName = dom.documentElement().attribute(
"name",
m_projectName);
00381
m_antOptions.
m_defaultTarget = dom.documentElement().attribute(
"default",
"");
00382
00383
QDomNode node = dom.documentElement().firstChild();
00384
while (!node.isNull())
00385 {
00386
if (node.toElement().tagName() ==
"target")
00387 {
00388
if (
m_antOptions.
m_defaultTarget.isEmpty())
00389
m_antOptions.
m_defaultTarget = node.toElement().attribute(
"name");
00390
m_antOptions.
m_targets.append(node.toElement().attribute(
"name"));
00391 }
00392
else if (node.toElement().tagName() ==
"property")
00393 {
00394
m_antOptions.
m_properties.insert(node.toElement().attribute(
"name"), node.toElement().attribute(
"value"));
00395
m_antOptions.
m_defineProperties.insert(node.toElement().attribute(
"name"),
false);
00396 }
00397
00400
00401 node = node.nextSibling();
00402 }
00403 }
00404
00405
00406 void AntProjectPart::fillMenu()
00407 {
00408
m_buildProjectAction->
setEnabled(!
m_antOptions.
m_defaultTarget.isEmpty());
00409
00410
m_targetMenu->clear();
00411
int id = 0;
00412 QStringList::ConstIterator it;
00413
for (it =
m_antOptions.
m_targets.begin(); it !=
m_antOptions.
m_targets.end(); ++it)
00414
m_targetMenu->insertItem(*it,
id++);
00415 }
00416
00417
00418 void AntProjectPart::slotBuild()
00419 {
00420
ant(
m_antOptions.
m_defaultTarget);
00421 }
00422
00423
00424 void AntProjectPart::slotTargetMenuActivated(
int id)
00425 {
00426
ant(
m_antOptions.
m_targets[
id]);
00427 }
00428
00429
00430 void AntProjectPart::ant(
const QString &target)
00431 {
00432
QString cmd =
"%0 cd %1 && ant %2 -buildfile %3 %4 %5";
00433
00434
QString verb =
"";
00435
switch (
m_antOptions.
m_verbosity)
00436 {
00437
case AntOptions::Quiet:
00438 verb =
"-quiet";
00439
break;
00440
case AntOptions::Verbose:
00441 verb =
"-verbose";
00442
break;
00443
default:
00444 verb =
"-debug";
00445
break;
00446 }
00447
00448
QString options =
"";
00449
QMap<QString,QString>::Iterator it;
00450
for (it =
m_antOptions.
m_properties.begin(); it !=
m_antOptions.
m_properties.end(); ++it)
00451
if (
m_antOptions.
m_defineProperties[it.key()])
00452 options +=
"-D" + it.key() +
"=\"" + it.data() +
"\" ";
00453
00454
QString cp;
00455
if (!
m_classPath.count() == 0)
00456 cp =
"CLASSPATH="+
m_classPath.join(
":");
00457
00458
makeFrontend()->
queueCommand(
m_projectDirectory, cmd.arg(cp).arg(
m_projectDirectory).arg(target).arg(
m_antOptions.
m_buildXML).arg(verb).arg(options));
00459 }
00460
00461
00462 void AntProjectPart::projectConfigWidget(
KDialogBase *dlg)
00463 {
00464
QVBox *vbox = dlg->
addVBoxPage(i18n(
"Ant Options"));
00465
m_antOptionsWidget =
new AntOptionsWidget(vbox);
00466
00467
m_antOptionsWidget->
BuildXML->
setURL(
m_antOptions.
m_buildXML);
00468
00469
switch (
m_antOptions.
m_verbosity)
00470 {
00471
case AntOptions::Quiet:
00472
m_antOptionsWidget->
Verbosity->
setCurrentItem(0);
00473
break;
00474
case AntOptions::Verbose:
00475
m_antOptionsWidget->
Verbosity->
setCurrentItem(1);
00476
break;
00477
default:
00478
m_antOptionsWidget->
Verbosity->
setCurrentItem(2);
00479
break;
00480 }
00481
00482
m_antOptionsWidget->
Properties->setNumRows(
m_antOptions.
m_properties.count());
00483
m_antOptionsWidget->
Properties->setNumCols(2);
00484
00485
QMap<QString,QString>::Iterator it;
00486
int i=0;
00487
for (it =
m_antOptions.
m_properties.begin(); it !=
m_antOptions.
m_properties.end(); ++it)
00488 {
00489
QCheckTableItem *citem =
new QCheckTableItem(
m_antOptionsWidget->
Properties, it.key());
00490 citem->setChecked(
m_antOptions.
m_defineProperties[it.key()]);
00491
m_antOptionsWidget->
Properties->setItem(i,0, citem);
00492
QTableItem *item =
new QTableItem(
m_antOptionsWidget->
Properties, QTableItem::WhenCurrent, it.data());
00493
m_antOptionsWidget->
Properties->setItem(i,1, item);
00494 ++i;
00495 }
00496
00497 connect(dlg, SIGNAL(okClicked()),
this, SLOT(
optionsAccepted()));
00498
00499 vbox = dlg->
addVBoxPage(i18n(
"Classpath"));
00500
m_classPathWidget =
new ClassPathWidget(vbox);
00501
00502
m_classPathWidget->
ClassPath->
insertStringList(
m_classPath);
00503 }
00504
00505
00506 void AntProjectPart::optionsAccepted()
00507 {
00508
if (!
m_antOptionsWidget || !
m_classPathWidget)
00509
return;
00510
00511
m_antOptions.
m_buildXML =
m_antOptionsWidget->
BuildXML->
url();
00512
00513
switch (
m_antOptionsWidget->
Verbosity->currentItem())
00514 {
00515
case 1:
00516
m_antOptions.
m_verbosity = AntOptions::Verbose;
00517
break;
00518
case 2:
00519
m_antOptions.
m_verbosity = AntOptions::Debug;
00520
break;
00521
default:
00522
m_antOptions.
m_verbosity = AntOptions::Quiet;
00523
break;
00524 }
00525
00526
for (
int i=0; i<
m_antOptionsWidget->
Properties->numRows(); ++i)
00527 {
00528
QString key =
m_antOptionsWidget->
Properties->text(i,0);
00529
m_antOptions.
m_properties.replace(key,
m_antOptionsWidget->
Properties->text(i,1));
00530
kdDebug() <<
"PROP: " << key <<
" = " <<
m_antOptionsWidget->
Properties->text(i,1);
00531
00532
QCheckTableItem *item =(
QCheckTableItem*)
m_antOptionsWidget->
Properties->item(i,0);
00533
m_antOptions.
m_defineProperties.replace(key, item->isChecked());
00534 }
00535
00536
m_classPath =
m_classPathWidget->
ClassPath->
items();
00537
00538
m_antOptionsWidget = 0;
00539
m_classPathWidget = 0;
00540 }
00541
00542
00543 void AntProjectPart::contextMenu(
QPopupMenu *popup,
const Context *context)
00544 {
00545
if (!context->
hasType( Context::FileContext ))
00546
return;
00547
00548
const FileContext *fcontext = static_cast<const FileContext*>(context);
00549
if (fcontext->
isDirectory())
00550
return;
00551
00552
m_contextFileName = fcontext->
fileName();
00553
bool inProject =
project()->
allFiles().contains(
m_contextFileName.mid ( project()->
projectDirectory().
length() + 1 ) );
00554
QString popupstr =
QFileInfo(
m_contextFileName).fileName();
00555
if (
m_contextFileName.startsWith(
projectDirectory()+
"/"))
00556
m_contextFileName.remove(0,
projectDirectory().
length()+1);
00557
00558 popup->insertSeparator();
00559
if (inProject)
00560 {
00561
int id = popup->insertItem( i18n(
"Remove %1 From Project").arg(popupstr),
00562
this, SLOT(
slotRemoveFromProject()) );
00563 popup->setWhatsThis(
id, i18n(
"<b>Remove from project</b><p>Removes current file from the project."));
00564 }
00565
else
00566 {
00567
int id = popup->insertItem( i18n(
"Add %1 to Project").arg(popupstr),
00568
this, SLOT(
slotAddToProject()) );
00569 popup->setWhatsThis(
id, i18n(
"<b>Add to project</b><p>Adds current file from the project."));
00570 }
00571 }
00572
00573
00574 void AntProjectPart::slotAddToProject()
00575 {
00576
QStringList fileList;
00577 fileList.append (
m_contextFileName );
00578
addFiles ( fileList );
00579 }
00580
00581
00582 void AntProjectPart::slotRemoveFromProject()
00583 {
00584
QStringList fileList;
00585 fileList.append (
m_contextFileName );
00586
removeFiles ( fileList );
00587 }
00588
00589
00590
#include "antprojectpart.moc"