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

 Copyright 2012 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 "MvQLayerWidget.h"

//#include <QDebug>

#include <QAction>
#include <QLabel>
#include <QHBoxLayout>
#include <QMenu>
#include <QSlider>
#include <QSpinBox>
#include <QToolButton>
#include <QVBoxLayout>

#include "MgQLayerItem.h"
#include "MgQSceneItem.h"
#include "MvQLayerContentsIcon.h"
#include "MvQLayerModel.h"
#include "MvQLayerSuperPage.h"
#include "MvQLayerViewLevel.h"

#include "ObjectList.h"
#include "PlotMod.h"
#include "Root.h"

MvQLayerWidget::MvQLayerWidget(MgQPlotScene *scene,QWidget *parent) : QWidget(parent)
{
   QVBoxLayout *layerVb=new QVBoxLayout;
   layerVb->setContentsMargins(2,2,2,2);
   setLayout(layerVb);

   // Top level: model and view initializations
   spModel_ = new MvQLayerSuperPageModel(this);
   spView_ = new MvQLayerSuperPageView(spModel_,this);
   QLabel *spLabel = new QLabel(tr("Top Level"));
   layerVb->addWidget(spLabel);
   layerVb->addWidget(spView_);

   // View level: model and view initializations
   vlModel_ = new MvQLayerViewLevelModel(this);
   vlView_ = new MvQLayerViewLevelView(vlModel_,this);
   QLabel *vlLabel = new QLabel(tr("View Level"));
   layerVb->addWidget(vlLabel);
   layerVb->addWidget(vlView_);

   // Layer Level: model and view initializations
   view_ = new MvQLayerView(this);
   view_->setItemDelegate(new MvQLayerDelegate());
   QLabel *viewLabel = new QLabel(tr("Layer Level"));
   layerVb->addWidget(viewLabel);	
   layerVb->addWidget(view_); 

   model_ = new MvQLayerModel(scene);
   filterModel_ = new MvQLayerFilterModel(this);
   filterModel_->setSourceModel(model_);
   view_->setModel(model_,filterModel_);

   view_->setDragEnabled(true);
   view_->setAcceptDrops(true);
   view_->setDropIndicatorShown(true);
   view_->setDragDropMode(QAbstractItemView::DragDrop);

   // Double click
   connect(view_,SIGNAL(doubleClicked(QModelIndex)),
           this,SLOT(slotDoubleClickItem(QModelIndex)));

   // Context menu
   view_->setContextMenuPolicy(Qt::CustomContextMenu);
   connect(view_,SIGNAL(customContextMenuRequested(const QPoint&)),
           this,SLOT(slotContextMenu(const QPoint&)));

//	QPalette pal = view_->palette();
//	pal.setColor(QPalette::Highlight,Qt::white);
//	view_->setPalette(pal);
	
	//Slider
	QHBoxLayout *hb = new QHBoxLayout;
	layerVb->addLayout(hb);
	
	QLabel *label=new QLabel(tr("Transparency (%)"));
	hb->addWidget(label);	

	trSlider_ = new QSlider;
	trSlider_->setOrientation(Qt::Horizontal);
	trSlider_->setMinimum(0);
	trSlider_->setMaximum(100);
	trSlider_->setToolTip(tr("Change layer transparency"));
	hb->addWidget(trSlider_);		
	
	trSpin_ = new QSpinBox;
	trSpin_->setMinimum(0);
	trSpin_->setMaximum(100);
	trSpin_->setToolTip(tr("Change layer transparency"));
	hb->addWidget(trSpin_);	

	initTrWidgets_=false;

	connect(trSlider_,SIGNAL(valueChanged(int)),
		this,SLOT(slotTrSliderValueChanged(int)));

	connect(trSlider_,SIGNAL(sliderReleased()),
		this,SLOT(slotTrSliderReleased()));

	connect(trSpin_,SIGNAL(valueChanged(int)),
		this,SLOT(slotTrSpinValueChanged(int)));
		
	//Buttons
	hb = new QHBoxLayout;
	layerVb->addLayout(hb);

	topTb_ = new QToolButton(this);
	topTb_->setToolTip(tr("Move the current layer to the top"));
	topTb_->setIcon(QPixmap(QString::fromUtf8(":/uPlot/arrow_top.svg")));

	upTb_ = new QToolButton(this);
	upTb_->setToolTip(tr("Move the current layer up"));
  	upTb_->setIcon(QPixmap(QString::fromUtf8(":/uPlot/arrow_up.svg")));

	downTb_ = new QToolButton(this);
	downTb_->setToolTip(tr("Move the current layer down"));
	downTb_->setIcon(QPixmap(QString::fromUtf8(":/uPlot/arrow_down.svg")));

	bottomTb_ = new QToolButton(this);
	bottomTb_->setToolTip(tr("Move the current layer to the bottom"));
	bottomTb_->setIcon(QPixmap(QString::fromUtf8(":/uPlot/arrow_bottom.svg")));
	
	hb->addWidget(topTb_);
	hb->addWidget(upTb_);
	hb->addWidget(downTb_);
	hb->addWidget(bottomTb_);
	hb->addStretch(1.);

   // Signal/slot functions
	connect(topTb_,SIGNAL(clicked()),
		this,SLOT(slotMoveTop()));

	connect(upTb_,SIGNAL(clicked()),
		this,SLOT(slotMoveUp()));

	connect(downTb_,SIGNAL(clicked()),
		this,SLOT(slotMoveDown()));

	connect(bottomTb_,SIGNAL(clicked()),
		this,SLOT(slotMoveBottom()));
		
	connect(view_,SIGNAL(clicked(const QModelIndex &)),
		this,SLOT(slotSelectLayer(const QModelIndex &)));

	connect(model_,SIGNAL(layerDragFinished()),
		this,SLOT(slotCheckItemStatus()));
		
	connect(model_,SIGNAL(layerTransparencyChanged(QString,int)),
		this,SIGNAL(layerTransparencyChanged(QString,int)));	
		
	connect(model_,SIGNAL(layerVisibilityChanged(QString,bool)),
		this,SIGNAL(layerVisibilityChanged(QString,bool)));
		
   connect(model_,SIGNAL(layerStackingOrderChanged(QList<QPair<QString,int> >)),
      this,SIGNAL(layerStackingOrderChanged(QList<QPair<QString,int> >)));

   connect(view_,SIGNAL(iconDropped(const MvQDrop&, const QModelIndex&)),
      this,SLOT(slotIconDropped(const MvQDrop&, const QModelIndex&)));

   connect(spView_,SIGNAL(iconDropped(const MvQDrop&)),
      this,SLOT(slotIconDroppedTopLevel(const MvQDrop&)));

   connect(vlView_,SIGNAL(iconDropped(const MvQDrop&)),
      this,SLOT(slotIconDroppedViewLevel(const MvQDrop&)));
}

