diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp
index dbf8adf4b78c8dc8b25add6fe6b0600cd9a59deb..41268e79f07cddc638050f83b9b73f0ff85f2ad5 100644
--- a/src/plugins/cvs/cvscontrol.cpp
+++ b/src/plugins/cvs/cvscontrol.cpp
@@ -53,9 +53,9 @@ bool CVSControl::supportsOperation(Operation operation) const
     case AddOperation:
     case DeleteOperation:
     case AnnotateOperation:
+    case OpenOperation:
         break;
     case MoveOperation:
-    case OpenOperation:
     case CreateRepositoryOperation:
     case SnapshotOperations:
         rc = false;
@@ -64,10 +64,10 @@ bool CVSControl::supportsOperation(Operation operation) const
     return rc;
 }
 
-bool CVSControl::vcsOpen(const QString & /* fileName */)
+bool CVSControl::vcsOpen(const QString &fileName)
 {
-    // Open for edit: N/A
-    return true;
+    const QFileInfo fi(fileName);
+    return m_plugin->edit(fi.absolutePath(), QStringList(fi.fileName()));
 }
 
 bool CVSControl::vcsAdd(const QString &fileName)
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 6ed72f93b2cad6ce20ad0c31e7c8b65ad5f755b6..84f7dc19f35e501ec2a209e1b82309e6effaf814 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -85,6 +85,9 @@ static inline QString msgLogParsingFailed()
 static const char * const CMD_ID_CVS_MENU    = "CVS.Menu";
 static const char * const CMD_ID_ADD                = "CVS.Add";
 static const char * const CMD_ID_DELETE_FILE        = "CVS.Delete";
+static const char * const CMD_ID_EDIT_FILE          = "CVS.EditFile";
+static const char * const CMD_ID_UNEDIT_FILE        = "CVS.UneditFile";
+static const char * const CMD_ID_UNEDIT_REPOSITORY  = "CVS.UneditRepository";
 static const char * const CMD_ID_REVERT             = "CVS.Revert";
 static const char * const CMD_ID_SEPARATOR0         = "CVS.Separator0";
 static const char * const CMD_ID_DIFF_PROJECT       = "CVS.DiffAll";
@@ -99,7 +102,12 @@ static const char * const CMD_ID_ANNOTATE_CURRENT   = "CVS.AnnotateCurrent";
 static const char * const CMD_ID_STATUS             = "CVS.Status";
 static const char * const CMD_ID_UPDATE             = "CVS.Update";
 static const char * const CMD_ID_PROJECTLOG         = "CVS.ProjectLog";
+static const char * const CMD_ID_PROJECTCOMMIT      = "CVS.ProjectCommit";
 static const char * const CMD_ID_REPOSITORYLOG      = "CVS.RepositoryLog";
+static const char * const CMD_ID_REPOSITORYDIFF     = "CVS.RepositoryDiff";
+static const char * const CMD_ID_REPOSITORYSTATUS   = "CVS.RepositoryStatus";
+static const char * const CMD_ID_REPOSITORYUPDATE   = "CVS.RepositoryUpdate";
+static const char * const CMD_ID_SEPARATOR3         = "CVS.Separator3";
 
 static const VCSBase::VCSBaseEditorParameters editorParameters[] = {
 {
@@ -148,6 +156,11 @@ Core::IEditor* locateEditor(const char *property, const QString &entry)
     return 0;
 }
 
+static inline bool messageBoxQuestion(const QString &title, const QString &question, QWidget *parent = 0)
+{
+    return QMessageBox::question(parent, title, question, QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes;
+}
+
 // ------------- CVSPlugin
 CVSPlugin *CVSPlugin::m_cvsPluginInstance = 0;
 
@@ -157,6 +170,9 @@ CVSPlugin::CVSPlugin() :
     m_addAction(0),
     m_deleteAction(0),
     m_revertAction(0),
+    m_editCurrentAction(0),
+    m_uneditCurrentAction(0),
+    m_uneditRepositoryAction(0),
     m_diffProjectAction(0),
     m_diffCurrentAction(0),
     m_logProjectAction(0),
@@ -168,6 +184,10 @@ CVSPlugin::CVSPlugin() :
     m_annotateCurrentAction(0),
     m_statusProjectAction(0),
     m_updateProjectAction(0),
+    m_commitProjectAction(0),
+    m_diffRepositoryAction(0),
+    m_updateRepositoryAction(0),
+    m_statusRepositoryAction(0),
     m_submitCurrentLogAction(0),
     m_submitDiffAction(0),
     m_submitUndoAction(0),
@@ -326,6 +346,28 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes
 
     cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR1, globalcontext));
 
