/***************************** LICENSE START ***********************************

 Copyright 2015 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QDrag>
#include <QDropEvent>
#include <QMessageBox>
#include <QObject>
#include <QPainter>
#include <QShortcut>

#include "MvQFolderViewBase.h"

#include "MvQ.h"
#include "MvQBookmarks.h"
#include "MvQContextMenu.h"
#include "MvQDesktopSettings.h"
#include "MvQFileBrowser.h"
#include "MvQFileDialog.h"
#include "MvQFolderItemProperty.h"
#include "MvQFolderModel.h"
#include "MvQIconMimeData.h"
#include "MvQIconProvider.h"
#include "MvQNewIconWidget.h"

#include "Command.h"
#include "Folder.h"
#include "IconClass.h"
#include "IconGroupTools.h"
#include "IconInfo.h"
#include "IconObject.h"

MvQFolderViewBase::MvQFolderViewBase(MvQFolderModel *folderModel,QWidget *view) :
   folderModel_(folderModel),
   view_(view),
   shortCutInit_(false)
{
  	filterModel_= new MvQFolderFilterModel;  
	filterModel_->setSourceModel(folderModel_);	
	filterModel_->setDynamicSortFilter(true);
	
	itemProp_=folderModel_->itemProp();
}
	
MvQFolderViewBase::~MvQFolderViewBase()
{
	delete filterModel_;	
}

QString MvQFolderViewBase::fullName(const QModelIndex& index,IndexType indexType)
{
	return (indexType == FilterModelIndex)?folderModel_->fullName(filterModel_->mapToSource(index)):folderModel_->fullName(index);
}

bool MvQFolderViewBase::isFolder(const QModelIndex& index,IndexType indexType)
{
  	return (indexType == FilterModelIndex)?folderModel_->isFolder(filterModel_->mapToSource(index)):folderModel_->isFolder(index);
} 
  
Folder* MvQFolderViewBase::currentFolder()
{
	return folderModel_->folder();
}	

bool MvQFolderViewBase::changeFolderToParent()
{	
	bool retVal=folderModel_->setFolderToParent();
	return retVal;
}

bool MvQFolderViewBase::changeFolder(const QModelIndex& index,IndexType indexType)
{ 
  	QModelIndex folderIndex=(indexType == FilterModelIndex)?filterModel_->mapToSource(index):index;
		
	bool retVal=folderModel_->setFolder(folderIndex);
	return retVal;
}

bool MvQFolderViewBase::changeFolder(QString fullName,int iconSize)
{
 	bool retVal=folderModel_->setFolder(fullName,iconSize);
	return retVal;
}

bool MvQFolderViewBase::changeFolder(Folder *folder,int iconSize)
{
 	bool retVal=folderModel_->setFolder(folder,iconSize);
	return retVal;
}

QString MvQFolderViewBase::itemInfo(const QModelIndex& index,IndexType indexType)
{
	QModelIndex folderIndex=(indexType == FilterModelIndex)?filterModel_->mapToSource(index):index;

	return folderModel_->objectInfo(folderIndex);
}  

void MvQFolderViewBase::handleDoubleClick(const QModelIndex& index)
{
	IconObject *obj=folderModel_->objectFromIndex(filterModel_->mapToSource(index));
	if(obj)
	{
		QString method=QString::fromStdString(obj->iconClass().defaultMethod()).toLower();
		
		if(obj->isFolder())
		{
		  	iconCommand("open",obj);
			return;
		}
		else if(!method.isEmpty())
		{
		  	obj->command(method.toStdString());
		}  
		else 
		{
		  	obj->doubleClick();
		}
	}
}	
	
void MvQFolderViewBase::handleContextMenu(QModelIndex indexClicked,QModelIndexList indexLst,QPoint globalPos,QPoint widgetPos,QWidget *widget)
{	
  	MvQContextItemSet *cms=cmSet();
	if(!cms)
	  	return;
  
  	//Icon actions
  	if(indexClicked.isValid() && indexClicked.column() == 0)   //indexLst[0].isValid() && indexLst[0].column() == 0) 
	{
	  	vector<IconObject*> objLst;
		for(int i=0; i < indexLst.count(); i++)
		{
	  		IconObject* obj=folderModel_->objectFromIndex(filterModel_->mapToSource(indexLst[i]));
			if(obj) objLst.push_back(obj);
		}	
		
		if(objLst.size() > 0)
		{
		  	QString selection;
			if(objLst.size() ==1)
			  	//selection=MvQContextMenu::instance()->exec(cmIconItems_,objLst[0],globalPos,widget);
				selection=MvQContextMenu::instance()->exec(cms->icon(),objLst[0],globalPos,widget);
			else 
				//selection=MvQContextMenu::instance()->exec(cmMultiIconItems_,objLst,globalPos,widget);
				selection=MvQContextMenu::instance()->exec(cms->multiIcon(),objLst,globalPos,widget);
			
			if(!selection.isEmpty())
				handleIconCommand(objLst,selection);
		}
			
		/*IconObject* obj=folderModel_->objectFromIndex(filterModel_->mapToSource(index));
		if(obj)
		{
			QString selection=MvQContextMenu::instance()->exec(cmIconItems_,obj,globalPos,widget);
		  				
			if(!selection.isEmpty())
				handleIconCommand(obj,selection);
		}*/	
	}
	
	//Desktop actions
	else
	{
	  	//QString selection=MvQContextMenu::instance()->exec(cmDesktopItems_,globalPos,widget);
		QString selection=MvQContextMenu::instance()->exec(cms->desktop(),globalPos,widget);
		if(!selection.isEmpty())
		{  
			handleDesktopCommand(selection,widgetPos,widget); 
		}
	}	
}	

  
void MvQFolderViewBase::handleIconShortCut(QShortcut* sc,QModelIndexList indexLst)
{
  	if(!sc)
  		return;
		
  	vector<IconObject*> objLst;
	for(int i=0; i < indexLst.count(); i++)
	{
	  	IconObject* obj=folderModel_->objectFromIndex(filterModel_->mapToSource(indexLst[i]));
		if(obj)  	  		  
			objLst.push_back(obj);
	}	
		
	if(objLst.size() > 0)
	{
		QString selection=sc->property("cmd").toString();
		qDebug() << "icon shortcut  selection" << selection;
		if(!selection.isEmpty())
		{  
			handleIconCommand(objLst,selection);
		}
	}
}