MgQLayerItem* MvQLayerWidget::currentLayer()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   int row = modelIndex.row(); 
   return model_->rowToLayer(row);
}  

QString MvQLayerWidget::currentLayerText()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   return model_->data(modelIndex).toString();  
}  

void MvQLayerWidget::slotSelectLayer(MgQLayerItem* layer)
{
   int row = model_->layerToRow(layer);
   QModelIndex index = filterModel_->mapFromSource(model_->index(row,0));
   slotSelectLayer(index);
}

void MvQLayerWidget::slotSelectLayer(const QModelIndex &index)
{
   #if 0   
   QModelIndex modelIndexCur = filterModel_->mapToSource(view_->currentIndex());
   QModelIndex modelIndex = filterModel_->mapToSource(index);
//   QModelIndex modelIndex = filterModel_->mapFromSource(index);
   if( modelIndex != modelIndexCur )
   {
      //QModelIndex proxyIndex = filterModel_->mapFromSource(index);
      //view_->setCurrentIndex(proxyIndex);
      view_->setCurrentIndex(index);
   }
#endif

	int value=model_->transparency(filterModel_->mapToSource(index));

	slotCheckItemStatus();

	initTrWidgets_=true;
	trSlider_->setValue(value);
	trSpin_->setValue(value);
	initTrWidgets_=false;
}


