/* ====================================================================
 * Copyright (c) 2003-2006, Martin Hauner
 *                          http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

// sc
#include "config.h"
#include "RepositoryFilesWidget.h"
#include "RepositoryLvi.h"
#include "DirEntryLvi.h"
#include "ActionStorage.h"
#include "CursorSupport.h"
#include "RepositoryModel.h"
#include "LogGraphDialog.h"
#include "CopyDialog.h"
#include "BlameDialog.h"
#include "SwitchDialog.h"
#include "ImportDialog.h"
#include "ExportDialog.h"
#include "MkdirDialog.h"
#include "ErrorSupport.h"
#include "PostCmdResult.h"
#include "ExternProviderImpl.h"
#include "DragDropMimeTypes.h"
#include "ScDragObject.h"
#include "DragInfo.h"
#include "dialogs/CopyDialogCmd.h"
#include "dialogs/CheckoutDialogCmd.h"
#include "commands/ScCmd.h"
#include "commands/PropListParam.h"
#include "commands/ListParam.h"
#include "commands/SwitchParam.h"
#include "commands/DiffParam.h"
#include "commands/ImportParam.h"
#include "commands/ExportParam.h"
#include "commands/MkdirParam.h"
#include "commands/MoveParam.h"
#include "commands/DeleteParam.h"
#include "events/ScParamEvent.h"
#include "util/Id.h"
#include "svn/ClientTypes.h"
#include "svn/Revision.h"
#include "svn/PropListItem.h"
#include "svn/Error.h"

// qt
#include <QtGui/QApplication>
#include <qpopupmenu.h>
#include <QtGui/QAction>
#include <qheader.h>
#include <QtGui/QToolTip>
#include <QtCore/QTimer>

// sys
#include <map>


///////////////////////////////////////////////////////////////////////////////

typedef SimpleCmdData<DirEntryLvi*> DirEntryLviCmdData;

///////////////////////////////////////////////////////////////////////////////

class RepositoryFilesWidgetVisitor :
  public ParamVisitor<PropListParam>,
  public ParamVisitor<CopyParam>,
  public ParamVisitor<SwitchParam>,
  public ParamVisitor<CheckoutParam>,
  public ParamVisitor<MergeParam>,
  public ParamVisitor<ImportParam>,
  public ParamVisitor<ExportParam>,
  public ParamVisitor<MkdirParam>
{
public:
  RepositoryFilesWidgetVisitor()
  {
  }

  void visit( PropListParam* p )
  {
    DirEntryLviCmdData* d = dynamic_cast<DirEntryLviCmdData*>(p->getCmdData());

    if( ! d )
    {
      // TODO log( "cmd initiator no longer available" )
    }
    else
    {
      DirEntryLvi*        lvi   = d->get();
      svn::PropListItems& items = p->getItems();
      //lvi->clear();

      for( svn::PropListItems::iterator it = items.begin(); it != items.end(); it++ )
      {
        svn::PropListItemPtr            item  = *it;
        const svn::PropListItem::Props& props = item->getProps();

        for( svn::PropListItem::Props::const_iterator it = props.begin(); it != props.end(); it++ )
        {
          new QListViewItem( lvi, QString::fromUtf8((*it).first) );
        }
      }
    }
  }

  void visit( CopyParam* p )
  {
  }

  void visit( SwitchParam* p )
  {
  }

  void visit( CheckoutParam* p )
  {
  }

  void visit( MergeParam* p )
  {
  }

  void visit( ImportParam* p )
  {
  }

  void visit( ExportParam* p )
  {
  }

  void visit( MkdirParam* p )
  {
  }
};

///////////////////////////////////////////////////////////////////////////////

enum Actions
{
  ActionLog,
  ActionBlame,
  ActionBranch,
  ActionTag,
  ActionSwitch,
  ActionDiff,
  ActionMerge,
  ActionMkdir,
  ActionImport,
  ActionExport,
  ActionCheckout,
  ActionRemove,
  ActionLogGraph
};


RepositoryFilesWidget::RepositoryFilesWidget( RepositoryModel* rpModel,
  QWidget* eventTarget, QWidget *parent, const char *name )
: super(parent,name), TargetId(this), _rpModel(rpModel),
  _eventTarget(eventTarget), _menu(NULL), _doubleClick(false),
  _clearItems(false)
{
  QTimer* timer = new QTimer(this);
  connect( timer, SIGNAL(timeout()), this, SLOT(dragTimeout()) );
  _dragInfo  = new DragInfo(timer);

  setAcceptDrops(true);

  setSelectionMode( QListView::Extended );
  //setRootIsDecorated(true);
  setItemMargin( 2 );
  setShowToolTips( true );
  setAllColumnsShowFocus(true);
  addColumn( _q("repository file/folder") );
  addColumn( _q("last rev") /*"last revision"*/ );
  addColumn( _q("size") );
  addColumn( _q("props")/*"properties"*/ );
  addColumn( _q("last author") );
  addColumn( _q("last time") );
  addColumn( "" );
  setColumnAlignment( 1, Qt::AlignRight );
  setColumnAlignment( 2, Qt::AlignRight );
  setColumnAlignment( 3, Qt::AlignRight );
  setColumnAlignment( 4, Qt::AlignRight );
  setColumnAlignment( 5, Qt::AlignRight );
  setColumnAlignment( 6, Qt::AlignLeft );
  setResizeMode(QListView::LastColumn);

  connect( this, SIGNAL(selectionChanged()), SLOT(updateSelection()) );

  connect( this, SIGNAL(contextMenuRequested(QListViewItem*,const QPoint&,int)),
    SLOT(contextMenuRequest(QListViewItem*,const QPoint&,int)) );

  connect( this, SIGNAL(itemRenamed(QListViewItem*,int,const QString&)),
    SLOT(itemRenamed(QListViewItem*,int,const QString&)) );

  connect( this, SIGNAL(expanded(QListViewItem*)), SLOT(expanded(QListViewItem*)) );
  connect( this, SIGNAL(collapsed(QListViewItem*)), SLOT(collapsed(QListViewItem*)) );

  connect( this, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)),
    SLOT(doubleClicked(QListViewItem*,const QPoint&,int)) );

  //connect( this, SIGNAL(expanded(QListViewItem*)), SLOT(proplist(QListViewItem*)) );

  {
    _actions = new ActionStorage();
    QAction* action;

    action = new QAction( _q("&log.."), _q("Ctrl+Shift+L"), this );
    action->setStatusTip( _q("view the log history of the selected item") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(log()) );
    _actions->addAction( ActionLog, action );

    action = new QAction( _q("log &graph.."), _q("Ctrl+Shift+G"), this );
    action->setStatusTip( _q("view the graphical log history of the selected item") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(loggraph()) );
    _actions->addAction( ActionLogGraph, action );

    action = new QAction( _q("blam&e.."), _q("Ctrl+Shift+E"), this );
    action->setStatusTip( _q("view blame information of the selected item") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(blame()) );
    _actions->addAction( ActionBlame, action );

    action = new QAction( _q("&branch.."), _q("Ctrl+Shift+B"), this );
    action->setStatusTip( _q("create a branch from the selected repository url") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(branch()) );
    _actions->addAction( ActionBranch, action );

    action = new QAction( _q("&tag.."), _q("Ctrl+Shift+T"), this );
    action->setStatusTip( _q("create a tag from the selected repository url") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(tag()) );
    _actions->addAction( ActionTag, action );

    action = new QAction( _q("&switch to.."), _q("Ctrl+Shift+S"), this );
    action->setStatusTip( _q("switch working copy to the selected repository url") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(switchx()) );
    _actions->addAction( ActionSwitch, action );

    action = new QAction( _q("&diff.."), _q("Ctrl+Shift+D"), this );
    action->setStatusTip( _q("show the differences between repository paths") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(diff()) );
    _actions->addAction( ActionDiff, action );

    action = new QAction( _q("me&rge.."), _q("Ctrl+Shift+R"), this );
    action->setStatusTip( _q("merge from the selected repository url into the working copy") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(merge()) );
    _actions->addAction( ActionMerge, action );

    action = new QAction( _q("m&kdir.."), _q("Ctrl+Shift+K"), this );
    action->setStatusTip( _q("create a new directory in the repository") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(mkdir()) );
    _actions->addAction( ActionMkdir, action );

    action = new QAction( _q("&import.."), _q("Ctrl+Shift+I"), this );
    action->setStatusTip( _q("import a folder at the selected repository url") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(import()) );
    _actions->addAction( ActionImport, action );

    action = new QAction( _q("e&xport.."), _q("Ctrl+Shift+X"), this );
    action->setStatusTip( _q("export a repository url") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(exportx()) );
    _actions->addAction( ActionExport, action );

    action = new QAction( _q("&checkout.."), _q("Ctrl+Shift+C"), this );
    action->setStatusTip( _q("checkout a working copy from a repository") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(checkout()) );
    _actions->addAction( ActionCheckout, action );

    action = new QAction( _q("&remove items"), _q("Ctrl+Shift+O"), this );
    action->setStatusTip( _q("remove file(s) or folder(s) from the repository") );
    action->setEnabled(false);
    connect( action, SIGNAL(activated()), SLOT(remove()) );
    _actions->addAction( ActionRemove, action );
  }

  {
    _menu = new QPopupMenu(qApp->mainWidget());
    QAction* action;

    action = _actions->getAction( ActionLog );
    action->addTo(_menu);
    action = _actions->getAction( ActionLogGraph );
    action->addTo(_menu);

    action = _actions->getAction( ActionBlame );
    action->addTo(_menu);

    _menu->insertSeparator();

    action = _actions->getAction( ActionBranch );
    action->addTo(_menu);
    action = _actions->getAction( ActionTag );
    action->addTo(_menu);

    _menu->insertSeparator();

    action = _actions->getAction( ActionCheckout );
    action->addTo(_menu);
    action = _actions->getAction( ActionSwitch );
    action->addTo(_menu);
    action = _actions->getAction( ActionDiff );
    action->addTo(_menu);
    action = _actions->getAction( ActionMerge );
    action->addTo(_menu);

    _menu->insertSeparator();

    action = _actions->getAction( ActionMkdir );
    action->addTo(_menu);
    action = _actions->getAction( ActionRemove );
    action->addTo(_menu);    
    action = _actions->getAction( ActionImport );
    action->addTo(_menu);
    action = _actions->getAction( ActionExport );
    action->addTo(_menu);
  }
}

