KDevelop API Documentation

buildtools/custommakefiles/customprojectpart.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2001-2002 by Bernd Gehrmann * 00003 * bernd@kdevelop.org * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 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 00052 00053 typedef KDevGenericFactory<CustomProjectPart> CustomProjectFactory; 00054 static const KAboutData data("kdevcustomproject", I18N_NOOP("Build Tool"), "1.0"); 00055 K_EXPORT_COMPONENT_FACTORY( libkdevcustomproject, CustomProjectFactory( &data ) ) 00056 00057 CustomProjectPart::CustomProjectPart(QObject *parent, const char *name, const QStringList &) 00058 : KDevProject("CustomProject", "customproject", parent, name ? name : "CustomProjectPart") 00059 , m_lastCompilationFailed(false) 00060 { 00061 setInstance(CustomProjectFactory::instance()); 00062 setXMLFile("kdevcustomproject.rc"); 00063 00064 m_executeAfterBuild = false; 00065 00066 KAction *action; 00067 00068 action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8, 00069 this, SLOT(slotBuild()), 00070 actionCollection(), "build_build" ); 00071 action->setToolTip(i18n("Build project")); 00072 action->setWhatsThis(i18n("<b>Build project</b><p>Runs <b>make</b> from the project directory.<br>" 00073 "Environment variables and make arguments can be specified " 00074 "in the project settings dialog, <b>Build Options</b> tab.")); 00075 00076 action = new KAction( i18n("Compile &File"), "make_kdevelop", 00077 this, SLOT(slotCompileFile()), 00078 actionCollection(), "build_compilefile" ); 00079 action->setToolTip(i18n("Compile file")); 00080 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>" 00081 "Environment variables and make arguments can be specified " 00082 "in the project settings dialog, <b>Build Options</b> tab.")); 00083 00084 action = new KAction( i18n("&Clean Project"), 0, 00085 this, SLOT(slotClean()), 00086 actionCollection(), "build_clean" ); 00087 action->setToolTip(i18n("Clean project")); 00088 action->setWhatsThis(i18n("<b>Clean project</b><p>Runs <b>make clean</b> command from the project directory.<br>" 00089 "Environment variables and make arguments can be specified " 00090 "in the project settings dialog, <b>Build Options</b> tab.")); 00091 00092 action = new KAction( i18n("Execute Program"), "exec", 0, 00093 this, SLOT(slotExecute()), 00094 actionCollection(), "build_execute" ); 00095 action->setToolTip(i18n("Execute program")); 00096 action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the main program specified in project settings, <b>Run Options</b> tab. " 00097 "If it is not specified then the active target is used to determine the application to run.")); 00098 00099 KActionMenu *menu = new KActionMenu( i18n("Build &Target"), 00100 actionCollection(), "build_target" ); 00101 m_targetMenu = menu->popupMenu(); 00102 menu->setToolTip(i18n("Build target")); 00103 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>" 00104 "Environment variables and make arguments can be specified " 00105 "in the project settings dialog, <b>Build Options</b> tab.")); 00106 00107 m_makeEnvironmentsSelector = new KSelectAction( i18n("Make &Environment"),0, 00108 actionCollection(), "build_make_environment" ); 00109 m_makeEnvironmentsSelector->setToolTip(i18n("Make Environment")); 00110 m_makeEnvironmentsSelector->setWhatsThis(i18n("<b>Make Environment</b><p> Choose the set of environment variables to be passed on to make.<br>" 00111 "Environment variables can be specified in the project " 00112 "settings dialog, <b>Build Options</b> tab.")); 00113 00114 connect( m_targetMenu, SIGNAL(aboutToShow()), 00115 this, SLOT(updateTargetMenu()) ); 00116 connect( m_targetMenu, SIGNAL(activated(int)), 00117 this, SLOT(targetMenuActivated(int)) ); 00118 connect( m_makeEnvironmentsSelector->popupMenu(), SIGNAL(aboutToShow()), 00119 this, SLOT(updateMakeEnvironmentsMenu()) ); 00120 connect( m_makeEnvironmentsSelector->popupMenu(), SIGNAL(activated(int)), 00121 this, SLOT(makeEnvironmentsMenuActivated(int)) ); 00122 connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)), 00123 this, SLOT(projectConfigWidget(KDialogBase*)) ); 00124 connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)), 00125 this, SLOT(contextMenu(QPopupMenu *, const Context *)) ); 00126 00127 connect( makeFrontend(), SIGNAL(commandFinished(const QString&)), 00128 this, SLOT(slotCommandFinished(const QString&)) ); 00129 connect( makeFrontend(), SIGNAL(commandFailed(const QString&)), 00130 this, SLOT(slotCommandFailed(const QString&)) ); 00131 } 00132 00133 00134 CustomProjectPart::~CustomProjectPart() 00135 {} 00136 00137 00138 void CustomProjectPart::projectConfigWidget(KDialogBase *dlg) 00139 { 00140 QVBox *vbox; 00141 vbox = dlg->addVBoxPage(i18n("Run Options")); 00142 RunOptionsWidget *w1 = new RunOptionsWidget(*projectDom(), "/kdevcustomproject", buildDirectory(), vbox); 00143 connect( dlg, SIGNAL(okClicked()), w1, SLOT(accept()) ); 00144 vbox = dlg->addVBoxPage(i18n("Build Options")); 00145 QTabWidget *buildtab = new QTabWidget(vbox); 00146 00147 CustomBuildOptionsWidget *w2 = new CustomBuildOptionsWidget(*projectDom(), buildtab); 00148 connect( dlg, SIGNAL(okClicked()), w2, SLOT(accept()) ); 00149 buildtab->addTab(w2, i18n("&Build")); 00150 00151 CustomMakeConfigWidget *w3 = new CustomMakeConfigWidget(this, "/kdevcustomproject", buildtab); 00152 buildtab->addTab(w3, i18n("Ma&ke")); 00153 w2->setMakeOptionsWidget(buildtab, w3); 00154 connect( dlg, SIGNAL(okClicked()), w3, SLOT(accept()) ); 00155 } 00156 00157 00158 void CustomProjectPart::contextMenu(QPopupMenu *popup, const Context *context) 00159 { 00160 if (!context->hasType( Context::FileContext )) 00161 return; 00162 00163 const FileContext *fcontext = static_cast<const FileContext*>(context); 00164 if (fcontext->isDirectory()) { 00165 // remember the name of the directory 00166 m_contextDirName = fcontext->fileName(); 00167 m_contextDirName = m_contextDirName.mid ( project()->projectDirectory().length() + 1 ); 00168 popup->insertSeparator(); 00169 int id = popup->insertItem( i18n("Make Active Directory"), 00170 this, SLOT(slotChooseActiveDirectory()) ); 00171 popup->setWhatsThis(id, i18n("<b>Make active directory</b><p>" 00172 "Chooses this directory as the destination for new files created using wizards " 00173 "like the <i>New Class</i> wizard.")); 00174 return; 00175 } 00176 00177 m_contextFileName = fcontext->fileName(); 00178 bool inProject = project()->allFiles().contains(m_contextFileName.mid ( project()->projectDirectory().length() + 1 )); 00179 QString popupstr = QFileInfo(m_contextFileName).fileName(); 00180 if (m_contextFileName.startsWith(projectDirectory()+ "/")) 00181 m_contextFileName.remove(0, projectDirectory().length()+1); 00182 00183 popup->insertSeparator(); 00184 if (inProject) 00185 { 00186 int id = popup->insertItem( i18n("Remove %1 From Project").arg(popupstr), 00187 this, SLOT(slotRemoveFromProject()) ); 00188 popup->setWhatsThis(id, i18n("<b>Remove from project</b><p>Removes current file from the list of files in project. " 00189 "Note that the file should be manually excluded from corresponding makefile or build.xml.")); 00190 } 00191 else 00192 { 00193 int id = popup->insertItem( i18n("Add %1 to Project").arg(popupstr), 00194 this, SLOT(slotAddToProject()) ); 00195 popup->setWhatsThis(id, i18n("<b>Add to project</b><p>Adds current file to the list of files in project. " 00196 "Note that the file should be manually added to corresponding makefile or build.xml.")); 00197 } 00198 } 00199 00200 00201 void CustomProjectPart::slotAddToProject() 00202 { 00203 addFile(m_contextFileName); 00204 } 00205 00206 00207 void CustomProjectPart::slotRemoveFromProject() 00208 { 00209 removeFile(m_contextFileName); 00210 } 00211 00212 00213 void CustomProjectPart::slotChooseActiveDirectory() 00214 { 00215 QDomDocument &dom = *projectDom(); 00216 DomUtil::writeEntry(dom, "/kdevcustomproject/general/activedir", m_contextDirName); 00217 } 00218 00219 00220 void CustomProjectPart::openProject(const QString &dirName, const QString &projectName) 00221 { 00222 m_projectDirectory = dirName; 00223 m_projectName = projectName; 00224 00225 QDomDocument &dom = *projectDom(); 00226 // Set the default directory radio to "executable" 00227 if (DomUtil::readEntry(dom, "/kdevcustomproject/run/directoryradio") == "" ) { 00228 DomUtil::writeEntry(dom, "/kdevcustomproject/run/directoryradio", "executable"); 00229 } 00230 00231 QFile f(dirName + "/" + projectName + ".filelist"); 00232 if (f.open(IO_ReadOnly)) { 00233 QTextStream stream(&f); 00234 while (!stream.atEnd()) { 00235 QString s = stream.readLine(); 00236 if (!s.startsWith("#")) 00237 m_sourceFiles << s; 00238 } 00239 } else { 00240 int r = KMessageBox::questionYesNo(mainWindow()->main(), 00241 i18n("This project does not contain any files yet.\n" 00242 "Populate it with all C/C++/Java files below " 00243 "the project directory?")); 00244 if (r == KMessageBox::Yes) 00245 populateProject(); 00246 } 00247 00248 // check if there is an old envvars entry (from old project file with single make environment) 00249 QDomElement el = 00250 DomUtil::elementByPath( dom , "/kdevcustomproject/make/envvars"); 00251 if (!el.isNull()) { 00252 QDomElement envs = DomUtil::createElementByPath( dom , "/kdevcustomproject/make/environments"); 00253 DomUtil::makeEmpty(envs); 00254 el.setTagName("default"); 00255 envs.appendChild(el); 00256 } 00257 00258 KDevProject::openProject( dirName, projectName ); 00259 } 00260 00261 00262 void CustomProjectPart::populateProject() 00263 { 00264 QApplication::setOverrideCursor(Qt::waitCursor); 00265 00266 QValueStack<QString> s; 00267 int prefixlen = m_projectDirectory.length()+1; 00268 s.push(m_projectDirectory); 00269 00270 QDir dir; 00271 do { 00272 dir.setPath(s.pop()); 00273 kdDebug(9025) << "Examining: " << dir.path() << endl; 00274 const QFileInfoList *dirEntries = dir.entryInfoList(); 00275 if ( dirEntries ) 00276 { 00277 QPtrListIterator<QFileInfo> it(*dirEntries); 00278 for (; it.current(); ++it) { 00279 QString fileName = it.current()->fileName(); 00280 if (fileName == "." || fileName == "..") 00281 continue; 00282 QString path = it.current()->absFilePath(); 00283 if (it.current()->isDir()) { 00284 kdDebug(9025) << "Pushing: " << path << endl; 00285 s.push(path); 00286 } 00287 else { 00288 kdDebug(9025) << "Adding: " << path << endl; 00289 m_sourceFiles.append(path.mid(prefixlen)); 00290 } 00291 } 00292 } 00293 } while (!s.isEmpty()); 00294 00295 QApplication::restoreOverrideCursor(); 00296 } 00297 00298 00299 void CustomProjectPart::closeProject() 00300 { 00301 QFile f(m_projectDirectory + "/" + m_projectName + ".filelist"); 00302 if (!f.open(IO_WriteOnly)) 00303 return; 00304 00305 QTextStream stream(&f); 00306 stream << "# KDevelop Custom Project File List" << endl; 00307 00308 QStringList::ConstIterator it; 00309 for (it = m_sourceFiles.begin(); it != m_sourceFiles.end(); ++it) 00310 stream << (*it) << endl; 00311 f.close(); 00312 } 00313 00314 00315 QString CustomProjectPart::projectDirectory() const 00316 { 00317 return m_projectDirectory; 00318 } 00319 00320 00321 QString CustomProjectPart::projectName() const 00322 { 00323 return m_projectName; 00324 } 00325 00326 00328 DomUtil::PairList CustomProjectPart::runEnvironmentVars() const 00329 { 00330 return DomUtil::readPairListEntry(*projectDom(), "/kdevcustomproject/run/envvars", "envvar", "name", "value"); 00331 } 00332 00333 00343 QString CustomProjectPart::runDirectory() const 00344 { 00345 QDomDocument &dom = *projectDom(); 00346 00347 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevcustomproject/run/directoryradio"); 00348 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevcustomproject/run/mainprogram"); 00349 00350 if ( directoryRadioString == "build" ) 00351 return buildDirectory(); 00352 00353 if ( directoryRadioString == "custom" ) 00354 return DomUtil::readEntry(dom, "/kdevcustomproject/run/customdirectory"); 00355 00356 int pos = DomMainProgram.findRev('/'); 00357 if (pos != -1) 00358 return buildDirectory() + "/" + DomMainProgram.left(pos); 00359 00360 return buildDirectory() + "/" + DomMainProgram; 00361 00362 } 00363 00364 00374 QString CustomProjectPart::mainProgram(bool relative) const 00375 { 00376 QDomDocument &dom = *projectDom(); 00377 00378 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevcustomproject/run/directoryradio"); 00379 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevcustomproject/run/mainprogram"); 00380 00381 if ( directoryRadioString == "custom" ) 00382 return DomMainProgram; 00383 00384 if ( relative == false ) 00385 return buildDirectory() + "/" + DomMainProgram; 00386 00387 if ( directoryRadioString == "executable" ) { 00388 int pos = DomMainProgram.findRev('/'); 00389 if (pos != -1) 00390 return DomMainProgram.mid(pos+1); 00391 return DomMainProgram; 00392 } 00393 else 00394 return DomMainProgram; 00395 } 00396 00398 QString CustomProjectPart::runArguments() const 00399 { 00400 return DomUtil::readEntry(*projectDom(), "/kdevcustomproject/run/programargs"); 00401 } 00402 00403 QString CustomProjectPart::activeDirectory() const 00404 { 00405 QDomDocument &dom = *projectDom(); 00406 return DomUtil::readEntry(dom, "/kdevcustomproject/general/activedir"); 00407 } 00408 00409 00410 QStringList CustomProjectPart::allFiles() const 00411 { 00412 // QStringList res; 00413 // 00414 // QStringList::ConstIterator it; 00415 // for (it = m_sourceFiles.begin(); it != m_sourceFiles.end(); ++it) { 00416 // QString fileName = *it; 00417 // if (!fileName.startsWith("/")) { 00418 // fileName.prepend("/"); 00419 // fileName.prepend(m_projectDirectory); 00420 // } 00421 // res += fileName; 00422 // } 00423 // 00424 // return res; 00425 00426 // return all files relative to the project directory! 00427 return m_sourceFiles; 00428 } 00429 00430 00431 void CustomProjectPart::addFile(const QString &fileName) 00432 { 00433 QStringList fileList; 00434 fileList.append ( fileName ); 00435 00436 this->addFiles ( fileList ); 00437 } 00438 00439 void CustomProjectPart::addFiles ( const QStringList& fileList ) 00440 { 00441 QStringList::ConstIterator it; 00442 00443 for ( it = fileList.begin(); it != fileList.end(); ++it ) 00444 { 00445 m_sourceFiles.append ( *it ); 00446 } 00447 00448 kdDebug(9025) << "Emitting addedFilesToProject" << endl; 00449 emit addedFilesToProject ( fileList ); 00450 } 00451 00452 void CustomProjectPart::removeFile(const QString &fileName) 00453 { 00454 QStringList fileList; 00455 fileList.append ( fileName ); 00456 00457 this->removeFiles( fileList ); 00458 } 00459 00460 void CustomProjectPart::removeFiles ( const QStringList& fileList ) 00461 { 00462 kdDebug(9025) << "Emitting removedFilesFromProject" << endl; 00463 emit removedFilesFromProject ( fileList ); 00464 00465 QStringList::ConstIterator it; 00466 00467 for ( it = fileList.begin(); it != fileList.end(); ++it ) 00468 { 00469 m_sourceFiles.remove ( *it ); 00470 } 00471 } 00472 00473 QString CustomProjectPart::buildDirectory() const 00474 { 00475 QString dir = DomUtil::readEntry(*projectDom(), "/kdevcustomproject/build/builddir"); 00476 return dir.isEmpty()? projectDirectory() : dir; 00477 } 00478 00479 00480 QString CustomProjectPart::makeEnvironment() const 00481 { 00482 // Get the make environment variables pairs into the environstr string 00483 // in the form of: "ENV_VARIABLE=ENV_VALUE" 00484 // Note that we quote the variable value due to the possibility of 00485 // embedded spaces 00486 DomUtil::PairList envvars = 00487 DomUtil::readPairListEntry(*projectDom(), "/kdevcustomproject/make/environments/" + currentMakeEnvironment(), "envvar", "name", "value"); 00488 00489 QString environstr; 00490 DomUtil::PairList::ConstIterator it; 00491 for (it = envvars.begin(); it != envvars.end(); ++it) { 00492 environstr += (*it).first; 00493 environstr += "="; 00494 environstr += EnvVarTools::quote((*it).second); 00495 environstr += " "; 00496 } 00497 return environstr; 00498 } 00499 00500 00501 void CustomProjectPart::startMakeCommand(const QString &dir, const QString &target) 00502 { 00503 partController()->saveAllFiles(); 00504 00505 QDomDocument &dom = *projectDom(); 00506 bool ant = DomUtil::readEntry(dom, "/kdevcustomproject/build/buildtool") == "ant"; 00507 00508 QString cmdline; 00509 if (ant) { 00510 cmdline = "ant"; 00511 } else { 00512 cmdline = DomUtil::readEntry(dom, "/kdevcustomproject/make/makebin"); 00513 if (cmdline.isEmpty()) 00514 cmdline = MAKE_COMMAND; 00515 if (!DomUtil::readBoolEntry(dom, "/kdevcustomproject/make/abortonerror")) 00516 cmdline += " -k"; 00517 int jobs = DomUtil::readIntEntry(dom, "/kdevcustomproject/make/numberofjobs"); 00518 if (jobs != 0) { 00519 cmdline += " -j"; 00520 cmdline += QString::number(jobs); 00521 } 00522 if (DomUtil::readBoolEntry(dom, "/kdevcustomproject/make/dontact")) 00523 cmdline += " -n"; 00524 } 00525 00526 cmdline += " "; 00527 cmdline += target; 00528 00529 QString dircmd = "cd "; 00530 dircmd += dir; 00531 dircmd += " && "; 00532 00533 cmdline.prepend(makeEnvironment()); 00534 m_buildCommand = dircmd + cmdline; 00535 makeFrontend()->queueCommand(dir, dircmd + cmdline); 00536 } 00537 00538 00539 void CustomProjectPart::slotBuild() 00540 { 00541 m_lastCompilationFailed = false; 00542 startMakeCommand(buildDirectory(), QString::fromLatin1("")); 00543 } 00544 00545 00546 void CustomProjectPart::slotCompileFile() 00547 { 00548 KParts::ReadWritePart *part = dynamic_cast<KParts::ReadWritePart*>(partController()->activePart()); 00549 if (!part || !part->url().isLocalFile()) 00550 return; 00551 00552 QString fileName = part->url().path(); 00553 QFileInfo fi(fileName); 00554 QString sourceDir = fi.dirPath(); 00555 QString baseName = fi.baseName(true); 00556 kdDebug(9020) << "Compiling " << fileName 00557 << "in dir " << sourceDir 00558 << " with baseName " << baseName << endl; 00559 00560 // What would be nice: In case of non-recursive build system, climb up from 00561 // the source dir until a Makefile is found 00562 00563 QString buildDir = sourceDir; 00564 QString target = baseName + ".o"; 00565 kdDebug(9020) << "builddir " << buildDir << ", target " << target << endl; 00566 00567 startMakeCommand(buildDir, target); 00568 } 00569 00570 00571 void CustomProjectPart::slotClean() 00572 { 00573 startMakeCommand(buildDirectory(), QString::fromLatin1("clean")); 00574 } 00575 00576 00577 void CustomProjectPart::slotExecute() 00578 { 00579 partController()->saveAllFiles(); 00580 00581 if( DomUtil::readBoolEntry(*projectDom(), "/kdevcustomproject/run/autocompile", true) && isDirty() ){ 00582 m_executeAfterBuild = true; 00583 slotBuild(); 00584 return; 00585 } 00586 00587 // Get the run environment variables pairs into the environstr string 00588 // in the form of: "ENV_VARIABLE=ENV_VALUE" 00589 // Note that we quote the variable value due to the possibility of 00590 // embedded spaces 00591 DomUtil::PairList envvars = runEnvironmentVars(); 00592 QString environstr; 00593 DomUtil::PairList::ConstIterator it; 00594 for (it = envvars.begin(); it != envvars.end(); ++it) { 00595 environstr += (*it).first; 00596 environstr += "="; 00597 environstr += EnvVarTools::quote((*it).second); 00598 environstr += " "; 00599 } 00600 00601 if (mainProgram(true).isEmpty()) 00602 // Do not execute non executable targets 00603 return; 00604 00605 QString program = environstr; 00606 // Adds the ./ that is necessary to execute the program in bash shells 00607 if (!mainProgram(true).startsWith("/")) 00608 program += "./"; 00609 program += mainProgram(true); 00610 program += " " + runArguments(); 00611 00612 bool inTerminal = DomUtil::readBoolEntry(*projectDom(), "/kdevcustomproject/run/terminal"); 00613 00614 kdDebug(9025) << "runDirectory: <" << runDirectory() << ">" <<endl; 00615 kdDebug(9025) << "environstr : <" << environstr << ">" <<endl; 00616 kdDebug(9025) << "mainProgram : <" << mainProgram(true) << ">" <<endl; 00617 kdDebug(9025) << "runArguments: <" << runArguments() << ">" <<endl; 00618 00619 appFrontend()->startAppCommand(runDirectory(), program, inTerminal); 00620 } 00621 00622 00623 void CustomProjectPart::updateTargetMenu() 00624 { 00625 m_targets.clear(); 00626 m_targetMenu->clear(); 00627 00628 QDomDocument &dom = *projectDom(); 00629 bool ant = DomUtil::readEntry(dom, "/kdevcustomproject/build/buildtool") == "ant"; 00630 00631 if (ant) { 00632 QFile f(buildDirectory() + "/build.xml"); 00633 if (!f.open(IO_ReadOnly)) { 00634 kdDebug(9025) << "No build file" << endl; 00635 return; 00636 } 00637 QDomDocument dom; 00638 if (!dom.setContent(&f)) { 00639 kdDebug(9025) << "Build script not valid xml" << endl; 00640 f.close(); 00641 return; 00642 } 00643 f.close(); 00644 00645 QDomNode node = dom.documentElement().firstChild(); 00646 while (!node.isNull()) { 00647 if (node.toElement().tagName() == "target") 00648 m_targets.append(node.toElement().attribute("name")); 00649 node = node.nextSibling(); 00650 } 00651 } else { 00652 kdDebug(9025) << "Trying to load a makefile... " << endl; 00653 QFile f(buildDirectory() + "/Makefile"); 00654 if (!f.exists()) 00655 f.setName( buildDirectory() + "/makefile" ); 00656 if (!f.open(IO_ReadOnly)) { 00657 kdDebug(9025) << "No Makefile" << endl; 00658 return; 00659 } 00660 QTextStream stream(&f); 00661 //QRegExp re(".PHONY\\s*:(.*)"); 00662 QRegExp re("^([^($%.#][^)\\s]+):.*$"); 00663 re.setMinimal(true); 00664 QString str = ""; 00665 while (!stream.atEnd()) { 00666 QString str = stream.readLine(); 00667 // Read all continuation lines 00668 // kdDebug(9025) << "Trying: " << str.simplifyWhiteSpace() << endl; 00669 //while (str.right(1) == "\\" && !stream.atEnd()) { 00670 // str.remove(str.length()-1, 1); 00671 // str += stream.readLine(); 00672 //} 00673 if (re.search(str) != -1) 00674 { 00675 QString tmpTarget=re.cap(1).simplifyWhiteSpace(); 00676 kdDebug(9025) << "Adding target: " << tmpTarget << endl; 00677 if (m_targets.find(tmpTarget)==m_targets.end()) 00678 m_targets += tmpTarget; 00679 } 00680 } 00681 f.close(); 00682 m_targets.sort(); 00683 } 00684 00685 int id = 0; 00686 QStringList::ConstIterator it; 00687 for (it = m_targets.begin(); it != m_targets.end(); ++it) 00688 m_targetMenu->insertItem(*it, id++); 00689 } 00690 00691 00692 void CustomProjectPart::targetMenuActivated(int id) 00693 { 00694 QString target = m_targets[id]; 00695 startMakeCommand(buildDirectory(), target); 00696 } 00697 00698 void CustomProjectPart::updateMakeEnvironmentsMenu() 00699 { 00700 QDomDocument &dom = *projectDom(); 00701 bool makeUsed = (DomUtil::readEntry(dom, "/kdevcustomproject/build/buildtool") == "make"); 00702 if (makeUsed) { 00703 QStringList l = allMakeEnvironments(); 00704 m_makeEnvironmentsSelector->setItems(l); 00705 m_makeEnvironmentsSelector->setCurrentItem(l.findIndex(currentMakeEnvironment())); 00706 } 00707 else { 00708 m_makeEnvironmentsSelector->clear(); 00709 } 00710 /* 00711 m_makeEnvironmentsMenu->clear(); 00712 QDomDocument &dom = *projectDom(); 00713 00714 QStringList environments = allMakeEnvironments(); 00715 QStringList::ConstIterator it; 00716 int id = 0; 00717 for (it = environments.begin(); it != environments.end(); ++it) 00718 m_makeEnvironmentsMenu->insertItem(*it, id++); 00719 } 00720 */ 00721 } 00722 00723 void CustomProjectPart::makeEnvironmentsMenuActivated(int id) 00724 { 00725 QDomDocument &dom = *projectDom(); 00726 QString environment = allMakeEnvironments()[id]; 00727 DomUtil::writeEntry(dom, "/kdevcustomproject/make/selectedenvironment", environment); 00728 } 00729 00730 void CustomProjectPart::slotCommandFinished( const QString& command ) 00731 { 00732 kdDebug(9020) << "CustomProjectPart::slotProcessFinished()" << endl; 00733 00734 if( m_buildCommand != command ) 00735 return; 00736 00737 m_buildCommand = QString::null; 00738 00739 m_timestamp.clear(); 00740 QStringList fileList = allFiles(); 00741 QStringList::Iterator it = fileList.begin(); 00742 while( it != fileList.end() ){ 00743 QString fileName = *it; 00744 ++it; 00745 00746 m_timestamp[ fileName ] = QFileInfo( projectDirectory(), fileName ).lastModified(); 00747 } 00748 00749 emit projectCompiled(); 00750 00751 if( m_executeAfterBuild ){ 00752 slotExecute(); 00753 m_executeAfterBuild = false; 00754 } 00755 } 00756 00757 void CustomProjectPart::slotCommandFailed( const QString& /*command*/ ) 00758 { 00759 kdDebug(9020) << k_funcinfo << endl; 00760 00761 m_lastCompilationFailed = true; 00762 } 00763 00764 bool CustomProjectPart::isDirty() 00765 { 00766 if (m_lastCompilationFailed) return true; 00767 00768 QStringList fileList = allFiles(); 00769 QStringList::Iterator it = fileList.begin(); 00770 while( it != fileList.end() ){ 00771 QString fileName = *it; 00772 ++it; 00773 00774 QMap<QString, QDateTime>::Iterator it = m_timestamp.find( fileName ); 00775 QDateTime t = QFileInfo( projectDirectory(), fileName ).lastModified(); 00776 if( it == m_timestamp.end() || *it != t ){ 00777 return true; 00778 } 00779 } 00780 00781 return false; 00782 } 00783 00784 00785 QStringList CustomProjectPart::allMakeEnvironments() const 00786 { 00787 QDomDocument &dom = *projectDom(); 00788 00789 QStringList allConfigs; 00790 00791 QDomNode node = 00792 DomUtil::elementByPath( dom , "/kdevcustomproject/make/environments"); 00793 // extract the names of the different make environments 00794 QDomElement childEl = node.firstChild().toElement(); 00795 while (!childEl.isNull()) { 00796 QString config = childEl.tagName(); 00797 allConfigs.append(config); 00798 childEl = childEl.nextSibling().toElement(); 00799 } 00800 if (allConfigs.isEmpty()) 00801 allConfigs.append("default"); 00802 00803 return allConfigs; 00804 } 00805 00806 00807 QString CustomProjectPart::currentMakeEnvironment() const 00808 { 00809 QStringList allEnvs = allMakeEnvironments(); 00810 QDomDocument &dom = *projectDom(); 00811 QString environment = DomUtil::readEntry(dom, "/kdevcustomproject/make/selectedenvironment"); 00812 if (environment.isEmpty() || !allEnvs.contains(environment )) 00813 environment = allEnvs[0]; 00814 return environment; 00815 } 00816 00817 00818 #include "customprojectpart.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Oct 6 17:38:54 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003