/***************************************************************************
                          kbconfigdlg.cpp  -  description
                             -------------------
    begin                : Sun Jul 8 2001
    copyright            : (C) 2001 by Leonid Zeitlin
    email                : lz@europe.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "kbconfigdlg.h"
#include "kbpickicondlg.h"
#include "boldlistboxitem.h"

#include <tqlayout.h>
#include <tqlabel.h>
#include <tqcheckbox.h>
#include <tqwhatsthis.h>
#include <tqvbox.h>
#include <tqstyle.h>
#include <tqgroupbox.h>
#include <tqheader.h>
#include <tqobjectlist.h>
#include <tqpushbutton.h>
#include <tqcombobox.h>

#include <tdeversion.h>
#include <tdelistbox.h>
#include <tdelocale.h>
#include <kdebug.h>
#include <tdeapplication.h>
#include <tdelistview.h>
#include <kkeydialog.h>
#include <tdeconfig.h>

/* This little subclass of KKeyChooser reimplements sizeHint() to
   look a little smaller in our config dialog. The default size
   is way too large IMHO and makes General page look oversized
 */
class SmallerKeyChooser : public KKeyChooser {
private:
  TQSize m_size_hint;
  void calcSizeHint();
public:
  SmallerKeyChooser(TDEGlobalAccel *accel, TQWidget *parent) :
    KKeyChooser(accel, parent) { calcSizeHint(); }
  virtual TQSize sizeHint() const { return m_size_hint; }
};

void SmallerKeyChooser::calcSizeHint()
{
	m_size_hint = KKeyChooser::sizeHint();

  TDEListView *lv = NULL;
  TQGroupBox *gb = NULL;
  const TQObjectList *objects = children();
  TQObjectListIt iter(*objects);
  TQObject *obj;

  while ( (obj = iter.current()) ) {
		++iter;
		if (obj->inherits("TDEListView"))
		  lv = dynamic_cast<TDEListView*>(obj);
		else if (obj->inherits("TQGroupBox"))
		  gb = dynamic_cast<TQGroupBox*>(obj);  
	}
	if (!lv || !gb) return; // oops, should not happen
	
	TQListViewItem *item = lv->firstChild();
	if (!item) return; 

	int height = item->height() * (1 + item->childCount()) + lv->header()->height() +
	  style().pixelMetric(TQStyle::PM_ScrollBarExtent) + gb->sizeHint().height() +
	  layout()->spacing() * 2;
	int width = lv->columnWidth(0) + lv->columnWidth(1);
	m_size_hint = TQSize(width, height);
}	

static inline bool iconTypeShowsFlag(KBConfig::IconStyle icon_style)
{
	return icon_style == KBConfig::ICON_FLAG || icon_style == KBConfig::ICON_CODE_AND_FLAG;
}

KBConfigDlg::KBConfigDlg(KBConfig *kbconf, TQWidget *parent, const char *name )
  : KDialogBase(Tabbed, i18n("Configure")/*caption*/, Ok | Apply | Cancel | Help,
      Ok, parent, name, true /*modal*/)
{
  m_kbconf = kbconf;
  m_default_groupno = m_kbconf->default_groupno();

  setHelp(TQString("configure-kkbswitch"));
  setButtonBoxOrientation(Horizontal);
  setupGeneralPage();
  setupShortcutsPage();

  showConfig();
  slotIconTypeSelected(m_kbconf->icon_style());
}

KBConfigDlg::~KBConfigDlg(){
}