void MvQLayerWidget::slotTrSpinValueChanged(int value)
{
	if(initTrWidgets_)
		return;

	trSlider_->setValue(value);
	changeTransparency(value);
}

void MvQLayerWidget::slotTrSliderValueChanged(int value)
{
	if(initTrWidgets_)
		return;
	
	initTrWidgets_=true;
	trSpin_->setValue(value);
	initTrWidgets_=false;
	
}

void MvQLayerWidget::slotTrSliderReleased()
{
	int value=trSlider_->value();	
	changeTransparency(value);
}

void MvQLayerWidget::changeTransparency(int value)
{
   QModelIndex modeIndex = filterModel_->mapToSource(view_->currentIndex());
   model_->setTransparency(modeIndex,value);
}

void MvQLayerWidget::slotMoveTop()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   model_->moveTop(modelIndex);

   QModelIndex proxyIndex = filterModel_->mapFromSource(model_->index(0,0));
   view_->setCurrentIndex(proxyIndex);

   slotCheckItemStatus();
}

void MvQLayerWidget::slotMoveUp()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   int row = modelIndex.row();

   model_->moveUp(modelIndex);

   QModelIndex proxyIndex = filterModel_->mapFromSource(model_->index(row-1,0));
   view_->setCurrentIndex(proxyIndex);

   slotCheckItemStatus();
}

void MvQLayerWidget::slotMoveBottom()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   model_->moveBottom(modelIndex);

   int num = model_->rowCount(QModelIndex());
   QModelIndex proxyIndex = filterModel_->mapFromSource(model_->index(num-1,0));
   view_->setCurrentIndex(proxyIndex);

   slotCheckItemStatus();
}

void MvQLayerWidget::slotMoveDown()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   int row = modelIndex.row();

   model_->moveDown(modelIndex);

   QModelIndex proxyIndex = filterModel_->mapFromSource(model_->index(row+1,0));
   view_->setCurrentIndex(proxyIndex);

   slotCheckItemStatus();
}

void MvQLayerWidget::slotCheckItemStatus()
{
   QModelIndex modelIndex = filterModel_->mapToSource(view_->currentIndex());
   if( !modelIndex.isValid() )
	{
		trSlider_->setEnabled(false);
		trSpin_->setEnabled(false);
		topTb_->setEnabled(false);
		upTb_->setEnabled(false);
		bottomTb_->setEnabled(false);
		downTb_->setEnabled(false);
	}
	else
	{
		trSlider_->setEnabled(true);
		trSpin_->setEnabled(true);
		
      int row = modelIndex.row();
		int num=model_->rowCount(QModelIndex());
	
		if(num==1)
		{
			topTb_->setEnabled(false);
			upTb_->setEnabled(false);
			downTb_->setEnabled(false);
			bottomTb_->setEnabled(false);
		}
		else if(row==0)
		{
			topTb_->setEnabled(false);
			upTb_->setEnabled(false);
			downTb_->setEnabled(true);
			bottomTb_->setEnabled(true);
		}		
		else if(row==num-1)
		{
			topTb_->setEnabled(true);
			upTb_->setEnabled(true);
			downTb_->setEnabled(false);
			bottomTb_->setEnabled(false);
		}
		else 
		{
			topTb_->setEnabled(true);
			upTb_->setEnabled(true);
			downTb_->setEnabled(true);
			bottomTb_->setEnabled(true);
		}
	}
}

void MvQLayerWidget::slotDoubleClickItem (const QModelIndex& index1)
{
   QModelIndex index = filterModel_->mapToSource(index1);
   if( !index.isValid() )
      return;

   // Get icon from the model
   MvQLayerContentsIcon *icon = model_->indexToIcon(index);
   if(!icon)
      return;

   // Start editor
   icon->startEditor();
}

