OSDN Git Service

56f14fc96b9e26ff7fd86d0b5282bfc4621c725d
[qt-creator-jp/qt-creator-jp.git] / src / plugins / perforce / perforceeditor.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "perforceeditor.h"
35
36 #include "annotationhighlighter.h"
37 #include "perforceconstants.h"
38 #include "perforceplugin.h"
39
40 #include <coreplugin/editormanager/editormanager.h>
41 #include <utils/qtcassert.h>
42 #include <vcsbase/diffhighlighter.h>
43
44 #include <QtCore/QDebug>
45 #include <QtCore/QFileInfo>
46 #include <QtCore/QProcess>
47 #include <QtCore/QRegExp>
48 #include <QtCore/QSet>
49 #include <QtCore/QTextStream>
50
51 #include <QtGui/QAction>
52 #include <QtGui/QKeyEvent>
53 #include <QtGui/QLayout>
54 #include <QtGui/QMenu>
55 #include <QtGui/QTextCursor>
56 #include <QtGui/QTextEdit>
57 #include <QtGui/QTextBlock>
58
59 namespace Perforce {
60 namespace Internal {
61
62 // ------------ PerforceEditor
63 PerforceEditor::PerforceEditor(const VCSBase::VCSBaseEditorParameters *type,
64                                QWidget *parent)  :
65     VCSBase::VCSBaseEditorWidget(type, parent),
66     m_changeNumberPattern(QLatin1String("^\\d+$")),
67     m_plugin(PerforcePlugin::perforcePluginInstance())
68 {
69     QTC_ASSERT(m_changeNumberPattern.isValid(), /**/);
70     setAnnotateRevisionTextFormat(tr("Annotate change list \"%1\""));
71     if (Perforce::Constants::debug)
72         qDebug() << "PerforceEditor::PerforceEditor" << type->type << type->id;
73 }
74
75 QSet<QString> PerforceEditor::annotationChanges() const
76 {
77     QSet<QString> changes;
78     const QString txt = toPlainText();
79     if (txt.isEmpty())
80         return changes;
81     // Hunt for first change number in annotation: "<change>:"
82     QRegExp r(QLatin1String("^(\\d+):"));
83     QTC_ASSERT(r.isValid(), return changes);
84     if (r.indexIn(txt) != -1) {
85         changes.insert(r.cap(1));
86         r.setPattern(QLatin1String("\n(\\d+):"));
87         QTC_ASSERT(r.isValid(), return changes);
88         int pos = 0;
89         while ((pos = r.indexIn(txt, pos)) != -1) {
90             pos += r.matchedLength();
91             changes.insert(r.cap(1));
92         }
93     }
94     if (Perforce::Constants::debug)
95         qDebug() << "PerforceEditor::annotationChanges() returns #" << changes.size();
96     return changes;
97 }
98
99 QString PerforceEditor::changeUnderCursor(const QTextCursor &c) const
100 {
101     QTextCursor cursor = c;
102     // Any number is regarded as change number.
103     cursor.select(QTextCursor::WordUnderCursor);
104     if (!cursor.hasSelection())
105         return QString();
106     const QString change = cursor.selectedText();
107     return m_changeNumberPattern.exactMatch(change) ? change : QString();
108 }
109
110 VCSBase::DiffHighlighter *PerforceEditor::createDiffHighlighter() const
111 {
112     const QRegExp filePattern(QLatin1String("^====.*"));
113     return new VCSBase::DiffHighlighter(filePattern);
114 }
115
116 VCSBase::BaseAnnotationHighlighter *PerforceEditor::createAnnotationHighlighter(const QSet<QString> &changes) const
117 {
118     return new PerforceAnnotationHighlighter(changes);
119 }
120
121 QString PerforceEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
122 {
123     QString errorMessage;
124     const QString diffIndicator = QLatin1String("==== ");
125     const QString diffEndIndicator = QLatin1String(" ====");
126     // Go back chunks. Note that for 'describe', an extra, empty line
127     // occurs.
128     for (QTextBlock  block = inBlock; block.isValid(); block = block.previous()) {
129         QString diffFileName = block.text();
130         if (diffFileName.startsWith(diffIndicator) && diffFileName.endsWith(diffEndIndicator)) {
131             // Split:
132             // 1) "==== //depot/.../mainwindow.cpp#2 - /depot/.../mainwindow.cpp ===="
133             // (as created by p4 diff) or
134             // 2) "==== //depot/.../mainwindow.cpp#15 (text) ===="
135             // (as created by p4 describe).
136             diffFileName.remove(0, diffIndicator.size());
137             diffFileName.truncate(diffFileName.size() - diffEndIndicator.size());
138             const int separatorPos = diffFileName.indexOf(QLatin1String(" - "));
139             if (separatorPos == -1) {
140                 // ==== depot path (text) ==== (p4 describe)
141                 const int blankPos = diffFileName.indexOf(QLatin1Char(' '));
142                 if (blankPos == -1)
143                     return QString();
144                 diffFileName.truncate(blankPos);
145             } else {
146                 // ==== depot path - local path ==== (p4 diff)
147                 diffFileName.truncate(separatorPos);
148             }
149             // Split off revision "#4"
150             const int revisionPos = diffFileName.lastIndexOf(QLatin1Char('#'));
151             if (revisionPos != -1 && revisionPos < diffFileName.length() - 1)
152                 diffFileName.truncate(revisionPos);
153             // Ask plugin to map back
154             const QString fileName = m_plugin->fileNameFromPerforceName(diffFileName.trimmed(), false, &errorMessage);
155             if (fileName.isEmpty())
156                 qWarning("%s", qPrintable(errorMessage));
157             return fileName;
158         }
159     }
160     return QString();
161 }
162
163 QStringList PerforceEditor::annotationPreviousVersions(const QString &v) const
164 {
165     bool ok;
166     const int changeList = v.toInt(&ok);
167     if (!ok || changeList < 2)
168         return QStringList();
169     return QStringList(QString::number(changeList - 1));
170 }
171
172 } // namespace Internal
173 } // namespace Perforce