/**
 * ==========================================================================
 * Copyright (c) 2003-2009  Martin Hauner
 *                          http://subcommander.tigris.org
 *
 * This file is part of Subcommander.
 *
 * Subcommander  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.
 *
 * Subcommander  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 Subcommander. If not, see <http://www.gnu.org/licenses/>.
 * ==========================================================================
 */

// sc
#include "config.h"
#include "LogDialog2.h"
#include "LogEntryLvi.h"
#include "RevisionWidget.h"
#include "RepositoryModel.h"
#include "LogViewModel.h"
#include "Project.h"
#include "ExternProviderImpl.h"
#include "ScModel.h"
#include "DiffViewModel.h"
#include "TextEdit.h"
#include "Bookmark.h"
#include "Settings.h"
#include "sublib/ActionStorage.h"
#include "sublib/IconFactory.h"
#include "sublib/MessageBox.h"
#include "sublib/SplitLayout.h"
#include "sublib/Utility.h"
#include "sublib/Splitter.h"
#include "sublib/Gui.h"
#include "sublib/settings/LayoutSettings.h"
#include "svn/ClientTypes.h"
#include "svn/LogEntry.h"
#include "svn/WcStatus.h"
#include "svn/Error.h"
#include "util/Id.h"
#include "util/max.h"

// qt
#include <QtGui/QPushButton>
#include <QtGui/QCheckBox>
#include <QtGui/QListView>
#include <QtGui/QTextEdit>
#include <QtGui/QMessageBox>
#include <QtGui/QSpinBox>
#include <QtGui/QMenuBar>
#include <QtGui/QLineEdit>
#include <QtGui/QLabel>
#include <QtGui/QToolBar>
#include <QtGui/QHeaderView>
#include <QtGui/QTreeWidget>
#include <QtGui/QTreeWidgetItem>
#include <QtGui/QGroupBox>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QRadioButton>
#include <QtGui/QMenu>
#include <QtCore/QList>


enum ActionsLog
{
  ActionLogDiff,
  ActionLogDiffBase,
  ActionLogDiffCommit,
  ActionLogMerge,
  ActionLogUndo,
  ActionLogCat
};

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


