Commit 751d7d04 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

VCS: Add 'Annotate' context menu entry to build issues task window.

parent 1abe898c
...@@ -44,7 +44,8 @@ public: ...@@ -44,7 +44,8 @@ public:
enum Operation { enum Operation {
AddOperation, DeleteOperation, OpenOperation, AddOperation, DeleteOperation, OpenOperation,
CreateRepositoryOperation, CreateRepositoryOperation,
SnapshotOperations SnapshotOperations,
AnnotateOperation
}; };
explicit IVersionControl(QObject *parent = 0) : QObject(parent) {} explicit IVersionControl(QObject *parent = 0) : QObject(parent) {}
...@@ -126,6 +127,11 @@ public: ...@@ -126,6 +127,11 @@ public:
*/ */
virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name) = 0; virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name) = 0;
/*!
* Display annotation for a file and scroll to line
*/
virtual bool vcsAnnotate(const QString &file, int line) = 0;
signals: signals:
void repositoryChanged(const QString &repository); void repositoryChanged(const QString &repository);
void filesChanged(const QStringList &files); void filesChanged(const QStringList &files);
......
...@@ -52,6 +52,7 @@ bool CVSControl::supportsOperation(Operation operation) const ...@@ -52,6 +52,7 @@ bool CVSControl::supportsOperation(Operation operation) const
switch (operation) { switch (operation) {
case AddOperation: case AddOperation:
case DeleteOperation: case DeleteOperation:
case AnnotateOperation:
break; break;
case OpenOperation: case OpenOperation:
case CreateRepositoryOperation: case CreateRepositoryOperation:
...@@ -105,6 +106,12 @@ bool CVSControl::vcsRemoveSnapshot(const QString &, const QString &) ...@@ -105,6 +106,12 @@ bool CVSControl::vcsRemoveSnapshot(const QString &, const QString &)
return false; return false;
} }
bool CVSControl::vcsAnnotate(const QString &file, int line)
{
m_plugin->vcsAnnotate(file, QString(), line);
return true;
}
bool CVSControl::managesDirectory(const QString &directory) const bool CVSControl::managesDirectory(const QString &directory) const
{ {
return m_plugin->managesDirectory(directory); return m_plugin->managesDirectory(directory);
......
...@@ -57,6 +57,7 @@ public: ...@@ -57,6 +57,7 @@ public:
virtual QStringList vcsSnapshots(const QString &topLevel); virtual QStringList vcsSnapshots(const QString &topLevel);
virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsAnnotate(const QString &file, int line);
void emitRepositoryChanged(const QString &s); void emitRepositoryChanged(const QString &s);
void emitFilesChanged(const QStringList &l); void emitFilesChanged(const QStringList &l);
......
...@@ -771,7 +771,7 @@ void CVSPlugin::annotateCurrentFile() ...@@ -771,7 +771,7 @@ void CVSPlugin::annotateCurrentFile()
annotate(state.currentFileTopLevel(), state.relativeCurrentFile()); annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
} }
void CVSPlugin::annotateVersion(const QString &file, const QString &revision, int lineNumber) void CVSPlugin::vcsAnnotate(const QString &file, const QString &revision, int lineNumber)
{ {
const QFileInfo fi(file); const QFileInfo fi(file);
annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber); annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber);
...@@ -1072,7 +1072,7 @@ Core::IEditor * CVSPlugin::showOutputInEditor(const QString& title, const QStrin ...@@ -1072,7 +1072,7 @@ Core::IEditor * CVSPlugin::showOutputInEditor(const QString& title, const QStrin
QString s = title; QString s = title;
Core::IEditor *editor = Core::EditorManager::instance()->openEditorWithContents(id, &s, output.toLocal8Bit()); Core::IEditor *editor = Core::EditorManager::instance()->openEditorWithContents(id, &s, output.toLocal8Bit());
connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)), connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)),
this, SLOT(annotateVersion(QString,QString,int))); this, SLOT(vcsAnnotate(QString,QString,int)));
CVSEditor *e = qobject_cast<CVSEditor*>(editor->widget()); CVSEditor *e = qobject_cast<CVSEditor*>(editor->widget());
if (!e) if (!e)
return 0; return 0;
......
...@@ -101,6 +101,9 @@ public: ...@@ -101,6 +101,9 @@ public:
static CVSPlugin *cvsPluginInstance(); static CVSPlugin *cvsPluginInstance();
public slots:
void vcsAnnotate(const QString &file, const QString &revision /* = QString() */, int lineNumber);
private slots: private slots:
void addCurrentFile(); void addCurrentFile();
void revertCurrentFile(); void revertCurrentFile();
...@@ -111,7 +114,6 @@ private slots: ...@@ -111,7 +114,6 @@ private slots:
void startCommitCurrentFile(); void startCommitCurrentFile();
void filelogCurrentFile(); void filelogCurrentFile();
void annotateCurrentFile(); void annotateCurrentFile();
void annotateVersion(const QString &file, const QString &revision, int lineNumber);
void projectStatus(); void projectStatus();
void slotDescribe(const QString &source, const QString &changeNr); void slotDescribe(const QString &source, const QString &changeNr);
void updateProject(); void updateProject();
......
...@@ -81,6 +81,9 @@ bool GitVersionControl::supportsOperation(Operation operation) const ...@@ -81,6 +81,9 @@ bool GitVersionControl::supportsOperation(Operation operation) const
case SnapshotOperations: case SnapshotOperations:
rc = true; rc = true;
break; break;
case AnnotateOperation:
rc = true;
break;
} }
return rc; return rc;
} }
...@@ -203,6 +206,13 @@ QString GitVersionControl::findTopLevelForDirectory(const QString &directory) co ...@@ -203,6 +206,13 @@ QString GitVersionControl::findTopLevelForDirectory(const QString &directory) co
return GitClient::findRepositoryForDirectory(directory); return GitClient::findRepositoryForDirectory(directory);
} }
bool GitVersionControl::vcsAnnotate(const QString &file, int line)
{
const QFileInfo fi(file);
gitClient()->blame(fi.absolutePath(), fi.fileName(), QString(), line);
return true;
}
void GitVersionControl::emitFilesChanged(const QStringList &l) void GitVersionControl::emitFilesChanged(const QStringList &l)
{ {
emit filesChanged(l); emit filesChanged(l);
......
...@@ -59,6 +59,8 @@ public: ...@@ -59,6 +59,8 @@ public:
virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsAnnotate(const QString &file, int line);
void emitFilesChanged(const QStringList &); void emitFilesChanged(const QStringList &);
void emitRepositoryChanged(const QString &); void emitRepositoryChanged(const QString &);
......
...@@ -66,6 +66,7 @@ bool MercurialControl::supportsOperation(Operation operation) const ...@@ -66,6 +66,7 @@ bool MercurialControl::supportsOperation(Operation operation) const
case Core::IVersionControl::AddOperation: case Core::IVersionControl::AddOperation:
case Core::IVersionControl::DeleteOperation: case Core::IVersionControl::DeleteOperation:
case Core::IVersionControl::CreateRepositoryOperation: case Core::IVersionControl::CreateRepositoryOperation:
case Core::IVersionControl::AnnotateOperation:
break; break;
case Core::IVersionControl::OpenOperation: case Core::IVersionControl::OpenOperation:
case Core::IVersionControl::SnapshotOperations: case Core::IVersionControl::SnapshotOperations:
...@@ -118,6 +119,13 @@ bool MercurialControl::vcsRemoveSnapshot(const QString &, const QString &) ...@@ -118,6 +119,13 @@ bool MercurialControl::vcsRemoveSnapshot(const QString &, const QString &)
return false; return false;
} }
bool MercurialControl::vcsAnnotate(const QString &file, int line)
{
const QFileInfo fi(file);
mercurialClient->annotate(fi.absolutePath(), fi.fileName(), QString(), line);
return true;
}
bool MercurialControl::sccManaged(const QString &filename) bool MercurialControl::sccManaged(const QString &filename)
{ {
const QFileInfo fi(filename); const QFileInfo fi(filename);
......
...@@ -62,6 +62,7 @@ public: ...@@ -62,6 +62,7 @@ public:
bool vcsRestoreSnapshot(const QString &topLevel, const QString &name); bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
bool vcsRemoveSnapshot(const QString &topLevel, const QString &name); bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
bool sccManaged(const QString &filename); bool sccManaged(const QString &filename);
virtual bool vcsAnnotate(const QString &file, int line);
public slots: public slots:
// To be connected to the HgTask's success signal to emit the repository/ // To be connected to the HgTask's success signal to emit the repository/
......
...@@ -723,7 +723,7 @@ void PerforcePlugin::annotate() ...@@ -723,7 +723,7 @@ void PerforcePlugin::annotate()
} }
} }
void PerforcePlugin::annotateVersion(const QString &file, const QString &revision, int lineNumber) void PerforcePlugin::vcsAnnotate(const QString &file, const QString &revision, int lineNumber)
{ {
const QFileInfo fi(file); const QFileInfo fi(file);
annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber); annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber);
...@@ -1175,7 +1175,7 @@ Core::IEditor * PerforcePlugin::showOutputInEditor(const QString& title, const Q ...@@ -1175,7 +1175,7 @@ Core::IEditor * PerforcePlugin::showOutputInEditor(const QString& title, const Q
QString s = title; QString s = title;
Core::IEditor *editor = Core::EditorManager::instance()->openEditorWithContents(id, &s, output); Core::IEditor *editor = Core::EditorManager::instance()->openEditorWithContents(id, &s, output);
connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)), connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)),
this, SLOT(annotateVersion(QString,QString,int))); this, SLOT(vcsAnnotate(QString,QString,int)));
PerforceEditor *e = qobject_cast<PerforceEditor*>(editor->widget()); PerforceEditor *e = qobject_cast<PerforceEditor*>(editor->widget());
if (!e) if (!e)
return 0; return 0;
......
...@@ -106,6 +106,7 @@ public: ...@@ -106,6 +106,7 @@ public:
public slots: public slots:
void describe(const QString &source, const QString &n); void describe(const QString &source, const QString &n);
void vcsAnnotate(const QString &file, const QString &revision /* = QString() */, int lineNumber);
private slots: private slots:
void openCurrentFile(); void openCurrentFile();
...@@ -123,7 +124,6 @@ private slots: ...@@ -123,7 +124,6 @@ private slots:
void describeChange(); void describeChange();
void annotateCurrentFile(); void annotateCurrentFile();
void annotate(); void annotate();
void annotateVersion(const QString &file, const QString &revision, int lineNumber);
void filelogCurrentFile(); void filelogCurrentFile();
void filelog(); void filelog();
void logProject(); void logProject();
......
...@@ -54,6 +54,7 @@ bool PerforceVersionControl::supportsOperation(Operation operation) const ...@@ -54,6 +54,7 @@ bool PerforceVersionControl::supportsOperation(Operation operation) const
case AddOperation: case AddOperation:
case DeleteOperation: case DeleteOperation:
case OpenOperation: case OpenOperation:
case AnnotateOperation:
return true; return true;
case CreateRepositoryOperation: case CreateRepositoryOperation:
case SnapshotOperations: case SnapshotOperations:
...@@ -105,6 +106,12 @@ bool PerforceVersionControl::vcsRemoveSnapshot(const QString &, const QString &) ...@@ -105,6 +106,12 @@ bool PerforceVersionControl::vcsRemoveSnapshot(const QString &, const QString &)
return false; return false;
} }
bool PerforceVersionControl::vcsAnnotate(const QString &file, int line)
{
m_plugin->vcsAnnotate(file, QString(), line);
return true;
}
bool PerforceVersionControl::managesDirectory(const QString &directory) const bool PerforceVersionControl::managesDirectory(const QString &directory) const
{ {
const bool rc = m_plugin->managesDirectory(directory); const bool rc = m_plugin->managesDirectory(directory);
......
...@@ -57,6 +57,7 @@ public: ...@@ -57,6 +57,7 @@ public:
virtual QStringList vcsSnapshots(const QString &topLevel); virtual QStringList vcsSnapshots(const QString &topLevel);
virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsAnnotate(const QString &file, int line);
void emitRepositoryChanged(const QString &s); void emitRepositoryChanged(const QString &s);
void emitFilesChanged(const QStringList &l); void emitFilesChanged(const QStringList &l);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/vcsmanager.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/uniqueidmanager.h> #include <coreplugin/uniqueidmanager.h>
...@@ -40,6 +42,7 @@ ...@@ -40,6 +42,7 @@
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QtGui/QClipboard> #include <QtGui/QClipboard>
#include <QtGui/QKeyEvent> #include <QtGui/QKeyEvent>
...@@ -464,16 +467,21 @@ TaskWindow::TaskWindow() ...@@ -464,16 +467,21 @@ TaskWindow::TaskWindow()
Core::Command *command = core->actionManager()-> Core::Command *command = core->actionManager()->
registerAction(m_copyAction, Core::Constants::COPY, m_taskWindowContext->context()); registerAction(m_copyAction, Core::Constants::COPY, m_taskWindowContext->context());
m_listview->addAction(command->action()); m_listview->addAction(command->action());
connect(m_copyAction, SIGNAL(triggered()), SLOT(copy()));
connect(m_listview->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), m_vcsAnnotateAction = new QAction(tr("&Annotate"), this);
tld, SLOT(currentChanged(const QModelIndex &, const QModelIndex &))); command = core->actionManager()->
registerAction(m_vcsAnnotateAction, QLatin1String("ProjectExplorer.Task.VCS_Annotate"), m_taskWindowContext->context());
m_listview->addAction(command->action());
connect(m_vcsAnnotateAction, SIGNAL(triggered()), SLOT(vcsAnnotate()));
connect(m_listview, SIGNAL(activated(const QModelIndex &)), connect(m_listview->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(showTaskInFile(const QModelIndex &))); tld, SLOT(currentChanged(QModelIndex,QModelIndex)));
connect(m_listview, SIGNAL(clicked(const QModelIndex &)),
this, SLOT(showTaskInFile(const QModelIndex &)));
connect(m_copyAction, SIGNAL(triggered()), SLOT(copy())); connect(m_listview, SIGNAL(activated(QModelIndex)),
this, SLOT(showTaskInFile(QModelIndex)));
connect(m_listview, SIGNAL(clicked(QModelIndex)),
this, SLOT(showTaskInFile(QModelIndex)));
m_filterWarningsButton = createFilterButton(Task::Warning, m_filterWarningsButton = createFilterButton(Task::Warning,
tr("Show Warnings"), m_model, tr("Show Warnings"), m_model,
...@@ -563,12 +571,29 @@ void TaskWindow::showTaskInFile(const QModelIndex &index) ...@@ -563,12 +571,29 @@ void TaskWindow::showTaskInFile(const QModelIndex &index)
m_listview->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); m_listview->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
} }
// Right-click VCS annotate: Find version control and point it to line
void TaskWindow::vcsAnnotate()
{
const QModelIndex index = m_listview->selectionModel()->currentIndex();
if (!index.isValid())
return;
const QString file = index.data(TaskModel::File).toString();
const int line = index.data(TaskModel::Line).toInt();
const QFileInfo fi(file);
if (fi.exists())
if (Core::IVersionControl *vc = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(fi.absolutePath()))
if (vc->supportsOperation(Core::IVersionControl::AnnotateOperation))
vc->vcsAnnotate(fi.absoluteFilePath(), line);
}
void TaskWindow::copy() void TaskWindow::copy()
{ {
QModelIndex index = m_listview->selectionModel()->currentIndex(); const QModelIndex index = m_listview->selectionModel()->currentIndex();
QString file = index.data(TaskModel::File).toString(); if (!index.isValid())
QString line = index.data(TaskModel::Line).toString(); return;
QString description = index.data(TaskModel::Description).toString(); const QString file = index.data(TaskModel::File).toString();
const QString line = index.data(TaskModel::Line).toString();
const QString description = index.data(TaskModel::Description).toString();
QString type; QString type;
switch (index.data(TaskModel::Type).toInt()) { switch (index.data(TaskModel::Type).toInt()) {
case Task::Error: case Task::Error:
......
...@@ -119,6 +119,7 @@ signals: ...@@ -119,6 +119,7 @@ signals:
private slots: private slots:
void showTaskInFile(const QModelIndex &index); void showTaskInFile(const QModelIndex &index);
void copy(); void copy();
void vcsAnnotate();
void setShowWarnings(bool); void setShowWarnings(bool);
void updateCategoriesMenu(); void updateCategoriesMenu();
void filterCategoryTriggered(QAction *action); void filterCategoryTriggered(QAction *action);
...@@ -132,6 +133,7 @@ private: ...@@ -132,6 +133,7 @@ private:
Internal::TaskView *m_listview; Internal::TaskView *m_listview;
Internal::TaskWindowContext *m_taskWindowContext; Internal::TaskWindowContext *m_taskWindowContext;
QAction *m_copyAction; QAction *m_copyAction;
QAction *m_vcsAnnotateAction;
QToolButton *m_filterWarningsButton; QToolButton *m_filterWarningsButton;
QToolButton *m_categoriesButton; QToolButton *m_categoriesButton;
QMenu *m_categoriesMenu; QMenu *m_categoriesMenu;
......
...@@ -52,6 +52,7 @@ bool SubversionControl::supportsOperation(Operation operation) const ...@@ -52,6 +52,7 @@ bool SubversionControl::supportsOperation(Operation operation) const
switch (operation) { switch (operation) {
case AddOperation: case AddOperation:
case DeleteOperation: case DeleteOperation:
case AnnotateOperation:
break; break;
case OpenOperation: case OpenOperation:
case CreateRepositoryOperation: case CreateRepositoryOperation:
...@@ -115,6 +116,13 @@ QString SubversionControl::findTopLevelForDirectory(const QString &directory) co ...@@ -115,6 +116,13 @@ QString SubversionControl::findTopLevelForDirectory(const QString &directory) co
return m_plugin->findTopLevelForDirectory(directory); return m_plugin->findTopLevelForDirectory(directory);
} }
bool SubversionControl::vcsAnnotate(const QString &file, int line)
{
const QFileInfo fi(file);
m_plugin->vcsAnnotate(fi.absolutePath(), fi.fileName(), QString(), line);
return true;
}
void SubversionControl::emitRepositoryChanged(const QString &s) void SubversionControl::emitRepositoryChanged(const QString &s)
{ {
emit repositoryChanged(s); emit repositoryChanged(s);
......
...@@ -59,6 +59,8 @@ public: ...@@ -59,6 +59,8 @@ public:
virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name); virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
virtual bool vcsAnnotate(const QString &file, int line);
void emitRepositoryChanged(const QString &); void emitRepositoryChanged(const QString &);
void emitFilesChanged(const QStringList &); void emitFilesChanged(const QStringList &);
......
...@@ -799,7 +799,7 @@ void SubversionPlugin::annotateCurrentFile() ...@@ -799,7 +799,7 @@ void SubversionPlugin::annotateCurrentFile()
{ {
const VCSBase::VCSBasePluginState state = currentState(); const VCSBase::VCSBasePluginState state = currentState();
QTC_ASSERT(state.hasFile(), return); QTC_ASSERT(state.hasFile(), return);
annotate(state.currentFileTopLevel(), state.relativeCurrentFile()); vcsAnnotate(state.currentFileTopLevel(), state.relativeCurrentFile());
} }
void SubversionPlugin::annotateVersion(const QString &file, void SubversionPlugin::annotateVersion(const QString &file,
...@@ -807,10 +807,10 @@ void SubversionPlugin::annotateVersion(const QString &file, ...@@ -807,10 +807,10 @@ void SubversionPlugin::annotateVersion(const QString &file,
int lineNr) int lineNr)
{ {
const QFileInfo fi(file); const QFileInfo fi(file);
annotate(fi.absolutePath(), fi.fileName(), revision, lineNr); vcsAnnotate(fi.absolutePath(), fi.fileName(), revision, lineNr);
} }
void SubversionPlugin::annotate(const QString &workingDir, const QString &file, void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &file,
const QString &revision /* = QString() */, const QString &revision /* = QString() */,
int lineNumber /* = -1 */) int lineNumber /* = -1 */)
{ {
......
...@@ -100,6 +100,10 @@ public: ...@@ -100,6 +100,10 @@ public:
static SubversionPlugin *subversionPluginInstance(); static SubversionPlugin *subversionPluginInstance();
public slots:
void vcsAnnotate(const QString &workingDir, const QString &file,
const QString &revision = QString(), int lineNumber = -1);
private slots: private slots:
void addCurrentFile(); void addCurrentFile();
void revertCurrentFile(); void revertCurrentFile();
...@@ -132,8 +136,6 @@ private: ...@@ -132,8 +136,6 @@ private:
SubversionResponse runSvn(const QString &workingDir, SubversionResponse runSvn(const QString &workingDir,
const QStringList &arguments, int timeOut, const QStringList &arguments, int timeOut,
bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0); bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0);
void annotate(const QString &workingDir, const QString &file,
const QString &revision = QString(), int lineNumber = -1);
void filelog(const QString &workingDir, void filelog(const QString &workingDir,
const QStringList &file = QStringList(), const QStringList &file = QStringList(),
bool enableAnnotationContextMenu = false); bool enableAnnotationContextMenu = false);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment