/*************************************************************************** * Copyright (C) 2001-2002 by Bernd Gehrmann * * bernd@kdevelop.org * * Copyright (C) 2007 by Andreas Pakulat * * apaku@gmx.de * * * * 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 "customprojectpart.h" #include #include #include #include #include #include #include #include #include #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 "runoptionswidget.h" #include "makeoptionswidget.h" #include "custombuildoptionswidget.h" #include "custommakeconfigwidget.h" #include "customotherconfigwidget.h" #include "custommanagerwidget.h" #include "config.h" #include "envvartools.h" #include "urlutil.h" #include "selectnewfilesdialog.h" #include typedef KDevGenericFactory CustomProjectFactory; static const KDevPluginInfo data( "kdevcustomproject" ); K_EXPORT_COMPONENT_FACTORY( libkdevcustomproject, CustomProjectFactory( data ) ) CustomProjectPart::CustomProjectPart( TQObject *tqparent, const char *name, const TQStringList & ) : KDevBuildTool( &data, tqparent, name ? name : "CustomProjectPart" ) , m_lastCompilationFailed( false ), m_recursive( false ), m_first_recursive( false ) { setInstance( CustomProjectFactory::instance() ); setXMLFile( "kdevcustomproject.rc" ); m_executeAfterBuild = false; KAction *action; action = new KAction( i18n( "Re-Populate Project" ), 0, this, TQT_SLOT( populateProject() ), actionCollection(), "repopulate_project" ); action->setToolTip( i18n( "Re-Populate Project" ) ); action->setWhatsThis( i18n( "Re-Populate Project

Re-Populates the project, searching through the project directory and adding all files that match one of the wildcards set in the custom manager options of the project filelist." ) ); action = new KAction( i18n( "&Build Project" ), "make_kdevelop", Key_F8, this, TQT_SLOT( slotBuild() ), actionCollection(), "build_build" ); action->setToolTip( i18n( "Build project" ) ); action->setWhatsThis( i18n( "Build project

Runs make from the project directory.
" "Environment variables and make arguments can be specified " "in the project settings dialog, Build Options tab." ) ); action = new KAction( i18n( "&Build Active Directory" ), "make_kdevelop", Key_F7, this, TQT_SLOT( slotBuildActiveDir() ), actionCollection(), "build_buildactivetarget" ); action->setToolTip( i18n( "Build active directory" ) ); action->setWhatsThis( i18n( "Build active directory

Constructs a series of make commands to build the active directory. " "Environment variables and make arguments can be specified " "in the project settings dialog, Make Options tab." ) ); action = new KAction( i18n( "Compile &File" ), "make_kdevelop", this, TQT_SLOT( slotCompileFile() ), actionCollection(), "build_compilefile" ); action->setToolTip( i18n( "Compile file" ) ); action->setWhatsThis( i18n( "Compile file

Runs make filename.o command from the directory where 'filename' is the name of currently opened file.
" "Environment variables and make arguments can be specified " "in the project settings dialog, Build Options tab." ) ); action = new KAction( i18n( "Install" ), 0, this, TQT_SLOT( slotInstall() ), actionCollection(), "build_install" ); action->setToolTip( i18n( "Install" ) ); action->setWhatsThis( i18n( "Install

Runs make install command from the project directory.
" "Environment variables and make arguments can be specified " "in the project settings dialog, Make Options tab." ) ); action = new KAction( i18n( "Install Active Directory" ), 0, this, TQT_SLOT( slotInstallActiveDir() ), actionCollection(), "build_installactivetarget" ); action->setToolTip( i18n( "Install active directory" ) ); action->setWhatsThis( i18n( "Install active directory

Runs make install command from the active directory.
" "Environment variables and make arguments can be specified " "in the project settings dialog, Make Options tab." ) ); action = new KAction( i18n( "Install (as root user)" ), 0, this, TQT_SLOT( slotInstallWithKdesu() ), actionCollection(), "build_install_kdesu" ); action->setToolTip( i18n( "Install as root user" ) ); action->setWhatsThis( i18n( "Install

Runs make install command from the project directory with root privileges.
" "It is executed via kdesu command.
" "Environment variables and make arguments can be specified " "in the project settings dialog, Make Options tab." ) ); action = new KAction( i18n( "&Clean Project" ), 0, this, TQT_SLOT( slotClean() ), actionCollection(), "build_clean" ); action->setToolTip( i18n( "Clean project" ) ); action->setWhatsThis( i18n( "Clean project

Runs make clean command from the project directory.
" "Environment variables and make arguments can be specified " "in the project settings dialog, Build Options tab." ) ); action = new KAction( i18n( "Execute Program" ), "exec", 0, this, TQT_SLOT( slotExecute() ), actionCollection(), "build_execute" ); action->setToolTip( i18n( "Execute program" ) ); action->setWhatsThis( i18n( "Execute program

Executes the main program specified in project settings, Run Options tab. " "If it is not specified then the active target is used to determine the application to run." ) ); KActionMenu *menu = new KActionMenu( i18n( "Build &Target" ), actionCollection(), "build_target" ); m_targetMenu = menu->popupMenu(); menu->setToolTip( i18n( "Build target" ) ); menu->setWhatsThis( i18n( "Build target

Runs make targetname from the project directory (targetname is the name of the target selected).
" "Environment variables and make arguments can be specified " "in the project settings dialog, Build Options tab." ) ); m_targetObjectFilesMenu = new TQPopupMenu(); m_targetOtherFilesMenu = new TQPopupMenu(); m_makeEnvironmentsSelector = new KSelectAction( i18n( "Make &Environment" ), 0, actionCollection(), "build_make_environment" ); m_makeEnvironmentsSelector->setToolTip( i18n( "Make environment" ) ); m_makeEnvironmentsSelector->setWhatsThis( i18n( "Make Environment

Choose the set of environment variables to be passed on to make.
" "Environment variables can be specified in the project " "settings dialog, Build Options tab." ) ); connect( m_targetMenu, TQT_SIGNAL( aboutToShow() ), this, TQT_SLOT( updateTargetMenu() ) ); connect( m_targetMenu, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( targetMenuActivated( int ) ) ); connect( m_targetObjectFilesMenu, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( targetObjectFilesMenuActivated( int ) ) ); connect( m_targetOtherFilesMenu, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( targetOtherFilesMenuActivated( int ) ) ); connect( m_makeEnvironmentsSelector->popupMenu(), TQT_SIGNAL( aboutToShow() ), this, TQT_SLOT( updateMakeEnvironmentsMenu() ) ); connect( m_makeEnvironmentsSelector->popupMenu(), TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( makeEnvironmentsMenuActivated( 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 * ) ) ); connect( makeFrontend(), TQT_SIGNAL( commandFinished( const TQString& ) ), this, TQT_SLOT( slotCommandFinished( const TQString& ) ) ); connect( makeFrontend(), TQT_SIGNAL( commandFailed( const TQString& ) ), this, TQT_SLOT( slotCommandFailed( const TQString& ) ) ); } CustomProjectPart::~CustomProjectPart() {} void CustomProjectPart::projectConfigWidget( KDialogBase *dlg ) { TQVBox *vbox; vbox = dlg->addVBoxPage( i18n( "Custom Manager" ), i18n( "Custom Manager" ), BarIcon( "make", KIcon::SizeMedium ) ); CustomManagerWidget *w0 = new CustomManagerWidget( this, vbox ); connect( dlg, TQT_SIGNAL( okClicked() ), w0, TQT_SLOT( accept() ) ); vbox = dlg->addVBoxPage( i18n( "Run Options" ), i18n( "Run Options" ), BarIcon( "make", KIcon::SizeMedium ) ); RunOptionsWidget *w1 = new RunOptionsWidget( *projectDom(), "/kdevcustomproject", buildDirectory(), vbox ); connect( dlg, TQT_SIGNAL( okClicked() ), w1, TQT_SLOT( accept() ) ); vbox = dlg->addVBoxPage( i18n( "Build Options" ), i18n( "Build Options" ), BarIcon( "make", KIcon::SizeMedium ) ); TQTabWidget *buildtab = new TQTabWidget( vbox ); CustomBuildOptionsWidget *w2 = new CustomBuildOptionsWidget( *projectDom(), buildtab ); connect( dlg, TQT_SIGNAL( okClicked() ), w2, TQT_SLOT( accept() ) ); buildtab->addTab( w2, i18n( "&Build" ) ); CustomOtherConfigWidget *w4 = new CustomOtherConfigWidget( this, "/kdevcustomproject", buildtab ); connect( dlg, TQT_SIGNAL( okClicked() ), w4, TQT_SLOT( accept() ) ); buildtab->addTab( w4, i18n( "&Other" ) ); CustomMakeConfigWidget *w3 = new CustomMakeConfigWidget( this, "/kdevcustomproject", buildtab ); buildtab->addTab( w3, i18n( "Ma&ke" ) ); w2->setMakeOptionsWidget( buildtab, w3, w4 ); connect( dlg, TQT_SIGNAL( okClicked() ), w3, TQT_SLOT( accept() ) ); } void CustomProjectPart::contextMenu( TQPopupMenu *popup, const Context *context ) { if ( !context->hasType( Context::FileContext ) ) return; const FileContext *fcontext = static_cast( context ); m_contextAddFiles.clear(); m_contextRemoveFiles.clear(); TQString popupstr = fcontext->urls().first().fileName(); if ( popupstr == TQString() ) popupstr = "."; if ( fcontext->urls().size() == 1 && URLUtil::isDirectory( fcontext->urls().first() ) && !isInBlacklist( fcontext->urls().first().path() ) ) { popup->insertSeparator(); // remember the name of the directory m_contextDirName = fcontext->urls().first().path(); m_contextDirName = m_contextDirName.mid( project()->projectDirectory().length() + 1 ); int id = popup->insertItem( i18n( "Make Active Directory" ), this, TQT_SLOT( slotChooseActiveDirectory() ) ); popup->tqsetWhatsThis( id, i18n( "Make active directory

" "Chooses this directory as the destination for new files created using wizards " "like the New Class wizard." ) ); } kdDebug( 9025 ) << "context urls: " << fcontext->urls() << endl; if ( fcontext->urls().size() == 1 && ( isProjectFileType( fcontext->urls().first().path() ) || URLUtil::isDirectory( fcontext->urls().first() ) ) ) { popup->insertSeparator(); m_contextDirName = fcontext->urls().first().path(); m_contextDirName = m_contextDirName.mid( project()->projectDirectory().length() + 1 ); int id; if ( isInBlacklist( m_contextDirName ) ) { id = popup->insertItem( i18n( "Remove from blacklist" ), this, TQT_SLOT( slotChangeBlacklist() ) ); popup->tqsetWhatsThis( id, i18n( "Remove from blacklist

" "Removes the given file or directory from the " "blacklist if it is already in it.
The blacklist contains files and" " directories that should be ignored even if they match a project filetype " "pattern" ) ); } else { id = popup->insertItem( i18n( "Add to blacklist" ), this, TQT_SLOT( slotChangeBlacklist() ) ); popup->tqsetWhatsThis( id, i18n( "Add to blacklist

" "Adds the given file or directory to the blacklist.
The blacklist contains files and" " directories that should be ignored even if they match a project filetype " "pattern" ) ); } } const KURL::List urls = fcontext->urls(); bool dirAddRecursive = false; bool dirDelRecursive = false; for ( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it ) { kdDebug( 9025 ) << "Checking URL: " << *it << endl; TQString canPath( URLUtil::canonicalPath(( *it ).path() ) ); TQString relPath = relativeToProject( canPath ); kdDebug( 9025 ) << "relpath: " << relPath << "|canpath: " << canPath << endl; if ( isInBlacklist( relPath ) ) continue; if ((( *it ).isLocalFile() && isProjectFileType(( *it ).fileName() ) ) ) { if ( project()->isProjectFile( canPath ) ) m_contextRemoveFiles << relPath; if ( !project()->isProjectFile( canPath ) ) m_contextAddFiles << relPath; } if ( TQFileInfo(( *it ).path() ).isDir() ) { if ( containsProjectFiles( canPath ) || project()->isProjectFile( canPath ) ) { if ( containsProjectFiles( canPath ) ) dirDelRecursive = true; m_contextRemoveFiles << relPath; } if ( containsNonProjectFiles( canPath ) || !project()->isProjectFile( canPath ) ) { if ( containsNonProjectFiles( canPath ) ) dirAddRecursive = true; m_contextAddFiles << relPath; } } } if ( m_contextAddFiles.size() > 0 || m_contextRemoveFiles.size() > 0 ) popup->insertSeparator(); if ( m_contextAddFiles.size() > 0 ) { int id = popup->insertItem( i18n( "Add Selected File/Dir(s) to Project" ), this, TQT_SLOT( slotAddToProject() ) ); popup->tqsetWhatsThis( id, i18n( "Add to project

Adds selected file/dir(s) to the list of files in the project. " "Note that the files should be manually added to the corresponding makefile or build.xml." ) ); if ( dirAddRecursive ) { int id = popup->insertItem( i18n( "Add Selected Dir(s) to Project (recursive)" ), this, TQT_SLOT( slotAddToProjectRecursive() ) ); popup->tqsetWhatsThis( id, i18n( "Add to project

Recursively adds selected dir(s) to the list of files in the project. " "Note that the files should be manually added to the corresponding makefile or build.xml." ) ); } } if ( m_contextRemoveFiles.size() > 0 ) { int id = popup->insertItem( i18n( "Remove Selected File/Dir(s) From Project" ), this, TQT_SLOT( slotRemoveFromProject() ) ); popup->tqsetWhatsThis( id, i18n( "Remove from project

Removes selected file/dir(s) from the list of files in the project. " "Note that the files should be manually excluded from the corresponding makefile or build.xml." ) ); if ( dirDelRecursive ) { int id = popup->insertItem( i18n( "Remove Selected Dir(s) From Project (recursive)" ), this, TQT_SLOT( slotRemoveFromProjectRecursive() ) ); popup->tqsetWhatsThis( id, i18n( "Remove from project

Recursively removes selected dir(s) from the list of files in the project. " "Note that the files should be manually excluded from the corresponding makefile or build.xml." ) ); } } } void CustomProjectPart::slotAddToProject() { m_recursive = false; m_first_recursive = true; addFiles( m_contextAddFiles ); } void CustomProjectPart::slotRemoveFromProject() { m_recursive = false; m_first_recursive = true; removeFiles( m_contextRemoveFiles ); } void CustomProjectPart::slotAddToProjectRecursive() { m_recursive = true; addFiles( m_contextAddFiles ); m_recursive = false; } void CustomProjectPart::slotRemoveFromProjectRecursive() { m_recursive = true; removeFiles( m_contextRemoveFiles ); m_recursive = false; } void CustomProjectPart::slotChangeBlacklist() { switchBlacklistEntry( m_contextDirName ); } void CustomProjectPart::slotChooseActiveDirectory() { TQString olddir = activeDirectory(); TQDomDocument &dom = *projectDom(); DomUtil::writeEntry( dom, "/kdevcustomproject/general/activedir", m_contextDirName ); emit activeDirectoryChanged( olddir, activeDirectory() ); } void CustomProjectPart::openProject( const TQString &dirName, const TQString &projectName ) { m_projectDirectory = dirName; m_projectName = projectName; TQDomDocument &dom = *projectDom(); // Set the default directory radio to "executable" if ( DomUtil::readEntry( dom, "/kdevcustomproject/run/directoryradio" ) == "" ) { DomUtil::writeEntry( dom, "/kdevcustomproject/run/directoryradio", "executable" ); } if ( filetypes().isEmpty() ) { TQStringList types; types << "*.java" << "*.h" << "*.H" << "*.hh" << "*.hxx" << "*.hpp" << "*.c" << "*.C" << "*.cc" << "*.cpp" << "*.c++" << "*.cxx" << "Makefile" << "CMakeLists.txt"; DomUtil::writeListEntry( dom, "/kdevcustomproject/filetypes", "filetype", types ); } /*this entry is currently only created by the cmake kdevelop3 project generator in order to support completely-out-of-source builds, where nothing, not even the kdevelop project files are created in the source directory, Alex */ m_filelistDir = DomUtil::readEntry( dom, "/kdevcustomproject/filelistdirectory" ); if ( m_filelistDir.isEmpty() ) m_filelistDir = dirName; if ( TQFileInfo( m_filelistDir + "/" + projectName.lower() + ".kdevelop.filelist" ).exists() ) { TQDir( m_filelistDir ).rename( projectName.lower() + ".kdevelop.filelist", projectName + ".kdevelop.filelist" ); } TQFile f( m_filelistDir + "/" + projectName + ".kdevelop.filelist" ); if ( f.open( IO_ReadOnly ) ) { TQTextStream stream( &f ); while ( !stream.atEnd() ) { TQString s = stream.readLine(); // Skip comments. if ( s.isEmpty() || s.startsWith( "#" ) ) continue; // Skip non-existent files. if ( ! TQFileInfo( projectDirectory() + "/" + s ).exists() ) continue; // Do not bother with files already in project or on blacklist. if ( isInProject( s ) || isInBlacklist( s ) ) continue; addToProject( s ); } TQStringList newfiles; findNewFiles( dirName, newfiles ); if ( newfiles.count() > 0 ) { addNewFilesToProject( newfiles ); } } else { int r = KMessageBox::questionYesNo( mainWindow()->main(), i18n( "This project does not contain any files yet.\n" "Populate it with all C/C++/Java files below " "the project directory?" ), TQString(), i18n( "Populate" ), i18n( "Do Not Populate" ) ); if ( r == KMessageBox::Yes ) populateProject(); } // check if there is an old envvars entry (from old project file with single make environment) TQString buildtool = DomUtil::readEntry( dom , "/kdevcustomproject/build/buildtool" ); TQDomElement el = DomUtil::elementByPath( dom , "/kdevcustomproject/" + buildtool + "/envvars" ); if ( !el.isNull() ) { TQDomElement envs = DomUtil::createElementByPath( dom , "/kdevcustomproject/" + buildtool + "/environments" ); DomUtil::makeEmpty( envs ); el.setTagName( "default" ); envs.appendChild( el ); } KDevProject::openProject( dirName, projectName ); } /** * @brief Recursively search given directory searching for files which may be part of this project. * * The files found not in a black list, * and not being already part of our project are gathered. * * @param dir directory to scan (and recurse) for potential project files. * @param[out] fileList the list of files found. */ void CustomProjectPart::findNewFiles( const TQString& dir, TQStringList& filelist ) const { if ( dir.isEmpty() ) return; TQStringList fileentries = TQDir( dir ).entryList( filetypes().join( ";" ) ); TQStringList dirs = TQDir( dir ).entryList( TQDir::Dirs ); TQStringList entries = fileentries + dirs; TQString relpath = relativeToProject( dir ); if ( !relpath.isEmpty() ) relpath += "/"; for ( TQStringList::const_iterator it = entries.begin(); it != entries.end(); ++it ) { // Only process genuine entries - files and directories. if (( *it == "." ) || ( *it == ".." ) ) continue; // If the entry (be it a file or a directory) is already part of this project, proceed to next one. const TQString relativeEntry( relpath + *it ); if ( isInProject( relativeEntry ) ) continue; // If the entry is blacklisted, proceed to next one. // Note that by using generic isInBlacklist(), // we are actually wasting resources, // because it also tests whether any tqparent directory of relativeEntry is blacklisted. // But by the order we are traversing and processing the directories, // we know it is not the case, ever. if ( isInBlacklist( relativeEntry ) ) continue; // We have a new, non-blacklisted entry. // Recurse into it (a directory) or add it to the potential list of new project files. const TQString absoluteEntry( dir + "/" + *it ); if ( TQFileInfo( absoluteEntry ).isFile() ) { filelist << relativeEntry; } else if ( TQFileInfo( absoluteEntry ).isDir() ) { bool searchRecursive = true; TQFileInfo fi( absoluteEntry ); if( fi.isSymLink() ) { TQString realDir = fi.readLink(); if( TQFileInfo( realDir ).exists() ) { for( TQStringList::const_iterator it = filelist.constBegin(); it != filelist.constEnd(); ++it ) { if( TQFileInfo(projectDirectory()+"/"+*it).absFilePath().startsWith( realDir ) ) { searchRecursive = false; } } } else { searchRecursive = false; } } if( searchRecursive ) { findNewFiles( absoluteEntry, filelist ); } } } } void CustomProjectPart::populateProject() { KDialogBase* dlg = new KDialogBase( mainWindow()->main(), "typeselector", true, "Select filetypes of project", KDialogBase::Ok | KDialogBase::Cancel ); TQVBox* box = dlg->makeVBoxMainWidget(); KEditListBox* lb = new KEditListBox( "Filetypes in the project", box, "selecttypes", false, KEditListBox::Add | KEditListBox::Remove ); lb->setItems( filetypes() ); if ( dlg->exec() == TQDialog::Accepted ) { setFiletypes( lb->items() ); } TQApplication::setOverrideCursor( TQt::waitCursor ); removeFiles( allFiles() ); updateBlacklist( TQStringList() ); TQStringList newlist; findNewFiles( projectDirectory(), newlist ); TQApplication::restoreOverrideCursor(); addNewFilesToProject( newlist ); } void CustomProjectPart::closeProject() { saveProject(); } void CustomProjectPart::saveProject() { TQFile f( m_filelistDir + "/" + m_projectName + ".kdevelop.filelist" ); if ( !f.open( IO_WriteOnly ) ) return; TQTextStream stream( &f ); stream << "# KDevelop Custom Project File List" << endl; ProjectFilesSet::ConstIterator it; for ( it = m_sourceFilesSet.constBegin(); it != m_sourceFilesSet.constEnd(); ++it ) stream << it.key() << endl; f.close(); } TQString CustomProjectPart::projectDirectory() const { return m_projectDirectory; } TQString CustomProjectPart::projectName() const { return m_projectName; } /** Retuns a PairList with the run environment variables */ DomUtil::PairList CustomProjectPart::runEnvironmentVars() const { return DomUtil::readPairListEntry( *projectDom(), "/kdevcustomproject/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 CustomProjectPart::runDirectory() const { TQString cwd = defaultRunDirectory( "kdevcustomproject" ); 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 CustomProjectPart::mainProgram() const { TQDomDocument * dom = projectDom(); if ( !dom ) return TQString(); TQString DomMainProgram = DomUtil::readEntry( *dom, "/kdevcustomproject/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 debug command line arguments */ TQString CustomProjectPart::debugArguments() const { return DomUtil::readEntry( *projectDom(), "/kdevcustomproject/run/globaldebugarguments" ); } /** Retuns a TQString with the run command line arguments */ TQString CustomProjectPart::runArguments() const { return DomUtil::readEntry( *projectDom(), "/kdevcustomproject/run/programargs" ); } TQString CustomProjectPart::activeDirectory() const { TQDomDocument &dom = *projectDom(); return DomUtil::readEntry( dom, "/kdevcustomproject/general/activedir", "." ); } TQStringList CustomProjectPart::allFiles() const { return m_sourceFilesSet.keys(); } void CustomProjectPart::addFile( const TQString &fileName ) { TQStringList fileList; fileList.append( fileName ); this->addFiles( fileList ); } void CustomProjectPart::addFiles( const TQStringList& fileList ) { TQStringList::ConstIterator it; TQStringList addedFiles; TQStringList myfileList = fileList; kdDebug( 9025 ) << "Adding files: " << myfileList << endl; myfileList.remove( "." ); myfileList.remove( "" ); myfileList.remove( ".." ); for ( it = myfileList.begin(); it != myfileList.end(); ++it ) { if ( isInBlacklist( *it ) ) continue; TQString relpath; kdDebug( 9025 ) << "Checking path: " << *it << endl; if ( TQDir::isRelativePath( *it ) ) { kdDebug( 9025 ) << *it << " is relative" << endl; relpath = *it; } else { kdDebug( 9025 ) << *it << " is not relative" << endl; relpath = relativeToProject( *it ); } if ( !TQFileInfo( projectDirectory() + "/" + relpath ).exists() ) continue; if ( TQFileInfo( projectDirectory() + "/" + relpath ).isDir() && ( m_recursive || m_first_recursive ) ) { kdDebug( 9025 ) << "is a dir and " << m_recursive << "|" << m_first_recursive << endl; m_first_recursive = false; TQStringList fileentries = TQDir( projectDirectory() + "/" + relpath ).entryList( filetypes().join( ";" ) ); TQStringList dirs = TQDir( projectDirectory() + "/" + relpath ).entryList( TQDir::Dirs ); TQStringList subentries = fileentries + dirs; for ( TQStringList::iterator subit = subentries.begin(); subit != subentries.end(); ++subit ) { if ( *subit != "." && *subit != ".." ) *subit = relpath + "/" + ( *subit ); if (( *subit ).startsWith( "/" ) ) *subit = ( *subit ).mid( 1, ( *subit ).length() ); } addFiles( subentries ); addedFiles << relpath; addToProject( relpath ); m_first_recursive = true; } else if ( isProjectFileType( TQFileInfo( relpath ).fileName() ) && ( ! isInProject( relpath ) ) ) { TQStringList paths = TQStringList::split( "/", relpath ); paths.pop_back(); TQString path; for ( TQStringList::const_iterator it = paths.begin(); it != paths.end(); ++it ) { path += *it; if ( ! isInProject( path ) ) { addedFiles << path; addToProject( path ); } path += "/"; } addedFiles << relpath; addToProject( relpath ); } else { kdDebug( 9025 ) << "not adding " << relpath << endl; } } m_first_recursive = false; saveProject(); kdDebug( 9025 ) << "Emitting addedFilesToProject" << addedFiles << endl; emit addedFilesToProject( addedFiles ); } void CustomProjectPart::removeFile( const TQString &fileName ) { TQStringList fileList; fileList.append( fileName ); this->removeFiles( fileList ); } void CustomProjectPart::removeFiles( const TQStringList& fileList ) { kdDebug( 9025 ) << "Emitting removedFilesFromProject" << fileList << endl; TQStringList removedFiles; TQStringList myfileList = fileList; TQStringList::ConstIterator it; myfileList.remove( "." ); myfileList.remove( ".." ); myfileList.remove( "" ); for ( it = myfileList.begin(); it != myfileList.end(); ++it ) { TQString relpath; if ( TQDir::isRelativePath( *it ) ) relpath = *it; else relpath = relativeToProject( *it ); if ( TQFileInfo( projectDirectory() + "/" + relpath ).isDir() && ( m_recursive || m_first_recursive ) ) { m_first_recursive = false; TQStringList fileentries = TQDir( projectDirectory() + "/" + relpath ).entryList( filetypes().join( ";" ) ); TQStringList dirs = TQDir( projectDirectory() + "/" + relpath ).entryList( TQDir::Dirs ); TQStringList subentries = fileentries + dirs; for ( TQStringList::iterator subit = subentries.begin(); subit != subentries.end(); ++subit ) if ( *subit != "." && *subit != ".." ) *subit = relpath + "/" + ( *subit ); removeFiles( subentries ); if ( !containsProjectFiles( relpath ) ) { removedFiles << relpath; removeFromProject( relpath ); } m_first_recursive = true; } else if ( isInProject( relpath ) ) { removedFiles << relpath; removeFromProject( relpath ); TQStringList paths = TQStringList::split( "/", relpath ); TQString lastsubentry = paths[paths.size()-1]; paths.pop_back(); while ( paths.size() > 0 ) { TQString dir = paths.join( "/" ); TQStringList projectentries = projectFilesInDir( dir ); if ( projectentries.size() == 0 ) { removedFiles << dir; removeFromProject( dir ); } else break; lastsubentry = paths[paths.size()-1]; paths.pop_back(); } } } saveProject(); emit removedFilesFromProject( removedFiles ); } TQString CustomProjectPart::buildDirectory() const { TQString dir = DomUtil::readEntry( *projectDom(), "/kdevcustomproject/build/builddir" ); if ( dir.isEmpty() ) return projectDirectory(); if ( TQFileInfo( dir ).isRelative() ) return TQDir::cleanDirPath( projectDirectory() + "/" + dir ); return dir; } TQString CustomProjectPart::makeEnvironment() const { // Get the make environment variables pairs into the environstr string // in the form of: "ENV_VARIABLE=ENV_VALUE" // Note that we quote the variable value due to the possibility of // embedded spaces TQString buildtool = DomUtil::readEntry( *projectDom(), "/kdevcustomproject/build/buildtool" ); DomUtil::PairList envvars = DomUtil::readPairListEntry( *projectDom(), "/kdevcustomproject/" + buildtool + "/environments/" + currentMakeEnvironment(), "envvar", "name", "value" ); TQString environstr; DomUtil::PairList::ConstIterator it; for ( it = envvars.begin(); it != envvars.end(); ++it ) { environstr += ( *it ).first; environstr += "="; environstr += EnvVarTools::quote(( *it ).second ); environstr += " "; } KConfigGroup grp( kapp->config(), "MakeOutputView" ); if( grp.readBoolEntry( "ForceCLocale", true ) ) environstr += "LC_MESSAGES=" + EnvVarTools::quote( "C" )+" "+" "+"LC_CTYPE="+EnvVarTools::quote("C")+" "; return environstr; } void CustomProjectPart::startMakeCommand( const TQString &dir, const TQString &target, bool withKdesu ) { if ( partController()->saveAllFiles() == false ) return; //user cancelled TQDomDocument &dom = *projectDom(); TQString buildtool = DomUtil::readEntry( dom, "/kdevcustomproject/build/buildtool" ); TQString cmdline; if ( buildtool == "ant" ) { cmdline = "ant"; } else if ( buildtool == "other" ) { cmdline = DomUtil::readEntry( dom, "/kdevcustomproject/other/otherbin" ); if ( cmdline.isEmpty() ) cmdline = "echo"; else if ( cmdline.tqfind( "/" ) == -1 ) cmdline = "./" + cmdline; cmdline += " " + DomUtil::readEntry( dom, "/kdevcustomproject/other/otheroptions" ); } else { cmdline = DomUtil::readEntry( dom, "/kdevcustomproject/make/makebin" ); if ( cmdline.isEmpty() ) cmdline = MAKE_COMMAND; if ( !DomUtil::readBoolEntry( dom, "/kdevcustomproject/make/abortonerror" ) ) cmdline += " -k"; int jobs = DomUtil::readIntEntry( dom, "/kdevcustomproject/make/numberofjobs" ); if ( jobs != 0 ) { cmdline += " -j"; cmdline += TQString::number( jobs ); } if ( DomUtil::readBoolEntry( dom, "/kdevcustomproject/make/dontact" ) ) cmdline += " -n"; cmdline += " " + DomUtil::readEntry( dom, "/kdevcustomproject/make/makeoptions" ); } cmdline += " "; if ( !target.isEmpty() ) cmdline += KProcess::quote( target ); TQString dircmd = "cd "; dircmd += KProcess::quote( dir ); dircmd += " && "; int prio = DomUtil::readIntEntry( dom, "/kdevcustomproject/" + buildtool + "/prio" ); TQString nice; if ( prio != 0 ) { nice = TQString( "nice -n%1 " ).tqarg( prio ); } cmdline.prepend( nice ); cmdline.prepend( makeEnvironment() ); if ( withKdesu ) cmdline = "kdesu -t -c '" + cmdline + "'"; m_buildCommand = dircmd + cmdline; makeFrontend()->queueCommand( dir, dircmd + cmdline ); } void CustomProjectPart::slotBuild() { m_lastCompilationFailed = false; TQString buildtool = DomUtil::readEntry( *projectDom(), "/kdevcustomproject/build/buildtool" ); startMakeCommand( buildDirectory(), DomUtil::readEntry( *projectDom(), "/kdevcustomproject/" + buildtool + "/defaulttarget" ) ); } void CustomProjectPart::slotBuildActiveDir() { m_lastCompilationFailed = false; TQString buildtool = DomUtil::readEntry( *projectDom(), "/kdevcustomproject/build/buildtool" ); startMakeCommand( buildDirectory() + "/" + activeDirectory(), DomUtil::readEntry( *projectDom(), "/kdevcustomproject/" + buildtool + "/defaulttarget" ) ); } void CustomProjectPart::slotCompileFile() { KParts::ReadWritePart *part = dynamic_cast( partController()->activePart() ); if ( !part || !part->url().isLocalFile() ) return; TQString fileName = part->url().path(); TQFileInfo fi( fileName ); TQString sourceDir = fi.dirPath(); TQString baseName = fi.baseName( true ); kdDebug( 9025 ) << "Compiling " << fileName << "in dir " << sourceDir << " with baseName " << baseName << endl; // What would be nice: In case of non-recursive build system, climb up from // the source dir until a Makefile is found TQString buildDir = sourceDir; TQString target = baseName + ".o"; TQString buildtool = DomUtil::readEntry( *projectDom(), "/kdevcustomproject/build/buildtool" ); //if there is no Makefile in the directory of the source file //try to build it from the main build dir //this works e.g. for non-recursive cmake Makefiles, Alex if ( buildtool == "make" && ( TQFile::exists( sourceDir + "/Makefile" ) == false ) && ( TQFile::exists( sourceDir + "/makefile" ) == false ) ) { buildDir = buildDirectory(); } startMakeCommand( buildDir, target ); } void CustomProjectPart::slotInstallActiveDir() { startMakeCommand( buildDirectory() + "/" + activeDirectory(), TQString::tqfromLatin1( "install" ) ); } void CustomProjectPart::slotInstall() { startMakeCommand( buildDirectory(), TQString::tqfromLatin1( "install" ) ); } void CustomProjectPart::slotInstallWithKdesu() { // First issue "make" to build the entire project with the current user // This way we make sure all files are up to date before we do the "make install" slotBuild(); // After that issue "make install" with the root user startMakeCommand( buildDirectory(), TQString::tqfromLatin1( "install" ), true ); } void CustomProjectPart::slotClean() { startMakeCommand( buildDirectory(), TQString::tqfromLatin1( "clean" ) ); } void CustomProjectPart::slotExecute() { partController()->saveAllFiles(); bool _auto = false; if ( DomUtil::readBoolEntry( *projectDom(), "/kdevcustomproject/run/autocompile", true ) && ( isDirty() || !TQFileInfo( mainProgram() ).exists() ) ) { m_executeAfterBuild = true; slotBuild(); _auto = true; } if ( DomUtil::readBoolEntry( *projectDom(), "/kdevcustomproject/run/autoinstall", false ) && ( isDirty() || !TQFileInfo( mainProgram() ).exists() ) ) { m_executeAfterBuild = true; // Use kdesu?? if ( DomUtil::readBoolEntry( *projectDom(), "/kdevcustomproject/run/autokdesu", false ) ) //slotInstallWithKdesu assumes that it hasn't just been build... _auto ? slotInstallWithKdesu() : startMakeCommand( buildDirectory(), TQString::tqfromLatin1( "install" ), true ); else slotInstall(); _auto = true; } if ( _auto ) return; // Get the run environment variables pairs into the environstr string // in the form of: "ENV_VARIABLE=ENV_VALUE" // Note that we quote the variable value due to the possibility of // embedded spaces DomUtil::PairList envvars = runEnvironmentVars(); TQString environstr; DomUtil::PairList::ConstIterator it; for ( it = envvars.begin(); it != envvars.end(); ++it ) { environstr += ( *it ).first; environstr += "="; environstr += EnvVarTools::quote(( *it ).second ); environstr += " "; } if ( mainProgram().isEmpty() ) // Do not execute non executable targets return; TQString program = environstr; program += mainProgram(); program += " " + runArguments(); bool inTerminal = DomUtil::readBoolEntry( *projectDom(), "/kdevcustomproject/run/terminal" ); kdDebug( 9025 ) << "runDirectory: <" << runDirectory() << ">" << endl; kdDebug( 9025 ) << "environstr : <" << environstr << ">" << endl; kdDebug( 9025 ) << "mainProgram : <" << mainProgram() << ">" << endl; kdDebug( 9025 ) << "runArguments: <" << runArguments() << ">" << endl; appFrontend()->startAppCommand( runDirectory(), program, inTerminal ); } void CustomProjectPart::updateTargetMenu() { m_targets.clear(); m_targetsObjectFiles.clear(); m_targetsOtherFiles.clear(); m_targetMenu->clear(); m_targetObjectFilesMenu->clear(); m_targetOtherFilesMenu->clear(); TQDomDocument &dom = *projectDom(); bool ant = DomUtil::readEntry( dom, "/kdevcustomproject/build/buildtool" ) == "ant"; if ( ant ) { TQFile f( buildDirectory() + "/build.xml" ); if ( !f.open( IO_ReadOnly ) ) { kdDebug( 9025 ) << "No build file" << endl; return; } TQDomDocument dom; if ( !dom.setContent( &f ) ) { kdDebug( 9025 ) << "Build script not valid xml" << endl; f.close(); return; } f.close(); TQDomNode node = dom.documentElement().firstChild(); while ( !node.isNull() ) { if ( node.toElement().tagName() == "target" ) m_targets.append( node.toElement().attribute( "name" ) ); node = node.nextSibling(); } } else { kdDebug( 9025 ) << "Trying to load a makefile... " << endl; m_makefileVars.clear(); m_parsedMakefiles.clear(); m_makefilesToParse.clear(); m_makefilesToParse.push( "Makefile" ); m_makefilesToParse.push( "makefile" ); putEnvVarsInVarMap(); while ( !m_makefilesToParse.isEmpty() ) parseMakefile( m_makefilesToParse.pop() ); //free the memory again m_makefileVars.clear(); m_parsedMakefiles.clear(); m_targets.sort(); m_targetsObjectFiles.sort(); m_targetsOtherFiles.sort(); } m_targetMenu->insertItem( i18n( "Object Files" ), m_targetObjectFilesMenu ); m_targetMenu->insertItem( i18n( "Other Files" ), m_targetOtherFilesMenu ); int id = 0; TQStringList::ConstIterator it; for ( it = m_targets.begin(); it != m_targets.end(); ++it ) m_targetMenu->insertItem( *it, id++ ); id = 0; for ( it = m_targetsObjectFiles.begin(); it != m_targetsObjectFiles.end(); ++it ) m_targetObjectFilesMenu->insertItem( *it, id++ ); id = 0; for ( it = m_targetsOtherFiles.begin(); it != m_targetsOtherFiles.end(); ++it ) m_targetOtherFilesMenu->insertItem( *it, id++ ); } void CustomProjectPart::putEnvVarsInVarMap() { DomUtil::PairList envvars = DomUtil::readPairListEntry( *projectDom(), "/kdevcustomproject/make/environments/" + currentMakeEnvironment(), "envvar", "name", "value" ); for ( DomUtil::PairList::ConstIterator it = envvars.begin(); it != envvars.end(); ++it ) m_makefileVars[( *it ).first] = ( *it ).second; //is qouting here required as in makeEnvironment() ?? } void CustomProjectPart::parseMakefile( const TQString& filename ) { if ( m_parsedMakefiles.tqcontains( filename ) ) return; m_parsedMakefiles.insert( filename, 1 ); TQString absFilename = filename; if ( !filename.startsWith( "/" ) ) absFilename = buildDirectory() + "/" + filename; TQFile f( absFilename ); if ( !f.open( IO_ReadOnly ) ) { kdDebug( 9025 ) << "could not open " << absFilename << endl; return; } TQRegExp targetRe( "^ *([^\\t$.#]\\S+) *:.*$" ); targetRe.setMinimal( true ); TQRegExp variablesRe( "\\$\\(\\s*([^\\)\\s]+)\\s*\\)" ); TQRegExp assignmentRe( "^\\s*(\\S+)\\s*[:\\?]?=\\s*(\\S+)\\s*(#.*)?$" ); TQRegExp includedMakefilesRe( "^include\\s+(\\S+)" ); TQString str = ""; while ( !f.atEnd() ) { f.readLine( str, 200 ); // Replace any variables in the current line int offset = -1; while (( offset = variablesRe.search( str, offset + 1 ) ) != -1 ) { TQString variableName = variablesRe.cap( 1 ).simplifyWhiteSpace(); if ( m_makefileVars.tqcontains( variableName ) ) { str.tqreplace( variablesRe.cap( 0 ), m_makefileVars[variableName] ); } } // Read all continuation lines // kdDebug(9025) << "Trying: " << str.simplifyWhiteSpace() << endl; //while (str.right(1) == "\\" && !stream.atEnd()) { // str.remove(str.length()-1, 1); // str += stream.readLine(); //} // Find any variables if ( assignmentRe.search( str ) != -1 ) { m_makefileVars[assignmentRe.cap( 1 ).simplifyWhiteSpace()] = assignmentRe.cap( 2 ).simplifyWhiteSpace(); } else if ( includedMakefilesRe.search( str ) != -1 ) { TQString includedMakefile = includedMakefilesRe.cap( 1 ).simplifyWhiteSpace(); m_makefilesToParse.push( includedMakefile ); } else if ( targetRe.search( str ) != -1 ) { TQString tmpTarget = targetRe.cap( 1 ).simplifyWhiteSpace(); if ( tmpTarget.endsWith( ".o" ) ) { if ( m_targetsObjectFiles.tqfind( tmpTarget ) == m_targetsObjectFiles.end() ) m_targetsObjectFiles += tmpTarget; } else if ( tmpTarget.tqcontains( '.' ) ) { if ( m_targetsOtherFiles.tqfind( tmpTarget ) == m_targetsOtherFiles.end() ) m_targetsOtherFiles += tmpTarget; } else { if ( m_targets.tqfind( tmpTarget ) == m_targets.end() ) m_targets += tmpTarget; } } } f.close(); } void CustomProjectPart::targetMenuActivated( int id ) { TQString target = m_targets[id]; startMakeCommand( buildDirectory(), target ); } void CustomProjectPart::targetObjectFilesMenuActivated( int id ) { TQString target = m_targetsObjectFiles[id]; startMakeCommand( buildDirectory(), target ); } void CustomProjectPart::targetOtherFilesMenuActivated( int id ) { TQString target = m_targetsOtherFiles[id]; startMakeCommand( buildDirectory(), target ); } void CustomProjectPart::updateMakeEnvironmentsMenu() { TQDomDocument &dom = *projectDom(); bool makeUsed = ( DomUtil::readEntry( dom, "/kdevcustomproject/build/buildtool" ) == "make" ); if ( makeUsed ) { TQStringList l = allMakeEnvironments(); m_makeEnvironmentsSelector->setItems( l ); m_makeEnvironmentsSelector->setCurrentItem( l.tqfindIndex( currentMakeEnvironment() ) ); } else { m_makeEnvironmentsSelector->clear(); } /* m_makeEnvironmentsMenu->clear(); TQDomDocument &dom = *projectDom(); TQStringList environments = allMakeEnvironments(); TQStringList::ConstIterator it; int id = 0; for (it = environments.begin(); it != environments.end(); ++it) m_makeEnvironmentsMenu->insertItem(*it, id++); } */ } void CustomProjectPart::makeEnvironmentsMenuActivated( int id ) { TQDomDocument &dom = *projectDom(); TQString environment = allMakeEnvironments()[id]; DomUtil::writeEntry( dom, "/kdevcustomproject/make/selectedenvironment", environment ); } void CustomProjectPart::slotCommandFinished( const TQString& command ) { kdDebug( 9025 ) << "CustomProjectPart::slotProcessFinished()" << endl; if ( m_buildCommand != command ) return; m_buildCommand = TQString(); m_timestamp.clear(); TQStringList fileList = allFiles(); TQStringList::Iterator it = fileList.begin(); while ( it != fileList.end() ) { TQString fileName = *it; ++it; m_timestamp[ fileName ] = TQFileInfo( projectDirectory(), fileName ).lastModified(); } emit projectCompiled(); if ( m_executeAfterBuild ) { slotExecute(); m_executeAfterBuild = false; } } void CustomProjectPart::slotCommandFailed( const TQString& /*command*/ ) { m_lastCompilationFailed = true; m_executeAfterBuild = false; } bool CustomProjectPart::isDirty() { if ( m_lastCompilationFailed ) return true; TQStringList fileList = allFiles(); TQStringList::Iterator it = fileList.begin(); while ( it != fileList.end() ) { TQString fileName = *it; ++it; TQMap::Iterator it = m_timestamp.tqfind( fileName ); TQDateTime t = TQFileInfo( projectDirectory(), fileName ).lastModified(); if ( it == m_timestamp.end() || *it != t ) { return true; } } return false; } TQStringList CustomProjectPart::allMakeEnvironments() const { TQDomDocument &dom = *projectDom(); TQStringList allConfigs; TQDomNode node = DomUtil::elementByPath( dom , "/kdevcustomproject/make/environments" ); // extract the names of the different make environments TQDomElement childEl = node.firstChild().toElement(); while ( !childEl.isNull() ) { TQString config = childEl.tagName(); allConfigs.append( config ); childEl = childEl.nextSibling().toElement(); } if ( allConfigs.isEmpty() ) allConfigs.append( "default" ); return allConfigs; } TQString CustomProjectPart::currentMakeEnvironment() const { TQStringList allEnvs = allMakeEnvironments(); TQDomDocument &dom = *projectDom(); TQString environment = DomUtil::readEntry( dom, "/kdevcustomproject/make/selectedenvironment" ); if ( environment.isEmpty() || !allEnvs.tqcontains( environment ) ) environment = allEnvs[0]; return environment; } /*! \fn CustomProjectPart::distFiles() const */ TQStringList CustomProjectPart::distFiles() const { TQStringList sourceList = allFiles(); // Scan current source directory for any .pro files. TQString projectDir = projectDirectory(); TQDir dir( projectDir ); TQStringList files = dir.entryList( "*README*" ); return sourceList + files; } bool CustomProjectPart::containsNonProjectFiles( const TQString& dir ) { if ( isInBlacklist( dir ) ) return false; TQStringList fileentries = TQDir( dir ).entryList( filetypes().join( ";" ) ); TQStringList dirs = TQDir( dir ).entryList( TQDir::Dirs ); TQStringList subentries = fileentries + dirs; subentries.remove( "." ); subentries.remove( ".." ); for ( TQStringList::const_iterator it = subentries.begin(); it != subentries.end(); ++it ) { if ( isInBlacklist( *it ) ) continue; if ( TQFileInfo( dir + "/" + *it ).isDir() && !isInBlacklist( *it ) ) { if ( containsNonProjectFiles( dir + "/" + *it ) ) { return true; } } else if ( !project()->isProjectFile( URLUtil::canonicalPath( dir + "/" + *it ) ) && !isInBlacklist( *it ) ) { return true; } } return false; } bool CustomProjectPart::containsProjectFiles( const TQString& dir ) { if ( isInBlacklist( dir ) ) return false; TQStringList fileentries = TQDir( dir ).entryList( filetypes().join( ";" ) ); TQStringList dirs = TQDir( dir ).entryList( TQDir::Dirs ); TQStringList subentries = fileentries + dirs; subentries.remove( "." ); subentries.remove( ".." ); for ( TQStringList::const_iterator it = subentries.begin(); it != subentries.end(); ++it ) { if ( isInBlacklist( *it ) ) continue; if ( TQFileInfo( dir + "/" + *it ).isDir() && !isInBlacklist( *it ) ) { if ( containsProjectFiles( dir + "/" + *it ) ) { return true; } } else if ( project()->isProjectFile( URLUtil::canonicalPath( dir + "/" + *it ) ) && !isInBlacklist( *it ) ) { return true; } } return false; } TQStringList CustomProjectPart::projectFilesInDir( const TQString& dir ) { TQStringList result; TQStringList fileentries = TQDir( projectDirectory() + "/" + dir ).entryList( filetypes().join( ";" ) ); TQStringList dirs = TQDir( projectDirectory() + "/" + dir ).entryList( TQDir::Dirs ); TQStringList subentries = fileentries + dirs; subentries.remove( "." ); subentries.remove( ".." ); for ( TQStringList::const_iterator it = subentries.begin(); it != subentries.end(); ++it ) { if ( isInProject( dir + "/" + *it ) ) { result << ( *it ); } } return result; } TQStringList CustomProjectPart::filetypes( ) const { return DomUtil::readListEntry( *projectDom(), "/kdevcustomproject/filetypes", "filetype" ); } bool CustomProjectPart::isProjectFileType( const TQString& filename ) const { TQStringList types = filetypes(); TQRegExp re( "", true, true ); for ( TQStringList::const_iterator it = types.begin(); it != types.end(); ++it ) { re.setPattern( *it ); int pos = re.search( filename ); uint len = re.matchedLength(); if ((( *it ).tqfind( "*" ) != -1 || ( *it ).tqfind( "?" ) != -1 ) && pos + len == filename.length() ) return true; else if ( filename.tqfind( "/" ) != -1 && filename.tqfind( *it ) != -1 ) return true; else if ( filename.tqfind( "/" ) == -1 && filename == *it ) return true; } return false; } void CustomProjectPart::switchBlacklistEntry( const TQString& path ) { TQStringList blacklist = this->blacklist(); kdDebug( 9025 ) << "Switching path " << path << endl; if ( !isInBlacklist( path ) ) { blacklist << path; m_recursive = true; removeFile( path ); m_recursive = false; } else { blacklist.remove( path ); } updateBlacklist( blacklist ); } TQString CustomProjectPart::relativeToProject( const TQString& abspath ) const { TQString path = abspath.mid( projectDirectory().length() + 1 ); kdDebug( 9025 ) << "abspath: " << "|project dir: " << projectDirectory() << "|path: " << path << endl; if ( path.endsWith( "/" ) ) path = path.mid( 0, path.length() - 1 ); if ( path.startsWith( "/" ) ) path = path.mid( 1, path.length() ); return path; } bool CustomProjectPart::isInBlacklist( const TQString& path ) const { TQString relpath = path; TQStringList blacklist = this->blacklist(); if ( !TQFileInfo( relpath ).isRelative() ) relpath = relativeToProject( path ); if ( blacklist.tqfind( relpath ) != blacklist.end() ) return true; TQStringList paths = TQStringList::split( "/", relpath ); TQString parentpath; for ( TQStringList::const_iterator it = paths.begin(); it != paths.end(); ++it ) { parentpath += *it; if ( blacklist.tqfind( parentpath ) != blacklist.end() ) return true; parentpath = parentpath + "/"; } return false; } void CustomProjectPart::updateBlacklist( const TQStringList& l ) { DomUtil::writeListEntry( *projectDom(), "kdevcustomproject/blacklist", "path", l ); } TQStringList CustomProjectPart::blacklist() const { return DomUtil::readListEntry( *projectDom(), "kdevcustomproject/blacklist", "path" ); } void CustomProjectPart::addNewFilesToProject( const TQStringList& filelist ) { TQStringList addfiles; for ( TQStringList::const_iterator it = filelist.begin(); it != filelist.end(); ++it ) { if (( ! isInProject( *it ) ) && ( isProjectFileType( *it ) || TQFileInfo( projectDirectory() + "/" + *it ).isDir() ) && !isInBlacklist( *it ) ) { addfiles << *it; } } if ( addfiles.isEmpty() ) return; SelectNewFilesDialog *dlg = new SelectNewFilesDialog( addfiles, mainWindow()->main() ); if ( dlg->exec() == KDialog::Accepted ) { m_first_recursive = false; m_recursive = false; TQStringList blacklist = this->blacklist(); TQStringList excludelist = dlg->excludedPaths(); TQStringList removeFromExcludes; for ( TQStringList::const_iterator it = excludelist.begin(); it != excludelist.end(); ++it ) { if ( TQFileInfo( projectDirectory() + "/" + *it ).isDir() ) { for ( ProjectFilesSet::ConstIterator it2 = m_sourceFilesSet.constBegin(); it2 != m_sourceFilesSet.constEnd(); ++it2 ) { if ( it2.key().tqfind( *it ) != -1 ) { removeFromExcludes << *it; } } } } for ( TQStringList::const_iterator it = removeFromExcludes.begin(); it != removeFromExcludes.end(); ++it ) { excludelist.remove( *it ); } blacklist += excludelist; updateBlacklist( blacklist ); addFiles( dlg->includedPaths() ); } } void CustomProjectPart::setFiletypes( const TQStringList& l ) { DomUtil::writeListEntry( *projectDom(), "kdevcustomproject/filetypes", "filetype", l ); } /** * @brief Is a given file (or a directory) part of this project? * * @param fileName */ bool CustomProjectPart::isInProject( const TQString& fileName ) const { return m_sourceFilesSet.tqcontains( fileName ); } /** * @brief Add a file (or a directory) to this project. * * @param fileName * * @see removeFromProject() */ void CustomProjectPart::addToProject( const TQString& fileName ) { m_sourceFilesSet.insert( fileName, false ); } /** * @brief Remove a file (or a directory) from this project. * * @param fileName */ void CustomProjectPart::removeFromProject( const TQString& fileName ) { m_sourceFilesSet.remove( fileName ); } #include "customprojectpart.moc"