#include <iostream.h>
#include <time.h>
#include "kexplorer.h"
#include <qpopupmenu.h>
#include <qmenubar.h>
#include <qtoolbutton.h>
#include <qtoolbar.h>
#include <qmessagebox.h>
#include <qcursor.h>
#include <qdir.h>
#include <qdragobject.h>
#include <qtextstream.h>
#include <qkeycode.h>
#include <kstdaccel.h>
#include <kprocess.h>
#include "PropertyDlg.h"
#include "DeviceDlg.h"
#include "DeviceDelDlg.h"
#include "LineDlg.h"
#include "OpenDlg.h"
#include "mountprot.h"
#include "trashprot.h"
// OLE
#include <kimgio.h>
#include <dither.h>
// OLE

#define APPLICATION(a,n)	SLOT(a)#n"()"

QString getTime()
{
	const long int	timeval = time(0);
	QString		tmp = ctime(&timeval);
	int	pos = tmp.find(' ')+1;
	int	pos2 = tmp.find(' ',pos+1);
	pos2 = tmp.find(' ',pos2+1);
	pos2 = tmp.find(':',pos2+1);
	pos2 = tmp.find(':',pos2+1);
	QString	retval = tmp.mid(pos,pos2-pos);
	return retval;
}

// replaces all occurences of ~, $HOME, ...
void processPath(QString& path)
{
	int	pos = path.find('~');
	if (pos != -1) path.replace(pos,1,getenv("HOME"));
	while ((pos = path.find('$')) != -1) {
		int	pos2(pos+1);
		while (pos2 < (int)(path.length()) && (isalnum(path[pos2]) || path[pos2] == '_')) pos2++;
		QString		var = path.mid(pos+1,pos2-pos-1);
		path.replace(pos,pos2-pos,getenv(var.data()));
	}
	while ((pos = path.find("//")) != -1) path.replace(pos,2,"/");
}

bool containDirs(QStrList& list)
{
	QStrListIterator	it(list);
	for (;it.current();++it) if (QString(it.current()).right(1) == "/") return TRUE;
	return FALSE;
}

void KExplorer::initBusy()
{
	if (!Busy) {
		MainView->setCursor(waitCursor);
		MenuBar->setCursor(waitCursor);
		DirectoryTree->installEventFilter(MainFilter);
		FileView->installEventFilter(MainFilter);
		ToolBar->setItemEnabled(ABORT_ID,TRUE);
		Busy = TRUE;
	}
}

void KExplorer::finishBusy()
{
	if (Busy) {
		MainView->setCursor(arrowCursor);
		MenuBar->setCursor(arrowCursor);
		DirectoryTree->removeEventFilter(MainFilter);
		FileView->removeEventFilter(MainFilter);
		ToolBar->setItemEnabled(ABORT_ID,FALSE);
		Busy = FALSE;
	}
}

KExplorer::KExplorer(const char *path, QWidget *parent, const char *name, WFlags f)
	: KTMainWindow(name)
{
	loadConfiguration();
// OLE
// this enables QPixmap::load/write to handle xv-thumbnails;
	kimgioRegister();
// OLE
	MainFilter = new Filter(this);
	Busy = FALSE;
	Manager = new ProtocolMgr(this);
	DeviceList.setAutoDelete(TRUE);
	MenuBar = menuBar();
	StatusBar = statusBar();
	MainView = new QSplitter(QSplitter::Horizontal,this);
	setView(MainView);
	LeftView = new KFixPanner(MainView,KFixPanner::Horizontal);
	RightView = new KFixPanner(MainView,KFixPanner::Horizontal);
	LeftViewInfo = new QLabel(i18n("All files"),LeftView);
	LeftViewInfo->resize(100,20);
	LeftViewInfo->setFrameStyle(QFrame::Panel | QFrame::Sunken);
	LeftViewInfo->setLineWidth(1);
	DirectoryTree = new DirView(LeftView);
	LeftView->activate(LeftViewInfo,DirectoryTree);
	RightViewInfo = new QLabel(i18n("Contents of "),RightView);
	RightViewInfo->resize(100,20);
	RightViewInfo->setFrameStyle(QFrame::Panel | QFrame::Sunken);
	RightViewInfo->setLineWidth(1);
	createFileView();
	IconLoader = new KPIconLoader(IconPath,UseKDEIcons);
	DirectoryTree->setRootLabel(i18n("Desktop"));
	DirectoryTree->setRootIcon(IconLoader->loadMiniIcon("desktop.xpm"));
	DirectoryTree->setModifierPixmap(DirLink,IconLoader->loadMiniIcon("link.xpm"));
	DirectoryTree->setModifierPixmap(DirMount,IconLoader->loadMiniIcon("mount.xpm"));
	if (Style == BIGICON_ID) FileView->setLinkArrow(IconLoader->loadIcon("link.xpm"));
	else FileView->setLinkArrow(IconLoader->loadMiniIcon("link.xpm"));
	FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
	setupToolBar();
	setupMenu();
	Status1Info = new QLabel(StatusBar);
	Status1Info->setFrameStyle(QFrame::Panel | QFrame::Sunken);
	Status1Info->setLineWidth(1);
	StatusBar->insertWidget(Status1Info,200,STATUS1_ID);
	Status2Info = new QLabel(StatusBar);
	Status2Info->setFrameStyle(QFrame::Panel | QFrame::Sunken);
	Status2Info->setLineWidth(1);
	StatusBar->insertWidget(Status2Info,400,STATUS2_ID);
	if (StatusBarEnabled) enableStatusBar(KStatusBar::Show);
	else enableStatusBar(KStatusBar::Hide);
	ApplicationList = new KMimeAppList;
	ApplicationList->setAutoDelete(TRUE);
	ApplicationDict = new KMimeAppDict;
	ApplicationDict->setAutoDelete(FALSE);
	ExtensionList = new KMimeExtList;
	ExtensionList->setAutoDelete(TRUE);
	ExtensionDict = new KMimeExtDict;
	ExtensionDict->setAutoDelete(FALSE);
	FilenameDict = new KMimeExtList;
	FilenameDict->setAutoDelete(FALSE);
	setupMimeTypes();
	Magic = new MimeMagic(MagicFile);
	Manager->setupMime(ExtensionDict,FilenameDict,Magic,UseMagicNumbers);
	Manager->setupSubProtList(ProtList);
	loadDevices();
	FileList = new FileInfoList;
	FileList->setAutoDelete(TRUE);

	connect(DirectoryTree,SIGNAL(selectionChanged(DirViewItem*)),SLOT(scanDirectory(DirViewItem*)));
	connect(DirectoryTree,SIGNAL(requestItemChilds(DirViewItem*)),SLOT(scanSubDirectories(DirViewItem*)));
	connect(DirectoryTree,SIGNAL(rightButtonPressed(DirViewItem*)),SLOT(popupDirectoryTree(DirViewItem*)));
	connect(DirectoryTree,SIGNAL(dropAccepted(QDropEvent*,DirViewItem*)),SLOT(dropOnTree(QDropEvent*,DirViewItem*)));
	connect(DirectoryTree,SIGNAL(updateHasChilds(DirViewItem*)),SLOT(updateHasChilds(DirViewItem*)));

	Pop1 = new QPopupMenu();
	Pop2 = new QPopupMenu();
	connect(Pop2,SIGNAL(activated(int)),SLOT(menuActivated(int)));
	Pop3 = new QPopupMenu();
	Pop4 = new QPopupMenu();

	resize(SavedWidth,SavedHeight);
	LeftView->resize(SavedDirWidth,DirectoryTree->height());
	MainView->setResizeMode(LeftView,QSplitter::KeepSize);

	QString		Path;
	if (path) {
		if (*path == '/') { Path = "file:"; Path += path;}
		else if (strchr(path,':')) Path = path;
	}
	else {
		if (StartupDir == 1) { if(!LastPath.isEmpty()) Path = LastPath.data();}
		else { Path = "file:"; Path += getenv("PWD");}
	}
cout << Path << endl;
	if (!Path.isEmpty()) {
		KURL	url(Path.data());
		goToDir(url);
	}
}

KExplorer::~KExplorer()
{
//	shutdown();
	delete ExtensionDict;
	delete FilenameDict;
	delete ExtensionList;
	delete ApplicationList;
	delete FileList;
	delete ProtList;
//	delete Manager;
//	delete Pop1;
//	delete Pop2;
//	delete Pop3;
//	delete Pop4;
}

void KExplorer::setupMenu()
{
	KStdAccel	keys(ConfigFile);

	QPopupMenu	*file = new QPopupMenu();
	QPopupMenu	*newPop = new QPopupMenu();
	newPop->insertItem(i18n("Directory"),this,SLOT(newDir()));
	newPop->insertItem(i18n("Device"),this,SLOT(newDevice()));
	file->insertItem(i18n("New ..."),newPop);
	file->insertSeparator();
	file->insertItem(i18n("Open terminal"),this,SLOT(openTerminal()),Key_T+CTRL);
	file->insertSeparator();
	file->insertItem(i18n("Quit"),this,SLOT(shutdown()),keys.quit());
	MenuBar->insertItem(i18n("&File"),file);
	connect(kapp,SIGNAL(shutDown()),SLOT(shutdown()));

	QPopupMenu	*edit = new QPopupMenu();
	edit->insertItem(i18n("Cut"),this,SLOT(cut()),keys.cut());
	edit->insertItem(i18n("Copy"),this,SLOT(copy()),keys.copy());
	edit->insertItem(i18n("Paste"),this,SLOT(paste()),keys.paste());
	edit->insertSeparator();
	edit->insertItem(i18n("Delete"),this,SLOT(remove()),Key_Delete);
	edit->insertItem(i18n("Move to trash"),this,SLOT(moveToTrash()));
	edit->insertSeparator();
	edit->insertItem(i18n("Select all"),this,SLOT(mainCallback()),Key_A+CTRL);
	MenuBar->insertItem(i18n("&Edit"),edit);

	QPopupMenu	*view = new QPopupMenu();
	view->setCheckable(TRUE);
	view->insertItem(i18n("ToolBar"),this,SLOT(toggleToolBar()),0,TOOLBAR_ID);
	view->setItemChecked(TOOLBAR_ID,ToolBarEnabled);
	view->insertItem(i18n("StatusBar"),this,SLOT(toggleStatusBar()),0,STATUSBAR_ID);
	view->setItemChecked(STATUSBAR_ID,StatusBarEnabled);
	view->insertSeparator();
	view->insertItem(i18n("Refresh"),this,SLOT(refresh()),Key_F5);
	view->insertItem(i18n("Options..."),this,SLOT(options()));
	view->insertSeparator();
	view->insertItem(i18n("Big icons"),this,SLOT(bigIcons()),0,BIGICON_ID);
	view->insertItem(i18n("List icons"),this,SLOT(listIcons()),0,LISTICON_ID);
	view->insertItem(i18n("Small icons"),this,SLOT(smallIcons()),0,SMALLICON_ID);
	view->insertItem(i18n("Details"),this,SLOT(detailIcons()),0,DETAILICON_ID);
	view->setItemChecked(Style,TRUE);
	view->insertSeparator();
	QPopupMenu	*listPop = new QPopupMenu();
	listPop->setCheckable(TRUE);
	listPop->insertItem(i18n("Name"),this,SLOT(listByName()),0,LISTNAME_ID);
	listPop->insertItem(i18n("Size"),this,SLOT(listBySize()),0,LISTSIZE_ID);
	listPop->insertItem(i18n("Type"),this,SLOT(listByType()),0,LISTTYPE_ID);
	listPop->insertItem(i18n("Date"),this,SLOT(listByDate()),0,LISTDATE_ID);
	listPop->setItemChecked(LISTNAME_ID,TRUE);
	view->insertItem(i18n("List by ..."),listPop);
	QPopupMenu	*viewPop = new QPopupMenu();
	viewPop->insertItem(i18n("Hidden files"),this,SLOT(toggleShowHidden()),0,HIDDEN_ID);
	viewPop->setItemChecked(HIDDEN_ID,ShowHiddenFiles);
// OLE
	viewPop->insertItem(i18n("Mini-Images"),this,SLOT(toggleShowMiniImages()),0,MINIIMAGES_ID);
        viewPop->setItemChecked(MINIIMAGES_ID,ShowMiniImages);			
// OLE
	viewPop->insertItem(i18n("Archive files"),this,SLOT(toggleShowArchive()),0,ARCHIVE_ID);
	viewPop->setItemChecked(ARCHIVE_ID,ShowArchive);
	view->insertItem(i18n("View..."),viewPop);
	MenuBar->insertItem(i18n("&View"),view);

	QPopupMenu	*tools = new QPopupMenu();
	tools->insertItem(i18n("Find ..."),this,SLOT(launchFind()),keys.find());
	tools->insertSeparator();
	tools->insertItem(i18n("Connect new device"),this,SLOT(newDevice()),keys.openNew());
	tools->insertItem(i18n("Disconnect"),this,SLOT(removeDevice()),Key_D+CTRL);
	tools->insertSeparator();
	tools->insertItem(i18n("Go to..."),this,SLOT(goToDir()),Key_G+CTRL);
	MenuBar->insertItem(i18n("&Tools"),tools);

	QPopupMenu	*help = new QPopupMenu();
	help->insertItem(i18n("Content"),this,SLOT(mainCallback()),keys.help());
	help->insertSeparator();
	help->insertItem(i18n("About KExplorer..."),this,SLOT(mainCallback()));
	MenuBar->insertSeparator();
	MenuBar->insertItem(i18n("&Help"),help);
}