void KBConfigDlg::setupGeneralPage()
{
  TQFrame *page = addPage(i18n("&General")); //makeMainWidget();
  TQVBoxLayout *vlayout = new TQVBoxLayout(page);
  vlayout->setSpacing(2);

  TQLabel *lbl = new TQLabel(i18n("Available &keyboard layouts:"), page);
  vlayout->addWidget(lbl);

  TQHBoxLayout *groupsLayout = new TQHBoxLayout(vlayout);
  groupsLayout->setSpacing(2);

  lbGroups = new TDEListBox(page);
  TQObject::connect(lbGroups, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(slotLayoutSelected()));
  TQObject::connect(lbGroups, TQ_SIGNAL(doubleClicked(TQListBoxItem *)), this,
    TQ_SLOT(slotListBoxExecuted(TQListBoxItem *)));
  groupsLayout->addWidget(lbGroups);
  lbl->setBuddy(lbGroups);
  TQWhatsThis::add(lbGroups, i18n("This list box shows keyboard layouts available in your system.\n"
    "Select a layout and click \"Change Icon...\" button to change the icon for a layout.\n"
    "If you have configured a non-default icon, you can reset the icon to default with \"Use Default Icon\" button.\n"
    "The layout shown is bold is the default layout. Use \"Set as default\" button "
    "to set the default layout."));

  TQVBoxLayout *btnLayout = new TQVBoxLayout(groupsLayout);
  btnLayout->setSpacing(2);

  btnChangeIcon = new TQPushButton(i18n("Cha&nge Icon..."), page);
  TQObject::connect(btnChangeIcon, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotPickIcon()));
  btnLayout->addWidget(btnChangeIcon, 0, TQt::AlignTop);
  TQWhatsThis::add(btnChangeIcon, i18n("Click this button to change the icon for the "
    "layout selected in the list box to the left."));

  btnSetDefaultIcon = new TQPushButton(i18n("Use &Default Icon"), page);
  TQObject::connect(btnSetDefaultIcon, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotSetDefaultIcon()));
  btnLayout->addWidget(btnSetDefaultIcon, 0, TQt::AlignTop); 
  TQWhatsThis::add(btnSetDefaultIcon, i18n("Click this button to use default icon for the " 
    "layout selected in the list box to the left."));
    
  btnSetDefaultGroup = new TQPushButton(i18n("&Set as Default"), page);
  TQObject::connect(btnSetDefaultGroup, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotSetDefaultGroup()));
  btnLayout->addWidget(btnSetDefaultGroup, 0, TQt::AlignTop);
  TQWhatsThis::add(btnSetDefaultGroup, i18n("Click this button to set the layout selected "
    "in the list box to the left as the default"));

  btnLayout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Minimum,
    TQSizePolicy::MinimumExpanding));

  lbl = new TQLabel(i18n("Layout &icon style:"), page);
  vlayout->addWidget(lbl);

  cbxIconType = new TQComboBox(page);
  cbxIconType->setEditable(false);
  cbxIconType->insertItem(i18n("Country flag"));
  cbxIconType->insertItem(i18n("Language code"));
  cbxIconType->insertItem(i18n("Flag and code"));
  TQObject::connect(cbxIconType, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotIconTypeSelected(int)));
  vlayout->addWidget(cbxIconType);
  lbl->setBuddy(cbxIconType);
  TQWhatsThis::add(cbxIconType, i18n("<p>Select the style of icons representing the "
    "current keyboard layout.\n"
    "You can choose from the following styles:"
    "<ul><li><b>Country flag</b> - displays the corresponding country flag"
    "<li><b>Language code</b> - displays the language ISO 2-letter code"
    "<li><b>Flag and code</b> - displays the language code superimposed over the country flag."
    "</ul></p>"));

  lbl = new TQLabel(i18n("&Layout applies to:"), page);
  vlayout->addWidget(lbl);
  
  cbxGroupScope = new TQComboBox(page);
  cbxGroupScope->setEditable(false);
  cbxGroupScope->insertItem(i18n("All windows"));
  cbxGroupScope->insertItem(i18n("Windows of one application"));
  cbxGroupScope->insertItem(i18n("One window"));
  vlayout->addWidget(cbxGroupScope);
  lbl->setBuddy(cbxGroupScope);
   TQWhatsThis::add(cbxGroupScope, i18n("<p>Select what windows the currently selected "
     "keyboard layout applies to:\n"
     "<ul><li><b>All windows</b> - one layout applies to all windows on your desktop\n"
     "<li><b>Windows of one application</b> - layout applies to one application; each " 
       "application can have its own layout. When you switch between applications, layout follows the active application\n"
     "<li><b>One window</b> - layout applies to one window only; each window can have its own layout. "
     "When you switch between windows, layout follows the active window.</ul></p>"));
  
  chkToggleMode = new TQCheckBox(i18n("Use \"&Toggle Mode\""), page);
  vlayout->addWidget(chkToggleMode);
  TQWhatsThis::add(chkToggleMode, i18n("Toggle mode is useful when you have more than two keyboard "
    "layouts defined. When toggle mode is on your normal layout switch key toggles between two most frequently used layouts. "
    "To activate other layouts use KKBSwitch's tray popup menu"));

  /*chkPerwindowGroup = new TQCheckBox(i18n("Use &per-window layout"), page);
  vlayout->addWidget(chkPerwindowGroup);
  TQWhatsThis::add(chkPerwindowGroup, i18n("When this checkbox is checked, "
    "each window has its own current keyboard layout. When it's unchecked, "
    "the current layout affects all windows"));*/

  chkAutostart = new TQCheckBox(i18n("A&utostart"), page);
  vlayout->addWidget(chkAutostart);
  TQWhatsThis::add(chkAutostart, i18n("When this checkbox is checked, KKBSwitch "
    "will start automatically when you log in"));
}
	