RepositoryFilesWidget::~RepositoryFilesWidget()
{
  delete _actions;
  delete _dragInfo;
}

void RepositoryFilesWidget::clear()
{
  _entries.clear();
  super::clear();
}

void RepositoryFilesWidget::focusInEvent( QFocusEvent* e )
{
  if( e->reason() == QFocusEvent::Popup )
  {
    return;
  }

  updateSelection();
}

void RepositoryFilesWidget::focusOutEvent( QFocusEvent* e )
{
  if( e->reason() == QFocusEvent::Popup )
  {
    return;
  }

  _actions->disableActions();
}

void RepositoryFilesWidget::customEvent( QCustomEvent* ce )
{
  switch( ce->type() )
  {
  case ScParameterEvent:
    {
      RepositoryFilesWidgetVisitor v;
      ScParamEvent* pe = dynamic_cast<ScParamEvent*>(ce);
      pe->getParam()->accept(&v);
      break;
    }
  default:
    break;
  }
}

QDragObject* RepositoryFilesWidget::dragObject()
{
  return new ScDragObject(ScMimeTypeRpFilesItem,_rpModel,this);
}

void RepositoryFilesWidget::dragTimeout()
{
  // drag scroll
  if( visibleHeight() < contentsHeight() )
  {
    int delta = _dragInfo->getScrollDelta(contentsHeight(),visibleHeight());
    if( delta != 0 )
    {
      scrollBy( 0, delta );
      return;
    }
  }
  
  // drag open/close
  _dragInfo->handleIdleItem();  
}