void MvQFolderViewBase::handleDesktopShortCut(QShortcut* sc,QPoint pos,QWidget *widget)
{
  	if(!sc)
  		return;
  	
	QString selection=sc->property("cmd").toString();
	if(!selection.isEmpty())
	 	 handleDesktopCommand(selection,pos,widget);
}

void MvQFolderViewBase::handleIconCommand(QModelIndexList indexLst,QString name)
{
  	vector<IconObject*> objLst;
	for(int i=0; i < indexLst.count(); i++)
	{
	 	IconObject* obj=folderModel_->objectFromIndex(filterModel_->mapToSource(indexLst[i]));
		if(obj) objLst.push_back(obj);
	}	
		
	if(objLst.size() > 0)
	{
		handleIconCommand(objLst,name);
	}
}	

void MvQFolderViewBase::handleIconCommand(const vector<IconObject*>& objLstIn,QString name)
{
  	//Selects the iconobjects for that the command is valid
  	vector<IconObject*> objLst;
  	for(vector<IconObject*>::const_iterator it=objLstIn.begin(); it!=objLstIn.end(); it++)				
	{
	  	if(*it)
		{  
		  	std::set<string> cmdSet=(*it)->can();
			QString canCmd=name;
			if(name.startsWith("compress_"))
			  	canCmd="compress";
			
			if(cmdSet.find(canCmd.toStdString()) !=  cmdSet.end())
			{
		  		objLst.push_back(*it);
			}
		}	
	}	
			  
	if(IconGroupTools::can(name.toStdString()))  
	{
	  	if(objLst.size() > 0)		  	
		{  
			QPoint refPos=itemProp_->referencePosition(objLst[0]);
			refPos+=QPoint(32,32);
		  	folderModel_->setPositionHint("",refPos.x(),refPos.y());						     						 
		}
		
		IconGroupTools::run(name.toStdString(),objLst);	  
	}
	else if(name == "destroy")
	{
	  	 if(confirmDelete(objLst.size()))
		 {
		  	for(vector<IconObject*>::const_iterator it=objLst.begin(); it!=objLst.end(); it++)				
			 	(*it)->command(name.toStdString()); 	
		 }
	}  
	else if(name == "copy")
	{
	  	if(objLst.size() > 0)
		{  
			QList<IconObject*> lst;
			for(vector<IconObject*>::const_iterator it=objLst.begin(); it!=objLst.end(); it++)
				lst << *it;
			
			copyToClipboard(lst.at(0),lst);
	 	}
	} 
	else if(name == "cut")
	{
	  	if(objLst.size() > 0)
		{  
			QList<IconObject*> lst;
			for(vector<IconObject*>::const_iterator it=objLst.begin(); it!=objLst.end(); it++)
			{
			  	//(*it)->notifyCutBegin();
			  	lst << *it;
			}
			
			cutToClipboard(lst.at(0),lst);
	 	}
	} 
	else if(name == "empty")
	{
		MvQ::emptyWasteBasket();
	}	
	else
	{  
		for(vector<IconObject*>::const_iterator it=objLst.begin(); it!=objLst.end(); it++)		  
			  handleIconCommand(*it,name);
	}
}  
  
