KDevelop API Documentation

buildtools/autotools/autoprojectpart.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2001-2002 by Bernd Gehrmann * 00003 * bernd@kdevelop.org * 00004 * * 00005 * Copyright (C) 2002 by Victor Roeder * 00006 * victor_roeder@gmx.de * 00007 * * 00008 * This program is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU General Public License as published by * 00010 * the Free Software Foundation; either version 2 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 ***************************************************************************/ 00014 00015 #include <config.h> 00016 00017 #include "autoprojectpart.h" 00018 #include "autolistviewitems.h" 00019 #include "configureoptionswidget.h" 00020 #include "addtranslationdlg.h" 00021 #include "addicondlg.h" 00022 #include "autoprojectwidget.h" 00023 00024 #include <qdom.h> 00025 #include <qdir.h> 00026 #include <qfileinfo.h> 00027 #include <qpopupmenu.h> 00028 #include <qstringlist.h> 00029 #include <qwhatsthis.h> 00030 #include <qregexp.h> 00031 #include <qgroupbox.h> 00032 00033 #include <kaction.h> 00034 #include <kdebug.h> 00035 #include <kdialogbase.h> 00036 #include <kiconloader.h> 00037 #include <klocale.h> 00038 #include <kmessagebox.h> 00039 #include <kparts/part.h> 00040 #include <kdeversion.h> 00041 #include <kprocess.h> 00042 00043 #include <domutil.h> 00044 #include <kdevcore.h> 00045 #include <kdevmakefrontend.h> 00046 #include <kdevappfrontend.h> 00047 #include <kdevmainwindow.h> 00048 #include <kdevpartcontroller.h> 00049 #include <makeoptionswidget.h> 00050 #include <runoptionswidget.h> 00051 #include <envvartools.h> 00052 00053 #include <configwidgetproxy.h> 00054 00055 #define CONFIGURE_OPTIONS 1 00056 #define RUN_OPTIONS 2 00057 #define MAKE_OPTIONS 3 00058 00059 static const KAboutData data("kdevautoproject", I18N_NOOP("Automake Manager"), "1.0"); 00060 00061 K_EXPORT_COMPONENT_FACTORY( libkdevautoproject, AutoProjectFactory( &data ) ) 00062 00063 AutoProjectPart::AutoProjectPart(QObject *parent, const char *name, const QStringList &args) 00064 : KDevProject("AutoProject", "autoproject", parent, name ? name : "AutoProjectPart") 00065 , m_lastCompilationFailed(false) 00066 { 00067 setInstance(AutoProjectFactory::instance()); 00068 00069 setXMLFile("kdevautoproject.rc"); 00070 00071 m_executeAfterBuild = false; 00072 m_isKDE = (args[0] == "kde"); 00073 m_needMakefileCvs = false; 00074 00075 m_widget = new AutoProjectWidget(this, m_isKDE); 00076 m_widget->setIcon(SmallIcon("make")); 00077 m_widget->setCaption(i18n("Automake Manager")); 00078 QWhatsThis::add(m_widget, i18n("<b>Automake manager</b><p>" 00079 "The project tree consists of two parts. The 'overview' " 00080 "in the upper half shows the subprojects, each one having a " 00081 "Makefile.am. The 'details' view in the lower half shows the " 00082 "targets and files for the subproject selected in the overview.")); 00083 00084 mainWindow()->embedSelectViewRight(m_widget, i18n("Automake Manager"), i18n("Automake manager")); 00085 00086 KAction *action; 00087 00088 action = new KAction( i18n("Add Translation..."), 0, 00089 this, SLOT(slotAddTranslation()), 00090 actionCollection(), "project_addtranslation" ); 00091 action->setToolTip(i18n("Add translation")); 00092 action->setWhatsThis(i18n("<b>Add translation</b><p>Creates .po file for the selected language.")); 00093 action->setGroup("autotools"); 00094 00095 /* action = new KAction ( i18n("&Import Existing Files && Directories..."), "", 0, 00096 this, SLOT ( slotImportExisting() ), 00097 actionCollection(), "project_importexisting" ); 00098 action->setStatusText ( i18n ( "Import existing files and directories to the currently loaded project" ) ); 00099 */ 00100 if (!m_isKDE) 00101 action->setEnabled(false); 00102 00103 action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8, 00104 this, SLOT(slotBuild()), 00105 actionCollection(), "build_build" ); 00106 action->setToolTip(i18n("Build project")); 00107 action->setWhatsThis(i18n("<b>Build project</b><p>Runs <b>make</b> from the project directory.<br>" 00108 "Environment variables and make arguments can be specified " 00109 "in the project settings dialog, <b>Make Options</b> tab.")); 00110 action->setGroup("autotools"); 00111 00112 action = new KAction( i18n("Build &Active Target"), "make_kdevelop", Key_F7, 00113 this, SLOT(slotBuildActiveTarget()), 00114 actionCollection(), "build_buildactivetarget" ); 00115 action->setToolTip(i18n("Build active target")); 00116 action->setWhatsThis(i18n("<b>Build active target</b><p>Constructs a series of make commands to build an active target. " 00117 "Also builds dependent targets.<br>" 00118 "Environment variables and make arguments can be specified " 00119 "in the project settings dialog, <b>Make Options</b> tab.")); 00120 action->setGroup("autotools"); 00121 00122 action = new KAction( i18n("Compile &File"), "make_kdevelop", 00123 this, SLOT(slotCompileFile()), 00124 actionCollection(), "build_compilefile" ); 00125 action->setToolTip(i18n("Compile file")); 00126 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>" 00127 "Environment variables and make arguments can be specified " 00128 "in the project settings dialog, <b>Make Options</b> tab.")); 00129 action->setGroup("autotools"); 00130 00131 action = new KAction( i18n("Run Configure"), 0, 00132 this, SLOT(slotConfigure()), 00133 actionCollection(), "build_configure" ); 00134 action->setToolTip(i18n("Run configure")); 00135 action->setWhatsThis(i18n("<b>Run configure</b><p>Executes <b>configure</b> with flags, arguments " 00136 "and environment variables specified in the project settings dialog, " 00137 "<b>Configure Options</b> tab.")); 00138 action->setGroup("autotools"); 00139 00140 action = new KAction( i18n("Run automake && friends"), 0, 00141 this, SLOT(slotMakefilecvs()), 00142 actionCollection(), "build_makefilecvs" ); 00143 action->setToolTip(i18n("Run automake && friends")); 00144 action->setWhatsThis(i18n("<b>Run automake && friends</b><p>Executes<br><b>make -f Makefile.cvs</b><br><b>./configure</b><br>commands from the project directory.")); 00145 action->setGroup("autotools"); 00146 00147 action = new KAction( i18n("Install"), 0, 00148 this, SLOT(slotInstall()), 00149 actionCollection(), "build_install" ); 00150 action->setToolTip(i18n("Install")); 00151 action->setWhatsThis(i18n("<b>Install</b><p>Runs <b>make install</b> command from the project directory.<br>" 00152 "Environment variables and make arguments can be specified " 00153 "in the project settings dialog, <b>Make Options</b> tab.")); 00154 action->setGroup("autotools"); 00155 00156 action = new KAction( i18n("Install (as root user)"), 0, 00157 this, SLOT(slotInstallWithKdesu()), 00158 actionCollection(), "build_install_kdesu" ); 00159 action->setToolTip(i18n("Install as root user")); 00160 action->setWhatsThis(i18n("<b>Install</b><p>Runs <b>make install</b> command from the project directory with root privileges.<br>" 00161 "It is executed via kdesu command.<br>" 00162 "Environment variables and make arguments can be specified " 00163 "in the project settings dialog, <b>Make Options</b> tab.")); 00164 action->setGroup("autotools"); 00165 00166 action = new KAction( i18n("&Clean Project"), 0, 00167 this, SLOT(slotClean()), 00168 actionCollection(), "build_clean" ); 00169 action->setToolTip(i18n("Clean project")); 00170 action->setWhatsThis(i18n("<b>Clean project</b><p>Runs <b>make clean</b> command from the project directory.<br>" 00171 "Environment variables and make arguments can be specified " 00172 "in the project settings dialog, <b>Make Options</b> tab.")); 00173 action->setGroup("autotools"); 00174 00175 action = new KAction( i18n("&Distclean"), 0, 00176 this, SLOT(slotDistClean()), 00177 actionCollection(), "build_distclean" ); 00178 action->setToolTip(i18n("Distclean")); 00179 action->setWhatsThis(i18n("<b>Distclean</b><p>Runs <b>make distclean</b> command from the project directory.<br>" 00180 "Environment variables and make arguments can be specified " 00181 "in the project settings dialog, <b>Make Options</b> tab.")); 00182 action->setGroup("autotools"); 00183 00184 action = new KAction( i18n("Make Messages && Merge"), 0, 00185 this, SLOT(slotMakeMessages()), 00186 actionCollection(), "build_messages" ); 00187 action->setToolTip(i18n("Make messages && merge")); 00188 action->setWhatsThis(i18n("<b>Make messages && merge</b><p>Runs <b>make package-messages</b> command from the project directory.<br>" 00189 "Environment variables and make arguments can be specified " 00190 "in the project settings dialog, <b>Make Options</b> tab.")); 00191 action->setGroup("autotools"); 00192 00193 if (!m_isKDE) 00194 action->setEnabled(false); 00195 00196 buildConfigAction = new KSelectAction( i18n("Build Configuration"), 0, 00197 actionCollection(), "project_configuration" ); 00198 buildConfigAction->setToolTip(i18n("Build configuration menu")); 00199 buildConfigAction->setWhatsThis(i18n("<b>Build configuration menu</b><p>Allows to switch between project build configurations.<br>" 00200 "Build configuration is a set of build and top source directory settings, " 00201 "configure flags and arguments, compiler flags, etc.<br>" 00202 "Modify build configurations in project settings dialog, <b>Configure Options</b> tab.")); 00203 buildConfigAction->setGroup("autotools"); 00204 00205 QDomDocument &dom = *projectDom(); 00206 if (!DomUtil::readBoolEntry(dom, "/kdevautoproject/run/disable_default")) { 00207 //ok we handle the execute in this kpart 00208 action = new KAction( i18n("Execute Program"), "exec", SHIFT+Key_F9, 00209 this, SLOT(slotExecute()), 00210 actionCollection(), "build_execute" ); 00211 action->setToolTip(i18n("Execute program")); 00212 action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the main program specified in project settings, <b>Run Options</b> tab. " 00213 "If it is not specified then the active target is used to determine the application to run.")); 00214 action->setGroup("autotools"); 00215 } 00216 00217 connect( buildConfigAction, SIGNAL(activated(const QString&)), 00218 this, SLOT(slotBuildConfigChanged(const QString&)) ); 00219 connect( buildConfigAction->popupMenu(), SIGNAL(aboutToShow()), 00220 this, SLOT(slotBuildConfigAboutToShow()) ); 00221 00222 // connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)), this, SLOT(projectConfigWidget(KDialogBase*)) ); 00223 00224 _configProxy = new ConfigWidgetProxy( core() ); 00225 _configProxy->createProjectConfigPage( i18n("Configure Options"), CONFIGURE_OPTIONS ); 00226 _configProxy->createProjectConfigPage( i18n("Run Options"), RUN_OPTIONS ); 00227 _configProxy->createProjectConfigPage( i18n("Make Options"), MAKE_OPTIONS ); 00228 connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )), this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) ); 00229 00230 00231 connect( makeFrontend(), SIGNAL(commandFinished(const QString&)), 00232 this, SLOT(slotCommandFinished(const QString&)) ); 00233 connect( makeFrontend(), SIGNAL(commandFailed(const QString&)), 00234 this, SLOT(slotCommandFailed(const QString&)) ); 00235 00236 setWantautotools(); 00237 } 00238 00239 00240 AutoProjectPart::~AutoProjectPart() 00241 { 00242 if (m_widget) 00243 mainWindow()->removeView(m_widget); 00244 delete m_widget; 00245 delete _configProxy; 00246 } 00247 00248 /*void AutoProjectPart::slotImportExisting() 00249 { 00250 ImportExistingDlg( this, m_widget, "import_existing", true ).exec(); 00251 }*/ 00252 /* 00253 void AutoProjectPart::projectConfigWidget(KDialogBase *dlg) 00254 { 00255 QVBox *vbox; 00256 vbox = dlg->addVBoxPage(i18n("Configure Options")); 00257 ConfigureOptionsWidget *w2 = new ConfigureOptionsWidget(this, vbox); 00258 connect( dlg, SIGNAL(okClicked()), w2, SLOT(accept()) ); 00259 QDomDocument &dom = *projectDom(); 00260 if (!DomUtil::readBoolEntry(dom, "/kdevautoproject/run/disable_default")) { 00261 //ok we handle the execute in this kpart 00262 vbox = dlg->addVBoxPage(i18n("Run Options")); 00263 RunOptionsWidget *w3 = new RunOptionsWidget(*projectDom(), "/kdevautoproject", buildDirectory(), vbox); 00264 w3->programGroupBox->setTitle(i18n("Program (if empty automatically uses active target and active target's arguments)")); 00265 connect( dlg, SIGNAL(okClicked()), w3, SLOT(accept()) ); 00266 } 00267 vbox = dlg->addVBoxPage(i18n("Make Options")); 00268 MakeOptionsWidget *w4 = new MakeOptionsWidget(*projectDom(), "/kdevautoproject", vbox); 00269 connect( dlg, SIGNAL(okClicked()), w4, SLOT(accept()) ); 00270 } 00271 */ 00272 00273 void AutoProjectPart::insertConfigWidget( const KDialogBase* dlg, QWidget * page, unsigned int pagenumber ) 00274 { 00275 switch ( pagenumber ) 00276 { 00277 case CONFIGURE_OPTIONS: 00278 { 00279 ConfigureOptionsWidget *w2 = new ConfigureOptionsWidget(this, page ); 00280 connect( dlg, SIGNAL(okClicked()), w2, SLOT(accept()) ); 00281 } 00282 break; 00283 00284 case RUN_OPTIONS: 00285 { 00286 QDomDocument &dom = *projectDom(); 00287 if (!DomUtil::readBoolEntry(dom, "/kdevautoproject/run/disable_default")) { 00288 //ok we handle the execute in this kpart 00289 RunOptionsWidget *w3 = new RunOptionsWidget(*projectDom(), "/kdevautoproject", buildDirectory(), page ); 00290 w3->programGroupBox->setTitle(i18n("Program (if empty automatically uses active target and active target's arguments)")); 00291 connect( dlg, SIGNAL(okClicked()), w3, SLOT(accept()) ); 00292 } 00293 } 00294 break; 00295 00296 case MAKE_OPTIONS: 00297 { 00298 MakeOptionsWidget *w4 = new MakeOptionsWidget(*projectDom(), "/kdevautoproject", page ); 00299 connect( dlg, SIGNAL(okClicked()), w4, SLOT(accept()) ); 00300 } 00301 break; 00302 } 00303 } 00304 00305 void AutoProjectPart::openProject(const QString &dirName, const QString &projectName) 00306 { 00307 m_projectName = projectName; 00308 m_projectPath =dirName; 00309 00310 m_widget->openProject(dirName); 00311 00312 QDomDocument &dom = *projectDom(); 00313 QString activeTarget = DomUtil::readEntry(dom, "/kdevautoproject/general/activetarget"); 00314 kdDebug(9020) << "activeTarget " << activeTarget << endl; 00315 if (!activeTarget.isEmpty()) 00316 m_widget->setActiveTarget(activeTarget); 00317 00318 // Set the default directory radio to "executable" 00319 if (!DomUtil::readBoolEntry(dom, "/kdevautoproject/run/disable_default") && DomUtil::readEntry(dom, "/kdevautoproject/run/directoryradio") == "" ) { 00320 DomUtil::writeEntry(dom, "/kdevautoproject/run/directoryradio", "executable"); 00321 } 00322 00323 KDevProject::openProject( dirName, projectName ); 00324 } 00325 00326 00327 void AutoProjectPart::closeProject() 00328 { 00329 m_widget->closeProject(); 00330 } 00331 00332 00333 QString AutoProjectPart::projectDirectory() const 00334 { 00335 return m_projectPath; 00336 } 00337 00338 00339 QString AutoProjectPart::projectName() const 00340 { 00341 return m_projectName; 00342 } 00343 00344 00346 DomUtil::PairList AutoProjectPart::runEnvironmentVars() const 00347 { 00348 return DomUtil::readPairListEntry(*projectDom(), "/kdevautoproject/run/envvars", "envvar", "name", "value"); 00349 } 00350 00351 00363 QString AutoProjectPart::runDirectory() const 00364 { 00365 QDomDocument &dom = *projectDom(); 00366 00367 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevautoproject/run/directoryradio"); 00368 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevautoproject/run/mainprogram"); 00369 00370 if ( directoryRadioString == "build" ) 00371 return buildDirectory(); 00372 00373 if ( directoryRadioString == "custom" ) 00374 return DomUtil::readEntry(dom, "/kdevautoproject/run/customdirectory"); 00375 00376 if ( DomMainProgram.isEmpty() ) 00377 // No Main Program was specified, return the directory of the active target 00378 return buildDirectory() + "/" + activeDirectory(); 00379 00380 // A Main Program was specified, return it's run directory 00381 int pos = DomMainProgram.findRev('/'); 00382 if (pos != -1) 00383 return buildDirectory() + "/" + DomMainProgram.left(pos); 00384 return buildDirectory() + "/" + DomMainProgram; 00385 } 00386 00387 00399 QString AutoProjectPart::mainProgram(bool relative) const 00400 { 00401 QDomDocument &dom = *projectDom(); 00402 00403 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevautoproject/run/directoryradio"); 00404 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevautoproject/run/mainprogram"); 00405 00406 if ( DomMainProgram.isEmpty() ) { 00407 // If no Main Program was specified, return the active target 00408 00409 // Get a pointer to the active target 00410 TargetItem* titem = m_widget->activeTarget(); 00411 00412 if ( !titem ) { 00413 kdDebug ( 9000 ) << "Error! : No Main Program was specified and there's no active target! -> Unable to determine the main program in AutoProjectPart::mainProgram()" << endl; 00414 return QString::null; 00415 } 00416 00417 if ( titem->primary != "PROGRAMS" ) { 00418 kdDebug ( 9000 ) << "Error! : No Main Program was specified and active target isn't binary (" << titem->primary << ") ! -> Unable to determine the main program in AutoProjectPart::mainProgram()" << endl; 00419 return QString::null; 00420 } 00421 00422 if (relative == false || directoryRadioString == "custom") 00423 return buildDirectory() + "/" + activeDirectory() + "/" + titem->name; 00424 00425 if ( directoryRadioString == "executable" ) 00426 return titem->name; 00427 00428 return activeDirectory() + "/" + titem->name; 00429 00430 } 00431 else { 00432 // A Main Program was specified, return it 00433 if ( directoryRadioString == "custom" ) 00434 return DomMainProgram; 00435 00436 if ( relative == false ) 00437 return buildDirectory() + "/" + DomMainProgram; 00438 00439 if ( directoryRadioString != "executable" ) 00440 return DomMainProgram; 00441 00442 int pos = DomMainProgram.findRev('/'); 00443 if (pos != -1) 00444 return DomMainProgram.mid(pos+1); 00445 return DomMainProgram; 00446 } 00447 } 00448 00449 00451 QString AutoProjectPart::runArguments() const 00452 { 00453 QDomDocument &dom = *projectDom(); 00454 00455 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevautoproject/run/mainprogram"); 00456 QString DomProgramArguments = DomUtil::readEntry(*projectDom(), "/kdevautoproject/run/programargs"); 00457 00458 if ( DomMainProgram.isEmpty() && DomProgramArguments.isEmpty() ) 00459 // If no "Main Program" and no "Program Arguments" were specified, return the active target's run arguments 00460 if (m_widget->activeTarget()) 00461 return DomUtil::readEntry(*projectDom(), "/kdevautoproject/run/runarguments/" + m_widget->activeTarget()->name); 00462 else 00463 return QString::null; 00464 else 00465 return DomProgramArguments; 00466 } 00467 00468 00469 QString AutoProjectPart::activeDirectory() const 00470 { 00471 return m_widget->activeDirectory(); 00472 } 00473 00474 00475 QStringList AutoProjectPart::allFiles() const 00476 { 00477 return m_widget->allFiles(); 00478 } 00479 00480 00481 void AutoProjectPart::setWantautotools() 00482 { 00483 QDomDocument &dom = *projectDom(); 00484 QDomElement el = DomUtil::elementByPath(dom, "/kdevautoproject/make"); 00485 if ( el.namedItem("envvars").isNull() ) { 00486 DomUtil::PairList list; 00487 list << DomUtil::Pair("WANT_AUTOCONF_2_5", "1"); 00488 list << DomUtil::Pair("WANT_AUTOMAKE_1_6", "1"); 00489 DomUtil::writePairListEntry(dom, "/kdevautoproject/make/envvars", "envvar", "name", "value", list); 00490 } 00491 } 00492 00493 00494 QString AutoProjectPart::makeEnvironment() const 00495 { 00496 // Get the make environment variables pairs into the environstr string 00497 // in the form of: "ENV_VARIABLE=ENV_VALUE" 00498 // Note that we quote the variable value due to the possibility of 00499 // embedded spaces 00500 DomUtil::PairList envvars = 00501 DomUtil::readPairListEntry(*projectDom(), "/kdevautoproject/make/envvars", "envvar", "name", "value"); 00502 00503 QString environstr; 00504 DomUtil::PairList::ConstIterator it; 00505 for (it = envvars.begin(); it != envvars.end(); ++it) { 00506 environstr += (*it).first; 00507 environstr += "="; 00508 /* 00509 #if (KDE_VERSION > 305) 00510 environstr += KProcess::quote((*it).second); 00511 #else 00512 environstr += KShellProcess::quote((*it).second); 00513 #endif 00514 */ 00515 environstr += EnvVarTools::quote((*it).second); 00516 environstr += " "; 00517 } 00518 return environstr; 00519 } 00520 00521 00522 void AutoProjectPart::addFile(const QString &fileName) 00523 { 00524 QStringList fileList; 00525 fileList.append ( fileName ); 00526 00527 this->addFiles ( fileList ); 00528 } 00529 00530 void AutoProjectPart::addFiles ( const QStringList& fileList ) 00531 { 00532 QString directory, name; 00533 QStringList::ConstIterator it; 00534 bool messageBoxShown = false; 00535 00536 for ( it = fileList.begin(); it != fileList.end(); ++it ) 00537 { 00538 int pos = ( *it ).findRev('/'); 00539 if (pos != -1) 00540 { 00541 directory = ( *it ).left(pos); 00542 name = ( *it ).mid(pos+1); 00543 } 00544 else 00545 { 00546 directory = ""; 00547 name = ( *it ); 00548 } 00549 00550 if (directory != m_widget->activeDirectory() || 00551 directory.isEmpty()) 00552 { 00553 if ( !messageBoxShown ) 00554 { 00555 KMessageBox::information(m_widget, i18n("The directory you selected is not the active directory!\n" 00556 "You should 'activate' the target you're currently working on in Automake Manager.\n" 00557 "Just right-click a target and choose 'Make Target Active'."), 00558 i18n ( "No Active Target Found" ), "No automake manager active target warning" ); 00559 messageBoxShown = true; 00560 } 00561 } 00562 } 00563 00564 m_widget->addFiles(fileList); 00565 } 00566 00567 void AutoProjectPart::removeFile(const QString &fileName) 00568 { 00569 QStringList fileList; 00570 fileList.append ( fileName ); 00571 00572 this->removeFiles ( fileList ); 00573 } 00574 00575 void AutoProjectPart::removeFiles ( const QStringList& fileList ) 00576 { 00578 m_widget->removeFiles ( fileList ); 00579 00580 emit removedFilesFromProject ( fileList ); 00581 } 00582 00583 QStringList AutoProjectPart::allBuildConfigs() const 00584 { 00585 QDomDocument &dom = *projectDom(); 00586 00587 QStringList allConfigs; 00588 allConfigs.append("default"); 00589 00590 QDomNode node = dom.documentElement().namedItem("kdevautoproject").namedItem("configurations"); 00591 QDomElement childEl = node.firstChild().toElement(); 00592 while (!childEl.isNull()) { 00593 QString config = childEl.tagName(); 00594 kdDebug(9020) << "Found config " << config << endl; 00595 if (config != "default") 00596 allConfigs.append(config); 00597 childEl = childEl.nextSibling().toElement(); 00598 } 00599 00600 return allConfigs; 00601 } 00602 00603 00604 QString AutoProjectPart::currentBuildConfig() const 00605 { 00606 QDomDocument &dom = *projectDom(); 00607 00608 QString config = DomUtil::readEntry(dom, "/kdevautoproject/general/useconfiguration"); 00609 if (config.isEmpty() || !allBuildConfigs().contains(config)) 00610 config = "default"; 00611 00612 return config; 00613 } 00614 00615 00616 QString AutoProjectPart::buildDirectory() const 00617 { 00618 QString prefix = "/kdevautoproject/configurations/" + currentBuildConfig() + "/"; 00619 00620 QString builddir = DomUtil::readEntry(*projectDom(), prefix + "builddir"); 00621 if (builddir.isEmpty()) 00622 return topsourceDirectory(); 00623 else if (builddir.startsWith("/")) 00624 return builddir; 00625 else 00626 return projectDirectory() + "/" + builddir; 00627 } 00628 00629 QString AutoProjectPart::topsourceDirectory() const 00630 { 00631 QString prefix = "/kdevautoproject/configurations/" + currentBuildConfig() + "/"; 00632 00633 QString topsourcedir = DomUtil::readEntry(*projectDom(), prefix + "topsourcedir"); 00634 if (topsourcedir.isEmpty()) 00635 return projectDirectory(); 00636 else if (topsourcedir.startsWith("/")) 00637 return topsourcedir; 00638 else 00639 return projectDirectory() + "/" + topsourcedir; 00640 } 00641 00642 QString AutoProjectPart::constructMakeCommandLine(const QString &dir, const QString &target) const 00643 { 00644 00645 QString preCommand; 00646 QFileInfo fi1(); 00647 if ( !QFile::exists(dir + "/GNUmakefile") && !QFile::exists(dir + "/makefile") 00648 && ! QFile::exists(dir + "/Makefile") ) { 00649 if (!QFile::exists(buildDirectory() + "/configure")) { 00650 int r = KMessageBox::questionYesNo(m_widget, i18n("There is no Makefile in this directory\n" 00651 "and no configure script for this project.\n" 00652 "Run automake & friends and configure first?")); 00653 if (r == KMessageBox::No) 00654 return 0; 00655 preCommand = makefileCvsCommand(); 00656 if (preCommand.isNull()) 00657 return 0; 00658 preCommand += " && "; 00659 preCommand += configureCommand() + " && "; 00660 } else { 00661 int r = KMessageBox::questionYesNo(m_widget, i18n("There is no Makefile in this directory. Run 'configure' first?")); 00662 if (r == KMessageBox::No) 00663 return 0; 00664 preCommand = configureCommand() + " && "; 00665 } 00666 } 00667 QDomDocument &dom = *projectDom(); 00668 00669 QString cmdline = DomUtil::readEntry(dom, "/kdevautoproject/make/makebin"); 00670 if (cmdline.isEmpty()) 00671 cmdline = MAKE_COMMAND; 00672 if (!DomUtil::readBoolEntry(dom, "/kdevautoproject/make/abortonerror")) 00673 cmdline += " -k"; 00674 int jobs = DomUtil::readIntEntry(dom, "/kdevautoproject/make/numberofjobs"); 00675 if (jobs != 0) { 00676 cmdline += " -j"; 00677 cmdline += QString::number(jobs); 00678 } 00679 if (DomUtil::readBoolEntry(dom, "/kdevautoproject/make/dontact")) 00680 cmdline += " -n"; 00681 00682 cmdline += " "; 00683 cmdline += target; 00684 cmdline.prepend(makeEnvironment()); 00685 00686 QString dircmd = "cd \""; 00687 dircmd += dir; 00688 dircmd += "\" && "; 00689 00690 return preCommand + dircmd + cmdline; 00691 } 00692 00693 00694 void AutoProjectPart::startMakeCommand(const QString &dir, const QString &target, bool withKdesu) 00695 { 00696 partController()->saveAllFiles(); 00697 00698 m_buildCommand = constructMakeCommandLine(dir, target); 00699 00700 if (withKdesu) 00701 m_buildCommand = "kdesu -t -c '" + m_buildCommand + "'"; 00702 00703 if (!m_buildCommand.isNull()) 00704 makeFrontend()->queueCommand(dir, m_buildCommand); 00705 } 00706 00707 00710 void AutoProjectPart::queueInternalLibDependenciesBuild(TargetItem* titem) 00711 { 00712 00713 QString addstr = (titem->primary == "PROGRAMS")? titem->ldadd : titem->libadd; 00714 QStringList l2 = QStringList::split(QRegExp("[ \t]"), addstr); // list of dependencies 00715 QString tdir; // temp target directory 00716 QString tname; // temp target name 00717 QString tcmd; // temp command line 00718 QStringList::Iterator l2it; 00719 for (l2it = l2.begin(); l2it != l2.end(); ++l2it) { 00720 QString dependency = *l2it; 00721 if (dependency.startsWith("$(top_builddir)/")) { 00722 // These are the internal libraries 00723 #if KDE_VERSION > 305 00724 dependency.remove("$(top_builddir)/"); 00725 #else 00726 QString topBuildDirStr("$(top_builddir)/"); 00727 int i = dependency.find(topBuildDirStr); 00728 if (i != -1) { 00729 dependency.remove(i, i + topBuildDirStr.length() - 1); 00730 } 00731 #endif 00732 tdir = buildDirectory(); 00733 if (!tdir.endsWith("/") && !tdir.isEmpty()) 00734 tdir += "/"; 00735 int pos = dependency.findRev('/'); 00736 if (pos == -1) { 00737 tname = dependency; 00738 } else { 00739 tdir += dependency.left(pos+1); 00740 tname = dependency.mid(pos+1); 00741 } 00742 kdDebug(9020) << "Scheduling : <" << tdir << "> target <" << tname << ">" << endl; 00743 00744 // Recursively queue the dependencies for building 00745 SubprojectItem *spi = m_widget->subprojectItemForPath( dependency.left(pos) ); 00746 if (spi) { 00747 QPtrList< TargetItem > tl = spi->targets; 00748 // Cycle throught the list of targets to find the one we're looking for 00749 TargetItem *ti = tl.first(); 00750 do { 00751 if (ti->name == tname) { 00752 // found it: queue it and stop looking 00753 queueInternalLibDependenciesBuild(ti); 00754 break; 00755 } 00756 ti = tl.next(); 00757 } while (ti); 00758 } 00759 00760 tcmd = constructMakeCommandLine(tdir, tname); 00761 if (!tcmd.isNull()) { 00762 makeFrontend()->queueCommand( tdir, tcmd); 00763 } 00764 } 00765 } 00766 } 00767 00768 00769 void AutoProjectPart::slotBuild() 00770 { 00771 //m_lastCompilationFailed = false; 00772 00773 if( m_needMakefileCvs ){ 00774 slotMakefilecvs(); 00775 slotConfigure(); 00776 m_needMakefileCvs = false; 00777 } 00778 00779 startMakeCommand(buildDirectory(), QString::fromLatin1("")); 00780 } 00781 00782 00783 void AutoProjectPart::buildTarget(QString relpath, TargetItem* titem) 00784 { 00785 00786 if ( !titem ) 00787 return; 00788 00789 //m_lastCompilationFailed = false; 00790 00791 // Calculate the complete name of the target and store it in name 00792 QString name = titem->name; 00793 if ( titem->primary == "KDEDOCS" ) 00794 name = "index.cache.bz2"; 00795 00796 // Calculate the full path of the target and store it in path 00797 QString path = buildDirectory(); 00798 if (!path.endsWith("/") && !path.isEmpty()) 00799 path += "/"; 00800 if (relpath.at(0) == '/') 00801 path += relpath.mid(1); 00802 else 00803 path += relpath; 00804 00805 // Save all files once 00806 partController()->saveAllFiles(); 00807 00808 // Add the make command for the libraries that the target depends on to the make frontend queue 00809 // if this recursive behavour is un-wanted comment the next line 00810 queueInternalLibDependenciesBuild(titem); 00811 00812 // Calculate the "make" command line for the target 00813 QString tcmd = constructMakeCommandLine( path, name ); 00814 00815 // Call make 00816 if (!tcmd.isNull()) { 00817 m_buildCommand = tcmd; 00818 makeFrontend()->queueCommand( path, tcmd); 00819 } 00820 } 00821 00822 00823 void AutoProjectPart::slotBuildActiveTarget() 00824 { 00825 // Get a pointer to the active target 00826 TargetItem* titem = m_widget->activeTarget(); 00827 00828 if ( !titem ) 00829 return; 00830 00831 // build it 00832 buildTarget(activeDirectory(), titem); 00833 00834 // hide the autoproject toolbar (if not sticky) 00835 mainWindow()->lowerView( m_widget ); 00836 } 00837 00838 00839 void AutoProjectPart::slotCompileFile() 00840 { 00841 KParts::ReadWritePart *part = dynamic_cast<KParts::ReadWritePart*>(partController()->activePart()); 00842 if (!part || !part->url().isLocalFile()) 00843 return; 00844 00845 QString fileName = part->url().path(); 00846 QFileInfo fi(fileName); 00847 QString sourceDir = fi.dirPath(); 00848 QString baseName = fi.baseName(true); 00849 kdDebug(9020) << "Compiling " << fileName 00850 << " in dir " << sourceDir 00851 << " with baseName " << baseName << endl; 00852 00853 QString projectDir = projectDirectory(); 00854 if (!sourceDir.startsWith(projectDir)) { 00855 KMessageBox::sorry(m_widget, i18n("Can only compile files in directories which belong to the project.")); 00856 return; 00857 } 00858 00859 QString buildDir = buildDirectory() + sourceDir.mid(projectDir.length()); 00860 QString target = baseName + ".lo"; 00861 kdDebug(9020) << "builddir " << buildDir << ", target " << target << endl; 00862 00863 startMakeCommand(buildDir, target); 00864 } 00865 00866 QString AutoProjectPart::configureCommand() const 00867 { 00868 QDomDocument &dom = *projectDom(); 00869 QString prefix = "/kdevautoproject/configurations/" + currentBuildConfig() + "/"; 00870 00871 QString cmdline = "\"" + topsourceDirectory(); 00872 cmdline += "/configure\""; 00873 QString cc = DomUtil::readEntry(dom, prefix + "ccompilerbinary"); 00874 if (!cc.isEmpty()) 00875 cmdline.prepend(QString("CC=%1 ").arg(cc)); 00876 QString cflags = DomUtil::readEntry(dom, prefix + "cflags"); 00877 if (!cflags.isEmpty()) 00878 cmdline.prepend(QString("CFLAGS=\"%1\" ").arg(cflags)); 00879 QString cxx = DomUtil::readEntry(dom, prefix + "cxxcompilerbinary"); 00880 if (!cxx.isEmpty()) 00881 cmdline.prepend(QString("CXX=%1 ").arg(cxx)); 00882 QString cxxflags = DomUtil::readEntry(dom, prefix + "cxxflags"); 00883 if (!cxxflags.isEmpty()) 00884 cmdline.prepend(QString("CXXFLAGS=\"%1\" ").arg(cxxflags)); 00885 QString f77 = DomUtil::readEntry(dom, prefix + "f77compilerbinary"); 00886 if (!f77.isEmpty()) 00887 cmdline.prepend(QString("F77=%1 ").arg(f77)); 00888 QString fflags = DomUtil::readEntry(dom, prefix + "f77flags"); 00889 if (!fflags.isEmpty()) 00890 cmdline.prepend(QString("FFLAGS=\"%1\" ").arg(fflags)); 00891 QString cppflags = DomUtil::readEntry(dom, prefix + "cppflags"); 00892 if (!cppflags.isEmpty()) 00893 cmdline.prepend(QString("CPPFLAGS=\"%1\" ").arg(cppflags)); 00894 QString ldflags = DomUtil::readEntry(dom, prefix + "ldflags"); 00895 if (!ldflags.isEmpty()) 00896 cmdline.prepend(QString("LDFLAGS=\"%1\" ").arg(ldflags)); 00897 00898 QString configargs = DomUtil::readEntry(dom, prefix + "configargs"); 00899 if (!configargs.isEmpty()) { 00900 cmdline += " "; 00901 cmdline += configargs; 00902 } 00903 00904 QString builddir = buildDirectory(); 00905 QString dircmd; 00906 00907 // if the build directory doesn't exist, add it's creation to the configureCommand 00908 if ( !QFile::exists(builddir)) { 00909 dircmd = "mkdir \""; 00910 dircmd += builddir; 00911 dircmd += "\" && "; 00912 } 00913 00914 // add "cd into the build directory" to the configureCommand 00915 dircmd += "cd \""; 00916 dircmd += builddir; 00917 dircmd += "\" && "; 00918 00919 return dircmd + cmdline; 00920 } 00921 00922 void AutoProjectPart::slotConfigure() 00923 { 00924 QString cmdline = configureCommand(); 00925 if (cmdline.isNull()) 00926 return; 00927 00928 makeFrontend()->queueCommand(buildDirectory(), cmdline); 00929 } 00930 00931 QString AutoProjectPart::makefileCvsCommand() const 00932 { 00933 QString cmdline = DomUtil::readEntry(*projectDom(), "/kdevautoproject/make/makebin"); 00934 if (cmdline.isEmpty()) 00935 cmdline = MAKE_COMMAND; 00936 00937 if (QFile::exists(topsourceDirectory() + "/Makefile.cvs")) 00938 cmdline += " -f Makefile.cvs"; 00939 else if (QFile::exists(topsourceDirectory() + "/Makefile.dist")) 00940 cmdline += " -f Makefile.dist"; 00941 else if (QFile::exists(topsourceDirectory() + "/autogen.sh")) 00942 cmdline = "./autogen.sh"; 00943 else { 00944 KMessageBox::sorry(m_widget, i18n("There is neither a Makefile.cvs file nor an " 00945 "autogen.sh script in the project directory.")); 00946 return QString::null; 00947 } 00948 00949 cmdline.prepend(makeEnvironment()); 00950 00951 QString dircmd = "cd \""; 00952 dircmd += topsourceDirectory(); 00953 dircmd += "\" && "; 00954 00955 return dircmd + cmdline; 00956 } 00957 00958 void AutoProjectPart::slotMakefilecvs() 00959 { 00960 QString cmdline = makefileCvsCommand(); 00961 if ( cmdline.isNull() ) 00962 return; 00963 00964 makeFrontend()->queueCommand(projectDirectory(), cmdline); 00965 } 00966 00967 00968 void AutoProjectPart::slotInstall() 00969 { 00970 startMakeCommand(buildDirectory(), QString::fromLatin1("install")); 00971 } 00972 00973 00974 void AutoProjectPart::slotInstallWithKdesu() 00975 { 00976 // First issue "make" to build the entire project with the current user 00977 // This way we make sure all files are up to date before we do the "make install" 00978 slotBuild(); 00979 00980 // After that issue "make install" with the root user 00981 startMakeCommand(buildDirectory(), QString::fromLatin1("install"), true); 00982 } 00983 00984 00985 void AutoProjectPart::slotClean() 00986 { 00987 startMakeCommand(buildDirectory(), QString::fromLatin1("clean")); 00988 } 00989 00990 00991 void AutoProjectPart::slotDistClean() 00992 { 00993 startMakeCommand(buildDirectory(), QString::fromLatin1("distclean")); 00994 } 00995 00996 00997 void AutoProjectPart::slotMakeMessages() 00998 { 00999 startMakeCommand(buildDirectory(), QString::fromLatin1("package-messages")); 01000 } 01001 01002 01009 void AutoProjectPart::slotExecute() 01010 { 01011 partController()->saveAllFiles(); 01012 QDomDocument &dom = *projectDom(); 01013 01014 if( DomUtil::readBoolEntry(dom, "/kdevautoproject/run/autocompile", true) && isDirty() ){ 01015 m_executeAfterBuild = true; 01016 if ( DomUtil::readEntry(dom, "/kdevautoproject/run/mainprogram").isEmpty() ) 01017 // If no Main Program was specified, build the active target 01018 slotBuildActiveTarget(); 01019 else 01020 // A Main Program was specified, build all targets because we don't know which is it 01021 slotBuild(); 01022 return; 01023 } 01024 01025 if (appFrontend()->isRunning()) { 01026 if (KMessageBox::questionYesNo(m_widget, i18n("Your application is currently running. Do you want to restart it?"), i18n("Application already running"), i18n("&Restart application"), i18n("Do &Nothing")) == KMessageBox::No) 01027 return; 01028 connect(appFrontend(), SIGNAL(processExited()), SLOT(slotExecute2())); 01029 appFrontend()->stopApplication(); 01030 return; 01031 } 01032 01033 slotExecute2(); 01034 } 01035 01036 01041 void AutoProjectPart::slotExecute2() 01042 { 01043 disconnect(appFrontend(), SIGNAL(processExited()), this, SLOT(slotExecute2())); 01044 01045 // Get the run environment variables pairs into the environstr string 01046 // in the form of: "ENV_VARIABLE=ENV_VALUE" 01047 // Note that we quote the variable value due to the possibility of 01048 // embedded spaces 01049 DomUtil::PairList envvars = runEnvironmentVars(); 01050 QString environstr; 01051 DomUtil::PairList::ConstIterator it; 01052 for (it = envvars.begin(); it != envvars.end(); ++it) { 01053 environstr += (*it).first; 01054 environstr += "="; 01055 /* 01056 #if (KDE_VERSION > 305) 01057 environstr += KProcess::quote((*it).second); 01058 #else 01059 environstr += KShellProcess::quote((*it).second); 01060 #endif 01061 */ 01062 environstr += EnvVarTools::quote((*it).second); 01063 environstr += " "; 01064 } 01065 01066 if (mainProgram(true).isEmpty()) 01067 // Do not execute non executable targets 01068 return; 01069 01070 QString program = environstr; 01071 // Adds the ./ that is necessary to execute the program in bash shells 01072 if (!mainProgram(true).startsWith("/")) 01073 program += "./"; 01074 program += mainProgram(true); 01075 program += " " + runArguments(); 01076 01077 bool inTerminal = DomUtil::readBoolEntry(*projectDom(), "/kdevautoproject/run/terminal"); 01078 01079 kdDebug(9020) << "runDirectory: <" << runDirectory() << ">" <<endl; 01080 kdDebug(9020) << "environstr : <" << environstr << ">" <<endl; 01081 kdDebug(9020) << "mainProgram : <" << mainProgram(true) << ">" <<endl; 01082 kdDebug(9020) << "runArguments: <" << runArguments() << ">" <<endl; 01083 01084 appFrontend()->startAppCommand(runDirectory(), program, inTerminal); 01085 } 01086 01087 01088 void AutoProjectPart::slotAddTranslation() 01089 { 01090 AddTranslationDialog dlg(this, m_widget); 01091 dlg.exec(); 01092 } 01093 01094 01095 void AutoProjectPart::slotBuildConfigChanged(const QString &config) 01096 { 01097 DomUtil::writeEntry(*projectDom(), "/kdevautoproject/general/useconfiguration", config); 01098 kdDebug(9020) << "Changed used configuration to " << config << endl; 01099 } 01100 01101 01102 void AutoProjectPart::slotBuildConfigAboutToShow() 01103 { 01104 QStringList l = allBuildConfigs(); 01105 buildConfigAction->setItems(l); 01106 buildConfigAction->setCurrentItem(l.findIndex(currentBuildConfig())); 01107 } 01108 01109 void AutoProjectPart::restorePartialProjectSession ( const QDomElement* el ) 01110 { 01111 m_widget->restoreSession ( el ); 01112 } 01113 01114 void AutoProjectPart::savePartialProjectSession ( QDomElement* el ) 01115 { 01116 QDomDocument domDoc = el->ownerDocument(); 01117 01118 KMessageBox::information ( 0, "Hallo, Welt!" ); 01119 01120 kdDebug ( 9000 ) << "*********************************************** 1) AutoProjectPart::savePartialProjectSession()" << endl; 01121 01122 if ( domDoc.isNull() ) 01123 { 01124 kdDebug ( 9000 ) << "*********************************************** 2) AutoProjectPart::savePartialProjectSession()" << endl; 01125 return; 01126 } 01127 01128 kdDebug ( 9000 ) << "*********************************************** 3) AutoProjectPart::savePartialProjectSession()" << endl; 01129 01130 m_widget->saveSession ( el ); 01131 } 01132 01133 void AutoProjectPart::slotCommandFinished( const QString& command ) 01134 { 01135 kdDebug(9020) << k_funcinfo << endl; 01136 01137 if( m_buildCommand != command ) 01138 return; 01139 01140 m_buildCommand = QString::null; 01141 01142 m_timestamp.clear(); 01143 QStringList fileList = allFiles(); 01144 QStringList::Iterator it = fileList.begin(); 01145 while( it != fileList.end() ){ 01146 QString fileName = *it; 01147 ++it; 01148 01149 m_timestamp[ fileName ] = QFileInfo( projectDirectory(), fileName ).lastModified(); 01150 } 01151 01152 emit projectCompiled(); 01153 01154 // reset the "last compilation has failed" flag 01155 m_lastCompilationFailed = false; 01156 01157 if( m_executeAfterBuild ){ 01158 slotExecute(); 01159 m_executeAfterBuild = false; 01160 } 01161 } 01162 01163 void AutoProjectPart::slotCommandFailed( const QString& /*command*/ ) 01164 { 01165 kdDebug(9020) << k_funcinfo << endl; 01166 01167 m_lastCompilationFailed = true; 01168 } 01169 01170 bool AutoProjectPart::isDirty() 01171 { 01172 if (m_lastCompilationFailed) return true; 01173 01174 QStringList fileList = allFiles(); 01175 QStringList::Iterator it = fileList.begin(); 01176 while( it != fileList.end() ){ 01177 QString fileName = *it; 01178 ++it; 01179 01180 QMap<QString, QDateTime>::Iterator it = m_timestamp.find( fileName ); 01181 QDateTime t = QFileInfo( projectDirectory(), fileName ).lastModified(); 01182 if( it == m_timestamp.end() || *it != t ){ 01183 return true; 01184 } 01185 } 01186 01187 return false; 01188 } 01189 01190 void AutoProjectPart::needMakefileCvs( ) 01191 { 01192 m_needMakefileCvs = true; 01193 } 01194 01195 bool AutoProjectPart::isKDE() const 01196 { 01197 return m_isKDE; 01198 } 01199 01200 KDevProject::Options AutoProjectPart::options() const 01201 { 01202 return UsesAutotoolsBuildSystem; 01203 } 01204 01205 #include "autoprojectpart.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:53 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003