forked from qt-creator/qt-creator
New code assist API
This is a re-work of our completion engine. Primary goals are: - Allow the computation to run in a separate thread so the GUI is not locked. - Support a model-based approach. QStrings are still needed (filtering, etc), but internal structures are free to use more efficient representations. - Unifiy all kinds of *assist* into a more reusable and extensible framework. - Remove unnecessary dependencies on the text editor so we have more generic and easily "plugable" components (still things to be resolved).
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "cppcompleteswitch.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <cplusplus/Overview.h>
|
||||
#include <cplusplus/TypeOfExpression.h>
|
||||
@@ -102,8 +103,11 @@ public:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, CompoundStatementAST *compoundStatement, const QStringList &values)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface,
|
||||
int priority,
|
||||
CompoundStatementAST *compoundStatement,
|
||||
const QStringList &values)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, compoundStatement(compoundStatement)
|
||||
, values(values)
|
||||
{
|
||||
@@ -150,15 +154,15 @@ static Enum *findEnum(const QList<LookupItem> &results,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Enum *conditionEnum(const CppQuickFixState &state,
|
||||
static Enum *conditionEnum(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface,
|
||||
SwitchStatementAST *statement)
|
||||
{
|
||||
Block *block = statement->symbol;
|
||||
Scope *scope = state.document()->scopeAt(block->line(), block->column());
|
||||
Scope *scope = interface->semanticInfo().doc->scopeAt(block->line(), block->column());
|
||||
TypeOfExpression typeOfExpression;
|
||||
typeOfExpression.init(state.document(), state.snapshot());
|
||||
typeOfExpression.init(interface->semanticInfo().doc, interface->snapshot());
|
||||
const QList<LookupItem> results = typeOfExpression(statement->condition,
|
||||
state.document(),
|
||||
interface->semanticInfo().doc,
|
||||
scope);
|
||||
|
||||
return findEnum(results, typeOfExpression.context());
|
||||
@@ -166,9 +170,10 @@ static Enum *conditionEnum(const CppQuickFixState &state,
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match(const CppQuickFixState &state)
|
||||
QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match(
|
||||
const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
if (path.isEmpty())
|
||||
return noResult(); // nothing to do
|
||||
@@ -178,13 +183,13 @@ QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match(const CppQui
|
||||
AST *ast = path.at(depth);
|
||||
SwitchStatementAST *switchStatement = ast->asSwitchStatement();
|
||||
if (switchStatement) {
|
||||
if (!state.isCursorOn(switchStatement->switch_token) || !switchStatement->statement)
|
||||
if (!interface->isCursorOn(switchStatement->switch_token) || !switchStatement->statement)
|
||||
return noResult();
|
||||
CompoundStatementAST *compoundStatement = switchStatement->statement->asCompoundStatement();
|
||||
if (!compoundStatement) // we ignore pathologic case "switch (t) case A: ;"
|
||||
return noResult();
|
||||
// look if the condition's type is an enum
|
||||
if (Enum *e = conditionEnum(state, switchStatement)) {
|
||||
if (Enum *e = conditionEnum(interface, switchStatement)) {
|
||||
// check the possible enum values
|
||||
QStringList values;
|
||||
Overview prettyPrint;
|
||||
@@ -195,8 +200,8 @@ QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match(const CppQui
|
||||
}
|
||||
// Get the used values
|
||||
Block *block = switchStatement->symbol;
|
||||
CaseStatementCollector caseValues(state.document(), state.snapshot(),
|
||||
state.document()->scopeAt(block->line(), block->column()));
|
||||
CaseStatementCollector caseValues(interface->semanticInfo().doc, interface->snapshot(),
|
||||
interface->semanticInfo().doc->scopeAt(block->line(), block->column()));
|
||||
QStringList usedValues = caseValues(switchStatement);
|
||||
// save the values that would be added
|
||||
foreach (const QString &usedValue, usedValues)
|
||||
@@ -204,7 +209,7 @@ QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match(const CppQui
|
||||
if (values.isEmpty())
|
||||
return noResult();
|
||||
else
|
||||
return singleResult(new Operation(state, depth, compoundStatement, values));
|
||||
return singleResult(new Operation(interface, depth, compoundStatement, values));
|
||||
}
|
||||
|
||||
return noResult();
|
||||
|
||||
@@ -46,7 +46,8 @@ namespace Internal {
|
||||
class CompleteSwitchCaseStatement: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(
|
||||
const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -35,11 +35,10 @@
|
||||
#include "cppplugin.h"
|
||||
#include "cpphighlighter.h"
|
||||
#include "cppchecksymbols.h"
|
||||
#include "cppquickfix.h"
|
||||
#include "cpplocalsymbols.h"
|
||||
#include "cppquickfixcollector.h"
|
||||
#include "cppqtstyleindenter.h"
|
||||
#include "cppautocompleter.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <AST.h>
|
||||
#include <Control.h>
|
||||
@@ -66,6 +65,7 @@
|
||||
#include <cpptools/cpptoolsplugin.h>
|
||||
#include <cpptools/cpptoolsconstants.h>
|
||||
#include <cpptools/cppcodeformatter.h>
|
||||
#include <cpptools/cppcompletionassist.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
@@ -83,6 +83,9 @@
|
||||
#include <texteditor/fontsettings.h>
|
||||
#include <texteditor/tabsettings.h>
|
||||
#include <texteditor/texteditorconstants.h>
|
||||
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
|
||||
#include <texteditor/codeassist/basicproposalitem.h>
|
||||
#include <texteditor/codeassist/genericproposal.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTime>
|
||||
@@ -1617,23 +1620,30 @@ void CPPEditorWidget::contextMenuEvent(QContextMenuEvent *e)
|
||||
QMenu *quickFixMenu = new QMenu(tr("&Refactor"), menu);
|
||||
quickFixMenu->addAction(am->command(Constants::RENAME_SYMBOL_UNDER_CURSOR)->action());
|
||||
|
||||
CppQuickFixCollector *quickFixCollector = CppPlugin::instance()->quickFixCollector();
|
||||
QSignalMapper mapper;
|
||||
connect(&mapper, SIGNAL(mapped(int)), this, SLOT(performQuickFix(int)));
|
||||
|
||||
if (! isOutdated()) {
|
||||
if (quickFixCollector->startCompletion(editor()) != -1) {
|
||||
m_quickFixes = quickFixCollector->quickFixes();
|
||||
|
||||
if (! m_quickFixes.isEmpty())
|
||||
quickFixMenu->addSeparator();
|
||||
|
||||
for (int index = 0; index < m_quickFixes.size(); ++index) {
|
||||
TextEditor::QuickFixOperation::Ptr op = m_quickFixes.at(index);
|
||||
TextEditor::IAssistInterface *interface =
|
||||
createAssistInterface(TextEditor::QuickFix, TextEditor::ExplicitlyInvoked);
|
||||
if (interface) {
|
||||
QScopedPointer<TextEditor::IAssistProcessor> processor(
|
||||
CppPlugin::instance()->quickFixProvider()->createProcessor());
|
||||
QScopedPointer<TextEditor::IAssistProposal> proposal(processor->perform(interface));
|
||||
if (!proposal.isNull()) {
|
||||
TextEditor::BasicProposalItemListModel *model =
|
||||
static_cast<TextEditor::BasicProposalItemListModel *>(proposal->model());
|
||||
for (int index = 0; index < model->size(); ++index) {
|
||||
TextEditor::BasicProposalItem *item =
|
||||
static_cast<TextEditor::BasicProposalItem *>(model->proposalItem(index));
|
||||
TextEditor::QuickFixOperation::Ptr op =
|
||||
item->data().value<TextEditor::QuickFixOperation::Ptr>();
|
||||
m_quickFixes.append(op);
|
||||
QAction *action = quickFixMenu->addAction(op->description());
|
||||
mapper.setMapping(action, index);
|
||||
connect(action, SIGNAL(triggered()), &mapper, SLOT(map()));
|
||||
}
|
||||
delete model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,7 +1656,6 @@ void CPPEditorWidget::contextMenuEvent(QContextMenuEvent *e)
|
||||
appendStandardContextMenuActions(menu);
|
||||
|
||||
menu->exec(e->globalPos());
|
||||
quickFixCollector->cleanup();
|
||||
m_quickFixes.clear();
|
||||
delete menu;
|
||||
}
|
||||
@@ -1921,6 +1930,7 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
|
||||
}
|
||||
|
||||
|
||||
|
||||
setExtraSelections(UnusedSymbolSelection, unusedSelections);
|
||||
|
||||
if (! m_renameSelections.isEmpty())
|
||||
@@ -2205,4 +2215,32 @@ QVector<QString> CPPEditorWidget::highlighterFormatCategories()
|
||||
return categories;
|
||||
}
|
||||
|
||||
TextEditor::IAssistInterface *CPPEditorWidget::createAssistInterface(
|
||||
TextEditor::AssistKind kind,
|
||||
TextEditor::AssistReason reason) const
|
||||
{
|
||||
if (kind == TextEditor::Completion) {
|
||||
QStringList includePaths;
|
||||
QStringList frameworkPaths;
|
||||
if (ProjectExplorer::Project *project =
|
||||
ProjectExplorer::ProjectExplorerPlugin::instance()->currentProject()) {
|
||||
includePaths = m_modelManager->projectInfo(project).includePaths;
|
||||
frameworkPaths = m_modelManager->projectInfo(project).frameworkPaths;
|
||||
}
|
||||
return new CppTools::Internal::CppCompletionAssistInterface(
|
||||
document(),
|
||||
position(),
|
||||
editor()->file(),
|
||||
reason,
|
||||
m_modelManager->snapshot(),
|
||||
includePaths,
|
||||
frameworkPaths);
|
||||
} else if (kind == TextEditor::QuickFix) {
|
||||
if (!semanticInfo().doc || semanticInfo().revision != editorRevision())
|
||||
return 0;
|
||||
return new CppQuickFixAssistInterface(const_cast<CPPEditorWidget *>(this), reason);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "cppeditor.moc"
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
#define CPPEDITOR_H
|
||||
|
||||
#include "cppeditorenums.h"
|
||||
#include "cppquickfix.h"
|
||||
#include "cppsemanticinfo.h"
|
||||
|
||||
#include <cplusplus/ModelManagerInterface.h>
|
||||
#include <cplusplus/CppDocument.h>
|
||||
#include <cplusplus/LookupContext.h>
|
||||
#include <texteditor/basetexteditor.h>
|
||||
#include <texteditor/quickfix.h>
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QMutex>
|
||||
@@ -189,6 +189,9 @@ public:
|
||||
|
||||
static QVector<QString> highlighterFormatCategories();
|
||||
|
||||
virtual TextEditor::IAssistInterface *createAssistInterface(TextEditor::AssistKind kind,
|
||||
TextEditor::AssistReason reason) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void outlineModelIndexChanged(const QModelIndex &index);
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ HEADERS += cppplugin.h \
|
||||
cppeditorenums.h \
|
||||
cppeditor_global.h \
|
||||
cppclasswizard.h \
|
||||
cppquickfix.h \
|
||||
cppchecksymbols.h \
|
||||
cppsemanticinfo.h \
|
||||
cppoutline.h \
|
||||
@@ -22,12 +21,13 @@ HEADERS += cppplugin.h \
|
||||
cpplocalsymbols.h \
|
||||
cpptypehierarchy.h \
|
||||
cppelementevaluator.h \
|
||||
cppquickfixcollector.h \
|
||||
cppqtstyleindenter.h \
|
||||
cppautocompleter.h \
|
||||
cppcompleteswitch.h \
|
||||
cppsnippetprovider.h \
|
||||
cppinsertqtpropertymembers.h
|
||||
cppinsertqtpropertymembers.h \
|
||||
cppquickfixassistant.h \
|
||||
cppquickfix.h
|
||||
|
||||
SOURCES += cppplugin.cpp \
|
||||
cppeditor.cpp \
|
||||
@@ -35,7 +35,6 @@ SOURCES += cppplugin.cpp \
|
||||
cpphoverhandler.cpp \
|
||||
cppfilewizard.cpp \
|
||||
cppclasswizard.cpp \
|
||||
cppquickfix.cpp \
|
||||
cppquickfixes.cpp \
|
||||
cppchecksymbols.cpp \
|
||||
cppsemanticinfo.cpp \
|
||||
@@ -44,12 +43,13 @@ SOURCES += cppplugin.cpp \
|
||||
cpplocalsymbols.cpp \
|
||||
cpptypehierarchy.cpp \
|
||||
cppelementevaluator.cpp \
|
||||
cppquickfixcollector.cpp \
|
||||
cppqtstyleindenter.cpp \
|
||||
cppautocompleter.cpp \
|
||||
cppcompleteswitch.cpp \
|
||||
cppsnippetprovider.cpp \
|
||||
cppinsertqtpropertymembers.cpp
|
||||
cppinsertqtpropertymembers.cpp \
|
||||
cppquickfixassistant.cpp \
|
||||
cppquickfix.cpp
|
||||
|
||||
RESOURCES += cppeditor.qrc
|
||||
OTHER_FILES += CppEditor.mimetypes.xml
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "cppinsertdecldef.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <CPlusPlus.h>
|
||||
#include <cplusplus/ASTPath.h>
|
||||
@@ -53,11 +54,12 @@ namespace {
|
||||
class InsertDeclOperation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
InsertDeclOperation(const CppQuickFixState &state, int priority,
|
||||
InsertDeclOperation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface,
|
||||
int priority,
|
||||
const QString &targetFileName, const Class *targetSymbol,
|
||||
InsertionPointLocator::AccessSpec xsSpec,
|
||||
const QString &decl)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, m_targetFileName(targetFileName)
|
||||
, m_targetSymbol(targetSymbol)
|
||||
, m_xsSpec(xsSpec)
|
||||
@@ -108,10 +110,11 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &state)
|
||||
QList<CppQuickFixOperation::Ptr> DeclFromDef::match(
|
||||
const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
FunctionDefinitionAST *funDef = 0;
|
||||
int idx = 0;
|
||||
@@ -158,7 +161,7 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat
|
||||
if (!q->base())
|
||||
return noResult();
|
||||
|
||||
if (ClassOrNamespace *binding = state.context().lookupType(q->base(), enclosingScope)) {
|
||||
if (ClassOrNamespace *binding = interface->context().lookupType(q->base(), enclosingScope)) {
|
||||
foreach (Symbol *s, binding->symbols()) {
|
||||
if (Class *matchingClass = s->asClass()) {
|
||||
for (Symbol *s = matchingClass->find(q->identifier()); s; s = s->next()) {
|
||||
@@ -177,11 +180,11 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat
|
||||
|
||||
const QString fn = QString::fromUtf8(matchingClass->fileName(),
|
||||
matchingClass->fileNameLength());
|
||||
const QString decl = generateDeclaration(state,
|
||||
const QString decl = generateDeclaration(interface,
|
||||
method,
|
||||
binding);
|
||||
return singleResult(
|
||||
new InsertDeclOperation(state, idx, fn, matchingClass,
|
||||
new InsertDeclOperation(interface, idx, fn, matchingClass,
|
||||
InsertionPointLocator::Public,
|
||||
decl));
|
||||
}
|
||||
@@ -191,7 +194,7 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat
|
||||
return noResult();
|
||||
}
|
||||
|
||||
QString DeclFromDef::generateDeclaration(const CppQuickFixState &,
|
||||
QString DeclFromDef::generateDeclaration(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &,
|
||||
Function *method,
|
||||
ClassOrNamespace *targetBinding)
|
||||
{
|
||||
@@ -214,9 +217,9 @@ namespace {
|
||||
class InsertDefOperation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
InsertDefOperation(const CppQuickFixState &state, int priority,
|
||||
InsertDefOperation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface, int priority,
|
||||
Declaration *decl, const InsertionLocation &loc)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, m_decl(decl)
|
||||
, m_loc(loc)
|
||||
{
|
||||
@@ -241,12 +244,12 @@ public:
|
||||
|
||||
//--
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(state().context());
|
||||
env.setContext(assistInterface()->context());
|
||||
env.switchScope(m_decl->enclosingScope());
|
||||
UseQualifiedNames q;
|
||||
env.enter(&q);
|
||||
|
||||
Control *control = state().context().control().data();
|
||||
Control *control = assistInterface()->context().control().data();
|
||||
FullySpecifiedType tn = rewriteType(m_decl->type(), &env, control);
|
||||
QString name = oo(LookupContext::fullyQualifiedName(m_decl));
|
||||
//--
|
||||
@@ -274,10 +277,11 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
QList<CppQuickFixOperation::Ptr> DefFromDecl::match(const CppQuickFixState &state)
|
||||
QList<CppQuickFixOperation::Ptr> DefFromDecl::match(
|
||||
const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
int idx = path.size() - 1;
|
||||
for (; idx >= 0; --idx) {
|
||||
@@ -292,12 +296,12 @@ QList<CppQuickFixOperation::Ptr> DefFromDecl::match(const CppQuickFixState &stat
|
||||
&& decl->enclosingScope()->isClass()) {
|
||||
DeclaratorAST *declarator = simpleDecl->declarator_list->value;
|
||||
if (file.isCursorOn(declarator->core_declarator)) {
|
||||
CppRefactoringChanges refactoring(state.snapshot());
|
||||
CppRefactoringChanges refactoring(interface->snapshot());
|
||||
InsertionPointLocator locator(&refactoring);
|
||||
QList<CppQuickFixOperation::Ptr> results;
|
||||
foreach (const InsertionLocation &loc, locator.methodDefinition(decl)) {
|
||||
if (loc.isValid())
|
||||
results.append(CppQuickFixOperation::Ptr(new InsertDefOperation(state, idx, decl, loc)));
|
||||
results.append(CppQuickFixOperation::Ptr(new InsertDefOperation(interface, idx, decl, loc)));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -47,10 +47,11 @@ namespace Internal {
|
||||
class DeclFromDef: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
|
||||
virtual QList<CppQuickFixOperation::Ptr>
|
||||
match(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface);
|
||||
|
||||
protected:
|
||||
static QString generateDeclaration(const CppQuickFixState &state,
|
||||
static QString generateDeclaration(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface,
|
||||
CPlusPlus::Function *method,
|
||||
CPlusPlus::ClassOrNamespace *targetBinding);
|
||||
};
|
||||
@@ -58,7 +59,8 @@ protected:
|
||||
class DefFromDecl: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
|
||||
virtual QList<CppQuickFixOperation::Ptr>
|
||||
match(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "cppinsertqtpropertymembers.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <AST.h>
|
||||
#include <Token.h>
|
||||
@@ -38,6 +39,7 @@
|
||||
#include <cpptools/insertionpointlocator.h>
|
||||
#include <cpptools/cpprefactoringchanges.h>
|
||||
#include <cppeditor/cppquickfix.h>
|
||||
#include <coreplugin/ifile.h>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
using namespace CppTools;
|
||||
@@ -46,9 +48,10 @@ using namespace Utils;
|
||||
using namespace CppEditor;
|
||||
using namespace CppEditor::Internal;
|
||||
|
||||
QList<CppQuickFixOperation::Ptr> InsertQtPropertyMembers::match(const CppQuickFixState &state)
|
||||
QList<CppQuickFixOperation::Ptr> InsertQtPropertyMembers::match(
|
||||
const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
if (path.isEmpty())
|
||||
return noResult();
|
||||
@@ -67,8 +70,8 @@ QList<CppQuickFixOperation::Ptr> InsertQtPropertyMembers::match(const CppQuickFi
|
||||
if (!klass)
|
||||
return noResult();
|
||||
|
||||
CppRefactoringChanges refactoring(state.snapshot());
|
||||
const CppRefactoringFile &file = refactoring.file(state.document()->fileName());
|
||||
CppRefactoringChanges refactoring(interface->snapshot());
|
||||
const CppRefactoringFile &file = refactoring.file(interface->file()->fileName());
|
||||
const QString propertyName = file.textOf(qtPropertyDeclaration->property_name);
|
||||
QString getterName;
|
||||
QString setterName;
|
||||
@@ -116,16 +119,17 @@ QList<CppQuickFixOperation::Ptr> InsertQtPropertyMembers::match(const CppQuickFi
|
||||
if (getterName.isEmpty() && setterName.isEmpty() && signalName.isEmpty())
|
||||
return noResult();
|
||||
|
||||
return singleResult(new Operation(state, path.size() - 1, qtPropertyDeclaration, c,
|
||||
return singleResult(new Operation(interface, path.size() - 1, qtPropertyDeclaration, c,
|
||||
generateFlags,
|
||||
getterName, setterName, signalName, storageName));
|
||||
}
|
||||
|
||||
InsertQtPropertyMembers::Operation::Operation(
|
||||
const CppQuickFixState &state, int priority, QtPropertyDeclarationAST *declaration, Class *klass,
|
||||
const QSharedPointer<const CppQuickFixAssistInterface> &interface,
|
||||
int priority, QtPropertyDeclarationAST *declaration, Class *klass,
|
||||
int generateFlags, const QString &getterName, const QString &setterName, const QString &signalName,
|
||||
const QString &storageName)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, m_declaration(declaration)
|
||||
, m_class(klass)
|
||||
, m_generateFlags(generateFlags)
|
||||
|
||||
@@ -62,7 +62,8 @@ class InsertQtPropertyMembers : public CppQuickFixFactory
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
|
||||
virtual QList<CppQuickFixOperation::Ptr>
|
||||
match(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface);
|
||||
|
||||
private:
|
||||
enum GenerateFlag {
|
||||
@@ -75,7 +76,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority,
|
||||
Operation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface,
|
||||
int priority,
|
||||
CPlusPlus::QtPropertyDeclarationAST *declaration, CPlusPlus::Class *klass,
|
||||
int generateFlags,
|
||||
const QString &getterName, const QString &setterName, const QString &signalName,
|
||||
|
||||
@@ -37,11 +37,10 @@
|
||||
#include "cppeditorenums.h"
|
||||
#include "cppfilewizard.h"
|
||||
#include "cpphoverhandler.h"
|
||||
#include "cppquickfix.h"
|
||||
#include "cppoutline.h"
|
||||
#include "cppquickfixcollector.h"
|
||||
#include "cpptypehierarchy.h"
|
||||
#include "cppsnippetprovider.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
@@ -54,7 +53,6 @@
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <coreplugin/navigationwidget.h>
|
||||
#include <texteditor/completionsupport.h>
|
||||
#include <texteditor/fontsettings.h>
|
||||
#include <texteditor/storagesettings.h>
|
||||
#include <texteditor/texteditoractionhandler.h>
|
||||
@@ -75,6 +73,8 @@
|
||||
using namespace CppEditor;
|
||||
using namespace CppEditor::Internal;
|
||||
|
||||
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
|
||||
|
||||
enum { QUICKFIX_INTERVAL = 20 };
|
||||
|
||||
//////////////////////////// CppEditorFactory /////////////////////////////
|
||||
@@ -149,15 +149,10 @@ CppPlugin::CppPlugin() :
|
||||
m_renameSymbolUnderCursorAction(0),
|
||||
m_findUsagesAction(0),
|
||||
m_updateCodeModelAction(0),
|
||||
m_openTypeHierarchyAction(0)
|
||||
m_openTypeHierarchyAction(0),
|
||||
m_quickFixProvider(0)
|
||||
{
|
||||
m_instance = this;
|
||||
|
||||
m_quickFixCollector = 0;
|
||||
m_quickFixTimer = new QTimer(this);
|
||||
m_quickFixTimer->setInterval(20);
|
||||
m_quickFixTimer->setSingleShot(true);
|
||||
connect(m_quickFixTimer, SIGNAL(timeout()), this, SLOT(quickFixNow()));
|
||||
}
|
||||
|
||||
CppPlugin::~CppPlugin()
|
||||
@@ -193,8 +188,10 @@ bool CppPlugin::sortedOutline() const
|
||||
return m_sortedOutline;
|
||||
}
|
||||
|
||||
CppQuickFixCollector *CppPlugin::quickFixCollector() const
|
||||
{ return m_quickFixCollector; }
|
||||
CppQuickFixAssistProvider *CppPlugin::quickFixProvider() const
|
||||
{
|
||||
return m_quickFixProvider;
|
||||
}
|
||||
|
||||
bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage)
|
||||
{
|
||||
@@ -209,9 +206,9 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
|
||||
addAutoReleasedObject(new CppTypeHierarchyFactory);
|
||||
addAutoReleasedObject(new CppSnippetProvider);
|
||||
|
||||
m_quickFixCollector = new CppQuickFixCollector;
|
||||
addAutoReleasedObject(m_quickFixCollector);
|
||||
CppQuickFixCollector::registerQuickFixes(this);
|
||||
m_quickFixProvider = new CppQuickFixAssistProvider;
|
||||
addAutoReleasedObject(m_quickFixProvider);
|
||||
registerQuickFixes(this);
|
||||
|
||||
CppFileWizard::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard);
|
||||
|
||||
@@ -380,31 +377,6 @@ void CppPlugin::findUsages()
|
||||
editor->findUsages();
|
||||
}
|
||||
|
||||
void CppPlugin::quickFix(TextEditor::ITextEditor *editor)
|
||||
{
|
||||
m_currentEditor = editor;
|
||||
quickFixNow();
|
||||
}
|
||||
|
||||
void CppPlugin::quickFixNow()
|
||||
{
|
||||
if (! m_currentEditor)
|
||||
return;
|
||||
|
||||
Core::EditorManager *em = Core::EditorManager::instance();
|
||||
CPPEditorWidget *currentEditor = qobject_cast<CPPEditorWidget*>(em->currentEditor()->widget());
|
||||
|
||||
if (CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(m_currentEditor->widget())) {
|
||||
if (currentEditor == editor) {
|
||||
if (editor->isOutdated())
|
||||
m_quickFixTimer->start(QUICKFIX_INTERVAL);
|
||||
else
|
||||
TextEditor::CompletionSupport::instance()->
|
||||
complete(m_currentEditor, TextEditor::QuickFixCompletion, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CppPlugin::onTaskStarted(const QString &type)
|
||||
{
|
||||
if (type == CppTools::Constants::TASK_INDEX) {
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace Internal {
|
||||
|
||||
class CPPEditorWidget;
|
||||
class CppQuickFixCollector;
|
||||
class CppQuickFixAssistProvider;
|
||||
|
||||
class CppPlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
@@ -70,7 +71,7 @@ public:
|
||||
|
||||
bool sortedOutline() const;
|
||||
|
||||
CppQuickFixCollector *quickFixCollector() const;
|
||||
CppQuickFixAssistProvider *quickFixProvider() const;
|
||||
|
||||
signals:
|
||||
void outlineSortingChanged(bool sort);
|
||||
@@ -86,8 +87,6 @@ private slots:
|
||||
void onTaskStarted(const QString &type);
|
||||
void onAllTasksFinished(const QString &type);
|
||||
void findUsages();
|
||||
void quickFix(TextEditor::ITextEditor *editable);
|
||||
void quickFixNow();
|
||||
void currentEditorChanged(Core::IEditor *editor);
|
||||
void openTypeHierarchy();
|
||||
|
||||
@@ -105,9 +104,8 @@ private:
|
||||
QAction *m_updateCodeModelAction;
|
||||
QAction *m_openTypeHierarchyAction;
|
||||
|
||||
CppQuickFixCollector *m_quickFixCollector;
|
||||
CppQuickFixAssistProvider *m_quickFixProvider;
|
||||
|
||||
QTimer *m_quickFixTimer;
|
||||
QPointer<TextEditor::ITextEditor> m_currentEditor;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#include "cppquickfix.h"
|
||||
#include "cppeditor.h"
|
||||
#include "cppquickfixcollector.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <AST.h>
|
||||
#include <TranslationUnit.h>
|
||||
@@ -58,53 +58,10 @@ using namespace TextEditor;
|
||||
using namespace CPlusPlus;
|
||||
using namespace Utils;
|
||||
|
||||
CppQuickFixState::CppQuickFixState(TextEditor::BaseTextEditorWidget *editor)
|
||||
: QuickFixState(editor)
|
||||
{}
|
||||
|
||||
const QList<AST *> &CppQuickFixState::path() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
Snapshot CppQuickFixState::snapshot() const
|
||||
{
|
||||
return _snapshot;
|
||||
}
|
||||
|
||||
Document::Ptr CppQuickFixState::document() const
|
||||
{
|
||||
return _semanticInfo.doc;
|
||||
}
|
||||
|
||||
SemanticInfo CppQuickFixState::semanticInfo() const
|
||||
{
|
||||
return _semanticInfo;
|
||||
}
|
||||
|
||||
const LookupContext &CppQuickFixState::context() const
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
const CppRefactoringFile CppQuickFixState::currentFile() const
|
||||
{
|
||||
return CppRefactoringFile(editor(), document());
|
||||
}
|
||||
|
||||
bool CppQuickFixState::isCursorOn(unsigned tokenIndex) const
|
||||
{
|
||||
return currentFile().isCursorOn(tokenIndex);
|
||||
}
|
||||
|
||||
bool CppQuickFixState::isCursorOn(const CPlusPlus::AST *ast) const
|
||||
{
|
||||
return currentFile().isCursorOn(ast);
|
||||
}
|
||||
|
||||
CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority)
|
||||
CppQuickFixOperation::CppQuickFixOperation(
|
||||
const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority)
|
||||
: QuickFixOperation(priority)
|
||||
, _state(state)
|
||||
, m_interface(interface)
|
||||
{}
|
||||
|
||||
CppQuickFixOperation::~CppQuickFixOperation()
|
||||
@@ -112,19 +69,21 @@ CppQuickFixOperation::~CppQuickFixOperation()
|
||||
|
||||
void CppQuickFixOperation::perform()
|
||||
{
|
||||
CppRefactoringChanges refactoring(_state.snapshot());
|
||||
CppRefactoringChanges refactoring(m_interface->snapshot());
|
||||
CppRefactoringFile current = refactoring.file(fileName());
|
||||
|
||||
performChanges(¤t, &refactoring);
|
||||
}
|
||||
|
||||
const CppQuickFixState &CppQuickFixOperation::state() const
|
||||
const CppQuickFixAssistInterface *CppQuickFixOperation::assistInterface() const
|
||||
{
|
||||
return _state;
|
||||
return m_interface.data();
|
||||
}
|
||||
|
||||
QString CppQuickFixOperation::fileName() const
|
||||
{ return state().document()->fileName(); }
|
||||
{
|
||||
return m_interface->file()->fileName();
|
||||
}
|
||||
|
||||
CppQuickFixFactory::CppQuickFixFactory()
|
||||
{
|
||||
@@ -134,12 +93,14 @@ CppQuickFixFactory::~CppQuickFixFactory()
|
||||
{
|
||||
}
|
||||
|
||||
QList<QuickFixOperation::Ptr> CppQuickFixFactory::matchingOperations(QuickFixState *state)
|
||||
QList<QuickFixOperation::Ptr> CppQuickFixFactory::matchingOperations(
|
||||
const QSharedPointer<const TextEditor::IAssistInterface> &interface)
|
||||
{
|
||||
if (CppQuickFixState *cppState = static_cast<CppQuickFixState *>(state))
|
||||
return match(*cppState);
|
||||
else
|
||||
return QList<TextEditor::QuickFixOperation::Ptr>();
|
||||
QSharedPointer<const CppQuickFixAssistInterface> cppInterface =
|
||||
interface.staticCast<const CppQuickFixAssistInterface>();
|
||||
if (cppInterface->path().isEmpty())
|
||||
return QList<QuickFixOperation::Ptr>();
|
||||
return match(cppInterface);
|
||||
}
|
||||
|
||||
QList<CppQuickFixOperation::Ptr> CppQuickFixFactory::singleResult(CppQuickFixOperation *operation)
|
||||
|
||||
@@ -53,40 +53,17 @@ class IPlugin;
|
||||
namespace CppEditor {
|
||||
|
||||
namespace Internal {
|
||||
class CppQuickFixCollector;
|
||||
} // namespace Internal
|
||||
|
||||
class CPPEDITOR_EXPORT CppQuickFixState: public TextEditor::QuickFixState
|
||||
{
|
||||
friend class Internal::CppQuickFixCollector;
|
||||
|
||||
public:
|
||||
CppQuickFixState(TextEditor::BaseTextEditorWidget *editor);
|
||||
|
||||
const QList<CPlusPlus::AST *> &path() const;
|
||||
CPlusPlus::Snapshot snapshot() const;
|
||||
CPlusPlus::Document::Ptr document() const;
|
||||
CppEditor::Internal::SemanticInfo semanticInfo() const;
|
||||
const CPlusPlus::LookupContext &context() const;
|
||||
|
||||
const CppTools::CppRefactoringFile currentFile() const;
|
||||
|
||||
bool isCursorOn(unsigned tokenIndex) const;
|
||||
bool isCursorOn(const CPlusPlus::AST *ast) const;
|
||||
|
||||
private:
|
||||
QList<CPlusPlus::AST *> _path;
|
||||
CPlusPlus::Snapshot _snapshot;
|
||||
CppEditor::Internal::SemanticInfo _semanticInfo;
|
||||
CPlusPlus::LookupContext _context;
|
||||
};
|
||||
class CppQuickFixAssistInterface;
|
||||
}
|
||||
|
||||
class CPPEDITOR_EXPORT CppQuickFixOperation: public TextEditor::QuickFixOperation
|
||||
{
|
||||
Q_DISABLE_COPY(CppQuickFixOperation)
|
||||
|
||||
public:
|
||||
explicit CppQuickFixOperation(const CppQuickFixState &state, int priority = -1);
|
||||
explicit CppQuickFixOperation(
|
||||
const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface,
|
||||
int priority = -1);
|
||||
virtual ~CppQuickFixOperation();
|
||||
|
||||
virtual void perform();
|
||||
@@ -97,10 +74,10 @@ protected:
|
||||
|
||||
QString fileName() const;
|
||||
|
||||
const CppQuickFixState &state() const;
|
||||
const Internal::CppQuickFixAssistInterface *assistInterface() const;
|
||||
|
||||
private:
|
||||
CppQuickFixState _state;
|
||||
QSharedPointer<const Internal::CppQuickFixAssistInterface> m_interface;
|
||||
};
|
||||
|
||||
class CPPEDITOR_EXPORT CppQuickFixFactory: public TextEditor::QuickFixFactory
|
||||
@@ -111,12 +88,15 @@ public:
|
||||
CppQuickFixFactory();
|
||||
virtual ~CppQuickFixFactory();
|
||||
|
||||
virtual QList<TextEditor::QuickFixOperation::Ptr> matchingOperations(TextEditor::QuickFixState *state);
|
||||
virtual QList<TextEditor::QuickFixOperation::Ptr>
|
||||
matchingOperations(const QSharedPointer<const TextEditor::IAssistInterface> &interface);
|
||||
|
||||
/*!
|
||||
Implement this method to match and create the appropriate
|
||||
CppQuickFixOperation objects.
|
||||
*/
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state) = 0;
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(
|
||||
const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface) = 0;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "cppquickfixassistant.h"
|
||||
#include "cppeditorconstants.h"
|
||||
#include "cppeditor.h"
|
||||
|
||||
// @TODO: temp
|
||||
#include "cppquickfix.h"
|
||||
|
||||
#include <AST.h>
|
||||
#include <TranslationUnit.h>
|
||||
#include <Token.h>
|
||||
|
||||
#include <cplusplus/ASTPath.h>
|
||||
#include <cplusplus/CppDocument.h>
|
||||
#include <cplusplus/ResolveExpression.h>
|
||||
#include <cplusplus/Overview.h>
|
||||
#include <cplusplus/TypeOfExpression.h>
|
||||
#include <cplusplus/DependencyTable.h>
|
||||
#include <cplusplus/CppRewriter.h>
|
||||
|
||||
#include <cpptools/cpprefactoringchanges.h>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QTextBlock>
|
||||
|
||||
using namespace CppEditor;
|
||||
using namespace CppEditor::Internal;
|
||||
using namespace TextEditor;
|
||||
using namespace CppTools;
|
||||
using namespace CPlusPlus;
|
||||
|
||||
// -------------------------
|
||||
// CppQuickFixAssistProvider
|
||||
// -------------------------
|
||||
bool CppQuickFixAssistProvider::supportsEditor(const QString &editorId) const
|
||||
{
|
||||
return editorId == QLatin1String(CppEditor::Constants::CPPEDITOR_ID);
|
||||
}
|
||||
|
||||
IAssistProcessor *CppQuickFixAssistProvider::createProcessor() const
|
||||
{
|
||||
return new CppQuickFixAssistProcessor(this);
|
||||
}
|
||||
|
||||
QList<TextEditor::QuickFixFactory *> CppQuickFixAssistProvider::quickFixFactories() const
|
||||
{
|
||||
QList<TextEditor::QuickFixFactory *> results;
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
foreach (CppQuickFixFactory *f, pm->getObjects<CppEditor::CppQuickFixFactory>())
|
||||
results.append(f);
|
||||
return results;
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// CppQuickFixAssistProcessor
|
||||
// --------------------------
|
||||
CppQuickFixAssistProcessor::CppQuickFixAssistProcessor(const IAssistProvider *provider)
|
||||
: m_provider(provider)
|
||||
{}
|
||||
|
||||
const IAssistProvider *CppQuickFixAssistProcessor::provider() const
|
||||
{
|
||||
return m_provider;
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// CppQuickFixAssistInterface
|
||||
// --------------------------
|
||||
CppQuickFixAssistInterface::CppQuickFixAssistInterface(CPPEditorWidget *editor,
|
||||
TextEditor::AssistReason reason)
|
||||
: DefaultAssistInterface(editor->document(), editor->position(), editor->file(), reason)
|
||||
, m_editor(editor)
|
||||
, m_semanticInfo(editor->semanticInfo())
|
||||
, m_snapshot(CPlusPlus::CppModelManagerInterface::instance()->snapshot())
|
||||
, m_context(m_semanticInfo.doc, m_snapshot)
|
||||
{
|
||||
CPlusPlus::ASTPath astPath(m_semanticInfo.doc);
|
||||
m_path = astPath(editor->textCursor());
|
||||
}
|
||||
|
||||
const QList<AST *> &CppQuickFixAssistInterface::path() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
Snapshot CppQuickFixAssistInterface::snapshot() const
|
||||
{
|
||||
return m_snapshot;
|
||||
}
|
||||
|
||||
SemanticInfo CppQuickFixAssistInterface::semanticInfo() const
|
||||
{
|
||||
return m_semanticInfo;
|
||||
}
|
||||
|
||||
const LookupContext &CppQuickFixAssistInterface::context() const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
CPPEditorWidget *CppQuickFixAssistInterface::editor() const
|
||||
{
|
||||
return m_editor;
|
||||
}
|
||||
|
||||
const CppRefactoringFile CppQuickFixAssistInterface::currentFile() const
|
||||
{
|
||||
return CppRefactoringFile(m_editor, m_semanticInfo.doc);
|
||||
}
|
||||
|
||||
bool CppQuickFixAssistInterface::isCursorOn(unsigned tokenIndex) const
|
||||
{
|
||||
return currentFile().isCursorOn(tokenIndex);
|
||||
}
|
||||
|
||||
bool CppQuickFixAssistInterface::isCursorOn(const CPlusPlus::AST *ast) const
|
||||
{
|
||||
return currentFile().isCursorOn(ast);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CPPQUICKFIXASSISTANT_H
|
||||
#define CPPQUICKFIXASSISTANT_H
|
||||
|
||||
#include "cppsemanticinfo.h"
|
||||
|
||||
#include <ASTfwd.h>
|
||||
#include <cplusplus/CppDocument.h>
|
||||
|
||||
#include <texteditor/codeassist/defaultassistinterface.h>
|
||||
#include <texteditor/codeassist/quickfixassistprovider.h>
|
||||
#include <texteditor/codeassist/quickfixassistprocessor.h>
|
||||
|
||||
namespace CppTools {
|
||||
class CppRefactoringFile;
|
||||
}
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
class CPPEditorWidget;
|
||||
|
||||
class CppQuickFixAssistInterface : public TextEditor::DefaultAssistInterface
|
||||
{
|
||||
public:
|
||||
CppQuickFixAssistInterface(CPPEditorWidget *editor, TextEditor::AssistReason reason);
|
||||
|
||||
const QList<CPlusPlus::AST *> &path() const;
|
||||
CPlusPlus::Snapshot snapshot() const;
|
||||
CppEditor::Internal::SemanticInfo semanticInfo() const;
|
||||
const CPlusPlus::LookupContext &context() const;
|
||||
CPPEditorWidget *editor() const;
|
||||
|
||||
const CppTools::CppRefactoringFile currentFile() const;
|
||||
|
||||
bool isCursorOn(unsigned tokenIndex) const;
|
||||
bool isCursorOn(const CPlusPlus::AST *ast) const;
|
||||
|
||||
private:
|
||||
CPPEditorWidget *m_editor;
|
||||
CppEditor::Internal::SemanticInfo m_semanticInfo;
|
||||
CPlusPlus::Snapshot m_snapshot;
|
||||
CPlusPlus::LookupContext m_context;
|
||||
QList<CPlusPlus::AST *> m_path;
|
||||
};
|
||||
|
||||
class CppQuickFixAssistProcessor : public TextEditor::QuickFixAssistProcessor
|
||||
{
|
||||
public:
|
||||
CppQuickFixAssistProcessor(const TextEditor::IAssistProvider *provider);
|
||||
|
||||
virtual const TextEditor::IAssistProvider *provider() const;
|
||||
|
||||
private:
|
||||
const TextEditor::IAssistProvider *m_provider;
|
||||
};
|
||||
|
||||
class CppQuickFixAssistProvider : public TextEditor::QuickFixAssistProvider
|
||||
{
|
||||
public:
|
||||
virtual bool supportsEditor(const QString &editorId) const;
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
|
||||
virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // CppEditor
|
||||
|
||||
#endif // CPPQUICKFIXASSISTANT_H
|
||||
@@ -1,100 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "cppquickfixcollector.h"
|
||||
#include "cppeditor.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <cplusplus/ModelManagerInterface.h>
|
||||
#include <cpptools/cpprefactoringchanges.h>
|
||||
#include <cpptools/cpptoolsconstants.h>
|
||||
|
||||
#include <AST.h>
|
||||
#include <cplusplus/ASTPath.h>
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
CppQuickFixCollector::CppQuickFixCollector()
|
||||
{
|
||||
}
|
||||
|
||||
CppQuickFixCollector::~CppQuickFixCollector()
|
||||
{
|
||||
}
|
||||
|
||||
bool CppQuickFixCollector::supportsEditor(TextEditor::ITextEditor *editor) const
|
||||
{
|
||||
return CPlusPlus::CppModelManagerInterface::instance()->isCppEditor(editor);
|
||||
}
|
||||
|
||||
TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditorWidget *editor)
|
||||
{
|
||||
if (CPPEditorWidget *cppEditor = qobject_cast<CPPEditorWidget *>(editor)) {
|
||||
const SemanticInfo info = cppEditor->semanticInfo();
|
||||
|
||||
if (info.revision != cppEditor->editorRevision()) {
|
||||
// outdated
|
||||
qWarning() << "TODO: outdated semantic info, force a reparse.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.doc) {
|
||||
CPlusPlus::ASTPath astPath(info.doc);
|
||||
|
||||
const QList<CPlusPlus::AST *> path = astPath(cppEditor->textCursor());
|
||||
if (! path.isEmpty()) {
|
||||
CppQuickFixState *state = new CppQuickFixState(editor);
|
||||
state->_path = path;
|
||||
state->_semanticInfo = info;
|
||||
state->_snapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot();
|
||||
state->_context = CPlusPlus::LookupContext(info.doc, state->snapshot());
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<TextEditor::QuickFixFactory *> CppQuickFixCollector::quickFixFactories() const
|
||||
{
|
||||
QList<TextEditor::QuickFixFactory *> results;
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
foreach (CppQuickFixFactory *f, pm->getObjects<CppEditor::CppQuickFixFactory>())
|
||||
results.append(f);
|
||||
return results;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppEditor
|
||||
@@ -35,7 +35,8 @@
|
||||
#include "cppquickfix.h"
|
||||
#include "cppinsertdecldef.h"
|
||||
#include "cppinsertqtpropertymembers.h"
|
||||
#include "cppquickfixcollector.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
#include "cppcompleteswitch.h"
|
||||
|
||||
#include <ASTVisitor.h>
|
||||
#include <AST.h>
|
||||
@@ -85,17 +86,17 @@ namespace {
|
||||
class UseInverseOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
QList<CppQuickFixOperation::Ptr> result;
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
int index = path.size() - 1;
|
||||
BinaryExpressionAST *binary = path.at(index)->asBinaryExpression();
|
||||
if (! binary)
|
||||
return result;
|
||||
if (! state.isCursorOn(binary->binary_op_token))
|
||||
if (! interface->isCursorOn(binary->binary_op_token))
|
||||
return result;
|
||||
|
||||
Kind invertToken;
|
||||
@@ -122,7 +123,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
result.append(CppQuickFixOperation::Ptr(new Operation(state, index, binary, invertToken)));
|
||||
result.append(CppQuickFixOperation::Ptr(new Operation(interface, index, binary, invertToken)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -136,8 +137,9 @@ private:
|
||||
QString replacement;
|
||||
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, BinaryExpressionAST *binary, Kind invertToken)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface,
|
||||
int priority, BinaryExpressionAST *binary, Kind invertToken)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, binary(binary), nested(0), negation(0)
|
||||
{
|
||||
Token tok;
|
||||
@@ -146,12 +148,12 @@ private:
|
||||
|
||||
// check for enclosing nested expression
|
||||
if (priority - 1 >= 0)
|
||||
nested = state.path()[priority - 1]->asNestedExpression();
|
||||
nested = interface->path()[priority - 1]->asNestedExpression();
|
||||
|
||||
// check for ! before parentheses
|
||||
if (nested && priority - 2 >= 0) {
|
||||
negation = state.path()[priority - 2]->asUnaryExpression();
|
||||
if (negation && ! state.currentFile().tokenAt(negation->unary_op_token).is(T_EXCLAIM))
|
||||
negation = interface->path()[priority - 2]->asUnaryExpression();
|
||||
if (negation && ! interface->currentFile().tokenAt(negation->unary_op_token).is(T_EXCLAIM))
|
||||
negation = 0;
|
||||
}
|
||||
}
|
||||
@@ -191,17 +193,17 @@ private:
|
||||
class FlipBinaryOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<QuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<QuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
QList<QuickFixOperation::Ptr> result;
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
int index = path.size() - 1;
|
||||
BinaryExpressionAST *binary = path.at(index)->asBinaryExpression();
|
||||
if (! binary)
|
||||
return result;
|
||||
if (! state.isCursorOn(binary->binary_op_token))
|
||||
if (! interface->isCursorOn(binary->binary_op_token))
|
||||
return result;
|
||||
|
||||
Kind flipToken;
|
||||
@@ -235,7 +237,7 @@ public:
|
||||
replacement = QLatin1String(tok.spell());
|
||||
}
|
||||
|
||||
result.append(QuickFixOperation::Ptr(new Operation(state, index, binary, replacement)));
|
||||
result.append(QuickFixOperation::Ptr(new Operation(interface, index, binary, replacement)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -243,8 +245,9 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, BinaryExpressionAST *binary, QString replacement)
|
||||
: CppQuickFixOperation(state)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface,
|
||||
int priority, BinaryExpressionAST *binary, QString replacement)
|
||||
: CppQuickFixOperation(interface)
|
||||
, binary(binary)
|
||||
, replacement(replacement)
|
||||
{
|
||||
@@ -288,12 +291,12 @@ private:
|
||||
class RewriteLogicalAndOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<QuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<QuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
QList<QuickFixOperation::Ptr> result;
|
||||
BinaryExpressionAST *expression = 0;
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
int index = path.size() - 1;
|
||||
for (; index != -1; --index) {
|
||||
@@ -305,10 +308,10 @@ public:
|
||||
if (! expression)
|
||||
return result;
|
||||
|
||||
if (! state.isCursorOn(expression->binary_op_token))
|
||||
if (! interface->isCursorOn(expression->binary_op_token))
|
||||
return result;
|
||||
|
||||
QSharedPointer<Operation> op(new Operation(state));
|
||||
QSharedPointer<Operation> op(new Operation(interface));
|
||||
|
||||
if (expression->match(op->pattern, &matcher) &&
|
||||
file.tokenAt(op->pattern->binary_op_token).is(T_AMPER_AMPER) &&
|
||||
@@ -331,8 +334,8 @@ private:
|
||||
UnaryExpressionAST *right;
|
||||
BinaryExpressionAST *pattern;
|
||||
|
||||
Operation(const CppQuickFixState &state)
|
||||
: CppQuickFixOperation(state)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
: CppQuickFixOperation(interface)
|
||||
, mk(new ASTPatternBuilder)
|
||||
{
|
||||
left = mk->UnaryExpression();
|
||||
@@ -400,12 +403,12 @@ class SplitSimpleDeclarationOp: public CppQuickFixFactory
|
||||
}
|
||||
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
QList<CppQuickFixOperation::Ptr> result;
|
||||
CoreDeclaratorAST *core_declarator = 0;
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
for (int index = path.size() - 1; index != -1; --index) {
|
||||
AST *node = path.at(index);
|
||||
@@ -424,12 +427,12 @@ public:
|
||||
|
||||
if (cursorPosition >= startOfDeclSpecifier && cursorPosition <= endOfDeclSpecifier) {
|
||||
// the AST node under cursor is a specifier.
|
||||
return singleResult(new Operation(state, index, declaration));
|
||||
return singleResult(new Operation(interface, index, declaration));
|
||||
}
|
||||
|
||||
if (core_declarator && state.isCursorOn(core_declarator)) {
|
||||
if (core_declarator && interface->isCursorOn(core_declarator)) {
|
||||
// got a core-declarator under the text cursor.
|
||||
return singleResult(new Operation(state, index, declaration));
|
||||
return singleResult(new Operation(interface, index, declaration));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,8 +447,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, SimpleDeclarationAST *decl)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, SimpleDeclarationAST *decl)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, declaration(decl)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||
@@ -503,16 +506,16 @@ private:
|
||||
class AddBracesToIfOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
// show when we're on the 'if' of an if statement
|
||||
int index = path.size() - 1;
|
||||
IfStatementAST *ifStatement = path.at(index)->asIfStatement();
|
||||
if (ifStatement && state.isCursorOn(ifStatement->if_token) && ifStatement->statement
|
||||
if (ifStatement && interface->isCursorOn(ifStatement->if_token) && ifStatement->statement
|
||||
&& ! ifStatement->statement->asCompoundStatement()) {
|
||||
return singleResult(new Operation(state, index, ifStatement->statement));
|
||||
return singleResult(new Operation(interface, index, ifStatement->statement));
|
||||
}
|
||||
|
||||
// or if we're on the statement contained in the if
|
||||
@@ -520,9 +523,9 @@ public:
|
||||
for (; index != -1; --index) {
|
||||
IfStatementAST *ifStatement = path.at(index)->asIfStatement();
|
||||
if (ifStatement && ifStatement->statement
|
||||
&& state.isCursorOn(ifStatement->statement)
|
||||
&& interface->isCursorOn(ifStatement->statement)
|
||||
&& ! ifStatement->statement->asCompoundStatement()) {
|
||||
return singleResult(new Operation(state, index, ifStatement->statement));
|
||||
return singleResult(new Operation(interface, index, ifStatement->statement));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,8 +539,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, StatementAST *statement)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, StatementAST *statement)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, _statement(statement)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||
@@ -576,10 +579,10 @@ private:
|
||||
class MoveDeclarationOutOfIfOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
QSharedPointer<Operation> op(new Operation(state));
|
||||
const QList<AST *> &path = interface->path();
|
||||
QSharedPointer<Operation> op(new Operation(interface));
|
||||
|
||||
int index = path.size() - 1;
|
||||
for (; index != -1; --index) {
|
||||
@@ -590,7 +593,7 @@ public:
|
||||
if (! op->core)
|
||||
return noResult();
|
||||
|
||||
if (state.isCursorOn(op->core)) {
|
||||
if (interface->isCursorOn(op->core)) {
|
||||
QList<CppQuickFixOperation::Ptr> result;
|
||||
op->setPriority(index);
|
||||
result.append(op);
|
||||
@@ -607,8 +610,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state)
|
||||
: CppQuickFixOperation(state)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
: CppQuickFixOperation(interface)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||
"Move Declaration out of Condition"));
|
||||
@@ -653,10 +656,10 @@ private:
|
||||
class MoveDeclarationOutOfWhileOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
QSharedPointer<Operation> op(new Operation(state));
|
||||
const QList<AST *> &path = interface->path();
|
||||
QSharedPointer<Operation> op(new Operation(interface));
|
||||
|
||||
int index = path.size() - 1;
|
||||
for (; index != -1; --index) {
|
||||
@@ -674,7 +677,7 @@ public:
|
||||
else if (! declarator->initializer)
|
||||
return noResult();
|
||||
|
||||
if (state.isCursorOn(op->core)) {
|
||||
if (interface->isCursorOn(op->core)) {
|
||||
QList<CppQuickFixOperation::Ptr> result;
|
||||
op->setPriority(index);
|
||||
result.append(op);
|
||||
@@ -691,8 +694,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state)
|
||||
: CppQuickFixOperation(state)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
: CppQuickFixOperation(interface)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||
"Move Declaration out of Condition"));
|
||||
@@ -753,10 +756,10 @@ private:
|
||||
class SplitIfStatementOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
IfStatementAST *pattern = 0;
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
int index = path.size() - 1;
|
||||
for (; index != -1; --index) {
|
||||
@@ -777,7 +780,7 @@ public:
|
||||
if (! condition)
|
||||
return noResult();
|
||||
|
||||
Token binaryToken = state.currentFile().tokenAt(condition->binary_op_token);
|
||||
Token binaryToken = interface->currentFile().tokenAt(condition->binary_op_token);
|
||||
|
||||
// only accept a chain of ||s or &&s - no mixing
|
||||
if (! splitKind) {
|
||||
@@ -791,8 +794,8 @@ public:
|
||||
return noResult();
|
||||
}
|
||||
|
||||
if (state.isCursorOn(condition->binary_op_token))
|
||||
return singleResult(new Operation(state, index, pattern, condition));
|
||||
if (interface->isCursorOn(condition->binary_op_token))
|
||||
return singleResult(new Operation(interface, index, pattern, condition));
|
||||
}
|
||||
|
||||
return noResult();
|
||||
@@ -802,9 +805,9 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority,
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority,
|
||||
IfStatementAST *pattern, BinaryExpressionAST *condition)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, pattern(pattern)
|
||||
, condition(condition)
|
||||
{
|
||||
@@ -889,12 +892,12 @@ class WrapStringLiteral: public CppQuickFixFactory
|
||||
public:
|
||||
enum Type { TypeString, TypeObjCString, TypeChar, TypeNone };
|
||||
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
ExpressionAST *literal = 0;
|
||||
Type type = TypeNone;
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
if (path.isEmpty())
|
||||
return noResult(); // nothing to do
|
||||
@@ -932,7 +935,7 @@ public:
|
||||
if (file.charAt(file.startOf(literal)) == QLatin1Char('@'))
|
||||
type = TypeObjCString;
|
||||
}
|
||||
return singleResult(new Operation(state,
|
||||
return singleResult(new Operation(interface,
|
||||
path.size() - 1, // very high priority
|
||||
type,
|
||||
literal));
|
||||
@@ -942,9 +945,9 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, Type type,
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, Type type,
|
||||
ExpressionAST *literal)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, type(type)
|
||||
, literal(literal)
|
||||
{
|
||||
@@ -996,9 +999,9 @@ class TranslateStringLiteral: public CppQuickFixFactory
|
||||
public:
|
||||
enum TranslationOption { unknown, useTr, useQCoreApplicationTranslate, useMacro };
|
||||
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
// Initialize
|
||||
ExpressionAST *literal = 0;
|
||||
QString trContext;
|
||||
@@ -1016,7 +1019,7 @@ public:
|
||||
if (call->base_expression) {
|
||||
if (IdExpressionAST *idExpr = call->base_expression->asIdExpression()) {
|
||||
if (SimpleNameAST *functionName = idExpr->name->asSimpleName()) {
|
||||
const QByteArray id(state.currentFile().tokenAt(functionName->identifier_token).identifier->chars());
|
||||
const QByteArray id(interface->currentFile().tokenAt(functionName->identifier_token).identifier->chars());
|
||||
|
||||
if (id == "tr" || id == "trUtf8"
|
||||
|| id == "translate"
|
||||
@@ -1029,7 +1032,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<Control> control = state.context().control();
|
||||
QSharedPointer<Control> control = interface->context().control();
|
||||
const Name *trName = control->identifier("tr");
|
||||
|
||||
// Check whether we are in a method:
|
||||
@@ -1037,14 +1040,14 @@ public:
|
||||
{
|
||||
if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) {
|
||||
Function *function = definition->symbol;
|
||||
ClassOrNamespace *b = state.context().lookupType(function);
|
||||
ClassOrNamespace *b = interface->context().lookupType(function);
|
||||
if (b) {
|
||||
// Do we have a tr method?
|
||||
foreach(const LookupItem &r, b->find(trName)) {
|
||||
Symbol *s = r.declaration();
|
||||
if (s->type()->isFunctionType()) {
|
||||
// no context required for tr
|
||||
return singleResult(new Operation(state, path.size() - 1, literal, useTr, trContext));
|
||||
return singleResult(new Operation(interface, path.size() - 1, literal, useTr, trContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1059,20 +1062,20 @@ public:
|
||||
// ... or global if none available!
|
||||
if (trContext.isEmpty())
|
||||
trContext = QLatin1String("GLOBAL");
|
||||
return singleResult(new Operation(state, path.size() - 1, literal, useQCoreApplicationTranslate, trContext));
|
||||
return singleResult(new Operation(interface, path.size() - 1, literal, useQCoreApplicationTranslate, trContext));
|
||||
}
|
||||
}
|
||||
|
||||
// We need to use Q_TRANSLATE_NOOP
|
||||
return singleResult(new Operation(state, path.size() - 1, literal, useMacro, QLatin1String("GLOBAL")));
|
||||
return singleResult(new Operation(interface, path.size() - 1, literal, useMacro, QLatin1String("GLOBAL")));
|
||||
}
|
||||
|
||||
private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, ExpressionAST *literal, TranslationOption option, const QString &context)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, ExpressionAST *literal, TranslationOption option, const QString &context)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, m_literal(literal)
|
||||
, m_option(option)
|
||||
, m_context(context)
|
||||
@@ -1120,16 +1123,16 @@ private:
|
||||
class CStringToNSString: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
if (state.editor()->mimeType() != CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)
|
||||
if (interface->editor()->mimeType() != CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)
|
||||
return noResult();
|
||||
|
||||
StringLiteralAST *stringLiteral = 0;
|
||||
CallAST *qlatin1Call = 0;
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
if (path.isEmpty())
|
||||
return noResult(); // nothing to do
|
||||
@@ -1147,7 +1150,7 @@ public:
|
||||
if (call->base_expression) {
|
||||
if (IdExpressionAST *idExpr = call->base_expression->asIdExpression()) {
|
||||
if (SimpleNameAST *functionName = idExpr->name->asSimpleName()) {
|
||||
const QByteArray id(state.currentFile().tokenAt(functionName->identifier_token).identifier->chars());
|
||||
const QByteArray id(interface->currentFile().tokenAt(functionName->identifier_token).identifier->chars());
|
||||
|
||||
if (id == "QLatin1String" || id == "QLatin1Literal")
|
||||
qlatin1Call = call;
|
||||
@@ -1157,15 +1160,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
return singleResult(new Operation(state, path.size() - 1, stringLiteral, qlatin1Call));
|
||||
return singleResult(new Operation(interface, path.size() - 1, stringLiteral, qlatin1Call));
|
||||
}
|
||||
|
||||
private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, StringLiteralAST *stringLiteral, CallAST *qlatin1Call)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, StringLiteralAST *stringLiteral, CallAST *qlatin1Call)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, stringLiteral(stringLiteral)
|
||||
, qlatin1Call(qlatin1Call)
|
||||
{
|
||||
@@ -1214,12 +1217,12 @@ private:
|
||||
class ConvertNumericLiteral: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<QuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<QuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
QList<QuickFixOperation::Ptr> result;
|
||||
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
if (path.isEmpty())
|
||||
return result; // nothing to do
|
||||
@@ -1266,7 +1269,7 @@ public:
|
||||
*/
|
||||
QString replacement;
|
||||
replacement.sprintf("0x%lX", value);
|
||||
QuickFixOperation::Ptr op(new ConvertNumeric(state, start, start + numberLength, replacement));
|
||||
QuickFixOperation::Ptr op(new ConvertNumeric(interface, start, start + numberLength, replacement));
|
||||
op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Hexadecimal"));
|
||||
op->setPriority(priority);
|
||||
result.append(op);
|
||||
@@ -1284,7 +1287,7 @@ public:
|
||||
*/
|
||||
QString replacement;
|
||||
replacement.sprintf("0%lo", value);
|
||||
QuickFixOperation::Ptr op(new ConvertNumeric(state, start, start + numberLength, replacement));
|
||||
QuickFixOperation::Ptr op(new ConvertNumeric(interface, start, start + numberLength, replacement));
|
||||
op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Octal"));
|
||||
op->setPriority(priority);
|
||||
result.append(op);
|
||||
@@ -1303,7 +1306,7 @@ public:
|
||||
*/
|
||||
QString replacement;
|
||||
replacement.sprintf("%lu", value);
|
||||
QuickFixOperation::Ptr op(new ConvertNumeric(state, start, start + numberLength, replacement));
|
||||
QuickFixOperation::Ptr op(new ConvertNumeric(interface, start, start + numberLength, replacement));
|
||||
op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Decimal"));
|
||||
op->setPriority(priority);
|
||||
result.append(op);
|
||||
@@ -1317,8 +1320,9 @@ private:
|
||||
class ConvertNumeric: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
ConvertNumeric(const CppQuickFixState &state, int start, int end, const QString &replacement)
|
||||
: CppQuickFixOperation(state)
|
||||
ConvertNumeric(const QSharedPointer<const CppQuickFixAssistInterface> &interface,
|
||||
int start, int end, const QString &replacement)
|
||||
: CppQuickFixOperation(interface)
|
||||
, start(start)
|
||||
, end(end)
|
||||
, replacement(replacement)
|
||||
@@ -1345,18 +1349,18 @@ private:
|
||||
class FixForwardDeclarationOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
for (int index = path.size() - 1; index != -1; --index) {
|
||||
AST *ast = path.at(index);
|
||||
if (NamedTypeSpecifierAST *namedTy = ast->asNamedTypeSpecifier()) {
|
||||
if (Symbol *fwdClass = checkName(state, namedTy->name))
|
||||
return singleResult(new Operation(state, index, fwdClass));
|
||||
if (Symbol *fwdClass = checkName(interface, namedTy->name))
|
||||
return singleResult(new Operation(interface, index, fwdClass));
|
||||
} else if (ElaboratedTypeSpecifierAST *eTy = ast->asElaboratedTypeSpecifier()) {
|
||||
if (Symbol *fwdClass = checkName(state, eTy->name))
|
||||
return singleResult(new Operation(state, index, fwdClass));
|
||||
if (Symbol *fwdClass = checkName(interface, eTy->name))
|
||||
return singleResult(new Operation(interface, index, fwdClass));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,16 +1368,18 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
static Symbol *checkName(const CppQuickFixState &state, NameAST *ast)
|
||||
static Symbol *checkName(const QSharedPointer<const CppQuickFixAssistInterface> &interface, NameAST *ast)
|
||||
{
|
||||
if (ast && state.isCursorOn(ast)) {
|
||||
if (ast && interface->isCursorOn(ast)) {
|
||||
if (const Name *name = ast->name) {
|
||||
unsigned line, column;
|
||||
state.document()->translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column);
|
||||
interface->semanticInfo().doc->translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column);
|
||||
|
||||
Symbol *fwdClass = 0;
|
||||
|
||||
foreach (const LookupItem &r, state.context().lookup(name, state.document()->scopeAt(line, column))) {
|
||||
foreach (const LookupItem &r,
|
||||
interface->context().lookup(name,
|
||||
interface->semanticInfo().doc->scopeAt(line, column))) {
|
||||
if (! r.declaration())
|
||||
continue;
|
||||
else if (ForwardClassDeclaration *fwd = r.declaration()->asForwardClassDeclaration())
|
||||
@@ -1393,8 +1399,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, Symbol *fwdClass)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, Symbol *fwdClass)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, fwdClass(fwdClass)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||
@@ -1405,13 +1411,13 @@ private:
|
||||
{
|
||||
Q_ASSERT(fwdClass != 0);
|
||||
|
||||
if (Class *k = state().snapshot().findMatchingClassDeclaration(fwdClass)) {
|
||||
if (Class *k = assistInterface()->snapshot().findMatchingClassDeclaration(fwdClass)) {
|
||||
const QString headerFile = QString::fromUtf8(k->fileName(), k->fileNameLength());
|
||||
|
||||
// collect the fwd headers
|
||||
Snapshot fwdHeaders;
|
||||
fwdHeaders.insert(state().snapshot().document(headerFile));
|
||||
foreach (Document::Ptr doc, state().snapshot()) {
|
||||
fwdHeaders.insert(assistInterface()->snapshot().document(headerFile));
|
||||
foreach (Document::Ptr doc, assistInterface()->snapshot()) {
|
||||
QFileInfo headerFileInfo(doc->fileName());
|
||||
if (doc->globalSymbolCount() == 0 && doc->includes().size() == 1)
|
||||
fwdHeaders.insert(doc);
|
||||
@@ -1448,7 +1454,7 @@ private:
|
||||
|
||||
unsigned currentLine = currentFile->cursor().blockNumber() + 1;
|
||||
unsigned bestLine = 0;
|
||||
foreach (const Document::Include &incl, state().document()->includes()) {
|
||||
foreach (const Document::Include &incl, assistInterface()->semanticInfo().doc->includes()) {
|
||||
if (incl.line() < currentLine)
|
||||
bestLine = incl.line();
|
||||
}
|
||||
@@ -1479,18 +1485,18 @@ private:
|
||||
class AddLocalDeclarationOp: public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const CppRefactoringFile &file = state.currentFile();
|
||||
const QList<AST *> &path = interface->path();
|
||||
const CppRefactoringFile &file = interface->currentFile();
|
||||
|
||||
for (int index = path.size() - 1; index != -1; --index) {
|
||||
if (BinaryExpressionAST *binary = path.at(index)->asBinaryExpression()) {
|
||||
if (binary->left_expression && binary->right_expression && file.tokenAt(binary->binary_op_token).is(T_EQUAL)) {
|
||||
IdExpressionAST *idExpr = binary->left_expression->asIdExpression();
|
||||
if (state.isCursorOn(binary->left_expression) && idExpr && idExpr->name->asSimpleName() != 0) {
|
||||
if (interface->isCursorOn(binary->left_expression) && idExpr && idExpr->name->asSimpleName() != 0) {
|
||||
SimpleNameAST *nameAST = idExpr->name->asSimpleName();
|
||||
const QList<LookupItem> results = state.context().lookup(nameAST->name, file.scopeAt(nameAST->firstToken()));
|
||||
const QList<LookupItem> results = interface->context().lookup(nameAST->name, file.scopeAt(nameAST->firstToken()));
|
||||
Declaration *decl = 0;
|
||||
foreach (const LookupItem &r, results) {
|
||||
if (! r.declaration())
|
||||
@@ -1504,7 +1510,7 @@ public:
|
||||
}
|
||||
|
||||
if (! decl) {
|
||||
return singleResult(new Operation(state, index, binary));
|
||||
return singleResult(new Operation(interface, index, binary));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1518,8 +1524,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, BinaryExpressionAST *binaryAST)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, BinaryExpressionAST *binaryAST)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, binaryAST(binaryAST)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix", "Add Local Declaration"));
|
||||
@@ -1528,7 +1534,8 @@ private:
|
||||
virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
|
||||
{
|
||||
TypeOfExpression typeOfExpression;
|
||||
typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings());
|
||||
typeOfExpression.init(assistInterface()->semanticInfo().doc,
|
||||
assistInterface()->snapshot(), assistInterface()->context().bindings());
|
||||
const QList<LookupItem> result = typeOfExpression(currentFile->textOf(binaryAST->right_expression),
|
||||
currentFile->scopeAt(binaryAST->firstToken()),
|
||||
TypeOfExpression::Preprocess);
|
||||
@@ -1536,12 +1543,12 @@ private:
|
||||
if (! result.isEmpty()) {
|
||||
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(state().context());
|
||||
env.setContext(assistInterface()->context());
|
||||
env.switchScope(result.first().scope());
|
||||
UseQualifiedNames q;
|
||||
env.enter(&q);
|
||||
|
||||
Control *control = state().context().control().data();
|
||||
Control *control = assistInterface()->context().control().data();
|
||||
FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
|
||||
|
||||
Overview oo;
|
||||
@@ -1573,9 +1580,9 @@ private:
|
||||
class ToCamelCaseConverter : public CppQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
|
||||
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const QList<AST *> &path = state.path();
|
||||
const QList<AST *> &path = interface->path();
|
||||
|
||||
if (path.isEmpty())
|
||||
return noResult();
|
||||
@@ -1597,7 +1604,7 @@ public:
|
||||
return noResult();
|
||||
for (int i = 1; i < newName.length() - 1; ++i) {
|
||||
if (Operation::isConvertibleUnderscore(newName, i))
|
||||
return singleResult(new Operation(state, path.size() - 1, newName));
|
||||
return singleResult(new Operation(interface, path.size() - 1, newName));
|
||||
}
|
||||
|
||||
return noResult();
|
||||
@@ -1607,8 +1614,8 @@ private:
|
||||
class Operation: public CppQuickFixOperation
|
||||
{
|
||||
public:
|
||||
Operation(const CppQuickFixState &state, int priority, const QString &newName)
|
||||
: CppQuickFixOperation(state, priority)
|
||||
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, const QString &newName)
|
||||
: CppQuickFixOperation(interface, priority)
|
||||
, m_name(newName)
|
||||
{
|
||||
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||
@@ -1627,7 +1634,7 @@ private:
|
||||
m_name[i] = m_name.at(i).toUpper();
|
||||
}
|
||||
}
|
||||
static_cast<CppEditor::Internal::CPPEditorWidget*>(state().editor())->renameUsagesNow(m_name);
|
||||
static_cast<CppEditor::Internal::CPPEditorWidget*>(assistInterface()->editor())->renameUsagesNow(m_name);
|
||||
}
|
||||
|
||||
static bool isConvertibleUnderscore(const QString &name, int pos)
|
||||
@@ -1643,7 +1650,7 @@ private:
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
void CppQuickFixCollector::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
||||
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
||||
{
|
||||
plugIn->addAutoReleasedObject(new UseInverseOp);
|
||||
plugIn->addAutoReleasedObject(new FlipBinaryOp);
|
||||
@@ -1657,11 +1664,11 @@ void CppQuickFixCollector::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
||||
plugIn->addAutoReleasedObject(new TranslateStringLiteral);
|
||||
plugIn->addAutoReleasedObject(new CStringToNSString);
|
||||
plugIn->addAutoReleasedObject(new ConvertNumericLiteral);
|
||||
plugIn->addAutoReleasedObject(new Internal::CompleteSwitchCaseStatement);
|
||||
plugIn->addAutoReleasedObject(new CompleteSwitchCaseStatement);
|
||||
plugIn->addAutoReleasedObject(new FixForwardDeclarationOp);
|
||||
plugIn->addAutoReleasedObject(new AddLocalDeclarationOp);
|
||||
plugIn->addAutoReleasedObject(new ToCamelCaseConverter);
|
||||
plugIn->addAutoReleasedObject(new Internal::InsertQtPropertyMembers);
|
||||
plugIn->addAutoReleasedObject(new Internal::DeclFromDef);
|
||||
plugIn->addAutoReleasedObject(new Internal::DefFromDecl);
|
||||
plugIn->addAutoReleasedObject(new InsertQtPropertyMembers);
|
||||
plugIn->addAutoReleasedObject(new DeclFromDef);
|
||||
plugIn->addAutoReleasedObject(new DefFromDecl);
|
||||
}
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CPPCODECOMPLETION_H
|
||||
#define CPPCODECOMPLETION_H
|
||||
|
||||
#include <ASTfwd.h>
|
||||
#include <FullySpecifiedType.h>
|
||||
#include <cplusplus/Icons.h>
|
||||
#include <cplusplus/Overview.h>
|
||||
#include <cplusplus/TypeOfExpression.h>
|
||||
|
||||
#include <texteditor/icompletioncollector.h>
|
||||
#include <texteditor/snippets/snippetcollector.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTextCursor;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace TextEditor {
|
||||
class ITextEditor;
|
||||
class BaseTextEditorWidget;
|
||||
}
|
||||
|
||||
namespace CPlusPlus {
|
||||
class LookupItem;
|
||||
class ClassOrNamespace;
|
||||
}
|
||||
|
||||
namespace CppTools {
|
||||
namespace Internal {
|
||||
|
||||
class CppModelManager;
|
||||
class FunctionArgumentWidget;
|
||||
|
||||
class CppCodeCompletion : public TextEditor::ICompletionCollector
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CppCodeCompletion(CppModelManager *manager);
|
||||
|
||||
void setObjcEnabled(bool objcEnabled)
|
||||
{ m_objcEnabled = objcEnabled; }
|
||||
|
||||
TextEditor::ITextEditor *editor() const;
|
||||
int startPosition() const;
|
||||
bool shouldRestartCompletion();
|
||||
QList<TextEditor::CompletionItem> getCompletions();
|
||||
bool supportsEditor(TextEditor::ITextEditor *editor) const;
|
||||
bool supportsPolicy(TextEditor::CompletionPolicy policy) const;
|
||||
bool triggersCompletion(TextEditor::ITextEditor *editor);
|
||||
int startCompletion(TextEditor::ITextEditor *editor);
|
||||
void completions(QList<TextEditor::CompletionItem> *completions);
|
||||
|
||||
bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
void complete(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
|
||||
void cleanup();
|
||||
|
||||
QIcon iconForSymbol(CPlusPlus::Symbol *symbol) const;
|
||||
|
||||
private:
|
||||
void addSnippets();
|
||||
void addKeywords();
|
||||
void addMacros(const QString &fileName, const CPlusPlus::Snapshot &snapshot);
|
||||
void addMacros_helper(const CPlusPlus::Snapshot &snapshot,
|
||||
const QString &fileName,
|
||||
QSet<QString> *processed,
|
||||
QSet<QString> *definedMacros);
|
||||
void addCompletionItem(CPlusPlus::Symbol *symbol);
|
||||
|
||||
bool completeInclude(const QTextCursor &cursor);
|
||||
void completePreprocessor();
|
||||
|
||||
void globalCompletion(CPlusPlus::Scope *scope);
|
||||
|
||||
bool completeConstructorOrFunction(const QList<CPlusPlus::LookupItem> &results,
|
||||
int endOfExpression, bool toolTipOnly);
|
||||
|
||||
bool completeMember(const QList<CPlusPlus::LookupItem> &results);
|
||||
bool completeScope(const QList<CPlusPlus::LookupItem> &results);
|
||||
|
||||
void completeNamespace(CPlusPlus::ClassOrNamespace *binding);
|
||||
|
||||
void completeClass(CPlusPlus::ClassOrNamespace *b,
|
||||
bool staticLookup = true);
|
||||
|
||||
bool completeConstructors(CPlusPlus::Class *klass);
|
||||
|
||||
bool completeQtMethod(const QList<CPlusPlus::LookupItem> &results,
|
||||
bool wantSignals);
|
||||
|
||||
bool completeSignal(const QList<CPlusPlus::LookupItem> &results)
|
||||
{ return completeQtMethod(results, true); }
|
||||
|
||||
bool completeSlot(const QList<CPlusPlus::LookupItem> &results)
|
||||
{ return completeQtMethod(results, false); }
|
||||
|
||||
int findStartOfName(int pos = -1) const;
|
||||
|
||||
int startCompletionHelper(TextEditor::ITextEditor *editor);
|
||||
|
||||
int startCompletionInternal(TextEditor::BaseTextEditorWidget *edit,
|
||||
const QString fileName,
|
||||
unsigned line, unsigned column,
|
||||
const QString &expression,
|
||||
int endOfExpression);
|
||||
|
||||
QList<TextEditor::CompletionItem> removeDuplicates(const QList<TextEditor::CompletionItem> &items);
|
||||
|
||||
private:
|
||||
void completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding,
|
||||
bool staticClassAccess);
|
||||
bool tryObjCCompletion(TextEditor::BaseTextEditorWidget *edit);
|
||||
bool objcKeywordsWanted() const;
|
||||
|
||||
static QStringList preprocessorCompletions;
|
||||
|
||||
CppModelManager *m_manager;
|
||||
TextEditor::ITextEditor *m_editor;
|
||||
int m_startPosition; // Position of the cursor from which completion started
|
||||
bool m_shouldRestartCompletion;
|
||||
|
||||
bool m_automaticCompletion;
|
||||
unsigned m_completionOperator;
|
||||
bool m_objcEnabled;
|
||||
|
||||
TextEditor::SnippetCollector m_snippetProvider;
|
||||
|
||||
CPlusPlus::Icons m_icons;
|
||||
CPlusPlus::Overview overview;
|
||||
CPlusPlus::TypeOfExpression typeOfExpression;
|
||||
QPointer<FunctionArgumentWidget> m_functionArgumentWidget;
|
||||
|
||||
QList<TextEditor::CompletionItem> m_completions;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppTools
|
||||
|
||||
Q_DECLARE_METATYPE(CPlusPlus::Symbol *)
|
||||
|
||||
#endif // CPPCODECOMPLETION_H
|
||||
+1204
-1461
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,172 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CPPCOMPLETIONASSIST_H
|
||||
#define CPPCOMPLETIONASSIST_H
|
||||
|
||||
#include <cplusplus/Icons.h>
|
||||
#include <cplusplus/Overview.h>
|
||||
#include <cplusplus/TypeOfExpression.h>
|
||||
#include <cplusplus/CppDocument.h>
|
||||
|
||||
#include <texteditor/codeassist/completionassistprovider.h>
|
||||
#include <texteditor/codeassist/iassistprocessor.h>
|
||||
#include <texteditor/snippets/snippetassistcollector.h>
|
||||
#include <texteditor/codeassist/defaultassistinterface.h>
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTextCursor;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
class LookupItem;
|
||||
class ClassOrNamespace;
|
||||
class Function;
|
||||
class LookupContext;
|
||||
}
|
||||
|
||||
namespace CppTools {
|
||||
namespace Internal {
|
||||
|
||||
class CppCompletionAssistInterface;
|
||||
class CppAssistProposalModel;
|
||||
|
||||
class CppCompletionAssistProvider : public TextEditor::CompletionAssistProvider
|
||||
{
|
||||
public:
|
||||
virtual bool supportsEditor(const QString &editorId) const;
|
||||
virtual int activationCharSequenceLength() const;
|
||||
virtual bool isActivationCharSequence(const QString &sequence) const;
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
};
|
||||
|
||||
class CppCompletionAssistProcessor : public TextEditor::IAssistProcessor
|
||||
{
|
||||
public:
|
||||
CppCompletionAssistProcessor();
|
||||
virtual ~CppCompletionAssistProcessor();
|
||||
|
||||
virtual TextEditor::IAssistProposal *perform(const TextEditor::IAssistInterface *interface);
|
||||
|
||||
private:
|
||||
TextEditor::IAssistProposal *createContentProposal();
|
||||
TextEditor::IAssistProposal *createHintProposal(QList<CPlusPlus::Function *> symbols) const;
|
||||
bool accepts() const;
|
||||
|
||||
int startOfOperator(int pos, unsigned *kind, bool wantFunctionCall) const;
|
||||
int findStartOfName(int pos = -1) const;
|
||||
int startCompletionHelper();
|
||||
bool tryObjCCompletion();
|
||||
bool objcKeywordsWanted() const;
|
||||
int startCompletionInternal(const QString fileName,
|
||||
unsigned line, unsigned column,
|
||||
const QString &expression,
|
||||
int endOfExpression);
|
||||
|
||||
void completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding, bool staticClassAccess);
|
||||
bool completeInclude(const QTextCursor &cursor);
|
||||
void completePreprocessor();
|
||||
bool completeConstructorOrFunction(const QList<CPlusPlus::LookupItem> &results,
|
||||
int endOfExpression,
|
||||
bool toolTipOnly);
|
||||
bool completeMember(const QList<CPlusPlus::LookupItem> &results);
|
||||
bool completeScope(const QList<CPlusPlus::LookupItem> &results);
|
||||
void completeNamespace(CPlusPlus::ClassOrNamespace *binding);
|
||||
void completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup = true);
|
||||
bool completeQtMethod(const QList<CPlusPlus::LookupItem> &results, bool wantSignals);
|
||||
bool completeSignal(const QList<CPlusPlus::LookupItem> &results)
|
||||
{ return completeQtMethod(results, true); }
|
||||
bool completeSlot(const QList<CPlusPlus::LookupItem> &results)
|
||||
{ return completeQtMethod(results, false); }
|
||||
void globalCompletion(CPlusPlus::Scope *scope);
|
||||
|
||||
void addCompletionItem(const QString &text,
|
||||
const QIcon &icon = QIcon(),
|
||||
int order = 0,
|
||||
const QVariant &data = QVariant());
|
||||
void addCompletionItem(CPlusPlus::Symbol *symbol);
|
||||
void addSnippets();
|
||||
void addKeywords();
|
||||
void addMacros(const QString &fileName, const CPlusPlus::Snapshot &snapshot);
|
||||
void addMacros_helper(const CPlusPlus::Snapshot &snapshot,
|
||||
const QString &fileName,
|
||||
QSet<QString> *processed,
|
||||
QSet<QString> *definedMacros);
|
||||
|
||||
int m_startPosition;
|
||||
bool m_objcEnabled;
|
||||
QScopedPointer<const CppCompletionAssistInterface> m_interface;
|
||||
QList<TextEditor::BasicProposalItem *> m_completions;
|
||||
TextEditor::SnippetAssistCollector m_snippetCollector;
|
||||
const CppCompletionAssistProvider *m_provider;
|
||||
CPlusPlus::Icons m_icons;
|
||||
CPlusPlus::TypeOfExpression typeOfExpression;
|
||||
QStringList preprocessorCompletions;
|
||||
QScopedPointer<CppAssistProposalModel> m_model;
|
||||
TextEditor::IAssistProposal *m_hintProposal;
|
||||
};
|
||||
|
||||
class CppCompletionAssistInterface : public TextEditor::DefaultAssistInterface
|
||||
{
|
||||
public:
|
||||
CppCompletionAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
TextEditor::AssistReason reason,
|
||||
const CPlusPlus::Snapshot &snapshot,
|
||||
const QStringList &includePaths,
|
||||
const QStringList &frameworkPaths)
|
||||
: TextEditor::DefaultAssistInterface(document, position, file, reason)
|
||||
, m_snapshot(snapshot)
|
||||
, m_includePaths(includePaths)
|
||||
, m_frameworkPaths(frameworkPaths)
|
||||
{}
|
||||
|
||||
const CPlusPlus::Snapshot &snapshot() const { return m_snapshot; }
|
||||
const QStringList &includePaths() const { return m_includePaths; }
|
||||
const QStringList &frameworkPaths() const { return m_frameworkPaths; }
|
||||
|
||||
private:
|
||||
CPlusPlus::Snapshot m_snapshot;
|
||||
QStringList m_includePaths;
|
||||
QStringList m_frameworkPaths;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // CppTools
|
||||
|
||||
Q_DECLARE_METATYPE(CPlusPlus::Symbol *)
|
||||
|
||||
#endif // CPPCOMPLETIONASSIST_H
|
||||
@@ -10,7 +10,6 @@ INCLUDEPATH += .
|
||||
DEFINES += CPPTOOLS_LIBRARY
|
||||
HEADERS += completionsettingspage.h \
|
||||
cppclassesfilter.h \
|
||||
cppcodecompletion.h \
|
||||
cppcurrentdocumentfilter.h \
|
||||
cppfunctionsfilter.h \
|
||||
cppmodelmanager.h \
|
||||
@@ -28,11 +27,11 @@ HEADERS += completionsettingspage.h \
|
||||
uicodecompletionsupport.h \
|
||||
insertionpointlocator.h \
|
||||
cpprefactoringchanges.h \
|
||||
abstracteditorsupport.h
|
||||
abstracteditorsupport.h \
|
||||
cppcompletionassist.h
|
||||
|
||||
SOURCES += completionsettingspage.cpp \
|
||||
cppclassesfilter.cpp \
|
||||
cppcodecompletion.cpp \
|
||||
cppcurrentdocumentfilter.cpp \
|
||||
cppfunctionsfilter.cpp \
|
||||
cppmodelmanager.cpp \
|
||||
@@ -48,7 +47,8 @@ SOURCES += completionsettingspage.cpp \
|
||||
symbolsfindfilter.cpp \
|
||||
uicodecompletionsupport.cpp \
|
||||
insertionpointlocator.cpp \
|
||||
cpprefactoringchanges.cpp
|
||||
cpprefactoringchanges.cpp \
|
||||
cppcompletionassist.cpp
|
||||
|
||||
FORMS += completionsettingspage.ui \
|
||||
cppfilesettingspage.ui
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
#include "completionsettingspage.h"
|
||||
#include "cppfilesettingspage.h"
|
||||
#include "cppclassesfilter.h"
|
||||
#include "cppcodecompletion.h"
|
||||
#include "cppfunctionsfilter.h"
|
||||
#include "cppcurrentdocumentfilter.h"
|
||||
#include "cppmodelmanager.h"
|
||||
#include "cpptoolsconstants.h"
|
||||
#include "cpplocatorfilter.h"
|
||||
#include "symbolsfindfilter.h"
|
||||
#include "cppcompletionassist.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
@@ -113,9 +113,7 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
|
||||
m_modelManager, SLOT(updateSourceFiles(QStringList)));
|
||||
addAutoReleasedObject(m_modelManager);
|
||||
|
||||
CppCodeCompletion *completion = new CppCodeCompletion(m_modelManager);
|
||||
addAutoReleasedObject(completion);
|
||||
|
||||
addAutoReleasedObject(new CppCompletionAssistProvider);
|
||||
addAutoReleasedObject(new CppLocatorFilter(m_modelManager));
|
||||
addAutoReleasedObject(new CppClassesFilter(m_modelManager));
|
||||
addAutoReleasedObject(new CppFunctionsFilter(m_modelManager));
|
||||
@@ -141,12 +139,6 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
|
||||
mcpptools->addAction(command);
|
||||
connect(switchAction, SIGNAL(triggered()), this, SLOT(switchHeaderSource()));
|
||||
|
||||
// Set completion settings and keep them up to date
|
||||
TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
|
||||
completion->setCompletionSettings(textEditorSettings->completionSettings());
|
||||
connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
|
||||
completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,12 +57,16 @@
|
||||
#include <texteditor/basetextdocumentlayout.h>
|
||||
#include <texteditor/basetexteditor.h>
|
||||
#include <texteditor/basetextmark.h>
|
||||
#include <texteditor/completionsupport.h>
|
||||
#include <texteditor/texteditorconstants.h>
|
||||
#include <texteditor/tabsettings.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/indenter.h>
|
||||
#include <texteditor/icompletioncollector.h>
|
||||
#include <texteditor/codeassist/basicproposalitem.h>
|
||||
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
|
||||
#include <texteditor/codeassist/completionassistprovider.h>
|
||||
#include <texteditor/codeassist/iassistprocessor.h>
|
||||
#include <texteditor/codeassist/iassistinterface.h>
|
||||
#include <texteditor/codeassist/genericproposal.h>
|
||||
|
||||
#include <find/findplugin.h>
|
||||
#include <find/textfindconstants.h>
|
||||
@@ -581,58 +585,15 @@ void FakeVimUserCommandsPage::apply()
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class WordCompletion : public ICompletionCollector
|
||||
class FakeVimCompletionAssistProvider : public TextEditor::CompletionAssistProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WordCompletion()
|
||||
virtual bool supportsEditor(const QString &) const
|
||||
{
|
||||
m_editable = 0;
|
||||
m_editor = 0;
|
||||
}
|
||||
|
||||
virtual bool shouldRestartCompletion()
|
||||
{
|
||||
//qDebug() << "SHOULD RESTART COMPLETION?";
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ITextEditor *editor() const
|
||||
{
|
||||
//qDebug() << "NO EDITOR?";
|
||||
return m_editable;
|
||||
}
|
||||
|
||||
virtual int startPosition() const
|
||||
{
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
virtual bool supportsEditor(ITextEditor *) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool supportsPolicy(CompletionPolicy policy) const
|
||||
{
|
||||
return policy == TextCompletion;
|
||||
}
|
||||
|
||||
virtual bool triggersCompletion(ITextEditor *editable)
|
||||
{
|
||||
//qDebug() << "TRIGGERS?";
|
||||
QTC_ASSERT(m_editable == editable, /**/);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual int startCompletion(ITextEditor *editable)
|
||||
{
|
||||
//qDebug() << "START COMPLETION";
|
||||
QTC_ASSERT(m_editor, return -1);
|
||||
QTC_ASSERT(m_editable == editable, return -1);
|
||||
return m_editor->textCursor().position();
|
||||
}
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
|
||||
void setActive(const QString &needle, bool forward, FakeVimHandler *handler)
|
||||
{
|
||||
@@ -640,96 +601,138 @@ public:
|
||||
m_handler = handler;
|
||||
if (!m_handler)
|
||||
return;
|
||||
m_editor = qobject_cast<BaseTextEditorWidget *>(handler->widget());
|
||||
if (!m_editor)
|
||||
|
||||
BaseTextEditorWidget *editor = qobject_cast<BaseTextEditorWidget *>(handler->widget());
|
||||
if (!editor)
|
||||
return;
|
||||
|
||||
//qDebug() << "ACTIVATE: " << needle << forward;
|
||||
m_needle = needle;
|
||||
m_editable = m_editor->editor();
|
||||
m_startPosition = m_editor->textCursor().position() - needle.size();
|
||||
|
||||
CompletionSupport::instance()->complete(m_editable, TextCompletion, false);
|
||||
editor->invokeAssist(Completion, this);
|
||||
}
|
||||
|
||||
void setInactive()
|
||||
{
|
||||
m_needle.clear();
|
||||
m_editable = 0;
|
||||
m_editor = 0;
|
||||
m_handler = 0;
|
||||
m_startPosition = -1;
|
||||
}
|
||||
|
||||
virtual void completions(QList<CompletionItem> *completions)
|
||||
const QString &needle() const
|
||||
{
|
||||
QTC_ASSERT(m_editor, return);
|
||||
QTC_ASSERT(completions, return);
|
||||
QTextCursor tc = m_editor->textCursor();
|
||||
return m_needle;
|
||||
}
|
||||
|
||||
void appendNeedle(const QChar &c)
|
||||
{
|
||||
m_needle.append(c);
|
||||
}
|
||||
|
||||
FakeVimHandler *handler() const
|
||||
{
|
||||
return m_handler;
|
||||
}
|
||||
|
||||
private:
|
||||
FakeVimHandler *m_handler;
|
||||
QString m_needle;
|
||||
};
|
||||
|
||||
class FakeVimAssistProposalItem : public BasicProposalItem
|
||||
{
|
||||
public:
|
||||
FakeVimAssistProposalItem(const FakeVimCompletionAssistProvider *provider)
|
||||
: m_provider(const_cast<FakeVimCompletionAssistProvider *>(provider))
|
||||
{}
|
||||
|
||||
virtual bool implicitlyApplies() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool prematurelyApplies(const QChar &c) const
|
||||
{
|
||||
m_provider->appendNeedle(c);
|
||||
return text() == m_provider->needle();
|
||||
}
|
||||
|
||||
virtual void applyContextualContent(BaseTextEditor *, int) const
|
||||
{
|
||||
QTC_ASSERT(m_provider->handler(), return);
|
||||
m_provider->handler()->handleReplay(text().mid(m_provider->needle().size()));
|
||||
const_cast<FakeVimCompletionAssistProvider *>(m_provider)->setInactive();
|
||||
}
|
||||
|
||||
private:
|
||||
FakeVimCompletionAssistProvider *m_provider;
|
||||
};
|
||||
|
||||
|
||||
class FakeVimAssistProposalModel : public BasicProposalItemListModel
|
||||
{
|
||||
public:
|
||||
FakeVimAssistProposalModel(const QList<BasicProposalItem *> &items)
|
||||
: BasicProposalItemListModel(items)
|
||||
{}
|
||||
|
||||
virtual bool supportsPrefixExpansion() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class FakeVimCompletionAssistProcessor : public IAssistProcessor
|
||||
{
|
||||
public:
|
||||
FakeVimCompletionAssistProcessor(const TextEditor::IAssistProvider *provider)
|
||||
: m_provider(static_cast<const FakeVimCompletionAssistProvider *>(provider))
|
||||
{}
|
||||
|
||||
virtual TextEditor::IAssistProposal *perform(const IAssistInterface *interface)
|
||||
{
|
||||
const QString &needle = m_provider->needle();
|
||||
|
||||
const int basePosition = interface->position() - needle.size();
|
||||
|
||||
QTextCursor tc(interface->document());
|
||||
tc.setPosition(interface->position());
|
||||
tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
||||
|
||||
QList<BasicProposalItem *> items;
|
||||
QSet<QString> seen;
|
||||
|
||||
QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively;
|
||||
while (1) {
|
||||
tc = tc.document()->find(m_needle, tc.position(), flags);
|
||||
tc = tc.document()->find(needle, tc.position(), flags);
|
||||
if (tc.isNull())
|
||||
break;
|
||||
QTextCursor sel = tc;
|
||||
sel.select(QTextCursor::WordUnderCursor);
|
||||
QString found = sel.selectedText();
|
||||
// Only add "real" completions.
|
||||
if (found.startsWith(m_needle)
|
||||
if (found.startsWith(needle)
|
||||
&& !seen.contains(found)
|
||||
&& sel.anchor() != m_startPosition) {
|
||||
&& sel.anchor() != basePosition) {
|
||||
seen.insert(found);
|
||||
CompletionItem item;
|
||||
item.collector = this;
|
||||
item.text = found;
|
||||
completions->append(item);
|
||||
BasicProposalItem *item = new FakeVimAssistProposalItem(m_provider);
|
||||
item->setText(found);
|
||||
items.append(item);
|
||||
}
|
||||
tc.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor);
|
||||
}
|
||||
//qDebug() << "COMPLETIONS" << completions->size();
|
||||
}
|
||||
|
||||
virtual bool typedCharCompletes(const CompletionItem &item, QChar typedChar)
|
||||
{
|
||||
m_needle += typedChar;
|
||||
//qDebug() << "COMPLETE? " << typedChar << item.text << m_needle;
|
||||
return item.text == m_needle;
|
||||
delete interface;
|
||||
return new GenericProposal(basePosition, new FakeVimAssistProposalModel(items));
|
||||
}
|
||||
|
||||
virtual void complete(const CompletionItem &item, QChar typedChar)
|
||||
{
|
||||
Q_UNUSED(typedChar);
|
||||
//qDebug() << "COMPLETE: " << item.text;
|
||||
QTC_ASSERT(m_handler, return);
|
||||
m_handler->handleReplay(item.text.mid(m_needle.size()));
|
||||
setInactive();
|
||||
}
|
||||
|
||||
virtual bool partiallyComplete(const QList<CompletionItem> &completionItems)
|
||||
{
|
||||
//qDebug() << "PARTIALLY";
|
||||
Q_UNUSED(completionItems);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void cleanup() {}
|
||||
|
||||
private:
|
||||
int findStartOfName(int pos = -1) const;
|
||||
bool isInComment() const;
|
||||
|
||||
FakeVimHandler *m_handler;
|
||||
BaseTextEditorWidget *m_editor;
|
||||
ITextEditor *m_editable;
|
||||
QString m_needle;
|
||||
QString m_currentPrefix;
|
||||
QList<CompletionItem> m_items;
|
||||
int m_startPosition;
|
||||
const FakeVimCompletionAssistProvider *m_provider;
|
||||
};
|
||||
|
||||
IAssistProcessor *FakeVimCompletionAssistProvider::createProcessor() const
|
||||
{
|
||||
return new FakeVimCompletionAssistProcessor(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -822,7 +825,9 @@ private:
|
||||
UserCommandMap m_defaultUserCommandMap;
|
||||
|
||||
Core::StatusBarWidget *m_statusBar;
|
||||
WordCompletion *m_wordCompletion;
|
||||
// @TODO: Delete
|
||||
//WordCompletion *m_wordCompletion;
|
||||
FakeVimCompletionAssistProvider *m_wordProvider;
|
||||
};
|
||||
|
||||
QVariant FakeVimUserCommandsModel::data(const QModelIndex &index, int role) const
|
||||
@@ -912,8 +917,10 @@ bool FakeVimPluginPrivate::initialize()
|
||||
m_actionManager = core()->actionManager();
|
||||
QTC_ASSERT(actionManager(), return false);
|
||||
|
||||
m_wordCompletion = new WordCompletion;
|
||||
q->addAutoReleasedObject(m_wordCompletion);
|
||||
//m_wordCompletion = new WordCompletion;
|
||||
//q->addAutoReleasedObject(m_wordCompletion);
|
||||
m_wordProvider = new FakeVimCompletionAssistProvider;
|
||||
|
||||
/*
|
||||
// Set completion settings and keep them up to date.
|
||||
TextEditorSettings *textEditorSettings = TextEditorSettings::instance();
|
||||
@@ -1407,16 +1414,15 @@ void FakeVimPluginPrivate::triggerCompletions()
|
||||
if (!handler)
|
||||
return;
|
||||
if (BaseTextEditorWidget *editor = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
|
||||
CompletionSupport::instance()->
|
||||
complete(editor->editor(), TextCompletion, false);
|
||||
// editor->triggerCompletions();
|
||||
editor->invokeAssist(Completion, m_wordProvider);
|
||||
// CompletionSupport::instance()->complete(editor->editor(), TextCompletion, false);
|
||||
}
|
||||
|
||||
void FakeVimPluginPrivate::triggerSimpleCompletions(const QString &needle,
|
||||
bool forward)
|
||||
{
|
||||
m_wordCompletion->setActive(needle, forward,
|
||||
qobject_cast<FakeVimHandler *>(sender()));
|
||||
// m_wordCompletion->setActive(needle, forward, qobject_cast<FakeVimHandler *>(sender()));
|
||||
m_wordProvider->setActive(needle, forward, qobject_cast<FakeVimHandler *>(sender()));
|
||||
}
|
||||
|
||||
void FakeVimPluginPrivate::setBlockSelection(bool on)
|
||||
|
||||
@@ -1,731 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "glslcodecompletion.h"
|
||||
#include "glsleditor.h"
|
||||
#include "glsleditorplugin.h"
|
||||
#include <glsl/glslengine.h>
|
||||
#include <glsl/glslengine.h>
|
||||
#include <glsl/glsllexer.h>
|
||||
#include <glsl/glslparser.h>
|
||||
#include <glsl/glslsemantic.h>
|
||||
#include <glsl/glslsymbols.h>
|
||||
#include <glsl/glslastdump.h>
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <texteditor/completionsettings.h>
|
||||
#include <utils/faketooltip.h>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QToolButton>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace GLSLEditor;
|
||||
using namespace GLSLEditor::Internal;
|
||||
|
||||
enum CompletionOrder {
|
||||
SpecialMemberOrder = -5
|
||||
};
|
||||
|
||||
static bool isIdentifierChar(QChar ch)
|
||||
{
|
||||
return ch.isLetterOrNumber() || ch == QLatin1Char('_');
|
||||
}
|
||||
|
||||
static bool isDelimiter(QChar ch)
|
||||
{
|
||||
switch (ch.unicode()) {
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ')':
|
||||
case '?':
|
||||
case '!':
|
||||
case ':':
|
||||
case ';':
|
||||
case ',':
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkStartOfIdentifier(const QString &word)
|
||||
{
|
||||
if (! word.isEmpty()) {
|
||||
const QChar ch = word.at(0);
|
||||
if (ch.isLetter() || ch == QLatin1Char('_'))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace GLSLEditor {
|
||||
namespace Internal {
|
||||
class FunctionArgumentWidget : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FunctionArgumentWidget();
|
||||
void showFunctionHint(QVector<GLSL::Function *> functionSymbols,
|
||||
int startPosition);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *e);
|
||||
|
||||
private slots:
|
||||
void nextPage();
|
||||
void previousPage();
|
||||
|
||||
private:
|
||||
void updateArgumentHighlight();
|
||||
void updateHintText();
|
||||
void placeInsideScreen();
|
||||
|
||||
GLSL::Function *currentFunction() const
|
||||
{ return m_items.at(m_current); }
|
||||
|
||||
int m_startpos;
|
||||
int m_currentarg;
|
||||
int m_current;
|
||||
bool m_escapePressed;
|
||||
|
||||
TextEditor::ITextEditor *m_editor;
|
||||
|
||||
QWidget *m_pager;
|
||||
QLabel *m_numberLabel;
|
||||
Utils::FakeToolTip *m_popupFrame;
|
||||
QVector<GLSL::Function *> m_items;
|
||||
};
|
||||
|
||||
|
||||
FunctionArgumentWidget::FunctionArgumentWidget():
|
||||
m_startpos(-1),
|
||||
m_current(0),
|
||||
m_escapePressed(false)
|
||||
{
|
||||
QObject *editorObject = Core::EditorManager::instance()->currentEditor();
|
||||
m_editor = qobject_cast<TextEditor::ITextEditor *>(editorObject);
|
||||
|
||||
m_popupFrame = new Utils::FakeToolTip(m_editor->widget());
|
||||
|
||||
QToolButton *downArrow = new QToolButton;
|
||||
downArrow->setArrowType(Qt::DownArrow);
|
||||
downArrow->setFixedSize(16, 16);
|
||||
downArrow->setAutoRaise(true);
|
||||
|
||||
QToolButton *upArrow = new QToolButton;
|
||||
upArrow->setArrowType(Qt::UpArrow);
|
||||
upArrow->setFixedSize(16, 16);
|
||||
upArrow->setAutoRaise(true);
|
||||
|
||||
setParent(m_popupFrame);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
m_pager = new QWidget;
|
||||
QHBoxLayout *hbox = new QHBoxLayout(m_pager);
|
||||
hbox->setMargin(0);
|
||||
hbox->setSpacing(0);
|
||||
hbox->addWidget(upArrow);
|
||||
m_numberLabel = new QLabel;
|
||||
hbox->addWidget(m_numberLabel);
|
||||
hbox->addWidget(downArrow);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_pager);
|
||||
layout->addWidget(this);
|
||||
m_popupFrame->setLayout(layout);
|
||||
|
||||
connect(upArrow, SIGNAL(clicked()), SLOT(previousPage()));
|
||||
connect(downArrow, SIGNAL(clicked()), SLOT(nextPage()));
|
||||
|
||||
setTextFormat(Qt::RichText);
|
||||
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
|
||||
void FunctionArgumentWidget::showFunctionHint(QVector<GLSL::Function *> functionSymbols,
|
||||
int startPosition)
|
||||
{
|
||||
Q_ASSERT(!functionSymbols.isEmpty());
|
||||
|
||||
if (m_startpos == startPosition)
|
||||
return;
|
||||
|
||||
m_pager->setVisible(functionSymbols.size() > 1);
|
||||
|
||||
m_items = functionSymbols;
|
||||
m_startpos = startPosition;
|
||||
m_current = 0;
|
||||
m_escapePressed = false;
|
||||
|
||||
// update the text
|
||||
m_currentarg = -1;
|
||||
updateArgumentHighlight();
|
||||
|
||||
m_popupFrame->show();
|
||||
}
|
||||
|
||||
void FunctionArgumentWidget::nextPage()
|
||||
{
|
||||
m_current = (m_current + 1) % m_items.size();
|
||||
updateHintText();
|
||||
}
|
||||
|
||||
void FunctionArgumentWidget::previousPage()
|
||||
{
|
||||
if (m_current == 0)
|
||||
m_current = m_items.size() - 1;
|
||||
else
|
||||
--m_current;
|
||||
|
||||
updateHintText();
|
||||
}
|
||||
|
||||
void FunctionArgumentWidget::updateArgumentHighlight()
|
||||
{
|
||||
int curpos = m_editor->position();
|
||||
if (curpos < m_startpos) {
|
||||
m_popupFrame->close();
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray str = m_editor->textAt(m_startpos, curpos - m_startpos).toLatin1();
|
||||
|
||||
int argnr = 0;
|
||||
int parcount = 0;
|
||||
GLSL::Lexer lexer(0, str.constData(), str.length());
|
||||
GLSL::Token tk;
|
||||
QList<GLSL::Token> tokens;
|
||||
do {
|
||||
lexer.yylex(&tk);
|
||||
tokens.append(tk);
|
||||
} while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
|
||||
for (int i = 0; i < tokens.count(); ++i) {
|
||||
const GLSL::Token &tk = tokens.at(i);
|
||||
if (tk.is(GLSL::Parser::T_LEFT_PAREN))
|
||||
++parcount;
|
||||
else if (tk.is(GLSL::Parser::T_RIGHT_PAREN))
|
||||
--parcount;
|
||||
else if (! parcount && tk.is(GLSL::Parser::T_COMMA))
|
||||
++argnr;
|
||||
}
|
||||
|
||||
if (m_currentarg != argnr) {
|
||||
m_currentarg = argnr;
|
||||
updateHintText();
|
||||
}
|
||||
|
||||
if (parcount < 0)
|
||||
m_popupFrame->close();
|
||||
}
|
||||
|
||||
bool FunctionArgumentWidget::eventFilter(QObject *obj, QEvent *e)
|
||||
{
|
||||
switch (e->type()) {
|
||||
case QEvent::ShortcutOverride:
|
||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
|
||||
m_escapePressed = true;
|
||||
}
|
||||
break;
|
||||
case QEvent::KeyPress:
|
||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
|
||||
m_escapePressed = true;
|
||||
}
|
||||
if (m_items.size() > 1) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent*>(e);
|
||||
if (ke->key() == Qt::Key_Up) {
|
||||
previousPage();
|
||||
return true;
|
||||
} else if (ke->key() == Qt::Key_Down) {
|
||||
nextPage();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case QEvent::KeyRelease:
|
||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape && m_escapePressed) {
|
||||
m_popupFrame->close();
|
||||
return false;
|
||||
}
|
||||
updateArgumentHighlight();
|
||||
break;
|
||||
case QEvent::WindowDeactivate:
|
||||
case QEvent::FocusOut:
|
||||
if (obj != m_editor->widget())
|
||||
break;
|
||||
m_popupFrame->close();
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::Wheel: {
|
||||
QWidget *widget = qobject_cast<QWidget *>(obj);
|
||||
if (! (widget == this || m_popupFrame->isAncestorOf(widget))) {
|
||||
m_popupFrame->close();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FunctionArgumentWidget::updateHintText()
|
||||
{
|
||||
setText(currentFunction()->prettyPrint(m_currentarg));
|
||||
|
||||
m_numberLabel->setText(tr("%1 of %2").arg(m_current + 1).arg(m_items.size()));
|
||||
|
||||
placeInsideScreen();
|
||||
}
|
||||
|
||||
void FunctionArgumentWidget::placeInsideScreen()
|
||||
{
|
||||
const QDesktopWidget *desktop = QApplication::desktop();
|
||||
#ifdef Q_WS_MAC
|
||||
const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_editor->widget()));
|
||||
#else
|
||||
const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_editor->widget()));
|
||||
#endif
|
||||
|
||||
m_pager->setFixedWidth(m_pager->minimumSizeHint().width());
|
||||
|
||||
setWordWrap(false);
|
||||
const int maxDesiredWidth = screen.width() - 10;
|
||||
const QSize minHint = m_popupFrame->minimumSizeHint();
|
||||
if (minHint.width() > maxDesiredWidth) {
|
||||
setWordWrap(true);
|
||||
m_popupFrame->setFixedWidth(maxDesiredWidth);
|
||||
const int extra =
|
||||
m_popupFrame->contentsMargins().bottom() + m_popupFrame->contentsMargins().top();
|
||||
m_popupFrame->setFixedHeight(heightForWidth(maxDesiredWidth - m_pager->width()) + extra);
|
||||
} else {
|
||||
m_popupFrame->setFixedSize(minHint);
|
||||
}
|
||||
|
||||
const QSize sz = m_popupFrame->size();
|
||||
QPoint pos = m_editor->cursorRect(m_startpos).topLeft();
|
||||
pos.setY(pos.y() - sz.height() - 1);
|
||||
|
||||
if (pos.x() + sz.width() > screen.right())
|
||||
pos.setX(screen.right() - sz.width());
|
||||
|
||||
m_popupFrame->move(pos);
|
||||
}
|
||||
|
||||
} // Internal
|
||||
} // GLSLEditor
|
||||
|
||||
|
||||
|
||||
CodeCompletion::CodeCompletion(QObject *parent)
|
||||
: ICompletionCollector(parent),
|
||||
m_editor(0),
|
||||
m_startPosition(-1),
|
||||
m_restartCompletion(false),
|
||||
m_keywordVariant(-1),
|
||||
m_keywordIcon(":/glsleditor/images/keyword.png"),
|
||||
m_varIcon(":/glsleditor/images/var.png"),
|
||||
m_functionIcon(":/glsleditor/images/func.png"),
|
||||
m_typeIcon(":/glsleditor/images/type.png"),
|
||||
m_constIcon(":/glsleditor/images/const.png"),
|
||||
m_attributeIcon(":/glsleditor/images/attribute.png"),
|
||||
m_uniformIcon(":/glsleditor/images/uniform.png"),
|
||||
m_varyingIcon(":/glsleditor/images/varying.png"),
|
||||
m_otherIcon(":/glsleditor/images/other.png")
|
||||
{
|
||||
}
|
||||
|
||||
CodeCompletion::~CodeCompletion()
|
||||
{
|
||||
}
|
||||
|
||||
TextEditor::ITextEditor *CodeCompletion::editor() const
|
||||
{
|
||||
return m_editor;
|
||||
}
|
||||
|
||||
int CodeCompletion::startPosition() const
|
||||
{
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
bool CodeCompletion::supportsEditor(TextEditor::ITextEditor *editor) const
|
||||
{
|
||||
return qobject_cast<GLSLTextEditorWidget *>(editor->widget()) != 0;
|
||||
}
|
||||
|
||||
bool CodeCompletion::supportsPolicy(TextEditor::CompletionPolicy policy) const
|
||||
{
|
||||
return policy == TextEditor::SemanticCompletion;
|
||||
}
|
||||
|
||||
bool CodeCompletion::triggersCompletion(TextEditor::ITextEditor *editor)
|
||||
{
|
||||
const int cursorPosition = editor->position();
|
||||
const QChar ch = editor->characterAt(cursorPosition - 1);
|
||||
|
||||
if (completionSettings().m_completionTrigger == TextEditor::AutomaticCompletion) {
|
||||
const QChar characterUnderCursor = editor->characterAt(cursorPosition);
|
||||
|
||||
if (isIdentifierChar(ch) && (characterUnderCursor.isSpace() ||
|
||||
characterUnderCursor.isNull() ||
|
||||
isDelimiter(characterUnderCursor))) {
|
||||
int pos = editor->position() - 1;
|
||||
for (; pos != -1; --pos) {
|
||||
if (! isIdentifierChar(editor->characterAt(pos)))
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
|
||||
const QString word = editor->textAt(pos, cursorPosition - pos);
|
||||
if (word.length() > 2 && checkStartOfIdentifier(word)) {
|
||||
for (int i = 0; i < word.length(); ++i) {
|
||||
if (! isIdentifierChar(word.at(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == QLatin1Char('(') || ch == QLatin1Char('.') || ch == QLatin1Char(','))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CodeCompletion::startCompletion(TextEditor::ITextEditor *editor)
|
||||
{
|
||||
m_editor = editor;
|
||||
|
||||
int pos = editor->position() - 1;
|
||||
QChar ch = editor->characterAt(pos);
|
||||
while (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
||||
ch = editor->characterAt(--pos);
|
||||
|
||||
CPlusPlus::ExpressionUnderCursor expressionUnderCursor;
|
||||
GLSLTextEditorWidget *edit = qobject_cast<GLSLTextEditorWidget *>(editor->widget());
|
||||
|
||||
QList<GLSL::Symbol *> members;
|
||||
QStringList specialMembers;
|
||||
|
||||
bool functionCall = (ch == QLatin1Char('(') && pos == editor->position() - 1);
|
||||
|
||||
if (ch == QLatin1Char(',')) {
|
||||
QTextCursor tc(edit->document());
|
||||
tc.setPosition(pos);
|
||||
const int start = expressionUnderCursor.startOfFunctionCall(tc);
|
||||
if (start == -1)
|
||||
return -1;
|
||||
|
||||
if (edit->characterAt(start) == QLatin1Char('(')) {
|
||||
pos = start;
|
||||
ch = QLatin1Char('(');
|
||||
functionCall = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == QLatin1Char('.') || functionCall) {
|
||||
const bool memberCompletion = ! functionCall;
|
||||
QTextCursor tc(edit->document());
|
||||
tc.setPosition(pos);
|
||||
|
||||
// get the expression under cursor
|
||||
const QByteArray code = expressionUnderCursor(tc).toLatin1();
|
||||
//qDebug() << endl << "expression:" << code;
|
||||
|
||||
// parse the expression
|
||||
GLSL::Engine engine;
|
||||
GLSL::Parser parser(&engine, code, code.size(), edit->languageVariant());
|
||||
GLSL::ExpressionAST *expr = parser.parseExpression();
|
||||
|
||||
#if 0
|
||||
// dump it!
|
||||
QTextStream qout(stdout, QIODevice::WriteOnly);
|
||||
GLSL::ASTDump dump(qout);
|
||||
dump(expr);
|
||||
#endif
|
||||
|
||||
if (Document::Ptr doc = edit->glslDocument()) {
|
||||
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
||||
|
||||
GLSL::Semantic sem;
|
||||
GLSL::Semantic::ExprResult exprTy = sem.expression(expr, currentScope, doc->engine());
|
||||
if (exprTy.type) {
|
||||
if (memberCompletion) {
|
||||
if (const GLSL::VectorType *vecTy = exprTy.type->asVectorType()) {
|
||||
members = vecTy->members();
|
||||
|
||||
// Sort the most relevant swizzle orderings to the top.
|
||||
specialMembers += QLatin1String("xy");
|
||||
specialMembers += QLatin1String("xyz");
|
||||
specialMembers += QLatin1String("xyzw");
|
||||
specialMembers += QLatin1String("rgb");
|
||||
specialMembers += QLatin1String("rgba");
|
||||
specialMembers += QLatin1String("st");
|
||||
specialMembers += QLatin1String("stp");
|
||||
specialMembers += QLatin1String("stpq");
|
||||
|
||||
} else if (const GLSL::Struct *structTy = exprTy.type->asStructType()) {
|
||||
members = structTy->members();
|
||||
|
||||
} else {
|
||||
// some other type
|
||||
}
|
||||
} else { // function completion
|
||||
QVector<GLSL::Function *> signatures;
|
||||
if (const GLSL::Function *funTy = exprTy.type->asFunctionType())
|
||||
signatures.append(const_cast<GLSL::Function *>(funTy)); // ### get rid of the const_cast
|
||||
else if (const GLSL::OverloadSet *overload = exprTy.type->asOverloadSetType())
|
||||
signatures = overload->functions();
|
||||
|
||||
if (! signatures.isEmpty()) {
|
||||
// Recreate if necessary
|
||||
if (!m_functionArgumentWidget)
|
||||
m_functionArgumentWidget = new FunctionArgumentWidget;
|
||||
|
||||
m_functionArgumentWidget->showFunctionHint(signatures, pos + 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// undefined
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
// sorry, there's no document
|
||||
}
|
||||
|
||||
} else {
|
||||
// it's a global completion
|
||||
if (Document::Ptr doc = edit->glslDocument()) {
|
||||
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
||||
bool isGlobal = !currentScope || !currentScope->scope();
|
||||
|
||||
// add the members from the scope chain
|
||||
for (; currentScope; currentScope = currentScope->scope())
|
||||
members += currentScope->members();
|
||||
|
||||
// if this is the global scope, then add some standard Qt attribute
|
||||
// and uniform names for autocompleting variable declarations
|
||||
// this isn't a complete list, just the most common
|
||||
if (isGlobal) {
|
||||
static const char * const attributeNames[] = {
|
||||
"qt_Vertex",
|
||||
"qt_Normal",
|
||||
"qt_MultiTexCoord0",
|
||||
"qt_MultiTexCoord1",
|
||||
"qt_MultiTexCoord2",
|
||||
0
|
||||
};
|
||||
static const char * const uniformNames[] = {
|
||||
"qt_ModelViewProjectionMatrix",
|
||||
"qt_ModelViewMatrix",
|
||||
"qt_ProjectionMatrix",
|
||||
"qt_NormalMatrix",
|
||||
"qt_Texture0",
|
||||
"qt_Texture1",
|
||||
"qt_Texture2",
|
||||
"qt_Color",
|
||||
"qt_Opacity",
|
||||
0
|
||||
};
|
||||
for (int index = 0; attributeNames[index]; ++index) {
|
||||
TextEditor::CompletionItem item(this);
|
||||
item.text = QString::fromLatin1(attributeNames[index]);
|
||||
item.icon = m_attributeIcon;
|
||||
m_completions.append(item);
|
||||
}
|
||||
for (int index = 0; uniformNames[index]; ++index) {
|
||||
TextEditor::CompletionItem item(this);
|
||||
item.text = QString::fromLatin1(uniformNames[index]);
|
||||
item.icon = m_uniformIcon;
|
||||
m_completions.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_keywordVariant != edit->languageVariant()) {
|
||||
QStringList keywords = GLSL::Lexer::keywords(edit->languageVariant());
|
||||
m_keywordCompletions.clear();
|
||||
for (int index = 0; index < keywords.size(); ++index) {
|
||||
TextEditor::CompletionItem item(this);
|
||||
item.text = keywords.at(index);
|
||||
item.icon = m_keywordIcon;
|
||||
m_keywordCompletions.append(item);
|
||||
}
|
||||
m_keywordVariant = edit->languageVariant();
|
||||
}
|
||||
|
||||
m_completions += m_keywordCompletions;
|
||||
}
|
||||
|
||||
foreach (GLSL::Symbol *s, members) {
|
||||
TextEditor::CompletionItem item(this);
|
||||
GLSL::Variable *var = s->asVariable();
|
||||
if (var) {
|
||||
int storageType = var->qualifiers() & GLSL::QualifiedTypeAST::StorageMask;
|
||||
if (storageType == GLSL::QualifiedTypeAST::Attribute)
|
||||
item.icon = m_attributeIcon;
|
||||
else if (storageType == GLSL::QualifiedTypeAST::Uniform)
|
||||
item.icon = m_uniformIcon;
|
||||
else if (storageType == GLSL::QualifiedTypeAST::Varying)
|
||||
item.icon = m_varyingIcon;
|
||||
else if (storageType == GLSL::QualifiedTypeAST::Const)
|
||||
item.icon = m_constIcon;
|
||||
else
|
||||
item.icon = m_varIcon;
|
||||
} else if (s->asArgument()) {
|
||||
item.icon = m_varIcon;
|
||||
} else if (s->asFunction() || s->asOverloadSet()) {
|
||||
item.icon = m_functionIcon;
|
||||
} else if (s->asStruct()) {
|
||||
item.icon = m_typeIcon;
|
||||
} else {
|
||||
item.icon = m_otherIcon;
|
||||
}
|
||||
item.text = s->name();
|
||||
if (specialMembers.contains(item.text))
|
||||
item.order = SpecialMemberOrder;
|
||||
m_completions.append(item);
|
||||
}
|
||||
|
||||
m_startPosition = pos + 1;
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
void CodeCompletion::completions(QList<TextEditor::CompletionItem> *completions)
|
||||
{
|
||||
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);
|
||||
|
||||
filter(m_completions, completions, key);
|
||||
|
||||
if (completions->size() == 1) {
|
||||
if (key == completions->first().text)
|
||||
completions->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CodeCompletion::typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar)
|
||||
{
|
||||
Q_UNUSED(item);
|
||||
Q_UNUSED(typedChar);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CodeCompletion::complete(const TextEditor::CompletionItem &item, QChar typedChar)
|
||||
{
|
||||
Q_UNUSED(typedChar);
|
||||
|
||||
QString toInsert = item.text;
|
||||
|
||||
const int length = m_editor->position() - m_startPosition;
|
||||
m_editor->setCursorPosition(m_startPosition);
|
||||
m_editor->replace(length, toInsert);
|
||||
|
||||
if (toInsert.endsWith(QLatin1Char('.')) || toInsert.endsWith(QLatin1Char('(')))
|
||||
m_restartCompletion = true;
|
||||
}
|
||||
|
||||
bool CodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
|
||||
{
|
||||
return ICompletionCollector::partiallyComplete(completionItems);
|
||||
}
|
||||
|
||||
bool CodeCompletion::glslCompletionItemLessThan(const TextEditor::CompletionItem &l, const TextEditor::CompletionItem &r)
|
||||
{
|
||||
if (l.order != r.order)
|
||||
return l.order < r.order;
|
||||
return completionItemLessThan(l, r);
|
||||
}
|
||||
|
||||
QList<TextEditor::CompletionItem> CodeCompletion::getCompletions()
|
||||
{
|
||||
QList<TextEditor::CompletionItem> completionItems;
|
||||
|
||||
completions(&completionItems);
|
||||
|
||||
qStableSort(completionItems.begin(), completionItems.end(), glslCompletionItemLessThan);
|
||||
|
||||
// Remove duplicates
|
||||
QString lastKey;
|
||||
QVariant lastData;
|
||||
QList<TextEditor::CompletionItem> uniquelist;
|
||||
|
||||
foreach (const TextEditor::CompletionItem &item, completionItems) {
|
||||
if (item.text != lastKey || item.data.type() != lastData.type()) {
|
||||
uniquelist.append(item);
|
||||
lastKey = item.text;
|
||||
lastData = item.data;
|
||||
}
|
||||
}
|
||||
|
||||
return uniquelist;
|
||||
}
|
||||
|
||||
bool CodeCompletion::shouldRestartCompletion()
|
||||
{
|
||||
return m_restartCompletion;
|
||||
}
|
||||
|
||||
void CodeCompletion::cleanup()
|
||||
{
|
||||
m_editor = 0;
|
||||
m_completions.clear();
|
||||
m_restartCompletion = false;
|
||||
m_startPosition = -1;
|
||||
}
|
||||
|
||||
#include "glslcodecompletion.moc"
|
||||
@@ -1,134 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
#ifndef GLSLCODECOMPLETION_H
|
||||
#define GLSLCODECOMPLETION_H
|
||||
|
||||
#include <texteditor/icompletioncollector.h>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
namespace GLSLEditor {
|
||||
namespace Internal {
|
||||
|
||||
class FunctionArgumentWidget;
|
||||
|
||||
class CodeCompletion: public TextEditor::ICompletionCollector
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CodeCompletion(QObject *parent = 0);
|
||||
virtual ~CodeCompletion();
|
||||
|
||||
/* Returns the current active ITextEditor */
|
||||
virtual TextEditor::ITextEditor *editor() const;
|
||||
virtual int startPosition() const;
|
||||
|
||||
/*
|
||||
* Returns true if this completion collector can be used with the given editor.
|
||||
*/
|
||||
virtual bool supportsEditor(TextEditor::ITextEditor *editor) const;
|
||||
|
||||
/*
|
||||
* Returns true if this completion collector supports the given completion policy.
|
||||
*/
|
||||
virtual bool supportsPolicy(TextEditor::CompletionPolicy policy) const;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
virtual bool triggersCompletion(TextEditor::ITextEditor *editor);
|
||||
|
||||
// returns starting position
|
||||
virtual int startCompletion(TextEditor::ITextEditor *editor);
|
||||
|
||||
/* This method should add all the completions it wants to show into the list,
|
||||
* based on the given cursor position.
|
||||
*/
|
||||
virtual void completions(QList<TextEditor::CompletionItem> *completions);
|
||||
|
||||
/**
|
||||
* This method should return true when the given typed character should cause
|
||||
* the selected completion item to be completed.
|
||||
*/
|
||||
virtual bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
|
||||
/**
|
||||
* This method should complete the given completion item.
|
||||
*
|
||||
* \param typedChar Non-null when completion was triggered by typing a
|
||||
* character. Possible values depend on typedCharCompletes()
|
||||
*/
|
||||
virtual void complete(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
|
||||
/* This method gives the completion collector a chance to partially complete
|
||||
* based on a set of items. The general use case is to complete the common
|
||||
* prefix shared by all possible completion items.
|
||||
*
|
||||
* Returns whether the completion popup should be closed.
|
||||
*/
|
||||
virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
|
||||
|
||||
virtual QList<TextEditor::CompletionItem> getCompletions();
|
||||
virtual bool shouldRestartCompletion();
|
||||
|
||||
/* Called when it's safe to clean up the completion items.
|
||||
*/
|
||||
virtual void cleanup();
|
||||
|
||||
private:
|
||||
QList<TextEditor::CompletionItem> m_completions;
|
||||
QList<TextEditor::CompletionItem> m_keywordCompletions;
|
||||
TextEditor::ITextEditor *m_editor;
|
||||
int m_startPosition;
|
||||
bool m_restartCompletion;
|
||||
QPointer<FunctionArgumentWidget> m_functionArgumentWidget;
|
||||
|
||||
static bool glslCompletionItemLessThan(const TextEditor::CompletionItem &l, const TextEditor::CompletionItem &r);
|
||||
|
||||
int m_keywordVariant;
|
||||
|
||||
QIcon m_keywordIcon;
|
||||
QIcon m_varIcon;
|
||||
QIcon m_functionIcon;
|
||||
QIcon m_typeIcon;
|
||||
QIcon m_constIcon;
|
||||
QIcon m_attributeIcon;
|
||||
QIcon m_uniformIcon;
|
||||
QIcon m_varyingIcon;
|
||||
QIcon m_otherIcon;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GLSLEditor
|
||||
|
||||
#endif // GLSLCODECOMPLETION_H
|
||||
@@ -0,0 +1,478 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "glslcompletionassist.h"
|
||||
#include "glsleditorconstants.h"
|
||||
#include "glsleditorplugin.h"
|
||||
#include "reuse.h"
|
||||
|
||||
#include <glsl/glslengine.h>
|
||||
#include <glsl/glslengine.h>
|
||||
#include <glsl/glsllexer.h>
|
||||
#include <glsl/glslparser.h>
|
||||
#include <glsl/glslsemantic.h>
|
||||
#include <glsl/glslsymbols.h>
|
||||
#include <glsl/glslastdump.h>
|
||||
|
||||
#include <coreplugin/ifile.h>
|
||||
#include <texteditor/completionsettings.h>
|
||||
#include <texteditor/codeassist/basicproposalitem.h>
|
||||
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
|
||||
#include <texteditor/codeassist/genericproposal.h>
|
||||
#include <texteditor/codeassist/functionhintproposal.h>
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <utils/faketooltip.h>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QToolButton>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace GLSLEditor;
|
||||
using namespace Internal;
|
||||
using namespace TextEditor;
|
||||
|
||||
namespace {
|
||||
|
||||
enum CompletionOrder {
|
||||
SpecialMemberOrder = -5
|
||||
};
|
||||
|
||||
|
||||
bool isActivationChar(const QChar &ch)
|
||||
{
|
||||
return ch == QLatin1Char('(') || ch == QLatin1Char('.') || ch == QLatin1Char(',');
|
||||
}
|
||||
|
||||
bool isIdentifierChar(QChar ch)
|
||||
{
|
||||
return ch.isLetterOrNumber() || ch == QLatin1Char('_');
|
||||
}
|
||||
|
||||
bool isDelimiter(QChar ch)
|
||||
{
|
||||
switch (ch.unicode()) {
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ')':
|
||||
case '?':
|
||||
case '!':
|
||||
case ':':
|
||||
case ';':
|
||||
case ',':
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool checkStartOfIdentifier(const QString &word)
|
||||
{
|
||||
if (! word.isEmpty()) {
|
||||
const QChar ch = word.at(0);
|
||||
if (ch.isLetter() || ch == QLatin1Char('_'))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Anonymous
|
||||
|
||||
// ----------------------------
|
||||
// GLSLCompletionAssistProvider
|
||||
// ----------------------------
|
||||
bool GLSLCompletionAssistProvider::supportsEditor(const QString &editorId) const
|
||||
{
|
||||
return editorId == QLatin1String(Constants::C_GLSLEDITOR_ID);
|
||||
}
|
||||
|
||||
IAssistProcessor *GLSLCompletionAssistProvider::createProcessor() const
|
||||
{
|
||||
return new GLSLCompletionAssistProcessor;
|
||||
}
|
||||
|
||||
int GLSLCompletionAssistProvider::activationCharSequenceLength() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool GLSLCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
||||
{
|
||||
return isActivationChar(sequence.at(0));
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// GLSLFunctionHintProposalModel
|
||||
// -----------------------------
|
||||
class GLSLFunctionHintProposalModel : public TextEditor::IFunctionHintProposalModel
|
||||
{
|
||||
public:
|
||||
GLSLFunctionHintProposalModel(QVector<GLSL::Function *> functionSymbols)
|
||||
: m_items(functionSymbols)
|
||||
, m_currentArg(-1)
|
||||
{}
|
||||
|
||||
virtual void reset() {}
|
||||
virtual int size() const { return m_items.size(); }
|
||||
virtual QString text(int index) const;
|
||||
virtual int activeArgument(const QString &prefix) const;
|
||||
|
||||
private:
|
||||
QVector<GLSL::Function *> m_items;
|
||||
mutable int m_currentArg;
|
||||
};
|
||||
|
||||
QString GLSLFunctionHintProposalModel::text(int index) const
|
||||
{
|
||||
return m_items.at(index)->prettyPrint(m_currentArg);
|
||||
}
|
||||
|
||||
int GLSLFunctionHintProposalModel::activeArgument(const QString &prefix) const
|
||||
{
|
||||
const QByteArray &str = prefix.toLatin1();
|
||||
int argnr = 0;
|
||||
int parcount = 0;
|
||||
GLSL::Lexer lexer(0, str.constData(), str.length());
|
||||
GLSL::Token tk;
|
||||
QList<GLSL::Token> tokens;
|
||||
do {
|
||||
lexer.yylex(&tk);
|
||||
tokens.append(tk);
|
||||
} while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
|
||||
for (int i = 0; i < tokens.count(); ++i) {
|
||||
const GLSL::Token &tk = tokens.at(i);
|
||||
if (tk.is(GLSL::Parser::T_LEFT_PAREN))
|
||||
++parcount;
|
||||
else if (tk.is(GLSL::Parser::T_RIGHT_PAREN))
|
||||
--parcount;
|
||||
else if (! parcount && tk.is(GLSL::Parser::T_COMMA))
|
||||
++argnr;
|
||||
}
|
||||
|
||||
if (parcount < 0)
|
||||
return -1;
|
||||
|
||||
if (argnr != m_currentArg)
|
||||
m_currentArg = argnr;
|
||||
|
||||
return argnr;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// GLSLCompletionAssistProcessor
|
||||
// -----------------------------
|
||||
GLSLCompletionAssistProcessor::GLSLCompletionAssistProcessor()
|
||||
: m_startPosition(0)
|
||||
, m_keywordIcon(":/glsleditor/images/keyword.png")
|
||||
, m_varIcon(":/glsleditor/images/var.png")
|
||||
, m_functionIcon(":/glsleditor/images/func.png")
|
||||
, m_typeIcon(":/glsleditor/images/type.png")
|
||||
, m_constIcon(":/glsleditor/images/const.png")
|
||||
, m_attributeIcon(":/glsleditor/images/attribute.png")
|
||||
, m_uniformIcon(":/glsleditor/images/uniform.png")
|
||||
, m_varyingIcon(":/glsleditor/images/varying.png")
|
||||
, m_otherIcon(":/glsleditor/images/other.png")
|
||||
{}
|
||||
|
||||
GLSLCompletionAssistProcessor::~GLSLCompletionAssistProcessor()
|
||||
{}
|
||||
|
||||
IAssistProposal *GLSLCompletionAssistProcessor::perform(const IAssistInterface *interface)
|
||||
{
|
||||
m_interface.reset(static_cast<const GLSLCompletionAssistInterface *>(interface));
|
||||
|
||||
if (interface->reason() == IdleEditor && !acceptsIdleEditor())
|
||||
return 0;
|
||||
|
||||
int pos = m_interface->position() - 1;
|
||||
QChar ch = m_interface->characterAt(pos);
|
||||
while (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
||||
ch = m_interface->characterAt(--pos);
|
||||
|
||||
CPlusPlus::ExpressionUnderCursor expressionUnderCursor;
|
||||
//GLSLTextEditorWidget *edit = qobject_cast<GLSLTextEditorWidget *>(editor->widget());
|
||||
|
||||
QList<GLSL::Symbol *> members;
|
||||
QStringList specialMembers;
|
||||
|
||||
bool functionCall = (ch == QLatin1Char('(') && pos == m_interface->position() - 1);
|
||||
|
||||
if (ch == QLatin1Char(',')) {
|
||||
QTextCursor tc(m_interface->document());
|
||||
tc.setPosition(pos);
|
||||
const int start = expressionUnderCursor.startOfFunctionCall(tc);
|
||||
if (start == -1)
|
||||
return 0;
|
||||
|
||||
if (m_interface->characterAt(start) == QLatin1Char('(')) {
|
||||
pos = start;
|
||||
ch = QLatin1Char('(');
|
||||
functionCall = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == QLatin1Char('.') || functionCall) {
|
||||
const bool memberCompletion = ! functionCall;
|
||||
QTextCursor tc(m_interface->document());
|
||||
tc.setPosition(pos);
|
||||
|
||||
// get the expression under cursor
|
||||
const QByteArray code = expressionUnderCursor(tc).toLatin1();
|
||||
//qDebug() << endl << "expression:" << code;
|
||||
|
||||
// parse the expression
|
||||
GLSL::Engine engine;
|
||||
GLSL::Parser parser(&engine, code, code.size(), languageVariant(m_interface->mimeType()));
|
||||
GLSL::ExpressionAST *expr = parser.parseExpression();
|
||||
|
||||
#if 0
|
||||
// dump it!
|
||||
QTextStream qout(stdout, QIODevice::WriteOnly);
|
||||
GLSL::ASTDump dump(qout);
|
||||
dump(expr);
|
||||
#endif
|
||||
|
||||
if (Document::Ptr doc = m_interface->glslDocument()) {
|
||||
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
||||
|
||||
GLSL::Semantic sem;
|
||||
GLSL::Semantic::ExprResult exprTy = sem.expression(expr, currentScope, doc->engine());
|
||||
if (exprTy.type) {
|
||||
if (memberCompletion) {
|
||||
if (const GLSL::VectorType *vecTy = exprTy.type->asVectorType()) {
|
||||
members = vecTy->members();
|
||||
|
||||
// Sort the most relevant swizzle orderings to the top.
|
||||
specialMembers += QLatin1String("xy");
|
||||
specialMembers += QLatin1String("xyz");
|
||||
specialMembers += QLatin1String("xyzw");
|
||||
specialMembers += QLatin1String("rgb");
|
||||
specialMembers += QLatin1String("rgba");
|
||||
specialMembers += QLatin1String("st");
|
||||
specialMembers += QLatin1String("stp");
|
||||
specialMembers += QLatin1String("stpq");
|
||||
|
||||
} else if (const GLSL::Struct *structTy = exprTy.type->asStructType()) {
|
||||
members = structTy->members();
|
||||
|
||||
} else {
|
||||
// some other type
|
||||
}
|
||||
} else { // function completion
|
||||
QVector<GLSL::Function *> signatures;
|
||||
if (const GLSL::Function *funTy = exprTy.type->asFunctionType())
|
||||
signatures.append(const_cast<GLSL::Function *>(funTy)); // ### get rid of the const_cast
|
||||
else if (const GLSL::OverloadSet *overload = exprTy.type->asOverloadSetType())
|
||||
signatures = overload->functions();
|
||||
|
||||
if (! signatures.isEmpty()) {
|
||||
m_startPosition = pos + 1;
|
||||
return createHintProposal(signatures);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// undefined
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
// sorry, there's no document
|
||||
}
|
||||
|
||||
} else {
|
||||
// it's a global completion
|
||||
if (Document::Ptr doc = m_interface->glslDocument()) {
|
||||
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
||||
bool isGlobal = !currentScope || !currentScope->scope();
|
||||
|
||||
// add the members from the scope chain
|
||||
for (; currentScope; currentScope = currentScope->scope())
|
||||
members += currentScope->members();
|
||||
|
||||
// if this is the global scope, then add some standard Qt attribute
|
||||
// and uniform names for autocompleting variable declarations
|
||||
// this isn't a complete list, just the most common
|
||||
if (isGlobal) {
|
||||
static const char * const attributeNames[] = {
|
||||
"qt_Vertex",
|
||||
"qt_Normal",
|
||||
"qt_MultiTexCoord0",
|
||||
"qt_MultiTexCoord1",
|
||||
"qt_MultiTexCoord2",
|
||||
0
|
||||
};
|
||||
static const char * const uniformNames[] = {
|
||||
"qt_ModelViewProjectionMatrix",
|
||||
"qt_ModelViewMatrix",
|
||||
"qt_ProjectionMatrix",
|
||||
"qt_NormalMatrix",
|
||||
"qt_Texture0",
|
||||
"qt_Texture1",
|
||||
"qt_Texture2",
|
||||
"qt_Color",
|
||||
"qt_Opacity",
|
||||
0
|
||||
};
|
||||
for (int index = 0; attributeNames[index]; ++index)
|
||||
addCompletion(QString::fromLatin1(attributeNames[index]), m_attributeIcon);
|
||||
for (int index = 0; uniformNames[index]; ++index)
|
||||
addCompletion(QString::fromLatin1(uniformNames[index]), m_uniformIcon);
|
||||
}
|
||||
}
|
||||
|
||||
// if (m_keywordVariant != languageVariant(m_interface->mimeType())) {
|
||||
QStringList keywords = GLSL::Lexer::keywords(languageVariant(m_interface->mimeType()));
|
||||
// m_keywordCompletions.clear();
|
||||
for (int index = 0; index < keywords.size(); ++index)
|
||||
addCompletion(keywords.at(index), m_keywordIcon);
|
||||
// m_keywordVariant = languageVariant(m_interface->mimeType());
|
||||
// }
|
||||
|
||||
// m_completions += m_keywordCompletions;
|
||||
}
|
||||
|
||||
foreach (GLSL::Symbol *s, members) {
|
||||
QIcon icon;
|
||||
GLSL::Variable *var = s->asVariable();
|
||||
if (var) {
|
||||
int storageType = var->qualifiers() & GLSL::QualifiedTypeAST::StorageMask;
|
||||
if (storageType == GLSL::QualifiedTypeAST::Attribute)
|
||||
icon = m_attributeIcon;
|
||||
else if (storageType == GLSL::QualifiedTypeAST::Uniform)
|
||||
icon = m_uniformIcon;
|
||||
else if (storageType == GLSL::QualifiedTypeAST::Varying)
|
||||
icon = m_varyingIcon;
|
||||
else if (storageType == GLSL::QualifiedTypeAST::Const)
|
||||
icon = m_constIcon;
|
||||
else
|
||||
icon = m_varIcon;
|
||||
} else if (s->asArgument()) {
|
||||
icon = m_varIcon;
|
||||
} else if (s->asFunction() || s->asOverloadSet()) {
|
||||
icon = m_functionIcon;
|
||||
} else if (s->asStruct()) {
|
||||
icon = m_typeIcon;
|
||||
} else {
|
||||
icon = m_otherIcon;
|
||||
}
|
||||
if (specialMembers.contains(s->name()))
|
||||
addCompletion(s->name(), icon, SpecialMemberOrder);
|
||||
else
|
||||
addCompletion(s->name(), icon);
|
||||
}
|
||||
|
||||
m_startPosition = pos + 1;
|
||||
return createContentProposal();
|
||||
}
|
||||
|
||||
IAssistProposal *GLSLCompletionAssistProcessor::createContentProposal() const
|
||||
{
|
||||
IGenericProposalModel *model = new BasicProposalItemListModel(m_completions);
|
||||
IAssistProposal *proposal = new GenericProposal(m_startPosition, model);
|
||||
return proposal;
|
||||
}
|
||||
|
||||
IAssistProposal *GLSLCompletionAssistProcessor::createHintProposal(
|
||||
const QVector<GLSL::Function *> &symbols)
|
||||
{
|
||||
IFunctionHintProposalModel *model = new GLSLFunctionHintProposalModel(symbols);
|
||||
IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model);
|
||||
return proposal;
|
||||
}
|
||||
|
||||
bool GLSLCompletionAssistProcessor::acceptsIdleEditor() const
|
||||
{
|
||||
const int cursorPosition = m_interface->position();
|
||||
const QChar ch = m_interface->characterAt(cursorPosition - 1);
|
||||
|
||||
const QChar characterUnderCursor = m_interface->characterAt(cursorPosition);
|
||||
|
||||
if (isIdentifierChar(ch) && (characterUnderCursor.isSpace() ||
|
||||
characterUnderCursor.isNull() ||
|
||||
isDelimiter(characterUnderCursor))) {
|
||||
int pos = m_interface->position() - 1;
|
||||
for (; pos != -1; --pos) {
|
||||
if (! isIdentifierChar(m_interface->characterAt(pos)))
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
|
||||
const QString word = m_interface->textAt(pos, cursorPosition - pos);
|
||||
if (word.length() > 2 && checkStartOfIdentifier(word)) {
|
||||
for (int i = 0; i < word.length(); ++i) {
|
||||
if (! isIdentifierChar(word.at(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return isActivationChar(ch);
|
||||
}
|
||||
|
||||
void GLSLCompletionAssistProcessor::addCompletion(const QString &text,
|
||||
const QIcon &icon,
|
||||
int order)
|
||||
{
|
||||
BasicProposalItem *item = new BasicProposalItem;
|
||||
item->setText(text);
|
||||
item->setIcon(icon);
|
||||
item->setOrder(order);
|
||||
m_completions.append(item);
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// GLSLCompletionAssistInterface
|
||||
// -----------------------------
|
||||
GLSLCompletionAssistInterface::GLSLCompletionAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
TextEditor::AssistReason reason,
|
||||
const QString &mimeType,
|
||||
const Document::Ptr &glslDoc)
|
||||
: DefaultAssistInterface(document, position, file, reason)
|
||||
, m_mimeType(mimeType)
|
||||
, m_glslDoc(glslDoc)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GLSLCOMPLETIONASSIST_H
|
||||
#define GLSLCOMPLETIONASSIST_H
|
||||
|
||||
#include "glsleditor.h"
|
||||
|
||||
#include <texteditor/codeassist/completionassistprovider.h>
|
||||
#include <texteditor/codeassist/iassistprocessor.h>
|
||||
#include <texteditor/codeassist/defaultassistinterface.h>
|
||||
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
|
||||
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace TextEditor {
|
||||
class BasicProposalItem;
|
||||
}
|
||||
|
||||
namespace GLSLEditor {
|
||||
namespace Internal {
|
||||
|
||||
class GLSLCompletionAssistInterface;
|
||||
|
||||
class GLSLCompletionAssistProvider : public TextEditor::CompletionAssistProvider
|
||||
{
|
||||
public:
|
||||
virtual bool supportsEditor(const QString &editorId) const;
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
|
||||
virtual int activationCharSequenceLength() const;
|
||||
virtual bool isActivationCharSequence(const QString &sequence) const;
|
||||
};
|
||||
|
||||
class GLSLCompletionAssistProcessor : public TextEditor::IAssistProcessor
|
||||
{
|
||||
public:
|
||||
GLSLCompletionAssistProcessor();
|
||||
virtual ~GLSLCompletionAssistProcessor();
|
||||
|
||||
virtual TextEditor::IAssistProposal *perform(const TextEditor::IAssistInterface *interface);
|
||||
|
||||
private:
|
||||
TextEditor::IAssistProposal *createContentProposal() const;
|
||||
TextEditor::IAssistProposal *createHintProposal(const QVector<GLSL::Function *> &symbols);
|
||||
bool acceptsIdleEditor() const;
|
||||
void addCompletion(const QString &text, const QIcon &icon, int order = 0);
|
||||
|
||||
int m_startPosition;
|
||||
QScopedPointer<const GLSLCompletionAssistInterface> m_interface;
|
||||
QList<TextEditor::BasicProposalItem *> m_completions;
|
||||
|
||||
QIcon m_keywordIcon;
|
||||
QIcon m_varIcon;
|
||||
QIcon m_functionIcon;
|
||||
QIcon m_typeIcon;
|
||||
QIcon m_constIcon;
|
||||
QIcon m_attributeIcon;
|
||||
QIcon m_uniformIcon;
|
||||
QIcon m_varyingIcon;
|
||||
QIcon m_otherIcon;
|
||||
};
|
||||
|
||||
class GLSLCompletionAssistInterface : public TextEditor::DefaultAssistInterface
|
||||
{
|
||||
public:
|
||||
GLSLCompletionAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
TextEditor::AssistReason reason,
|
||||
const QString &mimeType,
|
||||
const Document::Ptr &glslDoc);
|
||||
|
||||
const QString &mimeType() const { return m_mimeType; }
|
||||
const Document::Ptr &glslDocument() const { return m_glslDoc; }
|
||||
|
||||
private:
|
||||
QString m_mimeType;
|
||||
Document::Ptr m_glslDoc;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // GLSLEditor
|
||||
|
||||
#endif // GLSLCOMPLETIONASSIST_H
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "glslhighlighter.h"
|
||||
#include "glslautocompleter.h"
|
||||
#include "glslindenter.h"
|
||||
#include "glslcompletionassist.h"
|
||||
|
||||
#include <glsl/glsllexer.h>
|
||||
#include <glsl/glslparser.h>
|
||||
@@ -412,3 +413,17 @@ Document::Ptr GLSLTextEditorWidget::glslDocument() const
|
||||
{
|
||||
return m_glslDocument;
|
||||
}
|
||||
|
||||
TextEditor::IAssistInterface *GLSLTextEditorWidget::createAssistInterface(
|
||||
TextEditor::AssistKind kind,
|
||||
TextEditor::AssistReason reason) const
|
||||
{
|
||||
if (kind == TextEditor::Completion)
|
||||
return new GLSLCompletionAssistInterface(document(),
|
||||
position(),
|
||||
editor()->file(),
|
||||
reason,
|
||||
mimeType(),
|
||||
glslDocument());
|
||||
return BaseTextEditorWidget::createAssistInterface(kind, reason);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,9 @@ public:
|
||||
|
||||
Document::Ptr glslDocument() const;
|
||||
|
||||
TextEditor::IAssistInterface *createAssistInterface(TextEditor::AssistKind assistKind,
|
||||
TextEditor::AssistReason reason) const;
|
||||
|
||||
public slots:
|
||||
virtual void setFontSettings(const TextEditor::FontSettings &);
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@ glsleditorfactory.h \
|
||||
glsleditorplugin.h \
|
||||
glslfilewizard.h \
|
||||
glslhighlighter.h \
|
||||
glslcodecompletion.h \
|
||||
glslautocompleter.h \
|
||||
glslindenter.h \
|
||||
glslhoverhandler.h
|
||||
glslhoverhandler.h \
|
||||
glslcompletionassist.h \
|
||||
reuse.h
|
||||
|
||||
SOURCES += \
|
||||
glsleditor.cpp \
|
||||
@@ -30,10 +31,11 @@ glsleditorfactory.cpp \
|
||||
glsleditorplugin.cpp \
|
||||
glslfilewizard.cpp \
|
||||
glslhighlighter.cpp \
|
||||
glslcodecompletion.cpp \
|
||||
glslautocompleter.cpp \
|
||||
glslindenter.cpp \
|
||||
glslhoverhandler.cpp
|
||||
glslhoverhandler.cpp \
|
||||
glslcompletionassist.cpp \
|
||||
reuse.cpp
|
||||
|
||||
OTHER_FILES += GLSLEditor.mimetypes.xml
|
||||
RESOURCES += glsleditor.qrc
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
#include "glsleditor.h"
|
||||
#include "glsleditorconstants.h"
|
||||
#include "glsleditorfactory.h"
|
||||
#include "glslcodecompletion.h"
|
||||
#include "glslfilewizard.h"
|
||||
#include "glslhoverhandler.h"
|
||||
#include "glslcompletionassist.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
@@ -55,7 +55,6 @@
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/textfilewizard.h>
|
||||
#include <texteditor/texteditoractionhandler.h>
|
||||
#include <texteditor/completionsupport.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <glsl/glslengine.h>
|
||||
@@ -132,8 +131,7 @@ bool GLSLEditorPlugin::initialize(const QStringList & /*arguments*/, QString *er
|
||||
m_editor = new GLSLEditorFactory(this);
|
||||
addObject(m_editor);
|
||||
|
||||
CodeCompletion *completion = new CodeCompletion(this);
|
||||
addAutoReleasedObject(completion);
|
||||
addAutoReleasedObject(new GLSLCompletionAssistProvider);
|
||||
|
||||
m_actionHandler = new TextEditor::TextEditorActionHandler(GLSLEditor::Constants::C_GLSLEDITOR_ID,
|
||||
TextEditor::TextEditorActionHandler::Format
|
||||
@@ -164,12 +162,6 @@ bool GLSLEditorPlugin::initialize(const QStringList & /*arguments*/, QString *er
|
||||
cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
|
||||
contextMenu->addAction(cmd);
|
||||
|
||||
// Set completion settings and keep them up to date
|
||||
TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
|
||||
completion->setCompletionSettings(textEditorSettings->completionSettings());
|
||||
connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
|
||||
completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
|
||||
|
||||
error_message->clear();
|
||||
|
||||
Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance();
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "reuse.h"
|
||||
|
||||
#include <QtCore/QLatin1String>
|
||||
|
||||
#include <glsl/glsllexer.h>
|
||||
|
||||
using namespace GLSL;
|
||||
|
||||
namespace GLSLEditor {
|
||||
namespace Internal {
|
||||
|
||||
int languageVariant(const QString &mimeType)
|
||||
{
|
||||
int variant = 0;
|
||||
bool isVertex = false;
|
||||
bool isFragment = false;
|
||||
bool isDesktop = false;
|
||||
if (mimeType.isEmpty()) {
|
||||
// ### Before file has been opened, so don't know the mime type.
|
||||
isVertex = true;
|
||||
isFragment = true;
|
||||
} else if (mimeType == QLatin1String("text/x-glsl") ||
|
||||
mimeType == QLatin1String("application/x-glsl")) {
|
||||
isVertex = true;
|
||||
isFragment = true;
|
||||
isDesktop = true;
|
||||
} else if (mimeType == QLatin1String("text/x-glsl-vert")) {
|
||||
isVertex = true;
|
||||
isDesktop = true;
|
||||
} else if (mimeType == QLatin1String("text/x-glsl-frag")) {
|
||||
isFragment = true;
|
||||
isDesktop = true;
|
||||
} else if (mimeType == QLatin1String("text/x-glsl-es-vert")) {
|
||||
isVertex = true;
|
||||
} else if (mimeType == QLatin1String("text/x-glsl-es-frag")) {
|
||||
isFragment = true;
|
||||
}
|
||||
if (isDesktop)
|
||||
variant |= Lexer::Variant_GLSL_120;
|
||||
else
|
||||
variant |= Lexer::Variant_GLSL_ES_100;
|
||||
if (isVertex)
|
||||
variant |= Lexer::Variant_VertexShader;
|
||||
if (isFragment)
|
||||
variant |= Lexer::Variant_FragmentShader;
|
||||
return variant;
|
||||
}
|
||||
|
||||
} // Internal
|
||||
} // GLSLEditor
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REUSE_H
|
||||
#define REUSE_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
namespace GLSLEditor {
|
||||
namespace Internal {
|
||||
|
||||
int languageVariant(const QString &mimeType);
|
||||
|
||||
} // Internal
|
||||
} // GLSLEditor
|
||||
|
||||
#endif // REUSE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,114 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QMLJSCODECOMPLETION_H
|
||||
#define QMLJSCODECOMPLETION_H
|
||||
|
||||
#include <qmljs/qmljsdocument.h>
|
||||
#include <texteditor/icompletioncollector.h>
|
||||
#include <texteditor/snippets/snippetcollector.h>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
namespace TextEditor {
|
||||
class ITextEditor;
|
||||
}
|
||||
|
||||
namespace QmlJS {
|
||||
class ModelManagerInterface;
|
||||
|
||||
namespace Interpreter {
|
||||
class Value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace QmlJSEditor {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class FunctionArgumentWidget;
|
||||
|
||||
class CodeCompletion: public TextEditor::ICompletionCollector
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CodeCompletion(QmlJS::ModelManagerInterface *modelManager, QObject *parent = 0);
|
||||
virtual ~CodeCompletion();
|
||||
|
||||
virtual TextEditor::ITextEditor *editor() const;
|
||||
virtual int startPosition() const;
|
||||
virtual bool shouldRestartCompletion();
|
||||
virtual bool supportsEditor(TextEditor::ITextEditor *editor) const;
|
||||
virtual bool supportsPolicy(TextEditor::CompletionPolicy policy) const;
|
||||
virtual bool triggersCompletion(TextEditor::ITextEditor *editor);
|
||||
virtual int startCompletion(TextEditor::ITextEditor *editor);
|
||||
virtual void completions(QList<TextEditor::CompletionItem> *completions);
|
||||
virtual bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
virtual void complete(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
|
||||
virtual QList<TextEditor::CompletionItem> getCompletions();
|
||||
virtual void sortCompletion(QList<TextEditor::CompletionItem> &completionItems);
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
private:
|
||||
|
||||
bool maybeTriggersCompletion(TextEditor::ITextEditor *editor);
|
||||
bool isDelimiter(QChar ch) const;
|
||||
|
||||
bool completeUrl(const QString &relativeBasePath, const QString &urlString);
|
||||
bool completeFileName(const QString &relativeBasePath, const QString &fileName,
|
||||
const QStringList &patterns = QStringList());
|
||||
|
||||
void addCompletions(const QHash<QString, const QmlJS::Interpreter::Value *> &newCompletions,
|
||||
const QIcon &icon, int relevance);
|
||||
void addCompletions(const QStringList &newCompletions,
|
||||
const QIcon &icon, int relevance);
|
||||
void addCompletionsPropertyLhs(
|
||||
const QHash<QString, const QmlJS::Interpreter::Value *> &newCompletions,
|
||||
const QIcon &icon, int relevance, bool afterOn);
|
||||
|
||||
QmlJS::ModelManagerInterface *m_modelManager;
|
||||
TextEditor::ITextEditor *m_editor;
|
||||
int m_startPosition;
|
||||
bool m_restartCompletion;
|
||||
TextEditor::SnippetCollector m_snippetProvider;
|
||||
QList<TextEditor::CompletionItem> m_completions;
|
||||
QPointer<FunctionArgumentWidget> m_functionArgumentWidget;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QmlJSEditor
|
||||
|
||||
#endif // QMLJSCODECOMPLETION_H
|
||||
@@ -0,0 +1,854 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "qmljscompletionassist.h"
|
||||
#include "qmljseditorconstants.h"
|
||||
#include "qmljsreuse.h"
|
||||
#include "qmlexpressionundercursor.h"
|
||||
|
||||
#include <coreplugin/ifile.h>
|
||||
|
||||
#include <texteditor/codeassist/iassistinterface.h>
|
||||
#include <texteditor/codeassist/genericproposal.h>
|
||||
#include <texteditor/codeassist/functionhintproposal.h>
|
||||
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
#include <qmljs/parser/qmljsast_p.h>
|
||||
#include <qmljs/qmljsinterpreter.h>
|
||||
#include <qmljs/qmljslookupcontext.h>
|
||||
#include <qmljs/qmljsscanner.h>
|
||||
#include <qmljs/qmljsbind.h>
|
||||
#include <qmljs/qmljscompletioncontextfinder.h>
|
||||
#include <qmljs/qmljsscopebuilder.h>
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QtAlgorithms>
|
||||
#include <QtCore/QDirIterator>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
using namespace QmlJS;
|
||||
using namespace QmlJSEditor;
|
||||
using namespace Internal;
|
||||
using namespace TextEditor;
|
||||
|
||||
namespace {
|
||||
|
||||
enum CompletionOrder {
|
||||
EnumValueOrder = -5,
|
||||
SnippetOrder = -15,
|
||||
PropertyOrder = -10,
|
||||
SymbolOrder = -20,
|
||||
KeywordOrder = -25,
|
||||
TypeOrder = -30
|
||||
};
|
||||
|
||||
class EnumerateProperties: private Interpreter::MemberProcessor
|
||||
{
|
||||
QSet<const Interpreter::ObjectValue *> _processed;
|
||||
QHash<QString, const Interpreter::Value *> _properties;
|
||||
bool _globalCompletion;
|
||||
bool _enumerateGeneratedSlots;
|
||||
const Interpreter::Context *_context;
|
||||
const Interpreter::ObjectValue *_currentObject;
|
||||
|
||||
public:
|
||||
EnumerateProperties(const Interpreter::Context *context)
|
||||
: _globalCompletion(false),
|
||||
_enumerateGeneratedSlots(false),
|
||||
_context(context),
|
||||
_currentObject(0)
|
||||
{
|
||||
}
|
||||
|
||||
void setGlobalCompletion(bool globalCompletion)
|
||||
{
|
||||
_globalCompletion = globalCompletion;
|
||||
}
|
||||
|
||||
void setEnumerateGeneratedSlots(bool enumerate)
|
||||
{
|
||||
_enumerateGeneratedSlots = enumerate;
|
||||
}
|
||||
|
||||
QHash<QString, const Interpreter::Value *> operator ()(const Interpreter::Value *value)
|
||||
{
|
||||
_processed.clear();
|
||||
_properties.clear();
|
||||
_currentObject = Interpreter::value_cast<const Interpreter::ObjectValue *>(value);
|
||||
|
||||
enumerateProperties(value);
|
||||
|
||||
return _properties;
|
||||
}
|
||||
|
||||
QHash<QString, const Interpreter::Value *> operator ()()
|
||||
{
|
||||
_processed.clear();
|
||||
_properties.clear();
|
||||
_currentObject = 0;
|
||||
|
||||
foreach (const Interpreter::ObjectValue *scope, _context->scopeChain().all())
|
||||
enumerateProperties(scope);
|
||||
|
||||
return _properties;
|
||||
}
|
||||
|
||||
private:
|
||||
void insertProperty(const QString &name, const Interpreter::Value *value)
|
||||
{
|
||||
_properties.insert(name, value);
|
||||
}
|
||||
|
||||
virtual bool processProperty(const QString &name, const Interpreter::Value *value)
|
||||
{
|
||||
insertProperty(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool processEnumerator(const QString &name, const Interpreter::Value *value)
|
||||
{
|
||||
if (! _globalCompletion)
|
||||
insertProperty(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool processSignal(const QString &, const Interpreter::Value *)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool processSlot(const QString &name, const Interpreter::Value *value)
|
||||
{
|
||||
insertProperty(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool processGeneratedSlot(const QString &name, const Interpreter::Value *value)
|
||||
{
|
||||
if (_enumerateGeneratedSlots || (_currentObject && _currentObject->className().endsWith(QLatin1String("Keys")))) {
|
||||
// ### FIXME: add support for attached properties.
|
||||
insertProperty(name, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void enumerateProperties(const Interpreter::Value *value)
|
||||
{
|
||||
if (! value)
|
||||
return;
|
||||
else if (const Interpreter::ObjectValue *object = value->asObjectValue()) {
|
||||
enumerateProperties(object);
|
||||
}
|
||||
}
|
||||
|
||||
void enumerateProperties(const Interpreter::ObjectValue *object)
|
||||
{
|
||||
if (! object || _processed.contains(object))
|
||||
return;
|
||||
|
||||
_processed.insert(object);
|
||||
enumerateProperties(object->prototype(_context));
|
||||
|
||||
object->processMembers(this);
|
||||
}
|
||||
};
|
||||
|
||||
const Interpreter::Value *getPropertyValue(const Interpreter::ObjectValue *object,
|
||||
const QStringList &propertyNames,
|
||||
const Interpreter::Context *context)
|
||||
{
|
||||
if (propertyNames.isEmpty() || !object)
|
||||
return 0;
|
||||
|
||||
const Interpreter::Value *value = object;
|
||||
foreach (const QString &name, propertyNames) {
|
||||
if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) {
|
||||
value = objectValue->property(name, context);
|
||||
if (!value)
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool isLiteral(AST::Node *ast)
|
||||
{
|
||||
if (AST::cast<AST::StringLiteral *>(ast))
|
||||
return true;
|
||||
else if (AST::cast<AST::NumericLiteral *>(ast))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Anonymous
|
||||
|
||||
// -----------------------
|
||||
// QmlJSAssistProposalItem
|
||||
// -----------------------
|
||||
bool QmlJSAssistProposalItem::prematurelyApplies(const QChar &c) const
|
||||
{
|
||||
if (data().canConvert<QString>()) // snippet
|
||||
return false;
|
||||
|
||||
return (text().endsWith(QLatin1String(": ")) && c == QLatin1Char(':'))
|
||||
|| (text().endsWith(QLatin1Char('.')) && c == QLatin1Char('.'));
|
||||
}
|
||||
|
||||
void QmlJSAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor *editor,
|
||||
int basePosition) const
|
||||
{
|
||||
const int currentPosition = editor->position();
|
||||
editor->setCursorPosition(basePosition);
|
||||
editor->remove(currentPosition - basePosition);
|
||||
|
||||
QString replaceable;
|
||||
const QString &content = text();
|
||||
if (content.endsWith(QLatin1String(": ")))
|
||||
replaceable = QLatin1String(": ");
|
||||
else if (content.endsWith(QLatin1Char('.')))
|
||||
replaceable = QLatin1String(".");
|
||||
int replacedLength = 0;
|
||||
for (int i = 0; i < replaceable.length(); ++i) {
|
||||
const QChar a = replaceable.at(i);
|
||||
const QChar b = editor->characterAt(editor->position() + i);
|
||||
if (a == b)
|
||||
++replacedLength;
|
||||
else
|
||||
break;
|
||||
}
|
||||
const int length = editor->position() - basePosition + replacedLength;
|
||||
editor->replace(length, content);
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// FunctionHintProposalModel
|
||||
// -------------------------
|
||||
class FunctionHintProposalModel : public TextEditor::IFunctionHintProposalModel
|
||||
{
|
||||
public:
|
||||
FunctionHintProposalModel(const QString &functionName, const QStringList &signature)
|
||||
: m_functionName(functionName)
|
||||
, m_signature(signature)
|
||||
, m_minimumArgumentCount(signature.size())
|
||||
{}
|
||||
|
||||
virtual void reset() {}
|
||||
virtual int size() const { return 1; }
|
||||
virtual QString text(int index) const;
|
||||
virtual int activeArgument(const QString &prefix) const;
|
||||
|
||||
private:
|
||||
QString m_functionName;
|
||||
QStringList m_signature;
|
||||
int m_minimumArgumentCount;
|
||||
};
|
||||
|
||||
QString FunctionHintProposalModel::text(int index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
|
||||
QString prettyMethod;
|
||||
prettyMethod += QString::fromLatin1("function ");
|
||||
prettyMethod += m_functionName;
|
||||
prettyMethod += QLatin1Char('(');
|
||||
for (int i = 0; i < m_minimumArgumentCount; ++i) {
|
||||
if (i != 0)
|
||||
prettyMethod += QLatin1String(", ");
|
||||
|
||||
QString arg = m_signature.at(i);
|
||||
if (arg.isEmpty()) {
|
||||
arg = QLatin1String("arg");
|
||||
arg += QString::number(i + 1);
|
||||
}
|
||||
|
||||
prettyMethod += arg;
|
||||
}
|
||||
prettyMethod += QLatin1Char(')');
|
||||
return prettyMethod;
|
||||
}
|
||||
|
||||
int FunctionHintProposalModel::activeArgument(const QString &prefix) const
|
||||
{
|
||||
int argnr = 0;
|
||||
int parcount = 0;
|
||||
Scanner tokenize;
|
||||
const QList<Token> tokens = tokenize(prefix);
|
||||
for (int i = 0; i < tokens.count(); ++i) {
|
||||
const Token &tk = tokens.at(i);
|
||||
if (tk.is(Token::LeftParenthesis))
|
||||
++parcount;
|
||||
else if (tk.is(Token::RightParenthesis))
|
||||
--parcount;
|
||||
else if (! parcount && tk.is(Token::Colon))
|
||||
++argnr;
|
||||
}
|
||||
|
||||
if (parcount < 0)
|
||||
return -1;
|
||||
|
||||
return argnr;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// QmlJSCompletionAssistProvider
|
||||
// -----------------------------
|
||||
bool QmlJSCompletionAssistProvider::supportsEditor(const QString &editorId) const
|
||||
{
|
||||
return editorId == QLatin1String(Constants::C_QMLJSEDITOR_ID);
|
||||
}
|
||||
|
||||
int QmlJSCompletionAssistProvider::activationCharSequenceLength() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool QmlJSCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
||||
{
|
||||
return isActivationChar(sequence.at(0));
|
||||
}
|
||||
|
||||
bool QmlJSCompletionAssistProvider::isContinuationChar(const QChar &c) const
|
||||
{
|
||||
return isIdentifierChar(c, false);
|
||||
}
|
||||
|
||||
IAssistProcessor *QmlJSCompletionAssistProvider::createProcessor() const
|
||||
{
|
||||
return new QmlJSCompletionAssistProcessor;
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// QmlJSCompletionAssistProcessor
|
||||
// ------------------------------
|
||||
QmlJSCompletionAssistProcessor::QmlJSCompletionAssistProcessor()
|
||||
: m_startPosition(0)
|
||||
, m_snippetCollector(Constants::QML_SNIPPETS_GROUP_ID, iconForColor(Qt::red), SnippetOrder)
|
||||
{}
|
||||
|
||||
QmlJSCompletionAssistProcessor::~QmlJSCompletionAssistProcessor()
|
||||
{}
|
||||
|
||||
IAssistProposal *QmlJSCompletionAssistProcessor::createContentProposal() const
|
||||
{
|
||||
IGenericProposalModel *model = new QmlJSAssistProposalModel(m_completions);
|
||||
IAssistProposal *proposal = new GenericProposal(m_startPosition, model);
|
||||
return proposal;
|
||||
}
|
||||
|
||||
IAssistProposal *QmlJSCompletionAssistProcessor::createHintProposal(const QString &functionName,
|
||||
const QStringList &signature) const
|
||||
{
|
||||
IFunctionHintProposalModel *model = new FunctionHintProposalModel(functionName, signature);
|
||||
IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model);
|
||||
return proposal;
|
||||
}
|
||||
|
||||
IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface *assistInterface)
|
||||
{
|
||||
m_interface.reset(static_cast<const QmlJSCompletionAssistInterface *>(assistInterface));
|
||||
|
||||
if (assistInterface->reason() == IdleEditor && !acceptsIdleEditor())
|
||||
return 0;
|
||||
|
||||
const QString &fileName = m_interface->file()->fileName();
|
||||
|
||||
m_startPosition = assistInterface->position();
|
||||
while (isIdentifierChar(m_interface->document()->characterAt(m_startPosition - 1), false, false))
|
||||
--m_startPosition;
|
||||
|
||||
m_completions.clear();
|
||||
|
||||
const QmlJSCompletionAssistInterface *qmlInterface =
|
||||
static_cast<const QmlJSCompletionAssistInterface *>(assistInterface);
|
||||
const SemanticInfo &semanticInfo = qmlInterface->semanticInfo();
|
||||
if (!semanticInfo.isValid())
|
||||
return 0;
|
||||
|
||||
const Document::Ptr document = semanticInfo.document;
|
||||
const QFileInfo currentFileInfo(fileName);
|
||||
|
||||
bool isQmlFile = false;
|
||||
if (currentFileInfo.suffix() == QLatin1String("qml"))
|
||||
isQmlFile = true;
|
||||
|
||||
const QList<AST::Node *> path = semanticInfo.astPath(m_interface->position());
|
||||
LookupContext::Ptr lookupContext = semanticInfo.lookupContext(path);
|
||||
const Interpreter::Context *context = lookupContext->context();
|
||||
|
||||
// Search for the operator that triggered the completion.
|
||||
QChar completionOperator;
|
||||
if (m_startPosition > 0)
|
||||
completionOperator = m_interface->document()->characterAt(m_startPosition - 1);
|
||||
|
||||
QTextCursor startPositionCursor(qmlInterface->document());
|
||||
startPositionCursor.setPosition(m_startPosition);
|
||||
CompletionContextFinder contextFinder(startPositionCursor);
|
||||
|
||||
const Interpreter::ObjectValue *qmlScopeType = 0;
|
||||
if (contextFinder.isInQmlContext()) {
|
||||
// ### this should use semanticInfo.declaringMember instead, but that may also return functions
|
||||
for (int i = path.size() - 1; i >= 0; --i) {
|
||||
AST::Node *node = path[i];
|
||||
if (AST::cast<AST::UiObjectDefinition *>(node) || AST::cast<AST::UiObjectBinding *>(node)) {
|
||||
qmlScopeType = document->bind()->findQmlObject(node);
|
||||
if (qmlScopeType)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// fallback to getting the base type object
|
||||
if (!qmlScopeType)
|
||||
qmlScopeType = context->lookupType(document.data(), contextFinder.qmlObjectTypeName());
|
||||
}
|
||||
|
||||
if (contextFinder.isInStringLiteral()) {
|
||||
// get the text of the literal up to the cursor position
|
||||
//QTextCursor tc = textWidget->textCursor();
|
||||
QTextCursor tc(qmlInterface->document());
|
||||
tc.setPosition(qmlInterface->position());
|
||||
QmlExpressionUnderCursor expressionUnderCursor;
|
||||
expressionUnderCursor(tc);
|
||||
QString literalText = expressionUnderCursor.text();
|
||||
QTC_ASSERT(!literalText.isEmpty() && (
|
||||
literalText.at(0) == QLatin1Char('"')
|
||||
|| literalText.at(0) == QLatin1Char('\'')), return 0);
|
||||
literalText = literalText.mid(1);
|
||||
|
||||
if (contextFinder.isInImport()) {
|
||||
QStringList patterns;
|
||||
patterns << QLatin1String("*.qml") << QLatin1String("*.js");
|
||||
if (completeFileName(document->path(), literalText, patterns))
|
||||
return createContentProposal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Interpreter::Value *value =
|
||||
getPropertyValue(qmlScopeType, contextFinder.bindingPropertyName(), context);
|
||||
if (!value) {
|
||||
// do nothing
|
||||
} else if (value->asUrlValue()) {
|
||||
if (completeUrl(document->path(), literalText))
|
||||
return createContentProposal();
|
||||
}
|
||||
|
||||
// ### enum completion?
|
||||
|
||||
// completion gets triggered for / in string literals, if we don't
|
||||
// return here, this will mean the snippet completion pops up for
|
||||
// each / in a string literal that is not triggering file completion
|
||||
return 0;
|
||||
} else if (completionOperator.isSpace()
|
||||
|| completionOperator.isNull()
|
||||
|| isDelimiterChar(completionOperator)
|
||||
|| (completionOperator == QLatin1Char('(')
|
||||
&& m_startPosition != m_interface->position())) {
|
||||
|
||||
bool doGlobalCompletion = true;
|
||||
bool doQmlKeywordCompletion = true;
|
||||
bool doJsKeywordCompletion = true;
|
||||
bool doQmlTypeCompletion = false;
|
||||
|
||||
if (contextFinder.isInLhsOfBinding() && qmlScopeType) {
|
||||
doGlobalCompletion = false;
|
||||
doJsKeywordCompletion = false;
|
||||
doQmlTypeCompletion = true;
|
||||
|
||||
EnumerateProperties enumerateProperties(context);
|
||||
enumerateProperties.setGlobalCompletion(true);
|
||||
enumerateProperties.setEnumerateGeneratedSlots(true);
|
||||
|
||||
// id: is special
|
||||
BasicProposalItem *idProposalItem = new QmlJSAssistProposalItem;
|
||||
idProposalItem->setText(QLatin1String("id: "));
|
||||
idProposalItem->setIcon(m_interface->symbolIcon());
|
||||
idProposalItem->setOrder(PropertyOrder);
|
||||
m_completions.append(idProposalItem);
|
||||
|
||||
addCompletionsPropertyLhs(enumerateProperties(qmlScopeType),
|
||||
m_interface->symbolIcon(),
|
||||
PropertyOrder,
|
||||
contextFinder.isAfterOnInLhsOfBinding());
|
||||
|
||||
if (ScopeBuilder::isPropertyChangesObject(context, qmlScopeType)
|
||||
&& context->scopeChain().qmlScopeObjects.size() == 2) {
|
||||
addCompletions(enumerateProperties(context->scopeChain().qmlScopeObjects.first()),
|
||||
m_interface->symbolIcon(),
|
||||
SymbolOrder);
|
||||
}
|
||||
}
|
||||
|
||||
if (contextFinder.isInRhsOfBinding() && qmlScopeType) {
|
||||
doQmlKeywordCompletion = false;
|
||||
|
||||
// complete enum values for enum properties
|
||||
const Interpreter::Value *value =
|
||||
getPropertyValue(qmlScopeType, contextFinder.bindingPropertyName(), context);
|
||||
if (const Interpreter::QmlEnumValue *enumValue =
|
||||
dynamic_cast<const Interpreter::QmlEnumValue *>(value)) {
|
||||
foreach (const QString &key, enumValue->keys())
|
||||
addCompletion(key, m_interface->symbolIcon(),
|
||||
EnumValueOrder, QString("\"%1\"").arg(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (!contextFinder.isInImport() && !contextFinder.isInQmlContext())
|
||||
doQmlTypeCompletion = true;
|
||||
|
||||
if (doQmlTypeCompletion) {
|
||||
if (const Interpreter::ObjectValue *qmlTypes = context->scopeChain().qmlTypes) {
|
||||
EnumerateProperties enumerateProperties(context);
|
||||
addCompletions(enumerateProperties(qmlTypes), m_interface->symbolIcon(), TypeOrder);
|
||||
}
|
||||
}
|
||||
|
||||
if (doGlobalCompletion) {
|
||||
// It's a global completion.
|
||||
EnumerateProperties enumerateProperties(context);
|
||||
enumerateProperties.setGlobalCompletion(true);
|
||||
addCompletions(enumerateProperties(), m_interface->symbolIcon(), SymbolOrder);
|
||||
}
|
||||
|
||||
if (doJsKeywordCompletion) {
|
||||
// add js keywords
|
||||
addCompletions(Scanner::keywords(), m_interface->keywordIcon(), KeywordOrder);
|
||||
}
|
||||
|
||||
// add qml extra words
|
||||
if (doQmlKeywordCompletion && isQmlFile) {
|
||||
static QStringList qmlWords;
|
||||
static QStringList qmlWordsAlsoInJs;
|
||||
|
||||
if (qmlWords.isEmpty()) {
|
||||
qmlWords << QLatin1String("property")
|
||||
//<< QLatin1String("readonly")
|
||||
<< QLatin1String("signal")
|
||||
<< QLatin1String("import");
|
||||
}
|
||||
if (qmlWordsAlsoInJs.isEmpty())
|
||||
qmlWordsAlsoInJs << QLatin1String("default") << QLatin1String("function");
|
||||
|
||||
addCompletions(qmlWords, m_interface->keywordIcon(), KeywordOrder);
|
||||
if (!doJsKeywordCompletion)
|
||||
addCompletions(qmlWordsAlsoInJs, m_interface->keywordIcon(), KeywordOrder);
|
||||
}
|
||||
}
|
||||
|
||||
else if (completionOperator == QLatin1Char('.') || completionOperator == QLatin1Char('(')) {
|
||||
// Look at the expression under cursor.
|
||||
//QTextCursor tc = textWidget->textCursor();
|
||||
QTextCursor tc(qmlInterface->document());
|
||||
tc.setPosition(m_startPosition - 1);
|
||||
|
||||
QmlExpressionUnderCursor expressionUnderCursor;
|
||||
QmlJS::AST::ExpressionNode *expression = expressionUnderCursor(tc);
|
||||
|
||||
if (expression != 0 && ! isLiteral(expression)) {
|
||||
// Evaluate the expression under cursor.
|
||||
Interpreter::Engine *interp = lookupContext->engine();
|
||||
const Interpreter::Value *value =
|
||||
interp->convertToObject(lookupContext->evaluate(expression));
|
||||
//qDebug() << "type:" << interp.typeId(value);
|
||||
|
||||
if (value && completionOperator == QLatin1Char('.')) { // member completion
|
||||
EnumerateProperties enumerateProperties(context);
|
||||
if (contextFinder.isInLhsOfBinding() && qmlScopeType) {
|
||||
enumerateProperties.setEnumerateGeneratedSlots(true);
|
||||
addCompletionsPropertyLhs(enumerateProperties(value),
|
||||
m_interface->symbolIcon(),
|
||||
PropertyOrder,
|
||||
contextFinder.isAfterOnInLhsOfBinding());
|
||||
} else
|
||||
addCompletions(enumerateProperties(value), m_interface->symbolIcon(), SymbolOrder);
|
||||
} else if (value
|
||||
&& completionOperator == QLatin1Char('(')
|
||||
&& m_startPosition == m_interface->position()) {
|
||||
// function completion
|
||||
if (const Interpreter::FunctionValue *f = value->asFunctionValue()) {
|
||||
QString functionName = expressionUnderCursor.text();
|
||||
int indexOfDot = functionName.lastIndexOf(QLatin1Char('.'));
|
||||
if (indexOfDot != -1)
|
||||
functionName = functionName.mid(indexOfDot + 1);
|
||||
|
||||
QStringList signature;
|
||||
for (int i = 0; i < f->argumentCount(); ++i)
|
||||
signature.append(f->argumentName(i));
|
||||
|
||||
return createHintProposal(functionName.trimmed(), signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! m_completions.isEmpty())
|
||||
return createContentProposal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isQmlFile
|
||||
&& (completionOperator.isNull()
|
||||
|| completionOperator.isSpace()
|
||||
|| isDelimiterChar(completionOperator))) {
|
||||
m_completions.append(m_snippetCollector.collect());
|
||||
}
|
||||
|
||||
if (! m_completions.isEmpty())
|
||||
return createContentProposal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QmlJSCompletionAssistProcessor::acceptsIdleEditor() const
|
||||
{
|
||||
const int cursorPos = m_interface->position();
|
||||
|
||||
bool maybeAccept = false;
|
||||
const QChar &charBeforeCursor = m_interface->document()->characterAt(cursorPos - 1);
|
||||
if (isActivationChar(charBeforeCursor)) {
|
||||
maybeAccept = true;
|
||||
} else {
|
||||
const QChar &charUnderCursor = m_interface->document()->characterAt(cursorPos);
|
||||
if (isIdentifierChar(charBeforeCursor)
|
||||
&& ((charUnderCursor.isSpace()
|
||||
|| charUnderCursor.isNull()
|
||||
|| isDelimiterChar(charUnderCursor))
|
||||
|| isIdentifierChar(charUnderCursor))) {
|
||||
|
||||
int startPos = cursorPos - 1;
|
||||
for (; startPos != -1; --startPos) {
|
||||
if (!isIdentifierChar(m_interface->document()->characterAt(startPos)))
|
||||
break;
|
||||
}
|
||||
++startPos;
|
||||
|
||||
const QString &word = m_interface->textAt(startPos, cursorPos - startPos);
|
||||
if (word.length() > 2 && isIdentifierChar(word.at(0), true)) {
|
||||
for (int i = 1; i < word.length(); ++i) {
|
||||
if (!isIdentifierChar(word.at(i)))
|
||||
return false;
|
||||
}
|
||||
maybeAccept = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maybeAccept) {
|
||||
QTextCursor tc(m_interface->document());
|
||||
tc.setPosition(m_interface->position());
|
||||
const QTextBlock &block = tc.block();
|
||||
const QString &blockText = block.text();
|
||||
const int blockState = qMax(0, block.previous().userState()) & 0xff;
|
||||
|
||||
Scanner scanner;
|
||||
const QList<Token> tokens = scanner(blockText, blockState);
|
||||
const int column = block.position() - m_interface->position();
|
||||
foreach (const Token &tk, tokens) {
|
||||
if (column >= tk.begin() && column <= tk.end()) {
|
||||
if (charBeforeCursor == QLatin1Char('/') && tk.is(Token::String))
|
||||
return true; // path completion inside string literals
|
||||
if (tk.is(Token::Comment) || tk.is(Token::String))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (charBeforeCursor != QLatin1Char('/'))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QmlJSCompletionAssistProcessor::completeFileName(const QString &relativeBasePath,
|
||||
const QString &fileName,
|
||||
const QStringList &patterns)
|
||||
{
|
||||
const QFileInfo fileInfo(fileName);
|
||||
QString directoryPrefix;
|
||||
if (fileInfo.isRelative()) {
|
||||
directoryPrefix = relativeBasePath;
|
||||
directoryPrefix += QDir::separator();
|
||||
directoryPrefix += fileInfo.path();
|
||||
} else {
|
||||
directoryPrefix = fileInfo.path();
|
||||
}
|
||||
if (!QFileInfo(directoryPrefix).exists())
|
||||
return false;
|
||||
|
||||
QDirIterator dirIterator(directoryPrefix,
|
||||
patterns,
|
||||
QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
while (dirIterator.hasNext()) {
|
||||
dirIterator.next();
|
||||
const QString fileName = dirIterator.fileName();
|
||||
|
||||
BasicProposalItem *item = new QmlJSAssistProposalItem;
|
||||
item->setText(fileName);
|
||||
item->setIcon(m_interface->fileNameIcon());
|
||||
m_completions.append(item);
|
||||
}
|
||||
|
||||
return !m_completions.isEmpty();
|
||||
}
|
||||
|
||||
bool QmlJSCompletionAssistProcessor::completeUrl(const QString &relativeBasePath, const QString &urlString)
|
||||
{
|
||||
const QUrl url(urlString);
|
||||
QString fileName = url.toLocalFile();
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
return completeFileName(relativeBasePath, fileName);
|
||||
}
|
||||
|
||||
void QmlJSCompletionAssistProcessor::addCompletionsPropertyLhs(const QHash<QString,
|
||||
const QmlJS::Interpreter::Value *> &newCompletions,
|
||||
const QIcon &icon,
|
||||
int order,
|
||||
bool afterOn)
|
||||
{
|
||||
QHashIterator<QString, const Interpreter::Value *> it(newCompletions);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
|
||||
QString itemText = it.key();
|
||||
QLatin1String postfix(": ");
|
||||
if (afterOn)
|
||||
postfix = QLatin1String(" {");
|
||||
if (const Interpreter::QmlObjectValue *qmlValue =
|
||||
dynamic_cast<const Interpreter::QmlObjectValue *>(it.value())) {
|
||||
// to distinguish "anchors." from "gradient:" we check if the right hand side
|
||||
// type is instantiatable or is the prototype of an instantiatable object
|
||||
if (qmlValue->hasChildInPackage())
|
||||
itemText.append(postfix);
|
||||
else
|
||||
itemText.append(QLatin1Char('.'));
|
||||
} else {
|
||||
itemText.append(postfix);
|
||||
}
|
||||
|
||||
addCompletion(itemText, icon, order);
|
||||
}
|
||||
}
|
||||
|
||||
void QmlJSCompletionAssistProcessor::addCompletion(const QString &text,
|
||||
const QIcon &icon,
|
||||
int order,
|
||||
const QVariant &data)
|
||||
{
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
|
||||
BasicProposalItem *item = new QmlJSAssistProposalItem;
|
||||
item->setText(text);
|
||||
item->setIcon(icon);
|
||||
item->setOrder(order);
|
||||
item->setData(data);
|
||||
m_completions.append(item);
|
||||
}
|
||||
|
||||
void QmlJSCompletionAssistProcessor::addCompletions(const QHash<QString,
|
||||
const QmlJS::Interpreter::Value *> &newCompletions,
|
||||
const QIcon &icon,
|
||||
int order)
|
||||
{
|
||||
QHashIterator<QString, const Interpreter::Value *> it(newCompletions);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
addCompletion(it.key(), icon, order);
|
||||
}
|
||||
}
|
||||
|
||||
void QmlJSCompletionAssistProcessor::addCompletions(const QStringList &newCompletions,
|
||||
const QIcon &icon,
|
||||
int order)
|
||||
{
|
||||
foreach (const QString &text, newCompletions)
|
||||
addCompletion(text, icon, order);
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// QmlJSCompletionAssistInterface
|
||||
// ------------------------------
|
||||
QmlJSCompletionAssistInterface::QmlJSCompletionAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
TextEditor::AssistReason reason,
|
||||
const SemanticInfo &info)
|
||||
: DefaultAssistInterface(document, position, file, reason)
|
||||
, m_semanticInfo(info)
|
||||
, m_darkBlueIcon(iconForColor(Qt::darkBlue))
|
||||
, m_darkYellowIcon(iconForColor(Qt::darkYellow))
|
||||
, m_darkCyanIcon(iconForColor(Qt::darkCyan))
|
||||
{}
|
||||
|
||||
const SemanticInfo &QmlJSCompletionAssistInterface::semanticInfo() const
|
||||
{
|
||||
return m_semanticInfo;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct QmlJSLessThan
|
||||
{
|
||||
bool operator() (const BasicProposalItem *a, const BasicProposalItem *b)
|
||||
{
|
||||
if (a->order() != b->order())
|
||||
return a->order() > b->order();
|
||||
else if (a->text().isEmpty())
|
||||
return true;
|
||||
else if (b->text().isEmpty())
|
||||
return false;
|
||||
else if (a->data().isValid() != b->data().isValid())
|
||||
return a->data().isValid();
|
||||
else if (a->text().at(0).isUpper() && b->text().at(0).isLower())
|
||||
return false;
|
||||
else if (a->text().at(0).isLower() && b->text().at(0).isUpper())
|
||||
return true;
|
||||
return a->text() < b->text();
|
||||
}
|
||||
};
|
||||
|
||||
} // Anonymous
|
||||
|
||||
// -------------------------
|
||||
// QmlJSAssistProposalModel
|
||||
// -------------------------
|
||||
void QmlJSAssistProposalModel::sort()
|
||||
{
|
||||
qSort(currentItems().first, currentItems().second, QmlJSLessThan());
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QMLJSCOMPLETIONASSIST_H
|
||||
#define QMLJSCOMPLETIONASSIST_H
|
||||
|
||||
#include "qmljseditor.h"
|
||||
|
||||
#include <texteditor/codeassist/basicproposalitem.h>
|
||||
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
|
||||
#include <texteditor/codeassist/completionassistprovider.h>
|
||||
#include <texteditor/codeassist/iassistprocessor.h>
|
||||
#include <texteditor/snippets/snippetassistcollector.h>
|
||||
#include <texteditor/codeassist/defaultassistinterface.h>
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace QmlJS {
|
||||
namespace Interpreter {
|
||||
class Value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace QmlJSEditor {
|
||||
namespace Internal {
|
||||
|
||||
class QmlJSCompletionAssistInterface;
|
||||
|
||||
class QmlJSAssistProposalItem : public TextEditor::BasicProposalItem
|
||||
{
|
||||
public:
|
||||
virtual bool prematurelyApplies(const QChar &c) const;
|
||||
virtual void applyContextualContent(TextEditor::BaseTextEditor *editor,
|
||||
int basePosition) const;
|
||||
};
|
||||
|
||||
|
||||
class QmlJSAssistProposalModel : public TextEditor::BasicProposalItemListModel
|
||||
{
|
||||
public:
|
||||
QmlJSAssistProposalModel(const QList<TextEditor::BasicProposalItem *> &items)
|
||||
: TextEditor::BasicProposalItemListModel(items)
|
||||
{}
|
||||
|
||||
virtual void sort();
|
||||
};
|
||||
|
||||
|
||||
class QmlJSCompletionAssistProvider : public TextEditor::CompletionAssistProvider
|
||||
{
|
||||
public:
|
||||
virtual bool supportsEditor(const QString &editorId) const;
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
|
||||
virtual int activationCharSequenceLength() const;
|
||||
virtual bool isActivationCharSequence(const QString &sequence) const;
|
||||
virtual bool isContinuationChar(const QChar &c) const;
|
||||
};
|
||||
|
||||
|
||||
class QmlJSCompletionAssistProcessor : public TextEditor::IAssistProcessor
|
||||
{
|
||||
public:
|
||||
QmlJSCompletionAssistProcessor();
|
||||
virtual ~QmlJSCompletionAssistProcessor();
|
||||
|
||||
virtual TextEditor::IAssistProposal *perform(const TextEditor::IAssistInterface *interface);
|
||||
|
||||
private:
|
||||
TextEditor::IAssistProposal *createContentProposal() const;
|
||||
TextEditor::IAssistProposal *createHintProposal(const QString &functionName,
|
||||
const QStringList &signature) const;
|
||||
|
||||
bool acceptsIdleEditor() const;
|
||||
|
||||
bool completeUrl(const QString &relativeBasePath, const QString &urlString);
|
||||
bool completeFileName(const QString &relativeBasePath,
|
||||
const QString &fileName,
|
||||
const QStringList &patterns = QStringList());
|
||||
|
||||
void addCompletion(const QString &text,
|
||||
const QIcon &icon,
|
||||
int order,
|
||||
const QVariant &data = QVariant());
|
||||
void addCompletions(const QHash<QString, const QmlJS::Interpreter::Value *> &newCompletions,
|
||||
const QIcon &icon,
|
||||
int order);
|
||||
void addCompletions(const QStringList &newCompletions, const QIcon &icon, int order);
|
||||
void addCompletionsPropertyLhs(const QHash<QString,
|
||||
const QmlJS::Interpreter::Value *> &newCompletions,
|
||||
const QIcon &icon,
|
||||
int order,
|
||||
bool afterOn);
|
||||
|
||||
int m_startPosition;
|
||||
QScopedPointer<const QmlJSCompletionAssistInterface> m_interface;
|
||||
QList<TextEditor::BasicProposalItem *> m_completions;
|
||||
TextEditor::SnippetAssistCollector m_snippetCollector;
|
||||
const TextEditor::IAssistProvider *m_provider;
|
||||
};
|
||||
|
||||
|
||||
class QmlJSCompletionAssistInterface : public TextEditor::DefaultAssistInterface
|
||||
{
|
||||
public:
|
||||
QmlJSCompletionAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
TextEditor::AssistReason reason,
|
||||
const SemanticInfo &info);
|
||||
const SemanticInfo &semanticInfo() const;
|
||||
const QIcon &fileNameIcon() const { return m_darkBlueIcon; }
|
||||
const QIcon &keywordIcon() const { return m_darkYellowIcon; }
|
||||
const QIcon &symbolIcon() const { return m_darkCyanIcon; }
|
||||
|
||||
private:
|
||||
SemanticInfo m_semanticInfo;
|
||||
QIcon m_darkBlueIcon;
|
||||
QIcon m_darkYellowIcon;
|
||||
QIcon m_darkCyanIcon;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // QmlJSEditor
|
||||
|
||||
#endif // QMLJSCOMPLETIONASSIST_H
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "qmljscomponentfromobjectdef.h"
|
||||
#include "qmljscomponentnamedialog.h"
|
||||
#include "qmljsquickfixassist.h"
|
||||
|
||||
#include <coreplugin/ifile.h>
|
||||
|
||||
@@ -93,8 +94,9 @@ class Operation: public QmlJSQuickFixOperation
|
||||
QString m_idName, m_componentName;
|
||||
|
||||
public:
|
||||
Operation(const QmlJSQuickFixState &state, UiObjectDefinition *objDef)
|
||||
: QmlJSQuickFixOperation(state, 0)
|
||||
Operation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface,
|
||||
UiObjectDefinition *objDef)
|
||||
: QmlJSQuickFixOperation(interface, 0)
|
||||
, m_objDef(objDef)
|
||||
{
|
||||
Q_ASSERT(m_objDef != 0);
|
||||
@@ -117,7 +119,7 @@ public:
|
||||
QString componentName = m_componentName;
|
||||
QString path = QFileInfo(fileName()).path();
|
||||
if (componentName.isEmpty()) {
|
||||
ComponentNameDialog::go(&componentName, &path, state().editor());
|
||||
ComponentNameDialog::go(&componentName, &path, assistInterface()->widget());
|
||||
}
|
||||
|
||||
if (componentName.isEmpty() || path.isEmpty())
|
||||
@@ -157,19 +159,21 @@ public:
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
QList<QmlJSQuickFixOperation::Ptr> ComponentFromObjectDef::match(const QmlJSQuickFixState &state)
|
||||
{
|
||||
const int pos = state.currentFile().cursor().position();
|
||||
|
||||
QList<Node *> path = state.semanticInfo().astPath(pos);
|
||||
QList<QmlJSQuickFixOperation::Ptr> ComponentFromObjectDef::match(
|
||||
const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface)
|
||||
{
|
||||
const int pos = interface->currentFile().cursor().position();
|
||||
|
||||
QList<Node *> path = interface->semanticInfo().astPath(pos);
|
||||
for (int i = path.size() - 1; i >= 0; --i) {
|
||||
Node *node = path.at(i);
|
||||
if (UiObjectDefinition *objDef = cast<UiObjectDefinition *>(node)) {
|
||||
if (!state.currentFile().isCursorOn(objDef->qualifiedTypeNameId))
|
||||
if (!interface->currentFile().isCursorOn(objDef->qualifiedTypeNameId))
|
||||
return noResult();
|
||||
// check that the node is not the root node
|
||||
if (i > 0 && !cast<UiProgram*>(path.at(i - 1))) {
|
||||
return singleResult(new Operation(state, objDef));
|
||||
return singleResult(new Operation(interface, objDef));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ namespace Internal {
|
||||
class ComponentFromObjectDef: public QmlJSQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state);
|
||||
virtual QList<QmlJSQuickFixOperation::Ptr> match(
|
||||
const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -35,12 +35,13 @@
|
||||
#include "qmljseditorconstants.h"
|
||||
#include "qmljshighlighter.h"
|
||||
#include "qmljseditorplugin.h"
|
||||
#include "qmljsquickfix.h"
|
||||
#include "qmloutlinemodel.h"
|
||||
#include "qmljsfindreferences.h"
|
||||
#include "qmljssemantichighlighter.h"
|
||||
#include "qmljsindenter.h"
|
||||
#include "qmljsautocompleter.h"
|
||||
#include "qmljscompletionassist.h"
|
||||
#include "qmljsquickfixassist.h"
|
||||
|
||||
#include <qmljs/qmljsbind.h>
|
||||
#include <qmljs/qmljsevaluate.h>
|
||||
@@ -70,6 +71,8 @@
|
||||
#include <texteditor/syntaxhighlighter.h>
|
||||
#include <texteditor/refactoroverlay.h>
|
||||
#include <texteditor/tooltip/tooltip.h>
|
||||
#include <texteditor/codeassist/genericproposal.h>
|
||||
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
|
||||
#include <qmldesigner/qmldesignerconstants.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <utils/changeset.h>
|
||||
@@ -78,6 +81,7 @@
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QSignalMapper>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QComboBox>
|
||||
@@ -1347,21 +1351,30 @@ void QmlJSTextEditorWidget::contextMenuEvent(QContextMenuEvent *e)
|
||||
connect(a, SIGNAL(triggered()), this, SLOT(renameIdUnderCursor()));
|
||||
}
|
||||
|
||||
// Add other refactoring actions:
|
||||
QmlJSQuickFixCollector *quickFixCollector = QmlJSEditorPlugin::instance()->quickFixCollector();
|
||||
QSignalMapper mapper;
|
||||
connect(&mapper, SIGNAL(mapped(int)), this, SLOT(performQuickFix(int)));
|
||||
|
||||
if (! isOutdated()) {
|
||||
if (quickFixCollector->startCompletion(editor()) != -1) {
|
||||
m_quickFixes = quickFixCollector->quickFixes();
|
||||
|
||||
for (int index = 0; index < m_quickFixes.size(); ++index) {
|
||||
TextEditor::QuickFixOperation::Ptr op = m_quickFixes.at(index);
|
||||
TextEditor::IAssistInterface *interface =
|
||||
createAssistInterface(TextEditor::QuickFix, TextEditor::ExplicitlyInvoked);
|
||||
if (interface) {
|
||||
QScopedPointer<TextEditor::IAssistProcessor> processor(
|
||||
QmlJSEditorPlugin::instance()->quickFixAssistProvider()->createProcessor());
|
||||
QScopedPointer<TextEditor::IAssistProposal> proposal(processor->perform(interface));
|
||||
if (!proposal.isNull()) {
|
||||
TextEditor::BasicProposalItemListModel *model =
|
||||
static_cast<TextEditor::BasicProposalItemListModel *>(proposal->model());
|
||||
for (int index = 0; index < model->size(); ++index) {
|
||||
TextEditor::BasicProposalItem *item =
|
||||
static_cast<TextEditor::BasicProposalItem *>(model->proposalItem(index));
|
||||
TextEditor::QuickFixOperation::Ptr op =
|
||||
item->data().value<TextEditor::QuickFixOperation::Ptr>();
|
||||
m_quickFixes.append(op);
|
||||
QAction *action = refactoringMenu->addAction(op->description());
|
||||
mapper.setMapping(action, index);
|
||||
connect(action, SIGNAL(triggered()), &mapper, SLOT(map()));
|
||||
}
|
||||
delete model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1380,7 +1393,6 @@ void QmlJSTextEditorWidget::contextMenuEvent(QContextMenuEvent *e)
|
||||
|
||||
menu->exec(e->globalPos());
|
||||
menu->deleteLater();
|
||||
quickFixCollector->cleanup();
|
||||
m_quickFixes.clear();
|
||||
}
|
||||
|
||||
@@ -1578,3 +1590,19 @@ SemanticHighlighterSource QmlJSTextEditorWidget::currentSource(bool force)
|
||||
source.force = force;
|
||||
return source;
|
||||
}
|
||||
|
||||
TextEditor::IAssistInterface *QmlJSTextEditorWidget::createAssistInterface(
|
||||
TextEditor::AssistKind assistKind,
|
||||
TextEditor::AssistReason reason) const
|
||||
{
|
||||
if (assistKind == TextEditor::Completion) {
|
||||
return new QmlJSCompletionAssistInterface(document(),
|
||||
position(),
|
||||
editor()->file(),
|
||||
reason,
|
||||
m_semanticInfo);
|
||||
} else if (assistKind == TextEditor::QuickFix) {
|
||||
return new QmlJSQuickFixAssistInterface(const_cast<QmlJSTextEditorWidget *>(this), reason);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,9 @@ public:
|
||||
|
||||
static QVector<QString> highlighterFormatCategories();
|
||||
|
||||
TextEditor::IAssistInterface *createAssistInterface(TextEditor::AssistKind assistKind,
|
||||
TextEditor::AssistReason reason) const;
|
||||
|
||||
public slots:
|
||||
void forceSemanticRehighlight();
|
||||
void followSymbolUnderCursor();
|
||||
|
||||
@@ -8,7 +8,6 @@ DEFINES += \
|
||||
QT_CREATOR
|
||||
|
||||
HEADERS += \
|
||||
qmljscodecompletion.h \
|
||||
qmljseditor.h \
|
||||
qmljseditor_global.h \
|
||||
qmljseditoractionhandler.h \
|
||||
@@ -20,7 +19,6 @@ HEADERS += \
|
||||
qmljshighlighter.h \
|
||||
qmljshoverhandler.h \
|
||||
qmljspreviewrunner.h \
|
||||
qmljsquickfix.h \
|
||||
qmljscomponentfromobjectdef.h \
|
||||
qmljsoutline.h \
|
||||
qmloutlinemodel.h \
|
||||
@@ -35,10 +33,13 @@ HEADERS += \
|
||||
qmljsindenter.h \
|
||||
qmljsautocompleter.h \
|
||||
jsfilewizard.h \
|
||||
qmljssnippetprovider.h
|
||||
qmljssnippetprovider.h \
|
||||
qmljsreuse.h \
|
||||
qmljsquickfixassist.h \
|
||||
qmljscompletionassist.h \
|
||||
qmljsquickfix.h
|
||||
|
||||
SOURCES += \
|
||||
qmljscodecompletion.cpp \
|
||||
qmljseditor.cpp \
|
||||
qmljseditoractionhandler.cpp \
|
||||
qmljseditorfactory.cpp \
|
||||
@@ -48,7 +49,6 @@ SOURCES += \
|
||||
qmljshighlighter.cpp \
|
||||
qmljshoverhandler.cpp \
|
||||
qmljspreviewrunner.cpp \
|
||||
qmljsquickfix.cpp \
|
||||
qmljscomponentfromobjectdef.cpp \
|
||||
qmljsoutline.cpp \
|
||||
qmloutlinemodel.cpp \
|
||||
@@ -64,7 +64,11 @@ SOURCES += \
|
||||
qmljsindenter.cpp \
|
||||
qmljsautocompleter.cpp \
|
||||
jsfilewizard.cpp \
|
||||
qmljssnippetprovider.cpp
|
||||
qmljssnippetprovider.cpp \
|
||||
qmljsreuse.cpp \
|
||||
qmljsquickfixassist.cpp \
|
||||
qmljscompletionassist.cpp \
|
||||
qmljsquickfix.cpp
|
||||
|
||||
RESOURCES += qmljseditor.qrc
|
||||
OTHER_FILES += QmlJSEditor.mimetypes.xml
|
||||
|
||||
@@ -35,17 +35,17 @@
|
||||
#include "qmljseditor.h"
|
||||
#include "qmljseditorconstants.h"
|
||||
#include "qmljseditorfactory.h"
|
||||
#include "qmljscodecompletion.h"
|
||||
#include "qmljshoverhandler.h"
|
||||
#include "qmlfilewizard.h"
|
||||
#include "jsfilewizard.h"
|
||||
#include "qmljsoutline.h"
|
||||
#include "qmljspreviewrunner.h"
|
||||
#include "qmljsquickfix.h"
|
||||
#include "qmljssnippetprovider.h"
|
||||
#include "qmltaskmanager.h"
|
||||
#include "quicktoolbar.h"
|
||||
#include "quicktoolbarsettingspage.h"
|
||||
#include "qmljscompletionassist.h"
|
||||
#include "qmljsquickfixassist.h"
|
||||
|
||||
#include <qmljs/qmljsicons.h>
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
@@ -69,7 +69,6 @@
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/textfilewizard.h>
|
||||
#include <texteditor/texteditoractionhandler.h>
|
||||
#include <texteditor/completionsupport.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QtPlugin>
|
||||
@@ -89,21 +88,18 @@ enum {
|
||||
QUICKFIX_INTERVAL = 20
|
||||
};
|
||||
|
||||
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
|
||||
|
||||
QmlJSEditorPlugin *QmlJSEditorPlugin::m_instance = 0;
|
||||
|
||||
QmlJSEditorPlugin::QmlJSEditorPlugin() :
|
||||
m_modelManager(0),
|
||||
m_wizard(0),
|
||||
m_editor(0),
|
||||
m_actionHandler(0)
|
||||
m_actionHandler(0),
|
||||
m_quickFixAssistProvider(0)
|
||||
{
|
||||
m_instance = this;
|
||||
|
||||
m_quickFixCollector = 0;
|
||||
m_quickFixTimer = new QTimer(this);
|
||||
m_quickFixTimer->setInterval(20);
|
||||
m_quickFixTimer->setSingleShot(true);
|
||||
connect(m_quickFixTimer, SIGNAL(timeout()), this, SLOT(quickFixNow()));
|
||||
}
|
||||
|
||||
QmlJSEditorPlugin::~QmlJSEditorPlugin()
|
||||
@@ -211,25 +207,18 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
|
||||
cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
|
||||
contextMenu->addAction(cmd);
|
||||
|
||||
CodeCompletion *completion = new CodeCompletion(m_modelManager);
|
||||
addAutoReleasedObject(completion);
|
||||
m_quickFixAssistProvider = new QmlJSQuickFixAssistProvider;
|
||||
addAutoReleasedObject(m_quickFixAssistProvider);
|
||||
addAutoReleasedObject(new QmlJSCompletionAssistProvider);
|
||||
|
||||
addAutoReleasedObject(new HoverHandler);
|
||||
|
||||
// Set completion settings and keep them up to date
|
||||
TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
|
||||
completion->setCompletionSettings(textEditorSettings->completionSettings());
|
||||
connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
|
||||
completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
|
||||
|
||||
error_message->clear();
|
||||
|
||||
Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance();
|
||||
iconProvider->registerIconOverlayForSuffix(QIcon(QLatin1String(":/qmljseditor/images/qmlfile.png")), "qml");
|
||||
|
||||
m_quickFixCollector = new QmlJSQuickFixCollector;
|
||||
addAutoReleasedObject(m_quickFixCollector);
|
||||
QmlJSQuickFixCollector::registerQuickFixes(this);
|
||||
registerQuickFixes(this);
|
||||
|
||||
addAutoReleasedObject(new QmlJSOutlineWidgetFactory);
|
||||
|
||||
@@ -313,35 +302,9 @@ Core::Command *QmlJSEditorPlugin::addToolAction(QAction *a, Core::ActionManager
|
||||
return command;
|
||||
}
|
||||
|
||||
QmlJSQuickFixCollector *QmlJSEditorPlugin::quickFixCollector() const
|
||||
{ return m_quickFixCollector; }
|
||||
|
||||
void QmlJSEditorPlugin::quickFix(TextEditor::ITextEditor *editable)
|
||||
QmlJSQuickFixAssistProvider *QmlJSEditorPlugin::quickFixAssistProvider() const
|
||||
{
|
||||
m_currentTextEditable = editable;
|
||||
quickFixNow();
|
||||
}
|
||||
|
||||
void QmlJSEditorPlugin::quickFixNow()
|
||||
{
|
||||
if (! m_currentTextEditable)
|
||||
return;
|
||||
|
||||
Core::EditorManager *em = Core::EditorManager::instance();
|
||||
QmlJSTextEditorWidget *currentEditor = qobject_cast<QmlJSTextEditorWidget*>(em->currentEditor()->widget());
|
||||
|
||||
if (QmlJSTextEditorWidget *editor = qobject_cast<QmlJSTextEditorWidget*>(m_currentTextEditable->widget())) {
|
||||
if (currentEditor == editor) {
|
||||
if (editor->isOutdated()) {
|
||||
// qDebug() << "TODO: outdated document" << editor->editorRevision() << editor->semanticInfo().revision();
|
||||
// ### FIXME: m_quickFixTimer->start(QUICKFIX_INTERVAL);
|
||||
m_quickFixTimer->stop();
|
||||
} else {
|
||||
TextEditor::CompletionSupport::instance()
|
||||
->complete(m_currentTextEditable, TextEditor::QuickFixCompletion, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_quickFixAssistProvider;
|
||||
}
|
||||
|
||||
void QmlJSEditorPlugin::currentEditorChanged(Core::IEditor *editor)
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Internal {
|
||||
|
||||
class QmlJSEditorFactory;
|
||||
class QmlJSPreviewRunner;
|
||||
class QmlJSQuickFixCollector;
|
||||
class QmlJSQuickFixAssistProvider;
|
||||
class QmlTaskManager;
|
||||
|
||||
class QmlJSEditorPlugin : public ExtensionSystem::IPlugin
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
static QmlJSEditorPlugin *instance()
|
||||
{ return m_instance; }
|
||||
|
||||
QmlJSQuickFixCollector *quickFixCollector() const;
|
||||
QmlJSQuickFixAssistProvider *quickFixAssistProvider() const;
|
||||
|
||||
void initializeEditor(QmlJSEditor::QmlJSTextEditorWidget *editor);
|
||||
|
||||
@@ -97,8 +97,6 @@ public Q_SLOTS:
|
||||
void showContextPane();
|
||||
|
||||
private Q_SLOTS:
|
||||
void quickFix(TextEditor::ITextEditor *editable);
|
||||
void quickFixNow();
|
||||
void currentEditorChanged(Core::IEditor *editor);
|
||||
|
||||
private:
|
||||
@@ -115,9 +113,8 @@ private:
|
||||
QmlJSEditorFactory *m_editor;
|
||||
TextEditor::TextEditorActionHandler *m_actionHandler;
|
||||
|
||||
QmlJSQuickFixCollector *m_quickFixCollector;
|
||||
QmlJSQuickFixAssistProvider *m_quickFixAssistProvider;
|
||||
|
||||
QTimer *m_quickFixTimer;
|
||||
QPointer<TextEditor::ITextEditor> m_currentTextEditable;
|
||||
QmlTaskManager *m_qmlTaskManager;
|
||||
};
|
||||
|
||||
@@ -56,8 +56,6 @@ class QmlJSTextEditorWidget;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class SemanticInfo;
|
||||
|
||||
class HoverHandler : public TextEditor::BaseHoverHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "qmljscomponentfromobjectdef.h"
|
||||
#include "qmljseditor.h"
|
||||
#include "qmljs/parser/qmljsast_p.h"
|
||||
#include "qmljsquickfixassist.h"
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
@@ -50,34 +51,11 @@ using namespace QmlJSTools;
|
||||
using namespace TextEditor;
|
||||
using TextEditor::RefactoringChanges;
|
||||
|
||||
QmlJSQuickFixState::QmlJSQuickFixState(TextEditor::BaseTextEditorWidget *editor)
|
||||
: QuickFixState(editor)
|
||||
{
|
||||
}
|
||||
|
||||
SemanticInfo QmlJSQuickFixState::semanticInfo() const
|
||||
{
|
||||
return _semanticInfo;
|
||||
}
|
||||
|
||||
Snapshot QmlJSQuickFixState::snapshot() const
|
||||
{
|
||||
return _semanticInfo.snapshot;
|
||||
}
|
||||
|
||||
Document::Ptr QmlJSQuickFixState::document() const
|
||||
{
|
||||
return _semanticInfo.document;
|
||||
}
|
||||
|
||||
const QmlJSRefactoringFile QmlJSQuickFixState::currentFile() const
|
||||
{
|
||||
return QmlJSRefactoringFile(editor(), document());
|
||||
}
|
||||
|
||||
QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority)
|
||||
QmlJSQuickFixOperation::QmlJSQuickFixOperation(
|
||||
const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface,
|
||||
int priority)
|
||||
: QuickFixOperation(priority)
|
||||
, _state(state)
|
||||
, m_interface(interface)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -88,20 +66,21 @@ QmlJSQuickFixOperation::~QmlJSQuickFixOperation()
|
||||
void QmlJSQuickFixOperation::perform()
|
||||
{
|
||||
QmlJSRefactoringChanges refactoring(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(),
|
||||
_state.snapshot());
|
||||
//_state.snapshot());
|
||||
m_interface->semanticInfo().snapshot);
|
||||
QmlJSRefactoringFile current = refactoring.file(fileName());
|
||||
|
||||
performChanges(¤t, &refactoring);
|
||||
}
|
||||
|
||||
const QmlJSQuickFixState &QmlJSQuickFixOperation::state() const
|
||||
const QmlJSQuickFixAssistInterface *QmlJSQuickFixOperation::assistInterface() const
|
||||
{
|
||||
return _state;
|
||||
return m_interface.data();
|
||||
}
|
||||
|
||||
QString QmlJSQuickFixOperation::fileName() const
|
||||
{
|
||||
return state().document()->fileName();
|
||||
return m_interface->semanticInfo().document->fileName();
|
||||
}
|
||||
|
||||
QmlJSQuickFixFactory::QmlJSQuickFixFactory()
|
||||
@@ -112,12 +91,10 @@ QmlJSQuickFixFactory::~QmlJSQuickFixFactory()
|
||||
{
|
||||
}
|
||||
|
||||
QList<QuickFixOperation::Ptr> QmlJSQuickFixFactory::matchingOperations(QuickFixState *state)
|
||||
QList<QuickFixOperation::Ptr> QmlJSQuickFixFactory::matchingOperations(
|
||||
const QSharedPointer<const TextEditor::IAssistInterface> &interface)
|
||||
{
|
||||
if (QmlJSQuickFixState *qmljsState = static_cast<QmlJSQuickFixState *>(state))
|
||||
return match(*qmljsState);
|
||||
else
|
||||
return QList<TextEditor::QuickFixOperation::Ptr>();
|
||||
return match(interface.staticCast<const QmlJSQuickFixAssistInterface>());
|
||||
}
|
||||
|
||||
QList<QmlJSQuickFixOperation::Ptr> QmlJSQuickFixFactory::noResult()
|
||||
@@ -131,49 +108,3 @@ QList<QmlJSQuickFixOperation::Ptr> QmlJSQuickFixFactory::singleResult(QmlJSQuick
|
||||
result.append(QmlJSQuickFixOperation::Ptr(operation));
|
||||
return result;
|
||||
}
|
||||
|
||||
QmlJSQuickFixCollector::QmlJSQuickFixCollector()
|
||||
{
|
||||
}
|
||||
|
||||
QmlJSQuickFixCollector::~QmlJSQuickFixCollector()
|
||||
{
|
||||
}
|
||||
|
||||
bool QmlJSQuickFixCollector::supportsEditor(TextEditor::ITextEditor *editable) const
|
||||
{
|
||||
return qobject_cast<QmlJSTextEditorWidget *>(editable->widget()) != 0;
|
||||
}
|
||||
|
||||
bool QmlJSQuickFixCollector::supportsPolicy(TextEditor::CompletionPolicy policy) const
|
||||
{
|
||||
return policy == TextEditor::QuickFixCompletion;
|
||||
}
|
||||
|
||||
TextEditor::QuickFixState *QmlJSQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditorWidget *editor)
|
||||
{
|
||||
if (QmlJSTextEditorWidget *qmljsEditor = qobject_cast<QmlJSTextEditorWidget *>(editor)) {
|
||||
const SemanticInfo info = qmljsEditor->semanticInfo();
|
||||
|
||||
if (! info.isValid() || qmljsEditor->isOutdated()) {
|
||||
// outdated
|
||||
qWarning() << "TODO: outdated semantic info, force a reparse.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
QmlJSQuickFixState *state = new QmlJSQuickFixState(editor);
|
||||
state->_semanticInfo = info;
|
||||
return state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<TextEditor::QuickFixFactory *> QmlJSQuickFixCollector::quickFixFactories() const
|
||||
{
|
||||
QList<TextEditor::QuickFixFactory *> results;
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
foreach (QmlJSQuickFixFactory *f, pm->getObjects<QmlJSEditor::QmlJSQuickFixFactory>())
|
||||
results.append(f);
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include <qmljs/qmljsdocument.h>
|
||||
#include <qmljstools/qmljsrefactoringchanges.h>
|
||||
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
namespace ExtensionSystem {
|
||||
class IPlugin;
|
||||
}
|
||||
@@ -51,40 +53,12 @@ namespace QmlJS {
|
||||
namespace QmlJSEditor {
|
||||
|
||||
namespace Internal {
|
||||
class QmlJSQuickFixCollector;
|
||||
class QmlJSQuickFixAssistInterface;
|
||||
} // namespace Internal
|
||||
|
||||
/*!
|
||||
Specialized QuickFixState for QML/JavaScript quick-fixes.
|
||||
|
||||
This specialized state for QML/JavaScript quick-fixes also holds the
|
||||
QmlJSEditor::Internal::SemanticInfo for the document in the editor.
|
||||
*/
|
||||
class QmlJSQuickFixState: public TextEditor::QuickFixState
|
||||
{
|
||||
friend class Internal::QmlJSQuickFixCollector;
|
||||
|
||||
public:
|
||||
/// Creates a new state for the given editor.
|
||||
QmlJSQuickFixState(TextEditor::BaseTextEditorWidget *editor);
|
||||
|
||||
SemanticInfo semanticInfo() const;
|
||||
|
||||
/// \returns the snapshot holding the document of the editor.
|
||||
QmlJS::Snapshot snapshot() const;
|
||||
|
||||
/// \returns the document of the editor
|
||||
QmlJS::Document::Ptr document() const;
|
||||
|
||||
const QmlJSTools::QmlJSRefactoringFile currentFile() const;
|
||||
|
||||
private:
|
||||
SemanticInfo _semanticInfo;
|
||||
};
|
||||
|
||||
/*!
|
||||
A quick-fix operation for the QML/JavaScript editor, which works on a
|
||||
QmlJSQuickFixState .
|
||||
A quick-fix operation for the QML/JavaScript editor.
|
||||
*/
|
||||
class QmlJSQuickFixOperation: public TextEditor::QuickFixOperation
|
||||
{
|
||||
@@ -94,13 +68,12 @@ public:
|
||||
/*!
|
||||
Creates a new QmlJSQuickFixOperation.
|
||||
|
||||
This operation will copy the complete state, in order to be able to perform
|
||||
its changes later on.
|
||||
|
||||
\param state The state for which this operation was created.
|
||||
\param interface The interface on which the operation is performed.
|
||||
\param priority The priority for this operation.
|
||||
*/
|
||||
explicit QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority = -1);
|
||||
explicit QmlJSQuickFixOperation(
|
||||
const QSharedPointer<const Internal::QmlJSQuickFixAssistInterface> &interface,
|
||||
int priority = -1);
|
||||
virtual ~QmlJSQuickFixOperation();
|
||||
|
||||
virtual void perform();
|
||||
@@ -111,14 +84,13 @@ protected:
|
||||
virtual void performChanges(QmlJSTools::QmlJSRefactoringFile *currentFile,
|
||||
QmlJSTools::QmlJSRefactoringChanges *refactoring) = 0;
|
||||
|
||||
/// \returns A const-reference to the state of the operation.
|
||||
const QmlJSQuickFixState &state() const;
|
||||
const Internal::QmlJSQuickFixAssistInterface *assistInterface() const;
|
||||
|
||||
/// \returns The name of the file for for which this operation is invoked.
|
||||
QString fileName() const;
|
||||
|
||||
private:
|
||||
QmlJSQuickFixState _state;
|
||||
QSharedPointer<const Internal::QmlJSQuickFixAssistInterface> m_interface;
|
||||
};
|
||||
|
||||
class QmlJSQuickFixFactory: public TextEditor::QuickFixFactory
|
||||
@@ -129,39 +101,20 @@ public:
|
||||
QmlJSQuickFixFactory();
|
||||
virtual ~QmlJSQuickFixFactory();
|
||||
|
||||
virtual QList<TextEditor::QuickFixOperation::Ptr> matchingOperations(TextEditor::QuickFixState *state);
|
||||
virtual QList<TextEditor::QuickFixOperation::Ptr>
|
||||
matchingOperations(const QSharedPointer<const TextEditor::IAssistInterface> &interface);
|
||||
|
||||
/*!
|
||||
Implement this method to match and create the appropriate
|
||||
QmlJSQuickFixOperation objects.
|
||||
*/
|
||||
virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state) = 0;
|
||||
virtual QList<QmlJSQuickFixOperation::Ptr> match(
|
||||
const QSharedPointer<const Internal::QmlJSQuickFixAssistInterface> &interface) = 0;
|
||||
|
||||
static QList<QmlJSQuickFixOperation::Ptr> noResult();
|
||||
static QList<QmlJSQuickFixOperation::Ptr> singleResult(QmlJSQuickFixOperation *operation);
|
||||
};
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class QmlJSQuickFixCollector: public TextEditor::QuickFixCollector
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QmlJSQuickFixCollector();
|
||||
virtual ~QmlJSQuickFixCollector();
|
||||
|
||||
virtual bool supportsEditor(TextEditor::ITextEditor *editor) const;
|
||||
virtual bool supportsPolicy(TextEditor::CompletionPolicy policy) const;
|
||||
virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::BaseTextEditorWidget *editor);
|
||||
|
||||
virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
|
||||
|
||||
/// Registers all quick-fixes in this plug-in as auto-released objects.
|
||||
static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QmlJSEditor
|
||||
|
||||
#endif // QMLJSQUICKFIX_H
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "qmljsquickfixassist.h"
|
||||
#include "qmljseditorconstants.h"
|
||||
|
||||
//temp
|
||||
#include "qmljsquickfix.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
using namespace QmlJSEditor;
|
||||
using namespace Internal;
|
||||
using namespace QmlJSTools;
|
||||
using namespace TextEditor;
|
||||
|
||||
// -----------------------
|
||||
// QuickFixAssistInterface
|
||||
// -----------------------
|
||||
QmlJSQuickFixAssistInterface::QmlJSQuickFixAssistInterface(QmlJSTextEditorWidget *editor,
|
||||
TextEditor::AssistReason reason)
|
||||
: DefaultAssistInterface(editor->document(), editor->position(), editor->file(), reason)
|
||||
, m_editor(editor)
|
||||
, m_semanticInfo(editor->semanticInfo())
|
||||
{}
|
||||
|
||||
QmlJSQuickFixAssistInterface::~QmlJSQuickFixAssistInterface()
|
||||
{}
|
||||
|
||||
const SemanticInfo &QmlJSQuickFixAssistInterface::semanticInfo() const
|
||||
{
|
||||
return m_semanticInfo;
|
||||
}
|
||||
|
||||
const QmlJSTools::QmlJSRefactoringFile QmlJSQuickFixAssistInterface::currentFile() const
|
||||
{
|
||||
return QmlJSRefactoringFile(m_editor, m_semanticInfo.document);
|
||||
}
|
||||
|
||||
QWidget *QmlJSQuickFixAssistInterface::widget() const
|
||||
{
|
||||
return m_editor;
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// QmlJSQuickFixProcessor
|
||||
// ----------------------
|
||||
QmlJSQuickFixProcessor::QmlJSQuickFixProcessor(const TextEditor::IAssistProvider *provider)
|
||||
: m_provider(provider)
|
||||
{}
|
||||
|
||||
QmlJSQuickFixProcessor::~QmlJSQuickFixProcessor()
|
||||
{}
|
||||
|
||||
const IAssistProvider *QmlJSQuickFixProcessor::provider() const
|
||||
{
|
||||
return m_provider;
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// QmlJSQuickFixAssistProvider
|
||||
// ---------------------------
|
||||
QmlJSQuickFixAssistProvider::QmlJSQuickFixAssistProvider()
|
||||
{}
|
||||
|
||||
QmlJSQuickFixAssistProvider::~QmlJSQuickFixAssistProvider()
|
||||
{}
|
||||
|
||||
bool QmlJSQuickFixAssistProvider::supportsEditor(const QString &editorId) const
|
||||
{
|
||||
return editorId == QLatin1String(Constants::C_QMLJSEDITOR_ID);
|
||||
}
|
||||
|
||||
IAssistProcessor *QmlJSQuickFixAssistProvider::createProcessor() const
|
||||
{
|
||||
return new QmlJSQuickFixProcessor(this);
|
||||
}
|
||||
|
||||
QList<QuickFixFactory *> QmlJSQuickFixAssistProvider::quickFixFactories() const
|
||||
{
|
||||
QList<TextEditor::QuickFixFactory *> results;
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
foreach (QmlJSQuickFixFactory *f, pm->getObjects<QmlJSEditor::QmlJSQuickFixFactory>())
|
||||
results.append(f);
|
||||
return results;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QMLJSQUICKFIXASSIST_H
|
||||
#define QMLJSQUICKFIXASSIST_H
|
||||
|
||||
#include "qmljseditor.h"
|
||||
|
||||
#include <qmljstools/qmljsrefactoringchanges.h>
|
||||
|
||||
#include <texteditor/codeassist/defaultassistinterface.h>
|
||||
#include <texteditor/codeassist/quickfixassistprovider.h>
|
||||
#include <texteditor/codeassist/quickfixassistprocessor.h>
|
||||
|
||||
namespace QmlJSEditor {
|
||||
namespace Internal {
|
||||
|
||||
class QmlJSQuickFixAssistInterface : public TextEditor::DefaultAssistInterface
|
||||
{
|
||||
public:
|
||||
QmlJSQuickFixAssistInterface(QmlJSTextEditorWidget *editor, TextEditor::AssistReason reason);
|
||||
virtual ~QmlJSQuickFixAssistInterface();
|
||||
|
||||
const SemanticInfo &semanticInfo() const;
|
||||
const QmlJSTools::QmlJSRefactoringFile currentFile() const;
|
||||
QWidget *widget() const;
|
||||
|
||||
private:
|
||||
QmlJSTextEditorWidget *m_editor;
|
||||
SemanticInfo m_semanticInfo;
|
||||
};
|
||||
|
||||
|
||||
class QmlJSQuickFixProcessor : public TextEditor::QuickFixAssistProcessor
|
||||
{
|
||||
public:
|
||||
QmlJSQuickFixProcessor(const TextEditor::IAssistProvider *provider);
|
||||
virtual ~QmlJSQuickFixProcessor();
|
||||
|
||||
virtual const TextEditor::IAssistProvider *provider() const;
|
||||
|
||||
private:
|
||||
const TextEditor::IAssistProvider *m_provider;
|
||||
};
|
||||
|
||||
|
||||
class QmlJSQuickFixAssistProvider : public TextEditor::QuickFixAssistProvider
|
||||
{
|
||||
public:
|
||||
QmlJSQuickFixAssistProvider();
|
||||
virtual ~QmlJSQuickFixAssistProvider();
|
||||
|
||||
virtual bool supportsEditor(const QString &editorId) const;
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
|
||||
virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // QmlJSEditor
|
||||
|
||||
#endif // QMLJSQUICKFIXASSIST_H
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "qmljsquickfix.h"
|
||||
#include "qmljscomponentfromobjectdef.h"
|
||||
#include "qmljseditor.h"
|
||||
#include "qmljsquickfixassist.h"
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
@@ -64,13 +65,14 @@ namespace {
|
||||
class SplitInitializerOp: public QmlJSQuickFixFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state)
|
||||
virtual QList<QmlJSQuickFixOperation::Ptr> match(
|
||||
const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface)
|
||||
{
|
||||
UiObjectInitializer *objectInitializer = 0;
|
||||
|
||||
const int pos = state.currentFile().cursor().position();
|
||||
const int pos = interface->currentFile().cursor().position();
|
||||
|
||||
if (QmlJS::AST::Node *member = state.semanticInfo().declaringMember(pos)) {
|
||||
if (QmlJS::AST::Node *member = interface->semanticInfo().declaringMember(pos)) {
|
||||
if (QmlJS::AST::UiObjectBinding *b = QmlJS::AST::cast<QmlJS::AST::UiObjectBinding *>(member)) {
|
||||
if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
|
||||
objectInitializer = b->initializer;
|
||||
@@ -82,7 +84,7 @@ public:
|
||||
}
|
||||
|
||||
if (objectInitializer)
|
||||
return singleResult(new Operation(state, objectInitializer));
|
||||
return singleResult(new Operation(interface, objectInitializer));
|
||||
else
|
||||
return noResult();
|
||||
}
|
||||
@@ -93,8 +95,9 @@ private:
|
||||
UiObjectInitializer *_objectInitializer;
|
||||
|
||||
public:
|
||||
Operation(const QmlJSQuickFixState &state, UiObjectInitializer *objectInitializer)
|
||||
: QmlJSQuickFixOperation(state, 0)
|
||||
Operation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface,
|
||||
UiObjectInitializer *objectInitializer)
|
||||
: QmlJSQuickFixOperation(interface, 0)
|
||||
, _objectInitializer(objectInitializer)
|
||||
{
|
||||
setDescription(QApplication::translate("QmlJSEditor::QuickFix",
|
||||
@@ -129,7 +132,7 @@ private:
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
void QmlJSQuickFixCollector::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
||||
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
||||
{
|
||||
plugIn->addAutoReleasedObject(new SplitInitializerOp);
|
||||
plugIn->addAutoReleasedObject(new ComponentFromObjectDef);
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "qmljsreuse.h"
|
||||
|
||||
#include <QtCore/QChar>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
namespace QmlJSEditor {
|
||||
namespace Internal {
|
||||
|
||||
bool isIdentifierChar(const QChar &c, bool atStart, bool acceptDollar)
|
||||
{
|
||||
switch (c.unicode()) {
|
||||
case '_':
|
||||
return true;
|
||||
case '$':
|
||||
if (acceptDollar)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
default:
|
||||
if (atStart)
|
||||
return c.isLetter();
|
||||
else
|
||||
return c.isLetterOrNumber();
|
||||
}
|
||||
}
|
||||
|
||||
bool isDelimiterChar(const QChar &c)
|
||||
{
|
||||
switch (c.unicode()) {
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ')':
|
||||
case '?':
|
||||
case '!':
|
||||
case ':':
|
||||
case ';':
|
||||
case ',':
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isActivationChar(const QChar &c)
|
||||
{
|
||||
if (c == QLatin1Char('(') || c == QLatin1Char('.') || c == QLatin1Char('/'))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
QIcon iconForColor(const QColor &color)
|
||||
{
|
||||
QPixmap pix(6, 6);
|
||||
|
||||
int pixSize = 20;
|
||||
QBrush br(color);
|
||||
|
||||
QPixmap pm(2 * pixSize, 2 * pixSize);
|
||||
QPainter pmp(&pm);
|
||||
pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
|
||||
pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
|
||||
pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
|
||||
pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
|
||||
pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, color);
|
||||
br = QBrush(pm);
|
||||
|
||||
QPainter p(&pix);
|
||||
int corr = 1;
|
||||
QRect r = pix.rect().adjusted(corr, corr, -corr, -corr);
|
||||
p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
|
||||
p.fillRect(r, br);
|
||||
|
||||
p.fillRect(r.width() / 4 + corr, r.height() / 4 + corr,
|
||||
r.width() / 2, r.height() / 2,
|
||||
QColor(color.rgb()));
|
||||
p.drawRect(pix.rect().adjusted(0, 0, -1, -1));
|
||||
|
||||
return pix;
|
||||
}
|
||||
|
||||
|
||||
} // Internal
|
||||
} // QmlJSEditor
|
||||
@@ -0,0 +1,55 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QMLJSREUSE_H
|
||||
#define QMLJSREUSE_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QChar;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QmlJSEditor {
|
||||
namespace Internal {
|
||||
|
||||
bool isIdentifierChar(const QChar &c, bool atStart = false, bool acceptDollar = true);
|
||||
bool isDelimiterChar(const QChar &c);
|
||||
bool isActivationChar(const QChar &c);
|
||||
|
||||
QIcon iconForColor(const QColor &color);
|
||||
|
||||
} // Internal
|
||||
} // QmlJSEditor
|
||||
|
||||
#endif // QMLJSREUSE_H
|
||||
@@ -1,224 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "profilecompletion.h"
|
||||
#include "profileeditor.h"
|
||||
#include "profilekeywords.h"
|
||||
#include <texteditor/itexteditor.h>
|
||||
#include <texteditor/completionsettings.h>
|
||||
#include <cplusplus/Icons.h>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace Qt4ProjectManager::Internal;
|
||||
|
||||
ProFileCompletion::ProFileCompletion(QObject *parent) :
|
||||
TextEditor::ICompletionCollector(parent),
|
||||
m_editor(0),
|
||||
m_startPosition(-1),
|
||||
m_variableIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::VarPublicIconType)),
|
||||
m_functionIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::FuncPublicIconType))
|
||||
{
|
||||
}
|
||||
|
||||
ProFileCompletion::~ProFileCompletion()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QList<TextEditor::CompletionItem> ProFileCompletion::getCompletions()
|
||||
{
|
||||
QList<TextEditor::CompletionItem> completionItems;
|
||||
completions(&completionItems);
|
||||
|
||||
return completionItems;
|
||||
}
|
||||
|
||||
bool ProFileCompletion::shouldRestartCompletion()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TextEditor::ITextEditor *ProFileCompletion::editor() const
|
||||
{
|
||||
return m_editor;
|
||||
}
|
||||
|
||||
int ProFileCompletion::startPosition() const
|
||||
{
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
bool ProFileCompletion::supportsEditor(TextEditor::ITextEditor *editor) const
|
||||
{
|
||||
return qobject_cast<ProFileEditor *>(editor) != 0;
|
||||
}
|
||||
|
||||
bool ProFileCompletion::supportsPolicy(TextEditor::CompletionPolicy policy) const
|
||||
{
|
||||
return policy == TextEditor::SemanticCompletion;
|
||||
}
|
||||
|
||||
bool ProFileCompletion::triggersCompletion(TextEditor::ITextEditor *editor)
|
||||
{
|
||||
m_editor = editor;
|
||||
const int pos = editor->position();
|
||||
|
||||
if (completionSettings().m_completionTrigger == TextEditor::AutomaticCompletion) {
|
||||
QChar characterUnderCursor = editor->characterAt(pos);
|
||||
if (!characterUnderCursor.isLetterOrNumber()) {
|
||||
m_startPosition = findStartOfName();
|
||||
if (pos - m_startPosition >= 3 && !isInComment())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ProFileCompletion::findStartOfName(int pos) const
|
||||
{
|
||||
if (pos == -1)
|
||||
pos = m_editor->position();
|
||||
QChar chr;
|
||||
|
||||
// Skip to the start of a name
|
||||
do {
|
||||
chr = m_editor->characterAt(--pos);
|
||||
} while (chr.isLetterOrNumber() || chr == QLatin1Char('_'));
|
||||
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
bool ProFileCompletion::isInComment() const
|
||||
{
|
||||
const int beginOfLinePosition = m_editor->position(TextEditor::ITextEditor::StartOfLine);
|
||||
const QString lineBeginning = m_editor->textAt(beginOfLinePosition,
|
||||
m_startPosition - beginOfLinePosition);
|
||||
if (lineBeginning.contains(QLatin1Char('#')))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int ProFileCompletion::startCompletion(TextEditor::ITextEditor *editor)
|
||||
{
|
||||
m_editor = editor;
|
||||
m_startPosition = findStartOfName();
|
||||
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
void ProFileCompletion::completions(QList<TextEditor::CompletionItem> *completions)
|
||||
{
|
||||
const int length = m_editor->position() - m_startPosition;
|
||||
if (length < 0)
|
||||
return;
|
||||
|
||||
if (isInComment())
|
||||
return;
|
||||
|
||||
const QString key = m_editor->textAt(m_startPosition, length);
|
||||
|
||||
QList<TextEditor::CompletionItem> items;
|
||||
QStringList keywords = ProFileKeywords::variables()
|
||||
+ ProFileKeywords::functions();
|
||||
// qSort(keywords);
|
||||
for (int i = 0; i < keywords.count(); i++) {
|
||||
TextEditor::CompletionItem item(this);
|
||||
item.text = keywords[i];
|
||||
item.data = QVariant::fromValue(item.text);
|
||||
item.icon = ProFileKeywords::isFunction(item.text)
|
||||
? m_functionIcon : m_variableIcon;
|
||||
items.append(item);
|
||||
}
|
||||
|
||||
filter(items, completions, key);
|
||||
}
|
||||
|
||||
bool ProFileCompletion::typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar)
|
||||
{
|
||||
// only '(' in case of a function
|
||||
if (typedChar == QLatin1Char('(') && ProFileKeywords::isFunction(item.text))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProFileCompletion::complete(const TextEditor::CompletionItem &item, QChar typedChar)
|
||||
{
|
||||
Q_UNUSED(typedChar)
|
||||
|
||||
int replaceLength = m_editor->position() - m_startPosition;
|
||||
if (replaceLength < 0)
|
||||
return;
|
||||
|
||||
QString toInsert = item.text;
|
||||
int cursorOffset = 0;
|
||||
if (ProFileKeywords::isFunction(toInsert)
|
||||
&& completionSettings().m_autoInsertBrackets) {
|
||||
if (completionSettings().m_spaceAfterFunctionName) {
|
||||
if (m_editor->textAt(m_editor->position(), 2) == QLatin1String(" (")) {
|
||||
cursorOffset = 2;
|
||||
} else if (m_editor->characterAt(m_editor->position()) == QLatin1Char('(')
|
||||
|| m_editor->characterAt(m_editor->position()) == QLatin1Char(' ')) {
|
||||
replaceLength += 1;
|
||||
toInsert += QLatin1String(" (");
|
||||
} else {
|
||||
toInsert += QLatin1String(" ()");
|
||||
cursorOffset = -1;
|
||||
}
|
||||
} else {
|
||||
if (m_editor->characterAt(m_editor->position()) == QLatin1Char('(')) {
|
||||
cursorOffset = 1;
|
||||
} else {
|
||||
toInsert += QLatin1String("()");
|
||||
cursorOffset = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_editor->setCursorPosition(m_startPosition);
|
||||
m_editor->replace(replaceLength, toInsert);
|
||||
if (cursorOffset)
|
||||
m_editor->setCursorPosition(m_editor->position() + cursorOffset);
|
||||
}
|
||||
|
||||
bool ProFileCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
|
||||
{
|
||||
if (completionItems.count() == 1) {
|
||||
complete(completionItems.first(), QChar());
|
||||
return true;
|
||||
}
|
||||
|
||||
return TextEditor::ICompletionCollector::partiallyComplete(completionItems);
|
||||
}
|
||||
|
||||
void ProFileCompletion::cleanup()
|
||||
{
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef PROFILECOMPLETION_H
|
||||
#define PROFILECOMPLETION_H
|
||||
|
||||
#include <texteditor/icompletioncollector.h>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class ProFileCompletion : public TextEditor::ICompletionCollector
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProFileCompletion(QObject *parent = 0);
|
||||
|
||||
virtual ~ProFileCompletion();
|
||||
|
||||
virtual QList<TextEditor::CompletionItem> getCompletions();
|
||||
virtual bool shouldRestartCompletion();
|
||||
|
||||
virtual TextEditor::ITextEditor *editor() const;
|
||||
virtual int startPosition() const;
|
||||
|
||||
virtual bool supportsEditor(TextEditor::ITextEditor *editor) const;
|
||||
virtual bool supportsPolicy(TextEditor::CompletionPolicy policy) const;
|
||||
virtual bool triggersCompletion(TextEditor::ITextEditor *editor);
|
||||
virtual int startCompletion(TextEditor::ITextEditor *editor);
|
||||
virtual void completions(QList<TextEditor::CompletionItem> *completions);
|
||||
virtual bool typedCharCompletes(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
virtual void complete(const TextEditor::CompletionItem &item, QChar typedChar);
|
||||
virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
|
||||
virtual void cleanup();
|
||||
private:
|
||||
int findStartOfName(int pos = -1) const;
|
||||
bool isInComment() const;
|
||||
|
||||
TextEditor::ITextEditor *m_editor;
|
||||
int m_startPosition;
|
||||
const QIcon m_variableIcon;
|
||||
const QIcon m_functionIcon;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
#endif // PROFILECOMPLETION_H
|
||||
@@ -0,0 +1,231 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "profilecompletionassist.h"
|
||||
#include "qt4projectmanagerconstants.h"
|
||||
#include "profilekeywords.h"
|
||||
|
||||
#include <texteditor/codeassist/iassistinterface.h>
|
||||
#include <texteditor/codeassist/genericproposal.h>
|
||||
#include <texteditor/completionsettings.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/basetexteditor.h>
|
||||
|
||||
#include <cplusplus/Icons.h>
|
||||
|
||||
#include <QtGui/QTextCursor>
|
||||
|
||||
using namespace Qt4ProjectManager::Internal;
|
||||
using namespace TextEditor;
|
||||
|
||||
// -------------------------
|
||||
// ProFileAssistProposalItem
|
||||
// -------------------------
|
||||
ProFileAssistProposalItem::ProFileAssistProposalItem()
|
||||
{}
|
||||
|
||||
ProFileAssistProposalItem::~ProFileAssistProposalItem()
|
||||
{}
|
||||
|
||||
bool ProFileAssistProposalItem::prematurelyApplies(const QChar &c) const
|
||||
{
|
||||
// only '(' in case of a function
|
||||
if (c == QLatin1Char('(') && ProFileKeywords::isFunction(text()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProFileAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor *editor,
|
||||
int basePosition) const
|
||||
{
|
||||
const CompletionSettings &settings = TextEditorSettings::instance()->completionSettings();
|
||||
|
||||
int replaceLength = editor->position() - basePosition;
|
||||
QString toInsert = text();
|
||||
int cursorOffset = 0;
|
||||
if (ProFileKeywords::isFunction(toInsert) && settings.m_autoInsertBrackets) {
|
||||
if (settings.m_spaceAfterFunctionName) {
|
||||
if (editor->textAt(editor->position(), 2) == QLatin1String(" (")) {
|
||||
cursorOffset = 2;
|
||||
} else if (editor->characterAt(editor->position()) == QLatin1Char('(')
|
||||
|| editor->characterAt(editor->position()) == QLatin1Char(' ')) {
|
||||
replaceLength += 1;
|
||||
toInsert += QLatin1String(" (");
|
||||
} else {
|
||||
toInsert += QLatin1String(" ()");
|
||||
cursorOffset = -1;
|
||||
}
|
||||
} else {
|
||||
if (editor->characterAt(editor->position()) == QLatin1Char('(')) {
|
||||
cursorOffset = 1;
|
||||
} else {
|
||||
toInsert += QLatin1String("()");
|
||||
cursorOffset = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editor->setCursorPosition(basePosition);
|
||||
editor->replace(replaceLength, toInsert);
|
||||
if (cursorOffset)
|
||||
editor->setCursorPosition(editor->position() + cursorOffset);
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// ProFileCompletionAssistProvider
|
||||
// -------------------------------
|
||||
ProFileCompletionAssistProvider::ProFileCompletionAssistProvider()
|
||||
{}
|
||||
|
||||
ProFileCompletionAssistProvider::~ProFileCompletionAssistProvider()
|
||||
{}
|
||||
|
||||
bool ProFileCompletionAssistProvider::supportsEditor(const QString &editorId) const
|
||||
{
|
||||
return editorId == QLatin1String(Qt4ProjectManager::Constants::PROFILE_EDITOR_ID);
|
||||
}
|
||||
|
||||
bool ProFileCompletionAssistProvider::isAsynchronous() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int ProFileCompletionAssistProvider::activationCharSequenceLength() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ProFileCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
||||
{
|
||||
Q_UNUSED(sequence);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProFileCompletionAssistProvider::isContinuationChar(const QChar &c) const
|
||||
{
|
||||
return c.isLetterOrNumber() || c == QLatin1Char('_');
|
||||
}
|
||||
|
||||
IAssistProcessor *ProFileCompletionAssistProvider::createProcessor() const
|
||||
{
|
||||
return new ProFileCompletionAssistProcessor;
|
||||
}
|
||||
|
||||
// --------------------------------
|
||||
// ProFileCompletionAssistProcessor
|
||||
// --------------------------------
|
||||
ProFileCompletionAssistProcessor::ProFileCompletionAssistProcessor()
|
||||
: m_startPosition(-1)
|
||||
, m_variableIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::VarPublicIconType))
|
||||
, m_functionIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::FuncPublicIconType))
|
||||
{}
|
||||
|
||||
ProFileCompletionAssistProcessor::~ProFileCompletionAssistProcessor()
|
||||
{}
|
||||
|
||||
IAssistProposal *ProFileCompletionAssistProcessor::perform(const IAssistInterface *interface)
|
||||
{
|
||||
m_interface.reset(interface);
|
||||
|
||||
if (isInComment())
|
||||
return 0;
|
||||
|
||||
if (interface->reason() == IdleEditor && !acceptsIdleEditor())
|
||||
return 0;
|
||||
|
||||
if (m_startPosition == -1)
|
||||
m_startPosition = findStartOfName();
|
||||
|
||||
QList<TextEditor::BasicProposalItem *> items;
|
||||
QStringList keywords = ProFileKeywords::variables() + ProFileKeywords::functions();
|
||||
for (int i = 0; i < keywords.count(); i++) {
|
||||
BasicProposalItem *item = new ProFileAssistProposalItem;
|
||||
item->setText(keywords[i]);
|
||||
item->setIcon(ProFileKeywords::isFunction(item->text()) ? m_functionIcon : m_variableIcon);
|
||||
items.append(item);
|
||||
}
|
||||
|
||||
return new GenericProposal(m_startPosition, new ProFileAssistProposalModel(items));
|
||||
}
|
||||
|
||||
bool ProFileCompletionAssistProcessor::acceptsIdleEditor()
|
||||
{
|
||||
const int pos = m_interface->position();
|
||||
QChar characterUnderCursor = m_interface->characterAt(pos);
|
||||
if (!characterUnderCursor.isLetterOrNumber()) {
|
||||
m_startPosition = findStartOfName();
|
||||
if (pos - m_startPosition >= 3 && !isInComment())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ProFileCompletionAssistProcessor::findStartOfName(int pos) const
|
||||
{
|
||||
if (pos == -1)
|
||||
pos = m_interface->position();
|
||||
QChar chr;
|
||||
|
||||
// Skip to the start of a name
|
||||
do {
|
||||
chr = m_interface->characterAt(--pos);
|
||||
} while (chr.isLetterOrNumber() || chr == QLatin1Char('_'));
|
||||
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
bool ProFileCompletionAssistProcessor::isInComment() const
|
||||
{
|
||||
QTextCursor tc(m_interface->document());
|
||||
tc.setPosition(m_interface->position());
|
||||
tc.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
|
||||
const QString &lineBeginning = tc.selectedText();
|
||||
if (lineBeginning.contains(QLatin1Char('#')))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// ProFileAssistProposalModel
|
||||
// --------------------------
|
||||
ProFileAssistProposalModel::ProFileAssistProposalModel(
|
||||
const QList<BasicProposalItem *> &items)
|
||||
: BasicProposalItemListModel(items)
|
||||
{}
|
||||
|
||||
ProFileAssistProposalModel::~ProFileAssistProposalModel()
|
||||
{}
|
||||
|
||||
bool ProFileAssistProposalModel::isSortable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef PROFILECOMPLETIONASSIST_H
|
||||
#define PROFILECOMPLETIONASSIST_H
|
||||
|
||||
#include <texteditor/codeassist/basicproposalitem.h>
|
||||
#include <texteditor/codeassist/basicproposalitemlistmodel.h>
|
||||
#include <texteditor/codeassist/completionassistprovider.h>
|
||||
#include <texteditor/codeassist/iassistprocessor.h>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class ProFileAssistProposalItem : public TextEditor::BasicProposalItem
|
||||
{
|
||||
public:
|
||||
ProFileAssistProposalItem();
|
||||
virtual ~ProFileAssistProposalItem();
|
||||
|
||||
virtual bool prematurelyApplies(const QChar &c) const;
|
||||
virtual void applyContextualContent(TextEditor::BaseTextEditor *editor,
|
||||
int basePosition) const;
|
||||
};
|
||||
|
||||
|
||||
class ProFileCompletionAssistProvider : public TextEditor::CompletionAssistProvider
|
||||
{
|
||||
public:
|
||||
ProFileCompletionAssistProvider();
|
||||
virtual ~ProFileCompletionAssistProvider();
|
||||
|
||||
virtual bool supportsEditor(const QString &editorId) const;
|
||||
virtual TextEditor::IAssistProcessor *createProcessor() const;
|
||||
|
||||
virtual bool isAsynchronous() const;
|
||||
virtual int activationCharSequenceLength() const;
|
||||
virtual bool isActivationCharSequence(const QString &sequence) const;
|
||||
virtual bool isContinuationChar(const QChar &c) const;
|
||||
};
|
||||
|
||||
|
||||
class ProFileCompletionAssistProcessor : public TextEditor::IAssistProcessor
|
||||
{
|
||||
public:
|
||||
ProFileCompletionAssistProcessor();
|
||||
virtual ~ProFileCompletionAssistProcessor();
|
||||
|
||||
virtual TextEditor::IAssistProposal *perform(const TextEditor::IAssistInterface *interface);
|
||||
|
||||
private:
|
||||
bool acceptsIdleEditor();
|
||||
int findStartOfName(int pos = -1) const;
|
||||
bool isInComment() const;
|
||||
|
||||
int m_startPosition;
|
||||
QScopedPointer<const TextEditor::IAssistInterface> m_interface;
|
||||
const QIcon m_variableIcon;
|
||||
const QIcon m_functionIcon;
|
||||
};
|
||||
|
||||
|
||||
class ProFileAssistProposalModel : public TextEditor::BasicProposalItemListModel
|
||||
{
|
||||
public:
|
||||
ProFileAssistProposalModel(const QList<TextEditor::BasicProposalItem *> &items);
|
||||
virtual ~ProFileAssistProposalModel();
|
||||
|
||||
virtual bool isSortable() const;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // Qt4ProjectManager
|
||||
|
||||
#endif // PROFILECOMPLETIONASSIST_H
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <texteditor/texteditoractionhandler.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/completionsupport.h>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QAction>
|
||||
|
||||
@@ -69,7 +69,6 @@ HEADERS += \
|
||||
qmldumptool.h \
|
||||
qmlobservertool.h \
|
||||
qmldebugginglibrary.h \
|
||||
profilecompletion.h \
|
||||
profilekeywords.h \
|
||||
debugginghelperbuildtask.h \
|
||||
qt4targetsetupwidget.h \
|
||||
@@ -78,7 +77,8 @@ HEADERS += \
|
||||
qtversionfactory.h \
|
||||
winceqtversionfactory.h \
|
||||
baseqtversion.h \
|
||||
winceqtversion.h
|
||||
winceqtversion.h \
|
||||
profilecompletionassist.h
|
||||
|
||||
SOURCES += qt4projectmanagerplugin.cpp \
|
||||
qtparser.cpp \
|
||||
@@ -142,13 +142,14 @@ SOURCES += qt4projectmanagerplugin.cpp \
|
||||
qmldumptool.cpp \
|
||||
qmlobservertool.cpp \
|
||||
qmldebugginglibrary.cpp \
|
||||
profilecompletion.cpp \
|
||||
profilekeywords.cpp \
|
||||
debugginghelperbuildtask.cpp \
|
||||
qtversionfactory.cpp \
|
||||
winceqtversionfactory.cpp \
|
||||
baseqtversion.cpp \
|
||||
winceqtversion.cpp
|
||||
winceqtversion.cpp \
|
||||
profilecompletionassist.cpp
|
||||
|
||||
FORMS += makestep.ui \
|
||||
qmakestep.ui \
|
||||
qt4projectconfigwidget.ui \
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
#include "qtoptionspage.h"
|
||||
#include "externaleditors.h"
|
||||
#include "gettingstartedwelcomepage.h"
|
||||
#include "profilecompletion.h"
|
||||
#include "profilecompletionassist.h"
|
||||
|
||||
#include "qt-maemo/maemomanager.h"
|
||||
#include "qt-s60/s60manager.h"
|
||||
@@ -180,13 +180,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
|
||||
addAutoReleasedObject(new SimulatorQtVersionFactory);
|
||||
addAutoReleasedObject(new WinCeQtVersionFactory);
|
||||
|
||||
ProFileCompletion *completion = new ProFileCompletion;
|
||||
addAutoReleasedObject(completion);
|
||||
// Set completion settings and keep them up to date
|
||||
TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
|
||||
completion->setCompletionSettings(textEditorSettings->completionSettings());
|
||||
connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
|
||||
completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
|
||||
addAutoReleasedObject(new ProFileCompletionAssistProvider);
|
||||
|
||||
// TODO reenable
|
||||
//m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "behaviorsettings.h"
|
||||
#include "codecselector.h"
|
||||
#include "completionsettings.h"
|
||||
#include "completionsupport.h"
|
||||
#include "tabsettings.h"
|
||||
#include "texteditorconstants.h"
|
||||
#include "texteditorplugin.h"
|
||||
@@ -48,6 +47,9 @@
|
||||
#include "indenter.h"
|
||||
#include "autocompleter.h"
|
||||
#include "snippet.h"
|
||||
#include "codeassistant.h"
|
||||
#include "defaultassistinterface.h"
|
||||
#include "convenience.h"
|
||||
|
||||
#include <aggregation/aggregate.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
@@ -236,11 +238,6 @@ BaseTextEditorWidget::BaseTextEditorWidget(QWidget *parent)
|
||||
d->m_highlightBlocksTimer->setSingleShot(true);
|
||||
connect(d->m_highlightBlocksTimer, SIGNAL(timeout()), this, SLOT(_q_highlightBlocks()));
|
||||
|
||||
d->m_requestAutoCompletionTimer = new QTimer(this);
|
||||
d->m_requestAutoCompletionTimer->setSingleShot(true);
|
||||
d->m_requestAutoCompletionTimer->setInterval(500);
|
||||
connect(d->m_requestAutoCompletionTimer, SIGNAL(timeout()), this, SLOT(_q_requestAutoCompletion()));
|
||||
|
||||
d->m_animator = 0;
|
||||
|
||||
d->m_searchResultFormat.setBackground(QColor(0xffef0b));
|
||||
@@ -490,7 +487,8 @@ ITextMarkable *BaseTextEditorWidget::markableInterface() const
|
||||
BaseTextEditor *BaseTextEditorWidget::editor() const
|
||||
{
|
||||
if (!d->m_editor) {
|
||||
d->m_editor = const_cast<BaseTextEditorWidget*>(this)->createEditor();
|
||||
d->m_editor = const_cast<BaseTextEditorWidget *>(this)->createEditor();
|
||||
d->m_codeAssistant->configure(d->m_editor);
|
||||
connect(this, SIGNAL(textChanged()),
|
||||
d->m_editor, SIGNAL(contentsChanged()));
|
||||
connect(this, SIGNAL(changed()),
|
||||
@@ -668,6 +666,9 @@ void BaseTextEditorWidget::editorContentsChange(int position, int charsRemoved,
|
||||
|
||||
if (doc->isRedoAvailable())
|
||||
emit editor()->contentsChangedBecauseOfUndo();
|
||||
|
||||
if (charsAdded != 0 && characterAt(position + charsAdded - 1).isPrint())
|
||||
d->m_assistRelevantContentAdded = true;
|
||||
}
|
||||
|
||||
void BaseTextEditorWidget::slotSelectionChanged()
|
||||
@@ -1535,9 +1536,7 @@ void BaseTextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
|
||||
if (!ro
|
||||
&& (e == QKeySequence::InsertParagraphSeparator
|
||||
|| (!d->m_lineSeparatorsAllowed && e == QKeySequence::InsertLineSeparator))
|
||||
) {
|
||||
|
||||
|| (!d->m_lineSeparatorsAllowed && e == QKeySequence::InsertLineSeparator))) {
|
||||
if (d->m_snippetOverlay->isVisible()) {
|
||||
e->accept();
|
||||
d->m_snippetOverlay->hide();
|
||||
@@ -1548,7 +1547,6 @@ void BaseTextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QTextCursor cursor = textCursor();
|
||||
if (d->m_inBlockSelectionMode)
|
||||
cursor.clearSelection();
|
||||
@@ -1702,7 +1700,8 @@ void BaseTextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
case Qt::Key_Right:
|
||||
case Qt::Key_Left:
|
||||
#ifndef Q_WS_MAC
|
||||
if ((e->modifiers() & (Qt::AltModifier | Qt::ShiftModifier)) == (Qt::AltModifier | Qt::ShiftModifier)) {
|
||||
if ((e->modifiers()
|
||||
& (Qt::AltModifier | Qt::ShiftModifier)) == (Qt::AltModifier | Qt::ShiftModifier)) {
|
||||
int diff_row = 0;
|
||||
int diff_col = 0;
|
||||
if (e->key() == Qt::Key_Up)
|
||||
@@ -1833,39 +1832,8 @@ void BaseTextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
if (!ro && e->key() == Qt::Key_Delete && d->m_parenthesesMatchingEnabled)
|
||||
d->m_parenthesesMatchingTimer->start(50);
|
||||
|
||||
|
||||
if (!ro && d->m_contentsChanged && !e->text().isEmpty() && e->text().at(0).isPrint()) {
|
||||
maybeRequestAutoCompletion(e->text().at(0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BaseTextEditorWidget::maybeRequestAutoCompletion(const QChar &ch)
|
||||
{
|
||||
if (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
|
||||
if (CompletionSupport::instance()->isActive())
|
||||
d->m_requestAutoCompletionTimer->stop();
|
||||
else {
|
||||
d->m_requestAutoCompletionRevision = document()->revision();
|
||||
d->m_requestAutoCompletionPosition = position();
|
||||
d->m_requestAutoCompletionTimer->start();
|
||||
}
|
||||
} else {
|
||||
d->m_requestAutoCompletionTimer->stop();
|
||||
CompletionSupport::instance()->complete(editor(), SemanticCompletion, false);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseTextEditorWidget::_q_requestAutoCompletion()
|
||||
{
|
||||
d->m_requestAutoCompletionTimer->stop();
|
||||
|
||||
if (CompletionSupport::instance()->isActive())
|
||||
return;
|
||||
|
||||
if (d->m_requestAutoCompletionRevision == document()->revision()
|
||||
&& d->m_requestAutoCompletionPosition == position())
|
||||
CompletionSupport::instance()->complete(editor(), SemanticCompletion, false);
|
||||
if (!ro && d->m_contentsChanged && !e->text().isEmpty() && e->text().at(0).isPrint())
|
||||
d->m_codeAssistant->process();
|
||||
}
|
||||
|
||||
void BaseTextEditorWidget::insertCodeSnippet(const QTextCursor &cursor_arg, const QString &snippet)
|
||||
@@ -2025,14 +1993,7 @@ int BaseTextEditorWidget::position(ITextEditor::PositionOperation posOp, int at)
|
||||
|
||||
void BaseTextEditorWidget::convertPosition(int pos, int *line, int *column) const
|
||||
{
|
||||
QTextBlock block = document()->findBlock(pos);
|
||||
if (!block.isValid()) {
|
||||
(*line) = -1;
|
||||
(*column) = -1;
|
||||
} else {
|
||||
(*line) = block.blockNumber() + 1;
|
||||
(*column) = pos - block.position();
|
||||
}
|
||||
Convenience::convertPosition(document(), pos, line, column);
|
||||
}
|
||||
|
||||
QChar BaseTextEditorWidget::characterAt(int pos) const
|
||||
@@ -2087,6 +2048,7 @@ BaseTextDocument *BaseTextEditorWidget::baseTextDocument() const
|
||||
return d->m_document;
|
||||
}
|
||||
|
||||
|
||||
void BaseTextEditorWidget::setBaseTextDocument(BaseTextDocument *doc)
|
||||
{
|
||||
if (doc) {
|
||||
@@ -2403,9 +2365,8 @@ BaseTextEditorPrivate::BaseTextEditorPrivate()
|
||||
m_findScopeVerticalBlockSelectionFirstColumn(-1),
|
||||
m_findScopeVerticalBlockSelectionLastColumn(-1),
|
||||
m_highlightBlocksTimer(0),
|
||||
m_requestAutoCompletionRevision(0),
|
||||
m_requestAutoCompletionPosition(0),
|
||||
m_requestAutoCompletionTimer(0),
|
||||
m_codeAssistant(new CodeAssistant),
|
||||
m_assistRelevantContentAdded(false),
|
||||
m_cursorBlockNumber(-1),
|
||||
m_autoCompleter(new AutoCompleter),
|
||||
m_indenter(new Indenter)
|
||||
@@ -3787,6 +3748,7 @@ void BaseTextEditorWidget::extraAreaPaintEvent(QPaintEvent *e)
|
||||
const QString &number = QString::number(blockNumber + 1);
|
||||
bool selected = (
|
||||
(selStart < block.position() + block.length()
|
||||
|
||||
&& selEnd > block.position())
|
||||
|| (selStart == selEnd && selStart == block.position())
|
||||
);
|
||||
@@ -3961,6 +3923,7 @@ void BaseTextEditorWidget::slotCursorPositionChanged()
|
||||
} else if (d->m_contentsChanged) {
|
||||
saveCurrentCursorPositionForNavigation();
|
||||
}
|
||||
|
||||
updateHighlights();
|
||||
}
|
||||
|
||||
@@ -5650,8 +5613,8 @@ void BaseTextEditorWidget::insertFromMimeData(const QMimeData *source)
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
|
||||
if (CompletionSupport::instance()->isActive())
|
||||
setFocus();
|
||||
if (d->m_codeAssistant->hasContext())
|
||||
d->m_codeAssistant->destroyContext();
|
||||
|
||||
QStringList lines = text.split(QLatin1Char('\n'));
|
||||
QTextCursor cursor = textCursor();
|
||||
@@ -5696,8 +5659,8 @@ void BaseTextEditorWidget::insertFromMimeData(const QMimeData *source)
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
|
||||
if (CompletionSupport::instance()->isActive())
|
||||
setFocus();
|
||||
if (d->m_codeAssistant->hasContext())
|
||||
d->m_codeAssistant->destroyContext();
|
||||
|
||||
if (d->m_snippetOverlay->isVisible() && (text.contains(QLatin1Char('\n'))
|
||||
|| text.contains(QLatin1Char('\t')))) {
|
||||
@@ -5882,18 +5845,7 @@ QString BaseTextEditor::selectedText() const
|
||||
|
||||
QString BaseTextEditor::textAt(int pos, int length) const
|
||||
{
|
||||
QTextCursor c = e->textCursor();
|
||||
|
||||
if (pos < 0)
|
||||
pos = 0;
|
||||
c.movePosition(QTextCursor::End);
|
||||
if (pos + length > c.position())
|
||||
length = c.position() - pos;
|
||||
|
||||
c.setPosition(pos);
|
||||
c.setPosition(pos + length, QTextCursor::KeepAnchor);
|
||||
|
||||
return c.selectedText();
|
||||
return Convenience::textAt(e->textCursor(), pos, length);
|
||||
}
|
||||
|
||||
void BaseTextEditor::remove(int length)
|
||||
@@ -6166,3 +6118,15 @@ void BaseTextEditorWidget::inSnippetMode(bool *active)
|
||||
{
|
||||
*active = d->m_snippetOverlay->isVisible();
|
||||
}
|
||||
|
||||
void BaseTextEditorWidget::invokeAssist(AssistKind kind, IAssistProvider *provider)
|
||||
{
|
||||
d->m_codeAssistant->invoke(kind, provider);
|
||||
}
|
||||
|
||||
IAssistInterface *BaseTextEditorWidget::createAssistInterface(AssistKind kind,
|
||||
AssistReason reason) const
|
||||
{
|
||||
Q_UNUSED(kind);
|
||||
return new DefaultAssistInterface(document(), position(), d->m_document, reason);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define BASETEXTEDITOR_H
|
||||
|
||||
#include "itexteditor.h"
|
||||
#include "icompletioncollector.h"
|
||||
#include "codeassist/assistenums.h"
|
||||
|
||||
#include <find/ifindsupport.h>
|
||||
|
||||
@@ -56,6 +56,9 @@ namespace TextEditor {
|
||||
class TabSettings;
|
||||
class RefactorOverlay;
|
||||
struct RefactorMarker;
|
||||
class IAssistMonitorInterface;
|
||||
class IAssistInterface;
|
||||
class IAssistProvider;
|
||||
|
||||
namespace Internal {
|
||||
class BaseTextEditorPrivate;
|
||||
@@ -235,6 +238,11 @@ public:
|
||||
|
||||
QPoint toolTipPosition(const QTextCursor &c) const;
|
||||
|
||||
void invokeAssist(AssistKind assistKind, IAssistProvider *provider = 0);
|
||||
|
||||
virtual IAssistInterface *createAssistInterface(AssistKind assistKind,
|
||||
AssistReason assistReason) const;
|
||||
|
||||
public slots:
|
||||
void setDisplayName(const QString &title);
|
||||
|
||||
@@ -492,7 +500,6 @@ signals:
|
||||
void requestBlockUpdate(const QTextBlock &);
|
||||
|
||||
private:
|
||||
void maybeRequestAutoCompletion(const QChar &ch);
|
||||
void indentOrUnindent(bool doIndent);
|
||||
void handleHomeKey(bool anchor);
|
||||
void handleBackspaceKey();
|
||||
@@ -531,9 +538,6 @@ private:
|
||||
void transformSelection(Internal::TransformationMethod method);
|
||||
|
||||
private slots:
|
||||
// auto completion
|
||||
void _q_requestAutoCompletion();
|
||||
|
||||
void handleBlockSelection(int diff_row, int diff_col);
|
||||
|
||||
// parentheses matcher
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace TextEditor {
|
||||
|
||||
class BaseTextDocument;
|
||||
class TextEditorActionHandler;
|
||||
class CodeAssistant;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
@@ -288,9 +289,8 @@ public:
|
||||
BaseTextEditorPrivateHighlightBlocks m_highlightBlocksInfo;
|
||||
QTimer *m_highlightBlocksTimer;
|
||||
|
||||
int m_requestAutoCompletionRevision;
|
||||
int m_requestAutoCompletionPosition;
|
||||
QTimer *m_requestAutoCompletionTimer;
|
||||
QScopedPointer<CodeAssistant> m_codeAssistant;
|
||||
bool m_assistRelevantContentAdded;
|
||||
|
||||
QPointer<BaseTextEditorAnimator> m_animator;
|
||||
int m_cursorBlockNumber;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef ASSISTENUMS_H
|
||||
#define ASSISTENUMS_H
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
enum AssistKind
|
||||
{
|
||||
Completion,
|
||||
QuickFix
|
||||
};
|
||||
|
||||
enum AssistReason
|
||||
{
|
||||
IdleEditor,
|
||||
ActivationCharacter,
|
||||
ExplicitlyInvoked
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // ASSISTENUMS_H
|
||||
@@ -0,0 +1,142 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "basicproposalitem.h"
|
||||
|
||||
#include <texteditor/basetexteditor.h>
|
||||
#include <texteditor/quickfix.h>
|
||||
|
||||
#include <QtGui/QTextCursor>
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
BasicProposalItem::BasicProposalItem()
|
||||
: m_order(0)
|
||||
{}
|
||||
|
||||
BasicProposalItem::~BasicProposalItem()
|
||||
{}
|
||||
|
||||
void BasicProposalItem::setIcon(const QIcon &icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
}
|
||||
|
||||
const QIcon &BasicProposalItem::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
void BasicProposalItem::setText(const QString &text)
|
||||
{
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
const QString &BasicProposalItem::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
void BasicProposalItem::setDetail(const QString &detail)
|
||||
{
|
||||
m_detail = detail;
|
||||
}
|
||||
|
||||
const QString &BasicProposalItem::detail() const
|
||||
{
|
||||
return m_detail;
|
||||
}
|
||||
|
||||
void BasicProposalItem::setData(const QVariant &var)
|
||||
{
|
||||
m_data = var;
|
||||
}
|
||||
|
||||
const QVariant &BasicProposalItem::data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
int BasicProposalItem::order() const
|
||||
{
|
||||
return m_order;
|
||||
}
|
||||
|
||||
void BasicProposalItem::setOrder(int order)
|
||||
{
|
||||
m_order = order;
|
||||
}
|
||||
|
||||
bool BasicProposalItem::implicitlyApplies() const
|
||||
{
|
||||
return !data().canConvert<QString>() && !data().canConvert<QuickFixOperation::Ptr>();
|
||||
}
|
||||
|
||||
bool BasicProposalItem::prematurelyApplies(const QChar &c) const
|
||||
{
|
||||
Q_UNUSED(c);
|
||||
return false;
|
||||
}
|
||||
|
||||
void BasicProposalItem::apply(BaseTextEditor *editor, int basePosition) const
|
||||
{
|
||||
if (data().canConvert<QString>())
|
||||
applySnippet(editor, basePosition);
|
||||
else if (data().canConvert<QuickFixOperation::Ptr>())
|
||||
applyQuickFix(editor, basePosition);
|
||||
else
|
||||
applyContextualContent(editor, basePosition);
|
||||
}
|
||||
|
||||
void BasicProposalItem::applyContextualContent(BaseTextEditor *editor, int basePosition) const
|
||||
{
|
||||
const int currentPosition = editor->position();
|
||||
editor->setCursorPosition(basePosition);
|
||||
editor->replace(currentPosition - basePosition, text());
|
||||
}
|
||||
|
||||
void BasicProposalItem::applySnippet(BaseTextEditor *editor, int basePosition) const
|
||||
{
|
||||
BaseTextEditorWidget *editorWidget = static_cast<BaseTextEditorWidget *>(editor->widget());
|
||||
QTextCursor tc = editorWidget->textCursor();
|
||||
tc.setPosition(basePosition, QTextCursor::KeepAnchor);
|
||||
editorWidget->insertCodeSnippet(tc, data().toString());
|
||||
}
|
||||
|
||||
void BasicProposalItem::applyQuickFix(BaseTextEditor *editor, int basePosition) const
|
||||
{
|
||||
Q_UNUSED(editor)
|
||||
Q_UNUSED(basePosition)
|
||||
|
||||
QuickFixOperation::Ptr op = data().value<QuickFixOperation::Ptr>();
|
||||
op->perform();
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BASICPROPOSALITEM_H
|
||||
#define BASICPROPOSALITEM_H
|
||||
|
||||
#include "iassistproposalitem.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class TEXTEDITOR_EXPORT BasicProposalItem : public IAssistProposalItem
|
||||
{
|
||||
public:
|
||||
BasicProposalItem();
|
||||
virtual ~BasicProposalItem();
|
||||
|
||||
void setIcon(const QIcon &icon);
|
||||
const QIcon &icon() const;
|
||||
|
||||
void setText(const QString &text);
|
||||
const QString &text() const;
|
||||
|
||||
void setDetail(const QString &detail);
|
||||
const QString &detail() const;
|
||||
|
||||
void setData(const QVariant &var);
|
||||
const QVariant &data() const;
|
||||
|
||||
int order() const;
|
||||
void setOrder(int order);
|
||||
|
||||
virtual bool implicitlyApplies() const;
|
||||
virtual bool prematurelyApplies(const QChar &c) const;
|
||||
virtual void apply(BaseTextEditor *editor, int basePosition) const;
|
||||
virtual void applyContextualContent(BaseTextEditor *editor, int basePosition) const;
|
||||
virtual void applySnippet(BaseTextEditor *editor, int basePosition) const;
|
||||
virtual void applyQuickFix(BaseTextEditor *editor, int basePosition) const;
|
||||
|
||||
private:
|
||||
QIcon m_icon;
|
||||
QString m_text;
|
||||
QString m_detail;
|
||||
QVariant m_data;
|
||||
int m_order;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // BASICPROPOSALITEM_H
|
||||
@@ -0,0 +1,267 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "basicproposalitemlistmodel.h"
|
||||
#include "basicproposalitem.h"
|
||||
#include "texteditorsettings.h"
|
||||
#include "completionsettings.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QRegExp>
|
||||
#include <QtCore/QtAlgorithms>
|
||||
#include <QtCore/QHash>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
uint qHash(const BasicProposalItem &item)
|
||||
{
|
||||
return qHash(item.text());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const int kMaxSort = 1000;
|
||||
const int kMaxPrefixFilter = 100;
|
||||
|
||||
struct ContentLessThan
|
||||
{
|
||||
bool operator()(const BasicProposalItem *a, const BasicProposalItem *b)
|
||||
{
|
||||
// The order is case-insensitive in principle, but case-sensitive when this
|
||||
// would otherwise mean equality
|
||||
const QString &lowera = a->text().toLower();
|
||||
const QString &lowerb = b->text().toLower();
|
||||
if (lowera == lowerb)
|
||||
return lessThan(a->text(), b->text());
|
||||
else
|
||||
return lessThan(lowera, lowerb);
|
||||
}
|
||||
|
||||
bool lessThan(const QString &a, const QString &b)
|
||||
{
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), CharLessThan());
|
||||
}
|
||||
|
||||
struct CharLessThan
|
||||
{
|
||||
bool operator()(const QChar &a, const QChar &b)
|
||||
{
|
||||
if (a == QLatin1Char('_'))
|
||||
return false;
|
||||
else if (b == QLatin1Char('_'))
|
||||
return true;
|
||||
else
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // Anonymous
|
||||
|
||||
BasicProposalItemListModel::BasicProposalItemListModel()
|
||||
{}
|
||||
|
||||
BasicProposalItemListModel::BasicProposalItemListModel(const QList<BasicProposalItem *> &items)
|
||||
: m_originalItems(items)
|
||||
, m_currentItems(items)
|
||||
{
|
||||
mapPersistentIds();
|
||||
}
|
||||
|
||||
BasicProposalItemListModel::~BasicProposalItemListModel()
|
||||
{
|
||||
qDeleteAll(m_originalItems);
|
||||
}
|
||||
|
||||
void BasicProposalItemListModel::loadContent(const QList<BasicProposalItem *> &items)
|
||||
{
|
||||
m_originalItems = items;
|
||||
m_currentItems = items;
|
||||
mapPersistentIds();
|
||||
}
|
||||
|
||||
void BasicProposalItemListModel::mapPersistentIds()
|
||||
{
|
||||
for (int i = 0; i < m_originalItems.size(); ++i)
|
||||
m_idByText.insert(m_originalItems.at(i)->text(), i);
|
||||
}
|
||||
|
||||
void BasicProposalItemListModel::reset()
|
||||
{
|
||||
m_currentItems = m_originalItems;
|
||||
}
|
||||
|
||||
int BasicProposalItemListModel::size() const
|
||||
{
|
||||
return m_currentItems.size();
|
||||
}
|
||||
|
||||
QString BasicProposalItemListModel::text(int index) const
|
||||
{
|
||||
return m_currentItems.at(index)->text();
|
||||
}
|
||||
|
||||
QIcon BasicProposalItemListModel::icon(int index) const
|
||||
{
|
||||
return m_currentItems.at(index)->icon();
|
||||
}
|
||||
|
||||
QString BasicProposalItemListModel::detail(int index) const
|
||||
{
|
||||
return m_currentItems.at(index)->detail();
|
||||
}
|
||||
|
||||
void BasicProposalItemListModel::removeDuplicates()
|
||||
{
|
||||
QHash<QString, QVariant> unique;
|
||||
QList<BasicProposalItem *>::iterator it = m_originalItems.begin();
|
||||
while (it != m_originalItems.end()) {
|
||||
const BasicProposalItem *item = *it;
|
||||
if (unique.contains(item->text())
|
||||
&& unique.value(item->text(), QVariant()) == item->data()) {
|
||||
it = m_originalItems.erase(it);
|
||||
} else {
|
||||
unique.insert(item->text(), item->data());
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicProposalItemListModel::filter(const QString &prefix)
|
||||
{
|
||||
if (prefix.isEmpty())
|
||||
return;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* It also implements the first-letter-only case sensitivity.
|
||||
*/
|
||||
const TextEditor::CaseSensitivity caseSensitivity =
|
||||
TextEditorSettings::instance()->completionSettings().m_caseSensitivity;
|
||||
|
||||
QString keyRegExp;
|
||||
keyRegExp += QLatin1Char('^');
|
||||
bool first = true;
|
||||
const QLatin1String wordContinuation("[a-z0-9_]*");
|
||||
foreach (const QChar &c, prefix) {
|
||||
if (caseSensitivity == TextEditor::CaseInsensitive ||
|
||||
(caseSensitivity == TextEditor::FirstLetterCaseSensitive && !first)) {
|
||||
|
||||
keyRegExp += QLatin1String("(?:");
|
||||
if (c.isUpper() && !first)
|
||||
keyRegExp += wordContinuation;
|
||||
keyRegExp += QRegExp::escape(c.toUpper());
|
||||
keyRegExp += QLatin1Char('|');
|
||||
keyRegExp += QRegExp::escape(c.toLower());
|
||||
keyRegExp += QLatin1Char(')');
|
||||
} else {
|
||||
if (c.isUpper() && !first)
|
||||
keyRegExp += wordContinuation;
|
||||
keyRegExp += QRegExp::escape(c);
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
const QRegExp regExp(keyRegExp);
|
||||
|
||||
m_currentItems.clear();
|
||||
for (QList<BasicProposalItem *>::const_iterator it = m_originalItems.begin();
|
||||
it != m_originalItems.end();
|
||||
++it) {
|
||||
BasicProposalItem *item = *it;
|
||||
if (regExp.indexIn(item->text()) == 0)
|
||||
m_currentItems.append(item);
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicProposalItemListModel::isSortable() const
|
||||
{
|
||||
if (m_currentItems.size() < kMaxSort)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void BasicProposalItemListModel::sort()
|
||||
{
|
||||
qStableSort(m_currentItems.begin(), m_currentItems.end(), ContentLessThan());
|
||||
}
|
||||
|
||||
int BasicProposalItemListModel::persistentId(int index) const
|
||||
{
|
||||
return m_idByText.value(m_currentItems.at(index)->text());
|
||||
}
|
||||
|
||||
bool BasicProposalItemListModel::supportsPrefixExpansion() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QString BasicProposalItemListModel::proposalPrefix() const
|
||||
{
|
||||
if (m_currentItems.size() >= kMaxPrefixFilter)
|
||||
return QString();
|
||||
|
||||
// Compute common prefix
|
||||
QString firstKey = m_currentItems.first()->text();
|
||||
QString lastKey = m_currentItems.last()->text();
|
||||
const int length = qMin(firstKey.length(), lastKey.length());
|
||||
firstKey.truncate(length);
|
||||
lastKey.truncate(length);
|
||||
|
||||
while (firstKey != lastKey) {
|
||||
firstKey.chop(1);
|
||||
lastKey.chop(1);
|
||||
}
|
||||
|
||||
return firstKey;
|
||||
}
|
||||
|
||||
IAssistProposalItem *BasicProposalItemListModel::proposalItem(int index) const
|
||||
{
|
||||
return m_currentItems.at(index);
|
||||
}
|
||||
|
||||
QPair<QList<BasicProposalItem *>::iterator,
|
||||
QList<BasicProposalItem *>::iterator>
|
||||
BasicProposalItemListModel::currentItems()
|
||||
{
|
||||
return qMakePair(m_currentItems.begin(), m_currentItems.end());
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BASICPROPOSALITEMLISTMODEL_H
|
||||
#define BASICPROPOSALITEMLISTMODEL_H
|
||||
|
||||
#include "igenericproposalmodel.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QPair>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class BasicProposalItem;
|
||||
|
||||
class TEXTEDITOR_EXPORT BasicProposalItemListModel : public IGenericProposalModel
|
||||
{
|
||||
public:
|
||||
BasicProposalItemListModel();
|
||||
BasicProposalItemListModel(const QList<BasicProposalItem *> &items);
|
||||
virtual ~BasicProposalItemListModel();
|
||||
|
||||
virtual void reset();
|
||||
virtual int size() const;
|
||||
virtual QString text(int index) const;
|
||||
virtual QIcon icon(int index) const;
|
||||
virtual QString detail(int index) const;
|
||||
virtual int persistentId(int index) const;
|
||||
virtual void removeDuplicates();
|
||||
virtual void filter(const QString &prefix);
|
||||
virtual bool isSortable() const;
|
||||
virtual void sort();
|
||||
virtual bool supportsPrefixExpansion() const;
|
||||
virtual QString proposalPrefix() const;
|
||||
virtual IAssistProposalItem *proposalItem(int index) const;
|
||||
|
||||
void loadContent(const QList<BasicProposalItem *> &items);
|
||||
|
||||
protected:
|
||||
typedef QList<BasicProposalItem *>::iterator ItemIterator;
|
||||
QPair<ItemIterator, ItemIterator> currentItems();
|
||||
|
||||
private:
|
||||
void mapPersistentIds();
|
||||
|
||||
QHash<QString, int> m_idByText;
|
||||
QList<BasicProposalItem *> m_originalItems;
|
||||
QList<BasicProposalItem *> m_currentItems;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // BASICPROPOSALITEMLISTMODEL_H
|
||||
@@ -0,0 +1,506 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "codeassistant.h"
|
||||
#include "completionassistprovider.h"
|
||||
#include "quickfixassistprovider.h"
|
||||
#include "iassistprocessor.h"
|
||||
#include "iassistproposal.h"
|
||||
#include "iassistproposalwidget.h"
|
||||
#include "iassistinterface.h"
|
||||
#include "iassistproposalitem.h"
|
||||
#include "runner.h"
|
||||
|
||||
#include <texteditor/basetexteditor.h>
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/completionsettings.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QKeyEvent>
|
||||
|
||||
using namespace TextEditor;
|
||||
using namespace Internal;
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
void filterEditorSpecificProviders(QList<T *> *providers, const QString &editorId)
|
||||
{
|
||||
typename QList<T *>::iterator it = providers->begin();
|
||||
while (it != providers->end()) {
|
||||
if ((*it)->supportsEditor(editorId))
|
||||
++it;
|
||||
else
|
||||
it = providers->erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class CodeAssistantPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CodeAssistantPrivate(CodeAssistant *assistant);
|
||||
virtual ~CodeAssistantPrivate();
|
||||
|
||||
void configure(BaseTextEditor *textEditor);
|
||||
bool isConfigured() const;
|
||||
|
||||
void invoke(AssistKind kind, IAssistProvider *provider = 0);
|
||||
void process();
|
||||
void requestProposal(AssistReason reason, AssistKind kind, IAssistProvider *provider = 0);
|
||||
void cancelCurrentRequest();
|
||||
void invalidateCurrentRequestData();
|
||||
void displayProposal(IAssistProposal *newProposal, AssistReason reason);
|
||||
bool isDisplayingProposal() const;
|
||||
bool isWaitingForProposal() const;
|
||||
|
||||
void notifyChange();
|
||||
bool hasContext() const;
|
||||
void destroyContext();
|
||||
|
||||
CompletionAssistProvider *identifyActivationSequence();
|
||||
|
||||
void stopAutomaticProposalTimer();
|
||||
void startAutomaticProposalTimer();
|
||||
|
||||
virtual bool eventFilter(QObject *o, QEvent *e);
|
||||
|
||||
private slots:
|
||||
void finalizeRequest();
|
||||
void proposalComputed();
|
||||
void processProposalItem(IAssistProposalItem *proposalItem);
|
||||
void handlePrefixExpansion(const QString &newPrefix);
|
||||
void finalizeProposal();
|
||||
void automaticProposalTimeout();
|
||||
void updateCompletionSettings(const TextEditor::CompletionSettings &settings);
|
||||
|
||||
private:
|
||||
CodeAssistant *m_q;
|
||||
BaseTextEditor *m_textEditor;
|
||||
QList<CompletionAssistProvider *> m_completionProviders;
|
||||
QList<QuickFixAssistProvider *> m_quickFixProviders;
|
||||
Internal::ProcessorRunner *m_requestRunner;
|
||||
CompletionAssistProvider *m_requestProvider;
|
||||
AssistKind m_assistKind;
|
||||
IAssistProposalWidget *m_proposalWidget;
|
||||
QScopedPointer<IAssistProposal> m_proposal;
|
||||
bool m_proposalApplied;
|
||||
bool m_receivedContentWhileWaiting;
|
||||
QTimer m_automaticProposalTimer;
|
||||
CompletionSettings m_settings;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
// --------------------
|
||||
// CodeAssistantPrivate
|
||||
// --------------------
|
||||
CodeAssistantPrivate::CodeAssistantPrivate(CodeAssistant *assistant)
|
||||
: m_q(assistant)
|
||||
, m_textEditor(0)
|
||||
, m_requestRunner(0)
|
||||
, m_requestProvider(0)
|
||||
, m_proposalWidget(0)
|
||||
, m_proposalApplied(false)
|
||||
, m_receivedContentWhileWaiting(false)
|
||||
, m_settings(TextEditorSettings::instance()->completionSettings())
|
||||
{
|
||||
m_automaticProposalTimer.setSingleShot(true);
|
||||
m_automaticProposalTimer.setInterval(250);
|
||||
connect(&m_automaticProposalTimer, SIGNAL(timeout()), this, SLOT(automaticProposalTimeout()));
|
||||
|
||||
connect(TextEditorSettings::instance(),
|
||||
SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
|
||||
this,
|
||||
SLOT(updateCompletionSettings(TextEditor::CompletionSettings)));
|
||||
}
|
||||
|
||||
CodeAssistantPrivate::~CodeAssistantPrivate()
|
||||
{}
|
||||
|
||||
void CodeAssistantPrivate::configure(BaseTextEditor *textEditor)
|
||||
{
|
||||
// @TODO: There's a list of providers but currently only the first one is used. Perhaps we
|
||||
// should implement a truly mechanism to support multiple providers for an editor (either
|
||||
// merging or not proposals) or just leave it as not extensible and store directly the one
|
||||
// completion and quick-fix provider (getting rid of the list).
|
||||
|
||||
m_textEditor = textEditor;
|
||||
m_completionProviders =
|
||||
ExtensionSystem::PluginManager::instance()->getObjects<CompletionAssistProvider>();
|
||||
filterEditorSpecificProviders(&m_completionProviders, m_textEditor->id());
|
||||
m_quickFixProviders =
|
||||
ExtensionSystem::PluginManager::instance()->getObjects<QuickFixAssistProvider>();
|
||||
filterEditorSpecificProviders(&m_quickFixProviders, m_textEditor->id());
|
||||
|
||||
m_textEditor->editorWidget()->installEventFilter(this);
|
||||
}
|
||||
|
||||
bool CodeAssistantPrivate::isConfigured() const
|
||||
{
|
||||
return m_textEditor != 0;
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::invoke(AssistKind kind, IAssistProvider *provider)
|
||||
{
|
||||
if (!isConfigured())
|
||||
return;
|
||||
|
||||
stopAutomaticProposalTimer();
|
||||
|
||||
if (isDisplayingProposal() && m_assistKind == kind && !m_proposal->isFragile()) {
|
||||
m_proposalWidget->setReason(ExplicitlyInvoked);
|
||||
} else {
|
||||
destroyContext();
|
||||
requestProposal(ExplicitlyInvoked, kind, provider);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::process()
|
||||
{
|
||||
if (!isConfigured())
|
||||
return;
|
||||
|
||||
stopAutomaticProposalTimer();
|
||||
|
||||
if (m_settings.m_completionTrigger != ManualCompletion) {
|
||||
if (CompletionAssistProvider *provider = identifyActivationSequence()) {
|
||||
if (isWaitingForProposal())
|
||||
cancelCurrentRequest();
|
||||
requestProposal(ActivationCharacter, Completion, provider);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
startAutomaticProposalTimer();
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::requestProposal(AssistReason reason,
|
||||
AssistKind kind,
|
||||
IAssistProvider *provider)
|
||||
{
|
||||
Q_ASSERT(!isWaitingForProposal());
|
||||
|
||||
if (!provider) {
|
||||
if (kind == Completion) {
|
||||
if (!m_completionProviders.isEmpty())
|
||||
provider = m_completionProviders.at(0);
|
||||
} else if (!m_quickFixProviders.isEmpty()) {
|
||||
provider = m_quickFixProviders.at(0);
|
||||
}
|
||||
|
||||
if (!provider)
|
||||
return;
|
||||
}
|
||||
|
||||
m_assistKind = kind;
|
||||
IAssistProcessor *processor = provider->createProcessor();
|
||||
IAssistInterface *assistInterface =
|
||||
m_textEditor->editorWidget()->createAssistInterface(kind, reason);
|
||||
if (!assistInterface)
|
||||
return;
|
||||
|
||||
if (kind == Completion) {
|
||||
CompletionAssistProvider *completionProvider =
|
||||
static_cast<CompletionAssistProvider *>(provider);
|
||||
if (completionProvider->isAsynchronous()) {
|
||||
m_requestProvider = completionProvider;
|
||||
m_requestRunner = new ProcessorRunner;
|
||||
connect(m_requestRunner, SIGNAL(finished()), this, SLOT(proposalComputed()));
|
||||
connect(m_requestRunner, SIGNAL(finished()), this, SLOT(finalizeRequest()));
|
||||
assistInterface->detach(m_requestRunner);
|
||||
m_requestRunner->setReason(reason);
|
||||
m_requestRunner->setProcessor(processor);
|
||||
m_requestRunner->setAssistInterface(assistInterface);
|
||||
m_requestRunner->start();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IAssistProposal *newProposal = processor->perform(assistInterface);
|
||||
displayProposal(newProposal, reason);
|
||||
delete processor;
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::cancelCurrentRequest()
|
||||
{
|
||||
m_requestRunner->setDiscardProposal(true);
|
||||
disconnect(m_requestRunner, SIGNAL(finished()), this, SLOT(proposalComputed()));
|
||||
invalidateCurrentRequestData();
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::proposalComputed()
|
||||
{
|
||||
// Since the request runner is a different thread, there's still a gap in which the queued
|
||||
// signal could be processed after an invalidation of the current request.
|
||||
if (!m_requestRunner)
|
||||
return;
|
||||
|
||||
IAssistProposal *newProposal = m_requestRunner->proposal();
|
||||
AssistReason reason = m_requestRunner->reason();
|
||||
invalidateCurrentRequestData();
|
||||
displayProposal(newProposal, reason);
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistReason reason)
|
||||
{
|
||||
if (!newProposal)
|
||||
return;
|
||||
|
||||
QScopedPointer<IAssistProposal> proposalCandidate(newProposal);
|
||||
|
||||
if (isDisplayingProposal()) {
|
||||
if (!m_proposal->isFragile() || proposalCandidate->isFragile())
|
||||
return;
|
||||
destroyContext();
|
||||
}
|
||||
|
||||
if (m_textEditor->position() < proposalCandidate->basePosition())
|
||||
return;
|
||||
|
||||
m_proposal.reset(proposalCandidate.take());
|
||||
|
||||
if (m_proposal->isCorrective())
|
||||
m_proposal->makeCorrection(m_textEditor);
|
||||
|
||||
m_proposalWidget = m_proposal->createWidget();
|
||||
connect(m_proposalWidget, SIGNAL(destroyed()), this, SLOT(finalizeProposal()));
|
||||
connect(m_proposalWidget, SIGNAL(prefixExpanded(QString)),
|
||||
this, SLOT(handlePrefixExpansion(QString)));
|
||||
connect(m_proposalWidget, SIGNAL(proposalItemActivated(IAssistProposalItem*)),
|
||||
this, SLOT(processProposalItem(IAssistProposalItem*)));
|
||||
m_proposalWidget->setAssistant(m_q);
|
||||
m_proposalWidget->setReason(reason);
|
||||
m_proposalWidget->setUnderlyingWidget(m_textEditor->widget());
|
||||
m_proposalWidget->setModel(m_proposal->model());
|
||||
m_proposalWidget->setDisplayRect(m_textEditor->cursorRect(m_proposal->basePosition()));
|
||||
if (m_receivedContentWhileWaiting)
|
||||
m_proposalWidget->setIsSynchronized(false);
|
||||
else
|
||||
m_proposalWidget->setIsSynchronized(true);
|
||||
m_proposalWidget->showProposal(m_textEditor->textAt(
|
||||
m_proposal->basePosition(),
|
||||
m_textEditor->position() - m_proposal->basePosition()));
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::processProposalItem(IAssistProposalItem *proposalItem)
|
||||
{
|
||||
proposalItem->apply(m_textEditor, m_proposal->basePosition());
|
||||
destroyContext();
|
||||
process();
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::handlePrefixExpansion(const QString &newPrefix)
|
||||
{
|
||||
const int currentPosition = m_textEditor->position();
|
||||
m_textEditor->setCursorPosition(m_proposal->basePosition());
|
||||
m_textEditor->replace(currentPosition - m_proposal->basePosition(), newPrefix);
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::finalizeRequest()
|
||||
{
|
||||
if (ProcessorRunner *runner = qobject_cast<ProcessorRunner *>(sender()))
|
||||
delete runner;
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::finalizeProposal()
|
||||
{
|
||||
m_proposal.reset();
|
||||
m_proposalWidget = 0;
|
||||
if (m_receivedContentWhileWaiting)
|
||||
m_receivedContentWhileWaiting = false;
|
||||
}
|
||||
|
||||
bool CodeAssistantPrivate::isDisplayingProposal() const
|
||||
{
|
||||
return m_proposalWidget != 0;
|
||||
}
|
||||
|
||||
bool CodeAssistantPrivate::isWaitingForProposal() const
|
||||
{
|
||||
return m_requestRunner != 0;
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::invalidateCurrentRequestData()
|
||||
{
|
||||
m_requestRunner = 0;
|
||||
m_requestProvider = 0;
|
||||
}
|
||||
|
||||
CompletionAssistProvider *CodeAssistantPrivate::identifyActivationSequence()
|
||||
{
|
||||
for (int i = 0; i < m_completionProviders.size(); ++i) {
|
||||
CompletionAssistProvider *provider = m_completionProviders.at(i);
|
||||
const int length = provider->activationCharSequenceLength();
|
||||
if (length == 0)
|
||||
continue;
|
||||
const QString &sequence = m_textEditor->textAt(m_textEditor->position() - length, length);
|
||||
if (provider->isActivationCharSequence(sequence))
|
||||
return provider;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::notifyChange()
|
||||
{
|
||||
stopAutomaticProposalTimer();
|
||||
|
||||
if (isDisplayingProposal()) {
|
||||
if (m_textEditor->position() < m_proposal->basePosition())
|
||||
destroyContext();
|
||||
else
|
||||
m_proposalWidget->updateProposal(
|
||||
m_textEditor->textAt(m_proposal->basePosition(),
|
||||
m_textEditor->position() - m_proposal->basePosition()));
|
||||
}
|
||||
}
|
||||
|
||||
bool CodeAssistantPrivate::hasContext() const
|
||||
{
|
||||
return m_requestRunner || m_proposalWidget;
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::destroyContext()
|
||||
{
|
||||
stopAutomaticProposalTimer();
|
||||
|
||||
if (isWaitingForProposal()) {
|
||||
cancelCurrentRequest();
|
||||
} else if (isDisplayingProposal()) {
|
||||
m_proposalWidget->closeProposal();
|
||||
disconnect(m_proposalWidget, SIGNAL(destroyed()), this, SLOT(finalizeProposal()));
|
||||
finalizeProposal();
|
||||
}
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::startAutomaticProposalTimer()
|
||||
{
|
||||
if (m_settings.m_completionTrigger == AutomaticCompletion)
|
||||
m_automaticProposalTimer.start();
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::automaticProposalTimeout()
|
||||
{
|
||||
if (isWaitingForProposal() || (isDisplayingProposal() && !m_proposal->isFragile()))
|
||||
return;
|
||||
|
||||
requestProposal(IdleEditor, Completion);
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::stopAutomaticProposalTimer()
|
||||
{
|
||||
if (m_automaticProposalTimer.isActive())
|
||||
m_automaticProposalTimer.stop();
|
||||
}
|
||||
|
||||
void CodeAssistantPrivate::updateCompletionSettings(const TextEditor::CompletionSettings &settings)
|
||||
{
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
bool CodeAssistantPrivate::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
Q_UNUSED(o);
|
||||
|
||||
if (isWaitingForProposal()) {
|
||||
QEvent::Type type = e->type();
|
||||
if (type == QEvent::FocusOut) {
|
||||
destroyContext();
|
||||
} else if (type == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
|
||||
const QString &keyText = keyEvent->text();
|
||||
if ((keyText.isEmpty()
|
||||
&& keyEvent->key() != Qt::LeftArrow
|
||||
&& keyEvent->key() != Qt::RightArrow
|
||||
&& keyEvent->key() != Qt::Key_Shift)
|
||||
|| (!keyText.isEmpty() &&
|
||||
!m_requestProvider->isContinuationChar(keyText.at(0)))) {
|
||||
destroyContext();
|
||||
} else if (!keyText.isEmpty() && !m_receivedContentWhileWaiting) {
|
||||
m_receivedContentWhileWaiting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------
|
||||
// CodeAssistant
|
||||
// -------------
|
||||
CodeAssistant::CodeAssistant() : m_d(new CodeAssistantPrivate(this))
|
||||
{}
|
||||
|
||||
CodeAssistant::~CodeAssistant()
|
||||
{}
|
||||
|
||||
void CodeAssistant::configure(BaseTextEditor *textEditor)
|
||||
{
|
||||
m_d->configure(textEditor);
|
||||
}
|
||||
|
||||
void CodeAssistant::process()
|
||||
{
|
||||
m_d->process();
|
||||
}
|
||||
|
||||
void CodeAssistant::notifyChange()
|
||||
{
|
||||
m_d->notifyChange();
|
||||
}
|
||||
|
||||
bool CodeAssistant::hasContext() const
|
||||
{
|
||||
return m_d->hasContext();
|
||||
}
|
||||
|
||||
void CodeAssistant::destroyContext()
|
||||
{
|
||||
m_d->destroyContext();
|
||||
}
|
||||
|
||||
void CodeAssistant::invoke(AssistKind kind, IAssistProvider *provider)
|
||||
{
|
||||
m_d->invoke(kind, provider);
|
||||
}
|
||||
|
||||
#include "codeassistant.moc"
|
||||
+23
-22
@@ -30,39 +30,40 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QUICKFIXCOLLECTOR_H
|
||||
#define QUICKFIXCOLLECTOR_H
|
||||
#ifndef CODEASSISTANT_H
|
||||
#define CODEASSISTANT_H
|
||||
|
||||
#include <texteditor/quickfix.h>
|
||||
#include "assistenums.h"
|
||||
|
||||
namespace ExtensionSystem {
|
||||
class IPlugin;
|
||||
}
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
namespace TextEditor {
|
||||
class QuickFixState;
|
||||
}
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
class CodeAssistantPrivate;
|
||||
class IAssistProvider;
|
||||
class BaseTextEditor;
|
||||
|
||||
class CppQuickFixCollector: public TextEditor::QuickFixCollector
|
||||
class CodeAssistant
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CppQuickFixCollector();
|
||||
virtual ~CppQuickFixCollector();
|
||||
CodeAssistant();
|
||||
~CodeAssistant();
|
||||
|
||||
virtual bool supportsEditor(TextEditor::ITextEditor *editor) const;
|
||||
virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::BaseTextEditorWidget *editor);
|
||||
void configure(BaseTextEditor *textEditor);
|
||||
|
||||
virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
|
||||
void process();
|
||||
void notifyChange();
|
||||
bool hasContext() const;
|
||||
void destroyContext();
|
||||
|
||||
/// Registers all quick-fixes in this plug-in as auto-released objects.
|
||||
static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
|
||||
void invoke(AssistKind assistKind, IAssistProvider *provider = 0);
|
||||
|
||||
private:
|
||||
QScopedPointer<CodeAssistantPrivate> m_d;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppEditor
|
||||
} //TextEditor
|
||||
|
||||
#endif // QUICKFIXCOLLECTOR_H
|
||||
#endif // CODEASSISTANT_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "completionassistprovider.h"
|
||||
|
||||
#include <QtCore/QChar>
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
CompletionAssistProvider::CompletionAssistProvider()
|
||||
{}
|
||||
|
||||
CompletionAssistProvider::~CompletionAssistProvider()
|
||||
{}
|
||||
|
||||
bool CompletionAssistProvider::isAsynchronous() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int CompletionAssistProvider::activationCharSequenceLength() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
||||
{
|
||||
Q_UNUSED(sequence)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompletionAssistProvider::isContinuationChar(const QChar &c) const
|
||||
{
|
||||
return c.isLetterOrNumber() || c == QLatin1Char('_');
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef COMPLETIONASSISTPROVIDER_H
|
||||
#define COMPLETIONASSISTPROVIDER_H
|
||||
|
||||
#include "iassistprovider.h"
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class TEXTEDITOR_EXPORT CompletionAssistProvider : public IAssistProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CompletionAssistProvider();
|
||||
virtual ~CompletionAssistProvider();
|
||||
|
||||
virtual bool isAsynchronous() const;
|
||||
virtual int activationCharSequenceLength() const;
|
||||
virtual bool isActivationCharSequence(const QString &sequence) const;
|
||||
virtual bool isContinuationChar(const QChar &c) const;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // COMPLETIONASSISTPROVIDER_H
|
||||
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "defaultassistinterface.h"
|
||||
|
||||
#include <texteditor/convenience.h>
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtGui/QTextDocument>
|
||||
#include <QtGui/QTextCursor>
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
DefaultAssistInterface::DefaultAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
AssistReason reason)
|
||||
: m_document(document)
|
||||
, m_detached(false)
|
||||
, m_position(position)
|
||||
, m_file(file)
|
||||
, m_reason(reason)
|
||||
{}
|
||||
|
||||
DefaultAssistInterface::~DefaultAssistInterface()
|
||||
{
|
||||
if (m_detached)
|
||||
delete m_document;
|
||||
}
|
||||
|
||||
QChar DefaultAssistInterface::characterAt(int position) const
|
||||
{
|
||||
return m_document->characterAt(position);
|
||||
}
|
||||
|
||||
QString DefaultAssistInterface::textAt(int pos, int length) const
|
||||
{
|
||||
return Convenience::textAt(QTextCursor(m_document), pos, length);
|
||||
}
|
||||
|
||||
void DefaultAssistInterface::detach(QThread *destination)
|
||||
{
|
||||
m_document = new QTextDocument(m_document->toPlainText());
|
||||
m_document->moveToThread(destination);
|
||||
m_detached = true;
|
||||
}
|
||||
|
||||
AssistReason DefaultAssistInterface::reason() const
|
||||
{
|
||||
return m_reason;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef DEFAULTASSISTINTERFACE_H
|
||||
#define DEFAULTASSISTINTERFACE_H
|
||||
|
||||
#include "iassistinterface.h"
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class TEXTEDITOR_EXPORT DefaultAssistInterface : public IAssistInterface
|
||||
{
|
||||
public:
|
||||
DefaultAssistInterface(QTextDocument *document,
|
||||
int position,
|
||||
Core::IFile *file,
|
||||
AssistReason reason);
|
||||
virtual ~DefaultAssistInterface();
|
||||
|
||||
virtual int position() const { return m_position; }
|
||||
virtual QChar characterAt(int position) const;
|
||||
virtual QString textAt(int position, int length) const;
|
||||
virtual const Core::IFile *file() const { return m_file; }
|
||||
virtual QTextDocument *document() const { return m_document; }
|
||||
virtual void detach(QThread *destination);
|
||||
virtual AssistReason reason() const;
|
||||
|
||||
private:
|
||||
QTextDocument *m_document;
|
||||
bool m_detached;
|
||||
int m_position;
|
||||
Core::IFile *m_file;
|
||||
AssistReason m_reason;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // DEFAULTASSISTINTERFACE_H
|
||||
@@ -0,0 +1,73 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "functionhintproposal.h"
|
||||
#include "ifunctionhintproposalmodel.h"
|
||||
#include "functionhintproposalwidget.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
FunctionHintProposal::FunctionHintProposal(int cursorPos, IFunctionHintProposalModel *model)
|
||||
: m_basePosition(cursorPos)
|
||||
, m_model(model)
|
||||
{}
|
||||
|
||||
FunctionHintProposal::~FunctionHintProposal()
|
||||
{}
|
||||
|
||||
bool FunctionHintProposal::isFragile() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int FunctionHintProposal::basePosition() const
|
||||
{
|
||||
return m_basePosition;
|
||||
}
|
||||
|
||||
bool FunctionHintProposal::isCorrective() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void FunctionHintProposal::makeCorrection(BaseTextEditor *)
|
||||
{}
|
||||
|
||||
IAssistProposalModel *FunctionHintProposal::model() const
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
IAssistProposalWidget *FunctionHintProposal::createWidget() const
|
||||
{
|
||||
return new FunctionHintProposalWidget;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef FUNCTIONHINTPROPOSAL_H
|
||||
#define FUNCTIONHINTPROPOSAL_H
|
||||
|
||||
#include "iassistproposal.h"
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class IFunctionHintProposalModel;
|
||||
|
||||
class TEXTEDITOR_EXPORT FunctionHintProposal : public IAssistProposal
|
||||
{
|
||||
public:
|
||||
FunctionHintProposal(int cursorPos, IFunctionHintProposalModel *model);
|
||||
virtual ~FunctionHintProposal();
|
||||
|
||||
virtual bool isFragile() const;
|
||||
virtual int basePosition() const;
|
||||
virtual bool isCorrective() const;
|
||||
virtual void makeCorrection(BaseTextEditor *editor);
|
||||
virtual IAssistProposalModel *model() const;
|
||||
virtual IAssistProposalWidget *createWidget() const;
|
||||
|
||||
private:
|
||||
int m_basePosition;
|
||||
IFunctionHintProposalModel *m_model;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // FUNCTIONHINTPROPOSAL_H
|
||||
@@ -0,0 +1,314 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "functionhintproposalwidget.h"
|
||||
#include "ifunctionhintproposalmodel.h"
|
||||
#include "codeassistant.h"
|
||||
|
||||
#include <utils/faketooltip.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QToolButton>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QShortcutEvent>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
// -------------------------
|
||||
// HintProposalWidgetPrivate
|
||||
// -------------------------
|
||||
struct FunctionHintProposalWidgetPrivate
|
||||
{
|
||||
FunctionHintProposalWidgetPrivate();
|
||||
|
||||
const QWidget *m_underlyingWidget;
|
||||
CodeAssistant *m_assistant;
|
||||
IFunctionHintProposalModel *m_model;
|
||||
Utils::FakeToolTip *m_popupFrame;
|
||||
QLabel *m_numberLabel;
|
||||
QLabel *m_hintLabel;
|
||||
QWidget *m_pager;
|
||||
QRect m_displayRect;
|
||||
int m_currentHint;
|
||||
int m_totalHints;
|
||||
int m_currentArgument;
|
||||
bool m_escapePressed;
|
||||
};
|
||||
|
||||
FunctionHintProposalWidgetPrivate::FunctionHintProposalWidgetPrivate()
|
||||
: m_underlyingWidget(0)
|
||||
, m_assistant(0)
|
||||
, m_model(0)
|
||||
, m_popupFrame(new Utils::FakeToolTip)
|
||||
, m_numberLabel(new QLabel)
|
||||
, m_hintLabel(new QLabel)
|
||||
, m_pager(new QWidget)
|
||||
, m_currentHint(-1)
|
||||
, m_totalHints(0)
|
||||
, m_currentArgument(-1)
|
||||
, m_escapePressed(false)
|
||||
{
|
||||
m_hintLabel->setTextFormat(Qt::RichText);
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// HintProposalWidget
|
||||
// ------------------
|
||||
FunctionHintProposalWidget::FunctionHintProposalWidget()
|
||||
: m_d(new FunctionHintProposalWidgetPrivate)
|
||||
{
|
||||
QToolButton *downArrow = new QToolButton;
|
||||
downArrow->setArrowType(Qt::DownArrow);
|
||||
downArrow->setFixedSize(16, 16);
|
||||
downArrow->setAutoRaise(true);
|
||||
|
||||
QToolButton *upArrow = new QToolButton;
|
||||
upArrow->setArrowType(Qt::UpArrow);
|
||||
upArrow->setFixedSize(16, 16);
|
||||
upArrow->setAutoRaise(true);
|
||||
|
||||
QHBoxLayout *pagerLayout = new QHBoxLayout(m_d->m_pager);
|
||||
pagerLayout->setMargin(0);
|
||||
pagerLayout->setSpacing(0);
|
||||
pagerLayout->addWidget(upArrow);
|
||||
pagerLayout->addWidget(m_d->m_numberLabel);
|
||||
pagerLayout->addWidget(downArrow);
|
||||
|
||||
QHBoxLayout *popupLayout = new QHBoxLayout(m_d->m_popupFrame);
|
||||
popupLayout->setMargin(0);
|
||||
popupLayout->setSpacing(0);
|
||||
popupLayout->addWidget(m_d->m_pager);
|
||||
popupLayout->addWidget(m_d->m_hintLabel);
|
||||
|
||||
connect(upArrow, SIGNAL(clicked()), SLOT(previousPage()));
|
||||
connect(downArrow, SIGNAL(clicked()), SLOT(nextPage()));
|
||||
|
||||
qApp->installEventFilter(this);
|
||||
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
FunctionHintProposalWidget::~FunctionHintProposalWidget()
|
||||
{
|
||||
delete m_d->m_model;
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::setAssistant(CodeAssistant *assistant)
|
||||
{
|
||||
m_d->m_assistant = assistant;
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::setReason(AssistReason reason)
|
||||
{
|
||||
Q_UNUSED(reason);
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::setUnderlyingWidget(const QWidget *underlyingWidget)
|
||||
{
|
||||
m_d->m_underlyingWidget = underlyingWidget;
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::setModel(IAssistProposalModel *model)
|
||||
{
|
||||
m_d->m_model = static_cast<IFunctionHintProposalModel *>(model);
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::setDisplayRect(const QRect &rect)
|
||||
{
|
||||
m_d->m_displayRect = rect;
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::setIsSynchronized(bool)
|
||||
{}
|
||||
|
||||
void FunctionHintProposalWidget::showProposal(const QString &prefix)
|
||||
{
|
||||
m_d->m_totalHints = m_d->m_model->size();
|
||||
if (m_d->m_totalHints == 0) {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
m_d->m_pager->setVisible(m_d->m_totalHints > 1);
|
||||
m_d->m_currentHint = 0;
|
||||
if (!updateAndCheck(prefix)) {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
m_d->m_popupFrame->show();
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::updateProposal(const QString &prefix)
|
||||
{
|
||||
updateAndCheck(prefix);
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::closeProposal()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::abort()
|
||||
{
|
||||
if (m_d->m_popupFrame->isVisible())
|
||||
m_d->m_popupFrame->close();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
bool FunctionHintProposalWidget::eventFilter(QObject *obj, QEvent *e)
|
||||
{
|
||||
switch (e->type()) {
|
||||
case QEvent::ShortcutOverride:
|
||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
|
||||
m_d->m_escapePressed = true;
|
||||
}
|
||||
break;
|
||||
case QEvent::KeyPress:
|
||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
|
||||
m_d->m_escapePressed = true;
|
||||
}
|
||||
if (m_d->m_model->size() > 1) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent*>(e);
|
||||
if (ke->key() == Qt::Key_Up) {
|
||||
previousPage();
|
||||
return true;
|
||||
} else if (ke->key() == Qt::Key_Down) {
|
||||
nextPage();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case QEvent::KeyRelease:
|
||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape && m_d->m_escapePressed) {
|
||||
abort();
|
||||
return false;
|
||||
}
|
||||
m_d->m_assistant->notifyChange();
|
||||
break;
|
||||
case QEvent::WindowDeactivate:
|
||||
case QEvent::FocusOut:
|
||||
if (obj != m_d->m_underlyingWidget) {
|
||||
break;
|
||||
}
|
||||
abort();
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::Wheel: {
|
||||
QWidget *widget = qobject_cast<QWidget *>(obj);
|
||||
if (! (widget == this || isAncestorOf(widget))) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::nextPage()
|
||||
{
|
||||
m_d->m_currentHint = (m_d->m_currentHint + 1) % m_d->m_totalHints;
|
||||
updateContent();
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::previousPage()
|
||||
{
|
||||
if (m_d->m_currentHint == 0)
|
||||
m_d->m_currentHint = m_d->m_totalHints - 1;
|
||||
else
|
||||
--m_d->m_currentHint;
|
||||
updateContent();
|
||||
}
|
||||
|
||||
bool FunctionHintProposalWidget::updateAndCheck(const QString &prefix)
|
||||
{
|
||||
const int activeArgument = m_d->m_model->activeArgument(prefix);
|
||||
if (activeArgument == -1) {
|
||||
abort();
|
||||
return false;
|
||||
} else if (activeArgument != m_d->m_currentArgument) {
|
||||
m_d->m_currentArgument = activeArgument;
|
||||
updateContent();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::updateContent()
|
||||
{
|
||||
m_d->m_hintLabel->setText(m_d->m_model->text(m_d->m_currentHint));
|
||||
m_d->m_numberLabel->setText(tr("%1 of %2").arg(m_d->m_currentHint + 1).arg(m_d->m_totalHints));
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void FunctionHintProposalWidget::updatePosition()
|
||||
{
|
||||
const QDesktopWidget *desktop = QApplication::desktop();
|
||||
#ifdef Q_WS_MAC
|
||||
const QRect &screen = desktop->availableGeometry(desktop->screenNumber(m_d->m_underlyingWidget));
|
||||
#else
|
||||
const QRect &screen = desktop->screenGeometry(desktop->screenNumber(m_d->m_underlyingWidget));
|
||||
#endif
|
||||
|
||||
m_d->m_pager->setFixedWidth(m_d->m_pager->minimumSizeHint().width());
|
||||
|
||||
m_d->m_hintLabel->setWordWrap(false);
|
||||
const int maxDesiredWidth = screen.width() - 10;
|
||||
const QSize &minHint = m_d->m_popupFrame->minimumSizeHint();
|
||||
if (minHint.width() > maxDesiredWidth) {
|
||||
m_d->m_hintLabel->setWordWrap(true);
|
||||
m_d->m_popupFrame->setFixedWidth(maxDesiredWidth);
|
||||
const int extra = m_d->m_popupFrame->contentsMargins().bottom() +
|
||||
m_d->m_popupFrame->contentsMargins().top();
|
||||
m_d->m_popupFrame->setFixedHeight(
|
||||
m_d->m_hintLabel->heightForWidth(maxDesiredWidth - m_d->m_pager->width()) + extra);
|
||||
} else {
|
||||
m_d->m_popupFrame->setFixedSize(minHint);
|
||||
}
|
||||
|
||||
const QSize &sz = m_d->m_popupFrame->size();
|
||||
QPoint pos = m_d->m_displayRect.topLeft();
|
||||
pos.setY(pos.y() - sz.height() - 1);
|
||||
if (pos.x() + sz.width() > screen.right())
|
||||
pos.setX(screen.right() - sz.width());
|
||||
m_d->m_popupFrame->move(pos);
|
||||
}
|
||||
|
||||
} // TextEditor
|
||||
@@ -0,0 +1,82 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef FUNCTIONHINTPROPOSALWIDGET_H
|
||||
#define FUNCTIONHINTPROPOSALWIDGET_H
|
||||
|
||||
#include "iassistproposalwidget.h"
|
||||
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
struct FunctionHintProposalWidgetPrivate;
|
||||
|
||||
class TEXTEDITOR_EXPORT FunctionHintProposalWidget : public IAssistProposalWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FunctionHintProposalWidget();
|
||||
virtual ~FunctionHintProposalWidget();
|
||||
|
||||
virtual void setAssistant(CodeAssistant *assistant);
|
||||
virtual void setReason(AssistReason reason);
|
||||
virtual void setUnderlyingWidget(const QWidget *underlyingWidget);
|
||||
virtual void setModel(IAssistProposalModel *model);
|
||||
virtual void setDisplayRect(const QRect &rect);
|
||||
virtual void setIsSynchronized(bool isSync);
|
||||
|
||||
virtual void showProposal(const QString &prefix);
|
||||
virtual void updateProposal(const QString &prefix);
|
||||
virtual void closeProposal();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *o, QEvent *e);
|
||||
|
||||
private slots:
|
||||
void nextPage();
|
||||
void previousPage();
|
||||
|
||||
private:
|
||||
bool updateAndCheck(const QString &prefix);
|
||||
void updateContent();
|
||||
void updatePosition();
|
||||
void abort();
|
||||
|
||||
private:
|
||||
QScopedPointer<FunctionHintProposalWidgetPrivate> m_d;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // FUNCTIONHINTPROPOSALWIDGET_H
|
||||
@@ -0,0 +1,78 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "genericproposal.h"
|
||||
#include "igenericproposalmodel.h"
|
||||
#include "genericproposalwidget.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
GenericProposal::GenericProposal(int cursorPos, IGenericProposalModel *model)
|
||||
: m_basePosition(cursorPos)
|
||||
, m_model(model)
|
||||
{}
|
||||
|
||||
GenericProposal::~GenericProposal()
|
||||
{}
|
||||
|
||||
bool GenericProposal::isFragile() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int GenericProposal::basePosition() const
|
||||
{
|
||||
return m_basePosition;
|
||||
}
|
||||
|
||||
bool GenericProposal::isCorrective() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GenericProposal::makeCorrection(BaseTextEditor *)
|
||||
{}
|
||||
|
||||
IAssistProposalModel *GenericProposal::model() const
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
IAssistProposalWidget *GenericProposal::createWidget() const
|
||||
{
|
||||
return new GenericProposalWidget;
|
||||
}
|
||||
|
||||
void GenericProposal::moveBasePosition(int length)
|
||||
{
|
||||
m_basePosition += length;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GENERICPROPOSAL_H
|
||||
#define GENERICPROPOSAL_H
|
||||
|
||||
#include "iassistproposal.h"
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class IGenericProposalModel;
|
||||
|
||||
class TEXTEDITOR_EXPORT GenericProposal : public IAssistProposal
|
||||
{
|
||||
public:
|
||||
GenericProposal(int cursorPos, IGenericProposalModel *model);
|
||||
~GenericProposal();
|
||||
|
||||
virtual bool isFragile() const;
|
||||
virtual int basePosition() const;
|
||||
virtual bool isCorrective() const;
|
||||
virtual void makeCorrection(BaseTextEditor *editor);
|
||||
virtual IAssistProposalModel *model() const;
|
||||
virtual IAssistProposalWidget *createWidget() const;
|
||||
|
||||
protected:
|
||||
void moveBasePosition(int length);
|
||||
|
||||
private:
|
||||
int m_basePosition;
|
||||
IGenericProposalModel *m_model;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // GENERICPROPOSAL_H
|
||||
@@ -0,0 +1,576 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "genericproposalwidget.h"
|
||||
#include "iassistprovider.h"
|
||||
#include "igenericproposalmodel.h"
|
||||
#include "iassistproposalitem.h"
|
||||
#include "genericproposal.h"
|
||||
#include "codeassistant.h"
|
||||
|
||||
#include <texteditor/texteditorsettings.h>
|
||||
#include <texteditor/completionsettings.h>
|
||||
|
||||
#include <utils/faketooltip.h>
|
||||
|
||||
#include <QtCore/QRect>
|
||||
#include <QtCore/QLatin1String>
|
||||
#include <QtCore/QAbstractListModel>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QListView>
|
||||
#include <QtGui/QAbstractItemView>
|
||||
#include <QtGui/QScrollBar>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <QtGui/QLabel>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
// ------------
|
||||
// ModelAdapter
|
||||
// ------------
|
||||
class ModelAdapter : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ModelAdapter(IGenericProposalModel *completionModel, QWidget *parent);
|
||||
|
||||
virtual int rowCount(const QModelIndex &) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
private:
|
||||
IGenericProposalModel *m_completionModel;
|
||||
};
|
||||
|
||||
ModelAdapter::ModelAdapter(IGenericProposalModel *completionModel, QWidget *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_completionModel(completionModel)
|
||||
{}
|
||||
|
||||
int ModelAdapter::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_completionModel->size();
|
||||
}
|
||||
|
||||
QVariant ModelAdapter::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() >= m_completionModel->size())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return m_completionModel->text(index.row());
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
return m_completionModel->icon(index.row());
|
||||
} else if (role == Qt::WhatsThisRole) {
|
||||
return m_completionModel->detail(index.row());
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// GenericProposalInfoFrame
|
||||
// ------------------------
|
||||
class GenericProposalInfoFrame : public Utils::FakeToolTip
|
||||
{
|
||||
public:
|
||||
GenericProposalInfoFrame(QWidget *parent = 0)
|
||||
: Utils::FakeToolTip(parent), m_label(new QLabel(this))
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_label);
|
||||
|
||||
m_label->setForegroundRole(QPalette::ToolTipText);
|
||||
m_label->setBackgroundRole(QPalette::ToolTipBase);
|
||||
}
|
||||
|
||||
void setText(const QString &text)
|
||||
{
|
||||
m_label->setText(text);
|
||||
}
|
||||
|
||||
private:
|
||||
QLabel *m_label;
|
||||
};
|
||||
|
||||
// -----------------------
|
||||
// GenericProposalListView
|
||||
// -----------------------
|
||||
class GenericProposalListView : public QListView
|
||||
{
|
||||
public:
|
||||
GenericProposalListView(QWidget *parent) : QListView(parent) {}
|
||||
|
||||
QSize calculateSize() const;
|
||||
QPoint infoFramePos() const;
|
||||
|
||||
int rowSelected() const { return currentIndex().row(); }
|
||||
bool isFirstRowSelected() const { return rowSelected() == 0; }
|
||||
bool isLastRowSelected() const { return rowSelected() == model()->rowCount() - 1; }
|
||||
void selectRow(int row) { setCurrentIndex(model()->index(row, 0)); }
|
||||
void selectFirstRow() { selectRow(0); }
|
||||
void selectLastRow() { selectRow(model()->rowCount() - 1); }
|
||||
};
|
||||
|
||||
QSize GenericProposalListView::calculateSize() const
|
||||
{
|
||||
static const int maxVisibleItems = 10;
|
||||
|
||||
// Determine size by calculating the space of the visible items
|
||||
int visibleItems = model()->rowCount();
|
||||
if (visibleItems > maxVisibleItems)
|
||||
visibleItems = maxVisibleItems;
|
||||
|
||||
const QStyleOptionViewItem &option = viewOptions();
|
||||
QSize shint;
|
||||
for (int i = 0; i < visibleItems; ++i) {
|
||||
QSize tmp = itemDelegate()->sizeHint(option, model()->index(i, 0));
|
||||
if (shint.width() < tmp.width())
|
||||
shint = tmp;
|
||||
}
|
||||
shint.rheight() *= visibleItems;
|
||||
|
||||
return shint;
|
||||
}
|
||||
|
||||
QPoint GenericProposalListView::infoFramePos() const
|
||||
{
|
||||
const QRect &r = rectForIndex(currentIndex());
|
||||
QPoint p((parentWidget()->mapToGlobal(
|
||||
parentWidget()->rect().topRight())).x() + 3,
|
||||
mapToGlobal(r.topRight()).y() - verticalOffset()
|
||||
);
|
||||
return p;
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// GenericProposalWidgetPrivate
|
||||
// ----------------------------
|
||||
class GenericProposalWidgetPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GenericProposalWidgetPrivate(QWidget *completionWidget);
|
||||
|
||||
const QWidget *m_underlyingWidget;
|
||||
GenericProposalListView *m_completionListView;
|
||||
IGenericProposalModel *m_model;
|
||||
QRect m_displayRect;
|
||||
bool m_isSynchronized;
|
||||
bool m_explicitlySelected;
|
||||
AssistReason m_reason;
|
||||
bool m_gotContent;
|
||||
QPointer<GenericProposalInfoFrame> m_infoFrame;
|
||||
QTimer m_infoTimer;
|
||||
CodeAssistant *m_assistant;
|
||||
|
||||
public slots:
|
||||
void handleActivation(const QModelIndex &modelIndex);
|
||||
void maybeShowInfoTip();
|
||||
};
|
||||
|
||||
GenericProposalWidgetPrivate::GenericProposalWidgetPrivate(QWidget *completionWidget)
|
||||
: m_underlyingWidget(0)
|
||||
, m_completionListView(new GenericProposalListView(completionWidget))
|
||||
, m_model(0)
|
||||
, m_isSynchronized(true)
|
||||
, m_explicitlySelected(false)
|
||||
, m_gotContent(false)
|
||||
, m_assistant(0)
|
||||
{
|
||||
connect(m_completionListView, SIGNAL(activated(QModelIndex)),
|
||||
this, SLOT(handleActivation(QModelIndex)));
|
||||
|
||||
m_infoTimer.setInterval(1000);
|
||||
m_infoTimer.setSingleShot(true);
|
||||
connect(&m_infoTimer, SIGNAL(timeout()), SLOT(maybeShowInfoTip()));
|
||||
}
|
||||
|
||||
void GenericProposalWidgetPrivate::handleActivation(const QModelIndex &modelIndex)
|
||||
{
|
||||
static_cast<GenericProposalWidget *>
|
||||
(m_completionListView->parent())->notifyActivation(modelIndex.row());
|
||||
}
|
||||
|
||||
void GenericProposalWidgetPrivate::maybeShowInfoTip()
|
||||
{
|
||||
const QModelIndex ¤t = m_completionListView->currentIndex();
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
const QString &infoTip = current.data(Qt::WhatsThisRole).toString();
|
||||
if (infoTip.isEmpty()) {
|
||||
delete m_infoFrame.data();
|
||||
m_infoTimer.setInterval(200);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_infoFrame.isNull())
|
||||
m_infoFrame = new GenericProposalInfoFrame(m_completionListView);
|
||||
|
||||
m_infoFrame->move(m_completionListView->infoFramePos());
|
||||
m_infoFrame->setText(infoTip);
|
||||
m_infoFrame->adjustSize();
|
||||
m_infoFrame->show();
|
||||
m_infoFrame->raise();
|
||||
|
||||
m_infoTimer.setInterval(0);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// GenericProposalWidget
|
||||
// ------------------------
|
||||
GenericProposalWidget::GenericProposalWidget()
|
||||
: m_d(new GenericProposalWidgetPrivate(this))
|
||||
{
|
||||
#ifdef Q_WS_MAC
|
||||
if (m_d->m_completionListView->horizontalScrollBar())
|
||||
m_d->m_completionListView->horizontalScrollBar()->setAttribute(Qt::WA_MacMiniSize);
|
||||
if (m_d->m_completionListView->verticalScrollBar())
|
||||
m_d->m_completionListView->verticalScrollBar()->setAttribute(Qt::WA_MacMiniSize);
|
||||
#else
|
||||
// This improves the look with QGTKStyle.
|
||||
setFrameStyle(m_d->m_completionListView->frameStyle());
|
||||
#endif
|
||||
m_d->m_completionListView->setFrameStyle(QFrame::NoFrame);
|
||||
m_d->m_completionListView->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
m_d->m_completionListView->setUniformItemSizes(true);
|
||||
m_d->m_completionListView->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
m_d->m_completionListView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_d->m_completionListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_d->m_completionListView->setMinimumSize(1, 1);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(m_d->m_completionListView);
|
||||
|
||||
m_d->m_completionListView->installEventFilter(this);
|
||||
|
||||
setObjectName(QLatin1String("m_popupFrame"));
|
||||
setMinimumSize(1, 1);
|
||||
}
|
||||
|
||||
GenericProposalWidget::~GenericProposalWidget()
|
||||
{
|
||||
delete m_d->m_model;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::setAssistant(CodeAssistant *assistant)
|
||||
{
|
||||
m_d->m_assistant = assistant;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::setReason(AssistReason reason)
|
||||
{
|
||||
m_d->m_reason = reason;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::setUnderlyingWidget(const QWidget *underlyingWidget)
|
||||
{
|
||||
setFont(underlyingWidget->font());
|
||||
m_d->m_underlyingWidget = underlyingWidget;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::setModel(IAssistProposalModel *model)
|
||||
{
|
||||
delete m_d->m_model;
|
||||
m_d->m_model = static_cast<IGenericProposalModel *>(model);
|
||||
m_d->m_completionListView->setModel(new ModelAdapter(m_d->m_model, m_d->m_completionListView));
|
||||
|
||||
connect(m_d->m_completionListView->selectionModel(),
|
||||
SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||
&m_d->m_infoTimer,
|
||||
SLOT(start()));
|
||||
}
|
||||
|
||||
void GenericProposalWidget::setDisplayRect(const QRect &rect)
|
||||
{
|
||||
m_d->m_displayRect = rect;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::setIsSynchronized(bool isSync)
|
||||
{
|
||||
m_d->m_isSynchronized = isSync;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::showProposal(const QString &prefix)
|
||||
{
|
||||
ensurePolished();
|
||||
if (m_d->m_isSynchronized && !prefix.isEmpty())
|
||||
m_d->m_gotContent = true;
|
||||
m_d->m_model->removeDuplicates();
|
||||
if (!updateAndCheck(prefix))
|
||||
return;
|
||||
show();
|
||||
m_d->m_completionListView->setFocus();
|
||||
}
|
||||
|
||||
void GenericProposalWidget::updateProposal(const QString &prefix)
|
||||
{
|
||||
if (!isVisible())
|
||||
return;
|
||||
updateAndCheck(prefix);
|
||||
}
|
||||
|
||||
void GenericProposalWidget::closeProposal()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void GenericProposalWidget::notifyActivation(int index)
|
||||
{
|
||||
abort();
|
||||
emit proposalItemActivated(m_d->m_model->proposalItem(index));
|
||||
}
|
||||
|
||||
void GenericProposalWidget::abort()
|
||||
{
|
||||
if (isVisible())
|
||||
close();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
bool GenericProposalWidget::updateAndCheck(const QString &prefix)
|
||||
{
|
||||
// Keep track in the case there has been an explicit selection.
|
||||
int preferredItemId = -1;
|
||||
if (m_d->m_explicitlySelected)
|
||||
preferredItemId =
|
||||
m_d->m_model->persistentId(m_d->m_completionListView->currentIndex().row());
|
||||
|
||||
// Filter, sort, etc.
|
||||
m_d->m_model->reset();
|
||||
if (!prefix.isEmpty())
|
||||
m_d->m_model->filter(prefix);
|
||||
if (m_d->m_model->size() == 0
|
||||
|| (m_d->m_model->size() == 1 && prefix == m_d->m_model->proposalPrefix())) {
|
||||
abort();
|
||||
return false;
|
||||
}
|
||||
if (m_d->m_model->isSortable())
|
||||
m_d->m_model->sort();
|
||||
m_d->m_completionListView->reset();
|
||||
|
||||
// Try to find the previosly explicit selection (if any). If we can find the item set it
|
||||
// as the current. Otherwise (it might have been filtered out) select the first row.
|
||||
if (m_d->m_explicitlySelected) {
|
||||
Q_ASSERT(preferredItemId != -1);
|
||||
for (int i = 0; i < m_d->m_model->size(); ++i) {
|
||||
if (m_d->m_model->persistentId(i) == preferredItemId) {
|
||||
m_d->m_completionListView->selectRow(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_d->m_completionListView->currentIndex().isValid()) {
|
||||
m_d->m_completionListView->selectFirstRow();
|
||||
if (m_d->m_explicitlySelected)
|
||||
m_d->m_explicitlySelected = false;
|
||||
}
|
||||
|
||||
if (TextEditorSettings::instance()->completionSettings().m_partiallyComplete
|
||||
&& m_d->m_reason == ExplicitlyInvoked
|
||||
&& m_d->m_gotContent) {
|
||||
if (m_d->m_model->size() == 1) {
|
||||
IAssistProposalItem *item = m_d->m_model->proposalItem(0);
|
||||
if (item->implicitlyApplies()) {
|
||||
abort();
|
||||
emit proposalItemActivated(item);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (m_d->m_model->supportsPrefixExpansion()) {
|
||||
const QString &proposalPrefix = m_d->m_model->proposalPrefix();
|
||||
if (proposalPrefix.length() > prefix.length())
|
||||
emit prefixExpanded(proposalPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
updatePositionAndSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GenericProposalWidget::updatePositionAndSize()
|
||||
{
|
||||
const QSize &shint = m_d->m_completionListView->calculateSize();
|
||||
const int fw = frameWidth();
|
||||
const int width = shint.width() + fw * 2 + 30;
|
||||
const int height = shint.height() + fw * 2;
|
||||
|
||||
// Determine the position, keeping the popup on the screen
|
||||
const QDesktopWidget *desktop = QApplication::desktop();
|
||||
#ifdef Q_WS_MAC
|
||||
const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_d->m_underlyingWidget));
|
||||
#else
|
||||
const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_d->m_underlyingWidget));
|
||||
#endif
|
||||
|
||||
QPoint pos = m_d->m_displayRect.bottomLeft();
|
||||
pos.rx() -= 16 + fw; // Space for the icons
|
||||
if (pos.y() + height > screen.bottom())
|
||||
pos.setY(m_d->m_displayRect.top() - height);
|
||||
if (pos.x() + width > screen.right())
|
||||
pos.setX(screen.right() - width);
|
||||
setGeometry(pos.x(), pos.y(), width, height);
|
||||
}
|
||||
|
||||
bool GenericProposalWidget::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::FocusOut) {
|
||||
abort();
|
||||
#if defined(Q_OS_DARWIN) && ! defined(QT_MAC_USE_COCOA)
|
||||
QFocusEvent *fe = static_cast<QFocusEvent *>(e);
|
||||
if (fe->reason() == Qt::OtherFocusReason) {
|
||||
// Qt/carbon workaround
|
||||
// focus out is received before the key press event.
|
||||
if (m_d->m_completionListView->currentIndex().isValid())
|
||||
emit proposalItemActivated(m_d->m_model->proposalItem(
|
||||
m_d->m_completionListView->currentIndex().row()));
|
||||
}
|
||||
#endif
|
||||
if (m_d->m_infoFrame)
|
||||
m_d->m_infoFrame->close();
|
||||
return true;
|
||||
} else if (e->type() == QEvent::ShortcutOverride) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
|
||||
switch (ke->key()) {
|
||||
case Qt::Key_N:
|
||||
case Qt::Key_P:
|
||||
if (ke->modifiers() == Qt::ControlModifier) {
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (e->type() == QEvent::KeyPress) {
|
||||
m_d->m_gotContent = false;
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
|
||||
switch (ke->key()) {
|
||||
case Qt::Key_Escape:
|
||||
abort();
|
||||
return true;
|
||||
|
||||
case Qt::Key_N:
|
||||
case Qt::Key_P:
|
||||
// select next/previous completion
|
||||
m_d->m_explicitlySelected = true;
|
||||
if (ke->modifiers() == Qt::ControlModifier) {
|
||||
int change = (ke->key() == Qt::Key_N) ? 1 : -1;
|
||||
int nrows = m_d->m_model->size();
|
||||
int row = m_d->m_completionListView->currentIndex().row();
|
||||
int newRow = (row + change + nrows) % nrows;
|
||||
if (newRow == row + change || !ke->isAutoRepeat())
|
||||
m_d->m_completionListView->selectRow(newRow);
|
||||
return true;
|
||||
}
|
||||
m_d->m_gotContent = true;
|
||||
break;
|
||||
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Return:
|
||||
#if defined(QT_MAC_USE_COCOA) || !defined(Q_OS_DARWIN)
|
||||
abort();
|
||||
if (m_d->m_completionListView->currentIndex().isValid())
|
||||
emit proposalItemActivated(m_d->m_model->proposalItem(
|
||||
m_d->m_completionListView->currentIndex().row()));
|
||||
#endif
|
||||
return true;
|
||||
|
||||
case Qt::Key_Up:
|
||||
m_d->m_explicitlySelected = true;
|
||||
if (!ke->isAutoRepeat() && m_d->m_completionListView->isFirstRowSelected()) {
|
||||
m_d->m_completionListView->selectLastRow();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case Qt::Key_Down:
|
||||
m_d->m_explicitlySelected = true;
|
||||
if (!ke->isAutoRepeat() && m_d->m_completionListView->isLastRowSelected()) {
|
||||
m_d->m_completionListView->selectFirstRow();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_PageDown:
|
||||
case Qt::Key_PageUp:
|
||||
return false;
|
||||
|
||||
case Qt::Key_Right:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Home:
|
||||
case Qt::Key_End:
|
||||
case Qt::Key_Backspace:
|
||||
// We want these navigation keys to work in the editor.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Only forward keys that insert text and refine the completion.
|
||||
if (ke->text().isEmpty())
|
||||
return true;
|
||||
m_d->m_gotContent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ke->text().length() == 1
|
||||
&& m_d->m_completionListView->currentIndex().isValid()
|
||||
&& qApp->focusWidget() == o) {
|
||||
const QChar &typedChar = ke->text().at(0);
|
||||
IAssistProposalItem *item =
|
||||
m_d->m_model->proposalItem(m_d->m_completionListView->currentIndex().row());
|
||||
if (item->prematurelyApplies(typedChar)) {
|
||||
abort();
|
||||
emit proposalItemActivated(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QApplication::sendEvent(const_cast<QWidget *>(m_d->m_underlyingWidget), e);
|
||||
if (isVisible())
|
||||
m_d->m_assistant->notifyChange();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "genericproposalwidget.moc"
|
||||
|
||||
} // TextEditor
|
||||
@@ -0,0 +1,79 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GENERICPROPOSALWIDGET_H
|
||||
#define GENERICPROPOSALWIDGET_H
|
||||
|
||||
#include "iassistproposalwidget.h"
|
||||
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class GenericProposalWidgetPrivate;
|
||||
|
||||
class GenericProposalWidget : public IAssistProposalWidget
|
||||
{
|
||||
friend class GenericProposalWidgetPrivate;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GenericProposalWidget();
|
||||
virtual ~GenericProposalWidget();
|
||||
|
||||
virtual void setAssistant(CodeAssistant *assistant);
|
||||
virtual void setReason(AssistReason reason);
|
||||
virtual void setUnderlyingWidget(const QWidget *underlyingWidget);
|
||||
virtual void setModel(IAssistProposalModel *model);
|
||||
virtual void setDisplayRect(const QRect &rect);
|
||||
virtual void setIsSynchronized(bool isSync);
|
||||
|
||||
virtual void showProposal(const QString &prefix);
|
||||
virtual void updateProposal(const QString &prefix);
|
||||
virtual void closeProposal();
|
||||
|
||||
private:
|
||||
bool updateAndCheck(const QString &prefix);
|
||||
void updatePositionAndSize();
|
||||
void notifyActivation(int index);
|
||||
void abort();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *o, QEvent *e);
|
||||
|
||||
private:
|
||||
QScopedPointer<GenericProposalWidgetPrivate> m_d;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // GENERICPROPOSALWIDGET_H
|
||||
@@ -0,0 +1,100 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistinterface.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistInterface
|
||||
\brief The IAssistInterface is an interface for providing access to the document from which
|
||||
a proposal is computed.
|
||||
|
||||
This interface existis in order to avoid a direct dependency on the text editor. This is
|
||||
particularly important and safer for asynchronous providers, since in such cases computation
|
||||
of the proposal is not done in the GUI thread.
|
||||
|
||||
In general this API tries to be as decoupled as possible from the base text editor.
|
||||
This is in order to make the design a bit more generic and allow code assist to be
|
||||
pluggable into different types of documents (there are still issues to be treated).
|
||||
|
||||
\sa IAssistProposal, IAssistProvider, IAssistProcessor
|
||||
*/
|
||||
|
||||
IAssistInterface::IAssistInterface()
|
||||
{}
|
||||
|
||||
IAssistInterface::~IAssistInterface()
|
||||
{}
|
||||
|
||||
/*!
|
||||
\fn int position() const
|
||||
|
||||
Returns the cursor position.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QChar characterAt(int position) const
|
||||
|
||||
Returns the character at \a position.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QString textAt(int position, int length) const
|
||||
|
||||
Returns the text at \a position with the given \a length.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn const Core::IFile *file() const
|
||||
|
||||
Returns the file associated.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QTextDocument *document() const
|
||||
Returns the document.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void detach(QThread *destination)
|
||||
|
||||
Detaches the interface. If it is necessary to take any special care in order to allow
|
||||
this interface to be run in a separate thread \a destination this needs to be done
|
||||
in this method.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn AssistReason reason() const
|
||||
|
||||
The reason which triggered the assist.
|
||||
*/
|
||||
@@ -0,0 +1,70 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IASSISTINTERFACE_H
|
||||
#define IASSISTINTERFACE_H
|
||||
|
||||
#include "assistenums.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTextDocument;
|
||||
class QThread;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Core {
|
||||
class IFile;
|
||||
}
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class TEXTEDITOR_EXPORT IAssistInterface
|
||||
{
|
||||
public:
|
||||
IAssistInterface();
|
||||
virtual ~IAssistInterface();
|
||||
|
||||
virtual int position() const = 0;
|
||||
virtual QChar characterAt(int position) const = 0;
|
||||
virtual QString textAt(int position, int length) const = 0;
|
||||
virtual const Core::IFile *file() const = 0;
|
||||
virtual QTextDocument *document() const = 0;
|
||||
virtual void detach(QThread *destination) = 0;
|
||||
virtual AssistReason reason() const = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTINTERFACE_H
|
||||
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistprocessor.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistProcessor
|
||||
\brief The IAssistProcessor is an interface that actually computes an assist proposal.
|
||||
|
||||
\sa IAssistProposal, IAssistProvider
|
||||
*/
|
||||
|
||||
IAssistProcessor::IAssistProcessor()
|
||||
{}
|
||||
|
||||
IAssistProcessor::~IAssistProcessor()
|
||||
{}
|
||||
|
||||
/*!
|
||||
\fn IAssistProposal *perform(const IAssistInterface *interface)
|
||||
|
||||
Computes a proposal and returns it. Access to the document is made through the \a interface.
|
||||
If this is an asynchronous processor the \a interface will be detached.
|
||||
|
||||
The processor takes ownership of the interface. Also, one should be careful in the case of
|
||||
sharing data across asynchronous processors since there might be more than one instance of
|
||||
them computing a proposal at a particular time.
|
||||
|
||||
\sa IAssistInterface::detach()
|
||||
*/
|
||||
@@ -0,0 +1,57 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IASSISTPROCESSOR_H
|
||||
#define IASSISTPROCESSOR_H
|
||||
|
||||
#include "iassistproposalwidget.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class IAssistProvider;
|
||||
class IAssistInterface;
|
||||
class IAssistProposal;
|
||||
|
||||
class TEXTEDITOR_EXPORT IAssistProcessor
|
||||
{
|
||||
public:
|
||||
IAssistProcessor();
|
||||
virtual ~IAssistProcessor();
|
||||
|
||||
virtual IAssistProposal *perform(const IAssistInterface *interface) = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTPROCESSOR_H
|
||||
@@ -0,0 +1,102 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistproposal.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistProposal
|
||||
\brief The IAssistProposal is an interface for representing an assist proposal.
|
||||
|
||||
Known implenters of this interface are FunctionHintProposal and GenericProposal. The
|
||||
former is recommended to be used when assisting function call constructs (overloads
|
||||
and parameters) while the latter is quite generic so that it could be used to propose
|
||||
snippets, refactoring operations (quickfixes), and contextual content (the member of
|
||||
class or a string existent in the document, for example).
|
||||
|
||||
\sa IAssistProposalWidget, IAssistModel
|
||||
*/
|
||||
|
||||
IAssistProposal::IAssistProposal()
|
||||
{}
|
||||
|
||||
IAssistProposal::~IAssistProposal()
|
||||
{}
|
||||
|
||||
/*!
|
||||
\fn bool isFragile() const
|
||||
|
||||
Returns whether this is a fragile proposal. When a proposal is fragile it means that
|
||||
it will be replaced by a new proposal in the case one is created, even if due to an
|
||||
idle editor.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn int basePosition() const
|
||||
|
||||
Returns the position from which this proposal starts.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool isCorrective() const
|
||||
|
||||
Returns whether this proposal is also corrective. This could happen in C++, for example,
|
||||
when a dot operator (.) needs to be replaced by an arrow operator (->) before the proposal
|
||||
is displayed.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void makeCorrection(BaseTextEditor *editor)
|
||||
|
||||
This allows a correction to be made in the case this is a corrective proposal.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn IAssistModel *model() const
|
||||
|
||||
Returns the model associated with this proposal.
|
||||
|
||||
Although the IAssistModel from this proposal may be used on its own, it needs to be
|
||||
consistent with the widget returned by createWidget().
|
||||
|
||||
\sa createWidget()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn IAssistProposalWidget *createWidget() const
|
||||
|
||||
Returns the widget associated with this proposal. The IAssistProposalWidget implementor
|
||||
recommended for function hint proposals is FunctionHintProposalWidget. For snippets,
|
||||
refactoring operations (quickfixes), and contextual content the recommeded implementor
|
||||
is GenericProposalWidget.
|
||||
*/
|
||||
@@ -0,0 +1,60 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IASSISTPROPOSAL_H
|
||||
#define IASSISTPROPOSAL_H
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class IAssistProposalModel;
|
||||
class IAssistProposalWidget;
|
||||
class BaseTextEditor;
|
||||
|
||||
class TEXTEDITOR_EXPORT IAssistProposal
|
||||
{
|
||||
public:
|
||||
IAssistProposal();
|
||||
virtual ~IAssistProposal();
|
||||
|
||||
virtual bool isFragile() const = 0;
|
||||
virtual int basePosition() const = 0;
|
||||
virtual bool isCorrective() const = 0;
|
||||
virtual void makeCorrection(BaseTextEditor *editor) = 0;
|
||||
virtual IAssistProposalModel *model() const = 0;
|
||||
virtual IAssistProposalWidget *createWidget() const = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTPROPOSAL_H
|
||||
@@ -0,0 +1,65 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistproposalitem.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistProposalItem
|
||||
\brief The IAssistProposalItem is an interface for representing an assist proposal item.
|
||||
*/
|
||||
|
||||
IAssistProposalItem::IAssistProposalItem()
|
||||
{}
|
||||
|
||||
IAssistProposalItem::~IAssistProposalItem()
|
||||
{}
|
||||
|
||||
/*!
|
||||
\fn bool implicitlyApplies() const
|
||||
|
||||
Returns whether this item should implicitly apply in the case it is the only proposal
|
||||
item available.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool prematurelyApplies(const QChar &c) const
|
||||
|
||||
Returns whether the character \a c causes this item to be applied.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void apply(BaseTextEditor *editor, int basePosition) const
|
||||
|
||||
This is the place to implement the actual application of the item.
|
||||
*/
|
||||
@@ -0,0 +1,59 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IASSISTPROPOSALITEM_H
|
||||
#define IASSISTPROPOSALITEM_H
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QChar;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class BaseTextEditor;
|
||||
|
||||
class TEXTEDITOR_EXPORT IAssistProposalItem
|
||||
{
|
||||
public:
|
||||
IAssistProposalItem();
|
||||
virtual ~IAssistProposalItem();
|
||||
|
||||
virtual bool implicitlyApplies() const = 0;
|
||||
virtual bool prematurelyApplies(const QChar &c) const = 0;
|
||||
virtual void apply(BaseTextEditor *editor, int basePosition) const = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTPROPOSALITEM_H
|
||||
@@ -0,0 +1,52 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistproposalmodel.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistProposalModel
|
||||
\brief The IAssistProposalModel is an interface for representing proposals.
|
||||
|
||||
Known implenters of this interface are IFunctionHintProposalModel and IGenericProposalModel.
|
||||
The former is recommeded to be used when assisting function calls constructs (overloads
|
||||
and parameters) while the latter is quite generic so that it could be used to propose
|
||||
snippets, refactoring operations (quickfixes), and contextual content (the member of class
|
||||
or a string existent in the document, for example).
|
||||
*/
|
||||
|
||||
IAssistProposalModel::IAssistProposalModel()
|
||||
{}
|
||||
|
||||
IAssistProposalModel::~IAssistProposalModel()
|
||||
{}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IASSISTMODEL_H
|
||||
#define IASSISTMODEL_H
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class IAssistProposalItem;
|
||||
|
||||
class TEXTEDITOR_EXPORT IAssistProposalModel
|
||||
{
|
||||
public:
|
||||
IAssistProposalModel();
|
||||
virtual ~IAssistProposalModel();
|
||||
|
||||
virtual void reset() = 0;
|
||||
virtual int size() const = 0;
|
||||
virtual QString text(int index) const = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTMODEL_H
|
||||
@@ -0,0 +1,142 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistproposalwidget.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistProposalWidget
|
||||
\brief The IAssistProposalWidget is an interface for widgets that display assist proposals.
|
||||
|
||||
Known implenters of this interface are FunctionHintProposalWidget and GenericProposalWidget.
|
||||
The former is recommeded to be used when assisting function calls constructs (overloads
|
||||
and parameters) while the latter is quite generic so that it could be used to propose
|
||||
snippets, refactoring operations (quickfixes), and contextual content (the member of class
|
||||
or a string existent in the document, for example).
|
||||
|
||||
In general this API tries to be as decoupled as possible from the base text editor.
|
||||
This is in order to make the design a bit more generic and allow code assist to be
|
||||
pluggable into different types of documents (there are still issues to be treated).
|
||||
|
||||
\sa IAssistProposal
|
||||
*/
|
||||
|
||||
IAssistProposalWidget::IAssistProposalWidget()
|
||||
: QFrame(0, Qt::Popup)
|
||||
{}
|
||||
|
||||
IAssistProposalWidget::~IAssistProposalWidget()
|
||||
{}
|
||||
|
||||
/*!
|
||||
\fn void setAssistant(CodeAssistant *assistant)
|
||||
|
||||
Sets the code assistant which is the owner of this widget. This is used so that the code
|
||||
assistant can be notified when changes on the underlying widget happen.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void setReason(AssistReason reason)
|
||||
|
||||
Sets the reason which triggered the assist.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void setUnderlyingWidget(const QWidget *underlyingWidget)
|
||||
|
||||
Sets the underlying widget upon which this proposal operates.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void setModel(IAssistModel *model)
|
||||
|
||||
Sets the model.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void setDisplayRect(const QRect &rect)
|
||||
|
||||
Sets the \a rect on which this widget should be displayed.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void showProposal(const QString &prefix)
|
||||
|
||||
Shows the proposal. The \a prefix is the string comprised from the character at the base
|
||||
position of the proposal until the character immediately after the cursor at the moment
|
||||
the proposal is displayed.
|
||||
|
||||
\sa IAssistProposal::basePosition()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual void updateProposal(const QString &prefix)
|
||||
|
||||
Updates the proposal base on the give \a prefix.
|
||||
|
||||
\sa showProposal()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void closeProposal()
|
||||
|
||||
Closes the proposal.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void setIsSynchronized(bool isSync)
|
||||
|
||||
Sets whether this widget is synchronized. If a widget is synchronized it means that from
|
||||
the moment a proposal started being computed until the moment it is actually displayed,
|
||||
there was no content input into the underlying widget.
|
||||
|
||||
A widget is not synchronized in the case a proposal is computed in a separate thread and
|
||||
in the meanwhile (while it is still being processed) content is input into the underlying
|
||||
widget.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void prefixExpanded(const QString &newPrefix)
|
||||
|
||||
The signal is emitted whenever this widget automatically expands the prefix of the proposal.
|
||||
This can happen if all available proposal items share the same prefix and if the proposal's
|
||||
model supports prefix expansion.
|
||||
|
||||
\sa IGenericProposalModel::supportsPrefixExpansion()
|
||||
*/
|
||||
|
||||
/*!
|
||||
void proposalItemActivated(IAssistProposalItem *proposalItem)
|
||||
|
||||
This signal is emitted whenever \a proposalItem is chosen to be applied.
|
||||
*/
|
||||
@@ -0,0 +1,74 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IASSISTPROPOSALWIDGET_H
|
||||
#define IASSISTPROPOSALWIDGET_H
|
||||
|
||||
#include "assistenums.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtGui/QFrame>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class CodeAssistant;
|
||||
class IAssistProposalModel;
|
||||
class IAssistProposalItem;
|
||||
|
||||
class TEXTEDITOR_EXPORT IAssistProposalWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IAssistProposalWidget();
|
||||
virtual ~IAssistProposalWidget();
|
||||
|
||||
virtual void setAssistant(CodeAssistant *assistant) = 0;
|
||||
virtual void setReason(AssistReason reason) = 0;
|
||||
virtual void setUnderlyingWidget(const QWidget *underlyingWidget) = 0;
|
||||
virtual void setModel(IAssistProposalModel *model) = 0;
|
||||
virtual void setDisplayRect(const QRect &rect) = 0;
|
||||
virtual void setIsSynchronized(bool isSync) = 0;
|
||||
|
||||
virtual void showProposal(const QString &prefix) = 0;
|
||||
virtual void updateProposal(const QString &prefix) = 0;
|
||||
virtual void closeProposal() = 0;
|
||||
|
||||
signals:
|
||||
void prefixExpanded(const QString &newPrefix);
|
||||
void proposalItemActivated(IAssistProposalItem *proposalItem);
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTPROPOSALWIDGET_H
|
||||
@@ -0,0 +1,68 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "iassistprovider.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
/*!
|
||||
\class IAssistProvider
|
||||
\brief The IAssistProvider is an interface for providing code assist.
|
||||
|
||||
There might be different kinds of assist such as completions or refactoring
|
||||
actions (quickfixes).
|
||||
|
||||
Within this API the term completion denotes any kind of information prompted
|
||||
to the user in order to auxiliate her to "complete" a particular code construction.
|
||||
Examples of completions currently supported are snippets, function hints, and
|
||||
contextual contents.
|
||||
|
||||
\sa IAssistProposal, IAssistProcessor
|
||||
*/
|
||||
|
||||
IAssistProvider::IAssistProvider()
|
||||
{}
|
||||
|
||||
IAssistProvider::~IAssistProvider()
|
||||
{}
|
||||
|
||||
/*!
|
||||
\fn bool supportsEditor(const QString &editorId) const
|
||||
|
||||
Returns whether this provider supports the editor which has the give \a editorId.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn IAssistProcessor *createProcessor() const
|
||||
|
||||
Creates and returns the IAssistProcessor responsible for computing an IAssistProposal.
|
||||
*/
|
||||
+10
-25
@@ -30,44 +30,29 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef COMPLETIONSUPPORT_H
|
||||
#define COMPLETIONSUPPORT_H
|
||||
#ifndef IASSISTPROVIDER_H
|
||||
#define IASSISTPROVIDER_H
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
#include <texteditor/icompletioncollector.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class ITextEditor;
|
||||
class CompletionSupportPrivate;
|
||||
class IAssistProcessor;
|
||||
|
||||
/* Completion support is responsible for querying the list of completion collectors
|
||||
and popping up the CompletionWidget with the available completions.
|
||||
*/
|
||||
class TEXTEDITOR_EXPORT CompletionSupport : public QObject
|
||||
class TEXTEDITOR_EXPORT IAssistProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~CompletionSupport();
|
||||
IAssistProvider();
|
||||
virtual ~IAssistProvider();
|
||||
|
||||
static CompletionSupport *instance();
|
||||
|
||||
bool isActive() const;
|
||||
CompletionPolicy policy() const;
|
||||
|
||||
public slots:
|
||||
void complete(TextEditor::ITextEditor *editor,
|
||||
TextEditor::CompletionPolicy policy, bool forced);
|
||||
|
||||
private:
|
||||
CompletionSupport();
|
||||
QScopedPointer<CompletionSupportPrivate> d;
|
||||
virtual bool supportsEditor(const QString &editorId) const = 0;
|
||||
virtual IAssistProcessor *createProcessor() const = 0;
|
||||
};
|
||||
|
||||
} // namespace TextEditor
|
||||
|
||||
#endif // COMPLETIONSUPPORT_H
|
||||
} // TextEditor
|
||||
|
||||
#endif // IASSISTPROVIDER_H
|
||||
@@ -0,0 +1,41 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "ifunctionhintproposalmodel.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
IFunctionHintProposalModel::IFunctionHintProposalModel()
|
||||
{}
|
||||
|
||||
IFunctionHintProposalModel::~IFunctionHintProposalModel()
|
||||
{}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IFUNCTIONHINTPROPOSALMODEL_H
|
||||
#define IFUNCTIONHINTPROPOSALMODEL_H
|
||||
|
||||
#include "iassistproposalmodel.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class TEXTEDITOR_EXPORT IFunctionHintProposalModel : public IAssistProposalModel
|
||||
{
|
||||
public:
|
||||
IFunctionHintProposalModel();
|
||||
virtual ~IFunctionHintProposalModel();
|
||||
|
||||
virtual int activeArgument(const QString &prefix) const = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IFUNCTIONHINTPROPOSALMODEL_H
|
||||
@@ -0,0 +1,41 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "igenericproposalmodel.h"
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
IGenericProposalModel::IGenericProposalModel()
|
||||
{}
|
||||
|
||||
IGenericProposalModel::~IGenericProposalModel()
|
||||
{}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef IGENERICPROPOSALMODEL_H
|
||||
#define IGENERICPROPOSALMODEL_H
|
||||
|
||||
#include "iassistproposalmodel.h"
|
||||
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace TextEditor {
|
||||
|
||||
class IAssistProposalItem;
|
||||
|
||||
class TEXTEDITOR_EXPORT IGenericProposalModel : public IAssistProposalModel
|
||||
{
|
||||
public:
|
||||
IGenericProposalModel();
|
||||
virtual ~IGenericProposalModel();
|
||||
|
||||
virtual QIcon icon(int index) const = 0;
|
||||
virtual QString detail(int index) const = 0;
|
||||
virtual int persistentId(int index) const = 0;
|
||||
virtual void removeDuplicates() = 0;
|
||||
virtual void filter(const QString &prefix) = 0;
|
||||
virtual bool isSortable() const = 0;
|
||||
virtual void sort() = 0;
|
||||
virtual bool supportsPrefixExpansion() const = 0;
|
||||
virtual QString proposalPrefix() const = 0;
|
||||
virtual IAssistProposalItem *proposalItem(int index) const = 0;
|
||||
};
|
||||
|
||||
} // TextEditor
|
||||
|
||||
#endif // IGENERICPROPOSALMODEL_H
|
||||
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (info@qt.nokia.com)
|
||||
**
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "quickfixassistprocessor.h"
|
||||
#include "quickfixassistprovider.h"
|
||||
#include "iassistinterface.h"
|
||||
#include "basicproposalitemlistmodel.h"
|
||||
#include "basicproposalitem.h"
|
||||
#include "genericproposal.h"
|
||||
|
||||
// @TODO: Move...
|
||||
#include <texteditor/quickfix.h>
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
QuickFixAssistProcessor::QuickFixAssistProcessor()
|
||||
{}
|
||||
|
||||
QuickFixAssistProcessor::~QuickFixAssistProcessor()
|
||||
{}
|
||||
|
||||
IAssistProposal *QuickFixAssistProcessor::perform(const IAssistInterface *interface)
|
||||
{
|
||||
if (!interface)
|
||||
return 0;
|
||||
|
||||
QSharedPointer<const IAssistInterface> assistInterface(interface);
|
||||
|
||||
const QuickFixAssistProvider *quickFixProvider =
|
||||
static_cast<const QuickFixAssistProvider *>(provider());
|
||||
QMap<int, QList<QuickFixOperation::Ptr> > matchedOps;
|
||||
foreach (QuickFixFactory *factory, quickFixProvider->quickFixFactories()) {
|
||||
QList<QuickFixOperation::Ptr> ops = factory->matchingOperations(assistInterface);
|
||||
|
||||
foreach (QuickFixOperation::Ptr op, ops) {
|
||||
const int priority = op->priority();
|
||||
if (priority != -1)
|
||||
matchedOps[priority].append(op);
|
||||
}
|
||||
}
|
||||
|
||||
QList<QuickFixOperation::Ptr> quickFixes;
|
||||
QMapIterator<int, QList<QuickFixOperation::Ptr> > it(matchedOps);
|
||||
it.toBack();
|
||||
if (it.hasPrevious()) {
|
||||
it.previous();
|
||||
quickFixes = it.value();
|
||||
}
|
||||
|
||||
if (!quickFixes.isEmpty()) {
|
||||
QList<BasicProposalItem *> items;
|
||||
foreach (const QuickFixOperation::Ptr &op, quickFixes) {
|
||||
QVariant v;
|
||||
v.setValue(op);
|
||||
BasicProposalItem *item = new BasicProposalItem;
|
||||
item->setText(op->description());
|
||||
item->setData(v);
|
||||
items.append(item);
|
||||
}
|
||||
return new GenericProposal(interface->position(), new BasicProposalItemListModel(items));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user