/***************************************************************************
 *   Copyright (C) 2003 by Thomas Hasart                                   *
 *   thasart@gmx.de                                                        *
 *   Copyright (C) 2001-2002 by Bernd Gehrmann                             *
 *   bernd@kdevelop.org                                                    *
 *   Copyright (C) 2002 by Jakob Simon-Gaarde                              *
 *   jakob@jsg.dk                                                          *
 *                                                                         *
 *   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 "trollprojectpart.h"

#include <tqdir.h>
#include <tqfileinfo.h>
#include <tqwhatsthis.h>
#include <tdeversion.h>
#include <kdebug.h>
#include <kdialogbase.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kdirwatch.h>
#include <kstatusbar.h>
#include <tqmessagebox.h>
#include <kdevgenericfactory.h>
#include <tdeaction.h>
#include <tdeparts/part.h>
#include <kprocess.h>
#include <tdeconfig.h>
#include <tdeapplication.h>
#include <kurlrequesterdlg.h>
#include <kurlrequester.h>
#include <kurlcompletion.h>
#include <tdefile.h>
#include <makeoptionswidget.h>


#include "domutil.h"
#include "kdevcore.h"
#include "kdevmainwindow.h"
#include "kdevmakefrontend.h"
#include "kdevappfrontend.h"
#include "kdevpartcontroller.h"
#include "trollprojectwidget.h"
#include "runoptionswidget.h"
#include "config.h"
#include "envvartools.h"
#include "qmakeoptionswidget.h"
#include "scope.h"

#include <kdevplugininfo.h>
#include <urlutil.h>

typedef KDevGenericFactory<TrollProjectPart> TrollProjectFactory;
static const KDevPluginInfo pluginData("kdevtrollproject");
K_EXPORT_COMPONENT_FACTORY( libkdevtrollproject, TrollProjectFactory( pluginData ) )

TrollProjectPart::TrollProjectPart(TQObject *parent, const char *name, const TQStringList& args )
    : KDevBuildTool(&pluginData, parent, name ? name : "TrollProjectPart")
{
    setInstance(TrollProjectFactory::instance());

    if ( args.count() == 1 && args[0] == "TMake" )
        m_tmakeProject = true;
    else
        m_tmakeProject = false;

    setXMLFile("kdevtrollproject.rc");

    m_executeProjectAfterBuild = false;
    m_executeTargetAfterBuild = false;

    m_dirWatch = new KDirWatch(this);

    m_widget = new TrollProjectWidget(this);
    m_widget->setIcon(SmallIcon("qmakerun"));
    m_widget->setCaption(i18n("TQMake Manager"));
    TQWhatsThis::add(m_widget, i18n("<b>TQMake manager</b><p>"
                                   "The TQMake manager project tree consists of two parts. The 'overview' "
                                   "in the upper half shows the subprojects, each one having a "
                                   ".pro file. The 'details' view in the lower half shows the "
                                   "list of files for the active subproject selected in the overview."));

    mainWindow()->embedSelectViewRight(m_widget, i18n("TQMake Manager"), i18n("TQMake manager"));

    TDEAction *action;

    const TQIconSet icon(SmallIcon("compfile"));
    action = new TDEAction( i18n("Compile &File"), "compfile", 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotBuildOpenFile()),
                          actionCollection(),"build_compilefile"  );
    action->setToolTip(i18n("Compile file"));
    action->setWhatsThis(i18n("<b>Compile file</b><p>Runs <b>make filename.o</b> command from the directory where 'filename' is the name of currently opened file.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));


    action = new TDEAction( i18n("&Build Project"), "make_tdevelop", Key_F8,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotBuildProject()),
                          actionCollection(), "build_build_project" );
    action->setToolTip(i18n("Build project"));
    action->setWhatsThis(i18n("<b>Build project</b><p>Runs <b>make</b> from the project directory.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Rebuild Project"),"rebuild" , 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotRebuildProject()),
                          actionCollection(),"build_rebuild_project"  );
    action->setToolTip(i18n("Rebuild project"));
    action->setWhatsThis(i18n("<b>Rebuild project</b><p>Runs <b>make clean</b> and then <b>make</b> from the project directory.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Install Project"),"install" , 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotInstallProject()),
                          actionCollection(),"build_install_project"  );
    action->setToolTip(i18n("Install project"));
    action->setWhatsThis(i18n("<b>Install project</b><p>Runs <b>make install</b> from the project directory.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Clean Project"), 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotCleanProject()),
                          actionCollection(), "build_clean_project" );
    action->setToolTip(i18n("Clean project"));
    action->setWhatsThis(i18n("<b>Clean project</b><p>Runs <b>make clean</b> command from the project directory.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Dist-Clean Project"), 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotDistCleanProject()),
                          actionCollection(), "build_distclean_project" );
    action->setToolTip(i18n("Dist-Clean project"));
    action->setWhatsThis(i18n("<b>Dist-Clean project</b><p>Runs <b>make distclean</b> command from the "
                              "project directory.<br>Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("Execute Main Program"), "application-x-executable", SHIFT+Key_F9,
                          this, TQT_SLOT(slotBuildAndExecuteProject()),
                          actionCollection(), "build_execute_project" );
    action->setToolTip(i18n("Execute main program"));
    action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the currently selected subproject if it is an application or the program specified in project settings, <b>Run Options</b> tab."));

    action = new TDEAction( i18n("&Build Subproject"), "make_tdevelop", Key_F7,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotBuildTarget()),
                          actionCollection(), "build_build_target" );
    action->setToolTip(i18n("Build subproject"));
    action->setWhatsThis(i18n("<b>Build subproject</b><p>Runs <b>make</b> from the current subproject directory. "
                              "Current subproject is a subproject selected in <b>TQMake manager</b> 'overview' window.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Rebuild Subproject"), "rebuild", 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotRebuildTarget()),
                          actionCollection(),"build_rebuild_target"  );
    action->setToolTip(i18n("Rebuild subproject"));
    action->setWhatsThis(i18n("<b>Rebuild subproject</b><p>Runs <b>make clean</b> and then <b>make</b> from the current subproject directory. "
                              "Current subproject is a subproject selected in <b>TQMake manager</b> 'overview' window.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Install Subproject"), "install", 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotInstallTarget()),
                          actionCollection(),"build_install_target"  );
    action->setToolTip(i18n("Install subproject"));
    action->setWhatsThis(i18n("<b>Install subproject</b><p>Runs <b>make install</b> from the current subproject directory. "
                              "The current subproject is the subproject selected in the <b>TQMake manager</b> 'overview' window.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Clean Subproject"), 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotCleanTarget()),
                          actionCollection(), "build_clean_target" );
    action->setToolTip(i18n("Clean subproject"));
    action->setWhatsThis(i18n("<b>Clean subproject</b><p>Runs <b>make clean</b> from the current subproject directory. "
                              "The current subproject is the subproject selected in the <b>TQMake manager</b> 'overview' window.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("&Dist-Clean Subproject"), 0,
                          TQT_TQOBJECT(m_widget), TQT_SLOT(slotDistCleanTarget()),
                          actionCollection(), "build_distclean_target" );
    action->setToolTip(i18n("Dist-Clean subproject"));
    action->setWhatsThis(i18n("<b>Dist-Clean subproject</b><p>Runs <b>make distclean</b> from the current"
                              " subproject directory. The current subproject is the subproject selected in the <b>TQMake manager</b> 'overview' window.<br>"
                              "Environment variables and make arguments can be specified "
                              "in the project settings dialog, <b>Make Options</b> tab."));

    action = new TDEAction( i18n("Execute Subproject"), "application-x-executable", 0,
                          this, TQT_SLOT(slotBuildAndExecuteTarget()),
                          actionCollection(), "build_execute_target" );
    action->setToolTip(i18n("Execute subproject"));
    action->setWhatsThis(i18n("<b>Execute subproject</b><p>Executes the target program for the currently selected subproject. "
        "This action is allowed only if a type of the subproject is 'application'. The type of the subproject can be "
        "defined in <b>Subproject Settings</b> dialog (open it from the subproject context menu)."));

    connect( core(), TQT_SIGNAL(projectConfigWidget(KDialogBase*)),
             this, TQT_SLOT(projectConfigWidget(KDialogBase*)) );

    connect( makeFrontend(), TQT_SIGNAL(commandFinished(const TQString&)),
             this, TQT_SLOT(slotCommandFinished(const TQString&)) );

    TQString m_defaultTQtDir = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/root", "");
    TQString m_qmakePath = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/qmake", "");
    TQString qtversion = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/version", "3");

    if( m_defaultTQtDir.isEmpty() || !isValidTQtDir( m_defaultTQtDir ) )
    {
        m_defaultTQtDir = findTQtDir();
        kdDebug(9024) << "Setting default dir to: " << m_defaultTQtDir << endl;
        DomUtil::writeEntry(*projectDom(), "/kdevcppsupport/qt/root", m_defaultTQtDir );
    }
    if( m_qmakePath.isEmpty() || !isExecutable( m_qmakePath ) )
    {
        m_qmakePath = findExecutable( "qmake-qt"+qtversion );
        if( m_qmakePath.isEmpty() || !isExecutable( m_qmakePath ) )
            m_qmakePath = findExecutable( "qmake" );
        kdDebug(9024) << "Setting qmake binary to: " << m_qmakePath << endl;
        DomUtil::writeEntry(*projectDom(), "/kdevcppsupport/qt/qmake", m_qmakePath );
    }
}


TrollProjectPart::~TrollProjectPart()
{
    if (m_widget)
        mainWindow()->removeView(m_widget);
    delete m_widget;
}

TQString TrollProjectPart::makeEnvironment()
{
    // 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
    DomUtil::PairList envvars =
        DomUtil::readPairListEntry(*projectDom(), "/kdevtrollproject/make/envvars", "envvar", "name", "value");

    TQString environstr;
    DomUtil::PairList::ConstIterator it;
    bool hasTQtDir = false;
    for (it = envvars.begin(); it != envvars.end(); ++it) {
        if( (*it).first == "QTDIR" )
	    hasTQtDir = true;

        environstr += (*it).first;
        environstr += "=";
        environstr += EnvVarTools::quote((*it).second);
        environstr += " ";
    }

    if( !hasTQtDir && !isTQt4Project() && !DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/root", "").isEmpty() )
    {
         environstr += TQString( "QTDIR=" ) + EnvVarTools::quote( DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/root", "") ) + TQString( " PATH=$TQTDIR/bin:$PATH " );
    }

    TDEConfigGroup grp( kapp->config(), "MakeOutputView" );
    if( grp.readBoolEntry( "ForceCLocale", true ) )
        environstr += "LC_MESSAGES="+EnvVarTools::quote("C")+" "+" "+"LC_CTYPE="+EnvVarTools::quote("C")+" ";

    return environstr;
}

void TrollProjectPart::projectConfigWidget(KDialogBase *dlg)
{
    TQVBox *vbox;
    vbox = dlg->addVBoxPage(i18n("Run Options"), i18n("Run Options"), BarIcon( "text-x-makefile", TDEIcon::SizeMedium ));
    RunOptionsWidget *optdlg = new RunOptionsWidget(*projectDom(), "/kdevtrollproject", buildDirectory(), vbox);

    vbox = dlg->addVBoxPage(i18n("Make Options"), i18n("Make Options"), BarIcon( "text-x-makefile", TDEIcon::SizeMedium ));
    MakeOptionsWidget *w4 = new MakeOptionsWidget(*projectDom(), "/kdevtrollproject", vbox);

    vbox = dlg->addVBoxPage(i18n("TQMake Manager"), i18n("TQMake Manager"), BarIcon( "text-x-makefile", TDEIcon::SizeMedium ));
    QMakeOptionsWidget *qm = new QMakeOptionsWidget( projectDirectory(), *projectDom(), "/kdevtrollproject", vbox);


    connect( dlg, TQT_SIGNAL(okClicked()), w4, TQT_SLOT(accept()) );
    connect( dlg, TQT_SIGNAL(okClicked()), qm, TQT_SLOT(accept()) );
    connect( dlg, TQT_SIGNAL(okClicked()), optdlg, TQT_SLOT(accept()) );
}


void TrollProjectPart::openProject(const TQString &dirName, const TQString &projectName)
{
    mainWindow()->statusBar()->message( i18n("Loading Project...") );

    TQString defaultTQtDir = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/root", "");
    if( !isTQt4Project() && ( defaultTQtDir.isEmpty() || !isValidTQtDir( defaultTQtDir ) ) )
    {
        bool doask = true;
        while( doask )
        {
            KURLRequesterDlg dlg( i18n("Choose TQt3 directory"),
                i18n("Choose the TQt3 directory to use. This directory needs to have an include directory containing tqt.h.")
                                  , m_widget, 0);
            dlg.urlRequester() ->setMode( KFile::Directory | KFile::LocalOnly );
            dlg.urlRequester() ->setURL( TQString() );
            dlg.urlRequester() ->completionObject() ->setDir( "/" );

            if ( dlg.exec() == TQDialog::Accepted && !dlg.urlRequester() ->url().isEmpty() )
            {
                TQString qtdir = dlg.urlRequester()->url();
                if( !isValidTQtDir( qtdir ) )
                {
                    if( KMessageBox::warningYesNo( m_widget,
                                                i18n("The directory you gave is not a proper TQt directory, the "
                                                    "project might not work properly without one.\nPlease make "
                                                    "sure you give a directory that contains a bin with the "
                                                    "qmake binary in it and for TQt3 project also contains an "
                                                    "include directory with tqt.h in it.\nDo you want to try "
                                                    "setting a TQt directory again?"),
                                                i18n("Wrong TQt directory given"))
                        == KMessageBox::Yes
                    )
                    doask = true;
                else
                    doask = false;
                }else
                {
                    defaultTQtDir = qtdir;
                    doask = false;
                }

            }else
            {
                if( KMessageBox::warningYesNo( m_widget,
                                               i18n("You did not specify a TQt directory, and the project might not "
                                                   "work properly without one.\nDo you want to try setting a TQt"
                                                   " directory again?"),
                                               i18n("No TQt directory given"))
                        == KMessageBox::Yes
                    )
                    doask = true;
                else
                    doask = false;
            }
        }
    }
    TQString qmakePath = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/qmake", "");
    if( qmakePath.isEmpty() || !isExecutable( qmakePath ) )
    {
        bool doask = true;
        while( doask )
        {
            KURLRequesterDlg dlg( i18n("Choose TQMake executable"),
                i18n("Choose the TQMake binary to use. TQMake is used to generate Makefiles from the project files."), m_widget, 0);
            dlg.urlRequester() ->setMode( KFile::Directory | KFile::LocalOnly );
            dlg.urlRequester() ->setURL( TQString() );
            dlg.urlRequester() ->completionObject() ->setDir( "/" );

            if ( dlg.exec() == TQDialog::Accepted && !dlg.urlRequester() ->url().isEmpty() )
            {
                TQString qmake = dlg.urlRequester()->url();
                if( !isExecutable( qmake ) )
                {
                    if( KMessageBox::warningYesNo( m_widget,
                                                i18n("The binary you gave is not executable, the "
                                                    "project might not work properly.\nPlease make "
                                                    "sure you give a qmake binary that is executable.\nDo you want to try "
                                                    "setting the TQMake binary again?"),
                                                i18n("Wrong TQMake binary given"))
                        == KMessageBox::Yes
                    )
                    doask = true;
                else
                    doask = false;
                }else
                {
                    qmakePath = qmake;
                    doask = false;
                }

            }else
            {
                if( KMessageBox::warningYesNo( m_widget,
                                               i18n("You did not specify a TQMake binary, and the project might not "
                                                   "work properly without one.\nDo you want to try setting a TQMake"
                                                   " binary again?"),
                                               i18n("No TQMake binary given"))
                        == KMessageBox::Yes
                    )
                    doask = true;
                else
                    doask = false;
            }
        }
    }
    DomUtil::writeEntry( *projectDom(), "/kdevcppsupport/qt/root", defaultTQtDir );
    DomUtil::writeEntry( *projectDom(), "/kdevcppsupport/qt/qmake", qmakePath );

    m_projectName = projectName;

    m_widget->openProject(dirName);


    TQDomDocument &dom = *projectDom();
    // Set the default directory radio to "executable"
    if (DomUtil::readEntry(dom, "/kdevtrollproject/run/directoryradio") == "" ) {
        DomUtil::writeEntry(dom, "/kdevtrollproject/run/directoryradio", "executable");
    }

    KDevProject::openProject( dirName, projectName );
}


void TrollProjectPart::closeProject()
{
    m_widget->closeProject();
}


TQString TrollProjectPart::projectDirectory() const
{
  return m_widget->projectDirectory();
}


TQString TrollProjectPart::buildDirectory() const
{
  return m_widget->projectDirectory();
}

TQString TrollProjectPart::projectName() const
{
    return m_projectName;
}


/** Retuns a PairList with the run environment variables */
DomUtil::PairList TrollProjectPart::runEnvironmentVars() const
{
    return DomUtil::readPairListEntry(*projectDom(), "/kdevtrollproject/run/envvars", "envvar", "name", "value");
}