void MvQLayerWidget::slotContextMenu(const QPoint &position)
{
   QModelIndex index = filterModel_->mapToSource(view_->indexAt(position));
   if(!index.isValid() || model_->indexToLevel(index) == 0)
      return;

	MvQLayerContentsIcon *icon=model_->indexToIcon(index);
	if(!icon)
	  	return;
		
	QList<QAction*> actions;

    // Insert Edit key
   QAction *actionEdit = new QAction(this);
   actionEdit->setObjectName(QString::fromUtf8("actionEdit"));
   actionEdit->setText(tr("Edit in Plot"));
   QFont font = actionEdit->font();
   font.setWeight(QFont::Bold);
   actionEdit->setFont(font);
   actionEdit->setShortcut(QKeySequence(tr("Ctrl+E")));
   actions.append(actionEdit);
   if(!icon->canBeEdited())
      actionEdit->setEnabled(false); 

   //Insert Save key
   QAction *actionSave = new QAction(this);
   actionSave->setObjectName(QString::fromUtf8("actionSave"));
   actionSave->setText(tr("Save to Disk"));
   actionSave->setShortcut(QKeySequence::Save);
   actions.append(actionSave);
   if(!icon->canBeSaved())
      actionSave->setEnabled(false); 

   //Insert Delete key
   QAction *actionDelete = new QAction(this);
   actionDelete->setObjectName(QString::fromUtf8("actionDelete"));
   actionDelete->setText(tr("Remove from Plot"));
   actionDelete->setShortcuts(QKeySequence::Delete);
   actions.append(actionDelete);
   if(!icon->canBeDeleted())
      actionDelete->setEnabled(false); 

   QAction *res=QMenu::exec(actions,view_->mapToGlobal(position));	
   if(res == actionEdit)
      icon->startEditor();
   else if(res == actionSave)
      icon->saveIcon();
   else if(res == actionDelete)
      icon->deleteIcon();

   foreach(QAction *ac,actions)
      delete ac;
}

void MvQLayerWidget::slotFrameChanged()
{
}

void MvQLayerWidget::layersAreAboutToChange()
{
	//Save expand state
	QModelIndexList indexLst=model_->match(model_->index(0,0),
			    Qt::DisplayRole,"*",-1,
		            Qt::MatchWildcard | Qt::MatchRecursive);
	
	expandList_.clear();	
	foreach(QModelIndex index,indexLst)
	{
      QModelIndex proxyIndex = filterModel_->mapFromSource(index);
      if(view_->isExpanded(proxyIndex))
			expandList_ << index;
	}

   // Notify the layer model
   model_->layersAreAboutToChange();
}

/*void MvQLayerWidget::reset(MgQSceneItem *sceneItem,int layerIndex)
{
  	model_->resetLayers(sceneItem);
	
	QModelIndex index=model_->index(layerIndex,0);
	if(!index.isValid())
	{
		index=model_->index(model_->rowCount()-1,0);
	}

	if(index.isValid())
	{
		slotSelectLayer(index);
	}
	else
	{
		slotCheckItemStatus();
	}	
}*/

void MvQLayerWidget::reset(MgQSceneItem *sceneItem,MgQLayerItem *layer)
{
   model_->resetLayers(sceneItem);

	int row=model_->layerToRow(layer);
	QModelIndex index = filterModel_->mapFromSource(model_->index(row,0));
	if(index.isValid())
	{
//		slotSelectLayer(index);
      view_->setCurrentIndex(index);
	}
	else
	{
		slotCheckItemStatus();
	}
	
	//Try to restore the expand state
	foreach(QModelIndex index,expandList_)
	{
		if(model_->hasChildren(index))
		{
         QModelIndex proxyIndex = filterModel_->mapFromSource(index);
         view_->setExpanded(proxyIndex,true);
		}
	}
}

void MvQLayerWidget::reset(MgQSceneItem *sceneItem)
{
   int presId = atoi(sceneItem->layout().id().c_str());
   spModel_->reset();
   vlModel_->reset(presId);
   
   MgQLayerItem *layer=0;
	MgQLayerItem *lastLayer=0;
	
	for(int i=sceneItem->layerItems().count()-1; i >=0; i--)
	{
	  	MgQLayerItem *item=sceneItem->layerItems().at(i);
	  	lastLayer=item;
		
	  	QString str(item->layer().name().c_str());
      QStringList lst=str.split("/");
		if(!lst.isEmpty())
		{
			str=lst.last();
		}

		if(str == lastSelectedLayerText_)
		{  
			layer=item;
		}
	}
		
	if(!layer)
	  	layer=lastLayer;

	//contentsLoaded_=false;
	reset(sceneItem,layer);   
	//contentsLoaded_=true;
}


