/***************************************************************************
 *   Copyright (C) 2005 by Daniel Stöckel                                  *
 *   the_docter@gmx.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.                                   *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "kommando.h"

#include <klocale.h>
#include <X11/Xmu/Converters.h>
#include <kpixmapeffect.h>

#include "configuration.h"

Kommando::Kommando()
	:	DCOPObject("Menu"),
		QWidget( 0, "Kommando",	Qt::WDestructiveClose |
					Qt::WStyle_Customize  |
					Qt::WStyle_NoBorder),
		actMenu(NULL),
		mainMenu(NULL),
		navbutton(this),
		oldNavbuttonIconType(0)
{
		Config& config = Config::getSingleton();
		//set up the widget's properties
		setFixedSize(config.menuSize(),config.menuSize());
		setBackgroundMode( NoBackground );
		
		//apply a circular mask
		QRegion mask(rect(),QRegion::Ellipse);
		setMask(mask);
		
		//set up the navbutton
		navbutton.move(config.menuRadius(),config.menuRadius());
		connect(&navbutton, SIGNAL(clicked()), this, SLOT(slotNavClick()));
}

void Kommando::slotGlobAccel()
{
	toggle();
}

void Kommando::show( )
{
	/*
	 * TODO: Get rid of X if possible
	 * This is ugly! X dependencies just for querying the pointer...
	 * But as long as I do not know of another way to retrieve the mouse's position
	 * I will have to use this :(
	 */
	Window   rep_root, rep_child;
	int      rep_rootx, rep_rooty;
	unsigned int  rep_mask;
	int      mousex, mousey;  //only need these but have to declare the other ones to feed XQueryPointer(...) :(
	Display* dpy = qt_xdisplay();
	Window   win = qt_xrootwin();

	XQueryPointer (dpy, win, &rep_root, &rep_child, &rep_rootx, &rep_rooty, &mousex, &mousey, &rep_mask);

	Config& config = Config::getSingleton();
	move(mousex-config.menuRadius(),mousey-config.menuRadius());
	
	//get the part of the screen the widget is drawn onto and apply a fade effect to it
	mScreenshot = QPixmap::grabWindow( qt_xrootwin(), x(), y(), width(), height() );
	KPixmapEffect::fade( mScreenshot, config.opacity(), config.tintColor() );

	QWidget::show();
}

void Kommando::toggle( )
{
	if(!isHidden()){
		hide();
	} else {
		show();
	}
}

void Kommando::setActMenu( Menu * newmenu )
{
	//disconnect everything
	if(actMenu!=NULL){
		actMenu->disconnect();
		actMenu->hideButtons();
	}

	if(newmenu==mainMenu){
		navbutton.setIcon("error");
	} else {
		navbutton.setIcon("back");
	}
	/*
	 * TODO: I do not have the slightest idea why this is necessary and
	 * why a simple update command is not enough, but without
	 * those calls the navbutton will not be drawn properly.
	 * Should fix it if I'm really bored
	 */
	navbutton.hide();
	navbutton.show();

	actMenu=newmenu;
	
	//initialize the new menu
	if(newmenu!=NULL){
		connect(actMenu, SIGNAL(clicked(int)), this, SLOT(slotOnClick()) );
		connect(actMenu, SIGNAL(buttonSelected(int )),this,SLOT(slotButtonSelected(int )));
		actMenu->showButtons();
	}
}

void Kommando::setMainMenu( Menu* newmenu )
{
	if(mainMenu){
		Menu* temp=mainMenu;
		setActMenu(NULL);			//properly deinitialize everything
		delete temp;
	}
	mainMenu=newmenu;
}

void Kommando::windowActivationChange( bool oldActive )
{
	//if the menu loses focus hide it
	if(oldActive){
		hide();
	}
}

void Kommando::hideEvent( QHideEvent * evt )
{
	setActMenu(mainMenu);
}

void Kommando::paintEvent( QPaintEvent * evt )
{
	bitBlt( this, 0, 0, &mScreenshot );
}

void Kommando::wheelEvent( QWheelEvent * evt )
{
	actMenu->selectButton(actMenu->selectedButtonNum()+evt->delta()/120);
}

void Kommando::execute( )
{
	Menu* temp = actMenu->execute();
	if(temp){
		setActMenu(temp);
	} else {
		hide();
	}
}

void Kommando::slotOnClick( )
{
	execute();
}

void Kommando::slotNavClick( )
{
	if(actMenu->selectedButtonNum()==BUTTON_DESELECT){
		if(actMenu==mainMenu){
			hide();
		} else {
			setActMenu(actMenu->parentMenu());
		}
	} else {
		execute();
	}
}

void Kommando::slotButtonSelected( int type )
{
	if(oldNavbuttonIconType!=type){
		switch(type){
			case 0:
				if(actMenu==mainMenu){
					navbutton.setIcon("error");
				} else {
					navbutton.setIcon("back");
				}
				break;
			case 1:
				navbutton.setIcon("exec");
				break;
			case 2:
				navbutton.setIcon("folder");
				break;
		}
		navbutton.hide();
		navbutton.show();
		oldNavbuttonIconType=type;
	}
}

void Kommando::keyPressEvent( QKeyEvent * evt )
{
	switch(evt->key()){
		case Qt::Key_Left:
			actMenu->selectButton(actMenu->selectedButtonNum()-1);
			break;
		case Qt::Key_Right:
			actMenu->selectButton(actMenu->selectedButtonNum()+1);
			break;
		case Qt::Key_Return:
			slotNavClick();
			break;
		case Qt::Key_Escape:
			if(actMenu==mainMenu){
				hide();
			} else {
				setActMenu(actMenu->parentMenu());
			}
			break;
		case Qt::Key_1:
		case Qt::Key_2:
		case Qt::Key_3:
		case Qt::Key_4:
		case Qt::Key_5:
		case Qt::Key_6:
		case Qt::Key_7:
		case Qt::Key_8:
		case Qt::Key_9:
			actMenu->selectButton(evt->key()-Qt::Key_1);	//We want to get the number of the button, so treat the enum as number (yes I know, but it works fine :->)
		break;
	}
}

void Kommando::setNavButtonSize( unsigned short size )
{
	navbutton.setRadius(size);
	Config& config = Config::getSingleton();
	navbutton.move(config.menuRadius(),config.menuRadius());
}

void Kommando::resize( )
{
	Config& config = Config::getSingleton();
	setFixedSize(config.menuSize(),config.menuSize());
	//apply a circular mask
	QRegion mask(rect(),QRegion::Ellipse);
	setMask(mask);
}

#include "kommando.moc"