void KExplorer::setupToolBar()
{
	ToolBar = toolBar();
	if (ToolBarEnabled) enableToolBar(KToolBar::Show);
	else enableToolBar(KToolBar::Hide);
	Combo = new DirCombo(ToolBar);
	ToolBar->insertWidget(DIRCOMBO_ID,200,Combo);
	DirectoryTree->setCombo(Combo);
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("dirup.xpm")),DIRUP_ID,SIGNAL(clicked()),DirectoryTree,SLOT(cdUp()),TRUE,i18n("Parent directory"));
	ToolBar->insertSeparator();
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("connect.xpm")),CONNECT_ID,SIGNAL(clicked()),this,SLOT(newDevice()),TRUE,i18n("Connect new device"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("disconn.xpm")),DISCONNECT_ID,SIGNAL(clicked()),this,SLOT(removeDevice()),TRUE,i18n("Remove device"));
	ToolBar->insertSeparator();
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("delete.xpm")),DELETE_ID,SIGNAL(clicked()),this,SLOT(remove()),TRUE,i18n("Delete"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("property.xpm")),PROPERTY_ID,SIGNAL(clicked()),this,SLOT(property()),TRUE,i18n("Properties"));
	ToolBar->insertSeparator();
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("cut.xpm")),CUT_ID,SIGNAL(clicked()),this,SLOT(cut()),TRUE,i18n("Cut"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("copy.xpm")),COPY_ID,SIGNAL(clicked()),this,SLOT(copy()),TRUE,i18n("Copy"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("paste.xpm")),PASTE_ID,SIGNAL(clicked()),this,SLOT(paste()),TRUE,i18n("Paste"));
	ToolBar->insertSeparator();
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("bigicon.xpm")),BIGICON_ID,SIGNAL(clicked()),this,SLOT(bigIcons()),TRUE,i18n("Big icons"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("lsicon.xpm")),LISTICON_ID,SIGNAL(clicked()),this,SLOT(listIcons()),TRUE,i18n("Icon list"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("smicon.xpm")),SMALLICON_ID,SIGNAL(clicked()),this,SLOT(smallIcons()),TRUE,i18n("Small icons"));
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("detail.xpm")),DETAILICON_ID,SIGNAL(clicked()),this,SLOT(detailIcons()),TRUE,i18n("Detail list"));
	ToolBar->setToggle(BIGICON_ID,TRUE);
	ToolBar->setToggle(LISTICON_ID,TRUE);
	ToolBar->setToggle(SMALLICON_ID,TRUE);
	ToolBar->setToggle(DETAILICON_ID,TRUE);
	ToolBar->setButton(Style,TRUE);
	ToolBar->insertSeparator();
	ToolBar->insertButton(*(IconLoader->loadToolBarIcon("stop.xpm")),ABORT_ID,SIGNAL(clicked()),this,SLOT(abort()),FALSE,i18n("Abort"));
}

void KExplorer::loadConfiguration()
{
	ConfigFile = kapp->getConfig();
	ConfigFile->setGroup("Configuration");
	UseKDEIcons = ConfigFile->readBoolEntry("UseKDEIcons",TRUE);
	UseKDEMimeTypes = ConfigFile->readBoolEntry("UseKDEMimeTypes",TRUE);
	UseMagicNumbers = ConfigFile->readBoolEntry("UseMagicNumbers",FALSE);
	IconPath = ConfigFile->readEntry("IconPath");
	if (IconPath.isEmpty()) {
		IconPath = KApplication::kde_datadir();
		IconPath += "/kexplorer/icons;";
	}
	MagicFile = ConfigFile->readEntry("MagicFile");
	if (MagicFile.isEmpty()) {
		MagicFile = KApplication::kde_mimedir();
		MagicFile += "/magic";
	}
	ExtensionFile = ConfigFile->readEntry("ExtensionFile");
	if (ExtensionFile.isEmpty()) {
		ExtensionFile = KApplication::kde_datadir();
		ExtensionFile += "/kexplorer/dbext";
	}
	Style = ConfigFile->readNumEntry("Style",BIGICON_ID);
	Sorting = byName;
	TmpItem = 0;
	TmpFile = 0;
	TmpDevice = 0;
	ToolBarEnabled = ConfigFile->readBoolEntry("ToolBarEnabled",TRUE);
	StatusBarEnabled = ConfigFile->readBoolEntry("StatusBarEnabled",TRUE);
	ShowHiddenFiles = ConfigFile->readBoolEntry("ShowHiddenFiles",TRUE);
// OLE
	ShowMiniImages = ConfigFile->readBoolEntry("ShowMiniImages",FALSE);
// OLE
	MiniImageSaving = ConfigFile->readNumEntry("MiniImageSaving",0);
	ImageSize = ConfigFile->readNumEntry("ImageSize",4096);
	SavedWidth = ConfigFile->readNumEntry("Width",650);
	SavedHeight = ConfigFile->readNumEntry("Height",500);
	SavedDirWidth = ConfigFile->readNumEntry("DirWidth",250);
	ConfigFile->readListEntry("ColType",ColType);
	ConfigFile->readListEntry("ColWidth",ColWidth);
	if (ColType.count() == 0) {
		ColType.append("0");
		ColType.append("1");
		ColType.append("2");
		ColType.append("3");
		ColType.append("4");
		ColWidth.clear();
		ColWidth.append("150");
		ColWidth.append("100");
		ColWidth.append("150");
		ColWidth.append("200");
		ColWidth.append("150");
	}
	ColName[0] = i18n("Name");
	ColName[1] = i18n("Size");
	ColName[2] = i18n("File Type");
	ColName[3] = i18n("Modified");
	ColName[4] = i18n("Permissions");
	DateFormat = ConfigFile->readNumEntry("DateFormat",0);
	ShowArchive = ConfigFile->readBoolEntry("ShowArchive",FALSE);
	ProtList = new SubProtList;
	ProtList->setAutoDelete(TRUE);
	QStrList	list;
	if (ConfigFile->readListEntry("ArchiveFilter",list) > 0) {
		for (int i=0;i<(int)(list.count());i+=2) {
			int	type;
			if (strcmp(list.at(i),"tar") == 0) type = Protocol::Tar;
			else if (strcmp(list.at(i),"zip") == 0) type = Protocol::Zip;
			else if (strcmp(list.at(i),"rpm") == 0) type = Protocol::Rpm;
			ProtList->append(new SubProtocol(type,list.at(i+1)));
		}
	}
	else {
		ProtList->append(new SubProtocol(Protocol::Tar,"*.tar.gz"));
		ProtList->append(new SubProtocol(Protocol::Tar,"*.tgz"));
		ProtList->append(new SubProtocol(Protocol::Tar,"*.tar.Z"));
	}
	Shell = ConfigFile->readEntry("Shell");
	if (Shell.isEmpty()) Shell = "kvt";
	LastPath = ConfigFile->readEntry("LastPath");
	StartupDir = ConfigFile->readNumEntry("StartupDir",0);
}

void KExplorer::saveConfiguration()
{
	ConfigFile->setGroup("Configuration");
	ConfigFile->writeEntry("UseKDEIcons",UseKDEIcons);
	ConfigFile->writeEntry("UseKDEMimeTypes",UseKDEMimeTypes);
	ConfigFile->writeEntry("UseMagicNumbers",UseMagicNumbers);
	ConfigFile->writeEntry("IconPath",IconPath.data());
	ConfigFile->writeEntry("MagicFile",MagicFile.data());
	ConfigFile->writeEntry("ExtensionFile",ExtensionFile.data());
	ConfigFile->writeEntry("Style",Style);
	ConfigFile->writeEntry("ToolBarEnabled",ToolBarEnabled);
	ConfigFile->writeEntry("StatusBarEnabled",StatusBarEnabled);
	ConfigFile->writeEntry("ShowHiddenFiles",ShowHiddenFiles);
// OLE
	ConfigFile->writeEntry("ShowMiniImages",ShowMiniImages);
// OLE
	ConfigFile->writeEntry("MiniImageSaving",MiniImageSaving);
	ConfigFile->writeEntry("ImageSize",ImageSize);
	ConfigFile->writeEntry("Width",width());
	ConfigFile->writeEntry("Height",height());
	ConfigFile->writeEntry("DirWidth",DirectoryTree->width());
	if (Style == DETAILICON_ID) ((KDetailList*)FileView)->getColumns(ColType,ColWidth);
	ConfigFile->writeEntry("ColType",ColType);
	ConfigFile->writeEntry("ColWidth",ColWidth);
	ConfigFile->writeEntry("DateFormat",DateFormat);
	ConfigFile->writeEntry("ShowArchive",ShowArchive);
	QStrList	list;
	SubProtListIterator	it(*ProtList);
	for (;it.current();++it) {
		list.append(it.current()->protocol);
		list.append(it.current()->extension.pattern());
	}
	ConfigFile->writeEntry("ArchiveFilter",list);
	ConfigFile->writeEntry("Shell",Shell);
	ConfigFile->writeEntry("StartupDir",StartupDir);
}

