 /**************************************************************************
 *   Copyright (C) 2007-2011 by Peter Semiletov                            *
 *   peter.semiletov@gmail.com                                             *
 *                                                                         *
 *   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 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "fman.h"
#include "utils.h"
#include "logmemo.h"


void CFMan::dir_up()
{
  if (dir.path() == "/")
     return;
  
  QString oldcurdir = dir.dirName();

  dir.cdUp();
  nav (dir.path());

  QModelIndex index = index_from_name (oldcurdir);
  tree_view->selectionModel()->setCurrentIndex (index, QItemSelectionModel::Select |
                                                       QItemSelectionModel::Rows);
  tree_view->scrollTo (index);
}


void CFMan::nav (const QString &path)
{
  dir.setPath (path);
  if (! dir.exists())
      return;

  tree_view->setModel (0);

  model->removeRows (0, model->rowCount());
  QFileInfoList lst = dir.entryInfoList (QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot |
                                         QDir::Files | QDir::Drives, QDir::Name |
                                         QDir::DirsFirst | QDir::IgnoreCase | QDir::LocaleAware);

#if defined(Q_WS_WIN) || defined(Q_OS_OS2)

  if (path != "/")
     append_dot_entry ("..");

#else

  if (path.size() != 2)
     append_dot_entry ("..");

#endif

  foreach (QFileInfo fi, lst)
          add_entry (fi);
          
  tree_view->setModel (model);
  connect (tree_view->selectionModel(), SIGNAL(currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT(cb_fman_currentChanged (const QModelIndex &, const QModelIndex &)));
  emit dir_changed (path);
}


const QModelIndex CFMan::index_from_name (const QString &name)
{
  QList <QStandardItem *> lst = model->findItems (name);
  if (lst.size() > 0)
     return model->indexFromItem (lst[0]);
  else
      return QModelIndex();
}


void CFMan::tv_activated (const QModelIndex &index)
{
  QString item_string = index.data().toString();
  
  QString dpath = dir.path();
  
  if (dpath.size() > 1)
     if (dpath.endsWith("/") || dpath.endsWith("\\"))
      	  dpath.truncate(dpath.size() - 1);
    
  QString full_path;
  
  if (dpath == "/")
     full_path = "/" + item_string;
  else
     full_path = dpath + "/" + item_string;
  
  if (item_string == ".." && dir.path() != "/")
     {
      dir_up();
      return;
     }

  if (is_dir (full_path))
     {
      nav (full_path);
      QModelIndex index = model->index (0, 0);
      tree_view->selectionModel()->setCurrentIndex (index, QItemSelectionModel::Select |
                                                           QItemSelectionModel::Rows);

      return;
     }
  else
      emit file_activated (full_path);
}


void CFMan::add_entry (const QFileInfo &fi)
{
  QList<QStandardItem *> items;

  QStandardItem *item = new QStandardItem (fi.fileName());
  if (fi.isDir())
     {
      QFont f = item->font();
      f.setBold (true);
      item->setFont(f);
     }

  item->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
  items.append (item);

  item = new QStandardItem (QString::number (fi.size()));
  item->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEnabled);
  items.append (item);

  item = new QStandardItem (fi.lastModified().toString ("yyyy-MM-dd"));
  item->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEnabled);
  items.append (item);

  model->appendRow (items);
}


void CFMan::append_dot_entry (const QString &fname)
{
  QList<QStandardItem *> items;

  QStandardItem *item = new QStandardItem (fname);
  item->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEnabled);
  items.append (item);

  item = new QStandardItem ("-");
  item->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEnabled);
  items.append (item);

  item = new QStandardItem ("-");
  item->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEnabled);
  items.append (item);

  model->appendRow (items);
}


CFMan::CFMan (QObject *parent): QObject (parent)
{
  model = new QStandardItemModel (0, 3, parent);

  model->setHeaderData (0, Qt::Horizontal, QObject::tr ("Name"));
  model->setHeaderData (1, Qt::Horizontal, QObject::tr ("Size"));
  model->setHeaderData (2, Qt::Horizontal, QObject::tr ("Modified at"));

  tree_view = new CTreeView;
  tree_view->fman = this; 
  tree_view->setRootIsDecorated (false);
  tree_view->setAlternatingRowColors (true);
  tree_view->setModel (model);

  tree_view->setDragEnabled (true);
  
  tree_view->header()->setResizeMode (QHeaderView::ResizeToContents);
  tree_view->header()->setStretchLastSection (false);

  tree_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
  tree_view->setSelectionBehavior (QAbstractItemView::SelectRows);

  connect (tree_view, SIGNAL(activated(const QModelIndex &)), this, SLOT(tv_activated(const QModelIndex &)));

  evfilter = new CTvFmanKeyPressEater;
  tree_view->installEventFilter (evfilter);
  connect (evfilter, SIGNAL(backspacePressed()), this, SLOT(dir_up()));
}


void CFMan::cb_fman_currentChanged (const QModelIndex &current, const QModelIndex &previous )
{
  int row = current.row();
  if (row < 0)
     {
      emit current_file_changed ("", "");
      return;
     }

  QModelIndex i = tree_view->model()->index (row, 0);

  //QString item_string = current.data().toString();
  QString item_string = i.data().toString();

  QString full_path = dir.path() + "/" + item_string;

  if (! is_dir (full_path))
     emit current_file_changed (full_path, item_string);
}


CFMan::~CFMan()
{
  delete evfilter;
}


QString CFMan::get_sel_fname()
{
  if (! tree_view->selectionModel()->hasSelection())
      return QString();

  QModelIndex index = tree_view->selectionModel()->currentIndex();
  QString item_string = index.data().toString();
  QString full_path (dir.path());
  full_path.append ("/").append (item_string);
  return full_path;
}


QStringList CFMan::get_sel_fnames()
{
  if (! tree_view->selectionModel()->hasSelection())
      return QStringList();

  QModelIndexList il = tree_view->selectionModel()->QItemSelectionModel::selectedRows (0);
  QStringList li;

  foreach (QModelIndex index, il)
          {
           QString item_string = index.data().toString();
           if (item_string != "..") 
              {
               QString full_path = dir.path() + "/" + item_string;
               li.append (full_path);
              } 
          }

  return li;
}


void CFMan::refresh()
{
  QString current;

  if (tree_view->selectionModel()->hasSelection())
     {    
      QModelIndex index = tree_view->selectionModel()->currentIndex();
      current = index.data().toString();
     } 

  nav (dir.path());

  QModelIndex index = index_from_name (current);
  tree_view->selectionModel()->setCurrentIndex (index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
  tree_view->scrollTo (index);
}


bool CTvFmanKeyPressEater::eventFilter (QObject *obj, QEvent *event)
{
  if (event->type() == QEvent::KeyPress)
     {
      QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
  
      if (keyEvent->key() == Qt::Key_Backspace)
          emit backspacePressed();

      return false;
     }
  else
      return QObject::eventFilter (obj, event);
}


const QModelIndex CFMan::index_from_idx (int idx)
{
  QStandardItem *item = model->item (idx); 
  if (item)
     return model->indexFromItem (item);
  else
      return QModelIndex();
}


int CFMan::get_sel_index()
{
  if (! tree_view->selectionModel()->hasSelection())
     return -1;

  QModelIndex index = tree_view->selectionModel()->currentIndex();
  return index.row();
}


void CTreeView::mouseMoveEvent (QMouseEvent *event)
{
  if (! (event->buttons() & Qt::LeftButton)) 
     return;

  QStringList l = fman->get_sel_fnames();
  if (l.size() < 1)
     return;
  
  QDrag *drag = new QDrag (this);
  QMimeData *mimeData = new QMimeData;
 
  QList <QUrl> list;

  foreach (QString fn, l)
           list.append (QUrl::fromLocalFile (fn)); 

  mimeData->setUrls (list); 
  drag->setMimeData (mimeData);
 
  if (drag->exec (Qt::CopyAction | 
                  Qt::MoveAction |
                  Qt::LinkAction) == Qt::MoveAction)
     fman->refresh();
    
  event->accept();
}
