#include "antprojectpart.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "antoptionswidget.h" #include "classpathwidget.h" typedef KDevGenericFactory AntProjectFactory; static const KDevPluginInfo data("kdevantproject"); K_EXPORT_COMPONENT_FACTORY(libkdevantproject, AntProjectFactory( data )) AntOptions::AntOptions() : m_buildXML("build.xml"), m_verbosity(AntOptions::Quiet) { } AntProjectPart::AntProjectPart(TQObject *parent, const char *name, const TQStringList &) : KDevBuildTool(&data, parent, name ? name : "AntProjectPart") { setInstance(AntProjectFactory::instance()); setXMLFile("kdevantproject.rc"); m_buildProjectAction = new KAction(i18n("&Build Project"), "make_kdevelop", Key_F8, this, TQT_SLOT(slotBuild()), actionCollection(), "build_build" ); m_buildProjectAction->setToolTip(i18n("Build project")); m_buildProjectAction->setWhatsThis(i18n("Build project

Executes ant dist command to build the project.")); KActionMenu *menu = new KActionMenu(i18n("Build &Target"), actionCollection(), "build_target" ); menu->setToolTip(i18n("Build target")); menu->setWhatsThis(i18n("Build target

Executes ant target_name command to build the specified target.")); m_targetMenu = menu->popupMenu(); connect(m_targetMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotTargetMenuActivated(int))); connect(core(), TQT_SIGNAL(projectConfigWidget(KDialogBase*)), this, TQT_SLOT(projectConfigWidget(KDialogBase*))); connect(core(), TQT_SIGNAL(contextMenu(TQPopupMenu *, const Context *)), this, TQT_SLOT(contextMenu(TQPopupMenu *, const Context *))); m_antOptionsWidget = 0; } AntProjectPart::~AntProjectPart() { } void AntProjectPart::openProject(const TQString &dirName, const TQString &projectName) { m_projectDirectory = dirName; m_projectName = projectName; TQDomDocument &dom = *projectDom(); // Set the default directory radio to "executable" /// \FIXME there is no kdevantproject so this will not work ! if (DomUtil::readEntry(dom, "/kdevantproject/run/directoryradio") == "" ) { DomUtil::writeEntry(dom, "/kdevantproject/run/directoryradio", "executable"); } /// @todo read alternative build file from properties m_antOptions.m_buildXML = "build.xml"; parseBuildXML(); fillMenu(); TQFile f(dirName + "/" + projectName.lower() + ".kdevelop" + ".filelist"); if (f.open(IO_ReadOnly)) { TQTextStream stream(&f); while (!stream.atEnd()) { TQString s = stream.readLine(); if (!s.startsWith("#")) m_sourceFiles << s; } } else populateProject(); KDevProject::openProject( dirName, projectName ); } void AntProjectPart::populateProject() { TQApplication::setOverrideCursor(TQt::waitCursor); TQValueStack s; int prefixlen = m_projectDirectory.length()+1; s.push(m_projectDirectory); TQDir dir; do { dir.setPath(s.pop()); kdDebug() << "Examining: " << dir.path() << endl; const TQFileInfoList *dirEntries = dir.entryInfoList(); 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() << "Pushing: " << path << endl; s.push(path); } else { kdDebug() << "Adding: " << path << endl; m_sourceFiles.append(path.mid(prefixlen)); } } } while (!s.isEmpty()); TQApplication::restoreOverrideCursor(); } void AntProjectPart::closeProject() { m_projectDirectory = ""; m_projectName = ""; m_buildProjectAction->setEnabled(false); m_targetMenu->clear(); m_antOptions = AntOptions(); TQFile f(m_projectDirectory + "/" + m_projectName.lower() + ".kdevelop" + ".filelist"); if (!f.open(IO_WriteOnly)) return; TQTextStream stream(&f); stream << "# KDevelop Ant Project File List" << endl; TQStringList::ConstIterator it; for (it = m_sourceFiles.begin(); it != m_sourceFiles.end(); ++it) stream << (*it) << endl; f.close(); } TQString AntProjectPart::projectDirectory() const { return m_projectDirectory; } TQString AntProjectPart::buildDirectory() const { return m_projectDirectory; } TQString AntProjectPart::projectName() const { return m_projectName; } /** Retuns a PairList with the run environment variables */ DomUtil::PairList AntProjectPart::runEnvironmentVars() const { /// \FIXME there is no kdevantproject so this will not work ! return DomUtil::readPairListEntry(*projectDom(), "/kdevantproject/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 AntProjectPart::runDirectory() const { return buildDirectory(); /// \FIXME put the code below into use! TQDomDocument &dom = *projectDom(); /// \FIXME there is no kdevantproject so this will not work ! TQString directoryRadioString = DomUtil::readEntry(dom, "/kdevantproject/run/directoryradio"); TQString DomMainProgram = DomUtil::readEntry(dom, "/kdevantproject/run/mainprogram"); if ( directoryRadioString == "build" ) return buildDirectory(); if ( directoryRadioString == "custom" ) return DomUtil::readEntry(dom, "/kdevantproject/run/customdirectory"); int pos = DomMainProgram.findRev('/'); if (pos != -1) return buildDirectory() + "/" + DomMainProgram.left(pos); return buildDirectory() + "/" + DomMainProgram; } /** 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 AntProjectPart::mainProgram() const { TQDomDocument * dom = projectDom(); if ( !dom ) return TQString(); TQString DomMainProgram = DomUtil::readEntry( *dom, "/kdevantproject/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(); } TQString AntProjectPart::debugArguments() const { return TQString(""); } /** Retuns a TQString with the run command line arguments */ TQString AntProjectPart::runArguments() const { /// \FIXME there is no kdevantproject so this will not work ! return DomUtil::readEntry(*projectDom(), "/kdevantproject/run/programargs"); } TQString AntProjectPart::activeDirectory() const { /// \FIXME // return m_projectDirectory; // returning m_projectDirectory is wrong, the path returned should be _relative_ to the project dir // returning an empty string until antproject supports the idea of an active directory return TQString(""); } TQStringList AntProjectPart::allFiles() const { /* TQStringList res; TQStringList::ConstIterator it; for (it = m_sourceFiles.begin(); it != m_sourceFiles.end(); ++it) { TQString fileName = *it; if (!fileName.startsWith("/")) { fileName.prepend("/"); fileName.prepend(m_projectDirectory); } res += fileName; } return res;*/ // return all files relative to the project directory! return m_sourceFiles; } void AntProjectPart::addFile(const TQString &fileName) { TQStringList fileList; fileList.append ( fileName ); this->addFiles ( fileList ); } void AntProjectPart::addFiles ( const TQStringList& fileList ) { TQStringList::ConstIterator it; for ( it = fileList.begin(); it != fileList.end(); ++it ) { m_sourceFiles.append (*it ); } kdDebug() << "Emitting addedFilesToProject" << endl; emit addedFilesToProject(fileList); } void AntProjectPart::removeFile(const TQString &fileName) { TQStringList fileList; fileList.append ( fileName ); this->removeFiles ( fileList ); } void AntProjectPart::removeFiles ( const TQStringList& fileList ) { kdDebug() << "Emitting removedFilesFromProject" << endl; emit removedFilesFromProject(fileList); TQStringList::ConstIterator it; for ( it = fileList.begin(); it != fileList.end(); ++it ) { m_sourceFiles.remove ( *it ); } } void AntProjectPart::parseBuildXML() { m_antOptions.m_targets.clear(); m_antOptions.m_properties.clear(); m_antOptions.m_defineProperties.clear(); // open build file TQFile bf(m_projectDirectory + "/" + m_antOptions.m_buildXML); if (!bf.open(IO_ReadOnly)) return; // parse build file TQDomDocument dom; if (!dom.setContent(&bf)) { bf.close(); return; } bf.close(); m_projectName = dom.documentElement().attribute("name", m_projectName); m_antOptions.m_defaultTarget = dom.documentElement().attribute("default", ""); TQDomNode node = dom.documentElement().firstChild(); while (!node.isNull()) { if (node.toElement().tagName() == "target") { if (m_antOptions.m_defaultTarget.isEmpty()) m_antOptions.m_defaultTarget = node.toElement().attribute("name"); m_antOptions.m_targets.append(node.toElement().attribute("name")); } else if (node.toElement().tagName() == "property") { m_antOptions.m_properties.insert(node.toElement().attribute("name"), node.toElement().attribute("value")); m_antOptions.m_defineProperties.insert(node.toElement().attribute("name"), false); } /// @todo Handle property files /// @todo evaluate properties' values node = node.nextSibling(); } } void AntProjectPart::fillMenu() { m_buildProjectAction->setEnabled(!m_antOptions.m_defaultTarget.isEmpty()); m_targetMenu->clear(); int id = 0; TQStringList::ConstIterator it; for (it = m_antOptions.m_targets.begin(); it != m_antOptions.m_targets.end(); ++it) m_targetMenu->insertItem(*it, id++); } void AntProjectPart::slotBuild() { ant(m_antOptions.m_defaultTarget); } void AntProjectPart::slotTargetMenuActivated(int id) { ant(m_antOptions.m_targets[id]); } void AntProjectPart::ant(const TQString &target) { TQString cmd = "%0 cd %1 && ant %2 -buildfile %3 %4 %5"; TQString verb = ""; switch (m_antOptions.m_verbosity) { case AntOptions::Quiet: verb = "-quiet"; break; case AntOptions::Verbose: verb = "-verbose"; break; default: verb = "-debug"; break; } TQString options = ""; TQMap::Iterator it; for (it = m_antOptions.m_properties.begin(); it != m_antOptions.m_properties.end(); ++it) if (m_antOptions.m_defineProperties[it.key()]) options += "-D" + it.key() + "=\"" + it.data() + "\" "; TQString cp; if (!m_classPath.count() == 0) cp = "CLASSPATH="+m_classPath.join(":"); makeFrontend()->queueCommand(m_projectDirectory, cmd.arg(cp).arg(m_projectDirectory).arg(target).arg(m_antOptions.m_buildXML).arg(verb).arg(options)); } void AntProjectPart::projectConfigWidget(KDialogBase *dlg) { TQVBox *vbox = dlg->addVBoxPage(i18n("Ant Options")); m_antOptionsWidget = new AntOptionsWidget(vbox); m_antOptionsWidget->BuildXML->setURL(m_antOptions.m_buildXML); switch (m_antOptions.m_verbosity) { case AntOptions::Quiet: m_antOptionsWidget->Verbosity->setCurrentItem(0); break; case AntOptions::Verbose: m_antOptionsWidget->Verbosity->setCurrentItem(1); break; default: m_antOptionsWidget->Verbosity->setCurrentItem(2); break; } m_antOptionsWidget->Properties->setNumRows(m_antOptions.m_properties.count()); m_antOptionsWidget->Properties->setNumCols(2); TQMap::Iterator it; int i=0; for (it = m_antOptions.m_properties.begin(); it != m_antOptions.m_properties.end(); ++it) { TQCheckTableItem *citem = new TQCheckTableItem(m_antOptionsWidget->Properties, it.key()); citem->setChecked(m_antOptions.m_defineProperties[it.key()]); m_antOptionsWidget->Properties->setItem(i,0, citem); TQTableItem *item = new TQTableItem(m_antOptionsWidget->Properties, TQTableItem::WhenCurrent, it.data()); m_antOptionsWidget->Properties->setItem(i,1, item); ++i; } connect(dlg, TQT_SIGNAL(okClicked()), this, TQT_SLOT(optionsAccepted())); vbox = dlg->addVBoxPage(i18n("Classpath")); m_classPathWidget = new ClassPathWidget(vbox); m_classPathWidget->ClassPath->insertStringList(m_classPath); } void AntProjectPart::optionsAccepted() { if (!m_antOptionsWidget || !m_classPathWidget) return; m_antOptions.m_buildXML = m_antOptionsWidget->BuildXML->url(); switch (m_antOptionsWidget->Verbosity->currentItem()) { case 1: m_antOptions.m_verbosity = AntOptions::Verbose; break; case 2: m_antOptions.m_verbosity = AntOptions::Debug; break; default: m_antOptions.m_verbosity = AntOptions::Quiet; break; } for (int i=0; iProperties->numRows(); ++i) { TQString key = m_antOptionsWidget->Properties->text(i,0); m_antOptions.m_properties.replace(key, m_antOptionsWidget->Properties->text(i,1)); kdDebug() << "PROP: " << key << " = " << m_antOptionsWidget->Properties->text(i,1); TQCheckTableItem *item =(TQCheckTableItem*) m_antOptionsWidget->Properties->item(i,0); m_antOptions.m_defineProperties.replace(key, item->isChecked()); } m_classPath = m_classPathWidget->ClassPath->items(); m_antOptionsWidget = 0; m_classPathWidget = 0; } void AntProjectPart::contextMenu(TQPopupMenu *popup, const Context *context) { if (!context->hasType( Context::FileContext )) return; const FileContext *fcontext = static_cast(context); KURL url = fcontext->urls().first(); if (URLUtil::isDirectory(url)) return; m_contextFileName = url.fileName(); bool inProject = project()->allFiles().contains(m_contextFileName.mid ( project()->projectDirectory().length() + 1 ) ); TQString popupstr = TQFileInfo(m_contextFileName).fileName(); if (m_contextFileName.startsWith(projectDirectory()+ "/")) m_contextFileName.remove(0, projectDirectory().length()+1); popup->insertSeparator(); if (inProject) { int id = popup->insertItem( i18n("Remove %1 From Project").arg(popupstr), this, TQT_SLOT(slotRemoveFromProject()) ); popup->setWhatsThis(id, i18n("Remove from project

Removes current file from the project.")); } else { int id = popup->insertItem( i18n("Add %1 to Project").arg(popupstr), this, TQT_SLOT(slotAddToProject()) ); popup->setWhatsThis(id, i18n("Add to project

Adds current file from the project.")); } } void AntProjectPart::slotAddToProject() { TQStringList fileList; fileList.append ( m_contextFileName ); addFiles ( fileList ); } void AntProjectPart::slotRemoveFromProject() { TQStringList fileList; fileList.append ( m_contextFileName ); removeFiles ( fileList ); } #include "antprojectpart.moc" /*! \fn AntProjectPart::distFiles() const */ TQStringList AntProjectPart::distFiles() const { TQStringList sourceList = allFiles(); // Scan current source directory for any .pro files. TQString projectDir = projectDirectory(); TQDir dir(projectDir); TQStringList files = dir.entryList( "build.xml"); return sourceList + files; }