int MvQLayerWidget::layerAtGlobalPos(const QPoint& p)
{
  	QPoint pv=view_->mapFromGlobal(p);

   QModelIndex index = filterModel_->mapToSource(view_->indexAt(pv));

	MvQLayerContentsIcon *icon=model_->indexToIcon(index);
	if(!icon)
	  	return -1;

	return -1;
	
	//Get the dataUinitId
	/*MvIcon& dropIcon =  cl->GetIconMain ();
	Cached verbTarget = dropIcon.Request ().getVerb ();
	if ( ObjectList::IsDataUnit ( verbTarget ) == true )
	     set_value ( id->header, "_CONTENTS_DATAUNIT_ID", "%d", dropIcon.Id());*/
	
	/*if(index.isValid())
	{
	  	MgQLayerItem *layer=model_->rowToLayer(index.row());
		if(layer)
		{
		  	QString str(layer->layer().name().c_str());
		} 
	}
	
  	*/
}

void MvQLayerWidget::slotIconDropped(const MvQDrop& source, const QModelIndex& target)
{
   // Get the layer information
   MgQLayerItem* layer = model_->layerFromAnyLevel(target);
   if( !layer )
   {
      PlotMod::Instance().UserMessage("Invalid icon drop\n\nDrop icon over Layers     \n");
      return;
   }

   // Consistency check
   int duId;
   if ( !checkDroppedIcon(source,layer,duId) )
   {
      string text = "Invalid icon drop.\n\nThis icon cannot be applied to layer ";
      text += layer->name().toStdString();
      PlotMod::Instance().UserMessage(text.c_str());
      return;
   }
   // Therefore, if the target icon is a dataunit and all the dropped
   // icons are visdefs then these visdefs should be applied only to this
   // dataunit, not to the whole presentable. In order to do so, the
   // output drawing request should have a tag _CONTENTS_DATAUNIT_ID,
   // containing the dataunit id.

   // Get the target Presentable (Page) id
   // Here, the dropping happened into a layer not a presentable.
   // Therefore, first get the layer's first child icon id and then
   // use this id to find the Presentable id
   // int iconId = atoi(layer->layer().id().c_str());  // layer id
//   int iconId = atoi((*it).iconId().c_str());
//   Presentable* pres = Root::Instance().FindSuperPage();
//   int presId = pres->FindBranchIdByIconId(iconId);

#if 0
// Redraw uPlot: option 1: calls the uPlot redraw function
   // Analyse the dropping to determine the type of action to be taken
   string classSource = source.iconClass(0).toStdString();
   string classTarget = icon->type().toStdString();
   if ( classSource == classTarget )  // icons have the same type
   {
      // Read source icon request
      const char* cname = source.iconPath(0).toStdString().c_str();
      string sname = MakeUserPath(cname);
      MvRequest iconRequest;
      iconRequest.read(sname.c_str());

      // Add some hidden parameters. There are certain functions in Metview
      // that relies on them.
      if ( !(const char*)iconRequest("_NAME") )
         iconRequest("_NAME") = cname.c_str();

      if ( !(const char*)iconRequest("_CLASS") )
         iconRequest("_CLASS") = iconRequest.getVerb();

      // Replace target request in the database by the source request
      dataBase.UpdateIcon( icon->id().toInt(),iconRequest );

      // Redraw the whole map
      pres->HasDrawTask(true);
      pres->DrawTask();
   }
#endif


#if 0
// Redraw uPlot: option 2: calls yourself to redraw the plot
   // Create a new drop request
   MvRequest dropRequest("DROP");
   dropRequest("DROP_ID")   = presId;
   dropRequest("_CONTENTS") = 1;

   // Add the target dataunit request
   MvRequest iconRequest;
   string cname;
   string sname;

#if 0
   if ( addDU )
   {
      // Create icon path and read its request
      cname = (*it).iconName();
      sname = MakeUserPath(cname);
      iconRequest.setVerb((*it).iconClass().c_str());
      iconRequest("PATH") = sname.c_str();

      // Add some hidden parameters. There are certain functions
      // in Metview that relies on them.
      if ( !(const char*)iconRequest("_NAME") )
         iconRequest("_NAME") = (const char*)cname.c_str();

      if ( !(const char*)iconRequest("_CLASS") )
         iconRequest("_CLASS") = (const char*)(*it).iconClass().c_str();

      dropRequest = dropRequest + iconRequest;
   }
#endif

   // Create the dropped icons request
   for(int i = 0; i < source.iconNum(); i++)
   {
      // Create icon path and read its request
      cname = source.iconPath(i).toStdString();
      sname = MakeUserPath(cname);
      iconRequest.read(sname.c_str());

      // Add some hidden parameters. There are certain functions
      // in Metview that relies on them.
      if ( !(const char*)iconRequest("_NAME") )
         iconRequest("_NAME") = (const char*)cname.c_str();

      if ( !(const char*)iconRequest("_CLASS") )
         iconRequest("_CLASS") = (const char*)source.iconClass(i).toStdString().c_str();

      if ( addDU )
         iconRequest("_CONTENTS_DATAUNIT_ID") = (const char*)(*it).iconId().c_str();

      dropRequest = dropRequest + iconRequest;
   }

   // Call myself to process the request
   std::ostringstream appName;
   appName << "uPlot" << (long int)getpid();
   MvApplication::callService ( appName.str().c_str(),dropRequest,0 );

   return;
#endif
// Redraw uPlot: option 3: call MvApplication to redraw the plot

   // Create a new drop request
   MvRequest dropRequest("DROP_REQUEST");
// req("BATCH") = drop->batchNumber();
   dropRequest("ACTION") = 3;

   MvRequest subreq("DROP");
   subreq("DROP_ID") = model_->presentableId();
   subreq("_CONTENTS") = 1;
   if ( duId > 0 )
      subreq("_CONTENTS_DATAUNIT_ID") = duId;

   // Create the dropped icons request
   if(source.iconNum() > 0)
   {
      subreq.setValue("ICON_NAME",source.iconPath(0).toStdString().c_str());    
   
      for(int i = 1; i < source.iconNum(); i++)
      {              
         subreq.addValue("ICON_NAME", source.iconPath(i).toStdString().c_str());
      }
   }

#if 0
   for(int i = 0; i < source.iconNum(); i++)
   {
      // Create icon path and read its request
      cname = source.iconPath(i).toStdString();
      sname = MakeUserPath(cname);
      iconRequest.read(sname.c_str());

      // Add some hidden parameters. There are certain functions
      // in Metview that relies on them.
      if ( !(const char*)iconRequest("_NAME") )
         iconRequest("_NAME") = (const char*)cname.c_str();

      if ( !(const char*)iconRequest("_CLASS") )
         iconRequest("_CLASS") = (const char*)source.iconClass(i).toStdString().c_str();

      if ( addDU )
         iconRequest("_CONTENTS_DATAUNIT_ID") = (const char*)(*it).iconId().c_str();

      dropRequest = dropRequest + iconRequest;
   }
#endif

   dropRequest("HEADER") = subreq;

#if 0
   // Add View request if it exists
   if ( owner_ )
   {
   Presentable* pres = Root::Instance().FindSuperPage();
      if(pres)
      {
         MvRequest reqView =pres->GetView().ViewRequest();
         req("_CONTEXT") = reqView;
      }
      //Safety solution
      else
      {
         MvRequest reqView = owner_->Request()("PAGES");
         reqView = reqView("VIEW");
         req("_CONTEXT") = reqView;
      }
   }
#endif

   // Send drop request to the appropriate function
   emit sendDropRequest(&dropRequest);
}

