/* ====================================================================
 * Copyright (c) 2003-2008  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 "MainWindow.h"
#include "ListWidget.h"
#include "ScModel.h"
#include "DialogHandler.h"
#include "Cancel.h"
#include "Project.h"
#include "ProjectPropertiesDialog.h"
#include "ExternProviderImpl.h"
#include "Actions.h"
#include "PostProgressCallback.h"
#include "ConfigManager.h"
#include "Controller.h"
#include "Settings.h"
#include "Bookmark.h"
#include "BookmarkViewModel.h"
#include "settings/ProjectSettingsWidget.h"
#include "settings/ProjectSettingsInfo.h"
#include "settings/ToolsSettingsWidget.h"
#include "settings/ToolsSettingsInfo.h"
#include "settings/FontSettingsWidget.h"
#include "settings/FontSettingsInfo.h"
#include "settings/SubversionSettingsWidget.h"
#include "settings/SubversionSettingsInfo.h"
#include "events/DialogEvent.h"
#include "events/LviOnItemEvent.h"
#include "events/ExceptionEvent.h"
#include "events/CustomEvents.h"
#include "sublib/IconFactory.h"
#include "sublib/ActionStorage.h"
#include "sublib/AboutDialog.h"
#include "sublib/ErrorDialog.h"
#include "sublib/SettingsInfo.h"
#include "sublib/SettingsDialog.h"
#include "sublib/DebugSettingsInfo.h"
#include "sublib/DebugSettingsWidget.h"
#include "sublib/TargetRepository.h"
#include "sublib/MessageBox.h"
#include "sublib/Utility.h"
#include "sublib/settings/ColorSettingsWidget.h"
#include "sublib/settings/ColorSettingsInfo.h"
#include "sublib/settings/LayoutSettings.h"
#include "util/Error.h"
#include "util/Condition.h"

// qt
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QMenuBar>
#include <QtGui/QToolBar>
#include <QtGui/QToolButton>
#include <QtGui/QLabel>
#include <QtGui/QLayout>
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
#include <QtGui/QFileDialog>
#include <QtGui/QProgressBar>
#include <QtGui/QFontMetrics>
#include <QtGui/QListView>
#include <QtGui/QToolTip>
#include <QtGui/QKeyEvent>
#ifdef ENABLE_MANUAL
#include <qassistantclient.h>
#endif // ENABLE_MANUAL
#include <QtGui/QAction>
#include <Qt3Support/Q3PopupMenu>
#include <Qt3Support/Q3Header>
#include <Qt3Support/Q3VBox>

// sys
#include <string>
#include <fstream>
#include <math.h>



//\todo replace with QActions
enum MenuIds
{
  pmFile,
  pmTools,
  pmHelp
};


MainWindow::MainWindow( ScModel* model, ConfigManager* cfg, QWidget *parent )
: super(parent), TargetId(this), _config(cfg), _model(model), _assistant(NULL)
{
  TargetRepository::setError(getTid());
 
  setName( "main" );
 
  setCaption( _q("subcommander") );
  _controller = new Controller(model);

  // setup QActions
  _actions = new ActionStorage();
  createActions();

  // setup toolbars, a bit bigger icons look better on MacOSX.
#ifdef Q_WS_MAC
  setIconSize( QSize(22,22) );
  setUnifiedTitleAndToolBarOnMac(true);
#else
  setIconSize( QSize(20,20) );
#endif // Q_WS_MAC
  
  QToolBar* tbPrj = new QToolBar(this);
  tbPrj->setMovable(false);
  addToolBar(tbPrj);
  {
    tbPrj->addAction( _actions->getAction(ActionBookmarkProjectNewWizard) );
    //tbPrj->addSeparator();
  }

  QToolBar* tbCommands = new QToolBar(this);
  tbCommands->setMovable(false);
  addToolBar(tbCommands);
  {
    tbCommands->addAction( _actions->getAction(ActionBookmarkOptionRecursive) );
    //tbCommands->addSeparator();
  }

  QToolBar* tbWc = new QToolBar(this);
  tbWc->setMovable(false);
  addToolBar(tbWc);
  {
    tbWc->addAction( _actions->getAction(ActionBookmarkOptionUpdates) );
    tbWc->addAction( _actions->getAction(ActionBookmarkOptionAutoRefresh) );
    tbWc->addSeparator();
    tbWc->addAction( _actions->getAction(ActionCmdReload) );
    tbWc->addAction( _actions->getAction(ActionWcDiffBase) );
    tbWc->addAction( _actions->getAction(ActionWcUpdateRev) );
    tbWc->addAction( _actions->getAction(ActionWcCommit) );
  }

  // widget setup
  _list = new ListWidget(_controller,_actions,this);
  _list->installChildEventFilter(this);
  super::setCentralWidget(_list);


  QMenuBar* mb = menuBar();
  {
    Q3PopupMenu* m1 = new Q3PopupMenu(mb);
    mb->insertItem( _q("&File"), m1, pmFile );
    _fileMenu = m1;
    {
      m1->insertItem( _q("&Quit"),  qApp, SLOT(quit()), Qt::CTRL+Qt::Key_Q );
    }

    _bookMenu = new Q3PopupMenu(mb);
    mb->insertItem( _q("&Bookmark"), _bookMenu );
    connect( _bookMenu, SIGNAL(aboutToShow()), this, SLOT(showBookMenu()) );

    _itemMenu = new Q3PopupMenu(mb);
    mb->insertItem( _q("&Item View"), _itemMenu );
    connect( _itemMenu, SIGNAL(aboutToShow()), this, SLOT(showItemMenu()) );

    _adminMenu = new Q3PopupMenu(mb);
    mb->insertItem( _q("&Admin"), _adminMenu );
    connect( _adminMenu, SIGNAL(aboutToShow()), this, SLOT(showAdminMenu()) );

    Q3PopupMenu* m1b = new Q3PopupMenu(mb);
    mb->insertItem( _q("&Tools"), m1b, pmTools );
    {
      m1b->insertItem( _q("&Settings"),  this, SLOT(settings()), Qt::CTRL+Qt::Key_S );
    }
    
    Q3PopupMenu* m2 = new Q3PopupMenu(mb);
    mb->insertItem( _q("&Help"), m2 );
    {
      m2->insertItem( _q("A&bout"),  this, SLOT(about()), Qt::CTRL+Qt::Key_B );
#ifdef ENABLE_MANUAL
      m2->insertItem( _q("&Manual"), this, SLOT(manual()), Qt::Key_F1 ); 
#endif // ENABLE_MANUAL
    }
  }
    
  // statusbar
  _sbar = statusBar();
  {
    //_sbar1 = new QLabel(this);
    //sb->addWidget( _sbar1, 0, true );

    _sbar->setSizeGripEnabled(true);
    _sbar->message( _q("Ready"), 5000 );
  }

  Settings s;
  bool success = restoreGeometry( s.layout().getByteArray(
    objectName() + ".geometry", QByteArray() ) );

  if(!success)
    setGeometry( 100,100,800,600 );
}

MainWindow::~MainWindow()
{
  delete _controller;
}

void MainWindow::showEvent( QShowEvent* e )
{
}

void MainWindow::closeEvent( QCloseEvent* e )
{
  Settings s;
  s.layout().setByteArray( objectName() + ".geometry", saveGeometry() );
}

void MainWindow::about()
{
  AboutDialog* ab = new AboutDialog( this );

  ab->exec();

  delete ab;
}

void MainWindow::manual()
{
#ifdef ENABLE_MANUAL
  if( _assistant == NULL )
  {
    _assistant = new QAssistantClient( "/usr/bin", this );
    connect( _assistant, SIGNAL(error(const QString&)), SLOT(manualError(const QString&)));

    QStringList args;
    args << "-profile";
    args << QDir::convertSeparators("/usr/share/doc/subcommander/html/subcommander.adp");
    _assistant->setArguments(args);
  }

  _assistant->openAssistant();
#endif // ENABLE_MANUAL
}

void MainWindow::manualError(const QString& msg)
{
  msgCritical( _q("subcommander:manual"), msg, _q("&Ok") );
} 

void MainWindow::settings()
{
  settings("");
}

void MainWindow::settings( const QString& selected )
{
  SettingsDialog* sd = new SettingsDialog( _q("subcommander:settings"), this );
  SettingsInfo*   si;

#if 0
  // projects root item
  si = new ProjectSettingsInfo( _q("Projects"), "toplevel", 0 );
  si->setSelected(selected);
  sd->addSettingsInfo( si );
  
  // single project settings
  sd->addSettingsWidget( _q("Project Settings"), new ProjectSettingsWidget(&externProvider) );

  const Projects& prjs = _model->getProjects();
  for( Projects::const_iterator it = prjs.begin(); it != prjs.end(); it++ )
  {
    Project* prj = *it;

    si = new ProjectSettingsInfo( QString::fromUtf8(prj->getName()), _q("Project Settings"), prj );
    si->setSelected(selected);
    sd->addSettingsInfo( si, _q("Projects") );
  }
#endif

  int sortIndex = 0;
  ExternProviderImpl externProvider( _model );

  // tools settings
  sd->addSettingsWidget( _q("Diff/Merge Settings"), new ToolsSettingsWidget(&externProvider) );
  sd->addSettingsInfo( new ToolsSettingsInfo( _q("Diff/Merge"), _q("Diff/Merge Settings"), _config, ++sortIndex ) );

  // we currently have only windows specific subversion settings
#ifdef _WIN32
  // subversion settings
  sd->addSettingsWidget( _q("Subversion Settings"), new SubversionSettingsWidget() );
  sd->addSettingsInfo( new SubversionSettingsInfo( _q("Subversion"), _q("Subversion Settings"), _config, ++sortIndex ) );
#endif // _WIN32

  // font settings
  sd->addSettingsWidget( _q("Font Settings"), new FontSettingsWidget() );
  sd->addSettingsInfo( new FontSettingsInfo( _q("Fonts"), _q("Font Settings"), _config, ++sortIndex ) );

  // color settings
  sd->addSettingsWidget( _q("Color Settings"), new ColorSettingsWidget() );
  sd->addSettingsInfo( new ColorSettingsInfo( _q("Colors"), _q("Color Settings"), _config, ++sortIndex ) );

  // debug settings
  sd->addSettingsWidget( _q("Debug Settings"), new DebugSettingsWidget() );
  sd->addSettingsInfo( new DebugSettingsInfo( _q("Debug"), _q("Debug Settings"), _config, ++sortIndex ) );

  sd->exec();

  delete sd;

  _model->saveSettings();
  _controller->updateBookmarks();
}

void MainWindow::prjSettings( Project* prj )
{
  settings( QString::fromUtf8(prj->getName()) );
  _model->saveProject(prj);
}

void MainWindow::showBookMenu()
{
  _bookMenu->clear();

  Bookmark* bm  = _controller->getBookmarkViewModel()->getBookmark();

  if( !bm )
  {
    QAction* action;

    action = _actions->getAction( ActionBookmarkProjectNewWizard );
    action->addTo(_bookMenu);
  }
  else if( bm->isProject() )
  {
    QAction* action;

    action = _actions->getAction( ActionBookmarkProjectNewWizard );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkProjectRemove );
    action->addTo(_bookMenu);

    _bookMenu->insertSeparator();

    action = _actions->getAction( ActionBookmarkProjectNewRepository );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkProjectNewWorkingCopy );
    action->addTo(_bookMenu);

    _bookMenu->insertSeparator();
    
    action = _actions->getAction( ActionBookmarkProjectEditTrunk );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkProjectEditBranches );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkProjectEditTags );
    action->addTo(_bookMenu);
  }
  else if( bm->isRemote() )
  {
    QAction* action;

    action = _actions->getAction( ActionBookmarkLog );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkBranchTag );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkRpCheckout );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkRpSwitch );
    action->addTo(_bookMenu);

    _bookMenu->insertSeparator();

    action = _actions->getAction( ActionBookmarkEdit );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkRemove );
    action->addTo(_bookMenu);
  }
  else if( bm->isWorkingCopy() )
  {
    QAction* action;

    action = _actions->getAction( ActionBookmarkWcUpdate );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkWcUpdateRev );
    action->addTo(_bookMenu);

    _bookMenu->insertSeparator();

    action = _actions->getAction( ActionBookmarkWcCommit );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkLog );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkBranchTag );
    action->addTo(_bookMenu);

    _bookMenu->insertSeparator();

    action = _actions->getAction( ActionBookmarkWcCurrent );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkEdit );
    action->addTo(_bookMenu);

    action = _actions->getAction( ActionBookmarkRemove );
    action->addTo(_bookMenu);
  }
}

void MainWindow::showItemMenu()
{
  _itemMenu->clear();

  Bookmark* bm  = _controller->getBookmarkViewModel()->getBookmark();

  if( !bm )
  {
    QAction* action;

    action = _actions->getAction( ActionItemMenuNoBookmark );
    action->addTo(_itemMenu);
  }
  else if( bm->isProject() )
  {
    QAction* action;

    action = _actions->getAction( ActionItemMenuNoBookmark );
    action->addTo(_itemMenu);
  }
  else if( bm->isRemote() )
  {
    QAction* action;

    action = _actions->getAction( ActionRpLog );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpLogGraph );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpBlame );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionRpBranchTag );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionRpCheckout );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpSwitch );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpDiff );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpMerge );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionRpMkdir );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpRemove );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpImport );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionRpExport );
    action->addTo(_itemMenu);
  }
  else if( bm->isWorkingCopy() )
  {
    QAction* action;

    action = _actions->getAction( ActionWcDiffBase );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    //action = _actions->getAction( ActionWcCommit );
    //action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcLog );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcLogGraph );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcBlame );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionWcAdd );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcRevert );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcRemove );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcUpdateRev );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionWcLock );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcUnlock );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionWcProperties );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcIgnore );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionWcEditConflict );
    action->addTo(_itemMenu);
    action = _actions->getAction( ActionWcResolved );
    action->addTo(_itemMenu);

    _itemMenu->insertSeparator();

    action = _actions->getAction( ActionWcMkdir );
    action->addTo(_itemMenu);

    action = _actions->getAction( ActionWcBranchTag );
    action->addTo(_itemMenu);

    action = _actions->getAction( ActionWcExport );
    action->addTo(_itemMenu);

    action = _actions->getAction( ActionWcCleanup );
    action->addTo(_itemMenu);
  }
}

void MainWindow::showAdminMenu()
{
  _adminMenu->clear();

  QAction* action;

  action = _actions->getAction( ActionAdminMenuCreate );
  action->addTo(_adminMenu);
}

void MainWindow::onBookmarkItem( const QString& text )
{
  _sbar->message( text, 2500 );
}

void MainWindow::customEvent( QEvent* ce )
{
  switch( ce->type() )
  {
    case ScParameterEvent:
    {
      // there was an error, report it..
      // todo
      break;
    }
  case ScDialogEvent:
    {
      DialogEvent*    de = (DialogEvent*)ce;
      DialogHandler*  h  = de->getHandler();

      h->run( this );
      break;
    }
  case ScExceptionEvent:
    {
      ExceptionEvent* ee = (ExceptionEvent*)ce;

      ErrorDialog* edlg = new ErrorDialog( ee->getError(), ee->getStack() );
      edlg->exec();
      delete edlg;

      break;
    }
  default:
    {
      printf( "MainWindow: unknown custom event type %d!\n", ce->type() );
    }
  }
}

bool MainWindow::eventFilter( QObject* t, QEvent* e )
{
  switch( e->type() )
  {
  case ScLviOnItemEvent:
    {
      LviOnItemEvent* oie = (LviOnItemEvent*)e;
      statusBar()->message( oie->getInfo(), 5000 );
      return true;
    }
  default:
    {
      return super::eventFilter(t,e);
    }
  }
}


void MainWindow::keyPressEvent( QKeyEvent* e )
{
  e->ignore();

#if 0
  // AltGr = Qt::Key_Control + Qt::Key_Alt
  if( e->key() == Qt::Key_Control )
  {
    AltGr = true;
  }
  else if( AltGr && e->key() == Qt::Key_Alt )
  {
    AltGr = false;
    _sbar1->setText( _q("recurse: OFF") );
  }
  else
  {
    AltGr = false;
    e->ignore();
  }
#endif
}

void MainWindow::keyReleaseEvent( QKeyEvent* e )
{
  e->ignore();


#if 0
  if( e->key() == Qt::Key_Control )
  {
    AltGr = true;
  }
  else if( AltGr && e->key() == Qt::Key_Alt )
  {
    AltGr = false;
    _sbar1->setText( _q("recurse: option") );
  }
  else
  {
    AltGr = false;
    e->ignore();
  }
#endif
}

ScModel* MainWindow::getModel()
{
  return _model;
}

void MainWindow::runWcAutoUpdate()
{
  _controller->wcAutoUpdate();
}

void MainWindow::createActions()
{
  QAction* action;

  // working copy commands
  action = new QAction( _q("&diff"), this );
  action->setShortcut(  _q("Ctrl+Shift+D") );
  action->setStatusTip( _q("show the differences between working copy and base") );
  action->setIcon( IconFactory::createIcon("Diff-Normal.png", "WorkingCopy-Overlay2.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcDiffBase, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcDiffBase()) );

  action = new QAction( _q("&add item(s)"), this );
  action->setShortcut(  _q("Ctrl+Shift+A") );
  action->setStatusTip( _q("add new file(s) or folder(s) to the working copy") );
  action->setIcon( IconFactory::createIcon("Add-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcAdd, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcAdd()) );

  action = new QAction( _q("re&vert item(s)"), this );
  action->setShortcut(  _q("Ctrl+Shift+V") );
  action->setStatusTip( _q("revert the changes on file(s) or folder(s) in the working copy") );
  action->setIcon( IconFactory::createIcon("Revert-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcRevert, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcRevert()) );

  action = new QAction( _q("&remove item(s)"), this );
  action->setShortcut(  _q("Ctrl+Shift+R") );
  action->setStatusTip( _q("remove file(s) or folder(s) from the working copy") );
  action->setIcon( IconFactory::createIcon("Remove-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcRemove, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcRemove()) );

  action = new QAction( _q("&commit.."), this );
  action->setShortcut(  _q("Ctrl+Shift+C") );
  action->setStatusTip( _q("commit your changes in the working copy to the repository") );
  action->setIcon( IconFactory::createIcon("Commit-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcCommit, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcCommit()) );

  action = new QAction( _q("edit con&flict"), this );
  action->setShortcut(  _q("Ctrl+Shift+F") );
  action->setStatusTip( _q("resolve the conflicts of the selected file") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionWcEditConflict, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcEditConflict()) );

  action = new QAction( _q("resolved conflicts"), this );
  action->setShortcut(  _q("Ctrl+Shift+W") );
  action->setStatusTip( _q("mark the conflicts as resolved") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionWcResolved, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcResolved()) );

  action = new QAction( _q("&log.."), this );
  action->setShortcut(  _q("Ctrl+Shift+L") );
  action->setStatusTip( _q("view the log history of the selected file or folder") );
  action->setIcon( IconFactory::createIcon("Log-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcLog, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcLog()) );

  action = new QAction( _q("log &graph.."), this );
  action->setShortcut(  _q("Ctrl+Shift+G") );
  action->setStatusTip( _q("view the graphical log history of the selected file or folder") );
  action->setIcon( IconFactory::createIcon("LogGraph-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcLogGraph, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcLogGraph()) );

  action = new QAction( _q("properties.."), this );
  action->setShortcut(  _q("Ctrl+Shift+P") );
  action->setStatusTip( _q("modify the properties of the selected file or folder") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionWcProperties, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcProperties()) );

  action = new QAction( _q("svn:ignore"), this );
  action->setShortcut(  _q("Ctrl+Shift+I") );
  action->setStatusTip( _q("ignore the selected file(s) or folder(s)") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionWcIgnore, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcIgnore()) );

  action = new QAction( _q("blam&e.."), this );
  action->setShortcut(  _q("Ctrl+Shift+E") );
  action->setStatusTip( _q("view the blame information") );
  action->setIcon( IconFactory::createIcon("Blame-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcBlame, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcBlame()) );

  action = new QAction( _q("lock item(s).."), this );
  action->setShortcut(  _q("Ctrl+Shift+Y") );
  action->setStatusTip( _q("lock the selected working copy item(s)") );
  action->setIcon( IconFactory::createIcon("Lock-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcLock, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcLock()) );

  action = new QAction( _q("unlock item(s).."), this );
  action->setShortcut(  _q("Ctrl+Shift+Z") );
  action->setStatusTip( _q("unlock the selected working copy item(s)") );
  action->setIcon( IconFactory::createIcon("Unlock-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcUnlock, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcUnlock()) );

  action = new QAction( _q("cleanup"), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("cleanup the working copy path") );
  action->setIcon( IconFactory::createIcon("Cleanup-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcCleanup, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcCleanup()) );

  action = new QAction( _q("m&kdir.."), this );
  action->setShortcut(  _q("Ctrl+Shift+K") );
  action->setStatusTip( _q("create and add a new folder to the working copy") );
  action->setIcon( IconFactory::createIcon("Mkdir-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcMkdir, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcMkdir()) );

  action = new QAction( _q("e&xport.."), this );
  action->setShortcut(  _q("Ctrl+Shift+X") );
  action->setStatusTip( _q("export the working copy path") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionWcExport, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcExport()) );

  action = new QAction( _q("update.."), this );
  action->setShortcut(  _q("Ctrl+Shift+J") );
  action->setStatusTip( _q("update the working copy path or file to a specific revision") );
  action->setIcon( IconFactory::createIcon("Update-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcUpdateRev, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcUpdateRev()) );

  action = new QAction( _q("branch/tag.."), this );
  action->setShortcut(  _q("Ctrl+Shift+B") );
  action->setStatusTip( _q("create a branch/tag from the selected working copy path") );
  action->setIcon( IconFactory::createIcon("BranchTag-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcBranchTag, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcBranchTag()) );

  action = new QAction( _q("cat"), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("view the selected item") );
  //action->setIcon( IconFactory::createIcon("BranchTag-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionWcCat, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(wcCat()) );


  // repository commands
  action = new QAction( _q("&log.."), this );
  action->setShortcut(  _q("Ctrl+Shift+L") );
  action->setStatusTip( _q("view the log history of the selected file or folder") );
  action->setIcon( IconFactory::createIcon("Log-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpLog, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpLog()) );

  action = new QAction( _q("log &graph.."), this );
  action->setShortcut(  _q("Ctrl+Shift+G") );
  action->setStatusTip( _q("view the graphical log history of the selected file or folder") );
  action->setIcon( IconFactory::createIcon("Log-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpLogGraph, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpLogGraph()) );

  action = new QAction( _q("blam&e.."), this );
  action->setShortcut(  _q("Ctrl+Shift+E") );
  action->setStatusTip( _q("view the blame information") );
  action->setIcon( IconFactory::createIcon("Blame-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpBlame, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpBlame()) );

  action = new QAction( _q("branch/tag.."), this );
  action->setShortcut(  _q("Ctrl+Shift+B") );
  action->setStatusTip( _q("create a branch/tag from the selected (folder) url") );
  action->setIcon( IconFactory::createIcon("BranchTag-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpBranchTag, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpBranchTag()) );

  action = new QAction( _q("&diff.."), this );
  action->setShortcut(  _q("Ctrl+Shift+D") );
  action->setStatusTip( _q("show the differences between working copies and urls or working copy and url") );
  action->setIcon( IconFactory::createIcon("Diff-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpDiff, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpDiff()) );

  action = new QAction( _q("&checkout.."), this );
  action->setShortcut(  _q("Ctrl+Shift+C") );
  action->setStatusTip( _q("checkout a working copy from a repository") );
  action->setIcon( IconFactory::createIcon("Checkout.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpCheckout, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpCheckout()) );

  action = new QAction( _q("&switch to.."), this );
  action->setShortcut(  _q("Ctrl+Shift+S") );
  action->setStatusTip( _q("switch working copy to the selected repository url") );
  action->setIcon( IconFactory::createIcon("Switch.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpSwitch, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpSwitch()) );

  action = new QAction( _q("me&rge.."), this );
  action->setShortcut(  _q("Ctrl+Shift+R") );
  action->setStatusTip( _q("merge from the selected repository url into the working copy") );
  action->setIcon( IconFactory::createIcon("Merge-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpMerge, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpMerge()) );

  action = new QAction( _q("m&kdir.."), this );
  action->setShortcut(  _q("Ctrl+Shift+K") );
  action->setStatusTip( _q("create a new directory in the repository") );
  action->setIcon( IconFactory::createIcon("Mkdir-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpMkdir, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpMkdir()) );

  // \todo create icon
  action = new QAction( _q("&import.."), this );
  action->setShortcut(  _q("Ctrl+Shift+I") );
  action->setStatusTip( _q("import a folder at the selected repository url") );
  //action->setIcon( IconFactory::createIcon("Import.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpImport, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpImport()) );

  // \todo create icon
  action = new QAction( _q("e&xport.."), this );
  action->setShortcut(  _q("Ctrl+Shift+X") );
  action->setStatusTip( _q("export a repository url") );
  //action->setIcon( IconFactory::createIcon("Export.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpExport, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpExport()) );

  action = new QAction( _q("&remove items"), this );
  action->setShortcut(  _q("Ctrl+Shift+O") );
  action->setStatusTip( _q("remove file(s) or folder(s) from the repository") );
  action->setIcon( IconFactory::createIcon("Remove-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpRemove, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpRemove()) );

  action = new QAction( _q("view item"), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("view the selected item") );
  action->setIcon( IconFactory::createIcon("Cat-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionRpCat, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(rpCat()) );


  // working copy bookmarks
  action = new QAction( _q("&update"), this );
  action->setShortcut(  _q("Ctrl+Shift+U") );
  action->setStatusTip( _q("update the working copy path or file to the head revision") );
  action->setIcon( IconFactory::createIcon("Update-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkWcUpdate, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmUpdate()) );

  action = new QAction( _q("update.."), this );
  action->setShortcut(  _q("Ctrl+Shift+J") );
  action->setStatusTip( _q("update the working copy path to a specific revision") );
  action->setIcon( IconFactory::createIcon("Update-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkWcUpdateRev, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmUpdateRev()) );

  action = new QAction( _q("c&ommit.."), this );
  action->setShortcut(  _q("Ctrl+Shift+O") );
  action->setStatusTip( _q("commit changes in the working copy to the repository") );
  action->setIcon( IconFactory::createIcon("Commit-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkWcCommit, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmCommit()) );


  // repository bookmarks
  action = new QAction( _q("&checkout.."), this );
  action->setShortcut(  _q("Ctrl+Shift+C") );
  action->setStatusTip( _q("checkout a working copy from a repository") );
  action->setIcon( IconFactory::createIcon("Checkout.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkRpCheckout, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmCheckout()) );

  action = new QAction( _q("&switch to.."), this );
  action->setShortcut(  _q("Ctrl+Shift+S") );
  action->setStatusTip( _q("switch working copy to the selected repository url") );
  action->setIcon( IconFactory::createIcon("Switch.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkRpSwitch, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmSwitch()) );


  // working copy & repository bookmarks
  action = new QAction( _q("&log.."), this );
  action->setShortcut(  _q("Ctrl+Shift+L") );
  action->setStatusTip( _q("view the log history of the selected bookmark") );
  action->setIcon( IconFactory::createIcon("Log-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkLog, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmLog()) );

  action = new QAction( _q("branch/tag.."), this );
  action->setShortcut(  _q("Ctrl+Shift+B") );
  action->setStatusTip( _q("create a branch/tag from the selected bookmark") );
  action->setIcon( IconFactory::createIcon("BranchTag-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkBranchTag, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(bmBranchTag()) );

  // project bookmarks
  BookmarkViewModel* bvm = _controller->getBookmarkViewModel();

  action = new QAction( _q("&new project"), this );
  action->setShortcut(  _q("Ctrl+N") );
  action->setStatusTip( _q("add a new project") );
  action->setIcon( IconFactory::createIcon("ProjectNew-Normal.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectNew, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(createNewProjectSimple()) );

  action = new QAction( _q("&new project.."), this );
  action->setShortcut(  _q("Ctrl+W") );
  action->setStatusTip( _q("add a new project using the project setup wizard") );
  action->setIcon( IconFactory::createIcon("ProjectNewWizard-Normal.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectNewWizard, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(createNewProject()) );

  // \todo create icon
  action = new QAction( _q("&remove project"), this );
  action->setShortcut(  _q("Ctrl+R") );
  action->setStatusTip( _q("remove the selected project") );
  //action->setIcon( IconFactory::createIcon("ProjectRemove.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectRemove, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(removeBookmark()) );

  // \todo create icon
  action = new QAction( _q("new repository.."), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("add a new repository bookmark") );
  //action->setIcon( IconFactory::createIcon("ProjectNewRepository.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectNewRepository, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(addBookmarkRepository()) );

  // \todo create icon
  action = new QAction( _q("new working copy.."), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("add a new working copy bookmark") );
  //action->setIcon( IconFactory::createIcon("ProjectNewWorkingCopy.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectNewWorkingCopy, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(addBookmarkWorkingCopy()) );

  // \todo create icon
  action = new QAction( _q("edit trunk.."), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("edit the trunk bookmark") );
  //action->setIcon( IconFactory::createIcon("ProjectEditTrunk.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectEditTrunk, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(editBookmarkTrunk()) );

  // \todo create icon
  action = new QAction( _q("edit branches.."), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("edit the branches bookmark") );
  //action->setIcon( IconFactory::createIcon("ProjectEditBranches.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectEditBranches, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(editBookmarkBranches()) );

  // \todo create icon
  action = new QAction( _q("edit tags.."), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("edit the tags bookmark") );
  //action->setIcon( IconFactory::createIcon("ProjectEditTags.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectEditTags, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(editBookmarkTags()) );

  /** @obsolete ?? */
  action = new QAction( _q("rename project"), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("rename the selected project") );
  //action->setIcon( IconFactory::createIcon("ProjectRename-Normal.png") );
  action->setEnabled(true);
  _actions->addAction( ActionBookmarkProjectRename, action );

