/***************************************************************************
 *   Copyright (C) 2003-2005 by liuspider                                  *
 *   liuspider@users.sourceforge.net                                       *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#define Uses_SCIM_EVENT
#include <skimpluginmanager.h>

#include "skimkeygrabber.h"

#include <qlabel.h>
#include <qcheckbox.h>
#include <qlayout.h>
#include <qtooltip.h> 
#include <klocale.h>
#include <kkeynative.h> 

SkimKeyGrabber::SkimKeyGrabber(QWidget *parent, const char *name)
 : KDialogBase(KDialogBase::Plain, 0, parent, name, true, i18n("Grab Key"), KDialogBase::Cancel)
{
    setInputMethodEnabled(false);
    enableButtonOK(false);
    enableButtonCancel(true);
    QVBoxLayout * vb = new QVBoxLayout(plainPage());
    QLabel * lb = new QLabel(i18n("<center>Please press shortcut...</center><p>When you release a key this dialog will be closed automatically.</p>"), plainPage());
    lb->setAlignment(Qt::WordBreak);
//     lb->setAlignment(Qt::AlignCenter);
    vb->addWidget(lb);
    vb->addItem(new QSpacerItem(0, 10));
    QHBoxLayout * hb = new QHBoxLayout(vb, 3);
    ctrl = new QCheckBox(i18n("Control"), plainPage());
    hb->addWidget(ctrl);
    alt = new QCheckBox(i18n("Alt"), plainPage());
    hb->addWidget(alt);
    shift = new QCheckBox(i18n("Shift"), plainPage());
    hb->addWidget(shift);
    release = new QCheckBox(i18n("Release"), plainPage());
    hb->addWidget(release);
}

int SkimKeyGrabber::exec() {
    grabKeyboard();
    int result = KDialogBase::exec();
    QValueList<int> oldkeys = keys;
    keys.clear();
    checkKeys(Qt::Key_Control, oldkeys, keys, ctrl);
    checkKeys(Qt::Key_Shift, oldkeys, keys, shift);
    checkKeys(Qt::Key_Alt, oldkeys, keys, alt);
    keys += oldkeys;
    releaseKeyboard();
    
    for(uint i = 0; i<keys.size(); i++) {
      int qtKeyCode = keys[i];
      int mod;
      switch (qtKeyCode) {
        case Qt::Key_Control:
            mod = scim::SCIM_KEY_ControlMask;
          break;
        case Qt::Key_Shift:
            mod = scim::SCIM_KEY_ShiftMask;
          break;
        case Qt::Key_Alt:
            mod = scim::SCIM_KEY_Mod1Mask;
          break;
        case Qt::Key_Meta:
            mod = scim::SCIM_KEY_Mod2Mask;
          break;
        default:
            mod = scim::SCIM_KEY_NullMask;
      }
      KKeyNative b = KKey(qtKeyCode);
//       std::cout << "code mod sym " << b.code() << " " << b.mod() << " " << b.sym() << "\n";
  
      scim::KeyEvent scimkey(b.sym(), mod);
//       std::cout << " scimkey ascii: " << scimkey.get_ascii_code()<< "\n";
      scim::String s;
      scim_key_to_string(s, scimkey);
      
      if( i == keys.size() - 1 && (s == "Control" || s == "Shift" || s == "Alt") ) {
          if(release->isChecked())
            s += "+" + s;
      }
      finalKeys += QString::fromLatin1(s.c_str()) + "+";
    }
    if(release->isChecked())
      finalKeys += "KeyRelease";
    else
      finalKeys = finalKeys.left(finalKeys.length() - 1);
    
    return result;
}
void SkimKeyGrabber::checkKeys(int key, QValueList<int> & oldkeys, QValueList<int> & newkeys, QCheckBox * cb) {
    if(!oldkeys.contains(key) && cb->isChecked()) {
      newkeys.push_back(key);
      oldkeys.remove(key);
    }
}

void SkimKeyGrabber::keyPressEvent ( QKeyEvent * e ) {
    if(!e->isAutoRepeat() && !keys.contains(e->key())) {
      keys.push_back(e->key());
      switch (e->key()) {
        case Qt::Key_Control:
            ctrl->setChecked(true);
          break;
        case Qt::Key_Shift:
            shift->setChecked(true);
          break;
        case Qt::Key_Alt:
            alt->setChecked(true);
          break;
      }
    }
}

void SkimKeyGrabber::keyReleaseEvent ( QKeyEvent * /*e*/ ) {
    KDialogBase::accept();
}