void TrollProjectPart::slotBuildAndExecuteProject()
{
    partController()->saveAllFiles();
    if (isDirty()) {
        m_executeProjectAfterBuild = true;
        m_widget->slotBuildProject();
    } else
        m_widget->slotExecuteProject();
}

void TrollProjectPart::slotBuildAndExecuteTarget()
{
    partController()->saveAllFiles();
    if (isDirty()) {
        m_executeTargetAfterBuild = true;
        m_widget->slotBuildTarget();
    } else
        m_widget->slotExecuteTarget();
}


/** 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 TrollProjectPart::runDirectory() const
{
    TQDomDocument &dom = *projectDom();

    TQString cwd;
    if( DomUtil::readBoolEntry(dom, "/kdevtrollproject/run/useglobalprogram", true) )
    {
        cwd = defaultRunDirectory("kdevtrollproject");
    }else
    {
        TQString name = m_widget->getCurrentOutputFilename();
        if( name.findRev("/") != -1 )
            name = name.right( name.length()-name.findRev("/")-1 );
        cwd = DomUtil::readEntry( dom, "/kdevtrollproject/run/cwd/" + name );
    }
    if( cwd.isEmpty() )
    {
        TQString destpath = m_widget->getCurrentTarget();
        if( TQDir::isRelativePath( destpath ) )
        {
            destpath = m_widget->subprojectDirectory() + TQString( TQChar( TQDir::separator() ) ) + destpath;
        }
        destpath = destpath.left( destpath.findRev("/") );
        cwd = destpath;
    }

    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 TrollProjectPart::mainProgram() const
{

    TQDomDocument &dom = *projectDom();

    if( DomUtil::readBoolEntry(dom, "/kdevtrollproject/run/useglobalprogram", false) )
    {
        TQString DomMainProgram = DomUtil::readEntry(dom, "/kdevtrollproject/run/mainprogram");

        if ( DomMainProgram.isEmpty() ) return TQString();

        if ( DomMainProgram.startsWith("/") )   // assume absolute path
        {
            return DomMainProgram;
        }
        else // assume project relative path
        {
            return projectDirectory() + "/" + DomMainProgram;
        }
    }else
    {
        if( !m_widget->currentSubproject())
        {
            KMessageBox::error( m_widget, "There's no selected subproject!\n"
                                "Unable to determine the main program", "No selected subproject found" );
            kdDebug ( 9020 ) << k_funcinfo << "Error! : There's no active target! -> Unable to determine the main program in TrollProjectPart::mainProgram()" << endl;
            return TQString();
        }

        if ( m_widget->currentSubproject()->scope->variableValues("TEMPLATE").findIndex("app") == -1 )
        {
            KMessageBox::error( m_widget, "Selected Subproject \""+m_widget->currentSubproject()->scope->projectName()+"\"isn't binary ( " + m_widget->currentSubproject()->scope->variableValues("TEMPLATE").join(" ") + " ) !\n"
                                "Unable to determine the main program. If you want this\n"
                                "to be the selected subproject, set a main program under\n"
                                "Project -> Project Options -> Run Options", "Selected subproject is not a library" );
            kdDebug ( 9020 ) << k_funcinfo << "Error! : Active target isn't binary (" << m_widget->currentSubproject()->scope->variableValues("TEMPLATE").join(" ") << ") ! -> Unable to determine the main program in TrollProjectPart::mainProgram()" << endl;
            return TQString();
        }

        TQString destpath = m_widget->getCurrentTarget();
        if( TQDir::isRelativePath( destpath ) )
        {
            destpath = m_widget->subprojectDirectory() + TQString( TQChar( TQDir::separator() ) ) + destpath;
        }
        return destpath;
    }
}

TQString TrollProjectPart::debugArguments() const
{
    if( DomUtil::readBoolEntry(*projectDom(), "/kdevtrollproject/run/useglobalprogram", true ) )
    {
        return DomUtil::readEntry(*projectDom(), "/kdevtrollproject/run/globaldebugarguments");
    }else
    {
        return DomUtil::readEntry(*projectDom(), "/kdevtrollproject/run/debugarguments/"+m_widget->getCurrentOutputFilename() );
    }
}

/** Retuns a TQString with the run command line arguments */
TQString TrollProjectPart::runArguments() const
{
    if( DomUtil::readBoolEntry(*projectDom(), "/kdevtrollproject/run/useglobalprogram", true) )
    {
        return DomUtil::readEntry(*projectDom(), "/kdevtrollproject/run/programargs");
    }else
    {
        return DomUtil::readEntry(*projectDom(), "/kdevtrollproject/run/runarguments/"+m_widget->getCurrentOutputFilename() );
    }
}


