/***************************************************************************
                          ProjectEditorWid.cpp  -  description
                             -------------------
    begin                : lun déc 8 2003
    copyright            : (C) 2003 by Alain Gibaud
    email                : alain.gibaud@univ-valenciennes.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "ProjectEditorWid.h"
#include "AsmConfigWidget.h"
#include "PikMain.h"
#include <klocale.h>
#include <kiconloader.h>
#include <kfiledialog.h>
#include <kapplication.h>

#include <qlayout.h>
#include <qgrid.h>
#include <qvbox.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qtextedit.h>
#include <qgroupbox.h>
#include <qtooltip.h>
#include <qcheckbox.h>
#include <qpushbutton.h>

#include <iostream>
using namespace std ;

ProjectEditorWid::ProjectEditorWid(Project *proj, QWidget *parent, const char *wname )
        : QMainWindow(parent,wname, Qt::WDestructiveClose), project(proj)
{
    KIconLoader loader ;
    QIconSet iconset = loader.loadIcon("fileopen", KIcon::Toolbar) ;

    main_widget = dynamic_cast<PikMain *>(KApplication::kApplication()->mainWidget()) ;

    QStringList procs =  main_widget->getProcList() ;
    QStringList hfmt ;
    (((hfmt += "inhx8m") += "inhx8s") += "inhx16") += "inhx32" ;
    QStringList rad ;
    (rad += "dec") += "hex" ;
    QStringList warn ;
    ((warn +="0") += "1") += "2" ;

    setCaption(i18n("Project editor")) ;

    QVBox *vb = new QVBox(this) ;
    vb->setSpacing(8) ;
    vb->setFrameStyle( QFrame::Panel | QFrame::Sunken );
    vb->setLineWidth( 2 );
    vb->setMargin(8) ;
    setCentralWidget(vb) ;


    QGrid *group = new QGrid(4,vb) ;
    group->setSpacing(10) ;


    new QLabel(i18n("Project"), group);
    QLineEdit *name = new QLineEdit(group);
    name->setText(project->projectName( ) ) ;
    name->setReadOnly(true) ;
    new QLabel(i18n("Type"), group);
    QLineEdit *typname = new QLineEdit(group);
    typname->setMaximumWidth(55) ;
    typname->setReadOnly(true) ;
    typname->setText(project->getType( ) ) ;


    new QLabel(i18n("Directory"), group);
    QLineEdit *dir = new QLineEdit(group);
    dir->setText(proj->projectPath( ) ) ;
    dir->setReadOnly(true) ;
    //QGridLayout *gl =  dynamic_cast<QGridLayout *>(group->layout()) ;
    // if(gl)
    //  gl->addMultiCellWidget(dir, 1,1  ,1,3) ;


    QGrid *grid4x4 =  new QGrid(2,vb) ;
    grid4x4->setSpacing(8) ;

    // -------------------------- global section ----------------------
    QGroupBox *globalbox = new QGroupBox(2,Horizontal,i18n("Global"),grid4x4) ;
    new QLabel(i18n("Description"), globalbox) ;
    glob_description=new QTextEdit(globalbox) ;
    glob_description->setText(project->getDescription()) ;
    new QLabel(i18n("Version"), globalbox) ;
    glob_version = new QLineEdit(globalbox) ;
    glob_version->setText(project->getVersion()) ;


    // -------------------------- asm params  section ----------------------
    QGroupBox *asmbox = new QGroupBox(2,Horizontal,i18n("Assembler"),grid4x4 ) ;
    //   Processor
    new QLabel(i18n("Processor"), asmbox) ;
    asm_device = new QComboBox(asmbox) ;
    asm_device->insertStringList(procs);
    int k ;
    QString p=project->getDevice() ;
    if( ((k=procs.findIndex(p)) == -1) && (k=procs.findIndex(p+" (P)")) == -1)
        k = 0 ;
    asm_device->setCurrentItem(k) ;
    QToolTip::add
        (asm_device,i18n("PiKdev can only program processors marked with (P).\n"
                         "For the development of new programming drivers, please see\n"
                         "http://pikdev.free.fr, or contact the author.")) ;


    //   radix
    new QLabel(i18n("Radix"),asmbox) ;
    asm_radix = new QComboBox(asmbox) ;
    QToolTip::add
        (asm_radix,i18n("Choose the default radix used by gpasm to parse integer constants\n"
                        "* means that radix is specified by LIST directive."));
    asm_radix->insertItem("*") ;
    asm_radix->insertStringList(rad);
    QString r = project->getRadix() ;
    k=rad.findIndex(r) ;
    asm_radix->setCurrentItem(k+1) ;


    //  Warning level
    new QLabel(i18n("Warning level"),asmbox) ;
    asm_warning = new QComboBox(asmbox) ;
    asm_warning->insertItem("*") ;
    asm_warning->insertStringList(warn);
    QString w=project->getWarnLevel() ;
    k=warn.findIndex(w) ;
    asm_warning->setCurrentItem(k+1) ;
    QToolTip::add
        (asm_warning,i18n("For cleaner code, please choose '0'.\n"
                          "* means that warning level is specified by LIST directive.")) ;

    // list option
    new QLabel(i18n("List file"),asmbox) ;
    asm_list = new QCheckBox(asmbox) ;
    asm_list->setChecked(project->getAsmList()) ;


    //  Include Directories
    new QLabel(i18n("Include directory"),asmbox) ;
    QHBox *h1 = new QHBox(asmbox) ;
    asm_include = new QLineEdit(h1) ;
    QString i=project->getIncludeDir() ;
    asm_include->setText(i) ;
    QToolTip::add
        (asm_include,i18n("By using the pseudovariable $(PRJPATH), you can specify an include directory\n"
                          "relative to the project directory."	)) ;
    QPushButton *incdir_button = new  QPushButton(iconset,"", h1) ;
    connect(incdir_button,SIGNAL(clicked()), this, SLOT( slotSelectIncDir())) ;


    //  other option
    new QLabel(i18n("Other options"),asmbox) ;
    asm_other = new QLineEdit(asmbox) ;
    QString o=project->getOtherOptions() ;
    asm_other->setText(o) ;
    QToolTip::add
        (asm_other,i18n("This item allows you to manually specify a gpasm \"exotic\" option.\n"
                        "The $(PRJPATH) pseudo variable if supported in this item as it is "
                        "in the \"Include Directories\" one.")) ;

    // ------------------------------- C section -----------------
    QGroupBox *Cbox = new QGroupBox(2,Horizontal,i18n("C compiler"),grid4x4) ;
    new QLabel(i18n("Compiler"),Cbox) ;
    C_compiler = new QComboBox(false,Cbox) ;
    C_compiler->insertItem("cpik") ;

    // find correct entry and display it
    QString the_compiler(project->getCCompiler()) ;
    for(k=0 ; k < C_compiler->count() ; ++k)
        if( C_compiler->text(k) == the_compiler )
            break ;
    if(k == C_compiler->count() )
        k = 0 ; // not found , take first entry
    C_compiler->setCurrentItem(k) ;
    QToolTip::add
        (C_compiler,i18n("Sorry, PiKdev currently supports only one compiler.")) ;

    //  Include Directories
    new QLabel(i18n("Include directory"),Cbox) ;
    QHBox *Ch1 = new QHBox(Cbox) ;
    C_include = new QLineEdit(Ch1) ;
    C_include->setText(project->getCIncludeDir()) ;
    QToolTip::add
        (C_include,i18n("By using the pseudovariable $(PRJPATH), you can specify a directory\n"
                        "relative to the project directory."	)) ;
    QPushButton *Cincdir_button = new  QPushButton(iconset,"", Ch1,"C include button") ;
    connect(Cincdir_button,SIGNAL(clicked()), this, SLOT( slotSelectCIncDir())) ;

    // display slb files option
    new QLabel(i18n("Slb files"),Cbox) ;
    C_slb = new QCheckBox(Cbox) ;
    C_slb->setChecked(project->getCSlb()) ;

    //  Libs Directories
    new QLabel(i18n("Libs directory"),Cbox) ;
    QHBox *Ch2 = new QHBox(Cbox) ;
    C_libs = new QLineEdit(Ch2) ;
    C_libs->setText(project->getCLibsDir()) ;
    QToolTip::add
        (C_libs,i18n("By using the pseudovariable $(PRJPATH), you can specify a directory\n"
                     "relative to the project directory."	)) ;
    QPushButton *Clibs_button = new  QPushButton(iconset,"", Ch2,"C libs button") ;
    connect(Clibs_button,SIGNAL(clicked()), this, SLOT( slotSelectCLibDir())) ;

    // display asm files option
    new QLabel(i18n("Asm file"),Cbox) ;
    C_asm = new QCheckBox(Cbox) ;
    C_asm->setChecked(project->getCAsm()) ;

    // other options
    new QLabel(i18n("Other options"),Cbox) ;
    C_other = new QLineEdit(Cbox) ;
    C_other->setText(project->getOtherCOptions()) ;
    QToolTip::add
        (C_other,i18n("This item allows you to manually specify a C \"exotic\" option.\n"
                      "The $(PRJPATH) pseudo variable if supported in this item as it is "
                      "in the \"Libraries Directory\" one.")) ;


    // ------------------------------- linker section -----------------
    QGroupBox *linkbox = new QGroupBox(2,Horizontal,i18n("Linker"),grid4x4) ;
    // hex file format
    new QLabel(i18n("Hex file format"),linkbox) ;
    link_fformat = new QComboBox(linkbox) ;
    link_fformat->insertStringList(hfmt);
    QString h=project->getHexFormat() ;
    if( (k=hfmt.findIndex(h)) == -1)
        k = 0 ;
    ;
    link_fformat->setCurrentItem(k) ;
    QToolTip::add
        (link_fformat,i18n("CAUTION: inhx8s format is currently not supported by the PiKdev programmer.\n"
                           "If you need this support, please contact the author." )) ;

    // debug option
    new QLabel(i18n("Debug messages"),linkbox) ;
    link_debug = new QCheckBox(linkbox) ;
    link_debug->setChecked(project->getLinkDebug()) ;

    // map option
    new QLabel(i18n("Map file"),linkbox) ;
    link_map = new QCheckBox(linkbox) ;
    link_map->setChecked(project->getLinkMap()) ;

    //  object/libs Directories
    new QLabel(i18n("Libraries directory"),linkbox) ;
    QHBox *hb2 = new QHBox(linkbox) ;
    link_include = new QLineEdit(hb2) ;
    link_include->setText(project->getLibsDir()) ;
    QToolTip::add
        (link_include,i18n("By using the pseudovariable $(PRJPATH), you can specify a directory\n"
                           "relative to the project directory:" )) ;
    QPushButton *libdir_button = new  QPushButton(iconset,"", hb2) ;
    connect(libdir_button,SIGNAL(clicked()), this, SLOT( slotSelectLibDir())) ;

    // other options
    new QLabel(i18n("Other options"),linkbox) ;
    link_other = new QLineEdit(linkbox) ;
    link_other->setText(project->getOtherLinkOptions()) ;
    QToolTip::add
        (link_other,i18n("This item allows you to manually specify a gplink \"exotic\" option.\n"
                         "The $(PRJPATH) pseudo variable if supported in this item as it is "
                         "in the \"Libraries Directory\" one.")) ;

    // ------------------------- Buttons section ----------------------------

    QHBox *hbox7 = new QHBox(vb) ;
    hbox7->setSpacing(20) ;

    QHBox *space = new QHBox(hbox7) ;
    QPushButton *bok = new QPushButton(i18n("Ok"),hbox7) ;
    QPushButton *bapply = new QPushButton(i18n("Apply"),hbox7) ;
    QPushButton *bcancel = new QPushButton(i18n("Cancel"),hbox7) ;
    hbox7->setStretchFactor(space,1) ;
    hbox7->setStretchFactor(bcancel,0) ;
    hbox7->setStretchFactor(bapply,0) ;
    hbox7->setStretchFactor(bok,0) ;

    // Connect buttons
    connect(bcancel, SIGNAL(clicked()), this, SLOT(slotCancel())) ;
    connect(bapply, SIGNAL(clicked()), this, SLOT(slotApply())) ;
    connect(bok, SIGNAL(clicked()), this, SLOT(slotOk())) ;


    // disable link or C box, depending on type of project.
    if( project->isCproject())
        linkbox->setEnabled(false) ;
    else
        Cbox->setEnabled(false) ;


    show() ;
}
ProjectEditorWid::~ProjectEditorWid()
{}
/** No descriptions */
void ProjectEditorWid::slotCancel()
{
    close(true) ;
}
/** No descriptions */
void ProjectEditorWid::slotApply()
{
    project->setDescription(glob_description->text()) ;
    project->setVersion(glob_version->text()) ;

    QString dev =  asm_device->currentText()   ;
    // remove the (P) suffix if it exists
    if( dev.right(4) == " (P)")
        dev.remove(dev.length()-4, 4 ) ;
    project->setDevice(dev) ;
    project->setWarnLevel(asm_warning->currentText()) ;
    project->setOtherOptions(asm_other->text()) ;
    project->setIncludeDir(asm_include->text()) ;
    project->setRadix(asm_radix->currentText()) ;
    project->setAsmList(asm_list->isOn()) ;

    project->setHexFormat(link_fformat->currentText()) ;
    project->setLinkDebug(link_debug->isOn()) ;
    project->setLinkMap(link_map->isOn()) ;
    project->setLibsDir(link_include->text()) ;
    project->setOtherLinkOptions(link_other->text()) ;

    project->setCLibsDir(C_libs->text()) ;
    project->setOtherCOptions(C_other->text()) ;
    project->setCIncludeDir(C_include->text()) ;
    project->setCCompiler(C_compiler->currentText()) ;
    project->setCSlb(C_slb->isOn()) ;
    project->setCAsm(C_asm ->isOn()) ;


    project->commit() ;
}
/** No descriptions */
void ProjectEditorWid::slotOk()
{
    slotApply();
    slotCancel() ;
}
/** No descriptions */
void ProjectEditorWid::slotSelectIncDir()
{
    QString dir(KFileDialog::getExistingDirectory(QString::null,0,
                i18n("Select include directory") )) ;
    if( !dir.isEmpty())
    {
        asm_include->setText(dir) ;
    }
}
/** No descriptions */
void ProjectEditorWid::slotSelectLibDir()
{
    QString dir(KFileDialog::getExistingDirectory(QString::null,0,
                i18n("Select libraries directory") )) ;
    if( !dir.isEmpty())
    {
        link_include->setText(dir) ;
    }
}
/** No descriptions */
void ProjectEditorWid::slotSelectCIncDir()
{
    QString dir(KFileDialog::getExistingDirectory(QString::null,0,
                i18n("Select include directory") )) ;
    if( !dir.isEmpty())
    {
        C_include->setText(dir) ;
    }

}
/** No descriptions */
void ProjectEditorWid::slotSelectCLibDir()
{
    QString dir(KFileDialog::getExistingDirectory(QString::null,0,
                i18n("Select libraries directory") )) ;
    if( !dir.isEmpty())
    {
        C_include->setText(dir) ;
    }

}