#if 0
  action = new QAction( _q("project settings.."), QString(""), parent );
  action->setStatusTip( _q("open project settings") );
  action->setEnabled(true);
  parent->connect( action, SIGNAL(activated()), SLOT(prjSettings()) );
  _actions.addAction( ActionSettings, action );
#endif

  // bookmark commands
  action = new QAction( _q("se&t current"), this );
  action->setShortcut(  _q("Ctrl+T") );
  action->setStatusTip( _q("set the current target working copy path") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkWcCurrent, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(setCurrent()) );

  action = new QAction( _q("&edit.."), this );
  action->setShortcut(  _q("Ctrl+E") );
  action->setStatusTip( _q("edit bookmark") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkEdit, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(editBookmark()) );

  action = new QAction( _q("&delete"), this );
  action->setShortcut(  _q("Ctrl+D") );
  action->setStatusTip( _q("delete bookmark") );
  //action->setIcon( IconFactory::createIcon("") );
  action->setEnabled(false);
  _actions->addAction( ActionBookmarkRemove, action );
  connect( action, SIGNAL(triggered()), bvm, SLOT(removeBookmark()) );


  // bookmark options
  action = new QAction( _q("updates"), this );
  action->setShortcut(  _q("U") );
  action->setStatusTip( _q("working copy option: show items with updates in the repository") );
  action->setIcon( IconFactory::createToggleIcon("Updates.png", "ToggleOn.png") );
  action->setToggleAction(true);
  action->setEnabled(false);
  action->setOn(false);
  _actions->addAction( ActionBookmarkOptionUpdates, action );
  connect( action, SIGNAL(toggled(bool)), bvm, SLOT(toggleUpdate(bool)) );

  action = new QAction( _q("recursive"), this );
  action->setShortcut(  _q("C") );
  action->setStatusTip( _q("command option: run commands recursive") );
  action->setIcon( IconFactory::createToggleIcon("Recursive.png", "ToggleOn.png") );
  action->setToggleAction(true);
  action->setEnabled(false);
  action->setOn(false);
  _actions->addAction( ActionBookmarkOptionRecursive, action );
  connect( action, SIGNAL(toggled(bool)), bvm, SLOT(toggleRecursive(bool)) );

  action = new QAction( _q("auto refresh"), this );
  action->setShortcut(  _q("T") );
  action->setStatusTip( _q("working copy option: automatically refresh") );
  action->setIcon( IconFactory::createToggleIcon("AutoRefresh.png", "ToggleOn.png") );
  action->setToggleAction(true);
  action->setEnabled(false);
  action->setOn(false);
  _actions->addAction( ActionBookmarkOptionAutoRefresh, action );
  connect( action, SIGNAL(toggled(bool)), bvm, SLOT(toggleAutoRefresh(bool)) );


  // special commands
  action = new QAction( _q("reload"), this );
  action->setShortcut(  _q("R") );
  action->setStatusTip( _q("command: reload the selected repository or working copy") );
  action->setIcon( IconFactory::createIcon("Reload-Normal.png") );
  action->setEnabled(false);
  _actions->addAction( ActionCmdReload, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(reload()) );


  // misc
  action = new QAction( _q("no bookmark selected"), this );
  action->setStatusTip( _q("select a bookmark to make the menu visible!") );
  _actions->addAction( ActionItemMenuNoBookmark, action );


  action = new QAction( _q("new repository.."), this );
  //action->setShortcut(  _q("") );
  action->setStatusTip( _q("create a local repository") );
  //action->setIcon( IconFactory::createIcon("AdminNewRepository.png") );
  action->setEnabled(true);
  _actions->addAction( ActionAdminMenuCreate, action );
  connect( action, SIGNAL(triggered()), _controller, SLOT(adminCreate()) );
}
