
/***************************************************************************
 *                                                                         *
 *   KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson  *
 *                                       (c) 2002, Ben Burton              *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef __STATPOPUP_H
#define __STATPOPUP_H

#include <qwidget.h>

class KAction;
class KActionCollection;
class KConfig;
class KPopupMenu;
class KRadioAction;
class KSelectAction;
class KToggleAction;
class QTimer;
class StatDock;

/**
 * A small pop-up window that contains a continually updating display of
 * statistics.
 *
 * This pop-up will be sticky and stay-on-top by default.
 *
 * Up to two windows docked in the system tray (of class StatDock) can
 * be maintained by this pop-up.  There should only be one StatPopup
 * per application.
 *
 * Note that initDock() and cleanUpDock() \e must be called when a
 * system tray window is created or closed respectively, though
 * initDock() is generally called automatically from the StatDock
 * constructor.
 *
 * Note also that the constructor for this class does \e not call
 * setupActions(), readPopupState() or startUpdates(); these must all be
 * called by other routines (such as subclass constructors), since they
 * require either subclass initialisation or an existing system tray
 * window.
 */
class StatPopup : public QWidget {
    Q_OBJECT

public:
    /**
     * Colour constants.
     */
    static const QColor colorBorder;

public:
    /**
     * Constructors and destructors.
     *
     * This constructor will set the config variable but will not read
     * any configuration information.  See the general class notes also
     * for a list of other routines this constructor will not call.
     */
    StatPopup(bool useSupportSplit, QWidget *parent = 0, const char *name = 0);
    ~StatPopup();

    /**
     * Geometric pop-up state management.
     */
    void readPopupState();
    void savePopupState();

    /**
     * Initialises the given system tray window and its context menu.
     *
     * All global application properties (i.e., properties held by this
     * pop-up) will be propagated to the system tray window, and all
     * global application actions will be added to the given menu.
     *
     * Parameter whichDock must be either 0 or 1 to specify whether the
     * given system tray window will become window dock[0] or dock[1].
     *
     * This routine \e must be called when a system tray window is first
     * created, though in general this will be done automatically by the
     * StatDock constructor.
     */
    virtual void initDock(StatDock* target, KPopupMenu* menu, int whichDock);

    /**
     * Performs any cleaning up required before the given system tray
     * window is closed.
     *
     * This routine \e must be called when a system tray is about to be
     * closed.
     *
     * Parameter whichDock must be either 0 or 1 to specify whether
     * window dock[0] or dock[1] is to be closed.
     */
    virtual void cleanUpDock(int whichDock);

    /**
     * Is this application currently active (i.e., taking periodic
     * readings and displaying them)?
     */
    bool isActive() const;

    /**
     * Are split diagrams currently enabled?
     */
    bool isSplit() const;

    /**
     * Returns the frequency of updates in milliseconds.
     */
    int getSpeed() const;

public slots:
    /**
     * Slots for menu items.
     */
    void setActive(bool);
    void clearHistory();
    void selectSpeed();
    void setSplit(bool);
    void setFillLines();
    void setFillBars();
    void setFillShaded();
    void setSoft(bool);
    void setLabelled(bool);
    void setGrid(bool);
    void selectColor0();
    void selectColor1();

protected:
    /**
     * Return a human-readable name and default diagram colour for each
     * system tray window.
     * The argument given will be either 0 or 1, referring to window
     * dock[0] or dock[1] respectively.
     */
    virtual QString dockName(int which) const = 0;
    virtual QColor defaultDockColor(int which) const = 0;

    /**
     * Take a fresh reading.  Subclasses must override this routine.
     *
     * This routine must update the array upper.
     * If split readings are enabled, it must also update the array lower.
     * If this pop-up is visible, it must also update the string fullReading.
     */
    virtual void takeReadingInternal() = 0;

    /**
     * Sets up any actions specific to subclasses of StatPopup.
     * The global configuration should be read at this point to set the
     * initial states of these actions.
     *
     * This routine will be called during setupActions().
     */
    virtual void setupCustomActions() {}