TQString TrollProjectPart::activeDirectory() const
{
    TQDomDocument &dom = *projectDom();

    return DomUtil::readEntry(dom, "/kdevtrollproject/general/activedir");
}


TQStringList TrollProjectPart::allFiles() const
{
    return m_widget->allFiles();
}


void TrollProjectPart::addFile(const TQString &fileName)
{
	TQStringList fileList;
	fileList.append ( fileName );

    this->addFiles ( TQStringList( fileName ) );
}

void TrollProjectPart::addFiles ( const TQStringList &fileList )
{
    TQStringList files = fileList;
    for (TQStringList::iterator it = files.begin(); it != files.end(); ++it)
    {
        if( !TQFileInfo( *it ).isRelative() )
        {
            *it = URLUtil::relativePathToFile( projectDirectory(), *it );
        }
    }
    m_widget->addFiles(files);

}

void TrollProjectPart::removeFile(const TQString & /* fileName */)
{
    /// \FIXME
/*	TQStringList fileList;
	fileList.append ( fileName );

	this->removeFiles ( fileList );*/
}

void TrollProjectPart::removeFiles ( const TQStringList& fileList )
{
/// \FIXME missing remove files functionality
// 	TQStringList::ConstIterator it;
//
// 	it = fileList.begin();
//
// 	for ( ; it != fileList.end(); ++it )
// 	{
// 		FIXME
// 	}

	emit removedFilesFromProject ( fileList );
}
/*
void TrollProjectPart::startMakeCommand(const TQString &dir, const TQString &target)
{
    partController()->saveAllFiles();

    TQFileInfo fi(dir + "/Makefile");
    if (!fi.exists()) {
        int r = KMessageBox::questionYesNo(m_widget, i18n("There is no Makefile in this directory. Run qmake first?"), TQString(), i18n("Run qmake"), i18n("Do Not Run"));
        if (r == KMessageBox::No)
            return;
        startTQMakeCommand(dir);
    }
    TQDomDocument &dom = *projectDom();

    if (target=="clean")
    {
      TQString cmdline = DomUtil::readEntry(dom, "/kdevtrollproject/make/makebin");
      if (cmdline.isEmpty())
          cmdline = MAKE_COMMAND;
      cmdline += " clean";
      TQString dircmd = "cd ";
      dircmd += dir;
      dircmd += " && ";
      cmdline.prepend(makeEnvironment());
      makeFrontend()->queueCommand(dir, dircmd + cmdline);
    }

    TQString cmdline = DomUtil::readEntry(dom, "/kdevtrollproject/make/makebin");
    if (cmdline.isEmpty())
        cmdline = MAKE_COMMAND;
    if (!DomUtil::readBoolEntry(dom, "/kdevtrollproject/make/abortonerror"))
        cmdline += " -k";
    int jobs = DomUtil::readIntEntry(dom, "/kdevtrollproject/make/numberofjobs");
    if (jobs != 0) {
        cmdline += " -j";
        cmdline += TQString::number(jobs);
    }
    if (DomUtil::readBoolEntry(dom, "/kdevtrollproject/make/dontact"))
        cmdline += " -n";

    cmdline += " ";
    cmdline += target;

    TQString dircmd = "cd ";
    dircmd += dir;
    dircmd += " && ";

    cmdline.prepend(makeEnvironment());
    makeFrontend()->queueCommand(dir, dircmd + cmdline);
}
*/