void RepositoryFilesWidget::dragMoveEvent( QDragMoveEvent* e )
{
  QPoint pos = viewport()->mapFromParent(e->pos());
  _dragInfo->setDragPos(pos);
  
  QListViewItem* lvi = itemAt( pos );
  _dragInfo->setCurrLvi(lvi);
  
  if( lvi )
  {
    e->accept(lvi->acceptDrop(e));
  }
  else
  {
    e->accept(false);
  }
  
  _dragInfo->startTimer();
}

void RepositoryFilesWidget::dragLeaveEvent( QDragLeaveEvent* e )
{
  _dragInfo->stopTimer();
}

void RepositoryFilesWidget::dropEvent( QDropEvent* e )
{
  _dragInfo->stopTimer();
  
  QPoint         pos = viewport()->mapFromParent(e->pos());
  QListViewItem* item = itemAt( pos );
  DirEntryLvi*   lvi  = dynamic_cast<DirEntryLvi*>(item);

  if( ! lvi )
    return;

  if( e->action() == QDropEvent::Copy )
  {
    e->accept();
    _rpModel->copy2( lvi->getEntry()->getName(), new PostCmdResult(this) );
  }
  else if( e->action() == QDropEvent::Move )
  {
    e->accept();
    _rpModel->move2( lvi->getEntry()->getName(), new PostCmdResult(this) );
  }
}

