You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
609 lines
16 KiB
609 lines
16 KiB
#include "antprojectpart.h"
|
|
|
|
#include <tqapplication.h>
|
|
#include <tqfile.h>
|
|
#include <tqfileinfo.h>
|
|
#include <tqpopupmenu.h>
|
|
#include <tqvbox.h>
|
|
#include <tqtable.h>
|
|
#include <tqtextstream.h>
|
|
#include <tqvaluestack.h>
|
|
#include <tqdir.h>
|
|
|
|
|
|
#include <kdevgenericfactory.h>
|
|
#include <kdebug.h>
|
|
#include <kaction.h>
|
|
#include <kpopupmenu.h>
|
|
#include <kdialogbase.h>
|
|
#include <klineedit.h>
|
|
#include <kcombobox.h>
|
|
#include <keditlistbox.h>
|
|
#include <kurlrequester.h>
|
|
|
|
#include <kdevplugininfo.h>
|
|
|
|
#include <kdevcore.h>
|
|
#include <kdevmakefrontend.h>
|
|
#include <urlutil.h>
|
|
|
|
|
|
#include "antoptionswidget.h"
|
|
#include "classpathwidget.h"
|
|
|
|
|
|
|
|
|
|
typedef KDevGenericFactory<AntProjectPart> 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("<b>Build project</b><p>Executes <b>ant dist</b> command to build the project."));
|
|
|
|
KActionMenu *menu = new KActionMenu(i18n("Build &Target"),
|
|
actionCollection(), "build_target" );
|
|
menu->setToolTip(i18n("Build target"));
|
|
menu->setWhatsThis(i18n("<b>Build target</b><p>Executes <b>ant target_name</b> 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<TQString> 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<TQFileInfo> 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<TQString,TQString>::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.tqarg(cp).tqarg(m_projectDirectory).tqarg(target).tqarg(m_antOptions.m_buildXML).tqarg(verb).tqarg(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<TQString,TQString>::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; i<m_antOptionsWidget->Properties->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<const FileContext*>(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").tqarg(popupstr),
|
|
this, TQT_SLOT(slotRemoveFromProject()) );
|
|
popup->tqsetWhatsThis(id, i18n("<b>Remove from project</b><p>Removes current file from the project."));
|
|
}
|
|
else
|
|
{
|
|
int id = popup->insertItem( i18n("Add %1 to Project").tqarg(popupstr),
|
|
this, TQT_SLOT(slotAddToProject()) );
|
|
popup->tqsetWhatsThis(id, i18n("<b>Add to project</b><p>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;
|
|
}
|