void TrollProjectPart::startTQMakeCommand(const TQString &dir, bool recursive)
{
    TQFileInfo fi(dir);
    TQString cmdline;

    if ( isTMakeProject() )
    {
    	cmdline = "tmake ";
    }else
    {
        cmdline = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/qmake", "")+" ";
    }

    if(isTQt4Project() && recursive)
    {
        cmdline += " -recursive ";
    }

    //TQString cmdline = TQString::fromLatin1( isTMakeProject() ? "tmake " : "qmake " );
//    cmdline += fi.baseName() + ".pro";
    TQDir d(dir);
    TQStringList l = d.entryList("*.pro");

    if( l.isEmpty() || ( l.count() && l.findIndex( projectName() + ".pro" ) != -1 ) )
        cmdline += projectName()+".pro";
    else if( l.isEmpty() || (l.count() && l.findIndex( fi.baseName() + ".pro" ) != -1 ) )
        cmdline += fi.baseName() + ".pro";
    else
        cmdline += l[0];

//    cmdline += TQString::fromLatin1( " -o Makefile" );

    TQString dircmd = "cd ";
    dircmd += TDEProcess::quote(dir);
    dircmd += " && ";

    cmdline.prepend(makeEnvironment());
    makeFrontend()->queueCommand(dir, dircmd + cmdline);
}