QPopupMenu* RepositoryFilesWidget::getMenu()
{
  return _menu;
}

void RepositoryFilesWidget::reload()
{
  _clearItems = true;

  list( _rpModel->getCurrentUrl(), true );
}

void RepositoryFilesWidget::itemRenamed( QListViewItem* item, int col, const QString& text )
{
  DirEntryLvi* lvi = dynamic_cast<DirEntryLvi*>(item);

  QString newName = lvi->getParentUrl() + "/" + text;

  svn::Paths paths;
  paths.push_back(lvi->getEntry()->getName());

  MoveParam* param = new MoveParam(
    paths , new svn::Revision(svn::Revision_Unspecified),
    sc::String(newName.utf8()), _rpModel->isCmdForce() );
  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->move( param, pcres );
}

void RepositoryFilesWidget::contextMenuRequest( QListViewItem* item, const QPoint& p ,int col )
{
  _menu->exec(p);
}

void RepositoryFilesWidget::getSelection( svn::DirEntries& entries )
{
  QListViewItemIterator it( this, QListViewItemIterator::Selected );
  while( it.current() )
  {
    entries.push_back( ((DirEntryLvi*)it.current())->getEntry() );
    ++it;
  }
}

void RepositoryFilesWidget::updateSelection()
{
  svn::DirEntries entries;
  getSelection( entries );
  _rpModel->setSelection( entries );
  bool hasSelection = entries.size() > 0;

  // enable/disable actions based on current selection
  _actions->enableAction( ActionLog, hasSelection );
  _actions->enableAction( ActionBlame, _rpModel->isFile() );
  _actions->enableAction( ActionBranch, _rpModel->isDir() );
  _actions->enableAction( ActionTag, _rpModel->isDir() );
  _actions->enableAction( ActionSwitch, _rpModel->isDir() );
  _actions->enableAction( ActionCheckout, _rpModel->isDir() );
  _actions->enableAction( ActionDiff, hasSelection );
  _actions->enableAction( ActionMerge, hasSelection );
  _actions->enableAction( ActionMkdir, _rpModel->isDir() );
  _actions->enableAction( ActionRemove, hasSelection );
  _actions->enableAction( ActionImport, _rpModel->isDir() );
  _actions->enableAction( ActionExport, _rpModel->isDir() );
  _actions->enableAction( ActionLogGraph, hasSelection );
}

void RepositoryFilesWidget::collapsed( QListViewItem* item )
{
  // ignore calls caused by a double click
  if( _doubleClick )
  {
    _doubleClick = false;
  }
}

void RepositoryFilesWidget::expanded( QListViewItem* item )
{
  // ignore calls caused by a double click
  if( _doubleClick )
  {
    _doubleClick = false;
    return;
  }

  DirEntryLvi* lvi = dynamic_cast<DirEntryLvi*>(item);
  list( lvi->getEntry()->getName(), false );
}

void RepositoryFilesWidget::doubleClicked( QListViewItem* item, const QPoint& p, int col )
{
  DirEntryLvi* lvi = dynamic_cast<DirEntryLvi*>(item);
  if( !lvi || !lvi->getEntry()->isDir() )
  {
    return;
  }

  sc::String target;

  if( lvi->text(0) == "." )
  {
    // parent
    target = _rpModel->getParentUrl();
  }
  else
  {
    // child
    target = lvi->getEntry()->getName();
  }

  if( target.isEmpty() )
  {
    // no target, then there is no parent
    return;
  }

  _rpModel->setCurrentUrl( target );
  _rpModel->setCurrentEntry( lvi->getEntry() );
  _clearItems  = true;
  _doubleClick = true;

  list( target, false );
}

void RepositoryFilesWidget::list( const sc::String& url, bool reload )
{
  ListParam* param = new ListParam( url,
    new svn::Revision(svn::Revision_Unspecified), false, reload );

  param->setCmdData( new IdCmdData(_rpModel->getRpId()) );

  PostCmdResult* pcres = new PostCmdResult(_eventTarget);

  _rpModel->list( param, pcres );
}

void RepositoryFilesWidget::proplist( QListViewItem* item )
{
  DirEntryLvi*      lvi  = static_cast<DirEntryLvi*>(item);
  const sc::String& name = lvi->getEntry()->getName();
  sc::String        path = _rpModel->getCurrentUrl();
  path += "/";
  path += name;

  PropListParam* param = new PropListParam( path, 
    new svn::Revision(svn::Revision_Unspecified), false );
  param->setCmdData( new DirEntryLviCmdData(lvi) );
  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->proplist( param, pcres );
}

