/* Copyright (C) 2003 Oliver Kellogg * okellogg@users.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include "adaproject_part.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "domutil.h" #include "kdevcore.h" #include "kdevmainwindow.h" #include "kdevmakefrontend.h" #include "kdevappfrontend.h" #include "kdevpartcontroller.h" #include "kdevlanguagesupport.h" #include "kdevcompileroptions.h" #include "kdevgenericfactory.h" #include #include "adaproject_widget.h" #include "adaprojectoptionsdlg.h" #include "adaglobaloptionsdlg.h" typedef KDevGenericFactory AdaProjectFactory; static const KDevPluginInfo data("kdevadaproject"); K_EXPORT_COMPONENT_FACTORY( libkdevadaproject, AdaProjectFactory( data ) ) AdaProjectPart::AdaProjectPart(TQObject *parent, const char *name, const TQStringList& ) :KDevBuildTool(&data, parent, name ? name : "AdaProjectPart" ) { setInstance(AdaProjectFactory::instance()); setXMLFile("kdevadaproject.rc"); KAction *action; action = new KAction( i18n("&Build Project"), "make_tdevelop", Key_F8, this, TQT_SLOT(slotBuild()), actionCollection(), "build_build" ); action = new KAction( i18n("Execute Program"), "exec", 0, this, TQT_SLOT(slotExecute()), actionCollection(), "build_execute" ); connect( core(), TQT_SIGNAL(projectConfigWidget(KDialogBase*)), this, TQT_SLOT(projectConfigWidget(KDialogBase*)) ); connect( core(), TQT_SIGNAL(configWidget(KDialogBase*)), this, TQT_SLOT(configWidget(KDialogBase*)) ); // m_widget = new AdaProjectWidget(this); // TQWhatsThis::add(m_widget, i18n("WHAT DOES THIS PART DO?")); // now you decide what should happen to the widget. Take a look at kdevcore.h // or at other plugins how to embed it. // if you want to embed your widget as an outputview, simply uncomment // the following line. // mainWindow()->embedOutputView( m_widget, "name that should appear", "enter a tooltip" ); } AdaProjectPart::~AdaProjectPart() { // delete m_widget; } /** * This should really be merged with FileTreeWidget::matchesHidePattern() * and put in its own class. Currently this is repeated in scriptprojectpart.cpp, pascalproject_part.cpp, adaproject_part.cpp */ static bool matchesPattern(const TQString &fileName, const TQStringList &patternList) { TQStringList::ConstIterator it; for (it = patternList.begin(); it != patternList.end(); ++it) { TQRegExp re(*it, true, true); if (re.search(fileName) == 0 && re.matchedLength() == (int)fileName.length()) return true; } return false; } void AdaProjectPart::openProject(const TQString &dirName, const TQString &projectName) { m_buildDir = dirName; m_projectDir = dirName; m_projectName = projectName; TQDomDocument &dom = *projectDom(); // Set the default directory radio to "executable" if (DomUtil::readEntry(dom, "/kdevadaproject/run/directoryradio") == "" ) { DomUtil::writeEntry(dom, "/kdevadaproject/run/directoryradio", "executable"); } loadProjectConfig(); // Put all files from all subdirectories into file list TQValueStack s; int prefixlen = m_projectDir.length()+1; s.push(m_projectDir); TQStringList includepatternList; if ( languageSupport() ) { KMimeType::List list = languageSupport()->mimeTypes(); KMimeType::List::Iterator it = list.begin(); while( it != list.end() ){ includepatternList += (*it)->patterns(); ++it; } } TQString excludepatterns = "*~"; TQStringList excludepatternList = TQStringList::split(",", excludepatterns); TQDir dir; do { dir.setPath(s.pop()); kdDebug() << "AdaProjectPart::openProject examining: " << dir.path() << endl; const TQFileInfoList *dirEntries = dir.entryInfoList(); if( !dirEntries ) break; TQPtrListIterator it(*dirEntries); for (; it.current(); ++it) { TQString fileName = it.current()->fileName(); if (fileName == "." || fileName == "..") continue; TQString path = it.current()->absFilePath(); if (it.current()->isDir()) { kdDebug() << "AdaProjectPart::openProject pushing: " << path << endl; s.push(path); } else { if (matchesPattern(path, includepatternList) && !matchesPattern(path, excludepatternList)) { kdDebug() << "AdaProjectPart::openProject adding: " << path << endl; m_sourceFiles.append(path.mid(prefixlen)); } else { kdDebug() << "AdaProjectPart::openProject ignoring: " << path << endl; } } } } while (!s.isEmpty()); KDevProject::openProject( dirName, projectName ); } void AdaProjectPart::closeProject() { } /** Retuns a PairList with the run environment variables */ DomUtil::PairList AdaProjectPart::runEnvironmentVars() const { return DomUtil::readPairListEntry(*projectDom(), "/kdevadaproject/run/envvars", "envvar", "name", "value"); } /** Retuns the currently selected run directory * The returned string can be: * if run/directoryradio == executable * The directory where the executable is * if run/directoryradio == build * The directory where the executable is relative to build directory * if run/directoryradio == custom * The custom directory absolute path */ TQString AdaProjectPart::runDirectory() const { TQString cwd = defaultRunDirectory("kdevadaproject"); if (cwd.isEmpty()) cwd = buildDirectory(); return cwd; } /** Retuns the currently selected main program * The returned string can be: * if run/directoryradio == executable * The executable name * if run/directoryradio == build * The path to executable relative to build directory * if run/directoryradio == custom or relative == false * The absolute path to executable */ TQString AdaProjectPart::mainProgram() const { TQDomDocument * dom = projectDom(); if ( !dom ) return TQString(); TQString DomMainProgram = DomUtil::readEntry( *dom, "/kdevadaproject/run/mainprogram"); if ( DomMainProgram.isEmpty() ) return TQString(); if ( DomMainProgram.startsWith("/") ) // assume absolute path { return DomMainProgram; } else // assume project relative path { return projectDirectory() + "/" + DomMainProgram; } return TQString(); } /** Retuns a TQString with the run command line arguments */ TQString AdaProjectPart::debugArguments() const { return DomUtil::readEntry(*projectDom(), "/kdevadaproject/run/globaldebugarguments"); } /** Retuns a TQString with the run command line arguments */ TQString AdaProjectPart::runArguments() const { return DomUtil::readEntry(*projectDom(), "/kdevadaproject/run/programargs"); } TQString AdaProjectPart::mainSource() const { return projectDirectory() + "/" + m_mainSource; } void AdaProjectPart::setMainSource(TQString fullPath) { TQString olddir = activeDirectory(); m_mainSource = fullPath.replace(TQRegExp(TQString(projectDirectory() + TQString("/"))),""); emit activeDirectoryChanged( olddir, activeDirectory() ); } TQString AdaProjectPart::projectDirectory() const { return m_projectDir; } TQString AdaProjectPart::projectName() const { return m_projectName; } TQString AdaProjectPart::activeDirectory() const { TQFileInfo fi(mainSource()); return fi.dirPath(true).replace(TQRegExp(projectDirectory()),""); } TQString AdaProjectPart::buildDirectory() const { TQFileInfo fi(mainSource()); return fi.dirPath(true); } void AdaProjectPart::listOfFiles(TQStringList &result, TQString path) const { TQDir d(path); if (!d.exists()) return; const TQFileInfoList *entries = d.entryInfoList(TQDir::Dirs | TQDir::Files | TQDir::Hidden); if( !entries ) return; TQFileInfoListIterator it( *entries ); while( const TQFileInfo* fileInfo = it.current() ) { ++it; if (fileInfo->isDir() && fileInfo->filePath() != path) { kdDebug() << "entering dir " << fileInfo->dirPath() << endl; listOfFiles(result, fileInfo->dirPath()); } else { kdDebug() << "adding to result: " << fileInfo->filePath() << endl; result << fileInfo->filePath(); } } } TQStringList AdaProjectPart::allFiles() const { // TQStringList files; // listOfFiles(files, projectDirectory()); // return files; return m_sourceFiles; } void AdaProjectPart::addFile(const TQString& /*fileName*/) { } void AdaProjectPart::addFiles(const TQStringList& /*fileList*/) { } void AdaProjectPart::removeFile(const TQString& /*fileName*/) { } void AdaProjectPart::removeFiles(const TQStringList& /*fileList*/) { } void AdaProjectPart::slotBuild() { if (partController()->saveAllFiles()==false) return; //user cancelled TQString cmdline = m_compilerExec + " " + m_compilerOpts + " "; if (cmdline.isEmpty()) { KMessageBox::sorry(0, i18n("Could not find ada compiler.\nCheck if your compiler settings are correct.")); return; } TQFileInfo fi(mainSource()); cmdline += fi.fileName(); TQString dircmd = "cd "; dircmd += KProcess::quote(buildDirectory()); dircmd += " && "; makeFrontend()->queueCommand(buildDirectory(), dircmd + cmdline); } void AdaProjectPart::slotExecute() { partController()->saveAllFiles(); TQString program = "./"; appFrontend()->startAppCommand(buildDirectory(), mainProgram(), true); } void AdaProjectPart::changedFiles( const TQStringList & fileList ) { KDevProject::changedFiles(fileList); } void AdaProjectPart::changedFile( const TQString & fileName ) { KDevProject::changedFile(fileName); } void AdaProjectPart::projectConfigWidget( KDialogBase * dlg ) { TQVBox *vbox; vbox = dlg->addVBoxPage(i18n("Ada Compiler")); AdaProjectOptionsDlg *w = new AdaProjectOptionsDlg(this, vbox); connect( dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept()) ); connect( dlg, TQT_SIGNAL(okClicked()), this, TQT_SLOT(loadProjectConfig()) ); } void AdaProjectPart::loadProjectConfig( ) { TQDomDocument &dom = *(projectDom()); TQString config = DomUtil::readEntry(dom, "/kdevadaproject/general/useconfiguration", "default"); m_mainSource = DomUtil::readEntry(dom, TQString("/kdevadaproject/configurations/") + config + TQString("/mainsource") ); m_compilerOpts = DomUtil::readEntry(dom, TQString("/kdevadaproject/configurations/") + config + TQString("/compileroptions")); m_compilerExec = DomUtil::readEntry(dom, TQString("/kdevadaproject/configurations/") + config + TQString("/compilerexec")); if (m_compilerExec.isEmpty()) { KTrader::OfferList offers = KTrader::self()->query("TDevelop/CompilerOptions", "[X-TDevelop-Language] == 'Ada'"); TQValueList::ConstIterator it; for (it = offers.begin(); it != offers.end(); ++it) { if ((*it)->property("X-TDevelop-Default").toBool()) { m_compilerExec = (*it)->exec(); break; } } } } void AdaProjectPart::configWidget( KDialogBase * dlg ) { TQVBox *vbox; vbox = dlg->addVBoxPage(i18n("Ada Compiler")); AdaGlobalOptionsDlg *w = new AdaGlobalOptionsDlg(this, vbox); connect( dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept()) ); } KDevCompilerOptions *AdaProjectPart::createCompilerOptions(const TQString &name) { KService::Ptr service = KService::serviceByDesktopName(name); if (!service) { kdDebug() << "AdaProjectPart::createCompilerOptions can't find service " << name; return 0; } KLibFactory *factory = KLibLoader::self()->factory(TQFile::encodeName(service->library())); if (!factory) { TQString errorMessage = KLibLoader::self()->lastErrorMessage(); KMessageBox::error(0, i18n("There was an error loading the module %1.\n" "The diagnostics are:\n%2").arg(service->name()).arg(errorMessage)); exit(1); } TQStringList args; TQVariant prop = service->property("X-TDevelop-Args"); if (prop.isValid()) args = TQStringList::split(" ", prop.toString()); TQObject *obj = factory->create(this, service->name().latin1(), "KDevCompilerOptions", args); if (!obj->inherits("KDevCompilerOptions")) { kdDebug() << "AdaProjectPart::createCompilerOptions: component does not inherit KDevCompilerOptions" << endl; return 0; } KDevCompilerOptions *dlg = (KDevCompilerOptions*) obj; return dlg; } TQString AdaProjectPart::defaultOptions( const TQString compiler ) { KConfig *config = KGlobal::config(); config->setGroup("Ada Compiler"); return config->readPathEntry(compiler); } #include "adaproject_part.moc" /*! \fn AdaProjectPart::distFiles() const */ TQStringList AdaProjectPart::distFiles() const { TQStringList sourceList = allFiles(); // Scan current source directory for any .pro files. TQString projectDir = projectDirectory(); TQDir dir(projectDir); TQStringList files = dir.entryList( "Makefile"); return sourceList + files; }