/* ====================================================================
 * 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 "ProjectFoldersWidget.h"
#include "ActionStorage.h"
#include "RepositoryDialog.h"
#include "Project.h"
#include "ProjectLvi.h"
#include "RepositoryLvi.h"
#include "WorkingCopyLvi.h"
#include "ScLvi.h"
#include "WcModel.h"
#include "RepositoryModel.h"
#include "DragDropMimeTypes.h"
#include "PostCmdResult.h"
#include "MainWindow.h"
#include "ScModel.h"
#include "ExternProviderImpl.h"
#include "CheckoutDialog.h"
#include "RevisionWidget.h"
#include "events/ScParamEvent.h"
#include "events/ReOrderProjectsEvent.h"
#include "events/CopyWcItemEvent.h"
#include "events/MoveWcItemEvent.h"
#include "commands/StatusParam.h"
#include "commands/ListParam.h"
#include "commands/UpdateParam.h"
#include "commands/CommitParam.h"
#include "commands/CheckoutParam.h"
#include "commands/CopyParam.h"
#include "commands/MoveParam.h"
#include "commands/DiffParam.h"
#include "commands/MkdirParam.h"
#include "commands/SwitchParam.h"
#include "sublib/PathOps.h"
#include "sublib/DragDrop.h"
#include "sublib/Utility.h"
#include "sublib/MessageBox.h"
#include "svn/WcEntry.h"
#include "svn/DirEntry.h"
#include "svn/WcStatus.h"

// qt
#include <QtGui/QAction>
#include <QtGui/QMessageBox>
#include <qdragobject.h>
#include <qpopupmenu.h>
#include <QtCore/QDateTime>
#include <qhbox.h>
#include <qvbox.h>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>



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

class ProjectFoldersWidgetResultVisitor :
  public ParamVisitor<StatusParam>,
  public ParamVisitor<ListParam>,
  public ParamVisitor<UpdateParam>,
  public ParamVisitor<CommitParam>,
  public ParamVisitor<MkdirParam>,
  public ParamVisitor<CheckoutParam>,
  public ParamVisitor<DiffParam>,
  public ParamVisitor<SwitchParam>,
  public ParamVisitor<CopyParam>,
  public ParamVisitor<MoveParam>
{
public:
  ProjectFoldersWidgetResultVisitor(ProjectFoldersWidget* w) : _w(w)
  {
  }

  void visit( MoveParam* p )
  {
  }

  void visit( CopyParam* p )
  {
  }

  void visit( SwitchParam* p )
  {
  }

  void visit( DiffParam* p )
  {
  }

  // wc & rp result
  void visit( CheckoutParam* p )
  {
  }

  // wc & rp result
  void visit( MkdirParam* p )
  {
  }

  void visit( CommitParam* p )
  {
  }

  void visit( UpdateParam* p )
  {
  }

  void visit( StatusParam* p )
  {
    IdCmdData* d = dynamic_cast<IdCmdData*>(p->getCmdData());
    _w->setWorkingCopy( d->get(), p->getStatuss() );
  }

  void visit( ListParam* p )
  {
    IdCmdData* d = dynamic_cast<IdCmdData*>(p->getCmdData());
    _w->setRepository( d->get(), p->getEntries() );
  }

private:
  ProjectFoldersWidget* _w;
};

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

class ProjectFoldersWidget::LviSelectedVisitor :
  public LviVisitor<WorkingCopyLvi>,
  public LviVisitor<RepositoryLvi>,
  public LviVisitor<ProjectLvi>
{
public:
  LviSelectedVisitor( ProjectFoldersWidget* pfw ) : _pfw(pfw)
  {
  }

  void visit( WorkingCopyLvi* lvi )
  {
    _pfw->wcItemSelected();
  }

  void visit( RepositoryLvi* lvi )
  {
    _pfw->rpItemSelected();
  }

  void visit( ProjectLvi* lvi )
  {
    _pfw->prjItemSelected();
  }

private:
  ProjectFoldersWidget* _pfw;
};

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

enum Actions
{
  ActionNew
};

static ActionStorage _actions;


ProjectFoldersWidget::ProjectFoldersWidget( RepositoryModel* rmodel, WcModel* wmodel,
  QWidget *parent, const char *name )
: super(parent,name), TargetId(this), _rpModel(rmodel), _wcModel(wmodel),
  _ctrlKey(false), _prevSelItem(NULL)
{
  setAcceptDrops(true);

  setRootIsDecorated(true);
  setSorting(0,true);
  setItemMargin( 2 );
  setShowToolTips(true);
  setAllColumnsShowFocus(true);
  addColumn( _q("projects") );
  addColumn( _q("revision") );
  setColumnWidthMode( 0, QListView::Maximum );
  setColumnWidthMode( 1, QListView::Maximum );
  setResizeMode( QListView::LastColumn );
  setSelectionMode( QListView::Single );

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

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

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

  connect( this, SIGNAL(onItem(QListViewItem*)), SLOT(onItem(QListViewItem*)) );

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

  WorkingCopyLvi::setupActions(this);
  RepositoryLvi::setupActions(this);
  ProjectLvi::setupActions(this);

  // \todo fix duplicate code with ProjectLvi
  QAction* action;
  action = new QAction( _q("&new project.."), _q("Ctrl+N"), this );
  action->setStatusTip( _q("add a new project") );
  action->setEnabled(true);
  connect( action, SIGNAL(activated()), SLOT(addPrj()) );
  _actions.addAction( ActionNew, action );

  // setup revision popup
  _revPopup = new QPopupMenu(this);
  QHBox* h1 = new QHBox(_revPopup); h1->setMargin(3);
  QHBox* h2 = new QHBox(_revPopup); h2->setMargin(3);

  _rev = new RevisionWidget(false,"NDS","HBCP",0,h1);
  QPushButton* cl = new QPushButton(_q("close"),h2);

  _revPopup->insertItem(h1);
  _revPopup->insertItem(h2);

  connect( cl, SIGNAL(clicked()), SLOT(closeRevPopup()));
}

ProjectFoldersWidget::~ProjectFoldersWidget()
{
}

void ProjectFoldersWidget::customEvent( QCustomEvent* ce )
{
  switch( ce->type() )
  {
  case ScParameterEvent:
    {
      ScParamEvent* pe = dynamic_cast<ScParamEvent*>(ce);

      const sc::Error* err = pe->getError();
      if( err )
      {
        break;
      }

      ProjectFoldersWidgetResultVisitor v(this);
      pe->getParam()->accept(&v);
      break;
    }
  case ScReOrderProjectsEvent:
    {
      ReOrderProjectsEvent* e = dynamic_cast<ReOrderProjectsEvent*>(ce);
      _wcModel->reorderProjects( e->getSrc(), e->getDst() );
      sort();
      break;
    }
  case ScCopyWcItemEvent:
    {
      CopyWcItemEvent* e = dynamic_cast<CopyWcItemEvent*>(ce);
      _wcModel->copy2( sc::String(e->getDest().utf8()), new PostCmdResult(this) );
      break;
    }
  case ScMoveWcItemEvent:
    {
      MoveWcItemEvent* e = dynamic_cast<MoveWcItemEvent*>(ce);
      _wcModel->move2( sc::String(e->getDest().utf8()), new PostCmdResult(this) );
      break;
    }
  default:
    {
      printf( "ProjectFolderWidget: unknown custom event type %d!\n", ce->type() );
    }
  }
}

QDragObject* ProjectFoldersWidget::dragObject()
{
  QListViewItem* item = selectedItem();
  ScLvi*         lvi  = dynamic_cast<ScLvi*>(item);

  if( lvi )
  {
    return lvi->dragObject();
  }
  else
  {
    return 0;
  }
}

void ProjectFoldersWidget::refreshProjects()
{
  ProjectLvi* lvi = dynamic_cast<ProjectLvi* >(firstChild());
  while( lvi )
  {
    lvi->refresh();

    lvi = dynamic_cast<ProjectLvi* >(lvi->nextSibling());
  }

  //triggerUpdate();
}

QPopupMenu* ProjectFoldersWidget::getWorkingCopyMenu()
{
  return WorkingCopyLvi::getMenu();
}

QPopupMenu* ProjectFoldersWidget::getRepositoryMenu()
{
  return RepositoryLvi::getMenu();
}

QPopupMenu* ProjectFoldersWidget::getProjectMenu()
{
  return ProjectLvi::getMenu();
}

void ProjectFoldersWidget::onItem( QListViewItem* item )
{
  ScLvi* lvi = dynamic_cast<ScLvi*>(item);
  assert(lvi);

  lvi->onItem();
}

void ProjectFoldersWidget::expanded( QListViewItem* item )
{
  ScLvi* lvi = dynamic_cast<ScLvi*>(item);
  assert(lvi);

  if( ! _wcModel->isDragging() )
  {
    setSelected(item,true); // Windows
  }

  if( lvi->isSelectable(_prevSelItem) )
  {
    if( ! _wcModel->isDragging() )
    {
      //emit wcStatusNew(); // todo
    }

    lvi->expanded();
  }

  _prevSelItem = item;
}

void ProjectFoldersWidget::collapsed( QListViewItem* item )
{
  ScLvi* lvi = dynamic_cast<ScLvi*>(item);
  assert(lvi);

  setSelected(item,true); // Windows

  if( lvi->isSelectable(_prevSelItem) )
  {
    //emit wcStatusNew(); // todo

    lvi->pressed(false);
  }

  _prevSelItem = item;
}

void ProjectFoldersWidget::mouseButtonPressed( int button, QListViewItem* item, const QPoint& pos, int c )
{
  if( ! item )
  {
    return;
  }

#if 0
  RepositoryLvi *rpLvi = RpLvi_cast(item);
  if( button == Qt::RightButton && c == 1 && rpLvi )
  {
    _rev->setRevision( rpLvi->getProjectItem().getRevision().get() );
    _revPopup->exec(pos);
  }
#endif

  // don't select if...
  if( _ctrlKey || button == Qt::RightButton )
  {
    return;
  }

  // don't select if already selected
  if( _prevSelItem == item )
  {
    return;
  }

  _prevSelItem = item;

  // switch files view
  LviSelectedVisitor v(this);
  ScLvi* lvi = ScLvi_cast(item);
  lvi->accept(&v);

  lvi->pressed(false);
}

void ProjectFoldersWidget::closeRevPopup()
{
  _revPopup->close();

  RepositoryLvi* rpLvi = RpLvi_cast(selectedItem());
  if( rpLvi )
  {
    Project::Item item = rpLvi->getProjectItem();
    item.setRevision(svn::RevisionPtr(_rev->getRevision()));
    rpLvi->setProjectItem(item);
    rpLvi->repaint();
  }
}

void ProjectFoldersWidget::contextMenuRequest( QListViewItem* item, const QPoint& pos, int col )
{
  ScLvi* lvi = dynamic_cast<ScLvi*>(item);

  // no item hit?
  if( ! lvi )
  {
    QPopupMenu* menu = new QPopupMenu(this);
    QAction* action;

    action = _actions.getAction( ActionNew );
    action->addTo(menu);

    menu->exec(pos);

    delete menu;

    return;
  }

  lvi->contextMenuRequest(pos,col);
}


void ProjectFoldersWidget::keyPressEvent( QKeyEvent* e )
{
  if( e->key() == Qt::Key_Control )
  {
    _ctrlKey = true;
  }

  super::keyPressEvent(e);
}

void ProjectFoldersWidget::keyReleaseEvent( QKeyEvent* e )
{
  if( e->key() == Qt::Key_Control )
  {
    _ctrlKey = false;
  }

  super::keyReleaseEvent(e);
}

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

  _ctrlKey = false;

  super::focusOutEvent(e);
}


static QListViewItem* lastLvi = 0;

void ProjectFoldersWidget::dragMoveEvent( QDragMoveEvent* e )
{
  static QTime lastHit;

  QPoint pos = viewport()->mapFromParent(e->pos());

  // drag scroll
  if( visibleHeight() < contentsHeight() )
  {
    // bottom
    if( pos.y() > visibleHeight() - 10 )
    {
      scrollBy(0,5);
    }
    // top
    else if( contentsHeight() && pos.y() < 10 )
    {
      scrollBy(0,-5);
    }
  }

  QListViewItem* lvi = itemAt( pos );

  if( lvi )
  {
    if( lvi != lastLvi )
    {
      lastLvi = lvi;
      lastHit = QTime::currentTime();
    }
    else
    {
      if( lastHit.elapsed() > 1000 )
      {
        if( !lvi->isOpen() )
        {
          lvi->setOpen(true);
        }
      }
    }

    e->accept(lvi->acceptDrop(e));
  }
  else
  {
    bool text = QTextDrag::canDecode(e);
    e->accept( text );
  }
}

void ProjectFoldersWidget::dropEvent( QDropEvent* e )
{
  QPoint p = viewport()->mapFromParent(e->pos());

  QListViewItem* item = itemAt( p );
  ScLvi*         lvi  = dynamic_cast<ScLvi*>(item);

  if( lvi )
  {
    lvi->dropEvent(e);
  }
  else
  {
    QString text;

    if( QTextDrag::decode(e,text) )
    {
      QStringList list = decodeDropText( text, e->format() );
      if( list.size() == 0 )
      {
        return;
      }

      ScModel* model = _wcModel->getModel();
      Project* prj   = model->createProject();
      model->addProject(prj);

      ProjectLvi* prjLvi = new ProjectLvi( this, _rpModel, _wcModel, prj );
      prjLvi->setExpandable(true);

      prjLvi->dropEvent(e);
    }
  }
}

void ProjectFoldersWidget::checkout()
{
  // \todo is this the same as ListWidget: active item!?
  RepositoryLvi* lvi = dynamic_cast<RepositoryLvi*>( currentItem() );
  assert(lvi);
  
  lvi->checkout();
}

void ProjectFoldersWidget::switchx()
{
  RepositoryLvi* lvi = dynamic_cast<RepositoryLvi*>( currentItem() );
  assert(lvi);
  
  lvi->switchx();
}

void ProjectFoldersWidget::update()
{
  WorkingCopyLvi* lvi = dynamic_cast<WorkingCopyLvi*>( currentItem() );
  assert(lvi);

  lvi->update();
}

void ProjectFoldersWidget::updateRev()
{
  WorkingCopyLvi* lvi = dynamic_cast<WorkingCopyLvi*>( currentItem() );
  assert(lvi);
  
  lvi->updateRev();
}

void ProjectFoldersWidget::commit()
{
  WorkingCopyLvi* lvi = dynamic_cast<WorkingCopyLvi*>( currentItem() );
  assert(lvi);

  lvi->commit();
}

void ProjectFoldersWidget::diff()
{
  RepositoryLvi* lvi = dynamic_cast<RepositoryLvi*>( currentItem() );
  assert(lvi);
  RepositoryLvi* lvi2 = dynamic_cast<RepositoryLvi*>( _prevSelItem );

  lvi->diff( lvi2 );
}

void ProjectFoldersWidget::reload()
{
  ScLvi* lvi = dynamic_cast<ScLvi*>(currentItem());
  if( ! lvi )
  {
    return;
  }
  
  lvi->pressed(true);
}

void ProjectFoldersWidget::log()
{
  RepositoryLvi* lvi = dynamic_cast<RepositoryLvi*>( currentItem() );
  assert(lvi);
  
  lvi->log();
}

void ProjectFoldersWidget::logWc()
{
  WorkingCopyLvi* lvi = dynamic_cast<WorkingCopyLvi*>( currentItem() );
  assert(lvi);
  
  lvi->log();
}

void ProjectFoldersWidget::branch()
{
  RepositoryLvi* lvi = dynamic_cast<RepositoryLvi*>( currentItem() );
  assert(lvi);
  
  lvi->branch();
}

void ProjectFoldersWidget::tag()
{
  RepositoryLvi* lvi = dynamic_cast<RepositoryLvi*>( currentItem() );
  assert(lvi);
  
  lvi->tag();
}

void ProjectFoldersWidget::addPrj()
{
  ScModel* model = _wcModel->getModel();

  Project* prj = model->createProject();
  prj->setName( _s("new project..") );

  model->addProject(prj);

  ProjectLvi* lvi = new ProjectLvi( this, _rpModel, _wcModel, prj );
  lvi->setExpandable(true);
  lvi->startRename(0);
}

void ProjectFoldersWidget::renamePrj()
{
  ProjectLvi* lvi = dynamic_cast<ProjectLvi*>( currentItem() );
  assert(lvi);

  lvi->startRename(0);
}

void ProjectFoldersWidget::removePrj()
{
  ProjectLvi* lvi = dynamic_cast<ProjectLvi*>( currentItem() );
  assert(lvi);

  QString msg;
  msg  = _q("Remove the project '%1' ?")
    .arg( QString::fromUtf8(lvi->getProject()->getName()) );

  int answer = msgInformation( _q("subcommander:remove project"), msg,
    _q("&Ok"), _q("&Cancel") );
  
  if( answer != QMessageBox::Ok )
  {
    return;
  }

  takeItem(lvi);
  _wcModel->removeProject(lvi->getProject());
}

void ProjectFoldersWidget::prjSettings()
{
  ProjectLvi* lvi = dynamic_cast<ProjectLvi*>( currentItem() );
  assert(lvi);

  emit prjSettings(lvi->getProject());
}

void ProjectFoldersWidget::addPrjRepository()
{
#if 0
  ProjectLvi* lvi = dynamic_cast<ProjectLvi*>( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _rpModel );
  Project::Item newItem( 0, Project::Item_Repository, sc::NullString,
    sc::NullString );

  ProjectItemProperties* pip = new ProjectItemProperties( newItem, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    Project::Item prjItem = lvi->getProject()->createRepositoryItem();
    Project::Item tmpItem = pip->getItem();
    prjItem.setName( tmpItem.getName() );
    prjItem.setSource( tmpItem.getSource() );
    lvi->getProject()->setItem(prjItem);
    lvi->refresh();
    
    _wcModel->saveProject(lvi->getProject());
  }
#endif
}

void ProjectFoldersWidget::addPrjWorkingCopy()
{
#if 0
  ProjectLvi* lvi = dynamic_cast<ProjectLvi*>( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _wcModel );
  Project::Item newItem( 0, Project::Item_WorkingCopy, sc::NullString,
    sc::NullString );

  ProjectItemProperties* pip = new ProjectItemProperties( newItem, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    Project::Item prjItem = lvi->getProject()->createWorkingCopyItem();
    Project::Item tmpItem = pip->getItem();
    prjItem.setName( tmpItem.getName() );
    prjItem.setSource( tmpItem.getSource() );
    lvi->getProject()->setItem(prjItem);
    lvi->refresh();

    _wcModel->saveProject(lvi->getProject());
  }
#endif
}

void ProjectFoldersWidget::editWcPrjItem()
{
#if 0
  WorkingCopyLvi* lvi = WcLvi_cast( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _wcModel );
  Project::Item item = lvi->getProjectItem();

  ProjectItemProperties* pip = new ProjectItemProperties( item, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    lvi->getProject()->setItem(pip->getItem());
    lvi->setProjectItem(pip->getItem());

    _wcModel->saveProject(lvi->getProject());
  }
#endif
}

void ProjectFoldersWidget::delWcPrjItem()
{
  // we delete the signaling lvi, is this safe?
  WorkingCopyLvi* lvi = WcLvi_cast( currentItem() );
  assert(lvi);

  lvi->getProject()->delItem(lvi->getProjectItem().getId());
  _wcModel->saveProject(lvi->getProject());

  lvi->getProjectLvi()->refresh();
}

void ProjectFoldersWidget::editRpPrjItem()
{
#if 0
  RepositoryLvi* lvi = RpLvi_cast( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _rpModel );
  Project::Item item = lvi->getProjectItem();

  ProjectItemProperties* pip = new ProjectItemProperties( item, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    lvi->getProject()->setItem(pip->getItem());
    lvi->setProjectItem(pip->getItem());

    _wcModel->saveProject(lvi->getProject());

    lvi->getProjectLvi()->refresh();
  }
#endif
}

void ProjectFoldersWidget::delRpPrjItem()
{
  // we delete the signaling lvi, is this safe?
  RepositoryLvi* lvi = RpLvi_cast( currentItem() );
  assert(lvi);

  lvi->getProject()->delItem(lvi->getProjectItem().getId());

  _wcModel->saveProject(lvi->getProject());

  lvi->getProjectLvi()->refresh();
}

void ProjectFoldersWidget::editTrunkBookmark()
{
#if 0
  ProjectLvi* lvi = PrjLvi_cast( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _rpModel );

  Project*      prj  = lvi->getProject();
  Project::Item item = prj->getTrunkItem();

  ProjectItemProperties* pip = new ProjectItemProperties( item, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    lvi->getProject()->setItem(pip->getItem());
    _wcModel->saveProject(lvi->getProject());
    lvi->refresh();
  }
#endif
}

void ProjectFoldersWidget::editBranchesBookmark()
{
#if 0
  ProjectLvi* lvi = PrjLvi_cast( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _rpModel );

  Project*      prj  = lvi->getProject();
  Project::Item item = prj->getBranchesItem();

  ProjectItemProperties* pip = new ProjectItemProperties( item, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    lvi->getProject()->setItem(pip->getItem());
    _wcModel->saveProject(lvi->getProject());
    lvi->refresh();
  }
#endif
}

void ProjectFoldersWidget::editTagsBookmark()
{
#if 0
  ProjectLvi* lvi = PrjLvi_cast( currentItem() );
  assert(lvi);

  ExternProviderImpl ep( _rpModel );

  Project*      prj  = lvi->getProject();
  Project::Item item = prj->getTagsItem();

  ProjectItemProperties* pip = new ProjectItemProperties( item, &ep, this );

  if( pip->exec() == QDialog::Accepted )
  {
    lvi->getProject()->setItem(pip->getItem());
    _wcModel->saveProject(lvi->getProject());
    lvi->refresh();
  }
#endif
}

void ProjectFoldersWidget::prjChanged( Project* prj )
{
  QListViewItem* lvi = firstChild();
  while( lvi )
  {
    ProjectLvi* plvi = PrjLvi_cast(lvi);
    plvi->refresh(prj);
        
    lvi = lvi->nextSibling();
  }
}

void ProjectFoldersWidget::setCurrentWc()
{
  WorkingCopyLvi* lvi = dynamic_cast<WorkingCopyLvi*>(currentItem());

  long id = lvi->getProjectItem().getId();
  lvi->getProject()->setCurWorkingCopy(id);
  _wcModel->saveProject(lvi->getProject());

  repaintContents();
}

/**
 * list result handling starts here.
 */