void MvQFolderViewBase::handleIconCommand(IconObject* obj,QString name)
{
	if(!obj)
		return;
	
	//Check if the command is valid for the object
	std::set<string> cmdSet=obj->can();
	if(cmdSet.find(name.toStdString()) ==  cmdSet.end())
		return;

	//Delete icon (permanently)
	if(name == "destroy")
	{  								  
		if(confirmDelete(1))
		{
			obj->command(name.toStdString());			
		}
	}
	
	//Other actions
	else  if(Command::isValid(name.toStdString()))
	{
		if(name  == "save")
		{ 
			QPoint refPos=itemProp_->referencePosition(obj);
			refPos+=QPoint(32,32);
		  	folderModel_->setPositionHint("",refPos.x(),refPos.y());
		}
						         
		obj->command(name.toStdString());
	}
	else if(name  == "openInWin")
	{
		MvQFileBrowser::openBrowser(QString::fromStdString(obj->fullName()),view_);
	}	
	else if(name == "bookmark")
	{
		MvQBookmarks::addItem(obj);
	}  
	else if(name == "copy")
	{
	  	QList<IconObject*> lst;
		lst << obj;
		copyToClipboard(obj,lst);
	} 
	else if(name == "rename")
	{
	  	if(obj->renamable())
		  	rename(obj);
	} 	
	else
	{
		iconCommand(name,obj); 
	}	
}	

void MvQFolderViewBase::handleDesktopCommand(QString name,QPoint pos,QWidget *widget)
{
	Folder *folder=folderModel_->folder();
		
	//For the detailed view the actual icon position should be ignored for desktop commands, 
	//e.g. when creating a new icon. In this case we use an "undefined" position!!!
	//ignoreItemPositionForCm() tells us when we need to apply it.
	
	if(name == "createFolder")
	{
	 	const IconClass &kind=IconClass::find("FOLDER");	
		if(ignoreItemPositionForCm())		  
		  	kind.createOne(folder);
		else
		  	kind.createOne(folder,pos.x(),pos.y());
	}
	else if(name == "createMacro")
	{
	 	const IconClass &kind=IconClass::find("MACRO");	
		if(ignoreItemPositionForCm())	
		  	kind.createOne(folder);
		else 
			kind.createOne(folder,pos.x(),pos.y());
		
	}
	else if(name == "createIcon")
	{  
		MvQNewIconDialog dialog(widget);

        if(dialog.exec() == QDialog::Accepted)
		{
	  		const IconClass &kind=dialog.selected();
			QPoint refPos=itemProp_->referencePosition(QString::fromStdString(kind.name()),pos);
			if(ignoreItemPositionForCm())				  
				kind.createOne(folder);
			else	
				kind.createOne(folder,refPos.x(),refPos.y());
			  //showLastCreated();
		}	
	}
	else if(name == "createLinkToFile" || name == "createLinkToFolder")
	{  
		MvQFileDialog dialog(QString::fromStdString(folder->path().str()),QObject::tr("Create symbolic link"),widget);
		dialog.setAcceptMode(QFileDialog::AcceptOpen);
		
		if(name == "createLinkToFile" )
			dialog.setFileMode(QFileDialog::ExistingFile);
		else		  	
			dialog.setFileMode(QFileDialog::Directory);
		
		dialog.setLabelText(QFileDialog::Accept,"Ok");
		
		if(dialog.exec() == QDialog::Accepted)
		{
  			QStringList lst=dialog.selectedFiles();
  			if(lst.count() > 0)
			{
				Path result(lst[0].toStdString());
				string name = folder->uniqueName(result.name());
				Path path   = folder->path().add(name);

				path.symlink(result);		
		
				//The dot file for a link should not be created in the 
				//link target's folder. By commenting out the line below we can prevent it!
				//path.dot().symlink(result.dot());		
				if(ignoreItemPositionForCm())
					folder->scanForNewFile(name);
				else
				  	folder->scanForNewFile(name,pos.x(),pos.y());
			}	
		}	

	}
	else if(name == "bookmarkFolder")
	{
		MvQBookmarks::addItem(folder);
	}  
	else if(name == "paste")
	{
	 	if(ignoreItemPositionForCm())
		  	fromClipboard(pos); 
		else
		  	fromClipboard(pos); 
	}  	
	else
	{
	  	if(ignoreItemPositionForCm())
			desktopCommand(name,pos); 
		else 
			desktopCommand(name,pos);
	}	
}