void MvQLayerWidget::slotIconDroppedTopLevel( const MvQDrop& source )
{
   // Redraw uPlot: call MvApplication to redraw the plot
   // Create a new drop request
   MvRequest dropRequest("DROP_REQUEST");
   dropRequest("ACTION") = 3;

   MvRequest subreq("DROP");
   subreq("DROP_ID") = spModel_->presentableId();
   subreq("_CONTENTS") = 1;
//   if ( duId > 0 )
//      subreq("_CONTENTS_DATAUNIT_ID") = duId;

   // Create the dropped icons request
   if(source.iconNum() > 0)
   {
      subreq.setValue("ICON_NAME",source.iconPath(0).toStdString().c_str());    
   
      for(int i = 1; i < source.iconNum(); i++)
      {              
         subreq.addValue("ICON_NAME", source.iconPath(i).toStdString().c_str());
      }
   }

   dropRequest("HEADER") = subreq;

   // Send drop request to the appropriate function
   emit sendDropRequest(&dropRequest);
}

void MvQLayerWidget::slotIconDroppedViewLevel( const MvQDrop& source )
{
   // Redraw uPlot: call MvApplication to redraw the plot
   // Create a new drop request
   MvRequest dropRequest("DROP_REQUEST");
   dropRequest("ACTION") = 3;

   MvRequest subreq("DROP");
   subreq("DROP_ID") = vlModel_->presentableId();
   subreq("_CONTENTS") = 1;

   // Create the dropped icons request
   if(source.iconNum() > 0)
   {
      subreq.setValue("ICON_NAME",source.iconPath(0).toStdString().c_str());    
   
      for(int i = 1; i < source.iconNum(); i++)
      {              
         subreq.addValue("ICON_NAME", source.iconPath(i).toStdString().c_str());
      }
   }

   dropRequest("HEADER") = subreq;

   // Send drop request to the appropriate function
   emit sendDropRequest(&dropRequest);
}