void ProjectFoldersWidget::setRepository( long lviId, const svn::DirEntries& entries )
{
  //RepositoryLvi* selItem = RpLvi_cast(selectedItem());
  
  if( _rpModel->getRpId() == lviId )
  {
    _rpModel->addEntries(entries);

    emit rpEntryChanged();
  }
}

/**
 * status result handling starts here.
 */
void ProjectFoldersWidget::setWorkingCopy( long lviId, const svn::WcStatuss& statuss )
{
  WorkingCopyLvi* selItem = WcLvi_cast(selectedItem());

  if( _wcModel->getWcId() == lviId )
  {
    _wcModel->addStatus(statuss);

    emit wcStatusChanged();
  }

  if( selItem && selItem->getId() == lviId )
  {
    selItem->setSvnversion(getWcSvnVersion());
    selItem->repaint();
  }
  else
  {
    // find item, set version, repint
  }

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

QString ProjectFoldersWidget::getWcSvnVersion()
{
  WcModel::Version v = _wcModel->getVersion();

  QString vs = QString( "%1" ).arg( v.lowest );
  if( v.highest > v.lowest )
  {
    vs += QString( ":%1" ).arg( v.highest );
  }
  if( v.modified )
  {
    vs += "M";
  }
  if( v.switched )
  {
    vs += "S";
  }

  return vs;
}

void ProjectFoldersWidget::itemRenamed( QListViewItem* item, int col, const QString& text )
{
  ScLvi* lvi = dynamic_cast<ScLvi*>(item);
  if( ! lvi )
  {
    return;
  }

  lvi->renamed(text);
}

void ProjectFoldersWidget::list( long rpId, const sc::String& rpRoot, svn::RevisionPtr rev, Project*prj )
{
  emit rpItemSelected();

  if( _rpModel->getRpId() != rpId )
  {
    // init model
    _rpModel->setProject(prj);
    _rpModel->setRoot( rpId, rpRoot ); // todo rev
    _rpModel->setCurrentEntry( svn::DirEntryPtr(new svn::DirEntry(rpRoot)) );

    emit rpEntryReset();

    ListParam* param = new ListParam( rpRoot, rev->dup(), false, false );

    param->setCmdData( new IdCmdData(rpId) );

    PostCmdResult* pcres = new PostCmdResult(this);

    _rpModel->list( param, pcres );
  }
}

void ProjectFoldersWidget::status( long wcId, const sc::String& wcRoot, Project* prj )
{
#if 0
  emit wcItemSelected();

  if( ! _wcModel->isWorkingCopy(wcRoot) )
  {
    QString msg = _q("%1 is not a working copy. Checkout a new working copy ?")
      .arg( QString::fromUtf8(wcRoot) );

    int answer = msgInformation( _q("subcommander:status"), msg,
      _q("&Ok"), _q("&Cancel") );
  
    if( answer == QMessageBox::Ok )
    {
      ExternProviderImpl externProvider(_wcModel);

      CheckoutDialog *codlg = new CheckoutDialog(&externProvider,
        _wcModel->isCmdRecursive(), false, this );
      codlg->enableWorkingCopyPath(false);

      QString qwcRoot = QString::fromUtf8(wcRoot);
      codlg->setWorkingCopyPath( qwcRoot );

      if( prj->getTagsUrl().getCharCnt() )
      {
        QString url = QString::fromUtf8(prj->getTagsUrl());
        codlg->setRepositoryUrl(url);
      }
      if( prj->getBranchesUrl().getCharCnt() )
      {
        QString url = QString::fromUtf8(prj->getBranchesUrl());
        codlg->setRepositoryUrl(url);
      }
      if( prj->getRepositoryUrl().getCharCnt() )
      {
        QString url = QString::fromUtf8(prj->getRepositoryUrl());
        codlg->setRepositoryUrl(url);
      }

      int result = codlg->exec();

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

      CheckoutParam* param = new CheckoutParam( 
        sc::String(codlg->getRepositoryUrl().utf8()),
        sc::String(codlg->getWorkingCopyPath().utf8()),
        codlg->getPegRevision(), codlg->getRevision(),
        codlg->isRecursive() );

      PostCmdResult* pcres = new PostCmdResult(this);

      _wcModel->checkout( param, pcres );
    }
    return;
  }

  if( _wcModel->getWcId() != wcId )
  {
    // init model
    _wcModel->setProject(prj);
    _wcModel->setRoot( wcId, wcRoot );

    emit wcStatusReset();

    StatusParam* param = new StatusParam( wcRoot,
      new svn::Revision(svn::Revision_Unspecified), _wcModel->getStatusRecurse(),
      true /* that is correct! */, _wcModel->getStatusUpdates(),
      _wcModel->getStatusIgnored(), false );

    param->setCmdData( new IdCmdData(wcId) );

    PostCmdResult* pcres = new PostCmdResult(this);

    _wcModel->status( param, pcres );
  }
#endif
}

void ProjectFoldersWidget::runWcAutoUpdate()
{
  typedef std::vector<WorkingCopyLvi*> WcLvis;
  WcLvis wcLvis;

  QListViewItemIterator it(this);
  while ( it.current() )
  {
    WorkingCopyLvi* lvi = dynamic_cast<WorkingCopyLvi*>(it.current());
    if( lvi && lvi->getProjectItem().getAutoUpdate() )
    {
      wcLvis.push_back(lvi);
    }
    ++it;
  }

  if( wcLvis.size() == 0 )
  {
    return;
  }

  int answer = msgInformation( _q("subcommander:auto update"),
    _q("run automatic working copy update?"), _q("&Ok"), _q("&Cancel") );
  
  if( answer != QMessageBox::Ok )
  {
    return;
  }

  for( WcLvis::iterator it = wcLvis.begin(); it != wcLvis.end(); it++ )
  {
    (*it)->update();
  }
}
