/*
 * This file is part of the KFTPGrabber project
 *
 * Copyright (C) 2003-2006 by the KFTPGrabber developers
 * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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
 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
 * NON-INFRINGEMENT.  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.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.  If you delete this exception statement from all source
 * files in the program, then also delete it here.
 */
#ifndef KFTPWIDGETS_BROWSERDETAILSVIEW_H
#define KFTPWIDGETS_BROWSERDETAILSVIEW_H

#include "browser/locationnavigator.h"

#include <kfiledetailview.h>
#include <kdirlister.h>

namespace KFTPSession {
  class Session;
}

namespace KFTPWidgets {

namespace Browser {

class DirLister;
class TreeView;
class View;

/**
 * This class represents a detailed list view for displaying local and
 * remote directory contents. It is based upon KFileDetailView but uses
 * a custom (wrapped) DirLister for actual listings.
 *
 * @author Jernej Kos
 */
class DetailsView : public KFileDetailView {
Q_OBJECT
public:
    /**
     * Maps the column indices of KFileDetailView to a
     * descriptive column name.
     */
    enum ColumnName {
      NameColumn = 0,
      SizeColumn = 1,
      DateColumn = 2,
      PermissionsColumn = 3,
      OwnerColumn = 4,
      GroupColumn = 5
    };

    /**
     * Class constructor.
     *
     * @param parent Parent widget
     * @param view Main view container
     * @param session Current session
     */
    DetailsView(QWidget *parent, View *view, KFTPSession::Session *session);
    
    /**
     * Class destructor.
     */
    ~DetailsView();
    
    /**
     * Returns the navigator object for navigating this view.
     */
    const LocationNavigator *locationNavigator() const { return m_navigator; }
    
    /**
     * Returns the current URL.
     */
    const KURL &url() const;
    
    /**
     * Returns the current history elements.
     *
     * @param index Variable to save the current history position to
     * @return Current history element list
     */
    const QValueList<LocationNavigator::Element> history(int &index) const;
    
    /**
     * @overload
     * Reimplemented from KFileView to support filtered views.
     */
    bool isSelected(const KFileItem *i) const;
    
    /**
     * Set the tree view widget to use for the tree.
     *
     * @param tree A valid tree view widget
     */
    void setTreeView(TreeView *tree);
    
    /**
     * Set the home URL.
     *
     * @param url URL to use as home URL
     */
    void setHomeUrl(const KURL &url);
    
    /**
     * Changes the "show hidden files" setting.
     *
     * @param value True to enable showing hidden files, false otherwise
     */
    void setShowHidden(bool value) { m_showHidden = value; }
    
    /**
     * Go one history hop back.
     */
    void goBack();
    
    /**
     * Go one history hop forward.
     */
    void goForward();
    
    /**
     * Go up in the directory structure.
     */
    void goUp();
    
    /**
     * Go the the predefined home URL.
     */
    void goHome();
    
    /**
     * Do item post-processing.
     */
    void endItemUpdates();
    
    /**
     * @overload
     * Reimplemented from KFileDetailView.
     */
    void insertItem(KFileItem *fileItem);
    
    /**
     * Fetch a file item by its filename.
     *
     * @param file Item's filename
     */
    KFileItem *fileItem(const QString &filename);
    
    /**
     * Changes item's colors in the list view. Note that this overrides any
     * highlight colors predefined by user filters.
     *
     * @param item The item to change colors for
     * @param text Text color
     * @param background Background color
     */
    void setItemColor(KFileItem *item, const QColor &text, const QColor &background);
    
    /**
     * Changes item's visibility in the list view.
     *
     * @param item The item tho change visiblity for
     * @param visibility 1 if the item should be visible, 0 if it should be hidden, reverse otherwise
     */
    void setItemVisibility(KFileItem *item, int visibility = -1);
    
    /**
     * Mark or unmark the item. If the item is already marked it will be
     * unmarked and vice-versa.
     *
     * @param item The item to mark
     */
    void markItem(KFileItem *item);
    
