00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "customprojectpart.h"
00013
00014 #include <qapplication.h>
00015 #include <qdir.h>
00016 #include <qfileinfo.h>
00017 #include <qpopupmenu.h>
00018 #include <qregexp.h>
00019 #include <qstringlist.h>
00020 #include <qtabwidget.h>
00021 #include <qvaluestack.h>
00022 #include <qvbox.h>
00023 #include <qwhatsthis.h>
00024 #include <qdom.h>
00025
00026 #include <kaction.h>
00027 #include <kdebug.h>
00028 #include <kdialogbase.h>
00029 #include <kdevgenericfactory.h>
00030 #include <kiconloader.h>
00031 #include <klocale.h>
00032 #include <kmainwindow.h>
00033 #include <kmessagebox.h>
00034 #include <kparts/part.h>
00035 #include <kpopupmenu.h>
00036 #include <kdeversion.h>
00037 #include <kprocess.h>
00038
00039 #include "domutil.h"
00040 #include "kdevcore.h"
00041 #include "kdevmainwindow.h"
00042 #include "kdevmakefrontend.h"
00043 #include "kdevappfrontend.h"
00044 #include "kdevpartcontroller.h"
00045 #include "runoptionswidget.h"
00046 #include "makeoptionswidget.h"
00047 #include "custombuildoptionswidget.h"
00048 #include "custommakeconfigwidget.h"
00049 #include "config.h"
00050 #include "envvartools.h"
00051 #include "urlutil.h"
00052
00053
00054 typedef KDevGenericFactory<CustomProjectPart> CustomProjectFactory;
00055 static const KAboutData data("kdevcustomproject", I18N_NOOP("Build Tool"), "1.0");
00056 K_EXPORT_COMPONENT_FACTORY( libkdevcustomproject, CustomProjectFactory( &data ) )
00057
00058 CustomProjectPart::CustomProjectPart(QObject *parent, const char *name, const QStringList &)
00059 : KDevProject("CustomProject", "customproject", parent, name ? name : "CustomProjectPart")
00060 , m_lastCompilationFailed(false)
00061 {
00062 setInstance(CustomProjectFactory::instance());
00063 setXMLFile("kdevcustomproject.rc");
00064
00065 m_executeAfterBuild = false;
00066
00067 KAction *action;
00068
00069 action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8,
00070 this, SLOT(slotBuild()),
00071 actionCollection(), "build_build" );
00072 action->setToolTip(i18n("Build project"));
00073 action->setWhatsThis(i18n("<b>Build project</b><p>Runs <b>make</b> from the project directory.<br>"
00074 "Environment variables and make arguments can be specified "
00075 "in the project settings dialog, <b>Build Options</b> tab."));
00076
00077 action = new KAction( i18n("Compile &File"), "make_kdevelop",
00078 this, SLOT(slotCompileFile()),
00079 actionCollection(), "build_compilefile" );
00080 action->setToolTip(i18n("Compile file"));
00081 action->setWhatsThis(i18n("<b>Compile file</b><p>Runs <b>make filename.o</b> command from the directory where 'filename' is the name of currently opened file.<br>"
00082 "Environment variables and make arguments can be specified "
00083 "in the project settings dialog, <b>Build Options</b> tab."));
00084
00085 action = new KAction( i18n("&Clean Project"), 0,
00086 this, SLOT(slotClean()),
00087 actionCollection(), "build_clean" );
00088 action->setToolTip(i18n("Clean project"));
00089 action->setWhatsThis(i18n("<b>Clean project</b><p>Runs <b>make clean</b> command from the project directory.<br>"
00090 "Environment variables and make arguments can be specified "
00091 "in the project settings dialog, <b>Build Options</b> tab."));
00092
00093 action = new KAction( i18n("Execute Program"), "exec", 0,
00094 this, SLOT(slotExecute()),
00095 actionCollection(), "build_execute" );
00096 action->setToolTip(i18n("Execute program"));
00097 action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the main program specified in project settings, <b>Run Options</b> tab. "
00098 "If it is not specified then the active target is used to determine the application to run."));
00099
00100 KActionMenu *menu = new KActionMenu( i18n("Build &Target"),
00101 actionCollection(), "build_target" );
00102 m_targetMenu = menu->popupMenu();
00103 menu->setToolTip(i18n("Build target"));
00104 menu->setWhatsThis(i18n("<b>Build target</b><p>Runs <b>make targetname</b> from the project directory (targetname is the name of the target selected).<br>"
00105 "Environment variables and make arguments can be specified "
00106 "in the project settings dialog, <b>Build Options</b> tab."));
00107
00108 m_makeEnvironmentsSelector = new KSelectAction( i18n("Make &Environment"),0,
00109 actionCollection(), "build_make_environment" );
00110 m_makeEnvironmentsSelector->setToolTip(i18n("Make environment"));
00111 m_makeEnvironmentsSelector->setWhatsThis(i18n("<b>Make Environment</b><p> Choose the set of environment variables to be passed on to make.<br>"
00112 "Environment variables can be specified in the project "
00113 "settings dialog, <b>Build Options</b> tab."));
00114
00115 connect( m_targetMenu, SIGNAL(aboutToShow()),
00116 this, SLOT(updateTargetMenu()) );
00117 connect( m_targetMenu, SIGNAL(activated(int)),
00118 this, SLOT(targetMenuActivated(int)) );
00119 connect( m_makeEnvironmentsSelector->popupMenu(), SIGNAL(aboutToShow()),
00120 this, SLOT(updateMakeEnvironmentsMenu()) );
00121 connect( m_makeEnvironmentsSelector->popupMenu(), SIGNAL(activated(int)),
00122 this, SLOT(makeEnvironmentsMenuActivated(int)) );
00123 connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)),
00124 this, SLOT(projectConfigWidget(KDialogBase*)) );
00125 connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)),
00126 this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
00127
00128 connect( makeFrontend(), SIGNAL(commandFinished(const QString&)),
00129 this, SLOT(slotCommandFinished(const QString&)) );
00130 connect( makeFrontend(), SIGNAL(commandFailed(const QString&)),
00131 this, SLOT(slotCommandFailed(const QString&)) );
00132 }
00133
00134
00135 CustomProjectPart::~CustomProjectPart()
00136 {}
00137
00138
00139 void CustomProjectPart::projectConfigWidget(KDialogBase *dlg)
00140 {
00141 QVBox *vbox;
00142 vbox = dlg->addVBoxPage(i18n("Run Options"));
00143 RunOptionsWidget *w1 = new RunOptionsWidget(*projectDom(), "/kdevcustomproject", buildDirectory(), vbox);
00144 connect( dlg, SIGNAL(okClicked()), w1, SLOT(accept()) );
00145 vbox = dlg->addVBoxPage(i18n("Build Options"));
00146 QTabWidget *buildtab = new QTabWidget(vbox);
00147
00148 CustomBuildOptionsWidget *w2 = new CustomBuildOptionsWidget(*projectDom(), buildtab);
00149 connect( dlg, SIGNAL(okClicked()), w2, SLOT(accept()) );
00150 buildtab->addTab(w2, i18n("&Build"));
00151
00152 CustomMakeConfigWidget *w3 = new CustomMakeConfigWidget(this, "/kdevcustomproject", buildtab);
00153 buildtab->addTab(w3, i18n("Ma&ke"));
00154 w2->setMakeOptionsWidget(buildtab, w3);
00155 connect( dlg, SIGNAL(okClicked()), w3, SLOT(accept()) );
00156 }
00157
00158
00159 void CustomProjectPart::contextMenu(QPopupMenu *popup, const Context *context)
00160 {
00161 if (!context->hasType( Context::FileContext ))
00162 return;
00163
00164 const FileContext *fcontext = static_cast<const FileContext*>(context);
00165 if (fcontext->isDirectory()) {
00166
00167 m_contextDirName = fcontext->fileName();
00168 m_contextDirName = m_contextDirName.mid ( project()->projectDirectory().length() + 1 );
00169 popup->insertSeparator();
00170 int id = popup->insertItem( i18n("Make Active Directory"),
00171 this, SLOT(slotChooseActiveDirectory()) );
00172 popup->setWhatsThis(id, i18n("<b>Make active directory</b><p>"
00173 "Chooses this directory as the destination for new files created using wizards "
00174 "like the <i>New Class</i> wizard."));
00175 return;
00176 }
00177 m_contextAddFiles.clear();
00178 m_contextRemoveFiles.clear();
00179
00180 if( fcontext->urls().size() == 1 )
00181 {
00182 QString contextFileName = URLUtil::canonicalPath(fcontext->fileName());
00183 bool inProject = project()->isProjectFile(contextFileName);
00184 QString popupstr = QFileInfo(contextFileName).fileName();
00185 if (contextFileName.startsWith(projectDirectory()+ "/"))
00186 contextFileName.remove(0, projectDirectory().length()+1);
00187
00188 popup->insertSeparator();
00189 if (inProject)
00190 {
00191 m_contextRemoveFiles << contextFileName;
00192 int id = popup->insertItem( i18n("Remove %1 From Project").arg(popupstr),
00193 this, SLOT(slotRemoveFromProject()) );
00194 popup->setWhatsThis(id, i18n("<b>Remove from project</b><p>Removes current file from the list of files in project. "
00195 "Note that the file should be manually excluded from corresponding makefile or build.xml."));
00196 }
00197 else
00198 {
00199 m_contextAddFiles << contextFileName;
00200 int id = popup->insertItem( i18n("Add %1 to Project").arg(popupstr),
00201 this, SLOT(slotAddToProject()) );
00202 popup->setWhatsThis(id, i18n("<b>Add to project</b><p>Adds current file to the list of files in project. "
00203 "Note that the file should be manually added to corresponding makefile or build.xml."));
00204 }
00205 }
00206 else
00207 {
00208 const KURL::List urls = fcontext->urls();
00209 for (KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it)
00210 {
00211 if ((*it).isLocalFile())
00212 {
00213 QString path(URLUtil::canonicalPath((*it).path()));
00214 QString relPath( path );
00215 if (relPath.startsWith(projectDirectory()+ "/"))
00216 relPath.remove(0, projectDirectory().length()+1);
00217 if (project()->isProjectFile(path))
00218 m_contextRemoveFiles << relPath;
00219 else
00220 m_contextAddFiles << relPath;
00221 }
00222 }
00223
00224 if (m_contextAddFiles.size() > 0)
00225 {
00226 int id = popup->insertItem( i18n("Add Selected Files to Project"),
00227 this, SLOT(slotAddToProject()) );
00228 popup->setWhatsThis(id, i18n("<b>Add to project</b><p>Adds selected files to the list of files in project. "
00229 "Note that the files should be manually added to corresponding makefile or build.xml."));
00230 }
00231
00232 if (m_contextRemoveFiles.size() > 0)
00233 {
00234 int id = popup->insertItem( i18n("Remove Selected Files From Project"),
00235 this, SLOT(slotRemoveFromProject()) );
00236 popup->setWhatsThis(id, i18n("<b>Remove from project</b><p>Removes selected files from the list of files in project. "
00237 "Note that the files should be manually excluded from corresponding makefile or build.xml."));
00238 }
00239 }
00240 }
00241
00242
00243 void CustomProjectPart::slotAddToProject()
00244 {
00245 addFiles(m_contextAddFiles);
00246 }
00247
00248
00249 void CustomProjectPart::slotRemoveFromProject()
00250 {
00251 removeFiles(m_contextRemoveFiles);
00252 }
00253
00254
00255 void CustomProjectPart::slotChooseActiveDirectory()
00256 {
00257 QDomDocument &dom = *projectDom();
00258 DomUtil::writeEntry(dom, "/kdevcustomproject/general/activedir", m_contextDirName);
00259 }
00260
00261
00262 void CustomProjectPart::openProject(const QString &dirName, const QString &projectName)
00263 {
00264 m_projectDirectory = dirName;
00265 m_projectName = projectName;
00266
00267 QDomDocument &dom = *projectDom();
00268
00269 if (DomUtil::readEntry(dom, "/kdevcustomproject/run/directoryradio") == "" ) {
00270 DomUtil::writeEntry(dom, "/kdevcustomproject/run/directoryradio", "executable");
00271 }
00272
00273
00274
00275
00276
00277 QString filelistDir=DomUtil::readEntry(dom, "/kdevcustomproject/filelistdirectory");
00278 if (filelistDir.isEmpty())
00279 filelistDir=dirName;
00280
00281 QFile f(filelistDir + "/" + projectName + ".filelist");
00282 if (f.open(IO_ReadOnly)) {
00283 QTextStream stream(&f);
00284 while (!stream.atEnd()) {
00285 QString s = stream.readLine();
00286 if (!s.startsWith("#"))
00287 m_sourceFiles << s;
00288 }
00289 } else {
00290 int r = KMessageBox::questionYesNo(mainWindow()->main(),
00291 i18n("This project does not contain any files yet.\n"
00292 "Populate it with all C/C++/Java files below "
00293 "the project directory?"));
00294 if (r == KMessageBox::Yes)
00295 populateProject();
00296 }
00297
00298
00299 QDomElement el =
00300 DomUtil::elementByPath( dom , "/kdevcustomproject/make/envvars");
00301 if (!el.isNull()) {
00302 QDomElement envs = DomUtil::createElementByPath( dom , "/kdevcustomproject/make/environments");
00303 DomUtil::makeEmpty(envs);
00304 el.setTagName("default");
00305 envs.appendChild(el);
00306 }
00307
00308 KDevProject::openProject( dirName, projectName );
00309 }
00310
00311
00312 void CustomProjectPart::populateProject()
00313 {
00314 QApplication::setOverrideCursor(Qt::waitCursor);
00315
00316 QValueStack<QString> s;
00317 int prefixlen = m_projectDirectory.length()+1;
00318 s.push(m_projectDirectory);
00319
00320 QDir dir;
00321 do {
00322 dir.setPath(s.pop());
00323 kdDebug(9025) << "Examining: " << dir.path() << endl;
00324 const QFileInfoList *dirEntries = dir.entryInfoList();
00325 if ( dirEntries )
00326 {
00327 QPtrListIterator<QFileInfo> it(*dirEntries);
00328 for (; it.current(); ++it) {
00329 QString fileName = it.current()->fileName();
00330 if (fileName == "." || fileName == "..")
00331 continue;
00332 QString path = it.current()->absFilePath();
00333 if (it.current()->isDir()) {
00334 kdDebug(9025) << "Pushing: " << path << endl;
00335 s.push(path);
00336 }
00337 else {
00338 kdDebug(9025) << "Adding: " << path << endl;
00339 m_sourceFiles.append(path.mid(prefixlen));
00340 }
00341 }
00342 }
00343 } while (!s.isEmpty());
00344
00345 QApplication::restoreOverrideCursor();
00346 }
00347
00348
00349 void CustomProjectPart::closeProject()
00350 {
00351 saveProject();
00352 }
00353
00354 void CustomProjectPart::saveProject()
00355 {
00356 QFile f(m_projectDirectory + "/" + m_projectName + ".filelist");
00357 if (!f.open(IO_WriteOnly))
00358 return;
00359
00360 QTextStream stream(&f);
00361 stream << "# KDevelop Custom Project File List" << endl;
00362
00363 QStringList::ConstIterator it;
00364 for (it = m_sourceFiles.begin(); it != m_sourceFiles.end(); ++it)
00365 stream << (*it) << endl;
00366 f.close();
00367 }
00368
00369
00370 QString CustomProjectPart::projectDirectory() const
00371 {
00372 return m_projectDirectory;
00373 }
00374
00375
00376 QString CustomProjectPart::projectName() const
00377 {
00378 return m_projectName;
00379 }
00380
00381
00383 DomUtil::PairList CustomProjectPart::runEnvironmentVars() const
00384 {
00385 return DomUtil::readPairListEntry(*projectDom(), "/kdevcustomproject/run/envvars", "envvar", "name", "value");
00386 }
00387
00388
00398 QString CustomProjectPart::runDirectory() const
00399 {
00400 QDomDocument &dom = *projectDom();
00401
00402 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevcustomproject/run/directoryradio");
00403 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevcustomproject/run/mainprogram");
00404
00405 if ( directoryRadioString == "build" )
00406 return buildDirectory();
00407
00408 if ( directoryRadioString == "custom" )
00409 return DomUtil::readEntry(dom, "/kdevcustomproject/run/customdirectory");
00410
00411 int pos = DomMainProgram.findRev('/');
00412 if (pos != -1)
00413 return buildDirectory() + "/" + DomMainProgram.left(pos);
00414
00415 return buildDirectory() + "/" + DomMainProgram;
00416
00417 }
00418
00419
00429 QString CustomProjectPart::mainProgram(bool relative) const
00430 {
00431 QDomDocument &dom = *projectDom();
00432
00433 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevcustomproject/run/directoryradio");
00434 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevcustomproject/run/mainprogram");
00435
00436 if ( directoryRadioString == "custom" )
00437 return DomMainProgram;
00438
00439 if ( relative == false )
00440 return buildDirectory() + "/" + DomMainProgram;
00441
00442 if ( directoryRadioString == "executable" ) {
00443 int pos = DomMainProgram.findRev('/');
00444 if (pos != -1)
00445 return DomMainProgram.mid(pos+1);
00446 return DomMainProgram;
00447 }
00448 else
00449 return DomMainProgram;
00450 }
00451
00453 QString CustomProjectPart::runArguments() const
00454 {
00455 return DomUtil::readEntry(*projectDom(), "/kdevcustomproject/run/programargs");
00456 }
00457
00458 QString CustomProjectPart::activeDirectory() const
00459 {
00460 QDomDocument &dom = *projectDom();
00461 return DomUtil::readEntry(dom, "/kdevcustomproject/general/activedir");
00462 }
00463
00464
00465 QStringList CustomProjectPart::allFiles() const
00466 {
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 return m_sourceFiles;
00483 }
00484
00485
00486 void CustomProjectPart::addFile(const QString &fileName)
00487 {
00488 QStringList fileList;
00489 fileList.append ( fileName );
00490
00491 this->addFiles ( fileList );
00492 }
00493
00494 void CustomProjectPart::addFiles ( const QStringList& fileList )
00495 {
00496 QStringList::ConstIterator it;
00497
00498 for ( it = fileList.begin(); it != fileList.end(); ++it )
00499 {
00500 m_sourceFiles.append ( *it );
00501 }
00502
00503 saveProject();
00504
00505 kdDebug(9025) << "Emitting addedFilesToProject" << endl;
00506 emit addedFilesToProject ( fileList );
00507 }
00508
00509 void CustomProjectPart::removeFile(const QString &fileName)
00510 {
00511 QStringList fileList;
00512 fileList.append ( fileName );
00513
00514 this->removeFiles( fileList );
00515 }
00516
00517 void CustomProjectPart::removeFiles ( const QStringList& fileList )
00518 {
00519 kdDebug(9025) << "Emitting removedFilesFromProject" << endl;
00520 emit removedFilesFromProject ( fileList );
00521
00522 QStringList::ConstIterator it;
00523
00524 for ( it = fileList.begin(); it != fileList.end(); ++it )
00525 {
00526 m_sourceFiles.remove ( *it );
00527 }
00528
00529 saveProject();
00530 }
00531
00532 QString CustomProjectPart::buildDirectory() const
00533 {
00534 QString dir = DomUtil::readEntry(*projectDom(), "/kdevcustomproject/build/builddir");
00535 return dir.isEmpty()? projectDirectory() : dir;
00536 }
00537
00538
00539 QString CustomProjectPart::makeEnvironment() const
00540 {
00541
00542
00543
00544
00545 DomUtil::PairList envvars =
00546 DomUtil::readPairListEntry(*projectDom(), "/kdevcustomproject/make/environments/" + currentMakeEnvironment(), "envvar", "name", "value");
00547
00548 QString environstr;
00549 DomUtil::PairList::ConstIterator it;
00550 for (it = envvars.begin(); it != envvars.end(); ++it) {
00551 environstr += (*it).first;
00552 environstr += "=";
00553 environstr += EnvVarTools::quote((*it).second);
00554 environstr += " ";
00555 }
00556 return environstr;
00557 }
00558
00559
00560 void CustomProjectPart::startMakeCommand(const QString &dir, const QString &target)
00561 {
00562 partController()->saveAllFiles();
00563
00564 QDomDocument &dom = *projectDom();
00565 bool ant = DomUtil::readEntry(dom, "/kdevcustomproject/build/buildtool") == "ant";
00566
00567 QString cmdline;
00568 if (ant) {
00569 cmdline = "ant";
00570 } else {
00571 cmdline = DomUtil::readEntry(dom, "/kdevcustomproject/make/makebin");
00572 if (cmdline.isEmpty())
00573 cmdline = MAKE_COMMAND;
00574 if (!DomUtil::readBoolEntry(dom, "/kdevcustomproject/make/abortonerror"))
00575 cmdline += " -k";
00576 int jobs = DomUtil::readIntEntry(dom, "/kdevcustomproject/make/numberofjobs");
00577 if (jobs != 0) {
00578 cmdline += " -j";
00579 cmdline += QString::number(jobs);
00580 }
00581 if (DomUtil::readBoolEntry(dom, "/kdevcustomproject/make/dontact"))
00582 cmdline += " -n";
00583 cmdline += " " + DomUtil::readEntry(dom, "/kdevcustomproject/make/makeoptions");
00584 }
00585
00586 cmdline += " ";
00587 cmdline += target;
00588
00589 QString dircmd = "cd ";
00590 dircmd += KProcess::quote(dir);
00591 dircmd += " && ";
00592
00593 int prio = DomUtil::readIntEntry(dom, "/kdevcustomproject/make/prio");
00594 QString nice;
00595 if (prio != 0) {
00596 nice = QString("nice -n%1 ").arg(prio);
00597 }
00598
00599 cmdline.prepend(nice);
00600 cmdline.prepend(makeEnvironment());
00601 m_buildCommand = dircmd + cmdline;
00602 makeFrontend()->queueCommand(dir, dircmd + cmdline);
00603 }
00604
00605
00606 void CustomProjectPart::slotBuild()
00607 {
00608 m_lastCompilationFailed = false;
00609 startMakeCommand(buildDirectory(), QString::fromLatin1(""));
00610 }
00611
00612
00613 void CustomProjectPart::slotCompileFile()
00614 {
00615 KParts::ReadWritePart *part = dynamic_cast<KParts::ReadWritePart*>(partController()->activePart());
00616 if (!part || !part->url().isLocalFile())
00617 return;
00618
00619 QString fileName = part->url().path();
00620 QFileInfo fi(fileName);
00621 QString sourceDir = fi.dirPath();
00622 QString baseName = fi.baseName(true);
00623 kdDebug(9020) << "Compiling " << fileName
00624 << "in dir " << sourceDir
00625 << " with baseName " << baseName << endl;
00626
00627
00628
00629
00630 QString buildDir = sourceDir;
00631 QString target = baseName + ".o";
00632 kdDebug(9020) << "builddir " << buildDir << ", target " << target << endl;
00633
00634 startMakeCommand(buildDir, target);
00635 }
00636
00637
00638 void CustomProjectPart::slotClean()
00639 {
00640 startMakeCommand(buildDirectory(), QString::fromLatin1("clean"));
00641 }
00642
00643
00644 void CustomProjectPart::slotExecute()
00645 {
00646 partController()->saveAllFiles();
00647
00648 if( DomUtil::readBoolEntry(*projectDom(), "/kdevcustomproject/run/autocompile", true) && isDirty() ){
00649 m_executeAfterBuild = true;
00650 slotBuild();
00651 return;
00652 }
00653
00654
00655
00656
00657
00658 DomUtil::PairList envvars = runEnvironmentVars();
00659 QString environstr;
00660 DomUtil::PairList::ConstIterator it;
00661 for (it = envvars.begin(); it != envvars.end(); ++it) {
00662 environstr += (*it).first;
00663 environstr += "=";
00664 environstr += EnvVarTools::quote((*it).second);
00665 environstr += " ";
00666 }
00667
00668 if (mainProgram(true).isEmpty())
00669
00670 return;
00671
00672 QString program = environstr;
00673
00674 if (!mainProgram(true).startsWith("/"))
00675 program += "./";
00676 program += mainProgram(true);
00677 program += " " + runArguments();
00678
00679 bool inTerminal = DomUtil::readBoolEntry(*projectDom(), "/kdevcustomproject/run/terminal");
00680
00681 kdDebug(9025) << "runDirectory: <" << runDirectory() << ">" <<endl;
00682 kdDebug(9025) << "environstr : <" << environstr << ">" <<endl;
00683 kdDebug(9025) << "mainProgram : <" << mainProgram(true) << ">" <<endl;
00684 kdDebug(9025) << "runArguments: <" << runArguments() << ">" <<endl;
00685
00686 appFrontend()->startAppCommand(runDirectory(), program, inTerminal);
00687 }
00688
00689
00690 void CustomProjectPart::updateTargetMenu()
00691 {
00692 m_targets.clear();
00693 m_targetMenu->clear();
00694
00695 QDomDocument &dom = *projectDom();
00696 bool ant = DomUtil::readEntry(dom, "/kdevcustomproject/build/buildtool") == "ant";
00697
00698 if (ant) {
00699 QFile f(buildDirectory() + "/build.xml");
00700 if (!f.open(IO_ReadOnly)) {
00701 kdDebug(9025) << "No build file" << endl;
00702 return;
00703 }
00704 QDomDocument dom;
00705 if (!dom.setContent(&f)) {
00706 kdDebug(9025) << "Build script not valid xml" << endl;
00707 f.close();
00708 return;
00709 }
00710 f.close();
00711
00712 QDomNode node = dom.documentElement().firstChild();
00713 while (!node.isNull()) {
00714 if (node.toElement().tagName() == "target")
00715 m_targets.append(node.toElement().attribute("name"));
00716 node = node.nextSibling();
00717 }
00718 } else {
00719 kdDebug(9025) << "Trying to load a makefile... " << endl;
00720 QFile f(buildDirectory() + "/Makefile");
00721 if (!f.exists())
00722 f.setName( buildDirectory() + "/makefile" );
00723 if (!f.open(IO_ReadOnly)) {
00724 kdDebug(9025) << "No Makefile" << endl;
00725 return;
00726 }
00727 QTextStream stream(&f);
00728
00729 QRegExp re("^([^($%.#][^)\\s]+):.*$");
00730 re.setMinimal(true);
00731 QString str = "";
00732 while (!stream.atEnd()) {
00733 QString str = stream.readLine();
00734
00735
00736
00737
00738
00739
00740 if (re.search(str) != -1)
00741 {
00742 QString tmpTarget=re.cap(1).simplifyWhiteSpace();
00743 kdDebug(9025) << "Adding target: " << tmpTarget << endl;
00744 if (m_targets.find(tmpTarget)==m_targets.end())
00745 m_targets += tmpTarget;
00746 }
00747 }
00748 f.close();
00749 m_targets.sort();
00750 }
00751
00752 int id = 0;
00753 QStringList::ConstIterator it;
00754 for (it = m_targets.begin(); it != m_targets.end(); ++it)
00755 m_targetMenu->insertItem(*it, id++);
00756 }
00757
00758
00759 void CustomProjectPart::targetMenuActivated(int id)
00760 {
00761 QString target = m_targets[id];
00762 startMakeCommand(buildDirectory(), target);
00763 }
00764
00765 void CustomProjectPart::updateMakeEnvironmentsMenu()
00766 {
00767 QDomDocument &dom = *projectDom();
00768 bool makeUsed = (DomUtil::readEntry(dom, "/kdevcustomproject/build/buildtool") == "make");
00769 if (makeUsed) {
00770 QStringList l = allMakeEnvironments();
00771 m_makeEnvironmentsSelector->setItems(l);
00772 m_makeEnvironmentsSelector->setCurrentItem(l.findIndex(currentMakeEnvironment()));
00773 }
00774 else {
00775 m_makeEnvironmentsSelector->clear();
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 }
00789
00790 void CustomProjectPart::makeEnvironmentsMenuActivated(int id)
00791 {
00792 QDomDocument &dom = *projectDom();
00793 QString environment = allMakeEnvironments()[id];
00794 DomUtil::writeEntry(dom, "/kdevcustomproject/make/selectedenvironment", environment);
00795 }
00796
00797 void CustomProjectPart::slotCommandFinished( const QString& command )
00798 {
00799 kdDebug(9020) << "CustomProjectPart::slotProcessFinished()" << endl;
00800
00801 if( m_buildCommand != command )
00802 return;
00803
00804 m_buildCommand = QString::null;
00805
00806 m_timestamp.clear();
00807 QStringList fileList = allFiles();
00808 QStringList::Iterator it = fileList.begin();
00809 while( it != fileList.end() ){
00810 QString fileName = *it;
00811 ++it;
00812
00813 m_timestamp[ fileName ] = QFileInfo( projectDirectory(), fileName ).lastModified();
00814 }
00815
00816 emit projectCompiled();
00817
00818 if( m_executeAfterBuild ){
00819 slotExecute();
00820 m_executeAfterBuild = false;
00821 }
00822 }
00823
00824 void CustomProjectPart::slotCommandFailed( const QString& )
00825 {
00826 kdDebug(9020) << k_funcinfo << endl;
00827
00828 m_lastCompilationFailed = true;
00829 }
00830
00831 bool CustomProjectPart::isDirty()
00832 {
00833 if (m_lastCompilationFailed) return true;
00834
00835 QStringList fileList = allFiles();
00836 QStringList::Iterator it = fileList.begin();
00837 while( it != fileList.end() ){
00838 QString fileName = *it;
00839 ++it;
00840
00841 QMap<QString, QDateTime>::Iterator it = m_timestamp.find( fileName );
00842 QDateTime t = QFileInfo( projectDirectory(), fileName ).lastModified();
00843 if( it == m_timestamp.end() || *it != t ){
00844 return true;
00845 }
00846 }
00847
00848 return false;
00849 }
00850
00851
00852 QStringList CustomProjectPart::allMakeEnvironments() const
00853 {
00854 QDomDocument &dom = *projectDom();
00855
00856 QStringList allConfigs;
00857
00858 QDomNode node =
00859 DomUtil::elementByPath( dom , "/kdevcustomproject/make/environments");
00860
00861 QDomElement childEl = node.firstChild().toElement();
00862 while (!childEl.isNull()) {
00863 QString config = childEl.tagName();
00864 allConfigs.append(config);
00865 childEl = childEl.nextSibling().toElement();
00866 }
00867 if (allConfigs.isEmpty())
00868 allConfigs.append("default");
00869
00870 return allConfigs;
00871 }
00872
00873
00874 QString CustomProjectPart::currentMakeEnvironment() const
00875 {
00876 QStringList allEnvs = allMakeEnvironments();
00877 QDomDocument &dom = *projectDom();
00878 QString environment = DomUtil::readEntry(dom, "/kdevcustomproject/make/selectedenvironment");
00879 if (environment.isEmpty() || !allEnvs.contains(environment ))
00880 environment = allEnvs[0];
00881 return environment;
00882 }
00883
00884
00885 #include "customprojectpart.moc"
00886
00887
00891 QStringList CustomProjectPart::distFiles() const
00892 {
00893 QStringList sourceList = allFiles();
00894
00895 QString projectDir = projectDirectory();
00896 QDir dir(projectDir);
00897 QStringList files = dir.entryList( "*README*");
00898 return sourceList + files;
00899 }