OSDN Git Service

885d025902b43cc570ef2ea8f48a9af0ba8e929c
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qt4projectmanager / profilecompletion.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 "profilecompletion.h"
35 #include "profileeditor.h"
36 #include "profilekeywords.h"
37 #include <texteditor/itexteditor.h>
38 #include <texteditor/completionsettings.h>
39 #include <cplusplus/Icons.h>
40 #include <QtCore/QDebug>
41
42 using namespace Qt4ProjectManager::Internal;
43
44 ProFileCompletion::ProFileCompletion(QObject *parent) :
45     TextEditor::ICompletionCollector(parent),
46     m_editor(0),
47     m_startPosition(-1),
48     m_variableIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::VarPublicIconType)),
49     m_functionIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::FuncPublicIconType))
50 {
51 }
52
53 ProFileCompletion::~ProFileCompletion()
54 {
55
56 }
57
58 QList<TextEditor::CompletionItem> ProFileCompletion::getCompletions()
59 {
60     QList<TextEditor::CompletionItem> completionItems;
61     completions(&completionItems);
62
63     return completionItems;
64 }
65
66 bool ProFileCompletion::shouldRestartCompletion()
67 {
68     return false;
69 }
70
71 TextEditor::ITextEditor *ProFileCompletion::editor() const
72 {
73     return m_editor;
74 }
75
76 int ProFileCompletion::startPosition() const
77 {
78     return m_startPosition;
79 }
80
81 bool ProFileCompletion::supportsEditor(TextEditor::ITextEditor *editor) const
82 {
83     return qobject_cast<ProFileEditor *>(editor) != 0;
84 }
85
86 bool ProFileCompletion::supportsPolicy(TextEditor::CompletionPolicy policy) const
87 {
88     return policy == TextEditor::SemanticCompletion;
89 }
90
91 bool ProFileCompletion::triggersCompletion(TextEditor::ITextEditor *editor)
92 {
93     m_editor = editor;
94     const int pos = editor->position();
95
96     if (completionSettings().m_completionTrigger == TextEditor::AutomaticCompletion) {
97         QChar characterUnderCursor = editor->characterAt(pos);
98         if (!characterUnderCursor.isLetterOrNumber()) {
99             m_startPosition = findStartOfName();
100             if (pos - m_startPosition >= 3 && !isInComment())
101                 return true;
102         }
103     }
104     return false;
105 }
106
107 int ProFileCompletion::findStartOfName(int pos) const
108 {
109     if (pos == -1)
110         pos = m_editor->position();
111     QChar chr;
112
113     // Skip to the start of a name
114     do {
115         chr = m_editor->characterAt(--pos);
116     } while (chr.isLetterOrNumber() || chr == QLatin1Char('_'));
117
118     return pos + 1;
119 }
120
121 bool ProFileCompletion::isInComment() const
122 {
123     const int beginOfLinePosition = m_editor->position(TextEditor::ITextEditor::StartOfLine);
124     const QString lineBeginning = m_editor->textAt(beginOfLinePosition,
125                                   m_startPosition - beginOfLinePosition);
126     if (lineBeginning.contains(QLatin1Char('#')))
127         return true;
128     return false;
129 }
130
131 int ProFileCompletion::startCompletion(TextEditor::ITextEditor *editor)
132 {
133     m_editor = editor;
134     m_startPosition = findStartOfName();
135
136     return m_startPosition;
137 }
138
139 void ProFileCompletion::completions(QList<TextEditor::CompletionItem> *completions)
140 {
141     const int length = m_editor->position() - m_startPosition;
142     if (length < 0)
143         return;
144
145     if (isInComment())
146         return;
147
148     const QString key = m_editor->textAt(m_startPosition, length);
149
150     QList<TextEditor::CompletionItem> items;
151     QStringList keywords = ProFileKeywords::variables()
152             + ProFileKeywords::functions();
153 //    qSort(keywords);
154     for (int i = 0; i < keywords.count(); i++) {
155         TextEditor::CompletionItem item(this);
156         item.text = keywords[i];
157         item.data = QVariant::fromValue(item.text);
158         item.icon = ProFileKeywords::isFunction(item.text)
159                 ? m_functionIcon : m_variableIcon;
160         items.append(item);
161     }
162
163     filter(items, completions, key);
164 }
165
166 bool ProFileCompletion::typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar)
167 {
168     // only '(' in case of a function
169     if (typedChar == QLatin1Char('(') && ProFileKeywords::isFunction(item.text))
170         return true;
171     return false;
172 }
173
174 void ProFileCompletion::complete(const TextEditor::CompletionItem &item, QChar typedChar)
175 {
176     Q_UNUSED(typedChar)
177
178     int replaceLength = m_editor->position() - m_startPosition;
179     if (replaceLength < 0)
180         return;
181
182     QString toInsert = item.text;
183     int cursorOffset = 0;
184     if (ProFileKeywords::isFunction(toInsert)
185             && completionSettings().m_autoInsertBrackets) {
186         if (completionSettings().m_spaceAfterFunctionName) {
187             if (m_editor->textAt(m_editor->position(), 2) == QLatin1String(" (")) {
188                 cursorOffset = 2;
189             } else if (m_editor->characterAt(m_editor->position()) == QLatin1Char('(')
190                        || m_editor->characterAt(m_editor->position()) == QLatin1Char(' ')) {
191                 replaceLength += 1;
192                 toInsert += QLatin1String(" (");
193             } else {
194                 toInsert += QLatin1String(" ()");
195                 cursorOffset = -1;
196             }
197         } else {
198             if (m_editor->characterAt(m_editor->position()) == QLatin1Char('(')) {
199                 cursorOffset = 1;
200             } else {
201                 toInsert += QLatin1String("()");
202                 cursorOffset = -1;
203             }
204         }
205     }
206
207     m_editor->setCursorPosition(m_startPosition);
208     m_editor->replace(replaceLength, toInsert);
209     if (cursorOffset)
210         m_editor->setCursorPosition(m_editor->position() + cursorOffset);
211 }
212
213 bool ProFileCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
214 {
215     if (completionItems.count() == 1) {
216         complete(completionItems.first(), QChar());
217         return true;
218     }
219
220     return TextEditor::ICompletionCollector::partiallyComplete(completionItems);
221 }
222
223 void ProFileCompletion::cleanup()
224 {
225 }