summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2011-06-05 17:58:02 +0300
committerhjk <qthjk@ovi.com>2012-08-18 19:42:57 +0200
commit647071d84b4d214636985f743b40db1832cf7bf1 (patch)
treec980417573ef41b1df591f0b6279555bb0e20e88
parent0fcf5515e5efa9549bb7e62a8b8a35075ada8949 (diff)
downloadqt-creator-647071d84b4d214636985f743b40db1832cf7bf1.tar.gz
Introduce ClearCase plugin
Change-Id: Ib2cebaff0f035f48ca958cad16dedfdd80f4bff9 Reviewed-by: hjk <qthjk@ovi.com>
-rw-r--r--qtcreator.qbp1
-rw-r--r--src/plugins/clearcase/ClearCase.mimetypes.xml7
-rw-r--r--src/plugins/clearcase/ClearCase.pluginspec.in18
-rw-r--r--src/plugins/clearcase/activityselector.cpp123
-rw-r--r--src/plugins/clearcase/activityselector.h74
-rw-r--r--src/plugins/clearcase/annotationhighlighter.cpp50
-rw-r--r--src/plugins/clearcase/annotationhighlighter.h58
-rw-r--r--src/plugins/clearcase/checkoutdialog.cpp100
-rw-r--r--src/plugins/clearcase/checkoutdialog.h70
-rw-r--r--src/plugins/clearcase/checkoutdialog.ui176
-rw-r--r--src/plugins/clearcase/clearcase.pro40
-rw-r--r--src/plugins/clearcase/clearcase.qbs59
-rw-r--r--src/plugins/clearcase/clearcase.qrc5
-rw-r--r--src/plugins/clearcase/clearcase_dependencies.pri5
-rw-r--r--src/plugins/clearcase/clearcaseconstants.h56
-rw-r--r--src/plugins/clearcase/clearcasecontrol.cpp178
-rw-r--r--src/plugins/clearcase/clearcasecontrol.h84
-rw-r--r--src/plugins/clearcase/clearcaseeditor.cpp131
-rw-r--r--src/plugins/clearcase/clearcaseeditor.h64
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp1956
-rw-r--r--src/plugins/clearcase/clearcaseplugin.h270
-rw-r--r--src/plugins/clearcase/clearcasesettings.cpp144
-rw-r--r--src/plugins/clearcase/clearcasesettings.h86
-rw-r--r--src/plugins/clearcase/clearcasesubmiteditor.cpp69
-rw-r--r--src/plugins/clearcase/clearcasesubmiteditor.h65
-rw-r--r--src/plugins/clearcase/clearcasesubmiteditorwidget.cpp101
-rw-r--r--src/plugins/clearcase/clearcasesubmiteditorwidget.h72
-rw-r--r--src/plugins/clearcase/settingspage.cpp142
-rw-r--r--src/plugins/clearcase/settingspage.h90
-rw-r--r--src/plugins/clearcase/settingspage.ui236
-rw-r--r--src/plugins/clearcase/undocheckout.ui127
-rw-r--r--src/plugins/clearcase/versionselector.cpp110
-rw-r--r--src/plugins/clearcase/versionselector.h70
-rw-r--r--src/plugins/clearcase/versionselector.ui190
-rw-r--r--src/plugins/plugins.pro5
35 files changed, 5032 insertions, 0 deletions
diff --git a/qtcreator.qbp b/qtcreator.qbp
index 8254045085..dc9e273eb9 100644
--- a/qtcreator.qbp
+++ b/qtcreator.qbp
@@ -35,6 +35,7 @@ Project {
"src/plugins/bineditor/bineditor.qbs",
"src/plugins/bookmarks/bookmarks.qbs",
"src/plugins/classview/classview.qbs",
+ "src/plugins/clearcase/clearcase.qbs",
"src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs",
"src/plugins/coreplugin/coreplugin.qbs",
"src/plugins/coreplugin/images/logo/logo.qbs",
diff --git a/src/plugins/clearcase/ClearCase.mimetypes.xml b/src/plugins/clearcase/ClearCase.mimetypes.xml
new file mode 100644
index 0000000000..c8979ed1d2
--- /dev/null
+++ b/src/plugins/clearcase/ClearCase.mimetypes.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+ <mime-type type="application/vnd.audc.text.clearcase.submit">
+ <comment>ClearCase submit template</comment>
+ <sub-class-of type="text/plain"/>
+ </mime-type>
+</mime-info>
diff --git a/src/plugins/clearcase/ClearCase.pluginspec.in b/src/plugins/clearcase/ClearCase.pluginspec.in
new file mode 100644
index 0000000000..e816dee00d
--- /dev/null
+++ b/src/plugins/clearcase/ClearCase.pluginspec.in
@@ -0,0 +1,18 @@
+<plugin name=\"ClearCase\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\">
+ <vendor>AudioCodes</vendor>
+ <copyright>(C) 2012 AudioCodes Ltd.</copyright>
+ <license>
+GNU Lesser General Public License Usage
+
+this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. Please review the following information to ensure the GNU Lesser General Public License version 2.1 requirements will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ </license>
+ <category>Version Control</category>
+ <description>ClearCase integration.</description>
+ <url>http://www.qt-project.org</url>
+ <dependencyList>
+ <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/>
+ <dependency name=\"VcsBase\" version=\"$$QTCREATOR_VERSION\"/>
+ </dependencyList>
+</plugin>
diff --git a/src/plugins/clearcase/activityselector.cpp b/src/plugins/clearcase/activityselector.cpp
new file mode 100644
index 0000000000..2c42f6a1bc
--- /dev/null
+++ b/src/plugins/clearcase/activityselector.cpp
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "activityselector.h"
+#include "clearcaseconstants.h"
+#include "clearcaseplugin.h"
+
+#include <utils/qtcassert.h>
+
+#include <QComboBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QToolButton>
+
+using namespace ClearCase;
+using namespace ClearCase::Internal;
+
+ActivitySelector::ActivitySelector(QWidget *parent) :
+ QWidget(parent),
+ m_plugin(ClearCasePlugin::instance()),
+ m_changed(false)
+{
+ QHBoxLayout *hboxLayout = new QHBoxLayout(this);
+ hboxLayout->setContentsMargins(0, 0, 0, 0);
+
+ QLabel *lblActivity = new QLabel(tr("Select &Activity:"));
+ lblActivity->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ hboxLayout->addWidget(lblActivity);
+
+ m_cmbActivity = new QComboBox(this);
+ m_cmbActivity->setMinimumSize(QSize(350, 0));
+ hboxLayout->addWidget(m_cmbActivity);
+
+ QString addText = tr("Add");
+ if (!m_plugin->settings().autoAssignActivityName)
+ addText.append(QLatin1String("..."));
+ QToolButton *btnAdd = new QToolButton;
+ btnAdd->setText(addText);
+ hboxLayout->addWidget(btnAdd);
+
+#ifndef QT_NO_SHORTCUT
+ lblActivity->setBuddy(m_cmbActivity);
+#endif // QT_NO_SHORTCUT
+
+ connect(btnAdd, SIGNAL(clicked()), this, SLOT(newActivity()));
+
+ refresh();
+ connect(m_cmbActivity, SIGNAL(currentIndexChanged(int)), this, SLOT(userChanged()));
+}
+
+void ActivitySelector::userChanged()
+{
+ m_changed = true;
+}
+
+bool ActivitySelector::refresh()
+{
+ int current;
+ QList<QStringPair> activities = m_plugin->activities(&current);
+ m_cmbActivity->clear();
+ foreach (QStringPair activity, activities)
+ m_cmbActivity->addItem(activity.second, activity.first);
+ m_cmbActivity->setCurrentIndex(current);
+ m_cmbActivity->updateGeometry();
+ resize(size());
+ return !activities.isEmpty();
+}
+
+void ActivitySelector::addKeep()
+{
+ m_cmbActivity->insertItem(0, tr("Keep item activity"), QLatin1String(Constants::KEEP_ACTIVITY));
+ setActivity(QLatin1String(Constants::KEEP_ACTIVITY));
+}
+
+QString ActivitySelector::activity() const
+{
+ return m_cmbActivity->itemData(m_cmbActivity->currentIndex()).toString();
+}
+
+void ActivitySelector::setActivity(const QString &act)
+{
+ int index = m_cmbActivity->findData(act);
+ if (index != -1) {
+ disconnect(m_cmbActivity, SIGNAL(currentIndexChanged(int)), this, SLOT(userChanged()));
+ m_cmbActivity->setCurrentIndex(index);
+ connect(m_cmbActivity, SIGNAL(currentIndexChanged(int)), this, SLOT(userChanged()));
+ }
+}
+
+void ActivitySelector::newActivity()
+{
+ if (m_plugin->newActivity())
+ refresh();
+}
diff --git a/src/plugins/clearcase/activityselector.h b/src/plugins/clearcase/activityselector.h
new file mode 100644
index 0000000000..65405a7be7
--- /dev/null
+++ b/src/plugins/clearcase/activityselector.h
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef ACTIVITYSELECTOR_H
+#define ACTIVITYSELECTOR_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+QT_END_NAMESPACE
+
+namespace ClearCase {
+namespace Internal {
+
+class ClearCasePlugin;
+
+class ActivitySelector : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ActivitySelector(QWidget *parent = 0);
+ QString activity() const;
+ void setActivity(const QString &act);
+ void addKeep();
+ bool refresh();
+ bool changed() { return m_changed; }
+
+public slots:
+ void newActivity();
+
+private slots:
+ void userChanged();
+
+private:
+ ClearCasePlugin *m_plugin;
+ bool m_changed;
+ QComboBox *m_cmbActivity;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // ACTIVITYSELECTOR_H
diff --git a/src/plugins/clearcase/annotationhighlighter.cpp b/src/plugins/clearcase/annotationhighlighter.cpp
new file mode 100644
index 0000000000..d5549e6b30
--- /dev/null
+++ b/src/plugins/clearcase/annotationhighlighter.cpp
@@ -0,0 +1,50 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "annotationhighlighter.h"
+
+using namespace ClearCase;
+using namespace ClearCase::Internal;
+
+ClearCaseAnnotationHighlighter::ClearCaseAnnotationHighlighter(const ChangeNumbers &changeNumbers,
+ const QColor &bg,
+ QTextDocument *document) :
+ VcsBase::BaseAnnotationHighlighter(changeNumbers, bg, document),
+ m_separator(QLatin1Char('|'))
+{
+}
+
+QString ClearCaseAnnotationHighlighter::changeNumber(const QString &block) const
+{
+ const int pos = block.indexOf(m_separator);
+ return pos > 1 ? block.left(pos) : QString();
+}
diff --git a/src/plugins/clearcase/annotationhighlighter.h b/src/plugins/clearcase/annotationhighlighter.h
new file mode 100644
index 0000000000..df53253caf
--- /dev/null
+++ b/src/plugins/clearcase/annotationhighlighter.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef ANNOTATIONHIGHLIGHTER_H
+#define ANNOTATIONHIGHLIGHTER_H
+
+#include <vcsbase/baseannotationhighlighter.h>
+
+namespace ClearCase {
+namespace Internal {
+
+// Annotation highlighter for clearcase triggering on 'changenumber '
+class ClearCaseAnnotationHighlighter : public VcsBase::BaseAnnotationHighlighter
+{
+ Q_OBJECT
+public:
+ explicit ClearCaseAnnotationHighlighter(const ChangeNumbers &changeNumbers, const QColor &bg,
+ QTextDocument *document = 0);
+
+private:
+ virtual QString changeNumber(const QString &block) const;
+
+ const QChar m_separator;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // ANNOTATIONHIGHLIGHTER_H
diff --git a/src/plugins/clearcase/checkoutdialog.cpp b/src/plugins/clearcase/checkoutdialog.cpp
new file mode 100644
index 0000000000..3e7aba22f8
--- /dev/null
+++ b/src/plugins/clearcase/checkoutdialog.cpp
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "checkoutdialog.h"
+#include "clearcaseplugin.h"
+#include "ui_checkoutdialog.h"
+
+#include <QList>
+#include <QPair>
+#include <QPalette>
+
+namespace ClearCase {
+namespace Internal {
+
+CheckOutDialog::CheckOutDialog(const QString &fileName, QWidget *parent) :
+ QDialog(parent), ui(new Ui::CheckOutDialog)
+{
+ ui->setupUi(this);
+ ui->lblFileName->setText(fileName);
+}
+
+CheckOutDialog::~CheckOutDialog()
+{
+ delete ui;
+}
+
+QString CheckOutDialog::activity() const
+{
+ return ui->actSelector->activity();
+}
+
+QString CheckOutDialog::comment() const
+{
+ return ui->txtComment->toPlainText();
+}
+
+bool CheckOutDialog::isReserved() const
+{
+ return ui->chkReserved->isChecked();
+}
+
+bool CheckOutDialog::isUnreserved() const
+{
+ return ui->chkUnreserved->isChecked();
+}
+
+bool CheckOutDialog::isPreserveTime() const
+{
+ return ui->chkPTime->isChecked();
+}
+
+bool CheckOutDialog::isUseHijacked() const
+{
+ return ui->hijackedCheckBox->isChecked();
+}
+
+void CheckOutDialog::hideHijack()
+{
+ ui->hijackedCheckBox->setVisible(false);
+ ui->hijackedCheckBox->setChecked(false);
+}
+
+void CheckOutDialog::toggleUnreserved(bool checked)
+{
+ ui->chkUnreserved->setEnabled(checked);
+ if (!checked)
+ ui->chkUnreserved->setChecked(false);
+}
+
+} // namespace Internal
+} // namespace ClearCase
diff --git a/src/plugins/clearcase/checkoutdialog.h b/src/plugins/clearcase/checkoutdialog.h
new file mode 100644
index 0000000000..b04bb71d0b
--- /dev/null
+++ b/src/plugins/clearcase/checkoutdialog.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CHECKOUTDIALOG_H
+#define CHECKOUTDIALOG_H
+
+#include <QDialog>
+
+namespace ClearCase {
+namespace Internal {
+
+namespace Ui {
+ class CheckOutDialog;
+}
+
+class CheckOutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit CheckOutDialog(const QString &fileName, QWidget *parent = 0);
+ ~CheckOutDialog();
+ QString activity() const;
+ QString comment() const;
+ bool isReserved() const;
+ bool isUnreserved() const;
+ bool isPreserveTime() const;
+ bool isUseHijacked() const;
+ void hideHijack();
+
+private slots:
+ void toggleUnreserved(bool checked);
+
+private:
+ Ui::CheckOutDialog *ui;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // CHECKOUTDIALOG_H
diff --git a/src/plugins/clearcase/checkoutdialog.ui b/src/plugins/clearcase/checkoutdialog.ui
new file mode 100644
index 0000000000..691a9b0de0
--- /dev/null
+++ b/src/plugins/clearcase/checkoutdialog.ui
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClearCase::Internal::CheckOutDialog</class>
+ <widget class="QDialog" name="ClearCase::Internal::CheckOutDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>352</width>
+ <height>317</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Check Out</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="lblFileName">
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ActivitySelector" name="actSelector" native="true"/>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblComment">
+ <property name="text">
+ <string>&amp;Checkout Comment:</string>
+ </property>
+ <property name="buddy">
+ <cstring>txtComment</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="txtComment"/>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkReserved">
+ <property name="text">
+ <string>&amp;Reserved</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkUnreserved">
+ <property name="text">
+ <string>&amp;Unreserved if already reserved</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkPTime">
+ <property name="text">
+ <string>&amp;Preserve file modification time</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="hijackedCheckBox">
+ <property name="text">
+ <string>Use &amp;Hijacked file</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ActivitySelector</class>
+ <extends>QWidget</extends>
+ <header>activityselector.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ClearCase::Internal::CheckOutDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ClearCase::Internal::CheckOutDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chkReserved</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>ClearCase::Internal::CheckOutDialog</receiver>
+ <slot>toggleUnreserved(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>50</x>
+ <y>173</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>6</x>
+ <y>186</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <slot>toggleUnreserved(bool)</slot>
+ <slot>newActivity()</slot>
+ </slots>
+</ui>
diff --git a/src/plugins/clearcase/clearcase.pro b/src/plugins/clearcase/clearcase.pro
new file mode 100644
index 0000000000..347966dc04
--- /dev/null
+++ b/src/plugins/clearcase/clearcase.pro
@@ -0,0 +1,40 @@
+TEMPLATE = lib
+TARGET = ClearCase
+# PROVIDER = AudioCodes
+
+include(../../qtcreatorplugin.pri)
+include(clearcase_dependencies.pri)
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+
+HEADERS += annotationhighlighter.h \
+ clearcaseplugin.h \
+ clearcasecontrol.h \
+ settingspage.h \
+ clearcaseeditor.h \
+ clearcasesettings.h \
+ clearcaseconstants.h \
+ clearcasesubmiteditor.h \
+ checkoutdialog.h \
+ activityselector.h \
+ clearcasesubmiteditorwidget.h \
+ versionselector.h
+
+SOURCES += annotationhighlighter.cpp \
+ clearcaseplugin.cpp \
+ clearcasecontrol.cpp \
+ settingspage.cpp \
+ clearcaseeditor.cpp \
+ clearcasesettings.cpp \
+ clearcasesubmiteditor.cpp \
+ checkoutdialog.cpp \
+ activityselector.cpp \
+ clearcasesubmiteditorwidget.cpp \
+ versionselector.cpp
+
+FORMS += settingspage.ui \
+ checkoutdialog.ui \
+ undocheckout.ui \
+ versionselector.ui
+
+RESOURCES += clearcase.qrc
diff --git a/src/plugins/clearcase/clearcase.qbs b/src/plugins/clearcase/clearcase.qbs
new file mode 100644
index 0000000000..63c4d3ac64
--- /dev/null
+++ b/src/plugins/clearcase/clearcase.qbs
@@ -0,0 +1,59 @@
+import qbs.base 1.0
+
+import "../QtcPlugin.qbs" as QtcPlugin
+
+QtcPlugin {
+ name: "ClearCase"
+// provider: "AudioCodes"
+
+ condition: qbs.targetOS != "mac"
+
+ Depends { name: "Qt.widgets" }
+ Depends { name: "Core" }
+ Depends { name: "TextEditor" }
+ Depends { name: "ProjectExplorer" }
+ Depends { name: "Find" }
+ Depends { name: "VcsBase" }
+ Depends { name: "Locator" }
+
+ Depends { name: "cpp" }
+ cpp.defines: base.concat(["QT_NO_CAST_FROM_ASCII"])
+ cpp.includePaths: [
+ ".",
+ "..",
+ "../../libs",
+ buildDirectory
+ ]
+
+ files: [
+ "activityselector.cpp",
+ "activityselector.h",
+ "annotationhighlighter.cpp",
+ "annotationhighlighter.h",
+ "checkoutdialog.cpp",
+ "checkoutdialog.h",
+ "checkoutdialog.ui",
+ "clearcaseconstants.h",
+ "clearcasecontrol.cpp",
+ "clearcasecontrol.h",
+ "clearcaseeditor.cpp",
+ "clearcaseeditor.h",
+ "clearcaseplugin.cpp",
+ "clearcaseplugin.h",
+ "clearcase.qrc",
+ "clearcasesettings.cpp",
+ "clearcasesettings.h",
+ "clearcasesubmiteditor.cpp",
+ "clearcasesubmiteditor.h",
+ "clearcasesubmiteditorwidget.cpp",
+ "clearcasesubmiteditorwidget.h",
+ "settingspage.cpp",
+ "settingspage.h",
+ "settingspage.ui",
+ "undocheckout.ui",
+ "versionselector.cpp",
+ "versionselector.h",
+ "versionselector.ui",
+ ]
+}
+
diff --git a/src/plugins/clearcase/clearcase.qrc b/src/plugins/clearcase/clearcase.qrc
new file mode 100644
index 0000000000..150dedfb8f
--- /dev/null
+++ b/src/plugins/clearcase/clearcase.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/clearcase">
+ <file>ClearCase.mimetypes.xml</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/clearcase/clearcase_dependencies.pri b/src/plugins/clearcase/clearcase_dependencies.pri
new file mode 100644
index 0000000000..9e7c28e9e1
--- /dev/null
+++ b/src/plugins/clearcase/clearcase_dependencies.pri
@@ -0,0 +1,5 @@
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../plugins/texteditor/texteditor.pri)
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/vcsbase/vcsbase.pri)
+include(../../libs/utils/utils.pri)
diff --git a/src/plugins/clearcase/clearcaseconstants.h b/src/plugins/clearcase/clearcaseconstants.h
new file mode 100644
index 0000000000..72ea1182f6
--- /dev/null
+++ b/src/plugins/clearcase/clearcaseconstants.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASE_CONSTANTS_H
+#define CLEARCASE_CONSTANTS_H
+
+#include <QtGlobal>
+
+namespace ClearCase {
+namespace Constants {
+
+const char VCS_ID_CLEARCASE[] = "E.ClearCase";
+const char CLEARCASE_ROOT_FILE[] = "view.dat";
+const char CLEARCASE_SUBMIT_MIMETYPE[] = "application/vnd.audc.text.clearcase.submit";
+const char CLEARCASECHECKINEDITOR[] = "ClearCase Check In Editor";
+const char CLEARCASECHECKINEDITOR_ID[] = "ClearCase Check In Editor";
+const char CLEARCASECHECKINEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("VCS", "ClearCase Check In Editor");
+const char CHECKIN_SELECTED[] = "ClearCase.CheckInSelected";
+const char DIFF_SELECTED[] = "ClearCase.DiffSelected";
+const char TASK_INDEX[] = "ClearCase.Task.Index";
+const char KEEP_ACTIVITY[] = "__KEEP__";
+enum { debug = 0 };
+
+} // namespace Constants
+} // namespace ClearCase
+
+#endif // CLEARCASE_CONSTANTS_H
diff --git a/src/plugins/clearcase/clearcasecontrol.cpp b/src/plugins/clearcase/clearcasecontrol.cpp
new file mode 100644
index 0000000000..f052604577
--- /dev/null
+++ b/src/plugins/clearcase/clearcasecontrol.cpp
@@ -0,0 +1,178 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "clearcasecontrol.h"
+#include "clearcaseplugin.h"
+#include "clearcaseconstants.h"
+
+#include <vcsbase/vcsbaseconstants.h>
+#include <utils/synchronousprocess.h>
+
+#include <QFileInfo>
+
+using namespace ClearCase;
+using namespace ClearCase::Internal;
+
+ClearCaseControl::ClearCaseControl(ClearCasePlugin *plugin) :
+ m_plugin(plugin)
+{
+}
+
+QString ClearCaseControl::displayName() const
+{
+ return QLatin1String("ClearCase");
+}
+
+Core::Id ClearCaseControl::id() const
+{
+ return ClearCase::Constants::VCS_ID_CLEARCASE;
+}
+
+bool ClearCaseControl::isConfigured() const
+{
+ return !Utils::SynchronousProcess::locateBinary(m_plugin->settings().ccCommand).isEmpty();
+}
+
+bool ClearCaseControl::supportsOperation(Operation operation) const
+{
+ bool rc = isConfigured();
+ switch (operation) {
+ case OpenOperation:
+ case AddOperation:
+ case DeleteOperation:
+ case MoveOperation:
+ case AnnotateOperation:
+ case GetRepositoryRootOperation:
+ break;
+ case CheckoutOperation:
+ case CreateRepositoryOperation:
+ case SnapshotOperations:
+ rc = false;
+ break;
+ }
+ return rc;
+}
+
+bool ClearCaseControl::vcsOpen(const QString &fileName)
+{
+ const QFileInfo fi(fileName);
+ return m_plugin->vcsOpen(fi.absolutePath(), fi.fileName());
+}
+
+Core::IVersionControl::SettingsFlags ClearCaseControl::settingsFlags() const
+{
+ SettingsFlags rc;
+ if (m_plugin->settings().autoCheckOut)
+ rc|= AutoOpen;
+ return rc;
+}
+
+bool ClearCaseControl::vcsAdd(const QString &fileName)
+{
+ const QFileInfo fi(fileName);
+ return m_plugin->vcsAdd(fi.absolutePath(), fi.fileName());
+}
+
+bool ClearCaseControl::vcsDelete(const QString &fileName)
+{
+ const QFileInfo fi(fileName);
+ return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
+}
+
+bool ClearCaseControl::vcsMove(const QString &from, const QString &to)
+{
+ const QFileInfo ifrom(from);
+ const QFileInfo ito(to);
+ return m_plugin->vcsMove(ifrom.absolutePath(), ifrom.fileName(), ito.fileName());
+}
+
+QString ClearCaseControl::vcsGetRepositoryURL(const QString &directory)
+{
+ return m_plugin->vcsGetRepositoryURL(directory);
+}
+
+bool ClearCaseControl::managesDirectory(const QString &directory, QString *topLevel) const
+{
+ return m_plugin->managesDirectory(directory, topLevel);
+}
+
+bool ClearCaseControl::vcsAnnotate(const QString &file, int line)
+{
+ const QFileInfo fi(file);
+ m_plugin->vcsAnnotate(fi.absolutePath(), fi.fileName(), QString(), line);
+ return true;
+}
+
+void ClearCaseControl::emitRepositoryChanged(const QString &s)
+{
+ emit repositoryChanged(s);
+}
+
+void ClearCaseControl::emitFilesChanged(const QStringList &l)
+{
+ emit filesChanged(l);
+}
+
+void ClearCaseControl::emitConfigurationChanged()
+{
+ emit configurationChanged();
+}
+
+bool ClearCaseControl::vcsCheckout(const QString & /*directory*/, const QByteArray & /*url*/)
+{
+ return false;
+}
+
+bool ClearCaseControl::vcsCreateRepository(const QString &)
+{
+ return false;
+}
+
+QString ClearCaseControl::vcsCreateSnapshot(const QString &)
+{
+ return QString();
+}
+
+QStringList ClearCaseControl::vcsSnapshots(const QString &)
+{
+ return QStringList();
+}
+
+bool ClearCaseControl::vcsRestoreSnapshot(const QString &, const QString &)
+{
+ return false;
+}
+
+bool ClearCaseControl::vcsRemoveSnapshot(const QString &, const QString &)
+{
+ return false;
+}
diff --git a/src/plugins/clearcase/clearcasecontrol.h b/src/plugins/clearcase/clearcasecontrol.h
new file mode 100644
index 0000000000..789dbbf9b3
--- /dev/null
+++ b/src/plugins/clearcase/clearcasecontrol.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASECONTROL_H
+#define CLEARCASECONTROL_H
+
+#include <coreplugin/iversioncontrol.h>
+
+namespace ClearCase {
+namespace Internal {
+
+class ClearCasePlugin;
+
+// Just a proxy for ClearCasePlugin
+class ClearCaseControl : public Core::IVersionControl
+{
+ Q_OBJECT
+public:
+ explicit ClearCaseControl(ClearCasePlugin *plugin);
+ QString displayName() const;
+ Core::Id id() const;
+
+ bool managesDirectory(const QString &directory, QString *topLevel = 0) const;
+
+ bool isConfigured() const;
+
+ bool supportsOperation(Operation operation) const;
+ bool vcsOpen(const QString &fileName);
+ SettingsFlags settingsFlags() const;
+ bool vcsAdd(const QString &fileName);
+ bool vcsDelete(const QString &filename);
+ bool vcsMove(const QString &from, const QString &to);
+ bool vcsCreateRepository(const QString &directory);
+ bool vcsCheckout(const QString &directory, const QByteArray &url);
+ QString vcsGetRepositoryURL(const QString &directory);
+
+ QString vcsCreateSnapshot(const QString &topLevel);
+ QStringList vcsSnapshots(const QString &topLevel);
+ bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
+ bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
+
+ bool vcsAnnotate(const QString &file, int line);
+
+ void emitRepositoryChanged(const QString &);
+ void emitFilesChanged(const QStringList &);
+ void emitConfigurationChanged();
+
+private:
+ ClearCasePlugin *m_plugin;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // CLEARCASECONTROL_H
diff --git a/src/plugins/clearcase/clearcaseeditor.cpp b/src/plugins/clearcase/clearcaseeditor.cpp
new file mode 100644
index 0000000000..52041ded21
--- /dev/null
+++ b/src/plugins/clearcase/clearcaseeditor.cpp
@@ -0,0 +1,131 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "annotationhighlighter.h"
+#include "clearcaseconstants.h"
+#include "clearcaseeditor.h"
+#include "clearcaseplugin.h"
+
+#include <utils/qtcassert.h>
+#include <vcsbase/diffhighlighter.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QFileInfo>
+#include <QTextBlock>
+#include <QTextCursor>
+
+using namespace ClearCase;
+using namespace ClearCase::Internal;
+
+ClearCaseEditor::ClearCaseEditor(const VcsBase::VcsBaseEditorParameters *type,
+ QWidget *parent) :
+ VcsBase::VcsBaseEditorWidget(type, parent),
+ m_versionNumberPattern(QLatin1String("[\\\\/]main[\\\\/][^ \t\n\"]*"))
+{
+ QTC_ASSERT(m_versionNumberPattern.isValid(), return);
+ setAnnotateRevisionTextFormat(tr("Annotate version \"%1\""));
+}
+
+QSet<QString> ClearCaseEditor::annotationChanges() const
+{
+ QSet<QString> changes;
+ QString txt = toPlainText();
+ if (txt.isEmpty())
+ return changes;
+ // search until header
+ int separator = txt.indexOf(QRegExp(QLatin1String("\n-{30}")));
+ QRegExp r(QLatin1String("([^|]*)\\|[^\n]*\n"));
+ QTC_ASSERT(r.isValid(), return changes);
+ int pos = r.indexIn(txt, 0);
+ while (pos != -1 && pos < separator) {
+ changes.insert(r.cap(1));
+ pos = r.indexIn(txt, pos + r.matchedLength());
+ }
+ return changes;
+}
+
+QString ClearCaseEditor::changeUnderCursor(const QTextCursor &c) const
+{
+ QTextCursor cursor = c;
+ // Any number is regarded as change number.
+ cursor.select(QTextCursor::BlockUnderCursor);
+ if (!cursor.hasSelection())
+ return QString();
+ QString change = cursor.selectedText();
+ // Annotation output has number, log output has revision numbers
+ // as r1, r2...
+ if (m_versionNumberPattern.indexIn(change) != -1)
+ return m_versionNumberPattern.cap();
+ return QString();
+}
+
+/*
+ Diff header format (on Windows, native separators are used after the @@)
+--- main.cpp@@\main\2
++++ main.cpp@@\main\1
+@@ -6,6 +6,5 @@
+*/
+VcsBase::DiffHighlighter *ClearCaseEditor::createDiffHighlighter() const
+{
+ const QRegExp filePattern(QLatin1String("^[-+][-+][-+] "));
+ QTC_CHECK(filePattern.isValid());
+ return new VcsBase::DiffHighlighter(filePattern);
+}
+
+VcsBase::BaseAnnotationHighlighter *ClearCaseEditor::createAnnotationHighlighter(const QSet<QString> &changes,
+ const QColor &bg) const
+{
+ return new ClearCaseAnnotationHighlighter(changes, bg);
+}
+
+QString ClearCaseEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
+{
+ // "+++ D:\depot\...\mainwindow.cpp@@\main\3"
+ // "+++ D:\depot\...\mainwindow.cpp[TAB]Sun May 01 14:22:37 2011"
+ // Go back chunks
+ const QString diffIndicator = QLatin1String("+++ ");
+ for (QTextBlock block = inBlock; block.isValid() ; block = block.previous()) {
+ QString diffFileName = block.text();
+ if (diffFileName.startsWith(diffIndicator)) {
+ diffFileName.remove(0, diffIndicator.size());
+ const int tabIndex = diffFileName.indexOf(QRegExp(QLatin1String("@@|\t")));
+ if (tabIndex != -1)
+ diffFileName.truncate(tabIndex);
+ const QString rc = findDiffFile(diffFileName);
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << diffFileName << rc << source();
+ return rc;
+ }
+ }
+ return QString();
+}
diff --git a/src/plugins/clearcase/clearcaseeditor.h b/src/plugins/clearcase/clearcaseeditor.h
new file mode 100644
index 0000000000..c1f7b8808e
--- /dev/null
+++ b/src/plugins/clearcase/clearcaseeditor.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASEEDITOR_H
+#define CLEARCASEEDITOR_H
+
+#include <vcsbase/vcsbaseeditor.h>
+
+#include <QRegExp>
+
+namespace ClearCase {
+namespace Internal {
+
+class ClearCaseEditor : public VcsBase::VcsBaseEditorWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ClearCaseEditor(const VcsBase::VcsBaseEditorParameters *type,
+ QWidget *parent);
+
+private:
+ QSet<QString> annotationChanges() const;
+ QString changeUnderCursor(const QTextCursor &) const;
+ VcsBase::DiffHighlighter *createDiffHighlighter() const;
+ VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
+ QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
+
+ mutable QRegExp m_versionNumberPattern;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // CLEARCASEEDITOR_H
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
new file mode 100644
index 0000000000..4de02b43b0
--- /dev/null
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -0,0 +1,1956 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "activityselector.h"
+#include "checkoutdialog.h"
+#include "clearcaseconstants.h"
+#include "clearcasecontrol.h"
+#include "clearcaseeditor.h"
+#include "clearcaseplugin.h"
+#include "clearcasesubmiteditor.h"
+#include "clearcasesubmiteditorwidget.h"
+#include "settingspage.h"
+#include "versionselector.h"
+#include "ui_undocheckout.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/documentmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <locator/commandlocator.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/iprojectmanager.h>
+#include <utils/synchronousprocess.h>
+#include <utils/parameteraction.h>
+#include <utils/fileutils.h>
+#include <utils/qtcassert.h>
+#include <utils/runextensions.h>
+#include <vcsbase/basevcseditorfactory.h>
+#include <vcsbase/basevcssubmiteditorfactory.h>
+#include <vcsbase/vcsbaseeditor.h>
+#include <vcsbase/vcsbaseeditorparameterwidget.h>
+#include <vcsbase/vcsbaseoutputwindow.h>
+#include <vcsbase/vcsbasesubmiteditor.h>
+
+
+#include <QAction>
+#include <QDebug>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QDir>
+#include <QFileInfo>
+#include <QFuture>
+#include <QFutureInterface>
+#include <QInputDialog>
+#include <QList>
+#include <QMainWindow>
+#include <QMenu>
+#include <QMessageBox>
+#include <QMutex>
+#include <QTemporaryFile>
+#include <QTextCodec>
+#include <QProcess>
+#include <QSharedPointer>
+#include <QTimer>
+#include <QUrl>
+#include <QUuid>
+#include <QVariant>
+#include <QVBoxLayout>
+#include <QXmlStreamReader>
+#include <QtConcurrentRun>
+#include <QtPlugin>
+
+namespace ClearCase {
+namespace Internal {
+
+static const char CMD_ID_CLEARCASE_MENU[] = "ClearCase.Menu";
+static const char CMD_ID_CHECKOUT[] = "ClearCase.CheckOut";
+static const char CMD_ID_CHECKIN[] = "ClearCase.CheckInCurrent";
+static const char CMD_ID_UNDOCHECKOUT[] = "ClearCase.UndoCheckOut";
+static const char CMD_ID_UNDOHIJACK[] = "ClearCase.UndoHijack";
+static const char CMD_ID_DIFF_CURRENT[] = "ClearCase.DiffCurrent";
+static const char CMD_ID_HISTORY_CURRENT[] = "ClearCase.HistoryCurrent";
+static const char CMD_ID_ANNOTATE[] = "ClearCase.Annotate";
+static const char CMD_ID_ADD_FILE[] = "ClearCase.AddFile";
+static const char CMD_ID_DIFF_ACTIVITY[] = "ClearCase.DiffActivity";
+static const char CMD_ID_CHECKIN_ACTIVITY[] = "ClearCase.CheckInActivity";
+static const char CMD_ID_UPDATEINDEX[] = "ClearCase.UpdateIndex";
+static const char CMD_ID_UPDATE_VIEW[] = "ClearCase.UpdateView";
+static const char CMD_ID_CHECKIN_ALL[] = "ClearCase.CheckInAll";
+static const char CMD_ID_STATUS[] = "ClearCase.Status";
+
+StatusMap ClearCasePlugin::s_statusMap;
+
+static const VcsBase::VcsBaseEditorParameters editorParameters[] = {
+{
+ VcsBase::RegularCommandOutput,
+ "ClearCase Command Log Editor", // id
+ QT_TRANSLATE_NOOP("VCS", "ClearCase Command Log Editor"), // display name
+ "ClearCase Command Log Editor", // context
+ "application/vnd.audc.text.scs_cc_commandlog",
+ "scslog"},
+{ VcsBase::LogOutput,
+ "ClearCase File Log Editor", // id
+ QT_TRANSLATE_NOOP("VCS", "ClearCase File Log Editor"), // display_name
+ "ClearCase File Log Editor", // context
+ "application/vnd.audc.text.scs_cc_filelog",
+ "scsfilelog"},
+{ VcsBase::AnnotateOutput,
+ "ClearCase Annotation Editor", // id
+ QT_TRANSLATE_NOOP("VCS", "ClearCase Annotation Editor"), // display_name
+ "ClearCase Annotation Editor", // context
+ "application/vnd.audc.text.scs_cc_annotation",
+ "scsannotate"},
+{ VcsBase::DiffOutput,
+ "ClearCase Diff Editor", // id
+ QT_TRANSLATE_NOOP("VCS", "ClearCase Diff Editor"), // display_name
+ "ClearCase Diff Editor", // context
+ "text/x-patch","diff"}
+};
+
+// Utility to find a parameter set by type
+static inline const VcsBase::VcsBaseEditorParameters *findType(int ie)
+{
+ const VcsBase::EditorContentType et = static_cast<VcsBase::EditorContentType>(ie);
+ return VcsBase::VcsBaseEditorWidget::findType(editorParameters, sizeof(editorParameters)/sizeof(VcsBase::VcsBaseEditorParameters), et);
+}
+
+static inline QString debugCodec(const QTextCodec *c)
+{
+ return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec");
+}
+
+// ------------- ClearCasePlugin
+ClearCasePlugin *ClearCasePlugin::m_clearcasePluginInstance = 0;
+
+ClearCasePlugin::ClearCasePlugin() :
+ VcsBase::VcsBasePlugin(QLatin1String(ClearCase::Constants::CLEARCASECHECKINEDITOR_ID)),
+ m_commandLocator(0),
+ m_checkOutAction(0),
+ m_checkInCurrentAction(0),
+ m_undoCheckOutAction(0),
+ m_undoHijackAction(0),
+ m_diffCurrentAction(0),
+ m_historyCurrentAction(0),
+ m_annotateCurrentAction(0),
+ m_addFileAction(0),
+ m_diffActivityAction(0),
+ m_updateIndexAction(0),
+ m_updateViewAction(0),
+ m_checkInActivityAction(0),
+ m_checkInAllAction(0),
+ m_statusAction(0),
+ m_checkInSelectedAction(0),
+ m_checkInDiffAction(0),
+ m_submitUndoAction(0),
+ m_submitRedoAction(0),
+ m_menuAction(0),
+ m_submitActionTriggered(false),
+ activityMutex(0)
+{
+}
+
+ClearCasePlugin::~ClearCasePlugin()
+{
+ cleanCheckInMessageFile();
+ // wait for sync thread to finish reading activities
+ activityMutex->lock();
+ delete activityMutex;
+}
+
+void ClearCasePlugin::cleanCheckInMessageFile()
+{
+ if (!m_checkInMessageFileName.isEmpty()) {
+ QFile::remove(m_checkInMessageFileName);
+ m_checkInMessageFileName.clear();
+ }
+}
+
+bool ClearCasePlugin::isCheckInEditorOpen() const
+{
+ return !m_checkInMessageFileName.isEmpty();
+}
+
+QString ClearCasePlugin::findTopLevel(const QString &directory) const
+{
+ // Snapshot view
+ QString topLevel =
+ findRepositoryForDirectory(directory, QLatin1String(ClearCase::Constants::CLEARCASE_ROOT_FILE));
+ if (!topLevel.isEmpty())
+ return topLevel;
+ // Dynamic view
+ bool isDynamic;
+ ccGetView(directory, &isDynamic);
+ if (isDynamic) {
+ QDir dir(directory);
+ // Go up to one level before root
+ QDir outer = dir;
+ outer.cdUp();
+ while (outer.cdUp())
+ dir.cdUp();
+ topLevel = dir.path(); // M:/View_Name
+ dir.cdUp(); // Z:/ (dynamic view with assigned letter)
+ if (!ccGetView(dir.path()).isEmpty())
+ topLevel = dir.path();
+ }
+
+ return topLevel;
+}
+
+static const VcsBase::VcsBaseSubmitEditorParameters submitParameters = {
+ ClearCase::Constants::CLEARCASE_SUBMIT_MIMETYPE,
+ ClearCase::Constants::CLEARCASECHECKINEDITOR_ID,
+ ClearCase::Constants::CLEARCASECHECKINEDITOR_DISPLAY_NAME,
+ ClearCase::Constants::CLEARCASECHECKINEDITOR
+};
+
+bool ClearCasePlugin::initialize(const QStringList & /*arguments */, QString *errorMessage)
+{
+ typedef VcsBase::VcsSubmitEditorFactory<ClearCaseSubmitEditor> ClearCaseSubmitEditorFactory;
+ typedef VcsBase::VcsEditorFactory<ClearCaseEditor> ClearCaseEditorFactory;
+ using namespace Constants;
+
+ using namespace Core::Constants;
+ using namespace ExtensionSystem;
+
+ initializeVcs(new ClearCaseControl(this));
+
+ m_clearcasePluginInstance = this;
+ activityMutex = new QMutex;
+ connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(closing()));
+ connect(Core::ICore::progressManager(), SIGNAL(allTasksFinished(QString)),
+ this, SLOT(tasksFinished(QString)));
+
+ if (!Core::ICore::mimeDatabase()->addMimeTypes(QLatin1String(":/clearcase/ClearCase.mimetypes.xml"), errorMessage))
+ return false;
+
+ m_settings.fromSettings(Core::ICore::settings());
+
+ // update view name when changing active project
+ if (ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance())
+ connect(pe, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
+ this, SLOT(projectChanged(ProjectExplorer::Project*)));
+
+ addAutoReleasedObject(new SettingsPage);
+
+ addAutoReleasedObject(new ClearCaseSubmitEditorFactory(&submitParameters));
+
+ // any editor responds to describe (when clicking a version)
+ static const char *describeSlot = SLOT(describe(QString,QString));
+ const int editorCount = sizeof(editorParameters)/sizeof(VcsBase::VcsBaseEditorParameters);
+ for (int i = 0; i < editorCount; i++)
+ addAutoReleasedObject(new ClearCaseEditorFactory(editorParameters + i, this, describeSlot));
+
+ const QString description = QLatin1String("ClearCase");
+ const QString prefix = QLatin1String("cc");
+ // register cc prefix in Locator
+ m_commandLocator = new Locator::CommandLocator(prefix, description, prefix);
+ addAutoReleasedObject(m_commandLocator);
+
+ //register actions
+ Core::ActionContainer *toolsContainer = Core::ActionManager::actionContainer(M_TOOLS);
+
+ Core::ActionContainer *clearcaseMenu = Core::ActionManager::createMenu(Core::Id(CMD_ID_CLEARCASE_MENU));
+ clearcaseMenu->menu()->setTitle(tr("C&learCase"));
+ toolsContainer->addMenu(clearcaseMenu);
+ m_menuAction = clearcaseMenu->menu()->menuAction();
+ Core::Context globalcontext(C_GLOBAL);
+ Core::Command *command;
+
+ m_checkOutAction = new Utils::ParameterAction(tr("Check Out..."), tr("Check &Out \"%1\"..."), Utils::ParameterAction::AlwaysEnabled, this);
+ command = Core::ActionManager::registerAction(m_checkOutAction, CMD_ID_CHECKOUT,
+ globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+O") : tr("Alt+L,Alt+O")));
+ connect(m_checkOutAction, SIGNAL(triggered()), this, SLOT(checkOutCurrentFile()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_checkInCurrentAction = new Utils::ParameterAction(tr("Check &In..."), tr("Check &In \"%1\"..."), Utils::ParameterAction::AlwaysEnabled, this);
+ command = Core::ActionManager::registerAction(m_checkInCurrentAction, CMD_ID_CHECKIN, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+I") : tr("Alt+L,Alt+I")));
+ connect(m_checkInCurrentAction, SIGNAL(triggered()), this, SLOT(startCheckInCurrentFile()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_undoCheckOutAction = new Utils::ParameterAction(tr("Undo Check Out"), tr("&Undo Check Out \"%1\""), Utils::ParameterAction::AlwaysEnabled, this);
+ command = Core::ActionManager::registerAction(m_undoCheckOutAction, CMD_ID_UNDOCHECKOUT, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+U") : tr("Alt+L,Alt+U")));
+ connect(m_undoCheckOutAction, SIGNAL(triggered()), this, SLOT(undoCheckOutCurrent()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_undoHijackAction = new Utils::ParameterAction(tr("Undo Hijack"), tr("Undo Hi&jack \"%1\""), Utils::ParameterAction::AlwaysEnabled, this);
+ command = Core::ActionManager::registerAction(m_undoHijackAction, CMD_ID_UNDOHIJACK, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+R") : tr("Alt+L,Alt+R")));
+ connect(m_undoHijackAction, SIGNAL(triggered()), this, SLOT(undoHijackCurrent()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ clearcaseMenu->addSeparator(globalcontext);
+
+ m_diffCurrentAction = new Utils::ParameterAction(tr("Diff Current File"), tr("&Diff \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ command = Core::ActionManager::registerAction(m_diffCurrentAction,
+ CMD_ID_DIFF_CURRENT, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+D") : tr("Alt+L,Alt+D")));
+ connect(m_diffCurrentAction, SIGNAL(triggered()), this, SLOT(diffCurrentFile()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_historyCurrentAction = new Utils::ParameterAction(tr("History Current File"), tr("&History \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ command = Core::ActionManager::registerAction(m_historyCurrentAction,
+ CMD_ID_HISTORY_CURRENT, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+H") : tr("Alt+L,Alt+H")));
+ connect(m_historyCurrentAction, SIGNAL(triggered()), this,
+ SLOT(historyCurrentFile()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_annotateCurrentAction = new Utils::ParameterAction(tr("Annotate Current File"), tr("&Annotate \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ command = Core::ActionManager::registerAction(m_annotateCurrentAction,
+ CMD_ID_ANNOTATE, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+A") : tr("Alt+L,Alt+A")));
+ connect(m_annotateCurrentAction, SIGNAL(triggered()), this,
+ SLOT(annotateCurrentFile()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_addFileAction = new Utils::ParameterAction(tr("Add File..."), tr("Add File \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ command = Core::ActionManager::registerAction(m_addFileAction, CMD_ID_ADD_FILE, globalcontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ connect(m_addFileAction, SIGNAL(triggered()), this, SLOT(addCurrentFile()));
+ clearcaseMenu->addAction(command);
+
+ clearcaseMenu->addSeparator(globalcontext);
+
+ m_diffActivityAction = new QAction(tr("Diff A&ctivity..."), this);
+ command = Core::ActionManager::registerAction(m_diffActivityAction, CMD_ID_DIFF_ACTIVITY, globalcontext);
+ connect(m_diffActivityAction, SIGNAL(triggered()), this, SLOT(diffActivity()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_checkInActivityAction = new Utils::ParameterAction(tr("Ch&eck In Activity"), tr("Chec&k In Activity \"%1\"..."), Utils::ParameterAction::EnabledWithParameter, this);
+ command = Core::ActionManager::registerAction(m_checkInActivityAction, CMD_ID_CHECKIN_ACTIVITY, globalcontext);
+ connect(m_checkInActivityAction, SIGNAL(triggered()), this, SLOT(startCheckInActivity()));
+ command->setAttribute(Core::Command::CA_UpdateText);
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ clearcaseMenu->addSeparator(globalcontext);
+
+ m_updateIndexAction = new QAction(tr("Update Index"), this);
+ command = Core::ActionManager::registerAction(m_updateIndexAction, CMD_ID_UPDATEINDEX, globalcontext);
+ connect(m_updateIndexAction, SIGNAL(triggered()), this, SLOT(updateIndex()));
+ clearcaseMenu->addAction(command);
+
+ m_updateViewAction = new Utils::ParameterAction(tr("Update View"), tr("U&pdate View \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+ command = Core::ActionManager::registerAction(m_updateViewAction, CMD_ID_UPDATE_VIEW, globalcontext);
+ connect(m_updateViewAction, SIGNAL(triggered()), this, SLOT(updateView()));
+ command->setAttribute(Core::Command::CA_UpdateText);
+ clearcaseMenu->addAction(command);
+
+ clearcaseMenu->addSeparator(globalcontext);
+
+ m_checkInAllAction = new QAction(tr("Check In All &Files..."), this);
+ command = Core::ActionManager::registerAction(m_checkInAllAction, CMD_ID_CHECKIN_ALL, globalcontext);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+F") : tr("Alt+L,Alt+F")));
+ connect(m_checkInAllAction, SIGNAL(triggered()), this, SLOT(startCheckInAll()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ m_statusAction = new QAction(tr("View &Status"), this);
+ command = Core::ActionManager::registerAction(m_statusAction, CMD_ID_STATUS, globalcontext);
+ command->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+L,Meta+S") : tr("Alt+L,Alt+S")));
+ connect(m_statusAction, SIGNAL(triggered()), this, SLOT(viewStatus()));
+ clearcaseMenu->addAction(command);
+ m_commandLocator->appendCommand(command);
+
+ // Actions of the submit editor
+ Core::Context clearcasecheckincontext(Constants::CLEARCASECHECKINEDITOR);
+
+ m_checkInSelectedAction = new QAction(VcsBase::VcsBaseSubmitEditor::submitIcon(), tr("Check In"), this);
+ command = Core::ActionManager::registerAction(m_checkInSelectedAction, Constants::CHECKIN_SELECTED, clearcasecheckincontext);
+ command->setAttribute(Core::Command::CA_UpdateText);
+ connect(m_checkInSelectedAction, SIGNAL(triggered()), this, SLOT(checkInSelected()));
+
+ m_checkInDiffAction = new QAction(VcsBase::VcsBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this);
+ command = Core::ActionManager::registerAction(m_checkInDiffAction , Constants::DIFF_SELECTED, clearcasecheckincontext);
+
+ m_submitUndoAction = new QAction(tr("&Undo"), this);
+ command = Core::ActionManager::registerAction(m_submitUndoAction, Core::Constants::UNDO, clearcasecheckincontext);
+
+ m_submitRedoAction = new QAction(tr("&Redo"), this);
+ command = Core::ActionManager::registerAction(m_submitRedoAction, Core::Constants::REDO, clearcasecheckincontext);
+
+ return true;
+}
+
+// called before closing the submit editor
+bool ClearCasePlugin::submitEditorAboutToClose(VcsBase::VcsBaseSubmitEditor *submitEditor)
+{
+ if (!isCheckInEditorOpen())
+ return true;
+
+ Core::IDocument *editorDocument = submitEditor->document();
+ ClearCaseSubmitEditor *editor = qobject_cast<ClearCaseSubmitEditor *>(submitEditor);
+ if (!editorDocument || !editor)
+ return true;
+
+ // Submit editor closing. Make it write out the check in message
+ // and retrieve files
+ const QFileInfo editorFile(editorDocument->fileName());
+ const QFileInfo changeFile(m_checkInMessageFileName);
+ if (editorFile.absoluteFilePath() != changeFile.absoluteFilePath())
+ return true; // Oops?!
+
+ // Prompt user. Force a prompt unless submit was actually invoked (that
+ // is, the editor was closed or shutdown).
+ bool prompt = m_settings.promptToCheckIn;
+ const VcsBase::VcsBaseSubmitEditor::PromptSubmitResult answer =
+ editor->promptSubmit(tr("Closing ClearCase Editor"),
+ tr("Do you want to check in the files?"),
+ tr("The comment check failed. Do you want to check in the files?"),
+ &prompt, !m_submitActionTriggered);
+ m_submitActionTriggered = false;
+ switch (answer) {
+ case VcsBase::VcsBaseSubmitEditor::SubmitCanceled:
+ return false; // Keep editing and change file
+ case VcsBase::VcsBaseSubmitEditor::SubmitDiscarded:
+ cleanCheckInMessageFile();
+ return true; // Cancel all
+ default:
+ break;
+ }
+ // If user changed
+ if (prompt != m_settings.promptToCheckIn) {
+ m_settings.promptToCheckIn = prompt;
+ m_settings.toSettings(Core::ICore::settings());
+ }
+
+ const QStringList fileList = editor->checkedFiles();
+ bool closeEditor = true;
+ if (!fileList.empty()) {
+ // get message & check in
+ closeEditor = Core::DocumentManager::saveDocument(editorDocument);
+ if (closeEditor) {
+ ClearCaseSubmitEditorWidget *widget = editor->submitEditorWidget();
+ closeEditor = vcsCheckIn(m_checkInMessageFileName, fileList, widget->activity(),
+ widget->isIdentical(), widget->isPreserve(),
+ widget->activityChanged());
+ }
+ }
+ // vcsCheckIn might fail if some of the files failed to check-in (though it does check-in
+ // those who didn't fail). Therefore, if more than one file was sent, consider it as success
+ // anyway (sync will be called from vcsCheckIn for next attempt)
+ closeEditor |= (fileList.count() > 1);
+ if (closeEditor)
+ cleanCheckInMessageFile();
+ return closeEditor;
+}
+
+void ClearCasePlugin::diffCheckInFiles(const QStringList &files)
+{
+ ccDiffWithPred(files);
+}
+
+static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db)
+{
+ if (VcsBase::VcsBaseEditorWidget *ve = qobject_cast<VcsBase::VcsBaseEditorWidget*>(editor->widget()))
+ ve->setDiffBaseDirectory(db);
+}
+
+//! retrieve full location of predecessor of \a version
+QString ClearCasePlugin::ccGetPredecessor(const QString &version) const
+{
+ QStringList args(QLatin1String("describe"));
+ args << QLatin1String("-fmt") << QLatin1String("%En@@%PSn") << version;
+ const ClearCaseResponse response =
+ runCleartool(currentState().topLevel(), args, m_settings.timeOutMS(), SilentRun);
+ if (response.error || response.stdOut.endsWith(QLatin1Char('@'))) // <name-unknown>@@
+ return QString();
+ else
+ return response.stdOut;
+}
+
+QStringList ClearCasePlugin::ccGetActiveVobs() const
+{
+ QStringList res;
+ QStringList args(QLatin1String("lsvob"));
+ args << QLatin1String("-short");
+ QString topLevel = currentState().topLevel();
+ const ClearCaseResponse response =
+ runCleartool(topLevel, args, m_settings.timeOutMS(), SilentRun);
+ if (response.error)
+ return res;
+ foreach (QString dir, response.stdOut.split(QLatin1Char('\n'), QString::SkipEmptyParts)) {
+ dir = dir.mid(1); // omit first slash
+ QFileInfo fi(topLevel, dir);
+ if (fi.exists())
+ res.append(dir);
+ }
+ return res;
+}
+
+// file must be relative to topLevel, and using '/' path separator
+FileStatus ClearCasePlugin::vcsStatus(const QString &file) const
+{
+ return s_statusMap.value(file, FileStatus(FileStatus::Unknown));
+}
+
+QString ClearCasePlugin::ccGetFileActivity(const QString &workingDir, const QString &file)
+{
+ QStringList args(QLatin1String("lscheckout"));
+ args << QLatin1String("-fmt") << QLatin1String("%[activity]p");
+ args << file;
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(), SilentRun);
+ return response.stdOut;
+}
+
+ClearCaseSubmitEditor *ClearCasePlugin::openClearCaseSubmitEditor(const QString &fileName)
+{
+ Core::IEditor *editor =
+ Core::EditorManager::openEditor(fileName,
+ Constants::CLEARCASECHECKINEDITOR_ID,
+ Core::EditorManager::ModeSwitch);
+ ClearCaseSubmitEditor *submitEditor = qobject_cast<ClearCaseSubmitEditor*>(editor);
+ QTC_CHECK(submitEditor);
+ submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_checkInSelectedAction, m_checkInDiffAction);
+ connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffCheckInFiles(QStringList)));
+ submitEditor->setCheckScriptWorkingDirectory(currentState().topLevel());
+ return submitEditor;
+}
+
+void ClearCasePlugin::updateStatusActions()
+{
+ bool hasFile = currentState().hasFile();
+ FileStatus fileStatus = s_statusMap.value(currentState().relativeCurrentFile(), FileStatus(FileStatus::Unknown));
+ m_checkOutAction->setEnabled(hasFile && (fileStatus.status & (FileStatus::CheckedIn | FileStatus::Hijacked)));
+ m_undoCheckOutAction->setEnabled(hasFile && (fileStatus.status & FileStatus::CheckedOut));
+ m_undoHijackAction->setEnabled(hasFile && (fileStatus.status & FileStatus::Hijacked));
+ m_checkInCurrentAction->setEnabled(hasFile && (fileStatus.status & FileStatus::CheckedOut));
+ m_addFileAction->setEnabled(hasFile && (fileStatus.status & FileStatus::NotManaged));
+}
+
+void ClearCasePlugin::updateActions(VcsBase::VcsBasePlugin::ActionState as)
+{
+ if (!enableMenuAction(as, m_menuAction)) {
+ m_commandLocator->setEnabled(false);
+ return;
+ }
+ const VcsBase::VcsBasePluginState state = currentState();
+ const bool hasTopLevel = state.hasTopLevel();
+ m_commandLocator->setEnabled(hasTopLevel);
+ if (hasTopLevel)
+ m_topLevel = state.topLevel();
+
+ m_updateViewAction->setParameter(m_view);
+
+ const QString fileName = state.currentFileName();
+ m_checkOutAction->setParameter(fileName);
+ m_undoCheckOutAction->setParameter(fileName);
+ m_undoHijackAction->setParameter(fileName);
+ m_diffCurrentAction->setParameter(fileName);
+ m_checkInCurrentAction->setParameter(fileName);
+ m_historyCurrentAction->setParameter(fileName);
+ m_annotateCurrentAction->setParameter(fileName);
+ m_addFileAction->setParameter(fileName);
+ m_updateIndexAction->setEnabled(!m_settings.disableIndexer);
+ updateStatusActions();
+}
+
+void ClearCasePlugin::checkOutCurrentFile()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ vcsOpen(state.currentFileTopLevel(), state.relativeCurrentFile());
+}
+
+void ClearCasePlugin::addCurrentFile()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile());
+}
+
+void ClearCasePlugin::setStatus(const QString &file, FileStatus::Status status, bool update)
+{
+ s_statusMap[file] = FileStatus(status, QFileInfo(currentState().topLevel(), file).permissions());
+ if (update && (currentState().relativeCurrentFile() == file))
+ updateStatusActions();
+}
+
+void ClearCasePlugin::undoCheckOutCurrent()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ QString file = state.relativeCurrentFile();
+ const QString fileName = QDir::toNativeSeparators(file);
+
+ QStringList args(QLatin1String("diff"));
+ args << QLatin1String("-diff_format") << QLatin1String("-predecessor");
+ args << fileName;
+
+ const ClearCaseResponse diffResponse =
+ runCleartool(state.currentFileTopLevel(), args, m_settings.timeOutMS(), 0);
+
+ bool different = diffResponse.error; // return value is 1 if there is any difference
+ bool keep = false;
+ if (different) {
+ Ui::UndoCheckOut uncoUi;
+ QDialog uncoDlg;
+ uncoUi.setupUi(&uncoDlg);
+ uncoUi.lblMessage->setText(tr("Do you want to undo the check out of '%1'?").arg(fileName));
+ if (uncoDlg.exec() != QDialog::Accepted)
+ return;
+ keep = uncoUi.chkKeep->isChecked();
+ }
+ vcsUndoCheckOut(state.topLevel(), file, keep);
+}
+
+bool ClearCasePlugin::vcsUndoCheckOut(const QString &workingDir, const QString &fileName, bool keep)
+{
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << workingDir << fileName << keep;
+
+ Core::FileChangeBlocker fcb(fileName);
+
+ // revert
+ QStringList args(QLatin1String("uncheckout"));
+ args << QLatin1String(keep ? "-keep" : "-rm");
+ args << QDir::toNativeSeparators(fileName);
+
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(),
+ ShowStdOutInLogWindow | FullySynchronously);
+
+ if (!response.error) {
+ if (!m_settings.disableIndexer)
+ setStatus(fileName, FileStatus::CheckedIn);
+ clearCaseControl()->emitFilesChanged(QStringList(fileName));
+ }
+ return !response.error;
+}
+
+bool ClearCasePlugin::vcsUndoHijack(const QString &workingDir, const QString &fileName, bool keep)
+{
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << workingDir << fileName << keep;
+ QStringList args(QLatin1String("update"));
+ args << QLatin1String(keep ? "-rename" : "-overwrite");
+ args << QLatin1String("-log");
+#ifdef Q_OS_WIN32
+ args << QLatin1String("NUL");
+#else
+ args << QLatin1String("/dev/null");
+#endif
+ args << QDir::toNativeSeparators(fileName);
+
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(),
+ ShowStdOutInLogWindow | FullySynchronously);
+ if (!response.error && !m_settings.disableIndexer)
+ setStatus(fileName, FileStatus::CheckedIn);
+ return !response.error;
+}
+
+void ClearCasePlugin::undoHijackCurrent()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ const QString fileName = state.relativeCurrentFile();
+
+ bool keep = false;
+ QString diffres = diffExternal(ccGetFileVersion(state.topLevel(), fileName), fileName);
+ if (diffres.at(0) != QLatin1Char('F')) { // Files are identical
+ Ui::UndoCheckOut unhijackUi;
+ QDialog unhijackDlg;
+ unhijackUi.setupUi(&unhijackDlg);
+ unhijackDlg.setWindowTitle(tr("Undo hijack file"));
+ unhijackUi.lblMessage->setText(tr("Do you want to undo hijack of '%1'?")
+ .arg(QDir::toNativeSeparators(fileName)));
+ if (unhijackDlg.exec() != QDialog::Accepted)
+ return;
+ keep = unhijackUi.chkKeep->isChecked();
+ }
+
+ Core::FileChangeBlocker fcb(state.currentFile());
+
+ // revert
+ if (vcsUndoHijack(state.currentFileTopLevel(), fileName, keep))
+ clearCaseControl()->emitFilesChanged(QStringList(state.currentFile()));
+}
+
+QString ClearCasePlugin::ccGetFileVersion(const QString &workingDir, const QString &file) const
+{
+ QStringList args(QLatin1String("ls"));
+ args << QLatin1String("-short") << file;
+ return runCleartoolSync(workingDir, args).trimmed();
+}
+
+void ClearCasePlugin::ccDiffWithPred(const QStringList &files)
+{
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << files;
+ QString topLevel = currentState().topLevel();
+ const QString source = VcsBase::VcsBaseEditorWidget::getSource(topLevel, files);
+ QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VcsBase::VcsBaseEditorWidget::getCodec(source);
+
+ if ((m_settings.diffType == GraphicalDiff) && (files.count() == 1)) {
+ QString file = files.first();
+ if (s_statusMap[file].status == FileStatus::Hijacked)
+ diffGraphical(ccGetFileVersion(topLevel, file), file);
+ else
+ diffGraphical(file);
+ return; // done here, diff is opened in a new window
+ }
+ QString result;
+ foreach (const QString &file, files) {
+ if (s_statusMap[QDir::fromNativeSeparators(file)].status == FileStatus::Hijacked)
+ result += diffExternal(ccGetFileVersion(topLevel, file), file);
+ else
+ result += diffExternal(file);
+ }
+
+ QString diffname;
+
+ // diff of a single file? re-use an existing view if possible to support
+ // the common usage pattern of continuously changing and diffing a file
+ const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::DiffOutput, topLevel, files);
+ if (files.count() == 1) {
+ // Show in the same editor if diff has been executed before
+ if (Core::IEditor *existingEditor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) {
+ existingEditor->createNew(result);
+ Core::EditorManager::activateEditor(existingEditor, Core::EditorManager::ModeSwitch);
+ setDiffBaseDirectory(existingEditor, topLevel);
+ return;
+ }
+ diffname = QDir::toNativeSeparators(files.first());
+ }
+ const QString title = QString::fromLatin1("cc diff %1").arg(diffname);
+ Core::IEditor *editor = showOutputInEditor(title, result, VcsBase::DiffOutput, source, codec);
+ setDiffBaseDirectory(editor, topLevel);
+ VcsBase::VcsBaseEditorWidget::tagEditor(editor, tag);
+ ClearCaseEditor *diffEditorWidget = qobject_cast<ClearCaseEditor *>(editor->widget());
+ QTC_ASSERT(diffEditorWidget, return);
+ if (files.count() == 1)
+ editor->setProperty("originalFileName", diffname);
+}
+
+QStringList ClearCasePlugin::ccGetActivityVersions(const QString &workingDir, const QString &activity)
+{
+ QStringList args(QLatin1String("lsactivity"));
+ args << QLatin1String("-fmt") << QLatin1String("%[versions]Cp") << activity;
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(), SilentRun);
+ if (response.error)
+ return QStringList();
+ QStringList versions = response.stdOut.split(QLatin1String(", "));
+ versions.sort();
+ return versions;
+}
+
+void ClearCasePlugin::rmdir(const QString &path)
+{
+ QDir dir(path);
+ foreach (QFileInfo fi, dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)) {
+ if (fi.isDir()) {
+ rmdir(fi.canonicalFilePath());
+ dir.rmdir(fi.baseName());
+ }
+ else
+ QFile::remove(fi.canonicalFilePath());
+ }
+}
+
+void ClearCasePlugin::diffActivity()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasTopLevel(), return);
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO;
+ QString topLevel = state.topLevel();
+ QString activity = QInputDialog::getText(0, tr("Enter Activity"), tr("Activity Name"), QLineEdit::Normal, m_activity);
+ if (activity.isEmpty())
+ return;
+ QStringList versions = ccGetActivityVersions(topLevel, activity);
+
+ QString result;
+ // map from fileName to (first, latest) pair
+ QMap<QString, QStringPair> filever;
+ int topLevelLen = topLevel.length();
+ foreach (const QString &version, versions) {
+ QString shortver = version.mid(topLevelLen + 1);
+ int atatpos = shortver.indexOf(QLatin1String("@@"));
+ if (atatpos != -1) {
+ QString file = shortver.left(atatpos);
+ // latest version - updated each line
+ filever[file].second = shortver;
+
+ // pre-first version. only for the first occurence
+ if (filever[file].first.isEmpty()) {
+ int verpos = shortver.lastIndexOf(QRegExp(QLatin1String("[^0-9]"))) + 1;
+ int vernum = shortver.mid(verpos).toInt();
+ if (vernum)
+ --vernum;
+ shortver.replace(verpos, shortver.length() - verpos, QString::number(vernum));
+ // first version
+ filever[file].first = shortver;
+ }
+ }
+ }
+
+ if ((m_settings.diffType == GraphicalDiff) && (filever.count() == 1)) {
+ QStringPair pair(filever.values().at(0));
+ diffGraphical(pair.first, pair.second);
+ return;
+ }
+ rmdir(QDir::tempPath() + QLatin1String("/ccdiff/") + activity);
+ QDir(QDir::tempPath()).rmpath(QLatin1String("ccdiff/") + activity);
+ m_diffPrefix = activity;
+ foreach (const QString &file, filever.keys()) {
+ QStringPair pair(filever.value(file));
+ if (pair.first.contains(QLatin1String("CHECKEDOUT")))
+ pair.first = ccGetPredecessor(pair.first.left(pair.first.indexOf(QLatin1String("@@"))));
+ result += diffExternal(pair.first, pair.second, true);
+ }
+ m_diffPrefix.clear();
+ const QString title = QString::fromLatin1("%1.patch").arg(activity);
+ Core::IEditor *editor = showOutputInEditor(title, result, VcsBase::DiffOutput, activity, 0);
+ setDiffBaseDirectory(editor, topLevel);
+}
+
+void ClearCasePlugin::diffCurrentFile()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ ccDiffWithPred(QStringList(state.relativeCurrentFile()));
+}
+
+void ClearCasePlugin::startCheckInCurrentFile()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ QString nativeFile = QDir::toNativeSeparators(state.relativeCurrentFile());
+ startCheckIn(state.currentFileTopLevel(), QStringList(nativeFile));
+}
+
+void ClearCasePlugin::startCheckInAll()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasTopLevel(), return);
+ QString topLevel = state.topLevel();
+ QStringList files;
+ for (StatusMap::ConstIterator iterator = s_statusMap.constBegin();
+ iterator != s_statusMap.constEnd();
+ ++iterator)
+ {
+ if (iterator.value().status == FileStatus::CheckedOut)
+ files.append(QDir::toNativeSeparators(iterator.key()));
+ }
+ startCheckIn(topLevel, files);
+}
+
+void ClearCasePlugin::startCheckInActivity()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasProject(), return);
+ QDialog dlg;
+ QVBoxLayout *layout = new QVBoxLayout(&dlg);
+ ActivitySelector *actSelector = new ActivitySelector(&dlg);
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dlg);
+ connect(buttonBox, SIGNAL(accepted()), &dlg, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), &dlg, SLOT(reject()));
+ layout->addWidget(actSelector);
+ layout->addWidget(buttonBox);
+ dlg.setWindowTitle(tr("Check In Activity"));
+ if (!dlg.exec())
+ return;
+ QString topLevel = state.topLevel();
+ int topLevelLen = topLevel.length();
+ QStringList versions = ccGetActivityVersions(topLevel, actSelector->activity());
+ QStringList files;
+ QString last;
+ foreach (const QString &version, versions) {
+ int atatpos = version.indexOf(QLatin1String("@@"));
+ if ((atatpos != -1) && (version.indexOf(QLatin1String("CHECKEDOUT"), atatpos) != -1)) {
+ QString file = version.left(atatpos);
+ if (file != last)
+ files.append(file.mid(topLevelLen+1));
+ last = file;
+ }
+ }
+ startCheckIn(state.currentProjectPath(), files);
+}
+
+/* Start check in of files of a single repository by displaying
+ * template and files in a submit editor. On closing, the real
+ * check in will start. */
+void ClearCasePlugin::startCheckIn(const QString &workingDir, const QStringList &files)
+{
+ if (VcsBase::VcsBaseSubmitEditor::raiseSubmitEditor())
+ return;
+ VcsBase::VcsBaseOutputWindow *outputwindow = VcsBase::VcsBaseOutputWindow::instance();
+
+ if (isCheckInEditorOpen()) {
+ outputwindow->appendWarning(tr("Another check in is currently being executed."));
+ return;
+ }
+
+ // Get list of added/modified/deleted files
+ if (files.empty()) {
+ outputwindow->appendWarning(tr("There are no modified files."));
+ return;
+ }
+ // Create a new submit change file containing the submit template
+ Utils::TempFileSaver saver;
+ saver.setAutoRemove(false);
+ // TODO: Retrieve submit template from
+ const QString submitTemplate;
+ // Create a submit
+ saver.write(submitTemplate.toUtf8());
+ if (!saver.finalize()) {
+ VcsBase::VcsBaseOutputWindow::instance()->appendError(saver.errorString());
+ return;
+ }
+ m_checkInMessageFileName = saver.fileName();
+ // Create a submit editor and set file list
+ ClearCaseSubmitEditor *editor = openClearCaseSubmitEditor(m_checkInMessageFileName);
+ editor->setStatusList(files);
+ if (files.size() == 1) {
+ QString activity = ccGetFileActivity(workingDir, files.first());
+ editor->submitEditorWidget()->setActivity(activity);
+ }
+}
+
+void ClearCasePlugin::historyCurrentFile()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ history(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()), true);
+}
+
+void ClearCasePlugin::updateView()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasTopLevel(), return);
+ ccUpdate(state.topLevel());
+}
+
+void ClearCasePlugin::history(const QString &workingDir,
+ const QStringList &files,
+ bool enableAnnotationContextMenu)
+{
+ QTextCodec *codec = VcsBase::VcsBaseEditorWidget::getCodec(workingDir, files);
+ // no need for temp file
+ QStringList args(QLatin1String("lshistory"));
+ if (m_settings.historyCount > 0)
+ args << QLatin1String("-last") << QString::number(m_settings.historyCount);
+ if (!m_intStream.isEmpty())
+ args << QLatin1String("-branch") << m_intStream;
+ foreach (const QString &file, files)
+ args.append(QDir::toNativeSeparators(file));
+
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(),
+ 0, codec);
+ if (response.error)
+ return;
+
+ // Re-use an existing view if possible to support
+ // the common usage pattern of continuously changing and diffing a file
+
+ const QString id = VcsBase::VcsBaseEditorWidget::getTitleId(workingDir, files);
+ const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::LogOutput, workingDir, files);
+ if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) {
+ editor->createNew(response.stdOut);
+ Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch);
+ } else {
+ const QString title = QString::fromLatin1("cc history %1").arg(id);
+ const QString source = VcsBase::VcsBaseEditorWidget::getSource(workingDir, files);
+ Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VcsBase::LogOutput, source, codec);
+ VcsBase::VcsBaseEditorWidget::tagEditor(newEditor, tag);
+ if (enableAnnotationContextMenu)
+ VcsBase::VcsBaseEditorWidget::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true);
+ }
+}
+
+void ClearCasePlugin::viewStatus()
+{
+ QTC_ASSERT(!m_view.isEmpty() && !m_settings.disableIndexer, return);
+ VcsBase::VcsBaseOutputWindow *outputwindow = VcsBase::VcsBaseOutputWindow::instance();
+ outputwindow->appendCommand(QLatin1String("Indexed files status (C=Checked Out, H=Hijacked, ?=Missing)"));
+ bool anymod = false;
+ for (StatusMap::ConstIterator it = s_statusMap.constBegin();
+ it != s_statusMap.constEnd();
+ ++it)
+ {
+ char cstat = 0;
+ switch (it.value().status) {
+ case FileStatus::CheckedOut: cstat = 'C'; break;
+ case FileStatus::Hijacked: cstat = 'H'; break;
+ case FileStatus::Missing: cstat = '?'; break;
+ default: break;
+ }
+ if (cstat) {
+ outputwindow->append(QString::fromLatin1("%1 %2\n")
+ .arg(cstat)
+ .arg(QDir::toNativeSeparators(it.key())));
+ anymod = true;
+ }
+ }
+ if (!anymod)
+ outputwindow->appendWarning(QLatin1String("No modified files found!"));
+}
+
+void ClearCasePlugin::ccUpdate(const QString &workingDir, const QStringList &relativePaths)
+{
+ QStringList args(QLatin1String("update"));
+ args << QLatin1String("-noverwrite");
+ if (!relativePaths.isEmpty())
+ args.append(relativePaths);
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.longTimeOutMS(), ShowStdOutInLogWindow);
+ if (!response.error)
+ clearCaseControl()->emitRepositoryChanged(workingDir);
+}
+
+void ClearCasePlugin::annotateCurrentFile()
+{
+ const VcsBase::VcsBasePluginState state = currentState();
+ QTC_ASSERT(state.hasFile(), return);
+ vcsAnnotate(state.currentFileTopLevel(), state.relativeCurrentFile());
+}
+
+void ClearCasePlugin::annotateVersion(const QString &file,
+ const QString &revision,
+ int lineNr)
+{
+ const QFileInfo fi(file);
+ vcsAnnotate(fi.absolutePath(), fi.fileName(), revision, lineNr);
+}
+
+void ClearCasePlugin::vcsAnnotate(const QString &workingDir, const QString &file,
+ const QString &revision /* = QString() */,
+ int lineNumber /* = -1 */) const
+{
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << file;
+
+ QTextCodec *codec = VcsBase::VcsBaseEditorWidget::getCodec(file);
+
+ // Determine id
+ QString id = file;
+ if (!revision.isEmpty())
+ id += QLatin1String("@@") + revision;
+
+ QStringList args(QLatin1String("annotate"));
+ args << QLatin1String("-nco") << QLatin1String("-f");
+ args << QLatin1String("-fmt") << QLatin1String("%-14.14Sd %-8.8u | ");
+ args << QLatin1String("-out") << QLatin1String("-");
+ args.append(QDir::toNativeSeparators(id));
+
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(), 0, codec);
+ if (response.error)
+ return;
+
+ // Re-use an existing view if possible to support
+ // the common usage pattern of continuously changing and diffing a file
+ const QString source = workingDir + QLatin1Char('/') + file;
+ if (lineNumber <= 0)
+ lineNumber = VcsBase::VcsBaseEditorWidget::lineNumberOfCurrentEditor(source);
+
+ QString headerSep(QLatin1String("-------------------------------------------------"));
+ int pos = qMax(0, response.stdOut.indexOf(headerSep));
+ // there are 2 identical headerSep lines - skip them
+ int dataStart = response.stdOut.indexOf(QLatin1Char('\n'), pos) + 1;
+ dataStart = response.stdOut.indexOf(QLatin1Char('\n'), dataStart) + 1;
+ QString res;
+ QTextStream stream(&res, QIODevice::WriteOnly | QIODevice::Text);
+ stream << response.stdOut.mid(dataStart) << headerSep << QLatin1Char('\n')
+ << headerSep << QLatin1Char('\n') << response.stdOut.left(pos);
+ const QStringList files = QStringList(file);
+ const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::AnnotateOutput, workingDir, files);
+ if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) {
+ editor->createNew(res);
+ VcsBase::VcsBaseEditorWidget::gotoLineOfEditor(editor, lineNumber);
+ Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch);
+ } else {
+ const QString title = QString::fromLatin1("cc annotate %1").arg(id);
+ Core::IEditor *newEditor = showOutputInEditor(title, res, VcsBase::AnnotateOutput, source, codec);
+ VcsBase::VcsBaseEditorWidget::tagEditor(newEditor, tag);
+ VcsBase::VcsBaseEditorWidget::gotoLineOfEditor(newEditor, lineNumber);
+ }
+}
+
+void ClearCasePlugin::describe(const QString &source, const QString &changeNr)
+{
+ const QFileInfo fi(source);
+ QString topLevel;
+ const bool manages = managesDirectory(fi.isDir() ? source : fi.absolutePath(), &topLevel);
+ if (!manages || topLevel.isEmpty())
+ return;
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << source << topLevel << changeNr;
+ QString description;
+ QString relPath = QDir::toNativeSeparators(QDir(topLevel).relativeFilePath(source));
+ QString id = QString::fromLatin1("%1@@%2").arg(relPath).arg(changeNr);
+
+ QStringList args(QLatin1String("describe"));
+ args.push_back(id);
+ QTextCodec *codec = VcsBase::VcsBaseEditorWidget::getCodec(source);
+ const ClearCaseResponse response =
+ runCleartool(topLevel, args, m_settings.timeOutMS(), 0, codec);
+ description = response.stdOut;
+ description += diffExternal(id);
+
+ // Re-use an existing view if possible to support
+ // the common usage pattern of continuously changing and diffing a file
+ const QString tag = VcsBase::VcsBaseEditorWidget::editorTag(VcsBase::DiffOutput, source, QStringList(), changeNr);
+ if (Core::IEditor *editor = VcsBase::VcsBaseEditorWidget::locateEditorByTag(tag)) {
+ editor->createNew(description);
+ Core::EditorManager::activateEditor(editor, Core::EditorManager::ModeSwitch);
+ } else {
+ const QString title = QString::fromLatin1("cc describe %1").arg(id);
+ Core::IEditor *newEditor = showOutputInEditor(title, description, VcsBase::DiffOutput, source, codec);
+ VcsBase::VcsBaseEditorWidget::tagEditor(newEditor, tag);
+ }
+}
+
+void ClearCasePlugin::checkInSelected()
+{
+ m_submitActionTriggered = true;
+ Core::EditorManager::instance()->closeEditor();
+}
+
+QString ClearCasePlugin::runCleartoolSync(const QString &workingDir,
+ const QStringList &arguments) const
+{
+ return runCleartool(workingDir, arguments, m_settings.timeOutMS(), SilentRun).stdOut;
+}
+
+ClearCaseResponse
+ ClearCasePlugin::runCleartool(const QString &workingDir,
+ const QStringList &arguments,
+ int timeOut,
+ unsigned flags,
+ QTextCodec *outputCodec) const
+{
+ const QString executable = m_settings.ccCommand;
+ ClearCaseResponse response;
+ if (executable.isEmpty()) {
+ response.error = true;
+ response.message = tr("No ClearCase executable specified!");
+ return response;
+ }
+
+ const Utils::SynchronousProcessResponse sp_resp =
+ VcsBase::VcsBasePlugin::runVcs(workingDir, executable,
+ arguments, timeOut, flags, outputCodec);
+
+ response.error = sp_resp.result != Utils::SynchronousProcessResponse::Finished;
+ if (response.error)
+ response.message = sp_resp.exitMessage(executable, timeOut);
+ response.stdErr = sp_resp.stdErr;
+ response.stdOut = sp_resp.stdOut;
+ return response;
+}
+
+Core::IEditor *ClearCasePlugin::showOutputInEditor(const QString& title, const QString &output,
+ int editorType, const QString &source,
+ QTextCodec *codec) const
+{
+ const VcsBase::VcsBaseEditorParameters *params = findType(editorType);
+ QTC_ASSERT(params, return 0);
+ const Core::Id id = params->id;
+ if (ClearCase::Constants::debug)
+ qDebug() << "ClearCasePlugin::showOutputInEditor" << title << id.name()
+ << "Size= " << output.size() << " Type=" << editorType << debugCodec(codec);
+ QString s = title;
+ Core::IEditor *editor = Core::EditorManager::openEditorWithContents(id, &s, output);
+ connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)),
+ this, SLOT(annotateVersion(QString,QString,int)));
+ ClearCaseEditor *e = qobject_cast<ClearCaseEditor*>(editor->widget());
+ if (!e)
+ return 0;
+ e->setForceReadOnly(true);
+ s.replace(QLatin1Char(' '), QLatin1Char('_'));
+ e->setSuggestedFileName(s);
+ if (!source.isEmpty())
+ e->setSource(source);
+ if (codec)
+ e->setCodec(codec);
+ Core::IEditor *ie = e->editor();
+ Core::EditorManager::activateEditor(ie, Core::EditorManager::ModeSwitch);
+ return ie;
+}
+
+const ClearCaseSettings &ClearCasePlugin::settings() const
+{
+ return m_settings;
+}
+
+void ClearCasePlugin::setSettings(const ClearCaseSettings &s)
+{
+ if (s != m_settings) {
+ m_settings = s;
+ m_settings.toSettings(Core::ICore::settings());
+ clearCaseControl()->emitConfigurationChanged();
+ }
+}
+
+ClearCasePlugin *ClearCasePlugin::instance()
+{
+ QTC_ASSERT(m_clearcasePluginInstance, return m_clearcasePluginInstance);
+ return m_clearcasePluginInstance;
+}
+
+bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName)
+{
+ QTC_ASSERT(currentState().hasTopLevel(), return false);
+
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << workingDir << fileName;
+
+ QFileInfo fi(workingDir, fileName);
+ QString topLevel = currentState().topLevel();
+ QString absPath = fi.absoluteFilePath();
+ const QString relFile = QDir(topLevel).relativeFilePath(absPath);
+
+ const QString file = QDir::toNativeSeparators(relFile);
+ const QString title = QString::fromLatin1("Checkout %1").arg(file);
+ CheckOutDialog coDialog(title);
+ if (!m_settings.disableIndexer &&
+ (fi.isWritable() || s_statusMap[relFile].status == FileStatus::Unknown))
+ QtConcurrent::run(&sync, topLevel, QStringList(relFile)).waitForFinished();
+ if (s_statusMap[relFile].status == FileStatus::CheckedOut) {
+ QMessageBox::information(0, tr("ClearCase Checkout"), tr("File is already checked out!"));
+ return true;
+ }
+ bool isHijacked = (s_statusMap[relFile].status & FileStatus::Hijacked);
+ if (!isHijacked)
+ coDialog.hideHijack();
+ if (coDialog.exec() == QDialog::Accepted) {
+ if (!vcsSetActivity(topLevel, title, coDialog.activity()))
+ return false;
+ Core::FileChangeBlocker fcb(absPath);
+ QStringList args(QLatin1String("checkout"));
+ QString comment = coDialog.comment();
+ if (comment.isEmpty())
+ args << QLatin1String("-nc");
+ else
+ args << QLatin1String("-c") << comment;
+ args << QLatin1String("-query");
+ if (coDialog.isReserved())
+ args << QLatin1String("-reserved");
+ if (coDialog.isUnreserved())
+ args << QLatin1String("-unreserved");
+ if (coDialog.isPreserveTime())
+ args << QLatin1String("-ptime");
+ if (isHijacked) {
+ // -usehijack not supported in old cleartool versions...
+ // args << QLatin1String("-usehijack");
+ if (coDialog.isUseHijacked())
+ QFile::rename(absPath, absPath + QLatin1String(".hijack"));
+ vcsUndoHijack(topLevel, relFile, false); // don't keep, we've already kept a copy
+ }
+ args << file;
+ ClearCaseResponse response =
+ runCleartool(topLevel, args, m_settings.timeOutMS(), ShowStdOutInLogWindow |
+ SuppressStdErrInLogWindow | FullySynchronously);
+ if (response.error) {
+ if (response.stdErr.contains(QLatin1String("Versions other than the selected version"))) {
+ VersionSelector selector(file, response.stdErr);
+ if (selector.exec() == QDialog::Accepted) {
+ if (selector.isUpdate())
+ ccUpdate(workingDir, QStringList() << file);
+ else
+ args.removeOne(QLatin1String("-query"));
+ response = runCleartool(topLevel, args, m_settings.timeOutMS(),
+ ShowStdOutInLogWindow | FullySynchronously);
+ }
+ } else {
+ VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance();
+ outputWindow->append(response.stdOut);
+ outputWindow->append(response.stdErr);
+ }
+ }
+
+ if (!response.error && isHijacked && coDialog.isUseHijacked()) { // rename back
+ QFile::remove(absPath);
+ QFile::rename(absPath + QLatin1String(".hijack"), absPath);
+ }
+
+ if ((!response.error || response.stdOut.contains(QLatin1String("already checked out"))) && !m_settings.disableIndexer)
+ setStatus(relFile, FileStatus::CheckedOut);
+ return !response.error;
+ }
+ return true;
+}
+
+bool ClearCasePlugin::vcsSetActivity(const QString &workingDir, const QString &title, const QString &activity)
+{
+ QStringList args;
+ args << QLatin1String("setactivity") << activity;
+ const ClearCaseResponse actResponse =
+ runCleartool(workingDir, args, m_settings.timeOutMS(), ShowStdOutInLogWindow);
+ if (actResponse.error) {
+ QMessageBox::warning(0, title, tr("Set current activity failed: %1").arg(actResponse.message), QMessageBox::Ok);
+ return false;
+ }
+ m_activity = activity;
+ return true;
+}
+
+// files are received using native separators
+bool ClearCasePlugin::vcsCheckIn(const QString &messageFile, const QStringList &files, const QString &activity,
+ bool isIdentical, bool isPreserve, bool replaceActivity)
+{
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << messageFile << files << activity;
+ if (files.isEmpty())
+ return true;
+ const QString title = QString::fromLatin1("Checkin %1").arg(files.join(QLatin1String("; ")));
+ QString workingDir = currentState().topLevel();
+ typedef QSharedPointer<Core::FileChangeBlocker> FCBPointer;
+ replaceActivity &= (activity != QLatin1String(Constants::KEEP_ACTIVITY));
+ if (replaceActivity && !vcsSetActivity(workingDir, title, activity))
+ return false;
+ QFile msgFile(messageFile);
+ msgFile.open(QFile::ReadOnly | QFile::Text);
+ QString message = QString::fromLocal8Bit(msgFile.readAll().trimmed().constData());
+ msgFile.close();
+ QStringList args;
+ args << QLatin1String("checkin");
+ if (message.isEmpty())
+ args << QLatin1String("-nc");
+ else
+ args << QLatin1String("-cfile") << messageFile;
+ if (isIdentical)
+ args << QLatin1String("-identical");
+ if (isPreserve)
+ args << QLatin1String("-ptime");
+ args << files;
+ QList<FCBPointer> blockers;
+ foreach (QString fileName, files) {
+ FCBPointer fcb(new Core::FileChangeBlocker(QFileInfo(workingDir, fileName).canonicalFilePath()));
+ blockers.append(fcb);
+ }
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.longTimeOutMS(), ShowStdOutInLogWindow);
+ QRegExp checkedIn(QLatin1String("Checked in \\\"([^\"]*)\\\""));
+ bool anySucceeded = false;
+ int offset = checkedIn.indexIn(response.stdOut);
+ while (offset != -1) {
+ QString file = checkedIn.cap(1);
+ if (!m_settings.disableIndexer)
+ setStatus(QDir::fromNativeSeparators(file), FileStatus::CheckedIn);
+ clearCaseControl()->emitFilesChanged(files);
+ anySucceeded = true;
+ offset = checkedIn.indexIn(response.stdOut, offset + 12);
+ }
+ return anySucceeded;
+}
+
+bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title, const QStringList &opArgs,
+ const QString &fileName, const QString &file2)
+{
+ const QString file = QDir::toNativeSeparators(fileName);
+ bool noCheckout = false;
+ QVBoxLayout *verticalLayout;
+ ActivitySelector *actSelector;
+ QLabel *commentLabel;
+ QTextEdit *commentEdit;
+ QDialogButtonBox *buttonBox;
+ QDialog fileOpDlg;
+ fileOpDlg.setWindowTitle(title);
+
+ verticalLayout = new QVBoxLayout(&fileOpDlg);
+ actSelector = new ActivitySelector;
+ verticalLayout->addWidget(actSelector);
+
+ commentLabel = new QLabel(tr("Enter &comment:"));
+ verticalLayout->addWidget(commentLabel);
+
+ commentEdit = new QTextEdit;
+ verticalLayout->addWidget(commentEdit);
+
+ buttonBox = new QDialogButtonBox;
+ buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+ verticalLayout->addWidget(buttonBox);
+
+#ifndef QT_NO_SHORTCUT
+ commentLabel->setBuddy(commentEdit);
+#endif // QT_NO_SHORTCUT
+
+ connect(buttonBox, SIGNAL(accepted()), &fileOpDlg, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), &fileOpDlg, SLOT(reject()));
+
+ if (!fileOpDlg.exec())
+ return true;
+ QString comment = commentEdit->toPlainText();
+ if (actSelector->changed())
+ vcsSetActivity(workingDir, fileOpDlg.windowTitle(), actSelector->activity());
+ QString dirName = QDir::toNativeSeparators(QFileInfo(workingDir, fileName).absolutePath());
+ QStringList commentArg;
+ if (comment.isEmpty())
+ commentArg << QLatin1String("-nc");
+ else
+ commentArg << QLatin1String("-c") << comment;
+
+ // check out directory
+ QStringList args;
+ args << QLatin1String("checkout") << commentArg << dirName;
+ const ClearCaseResponse coResponse =
+ runCleartool(workingDir, args, m_settings.timeOutMS(),
+ ShowStdOutInLogWindow | FullySynchronously);
+ if (coResponse.error) {
+ if (coResponse.stdOut.contains(QLatin1String("already checked out")))
+ noCheckout = true;
+ else
+ return false;
+ }
+
+ // do the file operation
+ args.clear();
+ args << opArgs << commentArg << file;
+ if (!file2.isEmpty())
+ args << QDir::toNativeSeparators(file2);
+ const ClearCaseResponse opResponse =
+ runCleartool(workingDir, args, m_settings.timeOutMS(),
+ ShowStdOutInLogWindow | FullySynchronously);
+ if (opResponse.error) {
+ // on failure - undo checkout for the directory
+ if (!noCheckout)
+ vcsUndoCheckOut(workingDir, dirName, false);
+ return false;
+ }
+
+ if (!noCheckout) {
+ // check in the directory
+ args.clear();
+ args << QLatin1String("checkin") << commentArg << dirName;
+ const ClearCaseResponse ciResponse =
+ runCleartool(workingDir, args, m_settings.timeOutMS(),
+ ShowStdOutInLogWindow | FullySynchronously);
+ return !ciResponse.error;
+ }
+ return true;
+}
+
+bool ClearCasePlugin::vcsAdd(const QString &workingDir, const QString &fileName)
+{
+ return ccFileOp(workingDir, tr("ClearCase Add File"),
+ QStringList() << QLatin1String("mkelem") << QLatin1String("-ci"), fileName);
+}
+
+bool ClearCasePlugin::vcsDelete(const QString &workingDir, const QString &fileName)
+{
+ const QString title(tr("ClearCase Remove Element"));
+ if (QMessageBox::warning(0, title, tr("This operation is irreversible! Are you sure?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ return true;
+
+ return ccFileOp(workingDir, tr("ClearCase Remove File"),
+ QStringList() << QLatin1String("rmname") << QLatin1String("-force"), fileName);
+}
+
+bool ClearCasePlugin::vcsMove(const QString &workingDir, const QString &from, const QString &to)
+{
+ return ccFileOp(workingDir, tr("ClearCase Rename File"),
+ QStringList() << QLatin1String("move"), from, to);
+}
+
+bool ClearCasePlugin::vcsCheckout(const QString & /*directory*/, const QByteArray & /*url*/)
+{
+ return false;
+}
+
+QString ClearCasePlugin::vcsGetRepositoryURL(const QString & /*directory*/)
+{
+ return currentState().topLevel();
+}
+
+// ClearCase has "view.dat" file in the root directory it manages.
+bool ClearCasePlugin::managesDirectory(const QString &directory, QString *topLevel /* = 0 */) const
+{
+ QString topLevelFound = findTopLevel(directory);
+ if (topLevel)
+ *topLevel = topLevelFound;
+ return !topLevelFound.isEmpty();
+}
+
+ClearCaseControl *ClearCasePlugin::clearCaseControl() const
+{
+ return static_cast<ClearCaseControl *>(versionControl());
+}
+
+QString ClearCasePlugin::ccGetCurrentActivity() const
+{
+ QStringList args(QLatin1String("lsactivity"));
+ args << QLatin1String("-cact");
+ args << QLatin1String("-fmt") << QLatin1String("%n");
+ return runCleartoolSync(currentState().topLevel(), args);
+}
+
+QList<QStringPair> ClearCasePlugin::ccGetActivities() const
+{
+ QList<QStringPair> result;
+ // Maintain latest deliver and rebase activities only
+ QStringPair rebaseAct;
+ QStringPair deliverAct;
+ QStringList args(QLatin1String("lsactivity"));
+ // Retrieve all activities
+ args << QLatin1String("-fmt") << QLatin1String("%n\\t%[headline]p\\n");
+ const QString response = runCleartoolSync(currentState().topLevel(), args);
+ QStringList acts = response.split(QLatin1Char('\n'), QString::SkipEmptyParts);
+ foreach (QString activity, acts) {
+ QStringList act = activity.split(QLatin1Char('\t'));
+ // exclude deliver/rebase activities (and include only the latest ones)
+ QRegExp deliverRebase(QLatin1String("deliver\\.|rebase\\."));
+ if (act.size() >= 2)
+ {
+ QString actName = act.at(0);
+ if (actName.indexOf(deliverRebase) == -1)
+ result.append(QStringPair(actName, act.at(1).trimmed()));
+ else if ((actName.at(0) == QLatin1Char('r')) && (actName > rebaseAct.first))
+ rebaseAct = QStringPair(actName, act.at(1));
+ else if ((actName.at(0) == QLatin1Char('d')) && (actName > deliverAct.first))
+ deliverAct = QStringPair(actName, act.at(1));
+ }
+ }
+ if (!rebaseAct.first.isEmpty())
+ result.append(rebaseAct);
+ if (!deliverAct.first.isEmpty())
+ result.append(deliverAct);
+ qSort(result);
+ return result;
+}
+
+void ClearCasePlugin::refreshActivities()
+{
+ QMutexLocker locker(activityMutex);
+ m_activity = ccGetCurrentActivity();
+ m_activities = ccGetActivities();
+}
+
+QList<QStringPair> ClearCasePlugin::activities(int *current) const
+{
+ QList<QStringPair> activitiesList;
+ QString curActivity;
+ const VcsBase::VcsBasePluginState state = currentState();
+ if (state.topLevel() == state.currentProjectTopLevel()) {
+ QMutexLocker locker(activityMutex);
+ activitiesList = m_activities;
+ curActivity = m_activity;
+ } else {
+ activitiesList = ccGetActivities();
+ curActivity = ccGetCurrentActivity();
+ }
+ if (current) {
+ int nActivities = activitiesList.size();
+ *current = -1;
+ for (int i = 0; i < nActivities && (*current == -1); ++i) {
+ if (activitiesList[i].first == curActivity)
+ *current = i;
+ }
+ }
+ return activitiesList;
+}
+
+bool ClearCasePlugin::newActivity()
+{
+ QString workingDir = currentState().topLevel();
+ QStringList args;
+ args << QLatin1String("mkactivity") << QLatin1String("-f");
+ if (!m_settings.autoAssignActivityName) {
+ QString headline = QInputDialog::getText(0, tr("Activity Headline"), tr("Enter activity headline"));
+ if (headline.isEmpty())
+ return false;
+ args << QLatin1String("-headline") << headline;
+ }
+
+ const ClearCaseResponse response =
+ runCleartool(workingDir, args, m_settings.timeOutMS(), 0);
+
+ if (!response.error)
+ refreshActivities();
+ return (!response.error);
+}
+
+QString ClearCasePlugin::ccGetView(const QString &workingDir, bool *isDynamic) const
+{
+ QStringList args(QLatin1String("lsview"));
+ args << QLatin1String("-cview");
+ QString data = runCleartoolSync(workingDir, args);
+ if (data.isEmpty()) {
+ if (isDynamic)
+ *isDynamic = false;
+ return QString();
+ }
+ if (isDynamic)
+ *isDynamic = !data.isEmpty() && (data.at(0) == QLatin1Char('*'));
+ return data.mid(2, data.indexOf(QLatin1Char(' '), 2) - 2);
+}
+
+void ClearCasePlugin::updateStreamAndView()
+{
+ QStringList args(QLatin1String("lsstream"));
+ args << QLatin1String("-fmt") << QLatin1String("%n\\t%[def_deliver_tgt]Xp");
+ const QString sresponse = runCleartoolSync(m_topLevel, args);
+ int tabPos = sresponse.indexOf(QLatin1Char('\t'));
+ m_stream = sresponse.left(tabPos);
+ QRegExp intStreamExp(QLatin1String("stream:([^@]*)"));
+ if (intStreamExp.indexIn(sresponse.mid(tabPos + 1)) != -1)
+ m_intStream = intStreamExp.cap(1);
+ m_view = ccGetView(m_topLevel);
+ m_updateViewAction->setParameter(m_view);
+}
+
+void ClearCasePlugin::projectChanged(ProjectExplorer::Project *project)
+{
+ if (m_view == ccGetView(m_topLevel)) // New project on same view as old project
+ return;
+ m_view.clear();
+ m_stream.clear();
+ m_intStream.clear();
+ disconnect(Core::ICore::mainWindow(), SIGNAL(windowActivated()), this, SLOT(syncSlot()));
+ Core::ICore::progressManager()->cancelTasks(QLatin1String(ClearCase::Constants::TASK_INDEX));
+ if (project) {
+ QString projDir = project->projectDirectory();
+ QString topLevel = findTopLevel(projDir);
+ m_topLevel = topLevel;
+ if (topLevel.isEmpty())
+ return;
+ connect(Core::ICore::mainWindow(), SIGNAL(windowActivated()), this, SLOT(syncSlot()));
+ updateStreamAndView();
+ if (m_view.isEmpty())
+ return;
+ Core::EditorManager *editorManager = Core::ICore::editorManager();
+ editorManager->setWindowTitleAddition(editorManager->windowTitleAddition() + QLatin1String(" - ") + m_view);
+ updateIndex();
+ }
+ if ( ClearCase::Constants::debug )
+ qDebug() << "stream: " << m_stream << "; intStream: " << m_intStream << "view: " << m_view;
+}
+
+void ClearCasePlugin::tasksFinished(const QString &type)
+{
+ if (type == QLatin1String(ClearCase::Constants::TASK_INDEX))
+ m_checkInAllAction->setEnabled(true);
+}
+
+void ClearCasePlugin::updateIndex()
+{
+ QTC_ASSERT(currentState().hasTopLevel(), return);
+ Core::ICore::progressManager()->cancelTasks(QLatin1String(ClearCase::Constants::TASK_INDEX));
+ ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::currentProject();
+ if (!project)
+ return;
+ m_checkInAllAction->setEnabled(false);
+ s_statusMap.clear();
+ QFuture<void> result = QtConcurrent::run(&sync, currentState().topLevel(),
+ project->files(ProjectExplorer::Project::ExcludeGeneratedFiles));
+ if (!m_settings.disableIndexer)
+ Core::ICore::progressManager()->addTask(result, tr("CC Indexing"),
+ QLatin1String(ClearCase::Constants::TASK_INDEX));
+}
+
+/*! retrieve a \a file (usually of the form path\to\filename.cpp@@\main\ver)
+ * from cc and save it to a temporary location which is returned
+ */
+QString ClearCasePlugin::getFile(const QString &nativeFile, const QString &prefix)
+{
+ QString tempFile;
+ QDir tempDir = QDir::temp();
+ tempDir.mkdir(QLatin1String("ccdiff"));
+ tempDir.cd(QLatin1String("ccdiff"));
+ int atatpos = nativeFile.indexOf(QLatin1String("@@"));
+ QString file = QDir::fromNativeSeparators(nativeFile.left(atatpos));
+ if (prefix.isEmpty()) {
+ tempFile = tempDir.absoluteFilePath(QString::number(QUuid::createUuid().data1, 16));
+ } else {
+ tempDir.mkpath(prefix);
+ tempDir.cd(prefix);
+ int slash = file.lastIndexOf(QLatin1Char('/'));
+ if (slash != -1)
+ tempDir.mkpath(file.left(slash));
+ tempFile = tempDir.absoluteFilePath(file);
+ }
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << nativeFile;
+ if ((atatpos != -1) && (nativeFile.indexOf(QLatin1String("CHECKEDOUT"), atatpos) != -1)) {
+ bool res = QFile::copy(QDir(m_topLevel).absoluteFilePath(file), tempFile);
+ return res ? tempFile : QString();
+ }
+ QStringList args(QLatin1String("get"));
+ args << QLatin1String("-to") << tempFile << nativeFile;
+ const ClearCaseResponse response =
+ runCleartool(m_topLevel, args, m_settings.timeOutMS(), SilentRun);
+ if (response.error)
+ return QString();
+ QFile::setPermissions(tempFile, QFile::ReadOwner | QFile::ReadUser |
+ QFile::WriteOwner | QFile::WriteUser);
+ return tempFile;
+}
+
+// runs external (GNU) diff, and returns the stdout result
+QString ClearCasePlugin::diffExternal(QString file1, QString file2, bool keep)
+{
+ QTextCodec *codec = VcsBase::VcsBaseEditorWidget::getCodec(file1);
+
+ // if file2 is empty, we should compare to predecessor
+ if (file2.isEmpty()) {
+ QString predVer = ccGetPredecessor(file1);
+ return (predVer.isEmpty() ? QString() : diffExternal(predVer, file1, keep));
+ }
+
+ file1 = QDir::toNativeSeparators(file1);
+ file2 = QDir::toNativeSeparators(file2);
+ QString tempFile1, tempFile2;
+ QString prefix = m_diffPrefix;
+ if (!prefix.isEmpty())
+ prefix.append(QLatin1Char('/'));
+
+ if (file1.contains(QLatin1String("@@")))
+ tempFile1 = getFile(file1, prefix + QLatin1String("old"));
+ if (file2.contains(QLatin1String("@@")))
+ tempFile2 = getFile(file2, prefix + QLatin1String("new"));
+ QStringList args;
+ if (!tempFile1.isEmpty()) {
+ args << QLatin1String("-L") << file1;
+ args << tempFile1;
+ } else {
+ args << file1;
+ }
+ if (!tempFile2.isEmpty()) {
+ args << QLatin1String("-L") << file2;
+ args << tempFile2;
+ } else {
+ args << file2;
+ }
+ const QString diffResponse =
+ runExtDiff(m_topLevel, args, m_settings.timeOutMS(), codec);
+ if (!keep && !tempFile1.isEmpty()) {
+ QFile::remove(tempFile1);
+ QFileInfo(tempFile1).dir().rmpath(QLatin1String("."));
+ }
+ if (!keep && !tempFile2.isEmpty()) {
+ QFile::remove(tempFile2);
+ QFileInfo(tempFile2).dir().rmpath(QLatin1String("."));
+ }
+ if (diffResponse.isEmpty())
+ return QLatin1String("Files are identical");
+ QString header = QString::fromLatin1("diff %1 old/%2 new/%2\n")
+ .arg(m_settings.diffArgs)
+ .arg(QDir::fromNativeSeparators(file2.left(file2.indexOf(QLatin1String("@@")))));
+ return header + diffResponse;
+}
+
+// runs builtin diff (either graphical or diff_format)
+void ClearCasePlugin::diffGraphical(const QString &file1, const QString &file2)
+{
+ QStringList args;
+ bool pred = file2.isEmpty();
+ args.push_back(QLatin1String("diff"));
+ if (pred)
+ args.push_back(QLatin1String("-predecessor"));
+ args.push_back(QLatin1String("-graphical"));
+ args << file1;
+ if (!pred)
+ args << file2;
+ QProcess::startDetached(m_settings.ccCommand, args, m_topLevel);
+}
+
+QString ClearCasePlugin::runExtDiff(const QString &workingDir,
+ const QStringList &arguments,
+ int timeOut,
+ QTextCodec *outputCodec)
+{
+ const QString executable(QLatin1String("diff"));
+ QStringList args(m_settings.diffArgs.split(QLatin1Char(' '), QString::SkipEmptyParts));
+ args << arguments;
+
+ QProcess process;
+ process.setWorkingDirectory(workingDir);
+ process.start(executable, args);
+ if (!process.waitForFinished(timeOut))
+ return QString();
+ QByteArray ba = process.readAll();
+ return outputCodec ? outputCodec->toUnicode(ba) :
+ QString::fromLocal8Bit(ba.constData(), ba.size());
+}
+
+void ClearCasePlugin::syncSlot()
+{
+ VcsBase::VcsBasePluginState state = currentState();
+ if (!state.hasProject() || !state.hasTopLevel())
+ return;
+ QString topLevel = state.topLevel();
+ if (topLevel != state.currentProjectTopLevel())
+ return;
+ QtConcurrent::run(&sync, topLevel, QStringList());
+}
+
+void ClearCasePlugin::closing()
+{
+ // prevent syncSlot from being called on shutdown
+ Core::ICore::progressManager()->cancelTasks(QLatin1String(ClearCase::Constants::TASK_INDEX));
+ disconnect(Core::ICore::mainWindow(), SIGNAL(windowActivated()), this, SLOT(syncSlot()));
+}
+
+void ClearCasePlugin::sync(QFutureInterface<void> &future, QString topLevel, QStringList files)
+{
+ ClearCasePlugin *plugin = ClearCasePlugin::instance();
+
+ ClearCaseSettings settings = plugin->settings();
+ QString program = settings.ccCommand;
+ if (program.isEmpty())
+ return;
+ int total = files.size();
+ bool hot = (total < 10);
+ int processed = 0;
+ QString view = plugin->currentView();
+ if (view.isEmpty())
+ plugin->updateStreamAndView();
+ if (!hot)
+ total = settings.totalFiles.value(view, total);
+
+ // refresh activities list
+ plugin->refreshActivities();
+
+ if (settings.disableIndexer)
+ return;
+ QStringList vobs;
+ if (!settings.indexOnlyVOBs.isEmpty())
+ vobs = settings.indexOnlyVOBs.split(QLatin1Char(','));
+ else
+ vobs = plugin->ccGetActiveVobs();
+ QDir topLevelDir(topLevel);
+ QStringList args(QLatin1String("ls"));
+ if (hot) {
+ // find all files whose permissions changed OR hijacked files
+ // (might have become checked out)
+ foreach (const QString &file, s_statusMap.keys()) {
+ bool permChanged =
+ s_statusMap[file].permissions != QFileInfo(topLevel, file).permissions();
+ if (permChanged || s_statusMap[file].status == FileStatus::Hijacked) {
+ files.append(file);
+ s_statusMap[file].status = FileStatus::Unknown;
+ ++total;
+ }
+ }
+ args << files;
+ } else {
+ foreach (const QString &file, files)
+ plugin->setStatus(topLevelDir.relativeFilePath(file), FileStatus::Unknown, false);
+ args << QLatin1String("-recurse");
+ args << vobs;
+ }
+
+ // adding 1 for initial sync in which total is not accurate, to prevent finishing
+ // (we don't want it to become green)
+ future.setProgressRange(0, total + 1);
+ QProcess process;
+ process.setWorkingDirectory(topLevel);
+ process.start(program, args);
+ if (!process.waitForStarted())
+ return;
+ QString buffer;
+ while (process.waitForReadyRead() && !future.isCanceled()) {
+ while (process.state() == QProcess::Running &&
+ process.bytesAvailable() && !future.isCanceled())
+ {
+ QString line = QString::fromLocal8Bit(process.readLine().constData());
+ buffer += line;
+ if (buffer.endsWith(QLatin1Char('\n')) || process.atEnd()) {
+ int atatpos = buffer.indexOf(QLatin1String("@@"));
+ if (atatpos != -1) { // probably managed file
+ // find first whitespace. anything before that is not interesting
+ int wspos = buffer.indexOf(QRegExp(QLatin1String("\\s")));
+ const QString file = QDir::fromNativeSeparators(buffer.left(atatpos));
+ QString ccState;
+ QRegExp reState(QLatin1String("^\\s*\\[[^\\]]*\\]")); // [hijacked]; [loaded but missing]
+ if (reState.indexIn(buffer, wspos + 1, QRegExp::CaretAtOffset) != -1) {
+ ccState = reState.cap();
+ if (ccState.indexOf(QLatin1String("hijacked")) != -1)
+ plugin->setStatus(file, FileStatus::Hijacked, true);
+ else if (ccState.indexOf(QLatin1String("loaded but missing")) != -1)
+ plugin->setStatus(file, FileStatus::Missing, false);
+ }
+ else if (buffer.lastIndexOf(QLatin1String("CHECKEDOUT"), wspos) != -1)
+ plugin->setStatus(file, FileStatus::CheckedOut, true);
+ // don't care about checked-in files not listed in project
+ else if (s_statusMap.contains(file))
+ plugin->setStatus(file, FileStatus::CheckedIn, false);
+ }
+ buffer.clear();
+ future.setProgressValue(qMin(total, ++processed));
+ }
+ }
+ }
+
+ if (!future.isCanceled()) {
+ foreach (const QString &file, files) {
+ QString relFile = topLevelDir.relativeFilePath(file);
+ if (s_statusMap[relFile].status == FileStatus::Unknown)
+ plugin->setStatus(relFile, FileStatus::NotManaged, false);
+ }
+ future.setProgressValue(total + 1);
+ if (!hot) {
+ settings.totalFiles[view] = processed;
+ plugin->setSettings(settings);
+ }
+ }
+ if (process.state() == QProcess::Running)
+ process.kill();
+ process.waitForFinished();
+}
+
+} // namespace ClearCase
+} // namespace Internal
+
+Q_EXPORT_PLUGIN(ClearCase::Internal::ClearCasePlugin)
diff --git a/src/plugins/clearcase/clearcaseplugin.h b/src/plugins/clearcase/clearcaseplugin.h
new file mode 100644
index 0000000000..3e72f8f185
--- /dev/null
+++ b/src/plugins/clearcase/clearcaseplugin.h
@@ -0,0 +1,270 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASEPLUGIN_H
+#define CLEARCASEPLUGIN_H
+
+#include "clearcasesettings.h"
+
+#include <vcsbase/vcsbaseplugin.h>
+#include <QFile>
+#include <QPair>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QComboBox;
+class QDir;
+template <typename T>
+class QFutureInterface;
+class QMutex;
+typedef QPair<QString, QString> QStringPair;
+class QTextCodec;
+QT_END_NAMESPACE
+
+namespace Core {
+ class IVersionControl;
+ class IEditor;
+}
+namespace Utils {
+ class ParameterAction;
+}
+
+namespace VcsBase {
+ class VcsBaseSubmitEditor;
+}
+
+namespace Locator {
+ class CommandLocator;
+}
+
+namespace ProjectExplorer {
+ class Project;
+}
+
+namespace ClearCase {
+namespace Internal {
+
+class ClearCaseSubmitEditor;
+class ClearCaseControl;
+
+class ClearCaseResponse
+{
+public:
+ ClearCaseResponse() : error(false) {}
+ bool error;
+ QString stdOut;
+ QString stdErr;
+ QString message;
+};
+
+struct FileStatus
+{
+ enum Status
+ {
+ Unknown = 0x0f,
+ CheckedIn = 0x01,
+ CheckedOut = 0x02,
+ Hijacked = 0x04,
+ NotManaged = 0x08,
+ Missing = 0x10
+ } status;
+
+ QFile::Permissions permissions;
+
+ FileStatus(Status _status = Unknown, QFile::Permissions perm = 0)
+ : status(_status), permissions(perm)
+ {}
+};
+
+typedef QHash<QString, FileStatus> StatusMap;
+
+class ClearCasePlugin : public VcsBase::VcsBasePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClearCase.json")
+
+ static const unsigned SilentRun =
+ SuppressStdErrInLogWindow |
+ SuppressFailMessageInLogWindow |
+ SuppressCommandLogging |
+ FullySynchronously;
+
+public:
+ ClearCasePlugin();
+ ~ClearCasePlugin();
+
+ bool initialize(const QStringList &arguments, QString *error_message);
+
+ ClearCaseSubmitEditor *openClearCaseSubmitEditor(const QString &fileName);
+
+ const ClearCaseSettings &settings() const;
+ void setSettings(const ClearCaseSettings &s);
+
+ // IVersionControl
+ bool vcsOpen(const QString &workingDir, const QString &fileName);
+ bool vcsAdd(const QString &workingDir, const QString &fileName);
+ bool vcsDelete(const QString &workingDir, const QString &fileName);
+ bool vcsCheckIn(const QString &workingDir, const QStringList &files, const QString &activity,
+ bool isIdentical, bool isPreserve, bool replaceActivity);
+ bool vcsUndoCheckOut(const QString &workingDir, const QString &fileName, bool keep);
+ bool vcsUndoHijack(const QString &workingDir, const QString &fileName, bool keep);
+ bool vcsMove(const QString &workingDir, const QString &from, const QString &to);
+ bool vcsSetActivity(const QString &workingDir, const QString &title, const QString &activity);
+ bool managesDirectory(const QString &directory, QString *topLevel = 0) const;
+ bool vcsCheckout(const QString &directory, const QByteArray &url);
+ QString vcsGetRepositoryURL(const QString &directory);
+
+ static ClearCasePlugin *instance();
+
+ QString ccGetCurrentActivity() const;
+ QList<QStringPair> activities(int *current = 0) const;
+ QString ccGetPredecessor(const QString &version) const;
+ QStringList ccGetActiveVobs() const;
+ bool ccFileOp(const QString &workingDir, const QString &title, const QStringList &args,
+ const QString &fileName, const QString &file2 = QString());
+ FileStatus vcsStatus(const QString &file) const;
+ QString currentView() const { return m_view; }
+
+public slots:
+ void vcsAnnotate(const QString &workingDir, const QString &file,
+ const QString &revision = QString(), int lineNumber = -1) const;
+ bool newActivity();
+
+private slots:
+ void checkOutCurrentFile();
+ void addCurrentFile();
+ void undoCheckOutCurrent();
+ void undoHijackCurrent();
+ void diffActivity();
+ void diffCurrentFile();
+ void startCheckInAll();
+ void startCheckInActivity();
+ void startCheckInCurrentFile();
+ void historyCurrentFile();
+ void annotateCurrentFile();
+ void annotateVersion(const QString &file, const QString &revision, int lineNumber);
+ void describe(const QString &source, const QString &changeNr);
+ void viewStatus();
+ void checkInSelected();
+ void diffCheckInFiles(const QStringList &);
+ void updateIndex();
+ void updateView();
+ void projectChanged(ProjectExplorer::Project *project);
+ void tasksFinished(const QString &type);
+ void syncSlot();
+ void closing();
+
+protected:
+ void updateActions(VcsBase::VcsBasePlugin::ActionState);
+ bool submitEditorAboutToClose(VcsBase::VcsBaseSubmitEditor *submitEditor);
+ QString ccGet(const QString &workingDir, const QString &file, const QString &prefix = QString());
+ void refreshActivities();
+ QList<QStringPair> ccGetActivities() const;
+
+private:
+ inline bool isCheckInEditorOpen() const;
+ QString findTopLevel(const QString &directory) const;
+ Core::IEditor * showOutputInEditor(const QString& title, const QString &output,
+ int editorType, const QString &source,
+ QTextCodec *codec) const;
+ QString runCleartoolSync(const QString &workingDir, const QStringList &arguments) const;
+ ClearCaseResponse runCleartool(const QString &workingDir,
+ const QStringList &arguments, int timeOut,
+ unsigned flags, QTextCodec *outputCodec = 0) const;
+ static void sync(QFutureInterface<void> &future, QString topLevel, QStringList files);
+
+ void history(const QString &workingDir,
+ const QStringList &file = QStringList(),
+ bool enableAnnotationContextMenu = false);
+ QString ccGetFileVersion(const QString &workingDir, const QString &file) const;
+ void ccUpdate(const QString &workingDir, const QStringList &relativePaths = QStringList());
+ void ccDiffWithPred(const QStringList &files);
+ void startCheckIn(const QString &workingDir, const QStringList &files = QStringList());
+ void cleanCheckInMessageFile();
+ inline ClearCaseControl *clearCaseControl() const;
+ QString ccGetFileActivity(const QString &workingDir, const QString &file);
+ void setStatus(const QString &file, FileStatus::Status status, bool update = true);
+ QStringList ccGetActivityVersions(const QString &workingDir, const QString &activity);
+ void updateStatusActions();
+ void diffGraphical(const QString &file1, const QString &file2 = QString());
+ QString diffExternal(QString file1, QString file2 = QString(), bool keep = false);
+ QString getFile(const QString &nativeFile, const QString &prefix);
+ static void rmdir(const QString &path);
+ QString runExtDiff(const QString &workingDir, const QStringList &arguments,
+ int timeOut, QTextCodec *outputCodec = 0);
+ QString ccGetView(const QString &workingDir, bool *isDynamic = 0) const;
+ void updateStreamAndView();
+
+ ClearCaseSettings m_settings;
+
+ static StatusMap s_statusMap;
+ QString m_checkInMessageFileName;
+ QString m_topLevel;
+ QString m_stream;
+ QString m_view;
+ QString m_intStream;
+ QString m_activity;
+ QString m_diffPrefix;
+
+ Locator::CommandLocator *m_commandLocator;
+ Utils::ParameterAction *m_checkOutAction;
+ Utils::ParameterAction *m_checkInCurrentAction;
+ Utils::ParameterAction *m_undoCheckOutAction;
+ Utils::ParameterAction *m_undoHijackAction;
+ Utils::ParameterAction *m_diffCurrentAction;
+ Utils::ParameterAction *m_historyCurrentAction;
+ Utils::ParameterAction *m_annotateCurrentAction;
+ Utils::ParameterAction *m_addFileAction;
+ QAction *m_diffActivityAction;
+ QAction *m_updateIndexAction;
+ Utils::ParameterAction *m_updateViewAction;
+ Utils::ParameterAction *m_checkInActivityAction;
+ QAction *m_checkInAllAction;
+ QAction *m_statusAction;
+
+ QAction *m_checkInSelectedAction;
+ QAction *m_checkInDiffAction;
+ QAction *m_submitUndoAction;
+ QAction *m_submitRedoAction;
+ QAction *m_menuAction;
+ bool m_submitActionTriggered;
+ QMutex *activityMutex;
+ QList<QStringPair> m_activities;
+
+ static ClearCasePlugin *m_clearcasePluginInstance;
+};
+
+} // namespace ClearCase
+} // namespace Internal
+
+#endif // CLEARCASEPLUGIN_H
diff --git a/src/plugins/clearcase/clearcasesettings.cpp b/src/plugins/clearcase/clearcasesettings.cpp
new file mode 100644
index 0000000000..a9135b4308
--- /dev/null
+++ b/src/plugins/clearcase/clearcasesettings.cpp
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "clearcasesettings.h"
+
+#include <utils/environment.h>
+
+#include <QSettings>
+
+static const char groupC[] = "ClearCase";
+static const char commandKeyC[] = "Command";
+
+static const char historyCountKeyC[] = "HistoryCount";
+static const char timeOutKeyC[] = "TimeOut";
+static const char autoCheckOutKeyC[] = "AutoCheckOut";
+static const char diffTypeKeyC[] = "DiffType";
+static const char extDiffCommandKeyC[] = "ExternalDiffCommand";
+static const char diffArgsKeyC[] = "DiffArgs";
+static const char autoAssignActivityKeyC[] = "AutoAssignActivityName";
+static const char promptToCheckInKeyC[] = "PromptToCheckIn";
+static const char disableIndexerKeyC[] = "DisableIndexer";
+static const char totalFilesKeyC[] = "TotalFiles";
+static const char indexOnlyVOBsC[] = "IndexOnlyVOBs";
+
+static const char defaultDiffArgs[] = "-ubp";
+
+enum { defaultTimeOutS = 30, defaultHistoryCount = 50 };
+
+static QString defaultCommand(const char *command)
+{
+ QString rc = QLatin1String(command);
+ QString expanded = Utils::Environment::systemEnvironment().searchInPath(rc);
+ return expanded.isEmpty() ? rc : expanded;
+}
+
+using namespace ClearCase::Internal;
+
+ClearCaseSettings::ClearCaseSettings() :
+ ccCommand(defaultCommand("cleartool")),
+ historyCount(defaultHistoryCount),
+ timeOutS(defaultTimeOutS),
+ diffType(GraphicalDiff),
+ diffArgs(QLatin1String(defaultDiffArgs)),
+ autoAssignActivityName(true),
+ autoCheckOut(true),
+ promptToCheckIn(false),
+ disableIndexer(false)
+{
+}
+
+void ClearCaseSettings::fromSettings(QSettings *settings)
+{
+ settings->beginGroup(QLatin1String(groupC));
+ ccCommand = settings->value(QLatin1String(commandKeyC), defaultCommand("cleartool")).toString();
+ timeOutS = settings->value(QLatin1String(timeOutKeyC), defaultTimeOutS).toInt();
+ autoCheckOut = settings->value(QLatin1String(autoCheckOutKeyC), false).toBool();
+ QString sDiffType = settings->value(QLatin1String(diffTypeKeyC), QLatin1String("Graphical")).toString();
+ switch (sDiffType[0].toUpper().toLatin1()) {
+ case 'G': diffType = GraphicalDiff; break;
+ case 'E': diffType = ExternalDiff; break;
+ }
+
+ diffArgs = settings->value(QLatin1String(diffArgsKeyC), QLatin1String(defaultDiffArgs)).toString();
+ autoAssignActivityName = settings->value(QLatin1String(autoAssignActivityKeyC), true).toBool();
+ historyCount = settings->value(QLatin1String(historyCountKeyC), int(defaultHistoryCount)).toInt();
+ promptToCheckIn = settings->value(QLatin1String(promptToCheckInKeyC), false).toBool();
+ disableIndexer = settings->value(QLatin1String(disableIndexerKeyC), false).toBool();
+ indexOnlyVOBs = settings->value(QLatin1String(indexOnlyVOBsC), QString()).toString();
+ settings->beginGroup(QLatin1String(totalFilesKeyC));
+ foreach (const QString &view, settings->childKeys())
+ totalFiles[view] = settings->value(view).toInt();
+ settings->endGroup();
+ settings->endGroup();
+}
+
+void ClearCaseSettings::toSettings(QSettings *settings) const
+{
+ settings->beginGroup(QLatin1String(groupC));
+ settings->setValue(QLatin1String(commandKeyC), ccCommand);
+ settings->setValue(QLatin1String(autoCheckOutKeyC), autoCheckOut);
+ settings->setValue(QLatin1String(timeOutKeyC), timeOutS);
+ QString sDiffType;
+ switch (diffType) {
+ case ExternalDiff: sDiffType = QLatin1String("External"); break;
+ default: sDiffType = QLatin1String("Graphical"); break;
+ }
+
+ settings->setValue(QLatin1String(diffArgsKeyC), diffArgs);
+ settings->setValue(QLatin1String(diffTypeKeyC), sDiffType);
+ settings->setValue(QLatin1String(autoAssignActivityKeyC), autoAssignActivityName);
+ settings->setValue(QLatin1String(historyCountKeyC), historyCount);
+ settings->setValue(QLatin1String(promptToCheckInKeyC), promptToCheckIn);
+ settings->setValue(QLatin1String(disableIndexerKeyC), disableIndexer);
+ settings->setValue(QLatin1String(indexOnlyVOBsC), indexOnlyVOBs);
+ settings->beginGroup(QLatin1String(totalFilesKeyC));
+ foreach (const QString &view, totalFiles.keys())
+ settings->setValue(view, totalFiles[view]);
+ settings->endGroup();
+ settings->endGroup();
+}
+
+bool ClearCaseSettings::equals(const ClearCaseSettings &s) const
+{
+ return ccCommand == s.ccCommand
+ && historyCount == s.historyCount
+ && timeOutS == s.timeOutS
+ && autoCheckOut == s.autoCheckOut
+ && diffType == s.diffType
+ && diffArgs == s.diffArgs
+ && autoAssignActivityName == s.autoAssignActivityName
+ && promptToCheckIn == s.promptToCheckIn
+ && disableIndexer == s.disableIndexer
+ && indexOnlyVOBs == s.indexOnlyVOBs
+ && totalFiles == s.totalFiles;
+}
diff --git a/src/plugins/clearcase/clearcasesettings.h b/src/plugins/clearcase/clearcasesettings.h
new file mode 100644
index 0000000000..230963b4b3
--- /dev/null
+++ b/src/plugins/clearcase/clearcasesettings.h
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASESETTINGS_H
+#define CLEARCASESETTINGS_H
+
+#include <QHash>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace ClearCase {
+namespace Internal {
+
+enum DiffType
+{
+ GraphicalDiff,
+ ExternalDiff
+};
+
+class ClearCaseSettings
+{
+public:
+ ClearCaseSettings();
+
+ void fromSettings(QSettings *);
+ void toSettings(QSettings *) const;
+
+ inline int timeOutMS() const { return timeOutS * 1000; }
+ inline int longTimeOutMS() const { return timeOutS * 10000; }
+
+ bool equals(const ClearCaseSettings &s) const;
+
+ QString ccCommand;
+ int historyCount;
+ int timeOutS;
+ DiffType diffType;
+ QString diffArgs;
+ bool autoAssignActivityName;
+ bool autoCheckOut;
+ bool promptToCheckIn;
+ bool disableIndexer;
+ QString indexOnlyVOBs;
+ QHash<QString, int> totalFiles;
+};
+
+inline bool operator==(const ClearCaseSettings &p1, const ClearCaseSettings &p2)
+ { return p1.equals(p2); }
+inline bool operator!=(const ClearCaseSettings &p1, const ClearCaseSettings &p2)
+ { return !p1.equals(p2); }
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // CLEARCASESETTINGS_H
diff --git a/src/plugins/clearcase/clearcasesubmiteditor.cpp b/src/plugins/clearcase/clearcasesubmiteditor.cpp
new file mode 100644
index 0000000000..00357a2a39
--- /dev/null
+++ b/src/plugins/clearcase/clearcasesubmiteditor.cpp
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "clearcasesubmiteditor.h"
+#include "clearcasesubmiteditorwidget.h"
+
+#include <utils/submiteditorwidget.h>
+#include <vcsbase/submitfilemodel.h>
+
+using namespace ClearCase::Internal;
+
+ClearCaseSubmitEditor::ClearCaseSubmitEditor(const VcsBase::VcsBaseSubmitEditorParameters *parameters,
+ QWidget *parentWidget) :
+ VcsBase::VcsBaseSubmitEditor(parameters, new ClearCaseSubmitEditorWidget(parentWidget))
+{
+ setDisplayName(tr("ClearCase Check In"));
+}
+
+ClearCaseSubmitEditorWidget *ClearCaseSubmitEditor::submitEditorWidget()
+{
+ return static_cast<ClearCaseSubmitEditorWidget *>(widget());
+}
+
+void ClearCaseSubmitEditor::setStatusList(const QStringList &statusOutput)
+{
+ typedef QStringList::const_iterator ConstIterator;
+ VcsBase::SubmitFileModel *model = new VcsBase::SubmitFileModel(this);
+
+ const ConstIterator cend = statusOutput.constEnd();
+ for (ConstIterator it = statusOutput.constBegin(); it != cend; ++it)
+ model->addFile(*it, QLatin1String("C"), true);
+ setFileModel(model, checkScriptWorkingDirectory());
+ if (statusOutput.count() > 1)
+ submitEditorWidget()->addKeep();
+}
+
+QByteArray ClearCaseSubmitEditor::fileContents() const
+{
+ return VcsBase::VcsBaseSubmitEditor::fileContents().trimmed();
+}
diff --git a/src/plugins/clearcase/clearcasesubmiteditor.h b/src/plugins/clearcase/clearcasesubmiteditor.h
new file mode 100644
index 0000000000..d5ad3f3aea
--- /dev/null
+++ b/src/plugins/clearcase/clearcasesubmiteditor.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASESUBMITEDITOR_H
+#define CLEARCASESUBMITEDITOR_H
+
+#include <QPair>
+#include <QStringList>
+
+#include <vcsbase/vcsbasesubmiteditor.h>
+
+namespace ClearCase {
+namespace Internal {
+
+class ClearCaseSubmitEditorWidget;
+
+class ClearCaseSubmitEditor : public VcsBase::VcsBaseSubmitEditor
+{
+ Q_OBJECT
+public:
+ explicit ClearCaseSubmitEditor(const VcsBase::VcsBaseSubmitEditorParameters *parameters,
+ QWidget *parentWidget = 0);
+
+ static QString fileFromStatusLine(const QString &statusLine);
+
+ void setStatusList(const QStringList &statusOutput);
+ ClearCaseSubmitEditorWidget *submitEditorWidget();
+
+protected:
+ virtual QByteArray fileContents() const;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // CLEARCASESUBMITEDITOR_H
diff --git a/src/plugins/clearcase/clearcasesubmiteditorwidget.cpp b/src/plugins/clearcase/clearcasesubmiteditorwidget.cpp
new file mode 100644
index 0000000000..b55e20f5fc
--- /dev/null
+++ b/src/plugins/clearcase/clearcasesubmiteditorwidget.cpp
@@ -0,0 +1,101 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "activityselector.h"
+#include "clearcasesubmiteditorwidget.h"
+
+#include <vcsbase/submitfilemodel.h>
+
+#include <QCheckBox>
+#include <QFrame>
+#include <QVBoxLayout>
+
+using namespace ClearCase::Internal;
+
+ClearCaseSubmitEditorWidget::ClearCaseSubmitEditorWidget(QWidget *parent) :
+ Utils::SubmitEditorWidget(parent)
+{
+ setDescriptionMandatory(false);
+ QWidget *checkInWidget = new QWidget(this);
+
+ QVBoxLayout *verticalLayout = new QVBoxLayout(checkInWidget);
+ m_actSelector = new ActivitySelector;
+ verticalLayout->addWidget(m_actSelector);
+
+ QFrame *line = new QFrame;
+ line->setFrameShape(QFrame::HLine);
+ line->setFrameShadow(QFrame::Sunken);
+ verticalLayout->addWidget(line);
+
+ m_chkIdentical = new QCheckBox(tr("Chec&k in even if identical to previous version"));
+ verticalLayout->addWidget(m_chkIdentical);
+
+ m_chkPTime = new QCheckBox(tr("&Preserve file modification time"));
+ verticalLayout->addWidget(m_chkPTime);
+
+ insertTopWidget(checkInWidget);
+}
+
+QString ClearCaseSubmitEditorWidget::activity() const
+{
+ return m_actSelector->activity();
+}
+
+bool ClearCaseSubmitEditorWidget::isIdentical() const
+{
+ return m_chkIdentical->isChecked();
+}
+
+bool ClearCaseSubmitEditorWidget::isPreserve() const
+{
+ return m_chkPTime->isChecked();
+}
+
+void ClearCaseSubmitEditorWidget::setActivity(const QString &act)
+{
+ m_actSelector->setActivity(act);
+}
+
+bool ClearCaseSubmitEditorWidget::activityChanged() const
+{
+ return m_actSelector->changed();
+}
+
+void ClearCaseSubmitEditorWidget::addKeep()
+{
+ m_actSelector->addKeep();
+}
+
+QString ClearCaseSubmitEditorWidget::commitName() const
+{
+ return tr("&Check In");
+}
diff --git a/src/plugins/clearcase/clearcasesubmiteditorwidget.h b/src/plugins/clearcase/clearcasesubmiteditorwidget.h
new file mode 100644
index 0000000000..bf411e17d4
--- /dev/null
+++ b/src/plugins/clearcase/clearcasesubmiteditorwidget.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef CLEARCASESUBMITEDITORWIDGET_H
+#define CLEARCASESUBMITEDITORWIDGET_H
+
+#include <utils/submiteditorwidget.h>
+
+QT_BEGIN_NAMESPACE
+class QCheckBox;
+QT_END_NAMESPACE
+
+namespace ClearCase {
+namespace Internal {
+
+class ActivitySelector;
+
+class ClearCaseSubmitEditorWidget : public Utils::SubmitEditorWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ClearCaseSubmitEditorWidget(QWidget *parent = 0);
+ QString activity() const;
+ bool isIdentical() const;
+ bool isPreserve() const;
+ void setActivity(const QString &act);
+ bool activityChanged() const;
+ void addKeep();
+
+protected:
+ QString commitName() const;
+
+private:
+ ActivitySelector *m_actSelector;
+ QCheckBox *m_chkIdentical;
+ QCheckBox *m_chkPTime;
+};
+
+} // namespace Internal
+} // namespace ClearCase
+
+#endif // CLEARCASESUBMITEDITORWIDGET_H
diff --git a/src/plugins/clearcase/settingspage.cpp b/src/plugins/clearcase/settingspage.cpp
new file mode 100644
index 0000000000..a8cc6632ad
--- /dev/null
+++ b/src/plugins/clearcase/settingspage.cpp
@@ -0,0 +1,142 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "clearcaseconstants.h"
+#include "clearcasesettings.h"
+#include "clearcaseplugin.h"
+#include "settingspage.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <utils/pathchooser.h>
+
+#include <QCoreApplication>
+#include <QFileDialog>
+#include <QTextStream>
+
+using namespace ClearCase::Internal;
+using namespace Utils;
+
+SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
+ QWidget(parent)
+{
+ m_ui.setupUi(this);
+ m_ui.commandPathChooser->setPromptDialogTitle(tr("ClearCase Command"));
+ m_ui.commandPathChooser->setExpectedKind(PathChooser::ExistingCommand);
+}
+
+ClearCaseSettings SettingsPageWidget::settings() const
+{
+ ClearCaseSettings rc;
+ rc.ccCommand = m_ui.commandPathChooser->path();
+ rc.timeOutS = m_ui.timeOutSpinBox->value();
+ rc.autoCheckOut = m_ui.autoCheckOutCheckBox->isChecked();
+ if (m_ui.graphicalDiffRadioButton->isChecked())
+ rc.diffType = GraphicalDiff;
+ else if (m_ui.externalDiffRadioButton->isChecked())
+ rc.diffType = ExternalDiff;
+ rc.autoAssignActivityName = m_ui.autoAssignActivityCheckBox->isChecked();
+ rc.historyCount = m_ui.historyCountSpinBox->value();
+ rc.promptToCheckIn = m_ui.promptCheckBox->isChecked();
+ rc.disableIndexer = m_ui.disableIndexerCheckBox->isChecked();
+ rc.diffArgs = m_ui.diffArgsEdit->text();
+ rc.indexOnlyVOBs = m_ui.indexOnlyVOBsEdit->text();
+ return rc;
+}
+
+void SettingsPageWidget::setSettings(const ClearCaseSettings &s)
+{
+ m_ui.commandPathChooser->setPath(s.ccCommand);
+ m_ui.timeOutSpinBox->setValue(s.timeOutS);
+ m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut);
+ switch (s.diffType) {
+ case GraphicalDiff:
+ m_ui.graphicalDiffRadioButton->setChecked(true);
+ m_ui.diffWidget->setEnabled(false);
+ break;
+ case ExternalDiff:
+ m_ui.externalDiffRadioButton->setChecked(true);
+ m_ui.diffWidget->setEnabled(true);
+ break;
+ }
+ m_ui.autoAssignActivityCheckBox->setChecked(s.autoAssignActivityName);
+ m_ui.historyCountSpinBox->setValue(s.historyCount);
+ m_ui.promptCheckBox->setChecked(s.promptToCheckIn);
+ m_ui.disableIndexerCheckBox->setChecked(s.disableIndexer);
+ m_ui.diffArgsEdit->setText(s.diffArgs);
+ m_ui.indexOnlyVOBsEdit->setText(s.indexOnlyVOBs);
+}
+
+QString SettingsPageWidget::searchKeywords() const
+{
+ QString rc;
+ QLatin1Char sep(' ');
+ QTextStream(&rc) << m_ui.commandLabel->text()
+ << sep << m_ui.autoCheckOutCheckBox->text()
+ << sep << m_ui.externalDiffRadioButton->text()
+ << sep << m_ui.graphicalDiffRadioButton->text()
+ << sep << m_ui.diffArgsLabel->text()
+ << sep << m_ui.historyCountLabel->text()
+ << sep << m_ui.promptCheckBox->text()
+ << sep << m_ui.disableIndexerCheckBox->text()
+ << sep << m_ui.timeOutLabel->text()
+ << sep << m_ui.indexOnlyVOBsLabel->text()
+ ;
+ rc.remove(QLatin1Char('&'));
+ return rc;
+}
+
+SettingsPage::SettingsPage() :
+ m_widget(0)
+{
+ setId(QLatin1String(ClearCase::Constants::VCS_ID_CLEARCASE));
+ setDisplayName(tr("ClearCase"));
+}
+
+QWidget *SettingsPage::createPage(QWidget *parent)
+{
+ m_widget = new SettingsPageWidget(parent);
+ m_widget->setSettings(ClearCasePlugin::instance()->settings());
+ if (m_searchKeywords.isEmpty())
+ m_searchKeywords = m_widget->searchKeywords();
+ return m_widget;
+}
+
+void SettingsPage::apply()
+{
+ ClearCasePlugin::instance()->setSettings(m_widget->settings());
+}
+
+bool SettingsPage::matches(const QString &s) const
+{
+ return m_searchKeywords.contains(s, Qt::CaseInsensitive);
+}
diff --git a/src/plugins/clearcase/settingspage.h b/src/plugins/clearcase/settingspage.h
new file mode 100644
index 0000000000..fa89bb795d
--- /dev/null
+++ b/src/plugins/clearcase/settingspage.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef SETTINGSPAGE_H
+#define SETTINGSPAGE_H
+
+#include "ui_settingspage.h"
+
+#include <vcsbase/vcsbaseoptionspage.h>
+
+#include <QPointer>
+#include <QString>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace ClearCase {
+namespace Internal {
+
+class ClearCaseSettings;
+
+class SettingsPageWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SettingsPageWidget(QWidget *parent = 0);
+
+ ClearCaseSettings settings() const;
+ void setSettings(const ClearCaseSettings &);
+
+ QString searchKeywords() const;
+
+private:
+ Ui::SettingsPage m_ui;
+};
+
+
+class SettingsPage : public VcsBase::VcsBaseOptionsPage
+{
+ Q_OBJECT
+
+public:
+ SettingsPage();
+
+ QWidget *createPage(QWidget *parent);
+ void apply();
+ void finish() { }
+ bool matches(const QString &) const;
+
+private:
+ QString m_searchKeywords;
+ SettingsPageWidget* m_widget;
+};
+
+} // namespace ClearCase
+} // namespace Internal
+
+#endif // SETTINGSPAGE_H
diff --git a/src/plugins/clearcase/settingspage.ui b/src/plugins/clearcase/settingspage.ui
new file mode 100644
index 0000000000..06cb74647a
--- /dev/null
+++ b/src/plugins/clearcase/settingspage.ui
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClearCase::Internal::SettingsPage</class>
+ <widget class="QWidget" name="ClearCase::Internal::SettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>363</width>
+ <height>384</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="generalGroupBox">
+ <property name="title">
+ <string>Configuration</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="commandLabel">
+ <property name="text">
+ <string>&amp;Command:</string>
+ </property>
+ <property name="buddy">
+ <cstring>commandPathChooser</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="Utils::PathChooser" name="commandPathChooser" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Diff</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="graphicalDiffRadioButton">
+ <property name="text">
+ <string>&amp;Graphical (Single file only)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QRadioButton" name="externalDiffRadioButton">
+ <property name="text">
+ <string>&amp;External</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QWidget" name="diffWidget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="diffArgsLabel">
+ <property name="text">
+ <string>Arg&amp;uments:</string>
+ </property>
+ <property name="buddy">
+ <cstring>diffArgsEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="diffArgsEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="miscGroupBox">
+ <property name="title">
+ <string>Miscellaneous</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="historyCountLabel">
+ <property name="text">
+ <string>&amp;History count:</string>
+ </property>
+ <property name="buddy">
+ <cstring>historyCountSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="historyCountSpinBox">
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="timeOutLabel">
+ <property name="text">
+ <string>&amp;Timeout:</string>
+ </property>
+ <property name="buddy">
+ <cstring>timeOutSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QSpinBox" name="timeOutSpinBox">
+ <property name="suffix">
+ <string>s</string>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>360</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QCheckBox" name="autoCheckOutCheckBox">
+ <property name="text">
+ <string>&amp;Automatically check out files on edit</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="autoAssignActivityCheckBox">
+ <property name="toolTip">
+ <string>Check this if you have a trigger that renames the activity automatically. You will not be prompted for activity name</string>
+ </property>
+ <property name="text">
+ <string>Aut&amp;o assign activity names</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QCheckBox" name="promptCheckBox">
+ <property name="text">
+ <string>&amp;Prompt on check-in</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QCheckBox" name="disableIndexerCheckBox">
+ <property name="text">
+ <string>Di&amp;sable indexer</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="indexOnlyVOBsLabel">
+ <property name="text">
+ <string>&amp;Index only VOBs:</string>
+ </property>
+ <property name="buddy">
+ <cstring>indexOnlyVOBsEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QLineEdit" name="indexOnlyVOBsEdit">
+ <property name="toolTip">
+ <string>VOBs list, separated by comma. Indexer will only traverse the specified VOBs. If left blank, all active VOBs will be indexed</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ <slots>
+ <signal>editingFinished()</signal>
+ <signal>browsingFinished()</signal>
+ </slots>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>graphicalDiffRadioButton</tabstop>
+ <tabstop>externalDiffRadioButton</tabstop>
+ <tabstop>historyCountSpinBox</tabstop>
+ <tabstop>timeOutSpinBox</tabstop>
+ <tabstop>autoCheckOutCheckBox</tabstop>
+ <tabstop>autoAssignActivityCheckBox</tabstop>
+ <tabstop>indexOnlyVOBsEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>externalDiffRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>diffWidget</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>83</x>
+ <y>122</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>203</x>
+ <y>140</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/clearcase/undocheckout.ui b/src/plugins/clearcase/undocheckout.ui
new file mode 100644
index 0000000000..a830f84091
--- /dev/null
+++ b/src/plugins/clearcase/undocheckout.ui
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClearCase::Internal::UndoCheckOut</class>
+ <widget class="QDialog" name="ClearCase::Internal::UndoCheckOut">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>323</width>
+ <height>105</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="lblMessage"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblModified">
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>68</red>
+ <green>96</green>
+ <blue>92</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="text">
+ <string>The file was changed!</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkKeep">
+ <property name="text">
+ <string>&amp;Save copy of the file with a '.keep' extension</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::No|QDialogButtonBox::Yes</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ClearCase::Internal::UndoCheckOut</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ClearCase::Internal::UndoCheckOut</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/clearcase/versionselector.cpp b/src/plugins/clearcase/versionselector.cpp
new file mode 100644
index 0000000000..281ae2901f
--- /dev/null
+++ b/src/plugins/clearcase/versionselector.cpp
@@ -0,0 +1,110 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#include "versionselector.h"
+#include "ui_versionselector.h"
+
+#include <QRegExp>
+#include <QTextStream>
+
+namespace ClearCase {
+namespace Internal {
+
+VersionSelector::VersionSelector(const QString &fileName, const QString &message, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::VersionSelector)
+{
+ ui->setupUi(this);
+ ui->headerLabel->setText(ui->headerLabel->text().arg(fileName));
+ m_stream = new QTextStream(message.toLocal8Bit(), QIODevice::ReadOnly | QIODevice::Text);
+ QString line;
+ while (!m_stream->atEnd() && !line.contains(QLatin1String("1) Loaded version")))
+ line = m_stream->readLine();
+ if (!readValues())
+ return;
+ ui->loadedLabel->setText(m_versionID);
+ ui->loadedCreatedByLabel->setText(m_createdBy);
+ ui->loadedCreatedOnLabel->setText(m_createdOn);
+ ui->loadedText->insertPlainText(m_message + QLatin1Char(' '));
+
+ line = m_stream->readLine(); // 2) Version after update
+ if (!readValues())
+ return;
+ ui->updatedLabel->setText(m_versionID);
+ ui->updatedCreatedByLabel->setText(m_createdBy);
+ ui->updatedCreatedOnLabel->setText(m_createdOn);
+ ui->updatedText->setPlainText(m_message);
+}
+
+VersionSelector::~VersionSelector()
+{
+ delete m_stream;
+ delete ui;
+}
+
+bool VersionSelector::readValues()
+{
+ QString line;
+ line = m_stream->readLine();
+ QRegExp id(QLatin1String("Version ID: (.*)"));
+ if (id.indexIn(line) == -1)
+ return false;
+ m_versionID = id.cap(1);
+ line = m_stream->readLine();
+ QRegExp owner(QLatin1String("Created by: (.*)"));
+ if (owner.indexIn(line) == -1)
+ return false;
+ m_createdBy = owner.cap(1);
+ line = m_stream->readLine();
+ QRegExp dateTimeRE(QLatin1String("Created on: (.*)"));
+ if (dateTimeRE.indexIn(line) == -1)
+ return false;
+ m_createdOn = dateTimeRE.cap(1);
+ QStringList messageLines;
+ do
+ {
+ line = m_stream->readLine().trimmed();
+ if (line.isEmpty())
+ break;
+ messageLines << line;
+ } while (!m_stream->atEnd());
+ m_message = messageLines.join(QLatin1String(" "));
+ return true;
+}
+
+bool VersionSelector::isUpdate() const
+{
+ return (ui->updatedRadioButton->isChecked());
+}
+
+} // namespace Internal
+} // namespace ClearCase
diff --git a/src/plugins/clearcase/versionselector.h b/src/plugins/clearcase/versionselector.h
new file mode 100644
index 0000000000..5ee1d070d3
--- /dev/null
+++ b/src/plugins/clearcase/versionselector.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 AudioCodes Ltd.
+**
+** Author: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+**
+** Contact: http://www.qt-project.org/
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**************************************************************************/
+
+#ifndef VERSIONSELECTOR_H
+#define VERSIONSELECTOR_H
+
+#include <QDialog>
+#include <QDateTime>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+class QTextStream;
+QT_END_NAMESPACE
+
+namespace ClearCase {
+namespace Internal {
+
+namespace Ui {
+ class VersionSelector;
+}
+
+class VersionSelector : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit VersionSelector(const QString &fileName, const QString &message, QWidget *parent = 0);
+ ~VersionSelector();
+ bool isUpdate() const;
+
+private:
+ Ui::VersionSelector *ui;
+ QTextStream *m_stream;
+ QString m_versionID, m_createdBy, m_createdOn, m_message;
+ bool readValues();
+};
+
+
+} // namespace Internal
+} // namespace ClearCase
+#endif // VERSIONSELECTOR_H
diff --git a/src/plugins/clearcase/versionselector.ui b/src/plugins/clearcase/versionselector.ui
new file mode 100644
index 0000000000..38336a02e5
--- /dev/null
+++ b/src/plugins/clearcase/versionselector.ui
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClearCase::Internal::VersionSelector</class>
+ <widget class="QDialog" name="ClearCase::Internal::VersionSelector">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>413</width>
+ <height>435</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Confirm Version to Check Out</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="headerLabel">
+ <property name="text">
+ <string>There are multiple versions of '%1' which can be considered for checkout. Please select version to checkout:</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QFormLayout" name="loadedLayout">
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="loadedRadioButton">
+ <property name="text">
+ <string>&amp;Loaded Version</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="loadedLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="loadedCreatedByHeaderLabel">
+ <property name="text">
+ <string>Created By:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="loadedCreatedByLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="loadedCreatedOnHeaderLabel">
+ <property name="text">
+ <string>Created On:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="loadedCreatedOnLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QTextEdit" name="loadedText">
+ <property name="html">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt; font-weight:600;&quot;&gt;NOTE: You will not be able to check in this file without merging the changes (not supported by the plugin)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QFormLayout" name="updatedLayout">
+ <item row="0" column="1">
+ <widget class="QLabel" name="updatedLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="updatedCreatedByHeaderLabel">
+ <property name="text">
+ <string>Created By:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="updatedCreatedByLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="updatedCreatedOnHeaderLabel">
+ <property name="text">
+ <string>Created On:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="updatedCreatedOnLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QPlainTextEdit" name="updatedText">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="updatedRadioButton">
+ <property name="text">
+ <string>Version after &amp;update</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ClearCase::Internal::VersionSelector</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ClearCase::Internal::VersionSelector</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 642742187d..6d36a723b2 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -57,6 +57,7 @@ isEmpty(IDE_PACKAGE_MODE) {
linux-* {
SUBDIRS += debugger/ptracepreload.pro
}
+!macx:SUBDIRS += plugin_clearcase
include(../../qtcreator.pri)
@@ -331,3 +332,7 @@ plugin_qnx.depends = plugin_remotelinux
plugin_qnx.depends += plugin_qt4projectmanager
plugin_qnx.depends += plugin_coreplugin
+plugin_clearcase.subdir = clearcase
+plugin_clearcase.depends = plugin_vcsbase
+plugin_clearcase.depends += plugin_projectexplorer
+plugin_clearcase.depends += plugin_coreplugin