/*
** Copyright (C) 1999,2000 Toivo Pedaste <toivo@ucs.uwa.edu.au>
**
*/

/*
** 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.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-devel@kde.org
*/

#include "../config.h"

#include "kpackage.h"
#include "updateLoc.h"
#include "pkgInterface.h"
#include "options.h"
#include "cache.h"

#include <tqvbox.h>
#include <tqscrollview.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kcombobox.h>

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
apanel::apanel( TQWidget *parent,
              const char * name )
   : TQWidget( parent, name )
{
  puse = 0;

  pack = new TQHBoxLayout(this);
  {
    puse = new TQCheckBox(i18n("Use"),this);
    pack->addWidget(puse,0);

    pent = new TQLineEdit(this);
    pent->setMinimumWidth(600);
    pack->addWidget(pent,0);

  }
}

apanel::~apanel()
{
}

TQString apanel::getText() const
{
  TQString s = pent->text();
  return s;
}

void apanel::setText(const TQString &s)
{
 pent->setText(s);
}

bool apanel::getUse()
{
  if (puse)
    return puse->isChecked();
  else
    return FALSE;
}

void apanel::setUse(int n)
{
  if (puse) {
    if (n)
      puse->setChecked(TRUE);
    else
      puse->setChecked(FALSE);
  }
}

