diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index 1bf515f92e5d33e38628e4adb29183ac6db78484..80ab420c5fa1e139c7ecac08aa6f59c551accc56 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -602,8 +602,7 @@ QDumper &QDumper::operator<<(const QByteArray &ba) QDumper &QDumper::operator<<(const QString &str) { - QByteArray ba = str.toUtf8(); - putBase64Encoded(ba.constData(), ba.size()); + putBase64Encoded((const char *)str.constData(), 2 * str.size()); return *this; } @@ -649,7 +648,7 @@ void QDumper::putEllipsis() P(dumper, "value", value); \ P(dumper, "type", NS"QString"); \ P(dumper, "numchild", "0"); \ - P(dumper, "valueencoded", "1"); \ + P(dumper, "valueencoded", "2"); \ dumper.endHash(); // simple integer property @@ -680,7 +679,7 @@ void QDumper::putEllipsis() P(dumper, "name", name); \ P(dumper, "value", QString(QLatin1String("'%1' (%2, 0x%3)")) \ .arg(value).arg(value.unicode()).arg(value.unicode(), 0, 16)); \ - P(dumper, "valueencoded", "1"); \ + P(dumper, "valueencoded", "2"); \ P(dumper, "type", NS"QChar"); \ P(dumper, "numchild", "0"); \ dumper.endHash(); @@ -755,7 +754,7 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr const QObject *ob = reinterpret_cast<const QObject *>(addr); P(d, "addr", ob); P(d, "value", ob->objectName()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QObject"); P(d, "displayedtype", ob->metaObject()->className()); } else { @@ -767,7 +766,7 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr case 'S': if (isEqual(type, "QString")) { d.addCommaIfNeeded(); - d << field << "encoded=\"1\","; + d << field << "encoded=\"2\","; P(d, field, *(QString*)addr); } return; @@ -857,7 +856,7 @@ static void qDumpQDateTime(QDumper &d) P(d, "value", "(null)"); } else { P(d, "value", date.toString()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); } P(d, "type", NS"QDateTime"); P(d, "numchild", "3"); @@ -901,7 +900,7 @@ static void qDumpQDir(QDumper &d) { const QDir &dir = *reinterpret_cast<const QDir *>(d.data); P(d, "value", dir.path()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QDir"); P(d, "numchild", "3"); if (d.dumpChildren) { @@ -917,7 +916,7 @@ static void qDumpQFile(QDumper &d) { const QFile &file = *reinterpret_cast<const QFile *>(d.data); P(d, "value", file.fileName()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QFile"); P(d, "numchild", "2"); if (d.dumpChildren) { @@ -933,7 +932,7 @@ static void qDumpQFileInfo(QDumper &d) { const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data); P(d, "value", info.filePath()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QFileInfo"); P(d, "numchild", "3"); if (d.dumpChildren) { @@ -980,7 +979,7 @@ static void qDumpQFileInfo(QDumper &d) d.beginHash(); P(d, "name", "created"); P(d, "value", info.created().toString()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->created()"); P(d, "type", NS"QDateTime"); P(d, "numchild", "1"); @@ -989,7 +988,7 @@ static void qDumpQFileInfo(QDumper &d) d.beginHash(); P(d, "name", "lastModified"); P(d, "value", info.lastModified().toString()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->lastModified()"); P(d, "type", NS"QDateTime"); P(d, "numchild", "1"); @@ -998,7 +997,7 @@ static void qDumpQFileInfo(QDumper &d) d.beginHash(); P(d, "name", "lastRead"); P(d, "value", info.lastRead().toString()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->lastRead()"); P(d, "type", NS"QDateTime"); P(d, "numchild", "1"); @@ -1296,7 +1295,7 @@ static void qDumpQLocale(QDumper &d) { const QLocale &locale = *reinterpret_cast<const QLocale *>(d.data); P(d, "value", locale.name()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QLocale"); P(d, "numchild", "8"); if (d.dumpChildren) { @@ -1508,7 +1507,7 @@ static void qDumpQObject(QDumper &d) const QMetaObject *mo = ob->metaObject(); unsigned childrenOffset = d.extraInt[0]; P(d, "value", ob->objectName()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QObject"); P(d, "displayedtype", mo->className()); P(d, "numchild", 4); @@ -1627,7 +1626,7 @@ static void qDumpQObjectPropertyList(QDumper &d) << ")->" << prop.name() << "()"); if (isEqual(prop.typeName(), "QString")) { P(d, "value", prop.read(ob).toString()); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QString"); P(d, "numchild", "0"); } else if (isEqual(prop.typeName(), "bool")) { @@ -1941,7 +1940,7 @@ static void qDumpQString(QDumper &d) } P(d, "value", str); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); P(d, "type", NS"QString"); //P(d, "editvalue", str); // handled generically below P(d, "numchild", "0"); @@ -1973,7 +1972,7 @@ static void qDumpQStringList(QDumper &d) d.beginHash(); P(d, "name", i); P(d, "value", list[i]); - P(d, "valueencoded", "1"); + P(d, "valueencoded", "2"); d.endHash(); } if (n < list.size()) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 2bdaa6445f632d134fcb720235b83d1f80c18d61..9a9dd71ec3cbcf49652f243a47acf90398f7ffdc 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -508,6 +508,9 @@ static int startOfOperator(TextEditor::ITextEditable *editor, return start; } +bool CppCodeCompletion::isValid(TextEditor::ITextEditable *editor) +{ return m_manager->isCppEditor(editor); } + bool CppCodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor) { if (! m_manager->isCppEditor(editor)) // ### remove me diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index c37e09ea03e2ad5d22c9540e175de66411fc7d49..174e5d994f4fa4163f864795522be72e841171ee 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -58,6 +58,7 @@ class CppCodeCompletion : public TextEditor::ICompletionCollector public: explicit CppCodeCompletion(CppModelManager *manager); + bool isValid(TextEditor::ITextEditable *editor); bool triggersCompletion(TextEditor::ITextEditable *editor); int startCompletion(TextEditor::ITextEditable *editor); void completions(QList<TextEditor::CompletionItem> *completions); diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 6ea9da6d1c72f8a131b6b675faeb04f729eaece0..078692f7312f4af48f00b1dabceb8b0e3aaa9639 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -1056,7 +1056,8 @@ void DebuggerManager::sessionLoaded() void DebuggerManager::sessionUnloaded() { return; - cleanupViews(); + //FIXME: Breakview crashes on startup as there is + //cleanupViews(); if (m_engine) m_engine->shutdown(); setStatus(DebuggerProcessNotReady); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 17cb99081acaae01620b9ad178dbca6359bc012c..b53bee9607335799f2abbc75023170496b5bf4af 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -65,6 +65,7 @@ #include <unistd.h> #include <dlfcn.h> #endif +#include <ctype.h> using namespace Debugger; using namespace Debugger::Internal; @@ -2776,36 +2777,55 @@ void GdbEngine::setToolTipExpression(const QPoint &pos, const QString &exp0) static const QString strNotInScope = QLatin1String("<not in scope>"); +static QString quoteUnprintableLatin1(const QByteArray &ba) +{ + QString res; + char buf[10]; + for (int i = 0, n = ba.size(); i != n; ++i) { + unsigned char c = ba.at(i); + if (isprint(c)) { + res += c; + } else { + qsnprintf(buf, sizeof(buf) - 1, "\\%x", int(c)); + res += buf; + } + } + return res; +} + static void setWatchDataValue(WatchData &data, const GdbMi &mi, int encoding = 0) { if (mi.isValid()) { QByteArray ba; + QString str; switch (encoding) { case 0: // unencoded 8 bit data ba = mi.data(); + str = quoteUnprintableLatin1(ba); break; - case 1: // base64 encoded 8 bit data + case 1: // base64 encoded 8 bit data, used for QByteArray ba = QByteArray::fromBase64(mi.data()); - ba = '"' + ba + '"'; + str = '"' + quoteUnprintableLatin1(ba) + '"'; break; - case 2: // base64 encoded 16 bit data + case 2: // base64 encoded 16 bit data, used for QString ba = QByteArray::fromBase64(mi.data()); - ba = QString::fromUtf16((ushort *)ba.data(), ba.size() / 2).toUtf8(); - ba = '"' + ba + '"'; + str = QString::fromUtf16((ushort *)ba.data(), ba.size() / 2); + str = '"' + str + '"'; break; case 3: // base64 encoded 32 bit data ba = QByteArray::fromBase64(mi.data()); - ba = QString::fromUcs4((uint *)ba.data(), ba.size() / 4).toUtf8(); - ba = '"' + ba + '"'; + str = QString::fromUcs4((uint *)ba.data(), ba.size() / 4); + str = '"' + str + '"'; break; - case 4: // base64 encoded 8 bit data + case 4: // base64 encoded 16 bit data, without quotes (see 2) ba = QByteArray::fromBase64(mi.data()); + str = QString::fromUtf16((ushort *)ba.data(), ba.size() / 2); break; } - data.setValue(ba); + data.setValue(str); } else { - data.setValueNeeded(); + data.setValueNeeded(); } } @@ -3411,7 +3431,7 @@ void GdbEngine::handleVarCreate(const GdbResultRecord &record, data.setChildrenNeeded(); setWatchDataChildCount(data, record.data.findChild("numchild")); //if (data.isValueNeeded() && data.childCount > 0) - // data.setValue(QByteArray()); + // data.setValue(QString()); insertData(data); } } else if (record.resultClass == GdbResultError) { @@ -3607,13 +3627,13 @@ void GdbEngine::handleDumpCustomValue3(const GdbResultRecord &record, QString str; for (int i = 0; i < list.size(); ++i) str.append(list.at(i).toInt()); - data.setValue('"' + str.toUtf8() + '"'); + data.setValue('"' + str + '"'); data.setChildCount(0); data.setAllUnneeded(); insertData(data); } else if (data.type == "QStringList" || data.type.endsWith("::QStringList")) { int l = list.size(); - data.setValue(QString("<%1 items>").arg(l).toLatin1()); + data.setValue(tr("<%1 items>").arg(l)); data.setChildCount(list.size()); data.setAllUnneeded(); insertData(data); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 9458bac9f3800aeb69efa9cbed9502e300230f8b..af120e3a18ca8c47bc9e5379ce1715f34f25f5b7 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -47,9 +47,9 @@ #include <QtGui/QToolTip> #include <QtGui/QTextEdit> - #include <ctype.h> + // creates debug output regarding pending watch data results #define DEBUG_PENDING 1 // creates debug output for accesses to the itemmodel @@ -91,25 +91,9 @@ void WatchData::setError(const QString &msg) valuedisabled = true; } -static QByteArray quoteUnprintable(const QByteArray &ba) -{ - QByteArray res; - char buf[10]; - for (int i = 0, n = ba.size(); i != n; ++i) { - unsigned char c = ba.at(i); - if (isprint(c)) { - res += c; - } else { - qsnprintf(buf, sizeof(buf) - 1, "\\%x", int(c)); - res += buf; - } - } - return res; -} - -void WatchData::setValue(const QByteArray &value0) +void WatchData::setValue(const QString &value0) { - value = quoteUnprintable(value0); + value = value0; if (value == "{...}") { value.clear(); childCount = 1; // at least one... diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index a31c8f0caec7675fe2085427a26a675df827103e..ba6bb64dd1b646c32d1b618331d622523ea16bd7 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -66,7 +66,7 @@ public: | ChildCountNeeded }; - void setValue(const QByteArray &); + void setValue(const QString &); void setType(const QString &); void setValueToolTip(const QString &); void setError(const QString &); diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index e2d777e8c4508e9a6a5d8b1dfee73a5db52b3195..34c0080ca099c8140debccff7138c663da17f3d4 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1247,6 +1247,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, m_tc.insertText(text); moveUp(n); } + moveToFirstNonBlankOnLine(); } else { m_desiredColumn = 0; for (int i = count(); --i >= 0; ) { diff --git a/src/plugins/projectexplorer/winguiprocess.cpp b/src/plugins/projectexplorer/winguiprocess.cpp index 75efc7cb7364c558e86c39f2ee1c5fd6bebeb8ba..5085978175311cfc5a5f89d82a6307aa9a4a72a7 100644 --- a/src/plugins/projectexplorer/winguiprocess.cpp +++ b/src/plugins/projectexplorer/winguiprocess.cpp @@ -147,7 +147,7 @@ void WinGuiProcess::run() switch (ret) { case WAIT_OBJECT_0 + 0: if (*processId == m_pid->dwProcessId) - emit receivedDebugOutput(QString::fromAscii(message)); + emit receivedDebugOutput(QString::fromLocal8Bit(message)); SetEvent(bufferReadyEvent); break; case WAIT_OBJECT_0 + 1: diff --git a/src/plugins/qtscripteditor/parser/javascript.g b/src/plugins/qtscripteditor/parser/javascript.g index f762498ee4c60cd19f3f2edd9e950735be84e791..80dfaddcad47229393aa98547e152568b8a3897f 100644 --- a/src/plugins/qtscripteditor/parser/javascript.g +++ b/src/plugins/qtscripteditor/parser/javascript.g @@ -2179,7 +2179,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; } } - const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(token_buffer[0].token); + const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(spell[token_buffer[0].token]); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc.startLine, token_buffer[0].loc.startColumn, msg)); } diff --git a/src/plugins/qtscripteditor/parser/javascriptengine_p.h b/src/plugins/qtscripteditor/parser/javascriptengine_p.h index 7bcbf1f3cc6a0a1017331554ca25a55e1bd58a31..480ef042a70595818773e7fdc271645b3cdcc592 100644 --- a/src/plugins/qtscripteditor/parser/javascriptengine_p.h +++ b/src/plugins/qtscripteditor/parser/javascriptengine_p.h @@ -77,6 +77,9 @@ public: : _lexer(0), _nodePool(0), _ast(0) { } + QSet<JavaScriptNameIdImpl> literals() const + { return _literals; } + JavaScriptNameIdImpl *intern(const QChar *u, int s) { return const_cast<JavaScriptNameIdImpl *>(&*_literals.insert(JavaScriptNameIdImpl(u, s))); } diff --git a/src/plugins/qtscripteditor/parser/javascriptparser.cpp b/src/plugins/qtscripteditor/parser/javascriptparser.cpp index 794c416b763c8f3aeca13a92420df57a22c8b7ae..ac8eabf09548eed7b35f30958996d69b6c0bf8cc 100644 --- a/src/plugins/qtscripteditor/parser/javascriptparser.cpp +++ b/src/plugins/qtscripteditor/parser/javascriptparser.cpp @@ -1184,7 +1184,7 @@ case 266: { } } - const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(token_buffer[0].token); + const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(spell[token_buffer[0].token]); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc.startLine, token_buffer[0].loc.startColumn, msg)); } diff --git a/src/plugins/qtscripteditor/qtscriptcodecompletion.cpp b/src/plugins/qtscripteditor/qtscriptcodecompletion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d08a3e175ef0a7d15d489fcb86f52d5ba505d5b9 --- /dev/null +++ b/src/plugins/qtscripteditor/qtscriptcodecompletion.cpp @@ -0,0 +1,151 @@ + +#include "qtscriptcodecompletion.h" +#include "qtscripteditor.h" +#include <texteditor/basetexteditor.h> +#include <QtDebug> + +using namespace QtScriptEditor::Internal; + +QtScriptCodeCompletion::QtScriptCodeCompletion(QObject *parent) + : TextEditor::ICompletionCollector(parent), + m_editor(0), + m_startPosition(0), + m_caseSensitivity(Qt::CaseSensitive) +{ } + +QtScriptCodeCompletion::~QtScriptCodeCompletion() +{ } + +Qt::CaseSensitivity QtScriptCodeCompletion::caseSensitivity() const +{ return m_caseSensitivity; } + +void QtScriptCodeCompletion::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) +{ m_caseSensitivity = caseSensitivity; } + +bool QtScriptCodeCompletion::isValid(TextEditor::ITextEditable *editor) +{ + if (qobject_cast<ScriptEditor *>(editor->widget())) + return true; + + return false; +} + +bool QtScriptCodeCompletion::triggersCompletion(TextEditor::ITextEditable *) +{ return false; } + +int QtScriptCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) +{ + m_editor = editor; + + ScriptEditor *edit = qobject_cast<ScriptEditor *>(m_editor->widget()); + if (! edit) + return -1; + + int pos = editor->position(); + + while (editor->characterAt(pos - 1).isLetterOrNumber() || editor->characterAt(pos - 1) == QLatin1Char('_')) + --pos; + + m_startPosition = pos; + m_completions.clear(); + + foreach (const QString &word, edit->words()) { + TextEditor::CompletionItem item(this); + item.m_text = word; + m_completions.append(item); + } + + return pos; +} + +void QtScriptCodeCompletion::completions(QList<TextEditor::CompletionItem> *completions) +{ + // ### FIXME: this code needs to be generalized. + + const int length = m_editor->position() - m_startPosition; + + if (length == 0) + *completions = m_completions; + else if (length > 0) { + const QString key = m_editor->textAt(m_startPosition, length); + + /* + * This code builds a regular expression in order to more intelligently match + * camel-case style. This means upper-case characters will be rewritten as follows: + * + * A => [a-z0-9_]*A (for any but the first capital letter) + * + * Meaning it allows any sequence of lower-case characters to preceed an + * upper-case character. So for example gAC matches getActionController. + */ + QString keyRegExp; + keyRegExp += QLatin1Char('^'); + bool first = true; + foreach (const QChar &c, key) { + if (c.isUpper() && !first) { + keyRegExp += QLatin1String("[a-z0-9_]*"); + keyRegExp += c; + } else if (m_caseSensitivity == Qt::CaseInsensitive && c.isLower()) { + keyRegExp += QLatin1Char('['); + keyRegExp += c; + keyRegExp += c.toUpper(); + keyRegExp += QLatin1Char(']'); + } else { + keyRegExp += QRegExp::escape(c); + } + first = false; + } + const QRegExp regExp(keyRegExp, Qt::CaseSensitive); + + foreach (TextEditor::CompletionItem item, m_completions) { + if (regExp.indexIn(item.m_text) == 0) { + item.m_relevance = (key.length() > 0 && + item.m_text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0; + (*completions) << item; + } + } + } +} + +void QtScriptCodeCompletion::complete(const TextEditor::CompletionItem &item) +{ + const QString toInsert = item.m_text; + const int length = m_editor->position() - m_startPosition; + m_editor->setCurPos(m_startPosition); + m_editor->replace(length, toInsert); +} + +bool QtScriptCodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems) +{ + if (completionItems.count() == 1) { + complete(completionItems.first()); + return true; + } else { + // Compute common prefix + QString firstKey = completionItems.first().m_text; + QString lastKey = completionItems.last().m_text; + const int length = qMin(firstKey.length(), lastKey.length()); + firstKey.truncate(length); + lastKey.truncate(length); + + while (firstKey != lastKey) { + firstKey.chop(1); + lastKey.chop(1); + } + + int typedLength = m_editor->position() - m_startPosition; + if (!firstKey.isEmpty() && firstKey.length() > typedLength) { + m_editor->setCurPos(m_startPosition); + m_editor->replace(typedLength, firstKey); + } + } + return false; +} + +void QtScriptCodeCompletion::cleanup() +{ + m_editor = 0; + m_startPosition = 0; + m_completions.clear(); +} + diff --git a/src/plugins/qtscripteditor/qtscriptcodecompletion.h b/src/plugins/qtscripteditor/qtscriptcodecompletion.h new file mode 100644 index 0000000000000000000000000000000000000000..a0650d5266ae07d80427e068aa2d000f31d6cbd4 --- /dev/null +++ b/src/plugins/qtscripteditor/qtscriptcodecompletion.h @@ -0,0 +1,43 @@ +#ifndef QTSCRIPTCODECOMPLETION_H +#define QTSCRIPTCODECOMPLETION_H + +#include <texteditor/icompletioncollector.h> + +namespace TextEditor { +class ITextEditable; +} + +namespace QtScriptEditor { +namespace Internal { + +class QtScriptCodeCompletion: public TextEditor::ICompletionCollector +{ + Q_OBJECT + +public: + QtScriptCodeCompletion(QObject *parent = 0); + virtual ~QtScriptCodeCompletion(); + + Qt::CaseSensitivity caseSensitivity() const; + void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); + + virtual bool isValid(TextEditor::ITextEditable *editor); + virtual bool triggersCompletion(TextEditor::ITextEditable *editor); + virtual int startCompletion(TextEditor::ITextEditable *editor); + virtual void completions(QList<TextEditor::CompletionItem> *completions); + virtual void complete(const TextEditor::CompletionItem &item); + virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems); + virtual void cleanup(); + +private: + TextEditor::ITextEditable *m_editor; + int m_startPosition; + QList<TextEditor::CompletionItem> m_completions; + Qt::CaseSensitivity m_caseSensitivity; +}; + + +} // end of namespace Internal +} // end of namespace QtScriptEditor + +#endif // QTSCRIPTCODECOMPLETION_H diff --git a/src/plugins/qtscripteditor/qtscripteditor.cpp b/src/plugins/qtscripteditor/qtscripteditor.cpp index 916567797ed99ce1da9046d560d103eb6caf40d0..14e77fb40edd9a6208ffec3f3377fb817e713b6e 100644 --- a/src/plugins/qtscripteditor/qtscripteditor.cpp +++ b/src/plugins/qtscripteditor/qtscripteditor.cpp @@ -166,6 +166,9 @@ ScriptEditor::~ScriptEditor() QList<Declaration> ScriptEditor::declarations() const { return m_declarations; } +QStringList ScriptEditor::words() const +{ return m_words; } + Core::IEditor *ScriptEditorEditable::duplicate(QWidget *parent) { ScriptEditor *newEditor = new ScriptEditor(m_context, parent); @@ -215,6 +218,10 @@ void ScriptEditor::updateDocumentNow() FindDeclarations decls; m_declarations = decls.accept(driver.ast()); + m_words.clear(); + foreach (const JavaScriptNameIdImpl &id, driver.literals()) + m_words.append(id.asString()); + QStringList items; items.append(tr("<Select Symbol>")); diff --git a/src/plugins/qtscripteditor/qtscripteditor.h b/src/plugins/qtscripteditor/qtscripteditor.h index dc6aa364b1178abedef299695a670c07c4da64b9..8042185796b71e59de102e1fd8d2e50c7873623c 100644 --- a/src/plugins/qtscripteditor/qtscripteditor.h +++ b/src/plugins/qtscripteditor/qtscripteditor.h @@ -91,6 +91,7 @@ public: ~ScriptEditor(); QList<Declaration> declarations() const; + QStringList words() const; public slots: virtual void setFontSettings(const TextEditor::FontSettings &); @@ -117,6 +118,7 @@ private: QTimer *m_updateDocumentTimer; QComboBox *m_methodCombo; QList<Declaration> m_declarations; + QStringList m_words; }; } // namespace Internal diff --git a/src/plugins/qtscripteditor/qtscripteditor.pro b/src/plugins/qtscripteditor/qtscripteditor.pro index 125b97e26c90d42798a5d20ba3631163c133c643..357e52df93d0e71b3799e832c510362259499a71 100644 --- a/src/plugins/qtscripteditor/qtscripteditor.pro +++ b/src/plugins/qtscripteditor/qtscripteditor.pro @@ -13,12 +13,14 @@ HEADERS += qtscripteditor.h \ qtscripteditorfactory.h \ qtscripteditorplugin.h \ qtscripthighlighter.h \ -qtscripteditoractionhandler.h +qtscripteditoractionhandler.h \ +qtscriptcodecompletion.h SOURCES += qtscripteditor.cpp \ qtscripteditorfactory.cpp \ qtscripteditorplugin.cpp \ qtscripthighlighter.cpp \ -qtscripteditoractionhandler.cpp +qtscripteditoractionhandler.cpp \ +qtscriptcodecompletion.cpp RESOURCES += qtscripteditor.qrc diff --git a/src/plugins/qtscripteditor/qtscripteditorplugin.cpp b/src/plugins/qtscripteditor/qtscripteditorplugin.cpp index b13ed76b8984ca92aa6cf7f6d1de4b99500c5ad2..eadf2711ea8c691abc5138d79318e1e223c30b96 100644 --- a/src/plugins/qtscripteditor/qtscripteditorplugin.cpp +++ b/src/plugins/qtscripteditor/qtscripteditorplugin.cpp @@ -33,6 +33,7 @@ #include "qtscripteditor.h" #include "qtscripteditorconstants.h" #include "qtscripteditorfactory.h" +#include "qtscriptcodecompletion.h" #include <coreplugin/icore.h> #include <coreplugin/coreconstants.h> @@ -46,10 +47,12 @@ #include <texteditor/texteditorsettings.h> #include <texteditor/textfilewizard.h> #include <texteditor/texteditoractionhandler.h> +#include <texteditor/completionsupport.h> #include <utils/qtcassert.h> #include <QtCore/QtPlugin> #include <QtCore/QDebug> +#include <QtCore/QSettings> #include <QtGui/QAction> using namespace QtScriptEditor::Internal; @@ -60,7 +63,8 @@ QtScriptEditorPlugin *QtScriptEditorPlugin::m_instance = 0; QtScriptEditorPlugin::QtScriptEditorPlugin() : m_wizard(0), m_editor(0), - m_actionHandler(0) + m_actionHandler(0), + m_completion(0) { m_instance = this; } @@ -105,6 +109,18 @@ bool QtScriptEditorPlugin::initialize(const QStringList & /*arguments*/, QString | TextEditor::TextEditorActionHandler::UnCommentSelection | TextEditor::TextEditorActionHandler::UnCollapseAll); + m_completion = new QtScriptCodeCompletion(); + addAutoReleasedObject(m_completion); + + // Restore settings + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(QLatin1String("CppTools")); // ### FIXME: + settings->beginGroup(QLatin1String("Completion")); + const bool caseSensitive = settings->value(QLatin1String("CaseSensitive"), true).toBool(); + m_completion->setCaseSensitivity(caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + settings->endGroup(); + settings->endGroup(); + error_message->clear(); return true; @@ -122,6 +138,10 @@ void QtScriptEditorPlugin::initializeEditor(QtScriptEditor::Internal::ScriptEdit m_actionHandler->setupActions(editor); TextEditor::TextEditorSettings::instance()->initializeEditor(editor); + + // auto completion + connect(editor, SIGNAL(requestAutoCompletion(ITextEditable*, bool)), + TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(ITextEditable*, bool))); } void QtScriptEditorPlugin::registerActions() diff --git a/src/plugins/qtscripteditor/qtscripteditorplugin.h b/src/plugins/qtscripteditor/qtscripteditorplugin.h index e43bb21c8a264807ca0d19161a788636ec6027be..4c1debb9fa11d7b36c9da4763331b2e9443607da 100644 --- a/src/plugins/qtscripteditor/qtscripteditorplugin.h +++ b/src/plugins/qtscripteditor/qtscripteditorplugin.h @@ -41,6 +41,7 @@ namespace QtScriptEditor { namespace Internal { class QtScriptEditorFactory; +class QtScriptCodeCompletion; class ScriptEditor; class QtScriptEditorPlugin : public ExtensionSystem::IPlugin @@ -72,6 +73,7 @@ private: TextEditor::TextFileWizard *m_wizard; QtScriptEditorFactory *m_editor; TextEditor::TextEditorActionHandler *m_actionHandler; + QtScriptCodeCompletion *m_completion; }; } // namespace Internal diff --git a/src/plugins/texteditor/completionsupport.cpp b/src/plugins/texteditor/completionsupport.cpp index 2e456193ad52f2af57952a6667f6e3a63f885ea7..ef4834c80883dc2fa35bec9a1e74d14d6c1bdddc 100644 --- a/src/plugins/texteditor/completionsupport.cpp +++ b/src/plugins/texteditor/completionsupport.cpp @@ -58,10 +58,11 @@ CompletionSupport::CompletionSupport() m_completionList(0), m_startPosition(0), m_checkCompletionTrigger(false), - m_editor(0) + m_editor(0), + m_completionCollector(0) { - m_completionCollector = ExtensionSystem::PluginManager::instance() - ->getObject<ICompletionCollector>(); + m_completionCollectors = ExtensionSystem::PluginManager::instance() + ->getObjects<ICompletionCollector>(); } void CompletionSupport::performCompletion(const CompletionItem &item) @@ -90,6 +91,15 @@ void CompletionSupport::cleanupCompletions() void CompletionSupport::autoComplete(ITextEditable *editor, bool forced) { + m_completionCollector = 0; + + foreach (ICompletionCollector *collector, m_completionCollectors) { + if (collector->isValid(editor)) { + m_completionCollector = collector; + break; + } + } + if (!m_completionCollector) return; diff --git a/src/plugins/texteditor/completionsupport.h b/src/plugins/texteditor/completionsupport.h index 7cbd5ece5b424a1951a3f08c9ef5700c84c38208..ebe9cbd70f3aeda30838eb540f867c2a1e28f06f 100644 --- a/src/plugins/texteditor/completionsupport.h +++ b/src/plugins/texteditor/completionsupport.h @@ -69,6 +69,7 @@ private: int m_startPosition; bool m_checkCompletionTrigger; // Whether to check for completion trigger after cleanup ITextEditable *m_editor; + QList<ICompletionCollector *> m_completionCollectors; ICompletionCollector *m_completionCollector; }; diff --git a/src/plugins/texteditor/icompletioncollector.h b/src/plugins/texteditor/icompletioncollector.h index 49d70f182883b2302cd16c1203b2216b3a39d749..a151e4cf41fd7d2451a3f18d65440ea23e1663f6 100644 --- a/src/plugins/texteditor/icompletioncollector.h +++ b/src/plugins/texteditor/icompletioncollector.h @@ -77,6 +77,11 @@ public: ICompletionCollector(QObject *parent = 0) : QObject(parent) {} virtual ~ICompletionCollector() {} + /* + * Returns true if this completion collector can be used with the given editor. + */ + virtual bool isValid(ITextEditable *editor) = 0; + /* This method should return whether the cursor is at a position which could * trigger an autocomplete. It will be called each time a character is typed in * the text editor. diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 141c7b547396283d785e298e0434d3c899e343bf..666d4c9a7085d25dc82e401edf2319beb71d6c7a 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -416,7 +416,8 @@ void testQObject(int &argc, char *argv[]) obs.append(&app); ob1.setObjectName("A Subobject"); */ - QLabel l("XXXXXXXXXXXXXXXXX"); + QString str = QString::fromUtf8("XXXXXXXXXXXXXXyyXXX ö"); + QLabel l(str); l.show(); app.exec(); } @@ -998,6 +999,7 @@ int main(int argc, char *argv[]) testIO(); testHidden(); testArray(); + testQByteArray(); testStdDeque(); testStdList(); @@ -1012,7 +1014,6 @@ int main(int argc, char *argv[]) testQLinkedList(); testNamespace(); //return 0; - testQByteArray(); testQHash(); testQImage(); testQMap();