void MvQFolderViewBase::copyToClipboard(IconObject *obj,QList<IconObject*> lst)
{	
  	MvQIconMimeData* data=buildClipboardData(obj,lst,false,true);	
	QApplication::clipboard()->setMimeData(data);	  
}


void MvQFolderViewBase::cutToClipboard(IconObject *obj,QList<IconObject*> lst)
{	
  	MvQIconMimeData* data=buildClipboardData(obj,lst,false,false);	
	QApplication::clipboard()->setMimeData(data);	  
}

void MvQFolderViewBase::fromClipboard(QPoint pos)
{
	const MvQIconMimeData* mimeData=qobject_cast<const MvQIconMimeData*>(QApplication::clipboard()->mimeData());
	//If there is data we simulate drop
	if(mimeData)
	{
	  	if(mimeData->clipboardAction() == MvQIconMimeData::CopyAction)
	  		performDrop(Qt::CopyAction,mimeData,pos,false); 
		else if(mimeData->clipboardAction() == MvQIconMimeData::CutAction)
		  	performDrop(Qt::MoveAction,mimeData,pos,false); 
	}		  
}

bool MvQFolderViewBase::confirmDelete(int count)
{
	QString txt1, txt2;
	if(count == 1)
	{	txt1=QObject::tr("Delete icon");
		txt2=QObject::tr("Do you really want to delete this icon? It will be <b>permanently</b> deleted from disk!");
	}
	else
	{
	  	txt1=QObject::tr("Delete icons");
		txt2=QObject::tr("Do you really want to delete these ") + QString::number(count) + QObject::tr(" icons? They will be <b>permanently</b> deleted from disk!");
	}
	
  	return (QMessageBox::warning(0,txt1,txt2,
		QMessageBox::Yes | QMessageBox::Cancel,QMessageBox::Cancel) == QMessageBox::Yes);
		
}

QString  MvQFolderViewBase::formatFileSize(qint64 /*size*/)
{
#if 0
if(size < 1024)
	  	return QString::number(size) + " B";
	else if(size < 1024*1024)
	  	return QString::number(size/1024) + " KB";
	else if(size < 1024*1024*1024)
	  	return QString::number(size/(1024*1024)) + " MB";
	else
	  	return QString::number(size/(1024*1024*1024)) + " GB";
#endif	
	
 return QString();
}	