void apanel::clear()
{
      puse->setChecked(FALSE);
      pent->clear();
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
dpanel::dpanel( TQWidget *parent, const char * name )
   : TQWidget( parent, name )
{
  puse = 0;
  psubdirs = 0;

  pack = new TQHBoxLayout(this);
  {
    pent = new TQLineEdit(this);
    pent->setMinimumWidth(280);
    pack->addWidget(pent,0);

    pbut = new TQPushButton("...",this);
    pack->addWidget(pbut,0);

    connect(pbut, TQT_SIGNAL(clicked()), this, TQT_SLOT(dirOpen()));

  }
}

dpanel::dpanel(dpanel *basep,  const TQString &Pfilter,  bool bsubdirs,
	       TQWidget *parent, const char * name )
   : TQWidget( parent, name )
{
  filter = Pfilter;
  puse = 0;
  psubdirs = 0;

  base = basep;

  pack = new TQHBoxLayout(this);
  {
    puse = new TQCheckBox(i18n("Use"),this);
    pack->addWidget(puse,0);

    pent = new TQLineEdit(this);
    pent->setMinimumWidth(280);
    pack->addWidget(pent,0);

    if (bsubdirs) {
      psubdirs = new TQCheckBox(i18n("Subfolders"),this);
      psubdirs->setFixedSize(psubdirs->sizeHint());
      pack->addWidget(psubdirs,0);
    }

    pbut = new TQPushButton("...",this);
    pack->addWidget(pbut,0);

    if (base)
      connect(pbut, TQT_SIGNAL(clicked()), this, TQT_SLOT(fileOpen()));
    else
      connect(pbut, TQT_SIGNAL(clicked()), this, TQT_SLOT(dirOpen()));

  }
}

dpanel::~dpanel()
{
}

TQString dpanel::getText() const
{
  TQString s = pent->text();
  return s;
}

void dpanel::setText(const TQString &s)
{
 pent->setText(s);
}

bool dpanel::getUse() const
{
  if (puse)
    return puse->isChecked();
  else
    return FALSE;
}

void dpanel::setUse(int n)
{
  if (puse) {
    if (n)
      puse->setChecked(TRUE);
    else
      puse->setChecked(FALSE);
  }
}

bool dpanel::getSubdirs() const
{
  if (psubdirs)
    return psubdirs->isChecked();
  else
    return FALSE;
}

void dpanel::setSubdirs(int n)
{
  if (psubdirs)
  {
    if (n)
      psubdirs->setChecked(TRUE);
    else
      psubdirs->setChecked(FALSE);
  }
}

void dpanel::fileOpen()
{
  TQString st;

  if (base && getText().isEmpty()) {
    st = base->getText();
  } else {
    st = getText();
  }
  if (st.right(8) == "Packages") {
    st.truncate(st.length() - 8);
  }

  KURL url =  KFileDialog::getOpenURL
    (st, filter, 0, i18n("Package File"));

  if( url.isEmpty() )
    return;

  pent->setText( url.url() );
}

void dpanel::dirOpen()
{
  TQString st;

  if (base && getText().isEmpty()) {
    st = base->getText();
  } else {
    st = getText();
  }

  KURL url  =  KFileDialog::getExistingURL
    (st, 0, i18n("Package Archive"));


  if( url.isEmpty() )
    return;

  pent->setText( url.url() );

}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
updateLoc::updateLoc(TQWidget *p, int panelNumber, pkgInterface *inter, const TQString &iname)
    : TQWidget(p,"updateLoc",FALSE)
{
  interName = iname;
  interface = inter;
  panNumber = panelNumber;

  vf = new TQVBoxLayout( this, 15, 10, "vf");
}

updateLoc::~updateLoc()
{
}

void updateLoc::doBase(const TQString & bmsg)
{
  base = 0;
  if (haveBase) {
    fbase = new TQGroupBox(bmsg, this);
    fbase->setColumnLayout(0, Qt::Vertical );
    fbase->layout()->setSpacing( KDialog::spacingHint() );
    fbase->layout()->setMargin( KDialog::marginHint() );
    vbase = new TQVBoxLayout(fbase->layout());
    vf->addWidget(fbase,1);
    base = new dpanel(fbase);
    vbase->addWidget(base,0);
    vbase->activate();
  }
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

aUpdateLoc::aUpdateLoc(TQWidget *p, int panelNumber, pkgInterface *inter, const TQString &iname,
			 int numberLines, const TQString &label)
  : updateLoc(p, panelNumber, inter, iname)
{

  if (numberLines > PNUM)
    numLines = PNUM;
  else
    numLines = numberLines;

  ap[0] = 0;

  TQGroupBox *floc = new TQGroupBox(1,Qt::Vertical, label, this);
  vf->addWidget(floc,1);
  TQScrollView* sv = new TQScrollView(floc);
    sv->setHScrollBarMode(TQScrollView::AlwaysOff);
    sv->setResizePolicy(TQScrollView::AutoOneFit);

      TQFrame *f = new TQFrame(sv->viewport());
    sv->addChild(f);

  TQVBoxLayout *vloc = new TQVBoxLayout(f, 0, 3, "vloc");

  for (int i = 0; i < numLines; i++) {
    ap[i] = new apanel( f);
    vloc->addWidget(ap[i],0);
  }

}


aUpdateLoc::~aUpdateLoc()
{
}

void aUpdateLoc::readSettings()
{
  int i = 0;
  TQString a,b;

  for (int i = 0; i < numLines; i++) {
    ap[i]->clear();
  }

  TQStringList list = interface->readApt();
  for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
    if (!(*it).isEmpty()) {
      if ((*it).left(1) == "#") {
	ap[i]->setText(((*it).mid(1)).stripWhiteSpace());
	ap[i]->setUse(0);
      } else {
	ap[i]->setText((*it));
	ap[i]->setUse(1);
      }
      i++;
      if (i >= numLines) {
	ap[numLines - 1]->setText(i18n("File truncated..."));
	break;
      }
    }
  }
}

void aUpdateLoc::writeSettings() {
  TQStringList list;
  TQString s;

  TQString ln;
  for (int i = 0; i < numLines; i++) {
    if (!ap[i])
      break;

    ln = ap[i]->getText();
    if (!ln.isEmpty()) {
      if (ap[i]->getUse()) {
	s = "";
      } else {
	s = "# ";
      }
      s += ln;
      list.append(s);
    }
  }
  interface->writeApt(list);
}

void aUpdateLoc::applyS(LcacheObj *) {
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

pdUpdateLoc::pdUpdateLoc(TQWidget *p, int panelNumber, pkgInterface *inter, const TQString &iname,
			 int numberLines, const TQString &filter,
			 const TQString &lmsg, TQString bmsg,
			 bool subdirs )
  : updateLoc(p, panelNumber, inter, iname)
{

  if (numberLines > PNUM)
    numLines = PNUM;
  else
    numLines = numberLines;

  haveBase = !bmsg.isNull();

  dp[0] = 0;

  TQString pn;
  pn.setNum(panNumber);
  pn += "_";

  packL = "Package_L_";
  packL += pn;
  packU = "Package_U_";
  packU += pn;
  packS = "Package_S_";
  packS += pn;
  availB = "Available_Base";
  availB += pn;

  doBase(bmsg);

  TQGroupBox *floc = new TQGroupBox(lmsg, this);
  floc->setColumnLayout(0, Qt::Vertical );
  floc->layout()->setSpacing( KDialog::spacingHint() );
  floc->layout()->setMargin( KDialog::marginHint() );
  vf->addWidget(floc,1);
  TQVBoxLayout *vloc = new TQVBoxLayout(floc->layout());

  for (int i = 0; i < numLines; i++) {
    dp[i] = new dpanel(base, filter,  subdirs, floc);
    vloc->addWidget(dp[i],0);
  }

  readSettings();
}


pdUpdateLoc::~pdUpdateLoc()
{
}

void pdUpdateLoc::applyS(LcacheObj *slist)
{
  TQString t,pn,cn,pv,prev,opts;
  cacheObj *CObj;
  TDEConfig *config = kapp->config();
  config->setGroup(interName);

  cn = interface->head;
  cn += "_";
  cn += pn.setNum(panNumber);
  cn += "_";


  for (int i = 0; i < numLines; i++) {
    // delete chached dir if text changed
    pv = packL + pn.setNum(i);
    prev = config->readEntry(pv);
    if (prev != dp[i]->getText())
      cacheObj::rmDCache(TQString(cn + pn.setNum(i)));

    // create cache object corresponding to this entry
    if (dp[i]->getUse()) {
      t = dp[i]->getText();
      if (!t.isEmpty()) {
	CObj = new cacheObj(haveBase ? base->getText() : TQString(),
			    t, cn + pn.setNum(i), "", dp[i]->getSubdirs());
	slist->append(CObj);
	//	printf("T=%s\n",t.data());
      }
    }
  }
  //  writeSettings();
}

void pdUpdateLoc::readSettings()
{
  TQString pv, pn;

  TDEConfig *config = kapp->config();

  config->setGroup(interName);

  if (haveBase)
    base->setText(config->readEntry(availB));

  for (int i = 0; i < numLines; i++) {
    if (!dp[i])
      break;
    pv = packL + pn.setNum(i);
    dp[i]->setText(config->readEntry(pv));
    pv = packU + pn.setNum(i);
    dp[i]->setUse(config->readNumEntry(pv));
    pv = packS + pn.setNum(i);
    dp[i]->setSubdirs(config->readNumEntry(pv));
  }
}

void pdUpdateLoc::writeSettings()
{
  TQString pv, pn;

  TDEConfig *config = kapp->config();

  config->setGroup(interName);
  if (haveBase) {
    if (!base->getText().isEmpty())
      config->writeEntry(availB,base->getText());
  }

  for (int i = 0; i < numLines; i++) {
    if (!dp[i])
      break;
    pv = packL + pn.setNum(i);
    config->writeEntry(pv,dp[i]->getText());
    pv = packU + pn.setNum(i);
    config->writeEntry(pv,(int)dp[i]->getUse());
    pv = packS + pn.setNum(i);
    config->writeEntry(pv,(int)dp[i]->getSubdirs());
  }

}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
cUpdateLoc::cUpdateLoc(TQWidget *p, int panelNumber, pkgInterface *inter, const TQString &iname,
		       int numberLines, const TQString &baseMsg,
		       const TQString &boxLabels, const TQString &boxValues)
  : updateLoc(p, panelNumber, inter, iname)
{
  if (numberLines > PNUM)
    numLines = PNUM;
  else
    numLines = numberLines;

  haveBase = !baseMsg.isNull();

  combo[0] = 0;

  TQString pn;
  pn.setNum(panNumber);
  pn += "_";

  packC = "Package_C_";
  packC += pn;
  availB = "Available_Base";
  availB += pn;

  TQStringList kc = TQStringList::split('\n', boxLabels);
  TQStringList::Iterator kcIt = kc.begin();

  TQStringList oc = TQStringList::split('\n', boxValues);
  TQStringList::Iterator ocIt = oc.begin();


  doBase(baseMsg);

  for (int i = 0; i < numLines; i++) {
    TQGroupBox *floc = new TQGroupBox(*kcIt, this);
    floc->setColumnLayout(0, Qt::Vertical );
    floc->layout()->setSpacing( KDialog::spacingHint() );
    floc->layout()->setMargin( KDialog::marginHint() );
    vf->addWidget(floc,1);
    TQVBoxLayout *vloc = new TQVBoxLayout(floc->layout());

    combo[i] = new KComboBox( true, floc);
    TDECompletion *comp = combo[i]->completionObject();
    connect(combo[i],TQT_SIGNAL(returnPressed(const TQString&))
	    ,comp,TQT_SLOT(addItem(const TQString&)));
    combo[i]->insertStringList(TQStringList::split(' ',*ocIt));
    vloc->addWidget(combo[i]);
    if (kcIt != kc.end()) {
      ++kcIt;
    }
    if (ocIt != oc.end()) {
      ++ocIt;
    }
  }

  readSettings();
}

cUpdateLoc::~cUpdateLoc()
{
}

 void cUpdateLoc::applyS(LcacheObj *slist)
{
  TQString t,pn,cn,pv,prev,opts;
  cacheObj *CObj;
  TDEConfig *config = kapp->config();
  config->setGroup(interName);

  cn = interface->head;
  cn += "_";
  cn += pn.setNum(panNumber);
  cn += "_";

    if (!base->getText().isEmpty()) {
      for (int i = 0; i < numLines; i++) {
	opts +=  combo[i]->currentText();
	opts += "\n";
      }
      CObj = new cacheObj(base->getText(),
			  "", cn + ":", opts);
      slist->append(CObj);
    }
    //  writeSettings();
}

void cUpdateLoc::readSettings()
{
  TQString pv, pn;

  TDEConfig *config = kapp->config();

  config->setGroup(interName);

  if (haveBase)
    base->setText(config->readEntry(availB));

  for (int i = 0; i < numLines; i++) {
    if (!combo[i])
      break;
    pv = packC + pn.setNum(i);
    if (!config->readEntry(pv).isEmpty()) {
      combo[i]->insertItem(config->readEntry(pv), 0);
    }
  }

}

void cUpdateLoc::writeSettings()
{
  TQString pv, pn;

  TDEConfig *config = kapp->config();

  config->setGroup(interName);

  if (haveBase) {
      config->writeEntry(availB,base->getText());
  }

  for (int i = 0; i < numLines; i++) {
    if (!combo[i])
      break;
    pv = packC + pn.setNum(i);
    config->writeEntry(pv,combo[i]->currentText());
  }

}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
Locations::Locations(const TQString &msg)
    : KDialogBase(Tabbed, msg, Ok | Cancel, Ok, 0, "Locations", false)
{
  numPanels = 0;

  connect( this, TQT_SIGNAL(okClicked()), TQT_SLOT(write_slot()) );
}

void Locations::dLocations(int numberDirs,  int numberLines,
		     pkgInterface *inter, const TQString &iname,
		     const TQString &label, const TQString &filter, const TQString &dirMsg,
		     bool subdirs)
{
  TQString nm;

  for (int i = numPanels ; (i <  numPanels + numberDirs) && (i < PANNUM); i++) {

    TQString mp = iname;
    nm.setNum(i+1);
    mp += nm;
    TQVBox *page = addVBoxPage(mp);
    pn[i] = new pdUpdateLoc(page, i, inter,
			    label, numberLines,
			    filter, dirMsg, NULL, subdirs);
  }
  numPanels += numberDirs;
}

void Locations::pLocations(int numberDirs,  int numberLines,
		     pkgInterface *inter, const TQString &iname, const TQString &label,
		     const TQString &filter,
		     const TQString &packMsg, TQString baseMsg, bool subdirs)
{
  TQString nm;

  for (int i = numPanels; (i < numPanels + numberDirs) && (i < PANNUM); i++) {
    TQString mp = iname;
    nm.setNum(i+1);
    mp += nm;
    TQVBox *page = addVBoxPage(mp);
    pn[i] = new pdUpdateLoc(page, i, inter, label,
			    numberLines,
			    filter, packMsg, baseMsg, subdirs);
  }
  numPanels += numberDirs;
}

void Locations::cLocations(int numberDirs,   int numberLines,
		     pkgInterface *inter, const TQString &iname, const TQString &label,
		     const TQString &boxLables, const TQString &baseMsg, const TQString &boxValues)
{
  TQString nm;

  for (int i = numPanels; (i < numPanels + numberDirs) && (i < PANNUM); i++) {
    TQString mp = iname;
    nm.setNum(i+1);
    mp += nm;
    TQVBox *page = addVBoxPage(mp);
    pn[i] = new cUpdateLoc(page, i, inter, label,
			   numberLines, baseMsg,
			   boxLables, boxValues);
  }
  numPanels += numberDirs;
}

void Locations::aLocations(int numberDirs,   int numberLines,
		     pkgInterface *inter, const TQString &iname, const TQString &label)
{
  TQString nm;

  for (int i = numPanels; (i < numPanels + numberDirs) && (i < PANNUM); i++) {
    TQString mp = iname;
    nm.setNum(i+1);
    mp += nm;
    TQVBox *page = addVBoxPage(mp);
    pn[i] = new aUpdateLoc(page, i, inter, iname,
			   numberLines, label);
  }
  numPanels += numberDirs;
}

Locations::~Locations() {
  //  for (int i = 0; (i < numPanels) && (i < PANNUM) && pn[i]; i++) {
  //    delete pn[i];
  //  }
}

void Locations::restore()
{
  for (int i = 0; (i <  numPanels) && (i < PANNUM); i++) {
    pn[i]->readSettings();
  }
  show();
}

void Locations::apply_slot()
{
   LcacheObj *slist = new LcacheObj();

  for (int i = 0; (i <  numPanels) && (i < PANNUM); i++) {
    pn[i]->applyS(slist);
  }
  emit returnVal(slist);
}

void Locations::write_slot()
{
  apply_slot();

  for (int i = 0; (i <  numPanels) && (i < PANNUM); i++) {
    pn[i]->writeSettings();
  }
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#include "updateLoc.moc"