LogDialog2::LogDialog2( LogViewModel* model, const QFont& font, QWidget *parent )
: super(parent), TargetId(this), _model(model),
  _findIdx(0), _findLastLvi(0)
{
  setName("LogDialog");
  setCaption( QString(_q("subcommander:log (%1)")).arg(QString::fromUtf8(_model->getName())) );

  _actions = new ActionStorage();
  _prj     = _model->getBookmark()->getProject();

  QWidget* mw = new QWidget(this);
  setCentralWidget(mw);

  QVBoxLayout* vbl = new QVBoxLayout(mw);
  {
    Splitter* h = new Splitter( mw, Qt::Horizontal, Splitter::First );
    vbl->setSpacing(0);
    vbl->addWidget(h,1);
    {
      _revs = new QTreeWidget(h);
      _revs->setColumnCount(3);
      _revs->setSelectionMode(QTreeWidget::ExtendedSelection);
      _revs->setSelectionBehavior(QAbstractItemView::SelectRows);
      _revs->setAllColumnsShowFocus(true);
      _revs->setSortingEnabled(true);
      _revs->setContextMenuPolicy(Qt::CustomContextMenu);
      
      QTreeWidgetItem* header = new QTreeWidgetItem();
      header->setText( 0, _q("revision") );
      header->setText( 1, _q("date") );
      header->setText( 2, _q("author") );
      header->setTextAlignment( 0, Qt::AlignRight );
      header->setTextAlignment( 1, Qt::AlignRight );
      header->setTextAlignment( 2, Qt::AlignLeft );
      _revs->setHeaderItem(header);

      _revs->header()->setResizeMode( QHeaderView::ResizeToContents );
      _revs->header()->setStretchLastSection(true);      
            
      connect( 
        _revs, SIGNAL(itemSelectionChanged()),
        this,  SLOT(updateSelection()) );
      connect( 
        _revs, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
        this,  SLOT(selected(QTreeWidgetItem*,QTreeWidgetItem*)) );
      connect( 
        _revs, SIGNAL(customContextMenuRequested(const QPoint&)),
        this,  SLOT(contextMenuRequest(const QPoint&)) );

      
      Splitter* v = new Splitter( h, Qt::Vertical, Splitter::Last );
      {
        QWidget*     vv = new QWidget(v);
        QVBoxLayout* vl  = new QVBoxLayout(vv);
        vl->setContentsMargins(0,0,0,0);
        {
          _log = new TextEdit(v);
          _log->setWordWrapMode( QTextOption::NoWrap );
          _log->setTextFormat( Qt::PlainText );
          _log->setFont(font);
          _log->setEnabled(false);
          vl->addWidget(_log);

          connect( _log, SIGNAL(textChanged()), SLOT(logChanged()) );

          QHBoxLayout* hb = new QHBoxLayout;
          vl->addLayout(hb);
          hb->addStretch(1);

          _set = new QPushButton(vv);
          _set->setText( _q("&Set") );
          _set->setEnabled(false);
          hb->addWidget(_set);

          connect( _set, SIGNAL(clicked()), SLOT(set()) );
        }

        _paths = new QTreeWidget(v);
        _paths->setColumnCount(2);
        _paths->setSelectionMode(QTreeWidget::SingleSelection);
        _paths->setSelectionBehavior(QAbstractItemView::SelectRows);
        _paths->setAllColumnsShowFocus(true);
        _paths->setSortingEnabled(true);
        _paths->sortItems(1,Qt::Ascending);
        
        QTreeWidgetItem* header = new QTreeWidgetItem();
        header->setText( 0, _q("action") );
        header->setText( 1, _q("path") );
        header->setTextAlignment( 0, Qt::AlignRight );
        header->setTextAlignment( 1, Qt::AlignLeft );
        header->setToolTip( 0, _q("child: copy from rev") );
        header->setToolTip( 1, _q("child: copy from path") );
        _paths->setHeaderItem(header);
        _paths->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
        _paths->header()->setStretchLastSection(true);
        
        connect( 
          _paths, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
          this,   SLOT(clickedPath(QTreeWidgetItem*,int)) );
      }
    }

    vbl->addSpacing(5);
    
    QHBoxLayout* hb = new QHBoxLayout();
    vbl->addLayout(hb);
    {
      QVBoxLayout* lg = new QVBoxLayout();
      lg->setContentsMargins(0,0,0,0);
      hb->addLayout(lg);
      {
        _limitCheck = new QCheckBox(_q("limit"),mw);
        _limitCheck->setChecked(_model->getLimit());
        lg->addWidget(_limitCheck);

        _limit = new QSpinBox(mw);
        _limit->setMinValue(1);
        _limit->setMaxValue(1000000);
        _limit->setValue(_model->getLimitVal());
        lg->addWidget(_limit);
        
        connect( _limitCheck, SIGNAL(toggled(bool)), _model, SLOT(setLimit(bool)) );
        connect( _limitCheck, SIGNAL(toggled(bool)), _limit, SLOT(setEnabled(bool)) );
        connect( _limit, SIGNAL(valueChanged(int)), _model, SLOT(setLimitVal(int)) );        
      }
      
      _rwStart = new RevisionWidget(false,"SDN","HBCP",0,mw);
      _rwStart->setTitle( _q("start revision") );
      hb->addWidget(_rwStart);
      
      _rwStop = new RevisionWidget(false,"NDS","HBCP",0,mw);
      _rwStop->setTitle( _q("stop revision") );
      hb->addWidget(_rwStop);
      
      _rwStart->setRevision(_model->getStartRevision());
      _rwStop->setRevision(_model->getStopRevision());
      
      connect(
              _rwStart, SIGNAL(revChanged(svn::RevisionPtr)),
              _model, SLOT(setStartRevision(svn::RevisionPtr)) );
      connect(
              _rwStop, SIGNAL(revChanged(svn::RevisionPtr)),
              _model, SLOT(setStopRevision(svn::RevisionPtr)) );
    }
    
    QHBoxLayout* hb2 = new QHBoxLayout();
    vbl->addLayout(hb2);
    {
      _diffv = new QRadioButton(mw);
      _diffv->setText( _q("&Visual Diff") );
      _diffv->setChecked(_model->isVisualDiff());
      hb2->addWidget(_diffv);
      
      _diffp = new QRadioButton(mw);
      _diffp->setText( _q("&Patch Diff") );
      _diffp->setChecked(!_model->isVisualDiff());
      hb2->addWidget(_diffp);
      
      connect( _diffv, SIGNAL(toggled(bool)), SLOT(diffToggled(bool)) );

      hb2->addStretch(1);
      _strictHistory = new QCheckBox(_q("&stop on copy"),mw);
      _strictHistory->setChecked(!_model->getCopies());
      hb2->addWidget(_strictHistory);
      
      //_changedPaths = new QCheckBox(_q("&changed paths"),mw);
      //_changedPaths->setChecked(_model->getChanges());
      //vb->addWidget(_changedPaths);
      
      connect( _strictHistory, SIGNAL(toggled(bool)), _model, SLOT(setCopies(bool)) );
      //connect( _changedPaths, SIGNAL(toggled(bool)), _model, SLOT(setChanges(bool)) );
    }
    
    QHBoxLayout* hu = new QHBoxLayout;
    hu->setSpacing(6);
    vbl->addLayout(hu);
    {
      int minWidth = 0;
      
      QLabel* fl = new QLabel( _q("&find"), mw );
      hu->addWidget(fl);

      _find = new QLineEdit(mw);
      hu->addWidget(_find);
      fl->setBuddy(_find);

      _findNext = new QPushButton( _q("&next"), mw );
      _findNext->setDisabled(true);
      hu->addWidget(_findNext);
      minWidth = std::max( minWidth, _findNext->sizeHint().width() );

      _findPrev = new QPushButton( _q("&prev"), mw );
      _findPrev->setDisabled(true);
      hu->addWidget(_findPrev);
      minWidth = std::max( minWidth, _findPrev->sizeHint().width() );

      connect( _find, SIGNAL(textChanged(const QString&)), SLOT(find(const QString&)) );
      connect( _findNext, SIGNAL(clicked()), SLOT(findNext()) );
      connect( _findPrev, SIGNAL(clicked()), SLOT(findPrev()) );
      
      QDialogButtonBox* db = new QDialogButtonBox(mw);
      db->setContentsMargins(0,0,0,0);
      hu->addWidget(db);
      {        
        _run = new QPushButton(mw);
        _run->setText( _q("&Run") );
        _run->setDefault(true);
        db->addButton( _run, QDialogButtonBox::AcceptRole );
        minWidth = std::max( minWidth, _run->sizeHint().width() );
        
        _done = new QPushButton(mw);
        _done->setText( _q("&Done") );
        db->addButton( _done, QDialogButtonBox::RejectRole );
        minWidth = std::max( minWidth, _done->sizeHint().width() );
        
        _findPrev->setMinimumWidth(minWidth);
        _findNext->setMinimumWidth(minWidth);
        _run->setMinimumWidth(minWidth);
        _done->setMinimumWidth(minWidth);
        
        connect( _run,  SIGNAL(clicked()), SLOT(run()) );
        connect( _done, SIGNAL(clicked()), SLOT(close()) );
      }        
    }
  }

  //////////////////////////////////////////////////////////////
  // action setup

  QAction* action;

  // diff
  action = new QAction( _q("&diff.."), this );
  action->setShortcut(  _q("Ctrl+Shift+D") );
  action->setStatusTip( _q("show diff between 2 selected revisions") );
  action->setIcon( IconFactory::createIcon("Diff-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionLogDiff, action );
  connect( action, SIGNAL(triggered()), this, SLOT(diff()) );

  action = new QAction( _q("diff &wc"), this );
  action->setShortcut(  _q("Ctrl+Shift+W") );
  action->setStatusTip( _q("show diff between the selected revision and the working copy") );
  action->setIcon( IconFactory::createIcon("Diff-Normal.png", "WorkingCopy-Overlay2.png") );
  action->setEnabled(false);
  _actions->addAction( ActionLogDiffBase, action );
  connect( action, SIGNAL(triggered()), _model, SLOT(diffwc()) );

  action = new QAction( _q("diff &commit"), this );
  action->setShortcut(  _q("Ctrl+Shift+C") );
  action->setStatusTip( _q("show diff between the selected revision and the previous revision") );
  action->setIcon( IconFactory::createIcon("Diff-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionLogDiffCommit, action );
  connect( action, SIGNAL(triggered()), _model, SLOT(diffc()) );

  // cat
  action = new QAction( _q("ca&t"), this );
  action->setShortcut(  _q("Ctrl+Shift+T") );
  action->setStatusTip( _q("view file") );
  action->setIcon( IconFactory::createIcon("Cat-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionLogCat, action );
  connect( action, SIGNAL(triggered()), _model, SLOT(cat()) );

  // merge
  action = new QAction( _q("&merge.."), this );
  action->setShortcut(  _q("Ctrl+Shift+M") );
  action->setStatusTip( _q("merge revision(s)") );
  action->setIcon( IconFactory::createIcon("Merge-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionLogMerge, action );
  connect( action, SIGNAL(triggered()), SLOT(merge()) );

  // undo
  action = new QAction( _q("&undo.."), this );
  action->setShortcut(  _q("Ctrl+Shift+U") );
  action->setStatusTip( _q("undo commit by reverse merging") );
  action->setIconSet( IconFactory::createIcon("Undo-Normal.png") );
  action->setEnabled( false );
  _actions->addAction( ActionLogUndo, action );
  connect( action, SIGNAL(triggered()), SLOT(undo()) );

  // setup toolbars
  setIconSize( QSize(20,20) );
  setUnifiedTitleAndToolBarOnMac(true);

  QToolBar* tbCommands = new QToolBar(this);
#ifdef Q_WS_MAC
  setUnifiedTitleAndToolBarOnMac(true);
#endif // Q_WS_MAC
  addToolBar(tbCommands);
  {
    tbCommands->addAction( _actions->getAction(ActionLogMerge) );    
    tbCommands->addAction( _actions->getAction(ActionLogUndo) );    
    tbCommands->addAction( _actions->getAction(ActionLogDiff) );    
    tbCommands->addAction( _actions->getAction(ActionLogDiffBase) );    
    tbCommands->addAction( _actions->getAction(ActionLogDiffCommit) );    
    tbCommands->addAction( _actions->getAction(ActionLogCat) );    
  }

  // setup menus
  QMenuBar* mb = new QMenuBar();
  {
    _menu = new QMenu( mb );
    mb->insertItem( _q("&Commands"), _menu );

    QAction* action;
    action = _actions->getAction(ActionLogMerge);
    action->addTo(_menu);

    action = _actions->getAction(ActionLogUndo);
    action->addTo(_menu);
    
    _menu->insertSeparator();

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

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

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

    _menu->insertSeparator();

    action = _actions->getAction(ActionLogCat);
    action->addTo(_menu);
  }

  connect( 
    _model, SIGNAL(addLogEntry(svn::LogEntryPtr)),
    this, SLOT(addLogEntry(svn::LogEntryPtr)) );
  connect( 
    _model, SIGNAL(doneLogEntry()),
    this, SLOT(finished()) );

  Settings s;
  resize( s.layout().getSize( name(), QSize(800,700) ) );
}

LogDialog2::~LogDialog2()
{
  Settings s;
  s.layout().setSize( name(), geometry().size() );

  delete _model;
}

void LogDialog2::updateSelection()
{
  svn::LogEntries entries;
  getSelection(entries);
  _model->setSelection(entries);
  
  svn::LogEntries::size_type size = entries.size();
  _actions->enableAction( ActionLogDiff, size == 1 || size == 2 );
  _actions->enableAction( ActionLogDiffBase, size == 1 && _model->getBookmark()->isWorkingCopy() );
  _actions->enableAction( ActionLogDiffCommit, size == 1 );
  _actions->enableAction( ActionLogCat, size == 1 && !_model->isDir() );
  _actions->enableAction( ActionLogMerge, size > 0 );
  _actions->enableAction( ActionLogUndo, size > 0 );
}

void LogDialog2::addLogEntry( svn::LogEntryPtr log )
{
  LogEntryLvi* lvi = new LogEntryLvi( _revs, log );
  _revs->addTopLevelItem(lvi);

  if( _revs->topLevelItemCount() == 1 )
  {
    _revs->setFocus();
    lvi->setSelected(true);
    selected(lvi,NULL);

    _findNext->setEnabled(true);
    _findPrev->setEnabled(true);
  }
}

void LogDialog2::finished()
{
  _run->setEnabled(true);
  _done->setEnabled(true);
}

void LogDialog2::run()
{
  _run->setEnabled(false);
  _done->setEnabled(false);
  _log->setEnabled(false);
  _set->setEnabled(false);
  _findNext->setEnabled(false);
  _findPrev->setEnabled(false);
  _revs->setFocus();

  _revs->clear();
  _log->clear();
  _paths->clear();

  _model->log();
}

void LogDialog2::selected( QTreeWidgetItem* item, QTreeWidgetItem* old )
{
  if( ! item )
  {
    return;
  }

  LogEntryLvi*           lvi = (LogEntryLvi*)item;
  const svn::LogEntryPtr e   = lvi->getLogEntry();

  _log->setText( QString::fromUtf8(e->getMessage()) );
  _log->setEnabled(true);
  _set->setEnabled(false);

  QFont copyFont = _paths->font();
  copyFont.setPointSizeF(copyFont.pointSizeF() * 0.8);
  
  _paths->clear();
  QList<QTreeWidgetItem*> items;
  const svn::LogEntry::ChangedPaths& paths = e->getPaths();
  for( svn::LogEntry::ChangedPaths::const_iterator it = paths.begin(); it != paths.end(); it++ )
  {
    const svn::LogEntry::Path& path = *it;

    QTreeWidgetItem* item = new QTreeWidgetItem(QTreeWidgetItem::UserType );
    item->setText( 0, QString(path._action) );
    item->setTextAlignment( 0, Qt::AlignRight );
    item->setText( 1, QString::fromUtf8(path._path) );
    item->setTextAlignment( 1, Qt::AlignLeft );

    if(path._copyFromRev >= 0)
    {
      QString copyfromrev = QString().sprintf( "%ld", (unsigned long)path._copyFromRev);

      QTreeWidgetItem* copy = new QTreeWidgetItem( item, QTreeWidgetItem::UserType );
      
      copy->setFont( 0, copyFont );
      copy->setText( 0, copyfromrev );
      copy->setTextAlignment( 0, Qt::AlignRight );
      copy->setFont( 1, copyFont );
      copy->setText( 1, QString::fromUtf8(path._copyFromPath) );
      copy->setTextAlignment( 1, Qt::AlignLeft );
    }    
    items.push_back(item);
  }
  _paths->addTopLevelItems(items);
}

void LogDialog2::clickedPath( QTreeWidgetItem* item, int column )
{
  if( ! item )
  {
    return;
  }
  
  svn::Paths paths;
  getSelectedPaths(paths);
  _model->setSelection(paths);
  
  _model->diffCommitPath();
}  
  
static void setSelection( QTextEdit* log, const QString& text, int pos )
{
  QTextCursor c = log->textCursor();
  c.setPosition(pos);
  c.movePosition(QTextCursor::NextCharacter,QTextCursor::KeepAnchor,text.length());
  log->setTextCursor(c);
}

void LogDialog2::find( const QString& text, bool forward, int findIdx )
{
  LogEntryLvi* lvi = (LogEntryLvi*)_revs->currentItem();

  if( ! lvi )
  {
    return;
  }

  if( lvi != _findLastLvi || text.isEmpty() )
  {
    _findLastLvi = lvi;
    _findIdx     = forward ? 0 : -1;
    findIdx      = _findIdx;
  }

  QString source = QString::fromUtf8(lvi->getLogEntry()->getMessage());

  int pos;
  if( forward )
  {
    pos = source.find( text, findIdx, false );
  }
  else
  {
    pos = source.findRev( text, findIdx, false );
  }

  if( pos != -1 )
  {
    _findIdx = pos;
    setSelection( _log, text, pos );
  }
  else
  {
    int pos = -1;
    while( lvi && pos == -1 )
    {
      if( forward )
      {
        lvi = (LogEntryLvi*)_revs->itemBelow(lvi);
      }
      else
      {
        lvi = (LogEntryLvi*)_revs->itemAbove(lvi);
      }

      if( ! lvi )
      {
        return;
      }

      QString source = QString::fromUtf8(lvi->getLogEntry()->getMessage());

      if( forward )
      {
        pos = source.find( text, 0, false );
      }
      else
      {
        pos = source.findRev( text, -1, false );
      }

      if( pos != -1 )
      {
        _revs->clearSelection();
        _revs->setCurrentItem(lvi);
        lvi->setSelected(true);
        selected(lvi,NULL);
        //todo? automatic? _revs->ensureItemVisible(lvi);

        _findIdx     = pos;
        _findLastLvi = lvi;
        setSelection( _log, text, pos );
      }
    }
  }
}

void LogDialog2::find( const QString& text )
{
  find( text, true, _findIdx );
}

void LogDialog2::findNext()
{
  find( _find->text(), true, _findIdx+1 );
}

void LogDialog2::findPrev()
{
  find( _find->text(), false,
    // if the first char was the last match (_findIdx = 0) we will find
    // the same match again instead of moving to a previous item.
    (_findIdx == 0) ? -1 * (_log->text().length() + 1) : _findIdx-1 );
}

void LogDialog2::getSelectedRevisions( LogEntryLvis& entries )
{
  QTreeWidgetItemIterator it( _revs, QTreeWidgetItemIterator::Selected );
  while( *it )
  {
    entries.push_back( (LogEntryLvi*)*it );
    ++it;
  }
}

void LogDialog2::getSelection( svn::LogEntries& entries )
{
#if 1
  QList<QTreeWidgetItem*> items = _revs->selectedItems();

  for( int idx = 0; idx < items.size(); ++idx )
  {
    entries.push_back( ((LogEntryLvi*)(items.at(idx)))->getLogEntry() );
  }
#else // the code below does not work due to a bug in qt 4.4.0.
  QTreeWidgetItemIterator it( _revs, QTreeWidgetItemIterator::Selected );
  while( *it )
  {
    entries.push_back( ((LogEntryLvi*)*it)->getLogEntry() );
    ++it;
  }
#endif
}

void LogDialog2::getSelectedPaths( svn::Paths& paths )
{
  QTreeWidgetItemIterator it( _paths, QTreeWidgetItemIterator::Selected );
  while( *it )
  {
    paths.push_back( sc::String((*it)->text(1).toUtf8()) );
    ++it;
  }
}

void LogDialog2::logChanged()
{
  LogEntryLvis entries;
  getSelectedRevisions( entries );

  if( entries.size() != 1 )
  {
    return;
  }

  _set->setEnabled(true);
}

void LogDialog2::contextMenuRequest( const QPoint& pos )
{
  _menu->exec(mapToGlobal(pos));
}

void LogDialog2::set()
{
  QString msg = "<qt>";
  msg += " <nobr><center>";
  msg += _q("Overwrite the log message?");
  msg += "</center></nobr>";
  msg += " <nobr><center>";
  msg += _q("Its current value is lost and can NOT be restored!");
  msg += "</center></nobr>";
  msg += "</qt>";

  int answer = msgInformation( _q("subcommander:set log message"), msg,
    _q("&Ok"), _q("&Cancel") );

  if( answer != QMessageBox::Ok )
  {
    return;
  }

  _set->setEnabled(false);

  svn::LogEntries entries;
  getSelection(entries);

  // store changed log message in entry so we don't need to reload it.
  entries[0]->setMessage(sc::String(_log->text().utf8()));

  _model->propsetrev();
}

void LogDialog2::diffToggled(bool)
{
  _model->setVisualDiff(_diffv->isChecked());
}

void LogDialog2::diff()
{
  emit showDiff( _model->createDiffViewModel() );
}

void LogDialog2::merge( bool undo )
{
  emit showMerge( _model->createMergeViewModel(undo) );
}

void LogDialog2::merge()
{
  merge(false);
}

void LogDialog2::undo()
{
  merge(true);
}
