/***************************************************************************
                          photo_foldertree.cpp  -  description
                             -------------------
    begin                : Sun Jan 13 2002
    copyright            : (C) 2002 by Renchi Raju
    email                : renchi@green.tam.uiuc.edu
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <klocale.h>
#include <kiconloader.h>
#include <kdirlister.h>
#include <kfileitem.h>
#include <klineeditdlg.h>
#include <kurl.h>
#include <kurldrag.h>
#include <kmessagebox.h>
#include <kpropsdlg.h>
#include <kio/global.h>
#include <kio/job.h>

#include <qdragobject.h>
#include <qdir.h>
#include <qstring.h>
#include <qpopupmenu.h>
#include <qlist.h>

#include "photo_foldertree.h"
#include "photo_folder.h"


Photo_FolderTree::Photo_FolderTree(QWidget* parent, const char *name):
  KListView(parent, name)
{

  setDragEnabled(true);
  setDropVisualizer(true);
  setDropHighlighter(true);
  setAcceptDrops(true);

  dirLister = new KDirLister;
  dirLister->setDirOnlyMode(true);

  connect( dirLister, SIGNAL(newItems(const KFileItemList&)),
	  SLOT(slot_newItems(const KFileItemList&)) );
  connect( dirLister, SIGNAL(deleteItem(KFileItem*)),
	  SLOT(slot_deleteItem(KFileItem*)) );
  connect( dirLister, SIGNAL(refreshItems(const KFileItemList&)),
	  SLOT(slot_refreshItems(const KFileItemList&)) );


  KURL rootURL;
  rootURL.setPath(QDir::homeDirPath());
  KFileItem* rootFileItem = new KFileItem(rootURL, "inode/directory", -1);
  Photo_Folder* photoRootFolder = new Photo_Folder(this, rootFileItem);
  
  setFolder(photoRootFolder);
  photoRootFolder->setText(0, "Home");
  photoRootFolder->setPixmap(0, SmallIcon("folder_home"));
  photoRootFolder->setOpen(true);

  connect( this,SIGNAL( contextMenu(KListView*, QListViewItem*, const QPoint&) ),
	  this,SLOT( slot_contextMenu(KListView*, QListViewItem*, const QPoint&) ) );

}


Photo_FolderTree::~Photo_FolderTree(){
  delete dirLister;
}

void Photo_FolderTree::setFolder(Photo_Folder* item) {
  
  dirLister->openURL(item->getURL(), false, true);

  if (item->isOpen())
    item->setOpen(false);
  else
    item->setOpen(true);
  
}

Photo_Folder* Photo_FolderTree::findParentFolder(const KURL& url) {

  KURL urlParent(url.directory());

  if (urlParent.cmp(KURL(QDir::homeDirPath()), true) )
    return (Photo_Folder*) firstChild();

  KFileItem* item = dirLister->find(urlParent);
  if (item) return folderMap[item];

  /*  QListIterator<KFileItem> it(dirLister->items());
  for ( ; it.current(); ++it ) {
    KFileItem *fileItem = it.current();
    if ( urlParent.cmp(fileItem->url(), true) ) {
      Photo_Folder* folderItem = folderMap[fileItem];
      return folderItem;
    }
    }*/

  return NULL;

}

void Photo_FolderTree::removeFolderItemFromMap(Photo_Folder* item) {

  QListViewItem* child;

  for (child=item->firstChild(); child; child=child->nextSibling() ) 
    removeFolderItemFromMap((Photo_Folder*)child);

  folderMap.remove(item->getFileItem());

}



void Photo_FolderTree::slot_newItems(const KFileItemList& fileItemList) {


  KFileItemListIterator it(fileItemList);
  for ( ; it.current(); ++it ) {
    Photo_Folder* parentItem = findParentFolder(it.current()->url());
    if (!parentItem) return;
    Photo_Folder* folderItem = new Photo_Folder(parentItem, it.current());
    folderMap.insert(it.current(), folderItem);
  }

}


void Photo_FolderTree::slot_deleteItem(KFileItem* fileItem) {

  if (!fileItem) return;
  if (!folderMap.contains(fileItem)) return;

  Photo_Folder* itemToDelete = folderMap[fileItem];
  if (itemToDelete) {
    
    if (itemToDelete==currentItem()) { 
          setCurrentItem(itemToDelete->parent());
      setSelected(itemToDelete->parent(), true);
    }

    removeFolderItemFromMap(itemToDelete);
    delete itemToDelete;
  }
}

void Photo_FolderTree::slot_refreshItems(const KFileItemList& fileItemList) {

  KFileItemListIterator it(fileItemList);
  for ( ; it.current(); ++it ) {

    KFileItem* fileItem = it.current();
    Photo_Folder* folderItem = folderMap[fileItem];

    // Check if really the folder url has changed
    if (folderItem->oldURL.cmp(folderItem->getURL(), true)) continue;

    if (folderItem) {

      folderItem->refreshItem();
      // if we have any children delete them and close the item
      if (folderItem->childCount() > 0) {
	QListViewItem* child=folderItem->firstChild();
	QListViewItem* nextChild;
	while (child) {
	  nextChild = child->nextSibling();
	  Photo_Folder* folderChild = (Photo_Folder*) child;
	  removeFolderItemFromMap(folderChild);
	  delete folderChild;
	  child = nextChild;
	}
	folderItem->setOpen(false);
      }

    }

  }
}