    /**
     * Inserts any menu items specific to subclasses of StatPopup into
     * the given menu.  If any items are inserted, a separator should
     * be inserted after them.
     *
     * This routine will be called during initDock().
     */
    virtual void insertCustomItems(KPopupMenu*) {}

    /**
     * Propagates any properties specific to subclasses of StatPopup to
     * the given system tray window during its initialisation.
     *
     * This routine will be called during initDock().
     */
    virtual void setCustomProperties(StatDock*) {}

    /**
     * Returns the first non-null pointer out of dock[0] and dock[1], or
     * returns null if both these pointers are null.
     */
    StatDock* firstDock();

    /**
     * Start and stop the periodic taking of readings.
     */
    void startUpdates();
    void stopUpdates();

    /**
     * Set up the collection of appliation-wide actions.
     * The global configuration will be read at this point to set the
     * initial states of these actions.
     */
    virtual void setupActions();

    /**
     * Request that this pop-up be resized at the next reading according
     * to its text contents.  The pop-up will be resized \e after the
     * reading is taken.
     */
    void requestResize();

    /**
     * Custom painting routine.
     */
    void paintEvent(QPaintEvent *);

    /**
     * Overrides for dragging support.
     */
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);

    /**
     * Overrides for saving the popup state.
     */
    void closeEvent(QCloseEvent *);
    void hideEvent(QHideEvent *);
    void showEvent(QShowEvent *);

protected slots:
    /**
     * Take a fresh reading and update all visual elements accordingly.
     */
    void takeReading();

protected:
    /**
     * Configuration and GUI elements.
     */
    KConfig* config;
        /**< The configuration for the underlying application. */
    StatDock* dock[2];
        /**< The two system tray windows maintained by this pop-up.
             Either of these pointers may be null. */
    KActionCollection* coll;
        /**< The collection of all application-level actions. */

    /**
     * Last readings taken.
     */
    int upper[2];
        /**< The upper readings taken during the last reading,
             one for each system tray window. */
    int lower[2];
        /**< The lower readings taken during the last reading,
             one for each system tray window. */
    QString fullReading;
        /**< A full string describing the last reading taken,
             to be displayed in this pop-up. */

private:
    /**
     * Resize this pop-up according to its text contents (i.e., the
     * variable fullReading).  A little extra room will be added to
     * accomodate potential minor variations in the text.
     */
    void resizeToText();

private:
    /**
     * Update support.
     */
    QTimer* timer;
        /**< The timer handling periodic updates. */
    int speed;
        /**< The frequency of updates in milliseconds. */

    /**
     * Diagram support.
     */
    QColor color[2];
        /**< The colours used in the two system tray diagrams. */
    int fillStyle;
        /**< The fill style used in the system tray diagrams. */
    bool supportSplit;
        /**< Does this application support split diagrams? */

    /**
     * Pop-up support.
     */
    int relX;
        /**< The X coordinate of this pop-up at the beginning of a drag
             operation. */
    int relY;
        /**< The Y coordinate of this pop-up at the beginning of a drag
             operation. */
    bool isDragged;
        /**< Are we in the middle of a drag operation? */
    bool closing;
        /**< Have we received a close event? */
    bool resizeRequested;
        /**< Has a pop-up resize been requested? */

    /**
     * Actions
     */
    KToggleAction* actActive;
    KAction* actClearHistory;
    KAction* actSpeed;
    KToggleAction* actSplit;
    KToggleAction* actFillLines;
    KToggleAction* actFillBars;
    KToggleAction* actFillShaded;
    KToggleAction* actSoft;
    KToggleAction* actLabelled;
    KToggleAction* actGrid;
    KAction* actColor0;
    KAction* actColor1;
};

inline int StatPopup::getSpeed() const {
    return speed;
}

inline void StatPopup::requestResize() {
    resizeRequested = true;
}

#endif