void TrollProjectPart::queueCmd(const TQString &dir, const TQString &cmd)
{
    makeFrontend()->queueCommand(dir, cmd);
}

void TrollProjectPart::slotCommandFinished( const TQString& command )
{
    Q_UNUSED( command );

//     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_executeProjectAfterBuild )
    {
        m_widget->slotExecuteProject();
        m_executeProjectAfterBuild = false;
    }else if( m_executeTargetAfterBuild )
        {
        m_widget->slotExecuteTarget();
        m_executeTargetAfterBuild = false;
    }

}

bool TrollProjectPart::isDirty()
{
    TQStringList fileList = allFiles();
    TQStringList::Iterator it = fileList.begin();
    while( it != fileList.end() ){
        TQString fileName = *it;
        ++it;

        TQMap<TQString, TQDateTime>::Iterator it = m_timestamp.find( fileName );
        TQDateTime t = TQFileInfo( projectDirectory(), fileName ).lastModified();
        if( it == m_timestamp.end() || *it != t ){
            return true;
        }
    }

    return false;
}

KDevProject::Options TrollProjectPart::options( ) const
{
    return UsesTQMakeBuildSystem;
}

bool TrollProjectPart::isValidTQtDir( const TQString& path ) const
{
    TQFileInfo inc( path + TQString( TQChar( TQDir::separator() ) )+
                   "include"+TQString( TQChar( TQDir::separator() ) )+
                   "tqt.h" );
    return ( isTQt4Project() || ( !isTQt4Project() && inc.exists() ) );
}