void KExplorer::loadDevices()
{
	DirectoryTree->addItem((DirViewItem*)0,i18n("My_Computer"),0,IconLoader->loadMiniIcon("background.xpm"),IconLoader->loadMiniIcon("background.xpm"),FALSE,FALSE);
	DirectoryTree->addItem((DirViewItem*)0,i18n("Remote_Computer"),0,IconLoader->loadMiniIcon("network_settings.xpm"),IconLoader->loadMiniIcon("network_settings.xpm"),FALSE,FALSE);
	ConfigFile->setGroup("Devices");
	int		n = ConfigFile->readNumEntry("NumberOfDevices",0);
	if (n > 0) {
		Device	*dev;
		Protocol	*prot = 0;
		QStrList	list;
		ConfigFile->readListEntry("Devices",list);
		for (int i=0;i<n;i++) {
			int	offset = i*8;
			QString	name(list.at(offset+1));
			if (strcmp(list.at(offset+0),"File") == 0) prot = Manager->createProtocol(Protocol::File,list.at(offset+2));
			else if (strcmp(list.at(offset+0),"Mount") == 0) prot = Manager->createProtocol(Protocol::Mount,list.at(offset+2),list.at(offset+3),list.at(offset+4));
			else if (strcmp(list.at(offset+0),"Ftp") == 0) prot = Manager->createProtocol(Protocol::Ftp,list.at(offset+2),list.at(offset+3),list.at(offset+4),list.at(offset+5),list.at(offset+6));
			else if (strcmp(list.at(offset+0),"Trash") == 0) { prot = Manager->createProtocol(Protocol::Trash,list.at(offset+2)); name = i18n("Trash");}
			dev = new Device(name.data(),list.at(offset+7),prot,TRUE,list.at(offset+2),list.at(offset+3),list.at(offset+4),list.at(offset+5),list.at(offset+6));
			QString	icon(list.at(offset+7)),iconSel;
			if (dev->type() == Protocol::Trash)
				icon = (((TrashProtocol*)prot)->isEmpty() ? "kfm_trash.xpm" : "kfm_fulltrash.xpm");
			if (icon == "folder.xpm") iconSel = "folder_open.xpm";
			else iconSel = icon.data();
			DeviceList.append(dev);
			if (dev->type() != Protocol::Ftp) {
				int	itemType = DirNormal;
				if (dev->type() == Protocol::Mount && ((MountProtocol*)prot)->isMounted()) itemType = DirMount;
				DirectoryTree->addItem(i18n("Desktop/My_Computer/"),name.data(),dev->path().data(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(iconSel.data()),TRUE,TRUE,itemType);
			}
			else DirectoryTree->addItem(i18n("Desktop/Remote_Computer/"),list.at(offset+1),dev->path().data(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(iconSel.data()),TRUE,TRUE,DirNormal,FALSE);
		}
	}
	else {		// init defaults devices under KDE
		Device	*dev;
		Protocol	*prot;
		// "Root" device
		prot = Manager->createProtocol(Protocol::File,"/");
		dev = new Device("Root","folder.xpm",prot,TRUE,"/","","","","");
		DeviceList.append(dev);
		DirectoryTree->addItem(i18n("Desktop/My_Computer/"),"Root","file:/",IconLoader->loadMiniIcon("folder.xpm"),IconLoader->loadMiniIcon("folder_open.xpm"),TRUE);
		// "Home" device
		QString		home(getenv("HOME"));
		if (!home.isEmpty()) {
			if (home[home.length()-1] != '/') home += "/";
			prot = Manager->createProtocol(Protocol::File,home.data());
			dev = new Device("Home","folder.xpm",prot,TRUE,home.data(),"","","","");
			DeviceList.append(dev);
			QString		tmp("file:");
			tmp += home;
			DirectoryTree->addItem(i18n("Desktop/My_Computer/"),"Home",tmp.data(),IconLoader->loadMiniIcon("folder.xpm"),IconLoader->loadMiniIcon("folder_open.xpm"),TRUE);
		}
		// "Trash" device
		if (!home.isEmpty()) {
			QString	tmp(home.data());
			tmp += "Desktop/Trash/";
			prot = Manager->createProtocol(Protocol::Trash,tmp.data());
			QString	icon = (((TrashProtocol*)prot)->isEmpty() ? "kfm_trash.xpm" : "kfm_fulltrash.xpm");
			dev = new Device(i18n("Trash"),"kfm_trash.xpm",prot,TRUE,tmp.data(),"","","","");
			DeviceList.append(dev);
			QString		tmp2("file:");
			tmp2 += tmp;
			DirectoryTree->addItem(i18n("Desktop/My_Computer/"),i18n("Trash"),tmp2.data(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(icon.data()),TRUE);
		}
	}
}

void KExplorer::saveDevices()
{
	QListIterator<Device>	it(DeviceList);
	int	index = 0;
	ConfigFile->setGroup("Devices");
	QStrList	list;
	for (;it.current();++it) {
		if (!it.current()->keep()) continue;
		switch (it.current()->type()) {
		   case Protocol::File:
			list.append("File");
			break;
		   case Protocol::Mount:
			list.append("Mount");
			break;
		   case Protocol::Ftp:
			list.append("Ftp");
			break;
		   case Protocol::Trash:
			list.append("Trash");
			break;
		}
		list.append(it.current()->name().data());
		for (int i=0;i<5;i++) list.append(it.current()->string(i).data());
		list.append(it.current()->icon().data());
		index++;
	}
	ConfigFile->writeEntry("NumberOfDevices",index);
	ConfigFile->writeEntry("Devices",list);
}

void KExplorer::setupMimeTypes()
{
	// Purge existing configuration
	ExtensionDict->clear();
	FilenameDict->clear();
	ExtensionList->clear();
	ApplicationDict->clear();
	ApplicationList->clear();

	// First load extensions
	if (UseKDEMimeTypes) {
		scanMimeDir(KApplication::localkdedir() + "/share/mimelnk");
		scanMimeDir(KApplication::kde_mimedir());
	}
	else {
		QString	file = ExtensionFile.data();
		KMimeExtension	*item;
		if (!file.isEmpty()) {
			QFile	f(file);
			f.open(IO_ReadOnly | IO_Translate);
			char	buffer[1024];
			QString		str[6],ext;
			while (f.readLine(buffer,1024) > 1) {
				char	*c = strtok(buffer,"\t\n\r");
				for (int i=0;i<6;i++,c=strtok(0,"\t\n\r")) str[i] = c;
				item = new KMimeExtension(str[5],str[0],str[1],str[2],str[3],(str[4] == "noshell" ? FALSE : TRUE));
				ExtensionList->inSort(item);
				for (int i=0;i<item->nExtension();i++)
					if (strncmp(item->extension(i),"*.",2) == 0) ExtensionDict->insert(item->extension(i)+2,item);
					else if (FilenameDict->findRef(item) == -1) FilenameDict->append(item);
				if (!item->MimeName.isEmpty()) ExtensionDict->insert(item->MimeName.data(),item);
			}
		}
		else QMessageBox::critical(this,i18n("Error"),i18n("Can't open extension file"),QMessageBox::Ok | QMessageBox::Default,0);
	}

	// Then load applications and associate with mime types
	scanAppLnkDir(KApplication::kde_appsdir());
	scanAppLnkDir(KApplication::localkdedir() + "/share/applnk/");
	if (UseKDEMimeTypes) associateMimeTypes(ApplicationList,ExtensionDict);
}

void KExplorer::saveMimeTypes()
{ // Only save if using non KDE mime types
	if (UseKDEMimeTypes) return;
	if (!ExtensionFile.isEmpty()) {
		QFile	f(ExtensionFile.data());
		if (f.open(IO_WriteOnly | IO_Translate)) {
			QTextStream	t(&f);
			KMimeExtListIterator	it(*ExtensionList);
			for (;it.current();++it) {
				QStrListIterator	lit(it.current()->Extensions);
				if (lit.current() == 0) t << ';';
				for (;lit.current();++lit) { t << lit.current() << ';';}
				t << '\t';
				t << it.current()->Application.data() << '\t';
				t << it.current()->Description.data() << '\t';
				t << it.current()->MimeIcon.data() << '\t';
				t << (it.current()->inShell ? "inshell" : "noshell") << '\t';
				t << (it.current()->MimeName.isEmpty() ? "none" : it.current()->MimeName.data()) << endl;
			}
			f.close();
		}
		else QMessageBox::critical(this,i18n("Error"),i18n("Unable to save extension file"),QMessageBox::Ok | QMessageBox::Default,0);
	}
}

void KExplorer::scanAppLnkDir(const QString& dirName)
{
	QDir	dir(dirName);
	if (!dir.exists()) return;
	QString	tmp(dir.dirName());
	if (tmp == "Games" || tmp == "Settings" || tmp == "System") return;
	const QFileInfoList	*list = dir.entryInfoList("*.kdelnk",QDir::Files,QDir::Name);
	QFileInfoListIterator	it(*list);
	for (;it.current();++it) {
		KMimeApplication	*item = new KMimeApplication(it.current()->absFilePath());
		ApplicationList->inSort(item);
		for (int i=0;i<item->nMimeType();i++) ApplicationDict->insert(item->mimeType(i),item);
	}
	list = dir.entryInfoList(QDir::Dirs,QDir::Name);
	it.toFirst(); it += 2;
	for (;it.current();++it) scanAppLnkDir(it.current()->absFilePath());
}

void KExplorer::scanMimeDir(const QString& dirName)
{
	QDir	dir(dirName);
	if (!dir.exists()) return;
	const QFileInfoList	*list = dir.entryInfoList("*.kdelnk",QDir::Files,QDir::Name);
	QFileInfoListIterator	it(*list);
	for (;it.current();++it) {
		KMimeExtension	*item = new KMimeExtension(it.current()->absFilePath());
		ExtensionList->inSort(item);
		for (int i=0;i<item->nExtension();i++)
			if (strncmp(item->extension(i),"*.",2) == 0) ExtensionDict->insert(item->extension(i)+2,item);
			else if (FilenameDict->findRef(item) == -1) FilenameDict->append(item);
		if (!item->MimeName.isEmpty()) ExtensionDict->insert(item->MimeName.data(),item);
	}
	list = dir.entryInfoList(QDir::Dirs,QDir::Name);
	it.toFirst(); it += 2;
	for (;it.current();++it) scanMimeDir(it.current()->absFilePath());
}

void KExplorer::mainCallback()
{
	QMessageBox::information(this,i18n("Information"),i18n("Sorry, not implemented yet"), QMessageBox::Ok | QMessageBox::Default,0);
}

void KExplorer::scanDirectory(DirViewItem *item)
{
	if (Busy) return;
cout << "scanning " << item->Address << endl;
	LastPath = item->Address.data();
	ConfigFile->setGroup("Configuration");
	ConfigFile->writeEntry("LastPath",LastPath);
	FileList->clear();
	if (item->Depth == 0) listDesktop();
	else if (item->Depth == 1) {
		if (item->Label == i18n("My_Computer")) listDevices(TRUE);
		else listDevices(FALSE);
	}
	if (item->Address.isEmpty()) {
		FileView->setFileList(FileList);
		return;
	}
	initBusy();
	KURL	url(item->Address.data());
	Protocol	*prot = Manager->searchProtocol(url);
	if (!prot) prot = createArchiveProtocol(url);
	if (prot == 0) { finishBusy(); return;}
	if (item->Depth == 2 && prot->type() == Protocol::Mount && !((MountProtocol*)prot)->isMounted()) {
		TmpDevice = item;
		mount();
	}
cout << "start thread" << endl;
	const FileInfoList	*list = Manager->list(prot,url,ShowHiddenFiles);
cout << "thread finished\nstarting processing" << endl;
	if (list) {
		FileList->setSorting(Sorting);
		FileInfoListIterator	it(*list);
		QString		icon;
		FileInfo	*fi;
		bool		created(FALSE);
		for (;it.current();++it) {
			fi = new FileInfo(*(it.current()));
			if (fi->mimeType()) {
				icon = fi->mimeType()->MimeIcon.data();
				if (strncmp(fi->mimeType()->MimeName.data(),"image/",6) == 0 && !created && (created=createXVPICSDir(url))) ;
			}
			else if (fi->isDir()) {
				if (fi->isReadable()) icon = "folder.xpm";
				else icon = "lockedfolder.xpm";
			}
			else icon = "unknown.xpm";
			fi->setIcons(IconLoader->loadIcon(icon.data(),"unknown.xpm"),IconLoader->loadMiniIcon(icon.data(),"unknown.xpm"));
			FileList->inSort(fi);
		}
		FileInfoListIterator	it2(*FileList);
		for (int i=0;it2.current();++it2,i++) it2.current()->setIndex(i);
	}
cout << "process finished" << endl;
	FileView->setFileList(FileList);
	QString		str(i18n("Content of ")), str2;
	uint		free(prot->freeSize(url.path()));
	str += url.path();
	RightViewInfo->setText(str.data());
	str.setNum(FileList->count());
	str += i18n(" objects");
	Status1Info->setText(str.data());
	str2.setNum(free);
	str = i18n("Free space : ") + processSize(free);
//	str += " Kbytes";
	Status2Info->setText(str.data());
	finishBusy();
}

void KExplorer::scanSubDirectories(DirViewItem *item)
{
cout << "scanning subdirs of " << item->Label << endl;
	if (Busy) return;
	if (item->Depth < 2 || item->Address.isEmpty()) return;
	initBusy();
	KURL	url(item->Address.data());
	Protocol	*prot = Manager->searchProtocol(url);
	if (!prot) prot = createArchiveProtocol(url);
	if (prot == 0) { finishBusy(); return;}
	if (item->Depth == 2 && prot->type() == Protocol::Mount && !((MountProtocol*)prot)->isMounted()) {
		TmpDevice = item;
		mount();
	}
	const FileInfoList	*list = Manager->listSubDirs(prot,url,ShowHiddenFiles,ShowArchive);
	if (list) {
		FileInfoListIterator	it(*list);
		QString		icon, iconSel;
		int	type;
		for (;it.current();++it) {
			if (it.current()->isDir()) {
				if (!it.current()->isReadable()) { icon = "lockedfolder.xpm"; iconSel = icon.data();}
				else { icon = "folder.xpm"; iconSel = "folder_open.xpm";}
			}
			else icon = "tgz.xpm", iconSel = "tgz.xpm";
			it.current()->setIcons(IconLoader->loadIcon(icon.data(),"unknown.xpm"),IconLoader->loadMiniIcon(icon.data(),"unknown.xpm"));
			if (it.current()->isSymLink()) type = DirLink;
			else type = DirNormal;
			KURL	url(it.current()->absFilePath().data());
//			bool	hasExpand = (ShowArchive ? TRUE : prot->hasChilds(url.path()));
			bool	hasExpand = (it.current()->isDir() ? prot->hasChilds(url.path()) : TRUE);
			DirectoryTree->addItem(item,it.current()->fileName().data(),it.current()->absFilePath().data(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(iconSel.data()),TRUE,hasExpand,type,it.atLast());
		}
		item->HasChilds = prot->hasChilds(url.path());
		item->ChildsScanned = TRUE;
	}
	finishBusy();
}

void KExplorer::listDevices(bool local)
{
	QListIterator<Device>	it(DeviceList);
	FileInfo	*fi;
	QString		str("drwxrwxrwx 1 root root 0 " + getTime() + " "), tmp;
	int		index(0);
	for (;it.current();++it) {
		if (local && !it.current()->protocol()->isLocal()) continue;
		else if (!local && it.current()->protocol()->isLocal()) continue;
		tmp = str.data();
		tmp += it.current()->name();
		fi = new FileInfo(tmp.data(),1);
		fi->setIcons(IconLoader->loadIcon(it.current()->icon().data()),IconLoader->loadMiniIcon(it.current()->icon().data()));
		QString		descr;
		switch (it.current()->type()) {
		   case Protocol::File: descr = i18n("Folder"); break;
		   case Protocol::Mount: descr = i18n("Mountable"); break;
		   case Protocol::Ftp: descr = i18n("Ftp"); break;
		   case Protocol::Trash: descr = i18n("Trash"); break;
		}
		fi->setDescription(descr.data());
		fi->setPath(it.current()->path());
		fi->setIndex(index++);
		FileList->append(fi);
	}
	QString		str1(i18n("Content of ")), str2;
	if (local) str1 += i18n("My_Computer");
	else str1 += i18n("Remote_Computer");
	RightViewInfo->setText(str1.data());
	str2.setNum(index);
	str2 += i18n(" objects");
	Status1Info->setText(str2.data());
	Status2Info->setText("");
}

void KExplorer::listDesktop()
{
	QString		str("drwxrwxrwx 1 root root 0 " + getTime() + " "), tmp;
	tmp = str.data();
	tmp += i18n("My_Computer");
	tmp += '/';
	FileInfo	*fi = new FileInfo(tmp.data(),1);
	fi->setIcons(IconLoader->loadIcon("background.xpm"),IconLoader->loadMiniIcon("background.xpm"));
	fi->setDescription(i18n("Local devices repository"));
	fi->setPath("file:/");
	fi->setIndex(0);
	FileList->append(fi);
	tmp = str.data();
	tmp += i18n("Remote_Computer");
	tmp += '/';
	fi = new FileInfo(tmp.data(),1);
	fi->setIcons(IconLoader->loadIcon("network_settings.xpm"),IconLoader->loadMiniIcon("network_settings.xpm"));
	fi->setDescription(i18n("Remote devices repository"));
	fi->setPath("file:/");
	fi->setIndex(1);
	FileList->append(fi);
	QString		str1(i18n("Content of "));
	str1 += i18n("Desktop");
	RightViewInfo->setText(str1.data());
	Status1Info->setText("");
	Status2Info->setText("");
}

void KExplorer::bigIcons()
{
	if (Style == BIGICON_ID) {
		ToolBar->setButton(BIGICON_ID,TRUE);
		return;
	}
	MenuBar->setItemChecked(Style,FALSE);
	MenuBar->setItemChecked(BIGICON_ID,TRUE);
	ToolBar->setButton(Style,FALSE);
	ToolBar->setButton(BIGICON_ID,TRUE);
	destroyFileView();
	Style = BIGICON_ID;
	createFileView();
	FileView->setLinkArrow(IconLoader->loadIcon("link.xpm"));
	FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
	FileView->setFileList(FileList);
	saveConfiguration();
}

void KExplorer::listIcons()
{
	if (Style == LISTICON_ID) {
		ToolBar->setButton(LISTICON_ID,TRUE);
		return;
	}
	MenuBar->setItemChecked(Style,FALSE);
	MenuBar->setItemChecked(LISTICON_ID,TRUE);
	ToolBar->setButton(Style,FALSE);
	ToolBar->setButton(LISTICON_ID,TRUE);
	destroyFileView();
	Style = LISTICON_ID;
	createFileView();
	FileView->setLinkArrow(IconLoader->loadMiniIcon("link.xpm"));
	FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
	FileView->setFileList(FileList);
	saveConfiguration();
}

void KExplorer::smallIcons()
{
	if (Style == SMALLICON_ID) {
		ToolBar->setButton(SMALLICON_ID,TRUE);
		return;
	}
	MenuBar->setItemChecked(Style,FALSE);
	MenuBar->setItemChecked(SMALLICON_ID,TRUE);
	ToolBar->setButton(Style,FALSE);
	ToolBar->setButton(SMALLICON_ID,TRUE);
	destroyFileView();
	Style = SMALLICON_ID;
	createFileView();
	FileView->setLinkArrow(IconLoader->loadMiniIcon("link.xpm"));
	FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
	FileView->setFileList(FileList);
	saveConfiguration();
}

void KExplorer::detailIcons()
{
	if (Style == DETAILICON_ID) {
		ToolBar->setButton(DETAILICON_ID,TRUE);
		return;
	}
	MenuBar->setItemChecked(Style,FALSE);
	MenuBar->setItemChecked(DETAILICON_ID,TRUE);
	ToolBar->setButton(Style,FALSE);
	ToolBar->setButton(DETAILICON_ID,TRUE);
	destroyFileView();
	Style = DETAILICON_ID;
	createFileView();
	FileView->setLinkArrow(IconLoader->loadMiniIcon("link.xpm"));
	FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
	FileView->setFileList(FileList);
	saveConfiguration();
}

void KExplorer::openItem(FileInfo *item)
{
	if (Busy) return;
	KURL	url(item->absFilePath());
	if (item->isDir()) DirectoryTree->cdDown(item->fileName());
	else if (item->mimeType()) {
		if (item->mimeType()->MimeName == "application/x-executable") {
			KProcess	proc;
			QString		cmd(item->absFilePath().data());
			proc << cmd.right(cmd.length()-cmd.find(':')-1).data();
			proc.start(KProcess::DontCare,KProcess::NoCommunication);
		}
		else if (item->mimeType()->MimeName == "application/x-shellscript")
			executeAction("%shell -caption \"%c\" -e %f",url);
		else if (item->mimeType()->Application != "None")
			executeAction(item->mimeType()->Application.data(),url);
		else openWith();
	}
	else openWith();
}

void KExplorer::openArchive()
{ DirectoryTree->cdDown(FileView->getSelected()->at(0)->fileName());}

void KExplorer::executeAction(const char *str, KURL& url)
{
	QString		cmd(str);
	KProcess	proc;
	char		*c = strtok(cmd.data()," ");
	Protocol	*prot = Manager->searchProtocol(url);
	QString		fileTmp(Manager->getFile(prot,url));
	bool		needFile = TRUE;
	while (c) {
		if (strcmp(c,"%u") == 0) proc << fileTmp, needFile = FALSE;
		else if (strcmp(c,"%f") == 0) proc << fileTmp, needFile = FALSE;
		else if (strcmp(c,"%m") == 0 || strcmp(c,"%i") == 0) ;	// nothing to do
		else if (strcmp(c,"\"%c\"") == 0) {
			QString		tmp("\"");
			tmp += fileTmp;
			tmp += "\"";
			proc << tmp.data();
		}
		else if (strcmp(c,"%shell") == 0) proc << Shell.data();
		else proc << c;
		c = strtok(0," ");
	}
	if (needFile) proc << fileTmp;
	proc.start(KProcess::DontCare,KProcess::NoCommunication);
}

void KExplorer::destroyFileView()
{
	if (Style == DETAILICON_ID) {
		((KDetailList*)FileView)->getColumns(ColType,ColWidth);
		RightSubView->disactivate();
		RightView->disactivate();
		delete RightSubView;
	}
	else {
		RightView->disactivate();
		delete FileView;
	}
}

void KExplorer::createFileView()
{
	if (Style == DETAILICON_ID) {
		RightSubView = new KFixPanner(RightView,KFixPanner::Horizontal);
		FileHeader = new KFileHeader(RightSubView);
		FileHeader->resize(450,20);
		FileView = new KDetailList(DateFormat,RightSubView);
		((KDetailList*)FileView)->setColumns(ColType,ColWidth);
		FileHeader->setColumns(ColType,ColWidth,ColName);
		QObject::connect(FileView,SIGNAL(hScroll(int)),FileHeader,SLOT(setHScrollValue(int)));
		QObject::connect(FileHeader,SIGNAL(changeColWidth(int,int)),FileView,SLOT(setColumnWidth(int,int)));
		connect(FileHeader,SIGNAL(columnPressed(int)),SLOT(columnPressed(int)));
		RightSubView->activate(FileHeader,FileView);
		RightView->activate(RightViewInfo,RightSubView);
		RightSubView->show();
		FileHeader->show();
		FileView->show();
	}
	else {
		switch (Style) {
		   case BIGICON_ID: FileView = new KBigIconList(
// OLE
								ShowMiniImages,
// OLE
										RightView);
// MG
				    connect(FileView,SIGNAL(requestMiniImage(FileInfo*)),SLOT(miniImageRequested(FileInfo*)));
// MG
				    break;
		   case LISTICON_ID:
		   case SMALLICON_ID: FileView = new KSmallIconList(RightView); break;
		}
		RightView->activate(RightViewInfo,FileView);
		FileView->show();
	}
	connect(FileView,SIGNAL(openItem(FileInfo*)),SLOT(openItem(FileInfo*)));
	connect(FileView,SIGNAL(popup()),SLOT(popupFileView()));
	connect(FileView,SIGNAL(selectionChanged()),SLOT(selectionChanged()));
	connect(FileView,SIGNAL(renameItem(FileInfo*,const QString&)),SLOT(renameItem(FileInfo*,const QString&)));
}

void KExplorer::columnPressed(int col)
{
	switch (col) {
	   case 0: listByName(); break;
	   case 1: listBySize(); break;
	   case 2: listByType(); break;
	   case 3: listByDate(); break;
	}
}

void KExplorer::resortFileList()
{
	FileInfoList	*newList = new FileInfoList(Sorting);
	FileInfoListIterator	it(*FileList);
	for (;it.current();++it) newList->inSort(it.current());
	FileList->setAutoDelete(FALSE);
	newList->setAutoDelete(TRUE);
	delete FileList;
	FileList = newList;
	FileInfoListIterator	it2(*FileList);
	for (int i=0;it2.current();++it2,i++) it2.current()->setIndex(i);
	FileView->setFileList(FileList);
}

void KExplorer::listByName()
{
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,FALSE);
	Sorting = byName;
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,TRUE);
	resortFileList();
}

void KExplorer::listBySize()
{
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,FALSE);
	Sorting = bySize;
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,TRUE);
	resortFileList();
}

