/***************************************************************************
 *   Copyright (C) 2007 by Todor Gyumyushev   *
 *   yodor@developer.bg   *
 *                                                                         *
 *   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; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/

#include "MainWidget.h"
#include "VButton.h"
#include "numpadvbutton.h"

#include <cstdlib>

#include <X11/extensions/XTest.h>
#include <X11/keysym.h>

#include <kiconloader.h>
#include <khelpmenu.h>
#include <tqtooltip.h>
#include <math.h>
#include <tqfont.h>
#include <tqfontdialog.h>
#include <tdeconfig.h>
#include <tdeapplication.h>
#include <tqcolordialog.h>


#define R1LEN 13
#define R2LEN 10
#define R3LEN 9
#define R4LEN 8

bool shutting=false;

MainWidget::MainWidget ( TDEAboutData *about, bool tren, TQWidget *parent, const char * name, WFlags f ) : ResizableDragWidget ( parent,name,f ), stand_alone(tren)
{
	tray=0;
	nresize=false;
	display=tqt_xdisplay();
	
	//TQString k1= "`1234567890-=";
	//TQString k1s = "~!@#$%^&*()_+";
	unsigned int kc1[R1LEN] = {49,10,11,12,13,14,15,16,17,18,19,20,21};

	//TQString k2= "qwertyuiop";
	//TQString k2s = "QWERTYUIOP";
	unsigned int kc2[R2LEN] = {24,25,26,27,28,29,30,31,32,33};

	//TQString k3= "asdfghjkl"; //;'";
	//TQString k3s="ASDFGHJKL";
	unsigned int kc3[R3LEN] = {38,39,40,41,42,43,44,45,46}; //,{47,48};

	//TQString k4="<zxcvbnm"; //,./";
	//TQString k4s=">ZXCVBNM";
	unsigned int kc4[R4LEN] = {94,52,53,54,55,56,57,58};//59,60,61};

	int stx=15;
	int sty=15;
	extent_visible=false;

	setFocusPolicy(TQWidget::NoFocus);
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	if (cfg)
	{
		extent_visible = cfg->readBoolEntry("numpad_visible", false);
		TQString backgroundC = cfg->readEntry("keyboardBackgroundColor", "#cdc0b0");
		setPaletteBackgroundColor(TQColor(backgroundC));
	}

	VButton *esc = new VButton ( this,"" );
	esc->setKeyCode ( 9 );
	esc->move ( stx,sty );
	esc->setText ( "Esc" );
	esc->res();
	other_keys.append(esc);
	connect ( esc,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	for ( int a=0;a<4;a++ )
	{
		VButton *f = new VButton ( this,"" );
		f->setKeyCode ( 67+a );
		f->setText ( "F"+TQString ( "%1" ).arg ( a+1 ) );
		f->move ( stx+esc->width() + ( 35*a ) +30,sty );
		f->res();
		other_keys.append(f);
		connect ( f,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	}
	for ( int a=0;a<4;a++ )
	{
		VButton *f = new VButton ( this,"" );
		f->setKeyCode ( 71+a );
		f->setText ( "F"+TQString ( "%1" ).arg ( a+5 ) );
		f->move ( stx+esc->width() + ( 35*a ) +44+ ( 4*35 ),sty );
		f->res();
		other_keys.append(f);
		connect ( f,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	}
	for ( int a=0;a<4;a++ )
	{
		VButton *f = new VButton ( this,"" );
		f->setKeyCode ( 75+a );
		if ( a>1 ) f->setKeyCode ( 93+a );
		f->setText ( "F"+TQString ( "%1" ).arg ( a+9 ) );
		f->move ( stx+esc->width() + ( 35*a ) +58+ ( 8*35 ),sty );
		f->res();
		other_keys.append(f);
		connect ( f,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	}

	//ROW 1
	for ( int a=0;a<R1LEN;a++ )
	{
		VButton *v = new VButton ( this,"" );
		v->setKeyCode ( kc1[a] );
		v->move ( stx+ ( 35*a ),sty+35 );
		connect ( v,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
		btns.append ( v );
		v->res();
	}

	VButton *bksp = new VButton ( this,"" );
	bksp->setKeyCode ( 22 );
	bksp->move ( stx+ ( R1LEN *35 ),sty+35 );
	bksp->resize ( 48,30 );
	bksp->setText ( "Bksp" );
	bksp->res();
	other_keys.append(bksp);
	connect ( bksp,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	//ROW 2
	VButton *tab = new VButton ( this,"" );
	tab->setKeyCode ( 23 );
	tab->move ( stx,sty+35+35 );
	tab->resize ( 48,30 );
	tab->setText ( "Tab" );
	tab->res();
	other_keys.append(tab);
	connect ( tab,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	for ( int a=0;a<R2LEN;a++ )
	{
		VButton *v = new VButton ( this,"" );
		v->setKeyCode ( kc2[a] );
		//v->setText ( k2.mid ( a,1 ) );
		//v->setShiftText ( k2s.mid ( a,1 ) );
		v->move ( stx+tab->width() +5+ ( 35*a ),sty+35+35 );
		v->res();
		connect ( v,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
		btns.append ( v );
	}

	VButton *lbr = new VButton ( this,"" );
	lbr->setKeyCode ( 34 );
	lbr->move ( stx+tab->width() +5+ ( R2LEN *35 ),sty+ ( 2*35 ) );
	//lbr->setText ( "[" );
	//lbr->setShiftText ( "{" );
	lbr->res();
	connect ( lbr,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( lbr );

	VButton *rbr = new VButton ( this,"" );
	rbr->setKeyCode ( 35 );
	rbr->move ( stx+tab->width() +5+ ( ( R2LEN +1 ) *35 ),sty+ ( 2*35 ) );
	//rbr->setText ( "]" );
	//rbr->setShiftText ( "}" );
	rbr->res();
	connect ( rbr,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( rbr );

	VButton *bksl = new VButton ( this,"" );
	bksl->setKeyCode ( 51 );
	bksl->move ( stx+tab->width() +5+ ( ( R2LEN +2 ) *35 ),sty+35+35 );
	bksl->resize ( 30,30 );
	//bksl->setText ( "\\" );
	//bksl->setShiftText ( "|" );
	bksl->res();
	connect ( bksl,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( bksl );

	//ROW 3
	caps = new VButton ( this,"" );
	caps->setKeyCode ( 66 );
	caps->move ( stx,sty+ ( 3*35 ) );
	caps->resize ( 63,30 );
	caps->setText ( "Caps" );
	caps->setToggleButton ( true );
	connect ( caps,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( toggleShiftCapsAltGr ( unsigned int ) ) );
	other_keys.append(caps);
	caps->res();

	for ( int a=0;a<R3LEN;a++ )
	{
		VButton *v = new VButton ( this,"" );
		v->setKeyCode ( kc3[a] );
		//v->setText ( k3.mid ( a,1 ) );
		//v->setShiftText ( k3s.mid ( a,1 ) );
		v->move ( stx+caps->width() +5+ ( 35*a ),sty+ ( 3*35 ) );
		btns.append ( v );
		v->res();
		connect ( v,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	}
	VButton *smcl = new VButton ( this,"" );
	smcl->setKeyCode ( 47 );
	smcl->move ( stx+ ( R3LEN *35 ) +caps->width() +5,sty+ ( 3*35 ) );
	//smcl->setText ( ";" );
	//smcl->setShiftText ( ":" );
	connect ( smcl,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( smcl );
	smcl->res();

	VButton *sngq = new VButton ( this,"" );
	sngq->setKeyCode ( 48 );
	sngq->move ( stx+ ( ( R3LEN +1 ) *35 ) +caps->width() +5,sty+ ( 3*35 ) );
	//sngq->setText ( "'" );
	//sngq->setShiftText ( "\"" );
	connect ( sngq,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( sngq );
	sngq->res();

	VButton *enter = new VButton ( this,"" );
	enter->setKeyCode ( 36 );
	enter->move ( stx+ ( ( R3LEN +2 ) *35 ) +caps->width() +5,sty+ ( 3*35 ) );
	enter->resize ( 50,30 );
	enter->setText ( "Enter" );
	connect ( enter,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	other_keys.append(enter);
	enter->res();

	//ROW 4
	lshift = new VButton ( this,"" );
	lshift->setKeyCode ( 50 );
	lshift->move ( stx,sty+ ( 4*35 ) );
	lshift->resize ( 45,30 );
	lshift->setText ( "Shift" );
	lshift->setToggleButton ( true );
	connect ( lshift,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( toggleShiftCapsAltGr( unsigned int ) ) );
	mod_keys.append ( lshift );
	lshift->res();

	for ( int a=0;a<R4LEN;a++ )
	{
		VButton *v = new VButton ( this,"" );
		v->setKeyCode ( kc4[a] );
		//v->setText ( k4.mid ( a,1 ) );
		//v->setShiftText ( k4s.mid ( a,1 ) );
		v->move ( stx+lshift->width() +5+ ( 35*a ),sty+ ( 4*35 ) );
		btns.append ( v );
		v->res();
		connect ( v,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	}

	VButton *sm = new VButton ( this,"" );
	sm->setKeyCode ( 59 );
	sm->move ( stx+ ( R4LEN *35 ) +lshift->width() +5,sty+ ( 4*35 ) );
	//sm->setText ( "," );
	//sm->setShiftText ( "<" );
	connect ( sm,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( sm );
	sm->res();

	VButton *gr = new VButton ( this,"" );
	gr->setKeyCode ( 60 );
	gr->move ( stx+ ( ( R4LEN +1 ) *35 ) +lshift->width() +5,sty+ ( 4*35 ) );
	//gr->setText ( "." );
	//gr->setShiftText ( ">" );
	connect ( gr,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( gr );
	gr->res();

	VButton *sl = new VButton ( this,"" );
	sl->setKeyCode ( 61 );
	sl->move ( stx+ ( ( R4LEN +2 ) *35 ) +lshift->width() +5,sty+ ( 4*35 ) );
	//sl->setText ( "/" );
	//sl->setShiftText ( "?" );
	connect ( sl,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	btns.append ( sl );
	sl->res();

	rshift = new VButton ( this,"" );
	rshift->setKeyCode ( 62 );
	rshift->move ( stx+ ( ( R4LEN +3 ) *35 ) +lshift->width() +5,sty+ ( 4*35 ) );
	rshift->resize ( 68,30 );
	rshift->setText ( "Shift" );
	rshift->setToggleButton ( true );
	connect ( rshift,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( toggleShiftCapsAltGr( unsigned int ) ) );
	mod_keys.append ( rshift );
	rshift->res();

	//ROW 5
	lctrl = new VButton ( this,"" );
	lctrl->resize ( 45,30 );
	lctrl->move ( stx, sty+ ( 5*35 ) );
	lctrl->setText ( "Ctrl" );
	lctrl->setKeyCode ( 37 );
	lctrl->setToggleButton ( true );
	mod_keys.append ( lctrl );
	lctrl->res();

	lwin = new VButton ( this,"" );
	lwin->resize ( 50,30 );
	lwin->move ( lctrl->x() +lctrl->width() +5, sty+ ( 5*35 ) );
	lwin->setText ( "LWin" );
	lwin->setKeyCode ( 133 );
	lwin->setToggleButton ( true );
	mod_keys.append ( lwin );
	lwin->res();

	lalt = new VButton ( this,"" );
	lalt->resize ( 45,30 );
	lalt->move ( lwin->x() +lwin->width() +6, sty+ ( 5*35 ) );
	lalt->setText ( "Alt" );
	lalt->setKeyCode ( 64 );
	lalt->setToggleButton ( true );
	mod_keys.append ( lalt );
	lalt->res();

	VButton *space = new VButton ( this,"" );
	space->setKeyCode ( 65 );
	space->resize ( 133,30 );
	space->move ( lalt->x() +lalt->width() +5, sty+ ( 5*35 ) );

	connect ( space, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	space->res();
	other_keys.append(space);

	ralt = new VButton ( this,"" );
	ralt->resize ( 48,30 );
	ralt->move ( 5+space->x() +space->width(), sty+ ( 5*35 ) );
	ralt->setText ( "AltGr" );
	ralt->setKeyCode ( 108 );
	ralt->setToggleButton ( true );
	connect ( ralt,TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( toggleShiftCapsAltGr ( unsigned int ) ) );
	mod_keys.append ( ralt );
	ralt->res();

	rwin = new VButton ( this,"" );
	rwin->resize ( 48,30 );
	rwin->move ( ralt->x() +ralt->width() +5, sty+ ( 5*35 ) );
	rwin->setText ( "RWin" );
	rwin->setKeyCode ( 134 );
	rwin->setToggleButton ( true );
	mod_keys.append ( rwin );
	rwin->res();

	mnu = new VButton ( this,"" );
	mnu->resize ( 49,30 );
	mnu->move ( rwin->x() +rwin->width() +5, sty+ ( 5*35 ) );
	mnu->setText ( "Menu" );
	mnu->setKeyCode ( 135 );
	mnu->setToggleButton ( false );
	connect ( mnu, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	other_keys.append(mnu);
	mnu->res();

	rctrl = new VButton ( this,"" );
	rctrl->resize ( 49,30 );
	rctrl->move ( 5+mnu->x() +mnu->width(), sty+ ( 5*35 ) );
	rctrl->setText ( "Ctrl" );
	rctrl->setKeyCode ( 105 );
	rctrl->setToggleButton ( true );
	mod_keys.append ( rctrl );
	rctrl->res();

	quit = new VButton ( this,"quit" );
	quit->resize ( 20,30 );
	quit->move ( 524,15 );
	quit->setPixmap(TQIconSet(SmallIcon("application-exit", TDEIcon::SizeMedium)).pixmap());
	TQToolTip::add( quit, i18n( "Hide keyboard" ) );
	quit->res();
	other_keys.append(quit);
	connect ( quit,TQ_SIGNAL ( clicked() ),this, TQ_SLOT ( quitClicked() ) );

	extent = new VButton(this,"extent");
	extent->resize ( 20,65 );
	extent->move (524, 85 );
	if (extent_visible)
	{
		extent->setPixmap(TQIconSet(SmallIcon("media-seek-backward", TDEIcon::SizeMedium)).pixmap());
		TQToolTip::add( extent, i18n( "Hide num pad" ) );
	}
	else
	{
		extent->setPixmap(TQIconSet(SmallIcon("media-seek-forward", TDEIcon::SizeMedium)).pixmap());
		TQToolTip::add( extent, i18n( "Show num pad" ) );
	}
	extent->res();
	other_keys.append(extent);
	connect (extent, TQ_SIGNAL( clicked() ) , this, TQ_SLOT ( toggleNumericPad() ) );
 
	TQTimer *t = new TQTimer ( this );
	connect ( t, TQ_SIGNAL ( timeout() ), this, TQ_SLOT ( queryModState() ) );
	t->start ( 500, false );

	int padx= 554;
	TQString txt[9] = { "Ho\nme", TQString::fromUtf8("▲"), "Pg\nUp",
		TQString::fromUtf8("◄"), " ", TQString::fromUtf8("►"),
		"End", TQString::fromUtf8("▼"), "Pg\nDn" };
	TQString nump[9] = {"7","8","9","4","5","6","1","2","3"};
	int val=0;
	int cval[9] = {79,80,81,83,84,85,87,88,89};
	for (int a=2;a<5;a++){
		for (int b=0;b<3;b++){
			NumpadVButton *v = new NumpadVButton(this,"");
			v->move(padx+(b*35),sty+(a*35));
			v->res();
			v->setKeyCode(cval[val]);
			v->setText(txt[val]);
			v->setShiftText(nump[val]);
			numl_keys.append(v);
			connect ( v, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
			val++;
		}
	}
	ins = new NumpadVButton(this,"ins");
	ins->resize(65,30);
	ins->move(padx,sty+(5*35));
	ins->res();
	ins->setText("Ins");
	ins->setKeyCode(90);
	ins->setShiftText("0");
	numl_keys.append(ins);	
	
	connect ( ins, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	del = new NumpadVButton(this,"del");
	del->resize(30,30);
	del->move(padx+70,sty+(5*35));
	del->res();
	del->setText("Del");
	del->setShiftText(".");
	del->setKeyCode(91);
	numl_keys.append(del);
	connect ( del, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	

	numl = new VButton(this,"numlock");
	numl->setKeyCode(77);
	numl->move(padx,sty+(1*35));
	numl->res();
	numl->setText("Num\nLock");
	numl->setToggleButton ( true );
	other_keys.append(numl);
	connect ( numl, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( toggleNumlock() ) );


	div = new VButton(this,"div");
	div->move(padx+(35),sty+(1*35));
	div->res();
	div->setText("/");
	div->setKeyCode(106);
	other_keys.append(div);
	connect ( div, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	mul = new VButton(this,"mul");
	mul->move(padx+(2*35),sty+(1*35));
	mul->res();
	mul->setText("*");
	mul->setKeyCode(63);
	other_keys.append(mul);	
	connect ( mul, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );
	
	ent = new VButton(this,"enter1");
	ent->resize(30,65);
	ent->move(padx+70+35,sty+(4*35));
	ent->res();
	ent->setText("En\nter");
	ent->setKeyCode(104);
	other_keys.append(ent);
	connect ( ent, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	plu = new VButton(this,"plus");
	plu->resize(30,65);
	plu->move(padx+70+35,sty+(2*35));
	plu->res();
	plu->setText("+");
	plu->setKeyCode(86);
	other_keys.append(plu);
	connect ( plu, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	min = new VButton(this,"minus");
	min->resize(30,30);
	min->move(padx+70+35,sty+(1*35));
	min->setText("-");
	min->setKeyCode(82);
	other_keys.append(min);
	min->res();
	connect ( min, TQ_SIGNAL ( keyClick ( unsigned int ) ), this, TQ_SLOT ( keyPress ( unsigned int ) ) );

	mappingNotify(NULL);

	if (!stand_alone)
	{
		tray = new KbdTray ( this );
		tray->setPixmap ( UserIcon ( "tray" ) );

		TDEConfig *cfg = TDEApplication::kApplication()->config();

		TDEPopupMenu *m = tray->contextMenu();
		m->setCheckable ( true );

		KHelpMenu *h = new KHelpMenu ( tray, about );
		m->insertItem ( i18n("Font ..."), this, TQ_SLOT ( chooseFont() ) );

		mnu_autores = m->insertItem( i18n("Auto resize font"),this, TQ_SLOT ( toggleFontAutoRes() ) );
		bool fnt_autores = cfg->readBoolEntry("autoresfont",true);
		m->setItemChecked(mnu_autores, fnt_autores);

		m->insertItem ( i18n ("Background color"), this, TQ_SLOT ( chooseBackgroundColor() ) );
		m->insertItem ( i18n ("Keys color"), this, TQ_SLOT ( chooseKeysColor() ) );

		m->insertSeparator();
		mnu_dock = m->insertItem ( i18n("Dock widget"), this, TQ_SLOT ( showDock() ) );
		bool show_dock = cfg->readBoolEntry("showdock",false);
		m->setItemChecked(mnu_dock, show_dock);

		mnu_lock = m->insertItem(i18n("Lock on screen"), this, TQ_SLOT(toggleLock()));
		locked = cfg->readBoolEntry("locked", false);
		m->setItemChecked(mnu_lock, locked);

		//m->insertItem("Configure", this, TQ_SLOT(config()));
		m->insertSeparator();
		m->insertItem ( i18n("Help"), h->menu() );
		
		tray->show();
		
		TQFont fnt = cfg->readFontEntry("KvkbdFont");
		m->setItemChecked(mnu_autores, fnt_autores);
		setFont(fnt);

		dock = new KbdDock(this);
		if (show_dock)
		{
			dock->show();
		}
		else
		{
			dock->hide();
		}

		setLockState(locked);

		popup_menu = new VButton ( this,"popupmenu" );
		popup_menu->resize ( 20,30 );
		popup_menu->move ( 524,15+35 );
		//popup_menu->setPaletteBackgroundColor ( TQt::green );
		popup_menu->res();
		
		popup_menu->setPixmap(TQIconSet(SmallIcon("configure", TDEIcon::SizeMedium)).pixmap());
		TQToolTip::add( popup_menu, i18n( "Configure" ) );
		other_keys.append(popup_menu);
		connect ( popup_menu,TQ_SIGNAL ( clicked() ),this, TQ_SLOT ( showConfigMenu() ) );
	}
	else
	{
		setCaption("kvkbdalone");
	}
}

void MainWidget::chooseBackgroundColor()
{
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	TQString backgroundC = cfg->readEntry("keyboardBackgroundColor", "#cdc0b0");
	TQColor newBackgroundC = TQColorDialog::getColor(TQColor(backgroundC));
	if (newBackgroundC.isValid())
	{
		cfg->writeEntry("keyboardBackgroundColor", newBackgroundC.name()); // save as #rrbbgg
		cfg->sync();
		setPaletteBackgroundColor(newBackgroundC);
	}
}

void MainWidget::chooseKeysColor()
{
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	TQString keysC = cfg->readEntry("keysColor", "#f0f0f0");
	TQColor newkeysC = TQColorDialog::getColor(TQColor(keysC));
	if (newkeysC.isValid())
	{
		cfg->writeEntry("keysColor", newkeysC.name()); // save as #rrbbgg
		cfg->sync();

		for (unsigned idx = 0; idx < btns.size(); ++idx)
		{
			btns[idx]->setColor(newkeysC);
		}
		for (unsigned idx = 0; idx < mod_keys.size(); ++idx)
		{
			mod_keys[idx]->setColor(newkeysC);
		}
		for (unsigned idx = 0; idx < other_keys.size(); ++idx)
		{
			other_keys[idx]->setColor(newkeysC);
		}
		for (unsigned idx = 0; idx < numl_keys.size(); ++idx)
		{
			numl_keys[idx]->setColor(newkeysC);
		}
	}
}

void MainWidget::finishInit()
{
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	bool vis = cfg->readBoolEntry("visible",true);
	if (vis) {
		show();
	}
	else {
		hide();
	}
}

bool MainWidget::close(bool alsoDelete)
{
	shutting=true;
	saveState();
	return TQWidget::close(alsoDelete);
}

void MainWidget::restorePosition()
{	
	TQDesktopWidget *desktop = TQApplication::desktop();
	TQRect screen_geom = desktop->screenGeometry();

	int d_width=553;
	int d_height=235;
	TQRect dflt_geom(screen_geom.width()-d_width-150,screen_geom.height()-d_height-50,d_width,d_height);

	TDEConfig *cfg = 0;
	cfg = TDEApplication::kApplication()->config();
	if (cfg){
		TQRect geom  = cfg->readRectEntry("geometry");
		if (!geom.isNull() && geom.isValid()) {
			dflt_geom=geom;
		}
	}
	setGeometry(dflt_geom);
}

void MainWidget::saveState()
{
	TDEConfig *cfg = 0;
	cfg = TDEApplication::kApplication()->config();
	if (cfg){
		cfg->writeEntry("visible",isShown());
		cfg->sync();
	}
}
void MainWidget::hideEvent ( TQHideEvent * )
{
	
	TDEConfig *cfg = 0;
	cfg = TDEApplication::kApplication()->config();
	if (cfg){
		cfg->writeEntry("geometry",geometry());
		cfg->writeEntry("numpad_visible",extent_visible);
		cfg->sync();
	}
}

void MainWidget::resizeEvent(TQResizeEvent * e)
{

 	if (nresize) return;

	const TQSize sz = e->size();	
	//512 x 243
	//spc x -> 5, spc y->7
	// btn x ->30 , btny -> 28

	if (extent_visible){
		sdxb = width();
		sdxs = width() - (width() * (150.0/703.0));
		VButton::pw=703.0;
		VButton::ph=235.0;
		setMinimumSize(703/3,235/3);
	}
	else{
		sdxs = width();
		sdxb = width() + (width() * (150.0/552.0));
		VButton::pw=552.0;
		VButton::ph=235.0;
		setMinimumSize(552/3,235/3);
	}

	for ( unsigned a=0;a<btns.size();a++ ){
		VButton *v = btns[a];
		v->reposition(sz.width(),sz.height());
	}
	for ( unsigned a=0;a<mod_keys.size();a++ ){
		VButton *v = mod_keys[a];
		v->reposition(sz.width(),sz.height());
	}
	for ( unsigned a=0;a<other_keys.size();a++ ){
		VButton *v = other_keys[a];
		v->reposition(sz.width(),sz.height());
	}
	for ( unsigned a=0;a<numl_keys.size();a++ ){
		VButton *v = numl_keys[a];
		v->reposition(sz.width(),sz.height());
	}

	updateFont();
	
}
void MainWidget::showConfigMenu()
{
	if (tray){
		TDEPopupMenu *m = tray->contextMenu();
		m->popup(mapToGlobal(popup_menu->pos()));
	}
}
void MainWidget::updateFont()
{
	if (tray->contextMenu()->isItemChecked(mnu_autores)){
		TQFont fnt = this->font();
		fnt.setWeight(TQFont::Bold);	
		//double rs = (100.0/700.0)*width();
		double rp = (11.0/600.0)*width();
		if (extent_visible)
		{
			rp *= (552.0/703.0);
		}
		//fnt.setStretch(rs);
		fnt.setPointSizeFloat(rp);
		setFont(fnt);
	}
}
void MainWidget::toggleNumericPad()
{
	nresize=true;

	if (extent_visible){
		extent_visible=false;
		extent->setPixmap(TQIconSet(SmallIcon("media-seek-forward", TDEIcon::SizeMedium)).pixmap());
		TQToolTip::add( extent, i18n( "Show num pad" ) );
		TQWidget::resize ( (int)sdxs, height() );
	}
	else{
		extent_visible=true;	
		extent->setPixmap(TQIconSet(SmallIcon("media-seek-backward", TDEIcon::SizeMedium)).pixmap());
		TQToolTip::add( extent, i18n( "Hide num pad" ) );
		TQWidget::resize ( (int)sdxb, height() );
	}
	nresize=false;
}

void MainWidget::chooseFont()
{
	bool c = false;
	if (isShown()) {
		hide();
		c=true;
	}

	bool ok;
    TQFont font = TQFontDialog::getFont(
                    &ok, this->font(), this );
    if ( ok ) {
			// font is set to the font the user selected
			setFont(font);
    } else {
        // the user canceled the dialog; font is set to the initial
        // value, in this case Helvetica [Cronyx], 10
    }
	
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	cfg->writeEntry ("KvkbdFont", this->font());
	cfg->sync();
	
	if (c)show();
	updateFont();
}

void MainWidget::quitClicked()
{
	if (stand_alone)
		close(true);
	else
		hide();
}

void MainWidget::setLockState(bool lock)
{
	locked = lock;
	tray->contextMenu()->setItemChecked(mnu_lock, locked);
	repaint(); // Force repainting to update the resize handle display
}

void MainWidget::toggleLock()
{
	setLockState(!locked);

	TDEConfig *cfg = TDEApplication::kApplication()->config();
	cfg->writeEntry("locked", locked);
	cfg->sync();
}

void MainWidget::showDock()
{
	bool c = dock->isShown();
	if ( c ) {
		tray->contextMenu()->setItemChecked ( mnu_dock, !c );
		dock->hide();
	}
	else {
		tray->contextMenu()->setItemChecked ( mnu_dock, !c );
		dock->show();
	}
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	cfg->writeEntry ("showdock", !c);
	cfg->sync();
	
}

void MainWidget::toggleFontAutoRes()
{
	bool c = tray->contextMenu()->isItemChecked( mnu_autores);
	tray->contextMenu()->setItemChecked(mnu_autores, !c);
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	cfg->writeEntry ("autoresfont", !c);
	cfg->sync();
}

void MainWidget::toggleNumlock()
{
	send_key(numl->getKeyCode());
	updateNumlock();
}

void MainWidget::updateNumlock()
{
	bool state = numl->isOn();
	for (unsigned a = 0; a < numl_keys.size();	a++)
	{
		numl_keys[a]->numlockPressed(state);
	}
}

void MainWidget::toggleShiftCapsAltGr(unsigned int keycode)
{
	send_key(keycode);
	updateShiftCapsAltGr();
}

void MainWidget::updateShiftCapsAltGr()
{
	bool shiftState = lshift->isOn() || rshift->isOn();
	bool capsState = caps->isOn();
	bool altGrState = ralt->isOn();
	for (unsigned a = 0; a < btns.size();	a++)
	{
		btns[a]->shiftCapsAltGrPressed(shiftState, capsState, altGrState);
	}
}

void MainWidget::keyPress(unsigned int a)
{
	send_key(a);
	for (unsigned a = 0; a < mod_keys.size();	a++)
	{
		mod_keys[a]->setOn(false);
	}
	// Make sure the key labels	are correctly updated
	updateShiftCapsAltGr();
}

void MainWidget::send_key(unsigned int keycode)
{
	Window curr_focus;
	int revert_to;

	XGetInputFocus ( display, &curr_focus, &revert_to );

	for ( unsigned a=0;a<mod_keys.size();a++ ) {
		VButton *mod = ( VButton* ) mod_keys[a];
		if ( mod->isOn() ) {
			XTestFakeKeyEvent ( display, mod->getKeyCode(), true, 0 );
		}
	}

	XTestFakeKeyEvent ( display, keycode, true,1 );
	XTestFakeKeyEvent ( display, keycode, false, 2 );
	for ( unsigned a=0;a<mod_keys.size();a++ ) {
		VButton *mod = ( VButton* ) mod_keys[a];
		if ( mod->isOn() ) {
			XTestFakeKeyEvent ( display, mod->getKeyCode(), false, 2 );
		}
	}
	XFlush ( display );

}
bool MainWidget::keyState ( int iKey )
{
	int          iKeyMask = 0;
	Window       wDummy1, wDummy2;
	int          iDummy3, iDummy4, iDummy5, iDummy6;
	unsigned int iMask;
	XModifierKeymap* map = XGetModifierMapping ( display );
	KeyCode keyCode = XKeysymToKeycode ( display,iKey );
	if ( keyCode == NoSymbol ) return false;
	for ( int i = 0; i < 8; ++i ) {
		if ( map->modifiermap[map->max_keypermod * i] == keyCode ) {
			iKeyMask = 1 << i;
		}
	}
	XQueryPointer ( display, DefaultRootWindow ( display ), &wDummy1, &wDummy2,&iDummy3, &iDummy4, &iDummy5, &iDummy6, &iMask );
	XFreeModifiermap ( map );
	return ( iMask & iKeyMask ) != 0;
}

void MainWidget::queryModState()
{
	bool caps_state = keyState(XK_Caps_Lock);
	if (caps_state != caps->isOn())
	{
		caps->setOn(caps_state);
		updateShiftCapsAltGr();
	}

	bool numl_state = keyState(XK_Num_Lock);
	if (numl_state != numl->isOn())
	{
		numl->setOn(numl_state);
		updateNumlock();
	}
}

void MainWidget::mappingNotify(XMappingEvent *)
{
	for (unsigned a = 0; a < btns.size(); a++)
	{
		btns[a]->setupTexts(display);
	}
	updateNumlock();
	updateShiftCapsAltGr();
}

KbdDock::KbdDock ( MainWidget *m )
		: DragWidget ( 0, "Dock", WStyle_Customize | TQt::WX11BypassWM |WStyle_NormalBorder ), mainWidget ( m )
{

	setFocusPolicy ( TQWidget::NoFocus );
	icn=UserIcon ( "dock" );
	resize ( 96,47 );

	TQToolTip::add ( this, i18n ("Toggle keyboard visibility") );
}

void KbdDock::paintEvent ( TQPaintEvent * )
{
	TQPainter p ( this );
	p.drawPixmap ( 0,0,icn );
}

KbdDock::~KbdDock()
{
}

void KbdDock::mouseReleaseEvent ( TQMouseEvent *e )
{
	TQPoint p = e->globalPos();
	int x = abs(p.x()-gpress.x());
	int y = abs(p.y()-gpress.y());

	if ( x<10 && y<10 ) {
		if ( mainWidget->isShown() )
			mainWidget->hide();
		else
			mainWidget->show();
	}
}

KbdTray::KbdTray(TQWidget *parent, const char *name) : KSystemTray(parent,name)
{
	TQToolTip::add ( this, i18n ("Virtual keyboard") );
}

void KbdTray::mousePressEvent(TQMouseEvent *e)
{
	if (e->button()==TQt::LeftButton) {
		TQWidget *p = parentWidget();
		if (p){
			if (p->isShown()){
				p->hide();
			}
			else {
				p->show();
			}
		}
	}
	else {
		KSystemTray::mousePressEvent(e);
	}
}

#include "MainWidget.moc"