+    m_editCurrentAction = new Utils::ParameterAction(tr("Edit"), tr("Edit \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+    command = ami->registerAction(m_editCurrentAction, CMD_ID_EDIT_FILE, globalcontext);
+    command->setAttribute(Core::Command::CA_UpdateText);
+    connect(m_editCurrentAction, SIGNAL(triggered()), this, SLOT(editCurrentFile()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
+
+    m_uneditCurrentAction = new Utils::ParameterAction(tr("Unedit"), tr("Unedit \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+    command = ami->registerAction(m_uneditCurrentAction, CMD_ID_UNEDIT_FILE, globalcontext);
+    command->setAttribute(Core::Command::CA_UpdateText);
+    connect(m_uneditCurrentAction, SIGNAL(triggered()), this, SLOT(uneditCurrentFile()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
+
+    m_uneditRepositoryAction = new QAction(tr("Unedit Repository"), this);
+    command = ami->registerAction(m_uneditRepositoryAction, CMD_ID_UNEDIT_REPOSITORY, globalcontext);
+    connect(m_uneditRepositoryAction, SIGNAL(triggered()), this, SLOT(uneditCurrentRepository()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
+
+    cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR2, globalcontext));
+
     m_diffProjectAction = new Utils::ParameterAction(tr("Diff Project"), tr("Diff Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
     command = ami->registerAction(m_diffProjectAction, CMD_ID_DIFF_PROJECT,
         globalcontext);
@@ -356,7 +398,26 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes
     cvsMenu->addAction(command);
     m_commandLocator->appendCommand(command);
 
-    cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR2, globalcontext));
+    m_commitProjectAction = new Utils::ParameterAction(tr("Commit Project"), tr("Commit Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+    command = ami->registerAction(m_commitProjectAction, CMD_ID_PROJECTCOMMIT, globalcontext);
+    command->setAttribute(Core::Command::CA_UpdateText);
+    connect(m_commitProjectAction, SIGNAL(triggered()), this, SLOT(commitProject()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
+
+    cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR3, globalcontext));
+
+    m_diffRepositoryAction = new QAction(tr("Diff Repository"), this);
+    command = ami->registerAction(m_diffRepositoryAction, CMD_ID_REPOSITORYDIFF, globalcontext);
+    connect(m_diffRepositoryAction, SIGNAL(triggered()), this, SLOT(diffRepository()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
+
+    m_statusRepositoryAction = new QAction(tr("Repository Status"), this);
+    command = ami->registerAction(m_statusRepositoryAction, CMD_ID_REPOSITORYSTATUS, globalcontext);
+    connect(m_statusRepositoryAction, SIGNAL(triggered()), this, SLOT(statusRepository()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
 
     m_logRepositoryAction = new QAction(tr("Repository Log"), this);
     command = ami->registerAction(m_logRepositoryAction, CMD_ID_REPOSITORYLOG, globalcontext);
@@ -364,6 +425,12 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes
     cvsMenu->addAction(command);
     m_commandLocator->appendCommand(command);
 
+    m_updateRepositoryAction = new QAction(tr("Update Repository"), this);
+    command = ami->registerAction(m_updateRepositoryAction, CMD_ID_REPOSITORYUPDATE, globalcontext);
+    connect(m_updateRepositoryAction, SIGNAL(triggered()), this, SLOT(updateRepository()));
+    cvsMenu->addAction(command);
+    m_commandLocator->appendCommand(command);
+
     m_commitAllAction = new QAction(tr("Commit All Files"), this);
     command = ami->registerAction(m_commitAllAction, CMD_ID_COMMIT_ALL,
         globalcontext);
@@ -522,7 +589,6 @@ void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
 
     const bool hasTopLevel = currentState().hasTopLevel();
     m_commandLocator->setEnabled(hasTopLevel);
-    m_logRepositoryAction->setEnabled(hasTopLevel);
 
     const QString currentFileName = currentState().currentFileName();
     m_addAction->setParameter(currentFileName);
@@ -532,14 +598,22 @@ void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
     m_commitCurrentAction->setParameter(currentFileName);
     m_filelogCurrentAction->setParameter(currentFileName);
     m_annotateCurrentAction->setParameter(currentFileName);
+    m_editCurrentAction->setParameter(currentFileName);
+    m_uneditCurrentAction->setParameter(currentFileName);
 
     const QString currentProjectName = currentState().currentProjectName();
     m_diffProjectAction->setParameter(currentProjectName);
     m_statusProjectAction->setParameter(currentProjectName);
     m_updateProjectAction->setParameter(currentProjectName);
     m_logProjectAction->setParameter(currentProjectName);
+    m_commitProjectAction->setParameter(currentProjectName);
 
+    m_diffRepositoryAction->setEnabled(hasTopLevel);
+    m_statusRepositoryAction->setEnabled(hasTopLevel);
+    m_updateRepositoryAction->setEnabled(hasTopLevel);
     m_commitAllAction->setEnabled(hasTopLevel);
+    m_logRepositoryAction->setEnabled(hasTopLevel);
+    m_uneditRepositoryAction->setEnabled(hasTopLevel);
 }
 
 void CVSPlugin::addCurrentFile()
@@ -554,8 +628,7 @@ void CVSPlugin::revertAll()
     const VCSBase::VCSBasePluginState state = currentState();
     QTC_ASSERT(state.hasTopLevel(), return)
     const QString title = tr("Revert repository");
-    if (QMessageBox::warning(0, title, tr("Would you like to revert all changes to the repository?"),
-                             QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
+    if (!messageBoxQuestion(title, tr("Would you like to revert all changes to the repository?")))
         return;
     QStringList args;
     args << QLatin1String("update") << QLatin1String("-C") << state.topLevel();
@@ -588,8 +661,8 @@ void CVSPlugin::revertCurrentFile()
         return;
     }
 
-    if (QMessageBox::warning(0, QLatin1String("CVS revert"), tr("The file has been changed. Do you want to revert it?"),
-                             QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
+    if (!messageBoxQuestion(QLatin1String("CVS Revert"),
+                            tr("The file has been changed. Do you want to revert it?")))
         return;
 
     Core::FileChangeBlocker fcb(state.currentFile());
@@ -760,15 +833,42 @@ void CVSPlugin::updateProject()
 {
     const VCSBase::VCSBasePluginState state = currentState();
     QTC_ASSERT(state.hasProject(), return)
+    update(state.currentProjectTopLevel(), state.relativeCurrentProject());
+}
+
+bool CVSPlugin::update(const QString &topLevel, const QStringList &files)
+{
+    QStringList args(QLatin1String("update"));
+    args.push_back(QLatin1String("-dR"));
+    args.append(files);
+    const CVSResponse response =
+            runCVS(topLevel, args, m_settings.longTimeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
+    const bool ok = response.result == CVSResponse::Ok;
+    if (ok)
+        cvsVersionControl()->emitRepositoryChanged(topLevel);
+    return ok;
+}
 
-   QStringList args(QLatin1String("update"));
-   args.push_back(QLatin1String("-dR"));
-   args.append(state.relativeCurrentProject());
-   const CVSResponse response =
-           runCVS(state.currentProjectTopLevel(), args, m_settings.longTimeOutMS(),
-                  SshPasswordPrompt|ShowStdOutInLogWindow);
-   if (response.result == CVSResponse::Ok)
-       cvsVersionControl()->emitRepositoryChanged(state.currentProjectTopLevel());
+void CVSPlugin::editCurrentFile()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+    edit(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
+}
+
+void CVSPlugin::uneditCurrentFile()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+    unedit(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
+}
+
+void CVSPlugin::uneditCurrentRepository()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return)
+    unedit(state.topLevel(), QStringList());
 }
 
 void CVSPlugin::annotateCurrentFile()
@@ -784,6 +884,56 @@ void CVSPlugin::vcsAnnotate(const QString &file, const QString &revision, int li
     annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber);
 }
 
+bool CVSPlugin::edit(const QString &topLevel, const QStringList &files)
+{
+    QStringList args(QLatin1String("edit"));
+    args.append(files);
+    const CVSResponse response =
+            runCVS(topLevel, args, m_settings.timeOutMS(),
+                   ShowStdOutInLogWindow|SshPasswordPrompt);
+    return response.result == CVSResponse::Ok;
+}
+
+bool CVSPlugin::diffCheckModified(const QString &topLevel, const QStringList &files, bool *modified)
+{
+    // Quick check for modified files using diff
+    *modified = false;
+    QStringList args(QLatin1String("-q"));
+    args << QLatin1String("diff");
+    args.append(files);
+    const CVSResponse response = runCVS(topLevel, args, m_settings.timeOutMS(), 0);
+    if (response.result == CVSResponse::OtherError)
+        return false;
+    *modified = response.result == CVSResponse::NonNullExitCode;
+    return true;
+}
+
+bool CVSPlugin::unedit(const QString &topLevel, const QStringList &files)
+{
+    bool modified;
+    // Prompt and use force flag if modified
+    if (!diffCheckModified(topLevel, files, &modified))
+        return false;
+    if (modified) {
+        const QString question = files.isEmpty() ?
+                      tr("Would you like to discard your changes to the repository '%1'?").arg(topLevel) :
+                      tr("Would you like to discard your changes to the file '%1'?").arg(files.front());
+        if (!messageBoxQuestion(tr("Unedit"), question))
+            return false;
+    }
+
+    QStringList args(QLatin1String("unedit"));
+    // Note: Option '-y' to force 'yes'-answer to CVS' 'undo change' prompt,
+    // exists in CVSNT only as of 6.8.2010. Standard CVS will otherwise prompt
+    if (modified)
+        args.append(QLatin1String("-y"));
+    args.append(files);
+    const CVSResponse response =
+            runCVS(topLevel, args, m_settings.timeOutMS(),
+                   ShowStdOutInLogWindow|SshPasswordPrompt);
+    return response.result == CVSResponse::Ok;
+}
+
 void CVSPlugin::annotate(const QString &workingDir, const QString &file,
                          const QString &revision /* = QString() */,
                          int lineNumber /* = -1 */)
@@ -820,16 +970,52 @@ void CVSPlugin::annotate(const QString &workingDir, const QString &file,
     }
 }
 
+bool CVSPlugin::status(const QString &topLevel, const QStringList &files, const QString &title)
+{
+    QStringList args(QLatin1String("status"));
+    args.append(files);
+    const CVSResponse response =
+            runCVS(topLevel, args, m_settings.timeOutMS(), 0);
+    const bool ok = response.result == CVSResponse::Ok;
+    if (ok)
+        showOutputInEditor(title, response.stdOut, VCSBase::RegularCommandOutput, topLevel, 0);
+    return ok;
+}
+
 void CVSPlugin::projectStatus()
 {
     const VCSBase::VCSBasePluginState state = currentState();
     QTC_ASSERT(state.hasProject(), return)
-    QStringList args;
-    args << QLatin1String("status") << state.relativeCurrentProject();
-    const CVSResponse response =
-            runCVS(state.currentProjectTopLevel(), args, m_settings.timeOutMS(), 0);
-    if (response.result == CVSResponse::Ok)
-        showOutputInEditor(tr("Project status"), response.stdOut, VCSBase::RegularCommandOutput, state.currentProjectTopLevel(), 0);
+    status(state.currentProjectTopLevel(), state.relativeCurrentProject(), tr("Project status"));
+}
+
+void CVSPlugin::commitProject()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasProject(), return)
+    startCommit(state.currentProjectTopLevel(), state.relativeCurrentProject());
+}
+
+void CVSPlugin::diffRepository()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return)
+    cvsDiff(state.topLevel(), QStringList());
+}
+
+void CVSPlugin::statusRepository()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return)
+    status(state.topLevel(), QStringList(), tr("Repository status"));
+}
+
+void CVSPlugin::updateRepository()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return)
+    update(state.topLevel(), QStringList());
+
 }
 
 void CVSPlugin::slotDescribe(const QString &source, const QString &changeNr)
diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h
index c1516595510c99d85fe51f0b4a27cf6aee260289..d6d0b9c0de381d96bcd9f0c94346567480bf6caa 100644
--- a/src/plugins/cvs/cvsplugin.h
+++ b/src/plugins/cvs/cvsplugin.h
@@ -96,6 +96,8 @@ public:
     bool vcsAdd(const QString &workingDir, const QString &fileName);
     bool vcsDelete(const QString &workingDir, const QString &fileName);
     bool managesDirectory(const QString &directory, QString *topLevel = 0) const;
+    // cvs 'edit' is used to implement 'open' (cvsnt).
+    bool edit(const QString &topLevel, const QStringList &files);
 
     static CVSPlugin *cvsPluginInstance();
 
@@ -119,6 +121,13 @@ private slots:
     void diffCommitFiles(const QStringList &);
     void logProject();
     void logRepository();
+    void commitProject();
+    void diffRepository();
+    void statusRepository();
+    void updateRepository();
+    void editCurrentFile();
+    void uneditCurrentFile();
+    void uneditCurrentRepository();
 
 protected:
     virtual void updateActions(VCSBase::VCSBasePlugin::ActionState);
@@ -143,7 +152,12 @@ private:
     void filelog(const QString &workingDir,
                  const QStringList &files = QStringList(),
                  bool enableAnnotationContextMenu = false);
+    bool unedit(const QString &topLevel, const QStringList &files);
+    bool status(const QString &topLevel, const QStringList &files, const QString &title);
+    bool update(const QString &topLevel, const QStringList &files);
     bool checkCVSDirectory(const QDir &directory) const;
+    // Quick check if files are modified
+    bool diffCheckModified(const QString &topLevel, const QStringList &files, bool *modified);
     QString findTopLevelForDirectoryI(const QString &directory) const;
     void startCommit(const QString &workingDir, const QStringList &files = QStringList());
     bool commit(const QString &messageFile, const QStringList &subVersionFileList);
@@ -158,6 +172,9 @@ private:
     Utils::ParameterAction *m_addAction;
     Utils::ParameterAction *m_deleteAction;
     Utils::ParameterAction *m_revertAction;
+    Utils::ParameterAction *m_editCurrentAction;
+    Utils::ParameterAction *m_uneditCurrentAction;
+    QAction *m_uneditRepositoryAction;
     Utils::ParameterAction *m_diffProjectAction;
     Utils::ParameterAction *m_diffCurrentAction;
     Utils::ParameterAction *m_logProjectAction;
@@ -169,6 +186,10 @@ private:
     Utils::ParameterAction *m_annotateCurrentAction;
     Utils::ParameterAction *m_statusProjectAction;
     Utils::ParameterAction *m_updateProjectAction;
+    Utils::ParameterAction *m_commitProjectAction;
+    QAction *m_diffRepositoryAction;
+    QAction *m_updateRepositoryAction;
+    QAction *m_statusRepositoryAction;
 
     QAction *m_submitCurrentLogAction;
     QAction *m_submitDiffAction;