void TrollProjectPart::buildBinDirs( TQStringList & dirs ) const
{
    if( !isTQt4Project() )
    {
        TQString m_defaultTQtDir = DomUtil::readEntry(*projectDom(), "/kdevcppsupport/qt/root", "");
        if( !m_defaultTQtDir.isEmpty() )
            dirs << (m_defaultTQtDir + TQString( TQChar( TQDir::separator() ) ) + "bin" );
        dirs << ( ::getenv("QTDIR") + TQString( TQChar( TQDir::separator() ) ) + "bin" );
    }
    TQStringList paths = TQStringList::split(":",::getenv("PATH"));
    dirs += paths;
    TQString binpath = TQDir::rootDirPath() + "bin";
    if( dirs.findIndex( binpath ) != -1 )
        dirs << binpath;

    binpath = TQDir::rootDirPath() + "usr" + TQString( TQChar( TQDir::separator() ) ) + "bin";
    if( dirs.findIndex( binpath ) != -1 )
        dirs << binpath;
    binpath = TQDir::rootDirPath() + "usr" + TQString( TQChar( TQDir::separator() ) ) + "local" + TQString( TQChar( TQDir::separator() ) ) + "bin";
    if( dirs.findIndex( binpath ) != -1 )
        dirs << binpath;
}


