/*
 *  Copyright (c) 2004 Gunnar Schmi Dt <gunnar@schmi-dt.de>
 *  Copyright (c) 2008 Sebastian Sauer <mail@dipe.org>
 *
 *  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
 */

#ifndef KBSTATE_H
#define KBSTATE_H

#include <QtGui/QPushButton>
#include <QtCore/QTimer>
#include <QtGui/QPixmap>
#include <QtGui/QMouseEvent>
#include <QtCore/QTimerEvent>
#include <QtGui/QGridLayout>
#include <QtGui/QResizeEvent>
#include <QtGui/QGraphicsLayout>

#include <kconfig.h>
#include <kconfigdialog.h>
#include <plasma/applet.h>

extern "C"
{
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <X11/keysymdef.h>
#include <X11/extensions/XKB.h>
}

class QGridLayout;
class KIconLoader;

class StatusIcon : public QPushButton {
        Q_OBJECT
    public:
        StatusIcon (const QString &text, QWidget *parent, const char *name=0);
        ~StatusIcon ();
        QSize minimumSizeHint () const;
};
typedef QList<StatusIcon*> IconList;

class TimeoutIcon : public StatusIcon {
    Q_OBJECT
    public:
        TimeoutIcon (KIconLoader *iconLoader, const QString &text, const QString &featurename, QWidget *parent, const char *name=0);
        ~TimeoutIcon ();
        void update ();
        void setGlyth (const QString &glyth);
        void setImage (const QString &name, int timeout = 0);
        void paintEvent(QPaintEvent *event);
    private:
        QString glyth;
        QString iconname;
        QString featurename;
        QPixmap pixmap;
        QPixmap image;
        QTimer timer;
        KIconLoader *iconLoader;
    private slots:
        void timeout ();
};

class KeyIcon : public StatusIcon {
        Q_OBJECT
    public:
        KeyIcon (int keyId, KIconLoader *iconLoader, QWidget *parent, const char *name=0);
        ~KeyIcon ();
        void setState (bool latched, bool locked);
        void paintEvent(QPaintEvent *event);
        void updateImages ();
    signals:
        void stateChangeRequest (KeyIcon *source, bool latched, bool locked);
    protected:
        void resizeEvent(QResizeEvent*);
    private slots:
        void clickedSlot();
        private:
        QPixmap locked;
        QPixmap latched;
        QPixmap unlatched;
        bool    isLatched;
        bool    isLocked;
        bool    tristate;
        int     keyId;
        KIconLoader *iconLoader;
};

class MouseIcon : public StatusIcon {
        Q_OBJECT
    public:
        MouseIcon (KIconLoader *iconLoader, QWidget *parent, const char *name=0);
        ~MouseIcon ();
        void setState (int state);
        void setActiveKey (int activekey);
        void paintEvent(QPaintEvent *event);
        void updateImages ();
    protected:
        void resizeEvent(QResizeEvent*);
    private:
        QPixmap mouse;
        QPixmap leftSelected;
        QPixmap middleSelected;
        QPixmap rightSelected;
        QPixmap leftDot;
        QPixmap middleDot;
        QPixmap rightDot;
        QPixmap leftDotSelected;
        QPixmap middleDotSelected;
        QPixmap rightDotSelected;
        int state, activekey;
        KIconLoader *iconLoader;
};

class KbStateApplet;

class KbStateWidget : public QWidget {
        Q_OBJECT
    public:
        explicit KbStateWidget(KbStateApplet *applet, QWidget *parent = 0);
        ~KbStateWidget();
        int widthForHeight(int height) const;
        int heightForWidth(int width) const;
        int orientation() const;
        Display* x11Display() const;
    signals:
        void updateLayout();
    protected:
        void timerEvent(QTimerEvent*);
        void resizeEvent(QResizeEvent*);
        bool x11Event (XEvent *);
    public slots:
        void updateSettings ();
        void paletteChanged();
    private slots:
        void stateChangeRequest (KeyIcon *source, bool latched, bool locked);
    private:
        void layout();
        KbStateApplet* m_applet;
        int xkb_base_event_type;
        KeyIcon *(icons[8]);
        IconList modifiers;
        IconList lockkeys;
        TimeoutIcon *sticky;
        TimeoutIcon *slow;
        TimeoutIcon *bounce;
        MouseIcon *mouse;
        int state;
        unsigned int accessxFeatures;
        int m_size;
        bool showModifiers, showLockkeys, showMouse, showAccessX;
        bool fillSpace;
        KComponentData componentData;
        XkbDescPtr xkb;
        KIconLoader *m_iconLoader;
        friend class KbStateApplet;
};

class KbStateApplet : public Plasma::Applet {
        Q_OBJECT
    public:
        KbStateApplet(QObject *parent, const QVariantList &args);
        virtual ~KbStateApplet();
        virtual void init();
        virtual void constraintsEvent(Plasma::Constraints constraints);
        virtual void createConfigurationInterface(KConfigDialog *parent);
    public Q_SLOTS:
        void configAccepted();
    private:
        class Private;
        Private* d;
};

#endif