void KExplorer::listByType()
{
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,FALSE);
	Sorting = byType;
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,TRUE);
	resortFileList();
}

void KExplorer::listByDate()
{
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,FALSE);
	Sorting = byTime;
	MenuBar->setItemChecked(Sorting+LISTNAME_ID,TRUE);
	resortFileList();
}

void KExplorer::cut()
{
	if (Busy) return;
	FileInfoListIterator	iter(*FileList);
	for (;iter.current();++iter) iter.current()->setCutted(FALSE);
	FileInfoList	*list = FileView->getSelected();
	if (list->count() < 1) return;
	URLList.clear();
	FileInfoListIterator	it(*list);
	for (;it.current();++it) {
		URLList.append(it.current()->absFilePath().data());
		it.current()->setCutted(TRUE);
//		FileList->removeRef(it.current());
	}
	Cutted = TRUE;
//	FileInfoListIterator	it2(*FileList);
//	for (int i=0;it2.current();++it2,i++) it2.current()->setIndex(i);
	FileView->setFileList(FileList);
}

void KExplorer::copy()
{
	if (Busy) return;
	FileInfoListIterator	iter(*FileList);
	for (;iter.current();++iter) iter.current()->setCutted(FALSE);
	FileInfoList	*list = FileView->getSelected();
	if (list->count() < 1) return;
	URLList.clear();
	FileInfoListIterator	it(*list);
	for (;it.current();++it) URLList.append(it.current()->absFilePath().data());
	Cutted = FALSE;
	FileView->setFileList(FileList,TRUE);
}