TQString TrollProjectPart::findExecutable( const TQString& execname ) const
{
    TQStringList dirs;
    buildBinDirs( dirs );

    for( TQStringList::Iterator it=dirs.begin(); it!=dirs.end(); ++it )
    {
        TQString designer = *it + TQString( TQChar( TQDir::separator() ) ) + execname;
        if( !designer.isEmpty() && isExecutable( designer ) )
        {
            return designer;
        }
    }
    return "";
}

bool TrollProjectPart::isExecutable( const TQString& path ) const
{
    TQFileInfo fi(path);
    return( fi.exists() && fi.isExecutable() );
}

TQString TrollProjectPart::findTQtDir()
{
    TQStringList qtdirs;
    if( !isTQt4Project() )
        qtdirs.push_back( ::getenv("QTDIR") );
    qtdirs.push_back( TQDir::rootDirPath()+"usr"+TQString( TQChar( TQDir::separator() ) )+"lib"+TQString( TQChar( TQDir::separator() ) )+"qt"+TQString("%1").arg( DomUtil::readEntry( *projectDom(), "/kdevcppsupport/qt/version", "3") ) );
    qtdirs.push_back( TQDir::rootDirPath()+"usr"+TQString( TQChar( TQDir::separator() ) )+"lib"+TQString( TQChar( TQDir::separator() ) )+"qt"+TQString( TQChar( TQDir::separator() ) )+TQString("%1").arg( DomUtil::readEntry( *projectDom(), "/kdevcppsupport/qt/version", "3") ) );
    qtdirs.push_back( TQDir::rootDirPath()+"usr"+TQString( TQChar( TQDir::separator() ) )+"share"+TQString( TQChar( TQDir::separator() ) )+"qt"+TQString("%1").arg( DomUtil::readEntry( *projectDom(), "/kdevcppsupport/qt/version", "3") ) );
    qtdirs.push_back( TQDir::rootDirPath()+"usr" );
    qtdirs.push_back( TQDir::rootDirPath()+"usr"+TQString( TQChar( TQDir::separator() ) )+"lib"+TQString( TQChar( TQDir::separator() ) )+"qt" );

    for( TQStringList::Iterator it=qtdirs.begin(); it!=qtdirs.end(); ++it )
    {
        TQString qtdir = *it;
        if( !qtdir.isEmpty() && isValidTQtDir(qtdir) )
        {
            return qtdir;
        }
    }
    return "";
}


