00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qdom.h>
00011 #include <qfileinfo.h>
00012 #include <qdir.h>
00013 #include <qvaluestack.h>
00014 #include <qregexp.h>
00015 #include <qvbox.h>
00016
00017 #include <kiconloader.h>
00018 #include <klocale.h>
00019 #include <kaction.h>
00020 #include <kgenericfactory.h>
00021 #include <kdebug.h>
00022 #include <kdialogbase.h>
00023 #include <kmessagebox.h>
00024 #include <klibloader.h>
00025 #include <kprocess.h>
00026 #include <kservice.h>
00027 #include <kconfig.h>
00028
00029 #include "domutil.h"
00030 #include "kdevcore.h"
00031 #include "kdevmainwindow.h"
00032 #include "kdevmakefrontend.h"
00033 #include "kdevappfrontend.h"
00034 #include "kdevpartcontroller.h"
00035 #include "kdevlanguagesupport.h"
00036 #include "kdevcompileroptions.h"
00037 #include "kdevgenericfactory.h"
00038
00039 #include "adaproject_widget.h"
00040 #include "adaproject_part.h"
00041 #include "adaprojectoptionsdlg.h"
00042 #include "adaglobaloptionsdlg.h"
00043
00044 typedef KDevGenericFactory<AdaProjectPart> AdaProjectFactory;
00045 static const KAboutData data("kdevadaproject", I18N_NOOP("Build Tool"), "1.0");
00046 K_EXPORT_COMPONENT_FACTORY( libkdevadaproject, AdaProjectFactory( &data ) )
00047
00048 AdaProjectPart::AdaProjectPart(QObject *parent, const char *name, const QStringList& )
00049 :KDevProject("AdaProject", "adaproject", parent, name ? name : "AdaProjectPart" )
00050 {
00051 setInstance(AdaProjectFactory::instance());
00052 setXMLFile("kdevadaproject.rc");
00053
00054 KAction *action;
00055 action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8,
00056 this, SLOT(slotBuild()),
00057 actionCollection(), "build_build" );
00058 action = new KAction( i18n("Execute Program"), "exec", 0,
00059 this, SLOT(slotExecute()),
00060 actionCollection(), "build_execute" );
00061
00062 connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)),
00063 this, SLOT(projectConfigWidget(KDialogBase*)) );
00064
00065 connect( core(), SIGNAL(configWidget(KDialogBase*)),
00066 this, SLOT(configWidget(KDialogBase*)) );
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 }
00081
00082 AdaProjectPart::~AdaProjectPart()
00083 {
00084
00085 }
00086
00091 static bool matchesPattern(const QString &fileName, const QStringList &patternList)
00092 {
00093 QStringList::ConstIterator it;
00094 for (it = patternList.begin(); it != patternList.end(); ++it) {
00095 QRegExp re(*it, true, true);
00096 if (re.search(fileName) == 0 && re.matchedLength() == (int)fileName.length())
00097 return true;
00098 }
00099
00100 return false;
00101 }
00102
00103 void AdaProjectPart::openProject(const QString &dirName, const QString &projectName)
00104 {
00105 m_buildDir = dirName;
00106 m_projectDir = dirName;
00107 m_projectName = projectName;
00108
00109 QDomDocument &dom = *projectDom();
00110
00111 if (DomUtil::readEntry(dom, "/kdevadaproject/run/directoryradio") == "" ) {
00112 DomUtil::writeEntry(dom, "/kdevadaproject/run/directoryradio", "executable");
00113 }
00114
00115 loadProjectConfig();
00116
00117
00118 QValueStack<QString> s;
00119 int prefixlen = m_projectDir.length()+1;
00120 s.push(m_projectDir);
00121
00122 QStringList includepatternList;
00123
00124 if ( languageSupport() )
00125 {
00126 KMimeType::List list = languageSupport()->mimeTypes();
00127 KMimeType::List::Iterator it = list.begin();
00128 while( it != list.end() ){
00129 includepatternList += (*it)->patterns();
00130 ++it;
00131 }
00132 }
00133
00134 QString excludepatterns = "*~";
00135 QStringList excludepatternList = QStringList::split(",", excludepatterns);
00136
00137 QDir dir;
00138 do {
00139 dir.setPath(s.pop());
00140 kdDebug() << "AdaProjectPart::openProject examining: " << dir.path() << endl;
00141 const QFileInfoList *dirEntries = dir.entryInfoList();
00142 if( !dirEntries )
00143 break;
00144
00145 QPtrListIterator<QFileInfo> it(*dirEntries);
00146 for (; it.current(); ++it) {
00147 QString fileName = it.current()->fileName();
00148 if (fileName == "." || fileName == "..")
00149 continue;
00150 QString path = it.current()->absFilePath();
00151 if (it.current()->isDir()) {
00152 kdDebug() << "AdaProjectPart::openProject pushing: " << path << endl;
00153 s.push(path);
00154 }
00155 else {
00156 if (matchesPattern(path, includepatternList)
00157 && !matchesPattern(path, excludepatternList)) {
00158 kdDebug() << "AdaProjectPart::openProject adding: " << path << endl;
00159 m_sourceFiles.append(path.mid(prefixlen));
00160 } else {
00161 kdDebug() << "AdaProjectPart::openProject ignoring: " << path << endl;
00162 }
00163 }
00164 }
00165 } while (!s.isEmpty());
00166
00167 KDevProject::openProject( dirName, projectName );
00168 }
00169
00170 void AdaProjectPart::closeProject()
00171 {
00172 }
00173
00175 DomUtil::PairList AdaProjectPart::runEnvironmentVars() const
00176 {
00177 return DomUtil::readPairListEntry(*projectDom(), "/kdevadaproject/run/envvars", "envvar", "name", "value");
00178 }
00179
00180
00190 QString AdaProjectPart::runDirectory() const
00191 {
00192 QDomDocument &dom = *projectDom();
00193
00194 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevadaproject/run/directoryradio");
00195 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevadaproject/run/mainprogram");
00196
00197 if ( directoryRadioString == "build" )
00198 return buildDirectory();
00199
00200 if ( directoryRadioString == "custom" )
00201 return DomUtil::readEntry(dom, "/kdevadaproject/run/customdirectory");
00202
00203 int pos = DomMainProgram.findRev('/');
00204 if (pos != -1)
00205 return buildDirectory() + "/" + DomMainProgram.left(pos);
00206
00207 return buildDirectory() + "/" + DomMainProgram;
00208
00209 }
00210
00211
00221 QString AdaProjectPart::mainProgram(bool relative) const
00222 {
00223 QFileInfo fi(mainSource());
00224 return buildDirectory() + "/" + fi.baseName();
00225
00227 QDomDocument &dom = *projectDom();
00228
00229 QString directoryRadioString = DomUtil::readEntry(dom, "/kdevadaproject/run/directoryradio");
00230 QString DomMainProgram = DomUtil::readEntry(dom, "/kdevadaproject/run/mainprogram");
00231
00232 if ( directoryRadioString == "custom" )
00233 return DomMainProgram;
00234
00235 if ( relative == false )
00236 return buildDirectory() + "/" + DomMainProgram;
00237
00238 if ( directoryRadioString == "executable" ) {
00239 int pos = DomMainProgram.findRev('/');
00240 if (pos != -1)
00241 return DomMainProgram.mid(pos+1);
00242 return DomMainProgram;
00243 }
00244 else
00245 return DomMainProgram;
00246 }
00247
00248
00250 QString AdaProjectPart::runArguments() const
00251 {
00252 return DomUtil::readEntry(*projectDom(), "/kdevadaproject/run/programargs");
00253 }
00254
00255 QString AdaProjectPart::mainSource() const
00256 {
00257 return projectDirectory() + "/" + m_mainSource;
00258 }
00259
00260 void AdaProjectPart::setMainSource(QString fullPath)
00261 {
00262 m_mainSource = fullPath.replace(QRegExp(QString(projectDirectory() + QString("/"))),"");
00263 }
00264
00265 QString AdaProjectPart::projectDirectory() const
00266 {
00267 return m_projectDir;
00268 }
00269
00270 QString AdaProjectPart::projectName() const
00271 {
00272 return m_projectName;
00273 }
00274
00275 QString AdaProjectPart::activeDirectory() const
00276 {
00277 QFileInfo fi(mainSource());
00278 return fi.dirPath(true).replace(QRegExp(projectDirectory()),"");
00279 }
00280
00281 QString AdaProjectPart::buildDirectory() const
00282 {
00283 QFileInfo fi(mainSource());
00284 return fi.dirPath(true);
00285 }
00286
00287 void AdaProjectPart::listOfFiles(QStringList &result, QString path) const
00288 {
00289 QDir d(path);
00290 if (!d.exists())
00291 return;
00292
00293 const QFileInfoList *entries = d.entryInfoList(QDir::Dirs | QDir::Files | QDir::Hidden);
00294 if( !entries )
00295 return;
00296
00297 QFileInfoListIterator it( *entries );
00298 while( const QFileInfo* fileInfo = it.current() )
00299 {
00300 ++it;
00301
00302 if (fileInfo->isDir() && fileInfo->filePath() != path)
00303 {
00304 kdDebug() << "entering dir " << fileInfo->dirPath() << endl;
00305 listOfFiles(result, fileInfo->dirPath());
00306 }
00307 else
00308 {
00309 kdDebug() << "adding to result: " << fileInfo->filePath() << endl;
00310 result << fileInfo->filePath();
00311 }
00312 }
00313 }
00314
00315 QStringList AdaProjectPart::allFiles() const
00316 {
00317
00318
00319
00320
00321
00322 return m_sourceFiles;
00323 }
00324
00325 void AdaProjectPart::addFile(const QString& )
00326 {
00327 }
00328
00329 void AdaProjectPart::addFiles(const QStringList& )
00330 {
00331 }
00332
00333 void AdaProjectPart::removeFile(const QString& )
00334 {
00335 }
00336
00337 void AdaProjectPart::removeFiles(const QStringList& )
00338 {
00339 }
00340
00341 void AdaProjectPart::slotBuild()
00342 {
00343 partController()->saveAllFiles();
00344
00345 QString cmdline = m_compilerExec + " " + m_compilerOpts + " ";
00346
00347 if (cmdline.isEmpty())
00348 {
00349 KMessageBox::sorry(0, i18n("Could not find ada compiler.\nCheck if your compiler settings are correct."));
00350 return;
00351 }
00352
00353 QFileInfo fi(mainSource());
00354 cmdline += fi.fileName();
00355
00356 QString dircmd = "cd ";
00357 dircmd += KProcess::quote(buildDirectory());
00358 dircmd += " && ";
00359
00360 makeFrontend()->queueCommand(buildDirectory(), dircmd + cmdline);
00361 }
00362
00363 void AdaProjectPart::slotExecute()
00364 {
00365 partController()->saveAllFiles();
00366 QString program = "./";
00367 appFrontend()->startAppCommand(buildDirectory(), mainProgram(), true);
00368 }
00369
00370 void AdaProjectPart::changedFiles( const QStringList & fileList )
00371 {
00372 KDevProject::changedFiles(fileList);
00373 }
00374
00375 void AdaProjectPart::changedFile( const QString & fileName )
00376 {
00377 KDevProject::changedFile(fileName);
00378 }
00379
00380 void AdaProjectPart::projectConfigWidget( KDialogBase * dlg )
00381 {
00382 QVBox *vbox;
00383 vbox = dlg->addVBoxPage(i18n("Ada Compiler"));
00384 AdaProjectOptionsDlg *w = new AdaProjectOptionsDlg(this, vbox);
00385 connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00386 connect( dlg, SIGNAL(okClicked()), this, SLOT(loadProjectConfig()) );
00387 }
00388
00389 void AdaProjectPart::loadProjectConfig( )
00390 {
00391 QDomDocument &dom = *(projectDom());
00392
00393 QString config = DomUtil::readEntry(dom, "/kdevadaproject/general/useconfiguration", "default");
00394 m_mainSource = DomUtil::readEntry(dom, QString("/kdevadaproject/configurations/") + config + QString("/mainsource") );
00395 m_compilerOpts = DomUtil::readEntry(dom, QString("/kdevadaproject/configurations/") + config + QString("/compileroptions"));
00396 m_compilerExec = DomUtil::readEntry(dom, QString("/kdevadaproject/configurations/") + config + QString("/compilerexec"));
00397
00398 if (m_compilerExec.isEmpty())
00399 {
00400 KTrader::OfferList offers = KTrader::self()->query("KDevelop/CompilerOptions", "[X-KDevelop-Language] == 'Ada'");
00401 QValueList<KService::Ptr>::ConstIterator it;
00402 for (it = offers.begin(); it != offers.end(); ++it) {
00403 if ((*it)->property("X-KDevelop-Default").toBool()) {
00404 m_compilerExec = (*it)->exec();
00405 break;
00406 }
00407 }
00408 }
00409 }
00410
00411 void AdaProjectPart::configWidget( KDialogBase * dlg )
00412 {
00413 QVBox *vbox;
00414 vbox = dlg->addVBoxPage(i18n("Ada Compiler"));
00415 AdaGlobalOptionsDlg *w = new AdaGlobalOptionsDlg(this, vbox);
00416 connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00417 }
00418
00419 KDevCompilerOptions *AdaProjectPart::createCompilerOptions(const QString &name)
00420 {
00421 KService::Ptr service = KService::serviceByDesktopName(name);
00422 if (!service) {
00423 kdDebug() << "AdaProjectPart::createCompilerOptions can't find service " << name;
00424 return 0;
00425 }
00426
00427 KLibFactory *factory = KLibLoader::self()->factory(QFile::encodeName(service->library()));
00428 if (!factory) {
00429 QString errorMessage = KLibLoader::self()->lastErrorMessage();
00430 KMessageBox::error(0, i18n("There was an error loading the module %1.\n"
00431 "The diagnostics are:\n%2").arg(service->name()).arg(errorMessage));
00432 exit(1);
00433 }
00434
00435 QStringList args;
00436 QVariant prop = service->property("X-KDevelop-Args");
00437 if (prop.isValid())
00438 args = QStringList::split(" ", prop.toString());
00439
00440 QObject *obj = factory->create(this, service->name().latin1(),
00441 "KDevCompilerOptions", args);
00442
00443 if (!obj->inherits("KDevCompilerOptions")) {
00444 kdDebug() << "AdaProjectPart::createCompilerOptions: component does not inherit KDevCompilerOptions" << endl;
00445 return 0;
00446 }
00447 KDevCompilerOptions *dlg = (KDevCompilerOptions*) obj;
00448
00449 return dlg;
00450 }
00451
00452 QString AdaProjectPart::defaultOptions( const QString compiler )
00453 {
00454 KConfig *config = KGlobal::config();
00455 config->setGroup("Ada Compiler");
00456 return config->readPathEntry(compiler);
00457 }
00458
00459 #include "adaproject_part.moc"
00460
00461
00465 QStringList AdaProjectPart::distFiles() const
00466 {
00467 QStringList sourceList = allFiles();
00468
00469 QString projectDir = projectDirectory();
00470 QDir dir(projectDir);
00471 QStringList files = dir.entryList( "Makefile");
00472 return sourceList + files;
00473 }