void KExplorer::paste()
{
	if (Busy) return;
	initBusy();
	if (Cutted) {
		if (Manager->move(URLList,DirectoryTree->currentItem()->Address.data())) removeURLs();
	}
	else Manager->copy(URLList,DirectoryTree->currentItem()->Address.data());
	if (DirectoryTree->currentItem()->Opened && containDirs(URLList)) DirectoryTree->rescanChilds(DirectoryTree->currentItem());
	else updateHasChilds(DirectoryTree->currentItem());
	finishBusy();
	scanDirectory(DirectoryTree->currentItem());
}

void KExplorer::remove()
{
	if (Busy) return;
	FileInfoList	*list = FileView->getSelected();
	if (list->count() < 1) return;
	Protocol	*prot = Manager->searchProtocol(KURL(list->at(0)->absFilePath().data()));
	if (prot) {
		int	res = QMessageBox::warning(this,i18n("Warning"),i18n("Do you really want to delete the selected files ?"),QMessageBox::Yes | QMessageBox::Default,QMessageBox::Cancel);
		if (res != QMessageBox::Yes) return;
		initBusy();
		FileInfoListIterator	it(*list);
		bool			ok = TRUE;
		SubProtocol		*subProt;
		for (;it.current();++it) {
			KURL	url(it.current()->absFilePath().data());
			if (it.current()->isDir() && !it.current()->isSymLink()) ok = Manager->rmdir(prot,url);
			else ok = Manager->remove(prot,url);
			if (!ok) break;
			else if (it.current()->isDir()) DirectoryTree->removeItem(it.current()->absFilePath().data());
			else if (ShowArchive && (subProt=matchFileName(it.current()->fileName().data(),ProtList)) != 0) {
				QString		str = it.current()->absFilePath().data();
				str += '#';
				str += subProt->protocol;
				str += ':';
				DirectoryTree->removeItem(str.data());
			}
		}
		DirectoryTree->refreshItem(DirectoryTree->currentItem()->Address.data());
		DirectoryTree->refresh();
		finishBusy();
		if (!ok) {
			QString		msg(i18n("Unable to delete "));
			msg += it.current()->absFilePath().data();
			QMessageBox::critical(this,i18n("Error"),msg.data(),QMessageBox::Ok | QMessageBox::Default,0);
		}
	}
	scanDirectory(DirectoryTree->currentItem());
}

void KExplorer::property()
{
	if (Busy) return;
	FileInfoList	*list = FileView->getSelected();
	if (list->count() < 1) return;
	if (list->count() > 1) {
		QMessageBox::critical(this,i18n("Error"),i18n("Can't display properties for more than one file"),QMessageBox::Ok | QMessageBox::Default,0);
		return;
	}
	PropertyDlg	*Dlg = new PropertyDlg(list->at(0),this);
	if (Dlg->exec() && Dlg->isChanged())
		if (!Manager->chmod(list->at(0)->absFilePath().data(),Dlg->permissions()))
			QMessageBox::critical(this,i18n("Error"),i18n("Unable to change permissions"),QMessageBox::Ok | QMessageBox::Default,0);
		else scanDirectory(DirectoryTree->currentItem());
	delete Dlg;
}