TQStringList recursiveProFind( const TQString &currDir, const TQString &baseDir )
{
	TQStringList fileList;

	if( !currDir.contains( TQString( TQChar ( TQDir::separator() ) ) +".." )
		&& !currDir.contains( TQString( TQChar( TQDir::separator() ) )+".") )
	{
		TQDir dir(currDir);
		TQStringList dirList = dir.entryList(TQDir::Dirs );
		TQStringList::Iterator idx = dirList.begin();
		for( ; idx != dirList.end(); ++idx )
		{
			fileList += recursiveProFind( currDir + TQString( TQChar( TQDir::separator() ) ) + (*idx),baseDir );
		}
		TQStringList newFiles = dir.entryList("*.pro *.PRO");
		idx = newFiles.begin();
		for( ; idx != newFiles.end(); ++idx )
		{
			TQString file = currDir + TQString( TQChar( TQDir::separator() ) ) + (*idx);
			fileList.append( file.remove( baseDir ) );
		}
	}


	return fileList;
}

/*!
    \fn TrollProjectPart::distFiles() const
 */
TQStringList TrollProjectPart::distFiles() const
{
	TQStringList sourceList = allFiles();
	// Scan current source directory for any .pro files.
	TQString projectDir = projectDirectory();
	TQStringList files = recursiveProFind( projectDir, projectDir + TQString( TQChar( TQDir::separator() ) ) );
	return sourceList + files;
}

bool TrollProjectPart::isTQt4Project() const
{
	return ( DomUtil::readIntEntry( *projectDom(), "kdevcppsupport/qt/version", 3 ) == 4 );
}

KDirWatch* TrollProjectPart::dirWatch()
{
    return m_dirWatch;
}

void TrollProjectPart::slotBuild()
{
    m_widget->slotBuildProject();
}

#include "trollprojectpart.moc"