#include <klineedit.h>

SkimShortcutEditor::SkimShortcutEditor(QWidget *parent, const char *name)
  : QWidget(parent, name)
{
    setInputMethodEnabled(false);
    (new QHBoxLayout(this))->setAutoAdd(true);
    lineEditor = new KLineEdit(this);
    lineEditor->setInputMethodEnabled(false);
    button = new QToolButton(this);
    button->setUsesTextLabel(true);
    button->setTextLabel("...");
    connect(button, SIGNAL(clicked()), SLOT(invokeGrabber()));
}

void SkimShortcutEditor::invokeGrabber() 
{
    SkimKeyGrabber g;
    if(g.exec() == QDialog::Accepted)
      lineEditor->setText(g.getShortcut());
}

#include <qmessagebox.h> 
#include <keditlistbox.h> 
SkimShortcutListEditor::SkimShortcutListEditor(QWidget *parent, const char *name)
 : KDialogBase(KDialogBase::Plain, 0, parent, name, true, 
   i18n("Edit Shortcut List"), KDialogBase::Ok | KDialogBase::Cancel)
{
    editor = new SkimShortcutEditor(plainPage());
    KEditListBox::CustomEditor * customeditor = 
      new KEditListBox::CustomEditor(editor, editor->lineEditor);
    listBox = new KEditListBox(i18n("Edit Shortcuts"), *customeditor, plainPage());
    (new QVBoxLayout(plainPage()))->addWidget(listBox);
    connect(listBox, SIGNAL(added(const QString &)), SLOT(verifyShortcut(const QString &)));
}

void SkimShortcutListEditor::setStringList(QStringList & s)
{
  listBox->insertStringList(s);
}

QString SkimShortcutListEditor::getCombinedString()
{
  return listBox->items().join(",");
}

void SkimShortcutListEditor::verifyShortcut(const QString &k)
{
  scim::KeyEventList keylist;
  scim::String str = k.latin1();
  if(!scim::scim_string_to_key_list(keylist, str))
  {
    QListBox * l = listBox->listBox();
    if( QListBoxItem * i = l->findItem(k))
    {
      l->removeItem(l->index(i));
    }
    QMessageBox::warning(this, i18n("Warning"), i18n("\"%1\" is not a valid shortcut!").arg(k),
      QMessageBox::Ok, QMessageBox::NoButton );
  }
}


SkimEditShortcutButton::SkimEditShortcutButton(QWidget *parent, const char *name)
  : QToolButton(parent, name), lineEditor(0) 
{
    setUsesTextLabel(true);
    setTextLabel("...");
    connect(this, SIGNAL(clicked()), SLOT(invokeShortcutListEditor()));
}


void SkimEditShortcutButton::invokeShortcutListEditor()
{
    SkimShortcutListEditor ed;
    QStringList keys = QStringList::split(",", shortcuts);
    ed.setStringList(keys);
    if(ed.exec() == QDialog::Accepted) {
      if(shortcuts != ed.getCombinedString()) {
//         shortcuts = ed.getCombinedString();
        emit setEditorText(ed.getCombinedString());
      }
    }
}
void SkimEditShortcutButton::setShortcuts(const QString & s)
{
    shortcuts = s.simplifyWhiteSpace().replace(' ', "");
}

#include "skimkeygrabber.moc"
