#ifndef _DIRVIEW_H_
#define _DIRVIEW_H_

#include <qtableview.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qlist.h>
#include <qdropsite.h>
#include <qdragobject.h>
#include "dircombo.h"
#include "fileinfo.h"

#include "kexplorer.def"
#include "protocol.h"

enum DirViewItem_Type { DirNormal, DirLink, DirMount, DirLock};

class DirView;
class DirViewItem;
class DirViewItemList;

typedef QList<QString>	KPath;
typedef QListIterator<QString>	KPathIterator;

struct DirViewItem
{
public:
	DirViewItem(DirViewItem *parent, const char *label, const char *addr, QPixmap *icon = 0, QPixmap *iconSel = 0, bool hasChilds = TRUE, int type = DirNormal);
	~DirViewItem();

	DirViewItem* getFirstParent();
	QList<DirViewItem> getParentList();
	DirViewItem* findChild(const char *name);
	void clear();
	void addChildItem(DirViewItem *item);

	QString		Label;
	QString		Address;
	DirViewItem	*ParentItem;
	DirViewItemList	*Childs;
	DirViewItem	*Next;
	bool		Opened;
	QPixmap		*Icon, *IconSel;
	int		Depth;
	int		Index;
	DirView		*ParentDirView;
	bool		ChildsScanned;
	bool		HasChilds;	// if true -> draw expand box
	int		Type;
	bool		Sorting;
};

typedef QList<DirViewItem>	DirViewItemListBase;
typedef QListIterator<DirViewItem>	DirViewItemListIterator;

class DirViewItemList : public DirViewItemListBase
{
public:
	DirViewItemList() : DirViewItemListBase() {}

protected:
#define	IT1	((DirViewItem*)item1)
#define	IT2	((DirViewItem*)item2)
	virtual int compareItems(GCI item1, GCI item2)
		{
			if (IT1->Address.findRev('#') == -1) {
				if (IT2->Address.findRev('#') == -1) return strcmp(IT1->Label.data(),IT2->Label.data());
				else return -1;
			}
			else {
				if (IT2->Address.findRev('#') != -1) return strcmp(IT1->Label.data(),IT2->Label.data());
				else return 1;
			}
//			return strcmp(IT1->Label.data(),IT2->Label.data());
		}
#undef	IT1
#undef	IT2
};

class DirView : public QTableView, public QDropSite
{
	Q_OBJECT;

public:
	DirView(QWidget *parent = 0, const char *name = 0);
	~DirView();

	void setModifierPixmap(int type, QPixmap *pixmap);
	void setRootIcon(QPixmap *icon);
	void setRootLabel(const char *text);
	void addItem(DirViewItem *parent, const char *name, const char *addr, QPixmap *icon = 0, QPixmap *iconSel = 0, bool sorting = FALSE, bool hasChilds = TRUE, int type = DirNormal, bool updateF = TRUE);
	void addItem(const char *path, const char *name, const char *addr, QPixmap *icon = 0, QPixmap *iconSel = 0, bool sorting = FALSE, bool hasChilds = TRUE, int type = DirNormal, bool updateF = TRUE);
	void removeItem(DirViewItem *parent, const char *name);
	void removeItem(const char *path, const char *name);
	void removeItem(const char *url);
	void renameItem(const char *urlsrc, const char *urldest);
	void removeItem(DirViewItem *item);
	void removePointFiles();
	void removeArchiveFiles(SubProtList *list = 0);
	void addItem(DirViewItem *item);
	DirViewItem* findItem(const char *path);
	DirViewItem* findItemFromURL(const char *url);
	DirViewItem* currentItem();
	void setCurrentItem(DirViewItem *item);
	DirViewItem* popupItem();
	void setCombo(DirCombo *combo);
	void refresh();
	void clearItem(DirViewItem *item);
	void rescanChilds(DirViewItem *item);
	void refreshItem(DirViewItem *item);
	void refreshItem(const char *url);
	void goToDir(const char *path);
	void updateCell(DirViewItem *item, bool redraw=FALSE);

signals:
	void selectionChanged(DirViewItem *item);
	void rightButtonPressed(DirViewItem *item);
	void requestItemChilds(DirViewItem *item);
	void dropAccepted(QDropEvent *e, DirViewItem *item);
	void updateHasChilds(DirViewItem *item);

public slots:
	void cdUp();
	bool cdDown(const char *dir);
	void expandItem(DirViewItem *item, bool redraw = TRUE);
	void collapseItem(DirViewItem *item, bool redraw = TRUE);
	void comboChanged(int item);

protected:
	void paintCell(QPainter *p, int row, int col);
	void mousePressEvent(QMouseEvent *e);
	void mouseDoubleClickEvent(QMouseEvent *e);
	void resizeEvent(QResizeEvent *e);
	void updateViewList();
	void scrollInView();
	void changeSelection(DirViewItem *newItem);
	QRect expandRect(DirViewItem *item);
	void updateCombo();
	void dragEnterEvent(QDragEnterEvent *e);
	void dragMoveEvent(QDragMoveEvent *e);
	void dropEvent(QDropEvent *e);

private:
	DirViewItem	*Root, *CurrentItem, *PopupItem;
	QList<DirViewItem>	ViewList;
	QList<DirViewItem>	ItemList;
	QPixmap		*LinkPixmap, *MountPixmap, *LockPixmap;
	DirCombo	*Combo;
};

inline void DirView::setModifierPixmap(int type, QPixmap *pixmap)
{
	switch(type) {
	   case DirLink : LinkPixmap = pixmap; break;
	   case DirMount : MountPixmap = pixmap; break;
	   case DirLock : LockPixmap = pixmap; break;
	   default : break;
	}
}

inline void DirView::setCombo(DirCombo *combo)
{
	Combo = combo;
	updateCombo();
	connect(Combo,SIGNAL(activated(int)),SLOT(comboChanged(int)));
}

inline void DirView::scrollInView()
{
	if (CurrentItem && (CurrentItem->Index*ICON_HEIGHT < yOffset() || CurrentItem->Index*ICON_HEIGHT > yOffset()+height())) {
		setYOffset(CurrentItem->Index*ICON_HEIGHT-height()/2);
	}
}

inline DirViewItem* DirView::currentItem()
{ return CurrentItem;}

inline DirViewItem* DirView::popupItem()
{ return PopupItem;}

inline void DirView::setCurrentItem(DirViewItem *item)
{
	changeSelection(item);
	emit selectionChanged(CurrentItem);
}

inline void DirView::dragEnterEvent(QDragEnterEvent *e)
{ if (QUrlDrag::canDecode(e)) e->accept();}

inline void DirView::dragMoveEvent(QDragMoveEvent *e)
{ if (QUrlDrag::canDecode(e)) e->accept();}

inline void DirView::setRootLabel(const char *text)
{ Root->Label = text;}

#endif