void KBConfigDlg::setupShortcutsPage()
{
  TQVBox *box = addVBoxPage(i18n("Sho&rtcuts"));
  chkUseShortcuts = new TQCheckBox(i18n("Use shortcuts to &activate keyboard layouts"), box);
  connect(chkUseShortcuts, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotUseShortcutsToggled(bool)));
  TQWhatsThis::add(chkUseShortcuts, i18n("Check this checkbox to be able to quickly "
    "activate any keyboard layout with keyboard shorcuts. Once this checkbox "
    "is checked, you can adjust the shortcuts at the key chooser pane below. "
    "Especially useful if you have three or four keyboard layouts configured"));
    
  keyChooser = new SmallerKeyChooser(m_kbconf->keys(), box);
}

/** Display the current KBSwitch configuration in the dialog */
void KBConfigDlg::showConfig(){
  int i;
  KBGroup *group;
  TDEConfig *conf = kapp->config();

  m_iconpaths.clear();
  conf->setGroup(ICONS_SECTION);
  for (i = 0; i < m_kbconf->groupCount(); i++) {
    group = m_kbconf->getGroup(i);
    (void) new BoldListBoxItem(lbGroups, group->getPixmap(), group->getName(),
      i == m_default_groupno);
    //m_iconpaths.append(conf->readEntry(KBConfig::entryForGroup(i)));
    m_iconpaths.append(group->getIconPath());
  }
  if (m_kbconf->groupCount() > 0) lbGroups->setCurrentItem(0);
  lbGroups->setMinimumHeight(lbGroups->itemHeight() * (m_kbconf->groupCount() + 1));
  cbxIconType->setCurrentItem(m_kbconf->icon_style());
  cbxGroupScope->setCurrentItem(m_kbconf->group_scope());
  chkToggleMode->setChecked(m_kbconf->toggle_mode());
  //chkPerwindowGroup->setChecked(m_kbconf->perwindow_group());
  chkAutostart->setChecked(m_kbconf->autostart());
  chkUseShortcuts->setChecked(m_kbconf->use_shortcuts());
  slotUseShortcutsToggled(m_kbconf->use_shortcuts());
}

/** Fire up "Pick Icon" dialog */
void KBConfigDlg::slotPickIcon(){
	int index = lbGroups->currentItem();
  TQApplication::setOverrideCursor(TQCursor(TQt::WaitCursor));
  KBPickIconDlg dlg(m_iconpaths[index], *(lbGroups->pixmap(index)), this);
  TQApplication::restoreOverrideCursor();
  if (dlg.exec()) {
		TQString path = dlg.getIconPath();
    KBGroup *group = m_kbconf->getGroup(index);
		if (!path.isEmpty() && path != group->getIconPath()) {
  		kapp->config()->writeEntry(group->getName()/*KBConfig::entryForGroup(index)*/, path);
  		redrawIcons(KBConfig::IconStyle(cbxIconType->currentItem()));
      checkIconDefault(index);
    }  
  }
}

void KBConfigDlg::slotSetDefaultGroup()
{
  int new_default_group = lbGroups->currentItem();
  if (m_default_groupno != new_default_group) {
		BoldListBoxItem *item = dynamic_cast<BoldListBoxItem*>(lbGroups->item(m_default_groupno));
		item->setBold(false);
    m_default_groupno = new_default_group;
    // NB: don't use selectedItem(); it's not present in TQt 3.0, and
    // we want to maintain compatibility with it
    int curitem = lbGroups->currentItem();
    if (curitem > -1) { // should not be -1, but just in case
      item = dynamic_cast<BoldListBoxItem*>(lbGroups->item(curitem));
      item->setBold(true);
      lbGroups->triggerUpdate(false);
    }  
  }
}

/** No descriptions */
void KBConfigDlg::slotLayoutSelected(){
  btnChangeIcon->setEnabled(lbGroups->currentItem() != -1 &&
    iconTypeShowsFlag(KBConfig::IconStyle(cbxIconType->currentItem())));
  checkIconDefault(lbGroups->currentItem());  
  btnSetDefaultGroup->setEnabled(lbGroups->currentItem() != -1 &&
    lbGroups->currentItem() != m_default_groupno);  
}