void RepositoryFilesWidget::updateView()
{
  if( _clearItems )
  {
    clear();
    _clearItems = false;
  }

  QString rpCurrentUrl;
  rpCurrentUrl = QString::fromUtf8(_rpModel->getCurrentUrl());
  setColumnText( 0, rpCurrentUrl );

  updateViewTree();
}

void RepositoryFilesWidget::updateViewTree()
{
  setRootIsDecorated(true);

  const RepositoryModel::MapEntry& entries = _rpModel->getNewEntries();

  for( RepositoryModel::MapEntry::const_iterator it = entries.begin(); it != entries.end(); it++ )
  {
    const svn::DirEntryPtr entry = (*it).second;

    // ignore duplicate entries
    std::pair<Entries::iterator,bool> pair =
      _entries.insert( Entries::value_type(entry->getName(),0) );

    if( ! pair.second )
    {
      continue;
    }

    // get parent lvi

    QString url    = QString::fromUtf8(entry->getName());
    QString last   = url.section( '/', -1 );
    QString parent = url.left( url.length() -last.length() -1 );
    
    Entries::iterator parIt = _entries.find( sc::String(parent.utf8()) );
    if( parIt != _entries.end() )
    {
      // child items
      DirEntryLvi* lvi = new DirEntryLvi( (*parIt).second, entry );
      lvi->setParentUrl( parent );

      if( entry->isDir() )
      {
        lvi->setExpandable(true);
      }

      pair.first->second = lvi;
    }
    else
    {
      // root item
      DirEntryLvi* lvi = new DirEntryLvi( this, entry );
      lvi->setParentUrl( url );

      if( entry->isDir() )
      {
        lvi->setExpandable(true);
      }
      _doubleClick = true;
      lvi->setOpen(true);

      pair.first->second = lvi;
    }
  }

  if( horizontalScrollBar()->isVisible() )
  {
    adjustColumn(0);
  }
}

void RepositoryFilesWidget::log()
{
#if 0
  QListViewItemIterator it( this, QListViewItemIterator::Selected );
  assert( it.current() );

  QListViewItem*   item  = it.current();
  svn::DirEntryPtr entry = ((DirEntryLvi*)item)->getEntry();

  LogDialog* ldlg = new LogDialog( _rpModel, _rpModel->getProject(),
    entry->getName(), entry->isDir() );

  ldlg->show();
#endif
}

void  RepositoryFilesWidget::blame()
{
#if 0
  BlameDialog* dlg = new BlameDialog( _rpModel );

  svn::Paths paths;
  _rpModel->getSelection(paths);

  dlg->setSource( paths.front() );

  dlg->show();
#endif
}

void RepositoryFilesWidget::branch()
{
  CopyDialogCmd copy( this, getTid(), _rpModel );

  svn::Paths paths;
  _rpModel->getSelection(paths);

  QString srcPath = QString::fromUtf8(paths.front());
  QString dstPath = QString::fromUtf8(_rpModel->getProject()->getBranchesUrl());

  copy.run( srcPath, dstPath );
}

void  RepositoryFilesWidget::tag()
{
  CopyDialogCmd copy( this, getTid(), _rpModel );

  svn::Paths paths;
  _rpModel->getSelection(paths);

  QString srcPath = QString::fromUtf8(paths.front());
  QString dstPath = QString::fromUtf8(_rpModel->getProject()->getTagsUrl());

  copy.run( srcPath, dstPath );
}

void RepositoryFilesWidget::switchx()
{
#if 0
  ExternProviderImpl externProvider(_rpModel);

  SwitchDialog* dlg =
    new SwitchDialog( &externProvider, _rpModel->isCmdRecursive(), this );
  dlg->enableRepositoryUrl(false);

  svn::Paths paths;
  _rpModel->getSelection(paths);
  QString url = QString::fromUtf8(paths.front());
  dlg->setRepositoryUrl(url);

  QString wc = QString::fromUtf8(_rpModel->getProject()->getCurWorkingCopyPath());
  dlg->setWorkingCopyPath(wc);

  int result = dlg->exec();

  if( result != QDialog::Accepted )
  {
    return;
  }

  SwitchParam* param = new SwitchParam(sc::String(dlg->getWorkingCopyPath()),
    paths.front(), dlg->getRevision(), dlg->isRecursive() );

  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->switchx( param, pcres );
#endif
}