    /**
     * Mark or unmark the item identified by its filename. If the item is
     * already marked it will be unmarked and vice-versa.
     *
     * @param filename Item's filename
     */
    void markItem(const QString &filename);
    
    /**
     * Unmark all items.
     */
    void unmarkItems();
public slots:
    /**
     * Open an URL. Note that if a remote URL is specified the session needs to
     * be connected to the specified host!
     *
     * @param url URL to open
     */
    void openUrl(const KURL &url);
    
    /**
     * Reload the current directory listing.
     */
    void reload();
    
    /**
     * Calculates new widths for all the columns.
     */
    void updateColumnWidths();
    
    /**
     * This method gets called when the widget is resized. It is used for automatic
     * resize handling.
     *
     * @param width The new width
     * @param height The new height
     */
    void resizeContents(int width, int height);
    
    /**
     * Returns the drag object to use for copy/paste and "drag and drop".
     */
    QDragObject *dragObject();
protected:
    /**
     * Instruct the directory lister object to fetch the specified URL.
     *
     * @param url URL to fetch
     * @param reload Should the cache be invalidated
     */
    void fetchLocation(const KURL &url, bool reload = false);
    
    /**
     * This method gets called when the widget is resized. It is used for automatic
     * resize handling.
     */
    void resizeEvent(QResizeEvent *event);
    
    /**
     * Returns true if the drop event should be accepted.
     */
    bool acceptDrag(QDropEvent *event) const;
    
    /**
     * Called when something acceptable gets dropped on us.
     */
    void contentsDropEvent(QDropEvent *event);
private:
    class ListViewItem : public KFileListViewItem {
    public:
        ListViewItem(QListView *parent, KFileItem *fileItem);
        
        /**
         * @overload
         * Reimplemented from KListView to implement nicer items.
         */
        void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment);
        
        /**
         * Set a text color for this item.
         *
         * @param color Text color
         */
        void setColor(QColor color) { m_textColor = color; }
        
        /**
         * Set a background color for this item.
         *
         * @param color Background color
         */
        void setBackground(QColor color) { m_backgroundColor = color; }
        
        /**
         * Set marked state for this item.
         *
         * @param marked True if this item should be marked, false otherwise
         */
        void markItem(bool marked);
        
        /**
         * Returns true if this item is marked.
         */
        bool marked() const { return m_marked; }
    private:
        QColor m_textColor;
        QColor m_backgroundColor;
        bool m_marked;
    };
    
    View *m_view;
    DirLister *m_dirLister;
    LocationNavigator *m_navigator;
    TreeView *m_treeView;
    QTimer *m_resizeTimer;
    
    bool m_refreshing;
    bool m_showHidden;
    bool m_shouldDisableResize;
    bool m_autoResizeEnabled;
protected slots:
    void slotClear();
    void slotCompleted();
    void slotDeleteItem(KFileItem *item);
    void slotRefreshItems();
    void slotSiteChanged(const KURL &url);
    
    void slotUrlChanged(const KURL &url);
    
    /**
     * This slot gets called when an item has been renamed.
     */
    void slotItemRenamed(QListViewItem *item, const QString &name);
    
    void slotContentsMoving(int x, int y);
    
    /**
     * This slot gets called when a context menu should be displayed.
     */
    void slotContextMenu(KListView*, QListViewItem *i, const QPoint &p);
    
    /**
     * This slot gets called when an item has been clicked.
     */
    void slotItemExecuted();
    
    /**
     * This slot gets called when a section in listview's header is resized. This
     * is needed for proper automatic resize handling.
     *
     * @param section The section that was resized
     */
    void slotHeaderResized(int section);
signals:
    /**
     * This signals gets emitted when user scrolls the widget.
     *
     * @param x New X position
     * @param y New Y position
     */
    void contentsMoved(int x, int y);
    
    /**
     * This signal is emitted when items change.
     */
    void itemsChanged();
};

}

}

#endif