QString  MvQFolderViewBase::formatFilePermissions(const QFile::Permissions& perm)
{  
//There is a bug in Qt 4.6.3 (it was the version used for the developments)!
//QFileSystemModel::permissions() gives inversed results for the
//write premissions. So the the code below had to be changed to cope
//with it (the original code is still kept but commented out).
  
	return "-" +
	       QString((perm.testFlag(QFile::ReadOwner))?"r":"-") +
	       QString((perm.testFlag(QFile::WriteOwner))?"-":"w") +
	       QString((perm.testFlag(QFile::ExeOwner))?"x":"-") +
	       QString((perm.testFlag(QFile::ReadGroup))?"r":"-") +
	       QString((perm.testFlag(QFile::WriteGroup))?"-":"w") +
	       QString((perm.testFlag(QFile::ExeGroup))?"x":"-") +
	       QString((perm.testFlag(QFile::ReadOther))?"r":"-") +
	       QString((perm.testFlag(QFile::WriteOther))?"-":"w") +
	       QString((perm.testFlag(QFile::ExeOther))?"x":"-");
  
#if 0 
  	return "-" +
	       QString((perm.testFlag(QFile::ReadOwner))?"r":"-") +
	       QString((perm.testFlag(QFile::WriteOwner))?"w":"-") +
	       QString((perm.testFlag(QFile::ExeOwner))?"x":"-") +
	       QString((perm.testFlag(QFile::ReadGroup))?"r":"-") +
	       QString((perm.testFlag(QFile::WriteGroup))?"w":"-") +
	       QString((perm.testFlag(QFile::ExeGroup))?"x":"-") +
	       QString((perm.testFlag(QFile::ReadOther))?"r":"-") +
	       QString((perm.testFlag(QFile::WriteOther))?"w":"-") +
	       QString((perm.testFlag(QFile::ExeOther))?"x":"-");
#endif

}

bool MvQFolderViewBase::isAccepted(const IconClass& kind)
{
  	return folderModel_->isAccepted(kind);
}  

bool MvQFolderViewBase::isAccepted(IconObject *obj)
{
	const IconClass& ic = obj->iconClass();
	return isAccepted(ic);
}

int MvQFolderViewBase::getIconSize() 
{
  	return itemProp_->iconSize();
}	

void MvQFolderViewBase::showLastCreated()
{
	QModelIndex index=filterModel_->mapFromSource(folderModel_->lastArrived());
	blink(index);
} 


QPixmap MvQFolderViewBase::dragPixmapWithCount(IconObject *dragObj,int cnt,QRect& iconPix)
{
	QFont f("Courier");
	f.setStyleHint(QFont::TypeWriter);
	f.setFixedPitch(true);	
	f.setPointSize(9);
	f.setBold(true);
	
	QFontMetrics fm(f);
	QRect textRect(0,0,fm.width(QString::number(cnt)),fm.height());	
	int padding=2;
	int overlapx=4;
	int overlapy=10;
	
	QPixmap pix(getIconSize()+textRect.width()+2*padding+2+1-overlapx,
		    getIconSize()+textRect.height()+2*padding+2+1-overlapy);
	
	pix.fill(Qt::transparent);
	
	QPainter painter(&pix); 
					
	painter.drawPixmap(0,pix.height()-getIconSize(),
		           MvQIconProvider::pixmap(dragObj->iconClass(),getIconSize()));
	
	iconPix=QRect(0,pix.height()-getIconSize(),getIconSize(),getIconSize());		   
			   
	//Item count indicator
	QPen pen(Qt::black);
	QBrush brush(QColor(255,230,191));
	painter.setPen(pen);
	painter.setBrush(brush);
	painter.setFont(f);
	
	//painter.setRenderHint(QPainter::Antialiasing,true);				
	
	QRect cntRect(getIconSize()-overlapx+2,1,textRect.width()+2*padding,textRect.height()+2*padding);
	painter.drawRoundedRect(cntRect,2,2);	
	
	cntRect.adjust(-2,2,-2,2);
	painter.drawRoundedRect(cntRect,2,2);
	
	painter.setPen(Qt::black);
	painter.drawText(cntRect,Qt::AlignVCenter | Qt::AlignHCenter,QString::number(cnt));
	
	QPoint hotSpot(getIconSize(),pix.height());
	
	return pix;
}	 