bool MvQLayerWidget::checkDroppedIcon( const MvQDrop& source, MgQLayerItem* layer, int& duId )
{
   // Special dropping case in Metview.
   // Here, the dropping happened into a Layer not a Presentable.
#if 1
   // Get list of icons related to this layer
   duId = -1;
   MvIconList iconList;
   int layerId = atoi(layer->layer().id().c_str());
   Presentable* pres = Root::Instance().FindSuperPage();
   pres->RetrieveIconsFromLayer ( layerId, iconList );
   if ( iconList.empty() )
      return false;

   // Get the target icon class by taking the first icon from the list.
   // If there is a dataUnit, it is the first in the list
   MvListCursor lCursor = iconList.begin();
//qDebug() << iconList.size() << (*lCursor).IconName() << (*lCursor).IconClass() << (*lCursor).Id();
   string targetClass = (*lCursor).IconClass();
#else
   // Get the target icon class by taking the first icon from the list
   duId = -1;
   vector<MetviewIcon >::const_iterator it = layer->layer().iconsBegin();
   assert(it !=  layer->layer().iconsEnd());  //must have at least one icon
   string targetClass = (*it).iconClass();
#endif

   // First, check if target and source icons have all the same "class"
   // (e.g., READ and GRIB are both dataunits).
   string sourceClass;
   bool targetDu = ObjectList::IsDataUnit(targetClass.c_str());
   bool flag = true;
   for(int i = 0; i < source.iconNum(); i++)
   {
      sourceClass = source.iconClass(i).toStdString();
      if ( targetClass != sourceClass )
      {
         // Check if both are dataunits
         if ( !targetDu || !ObjectList::IsDataUnit(sourceClass.c_str()) )
         {
            flag = false;
            break;
         }
      }
   }
   
   if ( flag )
      return true;

   // Target and source icons have not the same class.
   // Second, check an exception: a visdef dropped on a dataunit.
   // Check if the target layer is a dataunit
   if ( !targetDu )
      return false;

   // Check if the dropped icons are all visdefs
   for(int i = 0; i < source.iconNum(); i++)
   {
      sourceClass = source.iconClass(i).toStdString();
      if ( !ObjectList::IsVisDef(sourceClass.c_str()) )
         return false;
   }

   // Exception accepted
   duId = (*lCursor).Id(); //atoi((*it).iconId().c_str());

   return true;
}