void KExplorer::newDevice()
{
	if (Busy) return;
	initBusy();
	DeviceDlg	*Dlg = new DeviceDlg(this);
	char		*icons[6] = {"folder.xpm","3floppy_unmount.xpm","cdrom_unmount.xpm","background.xpm","socket.xpm","kfm_trash.xpm"};
	for (int i=0;i<6;i++) Dlg->insertIcon(IconLoader->loadMiniIcon(icons[i]));
	if (Dlg->exec()) {
		switch (Dlg->type()) {
		   case 0:	// Folder device
		      { QString		tmp(Dlg->path());
			processPath(tmp);
			if (tmp[tmp.length()-1] != '/') tmp += "/";
			Protocol	*prot = Manager->createProtocol(Protocol::File,tmp.data());
			QString		icon(icons[Dlg->icon()]),iconSel;
			if (icon == "folder.xpm") iconSel = "folder_open.xpm";
			else iconSel = icon.data();
			Device	*dev = new Device(Dlg->name(),icon.data(),prot,Dlg->keep(),tmp.data(),"","","","");
			DeviceList.append(dev);
			DirectoryTree->addItem(i18n("Desktop/My_Computer/"),Dlg->name(),dev->path(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(iconSel.data()),TRUE);
			break;
		      }
		   case 1:	// Mount device
		      {	QString		tmp(Dlg->host());
			processPath(tmp);
			Protocol	*prot = Manager->createProtocol(Protocol::Mount,Dlg->path(),tmp.data(),Dlg->login());
			QString		icon(icons[Dlg->icon()]), iconSel;
			if (icon == "folder.xpm") iconSel = "folder_open.xpm";
			else iconSel = icon.data();
			Device	*dev = new Device(Dlg->name(),icon.data(),prot,Dlg->keep(),Dlg->path(),tmp.data(),Dlg->login(),"","");
			DeviceList.append(dev);
			int	itemType = (((MountProtocol*)prot)->isMounted() ? DirMount : DirNormal);
			DirectoryTree->addItem(i18n("Desktop/My_Computer/"),Dlg->name(),dev->path(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(iconSel.data()),TRUE,TRUE,itemType);
			break;
		      }
		   case 2:	// Ftp device
		      {	Protocol	*prot(0);
			if (Dlg->anonymous()) prot = Manager->createProtocol(Protocol::Ftp,Dlg->host(),Dlg->path(),0,0,Dlg->port());
			else prot = Manager->createProtocol(Protocol::Ftp,Dlg->host(),Dlg->path(),Dlg->login(),Dlg->passwd(),Dlg->port());
			QString		icon(icons[Dlg->icon()]), iconSel;
			if (icon == "folder.xpm") iconSel = "folder_open.xpm";
			else iconSel = icon.data();
			Device	*dev = new Device(Dlg->name(),icon.data(),prot,Dlg->keep(),Dlg->host(),Dlg->path(),Dlg->login(),Dlg->passwd(),Dlg->port());
			DeviceList.append(dev);
			DirectoryTree->addItem(i18n("Desktop/Remote_Computer/"),Dlg->name(),dev->path(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(iconSel.data()),TRUE,TRUE,DirNormal,FALSE);
			break;
		      }
		   case 3:	// Trash device
		      {	if (findTrash() != 0) {
				QMessageBox::critical(this,i18n("Error"),i18n("There can be only one trash !"),QMessageBox::Ok | QMessageBox::Default,0);
				break;
			}
			QString		tmp(Dlg->path());
			processPath(tmp);
			if (tmp[tmp.length()-1] != '/') tmp += "/";
			Protocol	*prot = Manager->createProtocol(Protocol::Trash,tmp.data());
			QString		icon = (((TrashProtocol*)prot)->isEmpty() ? "kfm_trash.xpm" : "kfm_fulltrash.xpm");
			Device	*dev = new Device(i18n("Trash"),icon.data(),prot,Dlg->keep(),tmp.data(),"","","","");
			DeviceList.append(dev);
			DirectoryTree->addItem(i18n("Desktop/My_Computer/"),i18n("Trash"),dev->path(),IconLoader->loadMiniIcon(icon.data()),IconLoader->loadMiniIcon(icon.data()),TRUE);
			break;
		      }
		}
		saveDevices();
	}
	delete Dlg;
	finishBusy();
}

void KExplorer::removeDevice()
{
	if (Busy) return;
	Device	*dev = (TmpDevice ? findDevice(TmpDevice->Label.data()) : 0);
	if (dev == 0) {
		DeviceDelDlg	*Dlg = new DeviceDelDlg(this);
		QListIterator<Device>	it(DeviceList);
		for (it.toLast();it.current();--it) Dlg->insertDevice(it.current()->name().data(),it.current()->type(),it.current()->path().data(),IconLoader->loadMiniIcon(it.current()->icon().data()));
		if (Dlg->exec()) {
			dev = findDevice(Dlg->selected());
		}
		delete Dlg;
	}
	if (dev != 0) {
		QString		parent(i18n("Desktop"));
		parent += "/";
		if (dev->type() == Protocol::Ftp) parent += i18n("Remote_Computer");
		else parent += i18n("My_Computer");
		parent += "/";
		DirectoryTree->removeItem(parent.data(),dev->name().data());
		Manager->deleteProtocol(dev->protocol());
		DeviceList.removeRef(dev);
		saveDevices();
	}
}

Device* KExplorer::findDevice(const char *name)
{
	QListIterator<Device>	it(DeviceList);
	for (;it.current(); ++it)
		if (it.current()->name() == name) break;
	return it.current();
}

Device* KExplorer::findDevice(Protocol *prot)
{
	QListIterator<Device>	it(DeviceList);
	for (;it.current(); ++it)
		if (it.current()->protocol() == prot) break;
	return it.current();
}

void KExplorer::shutdown()
{
	saveConfiguration();
	saveDevices();
	delete Manager;
	kapp->quit();
}

void KExplorer::toggleToolBar()
{
	ToolBarEnabled = !ToolBarEnabled;
	MenuBar->setItemChecked(TOOLBAR_ID,ToolBarEnabled);
	enableToolBar();
	saveConfiguration();
}

void KExplorer::toggleStatusBar()
{
	StatusBarEnabled = !StatusBarEnabled;
	MenuBar->setItemChecked(STATUSBAR_ID,StatusBarEnabled);
	enableStatusBar();
	saveConfiguration();
}

void KExplorer::popupFileView()
{
	FileInfoList	*list = FileView->getSelected();
	Pop1->clear();
	if (list->count() == 0) {
		Pop2->clear();
		Pop2->insertItem(i18n("Big icons"),this,SLOT(bigIcons()),0,BIGICON_ID);
		Pop2->insertItem(i18n("List icons"),this,SLOT(listIcons()),0,LISTICON_ID);
		Pop2->insertItem(i18n("Small icons"),this,SLOT(smallIcons()),0,SMALLICON_ID);
		Pop2->insertItem(i18n("Details"),this,SLOT(detailIcons()),0,DETAILICON_ID);
		Pop2->setCheckable(TRUE);
		Pop2->setItemChecked(Style,TRUE);
		Pop1->insertItem(i18n("View"),Pop2);
		Pop1->insertSeparator();
		Pop3->clear();
		Pop3->insertItem(i18n("by name"),this,SLOT(listByName()),0,LISTNAME_ID);
		Pop3->insertItem(i18n("by size"),this,SLOT(listBySize()),0,LISTSIZE_ID);
		Pop3->insertItem(i18n("by type"),this,SLOT(listByType()),0,LISTTYPE_ID);
		Pop3->insertItem(i18n("by date"),this,SLOT(listByDate()),0,LISTDATE_ID);
		Pop3->setCheckable(TRUE);
		Pop3->setItemChecked(Sorting+LISTNAME_ID,TRUE);
		Pop1->insertItem(i18n("Sort icons"),Pop3);
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Paste"),this,SLOT(paste()));
		Pop1->insertItem(i18n("Paste as link"),this,SLOT(mainCallback()));
		Pop1->insertSeparator();
		if (DirectoryTree->currentItem()->Address.right(8) == ".xvpics/") {
			Pop1->insertItem(i18n("Select outdated thumbnails"),this,SLOT(selectOutdatedThumbnails()));
			Pop1->insertSeparator();
		}
		Pop4->clear();
		Pop4->insertItem(i18n("Directory"),this,SLOT(newDir()));
		Pop4->insertItem(i18n("Device"),this,SLOT(newDevice()));
		Pop4->insertItem(i18n("Symbolic link"),this,SLOT(mainCallback()));
		Pop1->insertItem(i18n("New ..."),Pop4);
	}
	else {
		if (list->count() == 1) {
			if (list->at(0)->isDir()) Pop1->insertItem(i18n("Explore"),this,SLOT(openThisItem()));
			else {
				if (ShowArchive && matchFileName(list->at(0)->fileName().data(),ProtList)) Pop1->insertItem(i18n("Explore"),this,SLOT(openArchive()));
				KMimeExtension	*ext = list->at(0)->mimeType();
				if (ext && (ext->MimeName == "application/x-executable" || ext->MimeName == "application/x-shellscript")) Pop1->insertItem(*(IconLoader->loadMiniIcon((ext->MimeName == "application/x-executable" ? "exec.xpm" : "terminal.xpm"),"unknown.xpm")),i18n("Execute"),this,SLOT(openThisItem()));
				else if (ext == 0 || (ext->MimeApplications.count() == 0 && ext->Application =="None")) Pop1->insertItem(i18n("Open with ..."),this,SLOT(openWith()));
				else if (ext->MimeApplications.count() == 0) Pop1->insertItem(i18n("Open"),this,SLOT(openThisItem()));
				else if (ext->MimeApplications.count() == 1) {
					Pop1->insertItem(*(IconLoader->loadKDEIcon(ext->MimeApplications.at(0)->MimeIcon.data())),ext->MimeApplications.at(0)->AppName.data(),this,SLOT(openThisItem()));
				}
				else {
					Pop2->clear();
					QListIterator<KMimeApplication>		it(ext->MimeApplications);
					for (int i=0;it.current() && i<4;++it,i++) Pop2->insertItem(*(IconLoader->loadKDEIcon(it.current()->MimeIcon.data())),it.current()->AppName.data(),APPLICATION_ID+i);
					Pop1->insertItem(i18n("Open"),Pop2);
				}
				Pop1->insertItem(i18n("Edit"),this,SLOT(edit()));
			}
			Pop1->insertSeparator();
		}
		Pop1->insertItem(i18n("Cut"),this,SLOT(cut()));
		Pop1->insertItem(i18n("Copy"),this,SLOT(copy()));
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Delete"),this,SLOT(remove()));
		Pop1->insertItem(i18n("Move to trash"),this,SLOT(moveToTrash()));
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Properties"),this,SLOT(property()));
	}
	Pop1->popup(QCursor::pos());
}

void KExplorer::removeThisDevice()
{
	TmpDevice = DirectoryTree->popupItem();
	removeDevice();
	TmpDevice = 0;
}

void KExplorer::openThisItem()
{ openItem(FileView->getSelected()->at(0));}

void KExplorer::edit()
{
	if (Busy) return;
	KProcess	proc;
	KURL		url(FileView->getSelected()->at(0)->absFilePath().data());
	Protocol	*prot = Manager->searchProtocol(url);
	QString		tmp(Manager->getFile(prot,url));
	proc << "kedit" << tmp.data();
	proc.start(KProcess::DontCare,KProcess::NoCommunication);
}

void KExplorer::menuActivated(int id)
{
	if (id < APPLICATION_ID) return;
	KURL	url(FileView->getSelected()->at(0)->absFilePath().data());
	executeAction(FileView->getSelected()->at(0)->mimeType()->MimeApplications.at(id-APPLICATION_ID)->ExecString,url);
}

void KExplorer::popupDirectoryTree(DirViewItem *item)
{
	Pop1->clear();
	if (item->Depth >= 2) {
		Pop1->insertItem(i18n("Explore"),this,SLOT(explore()));
		Pop1->insertSeparator();
	}
	Pop1->insertItem(i18n("Expand"),this,SLOT(expand()));
	Pop1->insertItem(i18n("Collapse"),this,SLOT(collapse()));
	Pop1->insertItem(i18n("Refresh"),this,SLOT(refreshDir()));
	if (item->Depth == 2) {
		Device	*dev = findDevice(item->Label.data());
		if (dev->type() == Protocol::Mount) {
			Pop1->insertSeparator();
			if (((MountProtocol*)(dev->protocol()))->isMounted()) Pop1->insertItem(i18n("Unmount"),this,SLOT(umount()));
			else Pop1->insertItem(i18n("Mount"),this,SLOT(mount()));
		}
		else if (dev->type() == Protocol::Trash) {
			Pop1->insertSeparator();
			Pop1->insertItem(i18n("Empty trash"),this,SLOT(emptyTrash()));
		}
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Disconnect"),this,SLOT(removeThisDevice()));
	}
	else if (item->Depth == 1) {
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Connect new device"),this,SLOT(newDevice()));
	}
	else if (item->Depth > 2) {
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Delete"),this,SLOT(removeThisFolder()));
		Pop1->insertSeparator();
		Pop1->insertItem(i18n("Properties"),this,SLOT(propertyThisFolder()));
	}
	Pop1->popup(QCursor::pos());
}

void KExplorer::newDir()
{
	if (Busy) return;
	if (DirectoryTree->currentItem()->Depth < 2) {
		QMessageBox::critical(this,i18n("Error"),i18n("Can't create directory here"),QMessageBox::Ok | QMessageBox::Default,0);
		return;
	}
	LineDlg		*Dlg = new LineDlg(this);
	Dlg->setCaption(i18n("New directory"));
	Dlg->setLabel(i18n("Directory name :"));
	if (Dlg->exec()) {
		QString		str = DirectoryTree->currentItem()->Address.data();
		if (str[str.length()-1] != '/') str += "/";
		str += Dlg->text();
		if (str[str.length()-1] != '/') str += "/";
		if (!Manager->mkdir(str.data()))
			QMessageBox::critical(this,i18n("Error"),i18n("Unable to create directory"),QMessageBox::Ok | QMessageBox::Default,0);
		else {
			if (DirectoryTree->currentItem()->ChildsScanned && (Dlg->text()[0] != '.' || ShowHiddenFiles))
				DirectoryTree->addItem(DirectoryTree->currentItem(),Dlg->text(),str.data(),IconLoader->loadMiniIcon("folder.xpm","unknown.xpm"),IconLoader->loadMiniIcon("folder_open.xpm","unknown.xpm"),TRUE,FALSE);
			else updateHasChilds(DirectoryTree->currentItem());
//			DirectoryTree->rescanChilds(DirectoryTree->currentItem());
			scanDirectory(DirectoryTree->currentItem());
		}
	}
	delete Dlg;
}

void KExplorer::openTerminal()
{
	DirViewItem	*item = DirectoryTree->currentItem();
	QString	path("/");
	if (item && !item->Address.isEmpty() && strncmp(item->Address.data(),"file:/",6) == 0) {
		KURL	url(item->Address.data());
		path = url.path();
	}
	QString		cmd;
	cmd.sprintf("cd %s && kvt&",path.data());
	system(cmd.data());
/*	KProcess	p;
	p << "kvt";
	p.start(KProcess::DontCare,KProcess::NoCommunication);*/
}

void KExplorer::openWith()
{
	if (Busy) return;
	OpenDlg		*Dlg = new OpenDlg(ApplicationList,IconLoader,this);
	if (Dlg->exec()) {
		QString		execStr(Dlg->text());
		KURL		url(FileView->getSelected()->at(0)->absFilePath().data());
		executeAction(execStr.data(),url);
	}
	delete Dlg;
}

void KExplorer::launchFind()
{
	DirViewItem	*item = DirectoryTree->currentItem();
	QString	path("/");
	if (item && !item->Address.isEmpty() && strncmp(item->Address.data(),"file:/",6) == 0) {
		KURL	url(item->Address.data());
		path = url.path();
	}
	QString		cmd;
	cmd.sprintf("cd %s && kfind&",path.data());
	system(cmd.data());
/*	KProcess	p;
	p << "kfind";
	p.start(KProcess::DontCare,KProcess::NoCommunication);*/
}

void KExplorer::dropOnTree(QDropEvent *e, DirViewItem *item)
{
	if (item->Depth < 2) return;
	URLList.clear();
	QUrlDrag::decode(e,URLList);
	TmpItem = item;
	if (item->Depth == 2) {
		Device	*dev = findDevice(item->Label.data());
		Protocol	*prot = dev->protocol();
		if (prot->type() == Protocol::Mount && !((MountProtocol*)prot)->isMounted()) {
			TmpDevice = item;
			mount();
		}
	}
	Pop1->clear();
	Pop1->insertItem(i18n("Move"),this,SLOT(moveDrag()));
	Pop1->insertItem(i18n("Copy"),this,SLOT(copyDrag()));
	Pop1->insertSeparator();
	Pop1->insertItem(i18n("Link"),this,SLOT(mainCallback()));
	Pop1->popup(QCursor::pos());
}

void KExplorer::moveDrag()
{
	initBusy();
	if (Manager->move(URLList,TmpItem->Address.data())) removeURLs();
	finishBusy();
	if (TmpItem->Opened && containDirs(URLList)) DirectoryTree->rescanChilds(TmpItem);
	else updateHasChilds(TmpItem);
	scanDirectory(DirectoryTree->currentItem());
}

void KExplorer::copyDrag()
{
	initBusy();
	Manager->copy(URLList,TmpItem->Address.data());
	finishBusy();
	if (TmpItem->Opened && containDirs(URLList)) DirectoryTree->rescanChilds(TmpItem);
	else updateHasChilds(TmpItem);
}

void KExplorer::linkDrag()
{
}

void KExplorer::removeURLs()
{
//	if (Busy) return;
	QStrListIterator	it(URLList);
	for (;it.current();++it) DirectoryTree->removeItem(it.current());
}

void KExplorer::toggleShowHidden()
{
	if (Busy) return;
	ShowHiddenFiles = !ShowHiddenFiles;
	MenuBar->setItemChecked(HIDDEN_ID,ShowHiddenFiles);
	DirectoryTree->removePointFiles();
	if (DirectoryTree->currentItem()->Depth > 1 && ShowHiddenFiles) {
		DirectoryTree->rescanChilds(DirectoryTree->currentItem());
	}
	scanDirectory(DirectoryTree->currentItem());
	saveConfiguration();
}

// OLE
void KExplorer::toggleShowMiniImages()
{
        if (Busy) return;
	ShowMiniImages = !ShowMiniImages;
	MenuBar->setItemChecked(MINIIMAGES_ID,ShowMiniImages);
	
	if (Style == BIGICON_ID)
// kick off redraw of right pane
// please check if these is a viable and good solution
	  {
          destroyFileView();
	  createFileView();
	  FileView->setLinkArrow(IconLoader->loadIcon("link.xpm"));
	  FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
	  FileView->setFileList(FileList);
	  }
	saveConfiguration();
}
// OLE

void KExplorer::toggleShowArchive()
{
	if (Busy) return;
	ShowArchive = !ShowArchive;
	MenuBar->setItemChecked(ARCHIVE_ID,ShowArchive);
	if (ShowArchive) {
		if (DirectoryTree->currentItem()->Depth > 1) DirectoryTree->rescanChilds(DirectoryTree->currentItem());
	}
	else DirectoryTree->removeArchiveFiles();
	saveConfiguration();
}

void KExplorer::options()
{
	OptionsDlg = new Options(this);
	OptionsDlg->setOkButton(i18n("OK"));
	OptionsDlg->setApplyButton(i18n("Apply"));
	OptionsDlg->setCancelButton(i18n("Cancel"));
	OptionsDlg->setConfig(ConfigFile);
	OptionsDlg->setExtList(ExtensionList,IconLoader,UseKDEMimeTypes);
	if (Style == DETAILICON_ID) ((KDetailList*)FileView)->getColumns(ColType,ColWidth);
	OptionsDlg->setColumns(ColType,ColWidth,ColName);
//	OptionsDlg->setDateFormat(DateFormat);
	OptionsDlg->setProtList(ProtList);
	connect(OptionsDlg,SIGNAL(applyButtonPressed()),SLOT(optionsApply()));
	OptionsDlg->exec();
	delete OptionsDlg;
}

void KExplorer::optionsApply()
{
	bool	needSave = FALSE;
	bool	needScan = FALSE;
	OptionsDlg->setCursor(waitCursor);
	if (OptionsDlg->archModified()) {
		OptionsDlg->getProtList(ProtList);
		if (ShowArchive) DirectoryTree->removeArchiveFiles(ProtList);
		needSave = TRUE;
	}
	if (OptionsDlg->miniImageSaving() != MiniImageSaving) {
		MiniImageSaving = OptionsDlg->miniImageSaving();
		needSave = TRUE;
		if (MiniImageSaving == 2) needScan = TRUE;
	}
	if (OptionsDlg->columnsModified() || OptionsDlg->dateFormat() != DateFormat) {
		DateFormat = OptionsDlg->dateFormat();
		if (Style == DETAILICON_ID) destroyFileView();
		OptionsDlg->getColumns(ColType,ColWidth);
		if (Style == DETAILICON_ID) {
			createFileView();
			FileView->setLinkArrow(IconLoader->loadMiniIcon("link.xpm"));
			FileView->setDNDIcon(IconLoader->loadMiniIcon("unknown.xpm"));
			FileView->setFileList(FileList);
		}
		needSave = TRUE;
	}
	if (OptionsDlg->useKDEIcons() != UseKDEIcons) {
		needSave = TRUE;
		UseKDEIcons = OptionsDlg->useKDEIcons();
		IconPath = OptionsDlg->iconPath();
		if (IconPath[IconPath.length()-1] != ';') IconPath += ";";
		IconLoader->reloadIcons(UseKDEIcons,IconPath);
	}
	if (OptionsDlg->useKDEMimeTypes() != UseKDEMimeTypes) {
		needSave = TRUE;
		needScan = TRUE;
		UseKDEMimeTypes = OptionsDlg->useKDEMimeTypes();
		ExtensionFile = OptionsDlg->extensionFile();
		setupMimeTypes();
	}
	else if (OptionsDlg->extensionsModified()) {	// This can only be achieved if mime types has not been changed
		needSave = TRUE;
		needScan = TRUE;
		saveMimeTypes();
		setupMimeTypes();
	}
	if (OptionsDlg->useMagicNumbers() != UseMagicNumbers || OptionsDlg->magicFile() != MagicFile) {
		needSave = TRUE;
		needScan = TRUE;
		UseMagicNumbers = OptionsDlg->useMagicNumbers();
		if (OptionsDlg->magicFile() != MagicFile) {
			MagicFile = OptionsDlg->magicFile();
			Magic->setMagicFile(MagicFile.data());
		}
		Manager->setupMime(ExtensionDict,FilenameDict,Magic,UseMagicNumbers);
	}
	if (OptionsDlg->shell() != Shell) { Shell = OptionsDlg->shell(); needSave = TRUE;}
	if (OptionsDlg->startup() != StartupDir) { StartupDir = OptionsDlg->startup(); needSave = TRUE;}
	if (OptionsDlg->imageSize() != ImageSize) { ImageSize = OptionsDlg->imageSize(); needSave = TRUE;}
	if (needSave) {
		saveConfiguration();
		OptionsDlg->setExtList(ExtensionList,IconLoader,UseKDEMimeTypes);
		refresh();
	}
	if (needScan) scanDirectory(DirectoryTree->currentItem());
	OptionsDlg->setCursor(arrowCursor);
}

void KExplorer::refresh()
{
	DirectoryTree->refresh();
	FileView->repaint(TRUE);
}

void KExplorer::selectionChanged()
{
	FileInfoList	*list = FileView->getSelected();
	QString		msg1, msg2;
	if (list->count() == 0) {
		msg1.setNum(FileList->count());
		msg1 += i18n(" objects");
		msg2 = "";
	}
	else if (list->count() == 1) {
		msg1.setNum(FileList->count());
		msg1 += i18n(" objects");
		msg2.sprintf("%s (%s) %s",list->at(0)->fileName().data(),processSize(list->at(0)->size()).data(),list->at(0)->description());
	}
	else {
		int	total(0);
		msg1.setNum(list->count());
		msg1 += i18n(" objects selected");
		FileInfoListIterator	it(*list);
		for (;it.current();++it) total += it.current()->size();
		msg2.sprintf("%s",processSize(total).data());
	}
	Status1Info->setText(msg1.data());
	Status2Info->setText(msg2.data());
}

void KExplorer::renameItem(FileInfo *item, const QString& newName)
{
	QString		newPath = item->dirPath() + newName;
	if (item->isDir()) newPath += '/';
	if (!Manager->rename(item->absFilePath().data(),newPath.data()))
		QMessageBox::critical(this,i18n("Error"),i18n("Unable to rename file"),QMessageBox::Ok | QMessageBox::Default,0);
	else {
		if (item->isDir()) DirectoryTree->renameItem(item->absFilePath().data(),newPath.data());
		scanDirectory(DirectoryTree->currentItem());
	}
}

void KExplorer::mount()
{
	Device	*dev;
	if (TmpDevice) dev = findDevice(TmpDevice->Label.data());
	else dev = findDevice(DirectoryTree->popupItem()->Label.data());
	MountProtocol	*prot = (MountProtocol*)(dev->protocol());
	if (!prot->isMountable()) QMessageBox::critical(this,i18n("Error"),i18n("Device is not mountable : check parameters"),QMessageBox::Ok | QMessageBox::Default,0);
	else if (!prot->mount()) QMessageBox::critical(this,i18n("Error"),i18n("Unable to mount device"),QMessageBox::Ok | QMessageBox::Default,0);
	else {
		if (TmpDevice) TmpDevice->Type = DirMount;
		else DirectoryTree->popupItem()->Type = DirMount;
		DirectoryTree->update();
	}
	TmpDevice = 0;
}

void KExplorer::umount()
{
	Device	*dev ;;
	if (TmpDevice) dev = findDevice(TmpDevice->Label.data());
	else dev = findDevice(DirectoryTree->popupItem()->Label.data());
	MountProtocol	*prot = (MountProtocol*)(dev->protocol());
	if (!prot->isMountable()) QMessageBox::critical(this,i18n("Error"),i18n("Device is not mountable : check parameters"),QMessageBox::Ok | QMessageBox::Default,0);
	else if (!prot->umount()) QMessageBox::critical(this,i18n("Error"),i18n("Unable to unmount device"),QMessageBox::Ok | QMessageBox::Default,0);
	else {
		if (TmpDevice) { TmpDevice->Type = DirNormal; DirectoryTree->clearItem(TmpItem);}
		else {
			DirectoryTree->popupItem()->Type = DirNormal;
			DirectoryTree->clearItem(DirectoryTree->popupItem());
		}
		DirectoryTree->update();
	}
	TmpDevice = 0;
}

Device* KExplorer::findTrash()
{
	QListIterator<Device>	it(DeviceList);
	for (;it.current();++it) if (it.current()->type() == Protocol::Trash) break;
	return it.current();
}

void KExplorer::moveToTrash()
{
	Device	*dev = findTrash();
	if (!dev) {
		QMessageBox::critical(this,i18n("Error"),i18n("No trash defined"),QMessageBox::Ok | QMessageBox::Default,0);
		return;
	}
	initBusy();
	FileInfoList	*list = FileView->getSelected();
	URLList.clear();
	FileInfoListIterator	it(*list);
	for (;it.current();++it) URLList.append(it.current()->absFilePath().data());
cout << "moving to trash : " << dev->path() << endl;
	if (Manager->move(URLList,dev->path())) {
		removeURLs();
		QString	path(i18n("Desktop/My_Computer/"));
		path += i18n("Trash");
		path += '/';
		DirViewItem	*item = DirectoryTree->findItem(path.data());
		item->Icon = item->IconSel = IconLoader->loadMiniIcon("kfm_fulltrash.xpm");
		DirectoryTree->refresh();
	}
	else QMessageBox::critical(this,i18n("Error"),i18n("Unable to move to trash"),QMessageBox::Ok | QMessageBox::Default,0);
	finishBusy();
	scanDirectory(DirectoryTree->currentItem());
}

void KExplorer::emptyTrash()
{
	Device	*dev = findTrash();
	if (Manager->emptyTrash(dev->protocol())) {
		QString	path(i18n("Desktop/My_Computer/"));
		path += i18n("Trash");
		path += '/';
		DirViewItem	*item = DirectoryTree->findItem(path.data());
		item->Icon = item->IconSel = IconLoader->loadMiniIcon("kfm_trash.xpm");
		DirectoryTree->clearItem(item);
		DirectoryTree->refresh();
		if (item == DirectoryTree->currentItem()) scanDirectory(item);
	}
	else QMessageBox::critical(this,i18n("Error"),i18n("Unable to empty trash"),QMessageBox::Ok | QMessageBox::Default,0);
}

void KExplorer::removeThisFolder()
{
	if (Busy) return;
	DirViewItem	*item = DirectoryTree->popupItem();
	KURL		url(item->Address.data());
	Protocol	*prot = Manager->searchProtocol(url);
	if (prot) {
		int	res = QMessageBox::warning(this,i18n("Warning"),i18n("Do you really want to delete the selected files ?"),QMessageBox::Yes | QMessageBox::Default,QMessageBox::Cancel);
		if (res != QMessageBox::Yes) return;
		initBusy();
		bool	ok(FALSE);
		if (item->Address[item->Address.length()-1] == '/') {
			ok = Manager->rmdir(prot,url);
			if (ok) DirectoryTree->removeItem(url.url());
		}
		else ok = Manager->remove(prot,url);
		finishBusy();
		if (!ok) {
			QString		msg(i18n("Unable to delete "));
			msg += url.url();
			QMessageBox::critical(this,i18n("Error"),msg.data(),QMessageBox::Ok | QMessageBox::Default,0);
		}
	}
	scanDirectory(DirectoryTree->currentItem());
}

void KExplorer::propertyThisFolder()
{
	DirViewItem	*item = DirectoryTree->popupItem();
	KURL		url(item->Address.data());
	Protocol	*prot = Manager->searchProtocol(url);
	if (prot == 0) return;
	FileInfo	*fi = prot->getInfo(url);
	if (fi == 0) return;
	PropertyDlg	*Dlg = new PropertyDlg(fi,this);
	if (Dlg->exec() && Dlg->isChanged())
		if (!Manager->chmod(item->Address.data(),Dlg->permissions()))
			QMessageBox::critical(this,i18n("Error"),i18n("Unable to change permissions"),QMessageBox::Ok | QMessageBox::Default,0);
		else scanDirectory(DirectoryTree->currentItem());
	delete Dlg;
	delete fi;
}

void KExplorer::updateHasChilds(DirViewItem *item)
{
	if (item->Address.isEmpty()) return;
//	if (ShowArchive) item->HasChilds = TRUE;
//	else {
		KURL	url(item->Address.data());
		Protocol	*prot = Manager->searchProtocol(url);
		if (prot) item->HasChilds = prot->hasChilds(url.path());
		DirectoryTree->updateCell(item);
//	}
}

void KExplorer::catchSignal(int sig)
{
	switch(sig) {
	   case SIGPIPE:
		cout << "SIGPIPE signal received" << endl;
		Manager->abort();
		break;
	}
}

Protocol* KExplorer::createArchiveProtocol(KURL& url)
{
	QString		path(url.parentURL());
	KURL		url2(path.data());
	QString		filename = url2.filename();
	SubProtocol	*subProt = matchFileName(filename.data(),ProtList);
	if (subProt) return Manager->createProtocol(subProt->type,url2.url().data());
	else return 0;
}

// OLE
void KExplorer::miniImageRequested(FileInfo *fi)
{
	QString image_path=QString(fi->absFilePath());
	KURL    image_url=KURL(image_path);

        // Do some tests, whether a thumbnail should be created or not
	// Maybe some tests could be droped, but so we are on the save side
      	if ((!(fi->yetSearchedForMiniImage()))
	    && fi->isLocal() && fi->isFile()
	    && (image_path.contains("file:")==1)
	    && (!image_url.hasSubProtocol()))
		{
		bool 	mini_image_outdated = false,
		     	mini_image_file_exists= false,
		        xvpics_dir_exists=false;
		QPixmap	mini_image;
		QString mini_image_path,
			xvpics_path ;
		
	      	fi->markAsYetSearchedForMiniImage();	
		
                // try to check the mimetype
		// this should speed up the processing of "large" directories very much
		// this test makes only sense, if we don't try to create thumbnails for
		// files which have a unknown MimeType
		// of course we may loose thumbnails even if we could create them
		// if this feature is unwanted just uncomment the unwanted if-branch
		if (fi->mimeType())
			{
			// only process files, whose mimetype includes "image"
			if (fi->mimeType()->MimeName.contains("image/")==0)
				{
				// no image mime-type
				return;
				}
			}
		else	
			{
			// No mime type information found
			return;
			}

		// if path to image contains ".xvpics" abort immediately
		// don't create thumbnail of thumbnail of thumbnail....
		if (image_path.find(".xvpics", 0) !=-1)
			{
			return;
			}

		// remove a "/", if last character is "/"
		// needed for the following path-manipulations
		if (image_path.findRev("/")==(int) image_path.length())
		       {
		       image_path.resize(image_path.length()-1);
		       }

// MG
//	      	mini_image_path = image_path.remove(0, 5); // remove leading "file:"
		mini_image_path = image_url.path();
// MG

	      	int last_backslash = mini_image_path.findRev("/");

	      	mini_image_path.insert(last_backslash+1, ".xvpics/");			

		xvpics_path = mini_image_path;

		last_backslash = xvpics_path.findRev("/");
		xvpics_path.truncate(last_backslash+1);

	      	struct stat     st;
	
		// check if xvpics-dir exists
		// this should speed up the function if we are in a "large" directory without thumbnails
		// of course we could try to cache, if there exists a xvpics-dir, but a good OS will do this for us
		// keep in mind: the second lstat is much more difficult to cache for the OS
		if (lstat(xvpics_path, &st)==0)
		    {
		    xvpics_dir_exists=true;

		    // Does file with corresponding file-name exists ?
		    if (lstat(mini_image_path,&st)==0)
		        {
		        // Yes
		        mini_image_file_exists=true;
			
			QDateTime mini_image_Date;

	          	mini_image_Date.setTime_t(st.st_mtime);

		  	// Is thumbnail outdated ?
		  	if (mini_image_Date >= fi->lastModified())
		    		{
		    		// No,
				// then try to load it as "XV-thumbnail"
				// different image.formats will not be loaded

		      		mini_image.load(mini_image_path,"XV");

				fi->setMiniImage(mini_image);
			
				cout << "not outdated" << endl;
				return;
				}
			else
				{
				cout << "outdated" << endl;
				mini_image_outdated = true;
		     		}	
			}
		    }

		if (!mini_image_file_exists || mini_image_outdated)
			{
			QImage 	image,
			        ditheredImage;

			// Is this a file we which can be loaded ?
//MG
			if (image.load(image_url.path()))	
//MG
		        	{
			        double  wexpand = (double) image.width() / (double) 80,
	   				hexpand = (double) image.height() / (double) 60;
 			
				if (wexpand >= 1.0 || hexpand >= 1.0) // don't expand small images  !
					{
					int 	neww, newh;

					if (wexpand > hexpand)
						{
						neww = (int) (image.width() / wexpand + 0.5);
						newh = (int) (image.height() / wexpand + 0.5);
						}
					else
						{
						neww = (int) (image.width() / hexpand + 0.5);
						newh = (int) (image.height() / hexpand + 0.5);
						}

					image=image.smoothScale(neww, newh);
					}
				}
			else
				{
				return;
				}

			// Do  we want to save the image ?
			// 2 = Allways; 0 = Never; 1 = Existing
			if (((MiniImageSaving==2) || ((MiniImageSaving==1) && xvpics_dir_exists))
// MG
			    && ((ImageSize==-1) || (fi->size()>ImageSize)))
// MG
			        {
				// Yes !

				// create .xvpics directory
				// Do we already have a .xvpics
				if (!xvpics_dir_exists)
				       {
					cout << "Don't have xvpics-dir to save thumbnail !" << endl;

				       // NO, try to create
				       //if (!mkdir(xvpics_path, 0777))
					//   {
					//   xvpics_dir_exists=true;
					//   }
				       }

				// only finish saving if xvpics_dir exists
				if (xvpics_dir_exists)
				       {
				       // at first dither for a better result
				
// Unfortunately the dithering provided by qt is far from optimal for dithering
// 24/32 8-8-8(rgb)bit to 3-3-2 (rgb); we would be happy if we could set the appropiate colour-table
// for this operation; this would yield much better miniImages with the same quality as xv
// maybe I will code a appropiate dithering function in the future;
// as we get no better thumbnails with dithering, don't do it !!
// Yes, we are happy ! the kde-libary provides the needed function, but only for depth!=8
				
					if (image.depth()>8)
					    {
					    QColor table[256];
				            int j;

					    // set the correct color table, which is implicit defined by xv-thumbnail format
					    for (j=0; j<256; j++)
					        {
						static int b_255_3[]= {0,85,170,255},  // index*255/3
							  rg_255_7[]={0,36,72,109,145,182,218,255}; // index *255/7
							
						table[j]=QColor(rg_255_7[((j >> 5) & 0x07)], rg_255_7[((j >> 2) & 0x07)],
								b_255_3[((j >> 0) & 0x03)]);

						}
				
					    // create K Floyd-Steinber-Dithering Class
					    kFSDither kdither = kFSDither (table, 256);
				
					    ditheredImage = kdither.dither(image);
					    }
					else
					    {
					    ditheredImage = image.convertDepth(8, PreferDither);
					    }
		
			     		// try to save mini_image !
					ditheredImage.save(mini_image_path, "XV");
				        }
				}
		
			        mini_image.convertFromImage( image, 0);
				fi->setMiniImage(mini_image);
				return;

// Watch out ! The thumbnails, which are freshly generated by kexplorer are displayed with "best" quality possible,
// but the thumbnails that are saved don't look that good; with better dithering this would change !!
			}
		 	
      	      	return;
	      	}
        else
		{
	      	return;
	      	}
}
// OLE

void KExplorer::selectOutdatedThumbnails()
{
// MG
//	QMessageBox::information(this,"Info","You have to write the code, Oliver !",QMessageBox::Ok | QMessageBox::Default,0);
	QString		Path(KURL(DirectoryTree->currentItem()->Address.data()).path());
	int	pos = Path.findRev('/',Path.length()-2);
	Path.truncate(pos+1);
	FileInfoList	list;
	list.setAutoDelete(FALSE);
	FileInfoListIterator	it(*FileList);
	for (;it.current();++it) {
		if (it.current()->isDir()) continue;
		QString		image(Path+it.current()->fileName());
		if (::access(image.data(),F_OK) != 0) list.append(it.current());
	}
	if (list.count() > 0) FileView->setSelection(list);
	else QMessageBox::information(this,i18n("Information"),i18n("No outdated thumbnails found"),QMessageBox::Ok | QMessageBox::Default,0);
// MG
}

void KExplorer::goToDir(KURL& url)
{
	Protocol	*prot = Manager->searchProtocol(url);
	if (!prot) {
		if (isVisible()) QMessageBox::critical(this,i18n("Error"),i18n("Can't find directory"),QMessageBox::Ok | QMessageBox::Default,0);
		return;
	}
	if (prot->type() != Protocol::File && prot->type() != Protocol::Mount && prot->type() != Protocol::Trash) return;
	QString		path(i18n("Desktop/My_Computer/"));
	Device		*dev = findDevice(prot);
	path += dev->name();
	path += url.url().mid(prot->prefix().length()-1,url.url().length());
	DirectoryTree->goToDir(path.data());
}

void KExplorer::goToDir()
{
	LineDlg	*Dlg = new LineDlg(this);
	Dlg->setLabel(i18n("Go to directory :"));
	if (Dlg->exec()) {
		QString		tmp;
		tmp.sprintf("file:%s",Dlg->text());
		if (tmp[tmp.length()-1] != '/') tmp += '/';
		KURL	url(tmp.data());
		goToDir(url);
	}
}

bool KExplorer::createXVPICSDir(KURL& url)
{
	if (!ShowMiniImages || MiniImageSaving != 2 || url.hasSubProtocol() || Style != BIGICON_ID
	    || strcmp(url.protocol(),"file") != 0 || url.url().right(8) == ".xvpics/") return FALSE;
	QString		path = url.path();
	path += ".xvpics/";
	if (::access(path.data(),F_OK) == 0) return FALSE;		// .xvpics already exists
	if (::mkdir(path.data(),0744) == 0) {
		path = (url.url() + ".xvpics/");
		if (DirectoryTree->currentItem()->ChildsScanned && ShowHiddenFiles)
			DirectoryTree->addItem(DirectoryTree->currentItem(),".xvpics",path.data(),IconLoader->loadMiniIcon("folder.xpm","unknown.xpm"),IconLoader->loadMiniIcon("folder_open.xpm","unknown.xpm"),TRUE,FALSE);
		else updateHasChilds(DirectoryTree->currentItem());
		KURL	newUrl(path.data());
		Protocol	*prot = Manager->searchProtocol(newUrl);
		FileInfo	*fi = prot->getInfo(newUrl);
		fi->setIcons(IconLoader->loadIcon("folder.xpm","unknown.xpm"),IconLoader->loadMiniIcon("folder.xpm","unknown.xpm"));
		FileList->inSort(fi);
//		DirectoryTree->update();
		return TRUE;
	}
	return FALSE;
}