MvQIconMimeData *MvQFolderViewBase::buildClipboardData(IconObject *dragObj,QList<IconObject*> objLst,bool fromHelper,bool copy)
{
	if(dragObj && objLst.contains(dragObj))
	{	  	
		//Hotspot is the bottom right corner of the dragged object's pixmap
		QPoint hotSpotInPix(1,1);
		
		//It has to have as many elements as there are in objLst
		QList<QPoint> pixDistanceLst; //It has 
		
		//Multiple items
		if(objLst.count() > 1)
		{  									  
			//Pixmap rect of the drag object
			QRect rect=pixmapRect(dragObj);
				
			for(int i=0; i < objLst.count(); i++)
			{
			 	QRect vr=pixmapRect(objLst[i]);
				
				//Normalised distance of the pixmap's bottom right corner from the 
				//bottom right corner of the dragged object's pixmap 		  
				pixDistanceLst << (vr.bottomRight()-rect.bottomRight())/getIconSize();		  
			}
		}
			
		//Single item
		else  
		{  		  
			pixDistanceLst << QPoint(0,0);			
		}
		
		MvQIconMimeData::ClipboardAction ca;
		if(copy)
		  	ca=MvQIconMimeData::CopyAction;
		else
		  	ca=MvQIconMimeData::CutAction;
		
		//Create and set drag mime data
		MvQIconMimeData *mimeData= new MvQIconMimeData(folderModel_,
							       dragObj,hotSpotInPix,
							       objLst,pixDistanceLst,ca);											     				       
		mimeData->setFromHelper(fromHelper);
	
		return mimeData;
	}
	
	return 0;
}

QDrag* MvQFolderViewBase::buildDrag(IconObject *dragObj,QList<IconObject*> objLst,bool fromHelper,QWidget* dragParent,QPoint dragPos)
{
	if(dragObj && objLst.contains(dragObj))
	{	  	
		QDrag *drag=new QDrag(dragParent);
	  
		//Hotspot is the bottom right corner of the dragged object's pixmap 
		//we overwrite it if dragPos is null!! We use normalised coordinates
		QPointF hotSpotInPix(1,1);
		
		//It has to have as many elements as there are in objLst
		QList<QPoint> pixDistanceLst;  
		
		//Multiple items
		if(objLst.count() > 1)
		{  									  
		  	if(MvQDesktopSettings::dragPolicy() == Desktop::DragShowAllIcons)
			{
			  	//Pixmap rect of the drag object
				QRect rect=pixmapRect(dragObj);
				
				//Find bounding box for selected pixmap rects				
				QRect bbox=pixmapRect(objLst);
				
				//Render the drag pixmap --> will contain all the icons pixmaps!
				QPixmap pix(bbox.size());
				pix.fill(Qt::transparent);
				QPainter painter(&pix);
				
				for(int i=0; i < objLst.count(); i++)
				{
			 		QRect vr=pixmapRect(objLst[i]);
					painter.drawPixmap(vr.topLeft()-bbox.topLeft(),
						          MvQIconProvider::pixmap(objLst.at(i)->iconClass(),getIconSize()));																	  
					
					//Normalised distance of the pixmap's bottom right corner from the 
					//bottom right corner of the dragged object's pixmap 		  
					pixDistanceLst << (vr.bottomRight()-rect.bottomRight())/getIconSize();		  
				}
				
				drag->setPixmap(pix);
						
				QPoint hotSpot;
				
				//Hotspot is the bottom right corner of the dragged object's pixmap 	
				if(dragPos.isNull())
				{
			 		 hotSpot=rect.bottomRight()-bbox.topLeft();
					 hotSpotInPix=QPointF(1,1);	
				}
				//We use the real drag position if dragPos in not present
				else
				{  
					hotSpot=dragPos-bbox.topLeft();			               								
					hotSpotInPix=QPointF(dragPos.x()-(rect.center().x()-getIconSize()/2),
			                                     dragPos.y()-rect.top());			
					hotSpotInPix/=getIconSize();
				}
				
				drag->setHotSpot(hotSpot);					
			}
			else
			{
				//Pixmap rect of the drag object
				QRect rect=pixmapRect(dragObj);
				
				for(int i=0; i < objLst.count(); i++)
				{
			 		QRect vr=pixmapRect(objLst[i]);																  
					
					//Normalised distance of the pixmap's bottom right corner from the 
					//bottom right corner of the dragged object's pixmap 
					pixDistanceLst << (vr.bottomRight()-rect.bottomRight())/getIconSize();		  
				}
				
				QRect iconPix;
				QPixmap pix=dragPixmapWithCount(dragObj,objLst.count(),iconPix);					
				drag->setPixmap(pix);
					
				//Hotspot is the bottom right corner of the dragged object's pixmap
				QPoint hotSpot(iconPix.bottomRight());	
				hotSpotInPix=QPointF(1,1);					
				drag->setHotSpot(hotSpot);							
			}
		}
			
		//Single item
		else  
		{  		  
			drag->setPixmap(MvQIconProvider::pixmap(dragObj->iconClass(),getIconSize()));
			
			QPoint hotSpot;
			if(dragPos.isNull())
			{
			  	hotSpot=QPoint(getIconSize(),getIconSize());
				hotSpotInPix=QPointF(1,1);	
			}
			//We use the real drag position
			else
			{  
				//Pixmap rect of the drag object
				QRect rect=pixmapRect(dragObj);
			
				hotSpot=QPoint(dragPos.x()-(rect.center().x()-getIconSize()/2),
			               dragPos.y()-rect.top());
			
				hotSpotInPix=hotSpot;
				hotSpotInPix/=getIconSize();
			}	
									
			drag->setHotSpot(hotSpot);										

			pixDistanceLst << QPoint(0,0);
			
		}
			

		//Create and set drag mime data
		MvQIconMimeData *mimeData= new MvQIconMimeData(folderModel_,
							       dragObj,hotSpotInPix,
							       objLst,pixDistanceLst);
											     				       
		mimeData->setFromHelper(fromHelper);
			
		drag->setMimeData(mimeData);
		
		return drag;
	}
	
	return 0;
}