/** No descriptions */
void KBConfigDlg::slotListBoxExecuted(TQListBoxItem *){
	if (iconTypeShowsFlag(KBConfig::IconStyle(cbxIconType->currentItem())))
    slotPickIcon();
}

/** No descriptions */
void KBConfigDlg::saveConfig(){
  TQString path;
  const TQPixmap *pix;
  TDEConfig *conf = kapp->config();
  conf->setGroup(ICONS_SECTION);
  for (int i = 0; i < m_kbconf->groupCount(); i++) {
    path = m_iconpaths[i];
    if (!path.isEmpty()) m_kbconf->getGroup(i)->setIconPath(path);
    //if (!path.isEmpty() && path != m_kbconf->getGroup(i)->getIconPath())
    //  conf->writeEntry(KBConfig::entryForGroup(i), path);
    pix = lbGroups->pixmap(i);
    if (pix) m_kbconf->getGroup(i)->setPixmap(*pix);
  }
  m_kbconf->set_toggle_mode(chkToggleMode->isChecked());
  m_kbconf->set_group_scope(KBConfig::GroupScope(cbxGroupScope->currentItem()));
  m_kbconf->set_default_groupno(m_default_groupno);
  //m_kbconf->set_perwindow_group(chkPerwindowGroup->isChecked());
  m_kbconf->set_icon_style(KBConfig::IconStyle(cbxIconType->currentItem()));
  m_kbconf->set_autostart(chkAutostart->isChecked());
  m_kbconf->set_use_shortcuts(chkUseShortcuts->isChecked());
  keyChooser->commitChanges();
  m_kbconf->checkKeysEnabled();
  m_kbconf->save(conf);

  //m_kbconf->notifyChanged();
  conf->sync();
}

/** No descriptions */
void KBConfigDlg::slotOk(){
  saveConfig();
  KDialogBase::slotOk();
}

/** No descriptions */
void KBConfigDlg::slotApply(){
  saveConfig();
  KDialogBase::slotApply();
}

void KBConfigDlg::slotIconTypeSelected(int index)
{
  KBConfig::IconStyle icon_style = KBConfig::IconStyle(index);
  redrawIcons(icon_style);
  slotLayoutSelected();
}

void KBConfigDlg::redrawIcons(KBConfig::IconStyle icon_style)
{
  TQValueVector<TQPixmap> pixlist;
  m_kbconf->drawIcons(icon_style, &pixlist, &m_iconpaths);
	int curIndex = lbGroups->currentItem();
  // NB: don't use count(), use size(); count() is not present in TQt 3.0, and
  // we want to maintain compatibility with it
  for (unsigned int i = 0; i < pixlist.size(); i++) {
    BoldListBoxItem *curItem = dynamic_cast<BoldListBoxItem*>(lbGroups->item(i));
    lbGroups->changeItem(new BoldListBoxItem(NULL, pixlist[i],
      curItem->text(), curItem->bold()), i);
  }
  lbGroups->setCurrentItem(curIndex);
}

void KBConfigDlg::slotCancel()
{
	TDEConfig *config = kapp->config();
	config->rollback();
	config->reparseConfiguration();
	KDialogBase::slotCancel();
}

void KBConfigDlg::slotUseShortcutsToggled(bool on)
{
	keyChooser->setEnabled(on);
}


/*!
    \fn KBConfigDlg::slotSetDefaultIcon()
 */
void KBConfigDlg::slotSetDefaultIcon()
{
	int index = lbGroups->currentItem();
  kapp->config()->setGroup(ICONS_SECTION);
	kapp->config()->deleteEntry(m_kbconf->getGroup(index)->getName()/*KBConfig::entryForGroup(index)*/);
	redrawIcons(KBConfig::IconStyle(cbxIconType->currentItem()));
}


/*!
    \fn KBConfigDlg::checkIconDefault()
 */
void KBConfigDlg::checkIconDefault(int index)
{
  TDEConfig *conf = kapp->config();
  if (index == -1 || ! iconTypeShowsFlag(KBConfig::IconStyle(cbxIconType->currentItem()))) {
    btnSetDefaultIcon->setEnabled(false);
  }  
  else {
    conf->setGroup(ICONS_SECTION);
    btnSetDefaultIcon->setEnabled(!conf->readEntry(m_kbconf->getGroup(index)->getName()/*KBConfig::entryForGroup(index)*/).isNull());
  }  
}

#include "kbconfigdlg.moc"