void RepositoryFilesWidget::diff()
{
#if 0
  svn::DirEntries paths;
  _rpModel->getSelection(paths);

  if( paths.size() < 1 )
  {
    assert( false );
    return;
  }

  Project* prj = _rpModel->getProject();
  DiffDialogCmd* diff = new DiffDialogCmd( 0, _rpModel, prj, false, false ); 

  QString url1    = QString::fromUtf8(paths.front()->getName());
  bool    folder1 = paths.front()->isDir();

  QString url2    = url1;
  if( paths.size() == 2 )
  {
    url2 = QString::fromUtf8(paths.back()->getName());
  }

  diff->run( url1, url2, &svn::RevHead, &svn::RevHead, folder1 );
#endif
}

void RepositoryFilesWidget::merge()
{
#if 0
  Project* prj = _rpModel->getProject();
  MergeDialogCmd* merge = new MergeDialogCmd( 0, getTid(), _rpModel, prj, false, false ); 

  svn::Paths paths;
  _rpModel->getSelection(paths);

  QString url1 = QString::fromUtf8(paths.front());
  QString url2 = url1;
  if( paths.size() == 2 )
  {
    url2 = QString::fromUtf8(paths.back());
  }
  QString wc = QString::fromUtf8(prj->getCurWorkingCopyPath());

  merge->run( url1, url2, &svn::RevHead, &svn::RevHead, wc );
#endif
}

void RepositoryFilesWidget::mkdir()
{
  MkdirDialog* mdlg = new MkdirDialog( this );

  int result = mdlg->exec();
  if( result != QDialog::Accepted )
  {
    return;
  }

  svn::Paths sel;
  _rpModel->getSelection(sel);

  svn::Paths paths;

  for( svn::Paths::iterator it = sel.begin(); it != sel.end(); it++ )
  {
    sc::String path = (*it);
    path += "/" + mdlg->getFolder().utf8();

    paths.push_back( path );
  }

  MkdirParam*    param = new MkdirParam(paths);
  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->mkdir( param, pcres );
}

void RepositoryFilesWidget::import()
{
  ExternProviderImpl externProvider(_rpModel);

  ImportDialog* dlg =
    new ImportDialog( &externProvider, _rpModel->isCmdRecursive(), this );

  svn::Paths paths;
  _rpModel->getSelection(paths);

  dlg->setDstUrl( QString::fromUtf8(paths.front()) );

  int result = dlg->exec();

  if( result != QDialog::Accepted )
  {
    return;
  }

  ImportParam*   param = dlg->getParameters();
  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->import( param, pcres );
}

void RepositoryFilesWidget::exportx()
{
  ExternProviderImpl externProvider(_rpModel);

  ExportDialog* dlg =
    new ExportDialog( &externProvider, _rpModel->isCmdForce(), this );

  svn::Paths paths;
  _rpModel->getSelection(paths);

  dlg->initSrcUrl(QString::fromUtf8(paths.front()) );

  int result = dlg->exec();

  if( result != QDialog::Accepted )
  {
    return;
  }

  ExportParam*   param = dlg->getParameters();
  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->exportx( param, pcres );
}

void RepositoryFilesWidget::checkout()
{
  CheckoutDialogCmd co( this, getTid(), _rpModel );

  svn::Paths paths;
  _rpModel->getSelection(paths);
  Project* prj = _rpModel->getProject();
  QString srcPath = QString::fromUtf8(paths.front());
  QString dstPath = QString::fromUtf8(prj->getCurWorkingCopyPath());

  co.run( srcPath, dstPath, prj );

  emit prjChanged(prj);
}

void RepositoryFilesWidget::remove()
{
  svn::DirEntries items;
  _rpModel->getSelection(items);

  svn::Paths rpItems;

  for( svn::DirEntries::iterator it = items.begin(); it != items.end(); it++ )
  {
    rpItems.push_back( (*it)->getName() );
  }

  DeleteParam*   param = new DeleteParam( rpItems, false );
  PostCmdResult* pcres = new PostCmdResult(this);

  _rpModel->remove( param, pcres );
}

void RepositoryFilesWidget::loggraph()
{
#if 0
  QListViewItemIterator it( this, QListViewItemIterator::Selected );
  assert( it.current() );

  QListViewItem*   item  = it.current();
  svn::DirEntryPtr entry = ((DirEntryLvi*)item)->getEntry();

  LogGraphDialog* dlg = new LogGraphDialog( _rpModel, _rpModel->getProject(),
    entry->getName(), entry->isDir() );

  dlg->show();
  dlg->run();
#endif
}