void MvQFolderViewBase::dropToFolder(Folder *folder,QDropEvent* event)
{
	if(!folder || folder->locked())
	{
		event->ignore();
		return;
	}
	
	if(!event->source())
	{
		event->ignore();
		return;
	}	
	
	if(event->proposedAction() != Qt::CopyAction &&
	   event->proposedAction() != Qt::MoveAction)
	{
		event->ignore();
		return;
	}	

	//--------------------------------------
	// Drag and drop from another Metview folder
	//--------------------------------------
	
	if(event->mimeData()->hasFormat("metview/icon"))
	{	
		const MvQIconMimeData* mimeData=qobject_cast<const MvQIconMimeData*>(event->mimeData());
				
		if(!mimeData)
		{
			event->ignore();
			return;
		}	
	
		IconObject* dragObj=mimeData->dragObject();
		MvQFolderModel *model=mimeData->model();		
	
		//Ignore drops from the same folder
		if(dragObj && dragObj->parent() == folder)
		{
	  		event->ignore();
			return;
		}	 
			
		//Drop from another view/model or from the clipboard  --> copy or move
		if(model && dragObj)
		{									
						  
			for(int i=0; i < mimeData->objects().count(); i++)
			{					  
				IconObject *obj=mimeData->objects().at(i);
		 
				//We set the object position to zero. This will instuct the icon folder view
				//(when the folder is next open in it) to find meaningful positions to the 
				//icons.
				
				//Copy  
				if(event->proposedAction() == Qt::CopyAction)
				{					  
					 obj->clone(folder,false);
				}	
				
				//Move
				else if(event->proposedAction() == Qt::MoveAction)
				{  
					obj->position(IconInfo::undefX(),IconInfo::undefY());					
					folder->adopt(obj);
				}	
			}
				
			event->accept();
			return;
		}
	}
	else if(event->mimeData()->hasFormat("metview/new_icon"))
	{	
		const MvQNewIconMimeData* mimeData=qobject_cast<const MvQNewIconMimeData*>(event->mimeData());
				
		if(!mimeData)
		{
			event->ignore();
			return;
		}	
	
		if(mimeData->iconDefType() == MvQNewIconMimeData::UserDef)
		{
			const IconClass &kind=IconClass::find(mimeData->className().toStdString());
			kind.createOne(folder);							
			event->accept();
			return;
		}
	}
	
	
	event->ignore();
}

void MvQFolderViewBase::showIcon(IconObject *obj)
{
  	if(!obj) return;
  	
  	QModelIndex  index=filterModel_->mapFromSource(folderModel_->indexFromObject(obj));
	if(index.isValid())
	  	showIcon(index);
}	