void Photo_FolderTree::slot_contextMenu(KListView* listview, QListViewItem* item, const QPoint& pos) {

  QPopupMenu menu(this);
  menu.insertItem( SmallIcon("folder_new"), i18n("New folder"), this, SLOT(slot_makeDir()));
  menu.insertSeparator();
  menu.insertItem( SmallIcon("pencil"), i18n("Rename..."), this, SLOT(slot_renameDir()));
  menu.insertItem( SmallIcon("editdelete"), i18n("Delete"), this, SLOT(slot_removeDir()));
  menu.insertSeparator();
  menu.insertItem(i18n("Properties"), this, SLOT(slot_showProperties()));
  menu.exec(pos);

}


void Photo_FolderTree::slot_makeDir() {

  Photo_Folder* item = (Photo_Folder*) currentItem();

  if (!item) return;

  bool ok;
  QString newDir=KLineEditDlg::getText(i18n("Enter the name of the new folder :"),"",&ok,this);
  if (!ok) return;

  KURL newURL(item->getURL());
  newURL.addPath(newDir);
  KIO::Job* job = KIO::mkdir(newURL);

  connect( job, SIGNAL( result( KIO::Job * ) ),
	   this, SLOT( slot_showKIOError( KIO::Job * ) ) );

}

void Photo_FolderTree::slot_renameDir() {

  Photo_Folder* item = (Photo_Folder*) currentItem();

  if (!item) return;

  bool ok;
  QString newDir=KLineEditDlg::getText(i18n("Enter New Name for the folder :"),"",&ok,this);
  if (!ok) return;

  KURL newURL(item->getURL().upURL());
  newURL.addPath(newDir);
  KIO::Job* job = KIO::rename(item->getURL(), newURL, false);

  connect( job, SIGNAL( result( KIO::Job * ) ),
	   this, SLOT( slot_showKIOError( KIO::Job * ) ) );

}

void Photo_FolderTree::slot_removeDir() {

  Photo_Folder* item = (Photo_Folder*) currentItem();

  if (!item) return;

  if ( KMessageBox::questionYesNo(this, 
				  i18n("About to delete Folder " +  item->getURL().path() + "\nAre you sure ?") ) 
       == KMessageBox::No) return;
  
  KIO::Job *job = KIO::del(item->getURL(), false, true);

  connect( job, SIGNAL( result( KIO::Job * ) ),
	   this, SLOT( slot_showKIOError( KIO::Job * ) ) );
}

void Photo_FolderTree::slot_showProperties() {

  if (!currentItem()) return;
  Photo_Folder *folderItem = (Photo_Folder*)  currentItem();
  (void)new KPropertiesDialog(folderItem->getURL());
}

void Photo_FolderTree::slot_showKIOError(KIO::Job* job) {

  if (job->error()) {
    job->showErrorDialog(this);
    return;
  }
}



// ------------- Drag n Drop -------------------------------------------------

void Photo_FolderTree::startDrag() {

  if (!currentItem()) return;
  
  KURL::List urls;
  urls.append( static_cast<Photo_Folder*>(currentItem())->getURL());

  QDragObject* dragObject=KURLDrag::newDrag( urls, this );
  dragObject->setPixmap( *(currentItem()->pixmap(0)) );
  dragObject->dragCopy();

}

void Photo_FolderTree::contentsDragMoveEvent(QDragMoveEvent* event) {

  if (!QUriDrag::canDecode(event)) {
    event->ignore();
    return;
  }

  QPoint point(0,event->pos().y());
  Photo_Folder* newDropTarget=static_cast<Photo_Folder*>( itemAt(contentsToViewport(point)) );

  if (newDropTarget) {
    event->accept();
  } else {
    event->ignore();
  }
  
  if (newDropTarget==dropTarget) return;
  dropTarget=newDropTarget;
  setSelected(dropTarget, true);


}


void Photo_FolderTree::contentsDragLeaveEvent(QDragLeaveEvent*) {
  dropTarget=0L;
}


void Photo_FolderTree::contentsDropEvent(QDropEvent* event) {

  if (!dropTarget) return;

  KURL dest=dropTarget->getURL();

  KURL::List urls;
  KURLDrag::decode(event,urls);


  QPopupMenu menu(this);
  int copyItemID = menu.insertItem( i18n("&Copy") );
  int moveItemID = menu.insertItem( i18n("&Move") );
  
  menu.setMouseTracking(true);
  int id = menu.exec(QCursor::pos());

  if (id!=-1) {
    if (id ==copyItemID) {
      KIO::copy(urls, dest, true);
    } else if (id==moveItemID) {
      KIO::move(urls, dest, true);
    }
  }

}


