/* -*- c++ -*-
 *
 * infolist.h
 *
 * Copyright (C) 2003, 2004 Petter Stokke <ummo@hellokitty.com>
 * Copyright (C) 2003, 2004 Sebastian Sauer <mail@dipe.org>
 * Copyright (C) 2006       Christian Muehlhaeuser <chris@chris.de>
 *
 * 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 Steet, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef __INFOLIST_H__
#define __INFOLIST_H__

#include "availability.h"

#include <klistview.h>

#include <time.h>
#include <qptrlist.h>
#include <qtimer.h>

class KPopupMenu;
class KProgress;

/**
 * Our base ListView-class which extends KListView a bit.
 */
class InfoList : public KListView
{
    Q_OBJECT

    public:
        /**
        * Constructor.
        * \param parent The parent QWidget-object
        * \param name Name of this InfoList.
        * \param headervisiblepopup Show/hide columns per headerpopupmenu?
        */
        InfoList( QWidget* parent = 0, const char* name = 0, bool headervisiblepopup = false );
        /**
        * Destructor.
        */
        ~InfoList();

        /**
        * Initialization.
        * This function should be called if all columns are avaible (the addColumn()-
        * function was called before at least one time to have a valid column) to do
        * some initial-work.
        */
        void initialise();

        /**
        * Save the layout.
        * This function saves all the listview-settings like columnposition and
        * which columns are shown/hidden to the KConfig.
        */
        void saveLayout();

        /**
        * Same as KListView::selectedItems() except that this
        * fixes http://bugs.kde.org/show_bug.cgi?id=86756.
        * TODO If the bug got fixed in future we may like to remove
        * this function again.
        */
        QPtrList<QListViewItem> selectedItems() const;

        /**
        * Overloaded function to add a column to the InfoList.
        * \param label The Column-label, diplsayed in the header()
        * \param width Columnwidth in pixel.
        * \param widthMode The width mode, could be QListView::Manual or QListView::Maximum.
        * \param hideColumn By default hide this column.
        * \return Position the column was added to.
        */
        int addColumn( const QString& label, int width = 90, QListView::WidthMode widthMode = QListView::Manual, bool hideColumn = false );

        /**
        * Returns numbers of real columns. Use header()->count() to determinate the
        * numbers of visibled columns if needed.
        * \return numbers of real columns.
        */
        int realColumnCount() const;

        /**
        * Map visible to real column. Each visibled column points to exactly one
        * real column.
        * \param c visible column position
        * \return real column position
        */
        int visibleToReal(int c) const;

        /**
        * Map real to visible column. Returns -1 if column isn't visible.
        * \param c real column position
        * \return visible column position
        */
        int realToVisible(int c);

        /**
        * Returns seconds the list gots automatically resorted or <=0
        * if auto-resort is disabled (default).
        * \return Frequency the list should be resorted in seconds.
        */
        int sortInterval();

        /**
        * Set the automatic sorting-frequency (<=0 to disable).
        * \param sec Frequency the list should be resorted in seconds.
        */
        void setSortInterval( int sec );

    signals:
        /**
        * Emitted if the InfoList got the focus.
        */
        void gotFocus();
        /**
        * Emitted if the InfoList lost the focus.
        */
        void lostFocus();
        /**
        * Emitted if the InfoList got or lost the focus.
        */
        void focusChanged();

    protected slots:
        void toggleColumnVisible( int );
        void sortTimer();

    protected:
        virtual bool eventFilter( QObject*, QEvent* );
        virtual void focusInEvent( QFocusEvent* );
        virtual void focusOutEvent( QFocusEvent* );

    private:
        void showColumn( int );
        void hideColumn( int );

        QString m_name;
        QValueList<int> m_visibleReal;
        QMap<int,int> m_realVisible;
        QMap<int,QString> m_columns;
        QMap<int,int> m_columnWidth;
        QMap<int,QListView::WidthMode> m_columnWidthMode;
        int m_columnCount;

        int m_sortInterval;
        QTimer *m_sortTimer;

        KPopupMenu *m_headerMenu;
        QStringList hideHeader;
};


/**
 * Used to cache InfoItem's.
 */
class InfoItemCacheEntry
{
    public:
        InfoItemCacheEntry() {}

        void update( const QString& str );
        void update( const QString& str, double num );
        int compare( const InfoItemCacheEntry* ) const;

        const QString& text() const { return m_str; }
        double numeric() const { return m_isNum ? m_num : 0.0; }
        bool isNumeric() const { return m_isNum; }

    private:
        QString m_str;
        double m_num;
        bool m_isNum;
};


/**
 * Base ListViewItem for InfoList's.
 */
class InfoItem : public KListViewItem
{
    public:
        InfoItem( KListView *parent, int file );
        ~InfoItem();

        QString text( int column ) const;
        virtual QString xtext( int column ) const = 0;
        void setFileNo( int file );
        int fileNo();

        virtual int compare( QListViewItem*, int, bool ) const;
        virtual double numeric( int ) const;
        virtual bool isNumeric( int ) const;

        virtual void refresh( bool alsoRepaint = true );
        const InfoItemCacheEntry* cacheEntry( int column ) const;

    protected:
        int fileno;
        QPtrList<InfoItemCacheEntry> cache;
};


class DownloadFile : public InfoItem, public AvailabilityRenderer
{
    public:
        DownloadFile( KListView *parent, int file );
        ~DownloadFile() {}

        void setText( int, const QString& );
        QString xtext( int column ) const;
        int compare( QListViewItem*, int, bool ) const;
        double numeric( int col ) const;
        bool isNumeric( int col ) const;

        virtual void paintCell( QPainter* p, const QColorGroup& cg, int col, int w, int align );
        virtual int width( const QFontMetrics& fm, const QListView* lv, int c ) const;
        virtual void flush();

    private:
        time_t m_lastFlush;
        KProgress* m_progress;
};


class DownloadedFile : public InfoItem
{
    public:
        DownloadedFile( KListView *parent, int file );
        ~DownloadedFile() {}

        QString xtext( int column ) const;
        double numeric( int col ) const;
        bool isNumeric( int col ) const;
};


class ServerInfoItem : public InfoItem
{
    public:
        ServerInfoItem( KListView *parent, int server );
        ~ServerInfoItem() {}

        void setText( int, const QString& );
        QString xtext( int column ) const;
        double numeric( int col ) const;
        bool isNumeric( int col ) const;

        virtual void paintCell( QPainter* p, const QColorGroup& cg, int col, int w, int align );
};


class ClientItem : public InfoItem
{
    public:
        ClientItem( KListView *parent, int client );
        ~ClientItem() {}

        QString xtext( int column ) const;
        virtual void paintCell( QPainter* p, const QColorGroup& cg, int col, int w, int align );

        void setFilesListed( bool listed );

    private:
        bool filesListed;
};


class ResultInfo;

class ClientFile : public InfoItem
{
    public:
        ClientFile( KListView* parent, int file );
        ~ClientFile() {}

        QString xtext( int column ) const;
        double numeric( int col ) const;
        bool isNumeric( int col ) const;
};


QString humanReadableSize( int64 rsz );
QString humanReadableSpeed( double sp );
QString humanReadableTime( time_t t, bool shortFormat );
QString calculateETA( FileInfo* fi );
QString humanReadablePriority( int pri );


#endif /* __INFOLIST_H__ */
