forked from qt-creator/qt-creator
Initial work on better function argument widget
Done with Roberto Raggi.
This commit is contained in:
@@ -60,10 +60,11 @@
|
|||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
#include <QtGui/QAction>
|
#include <QtGui/QAction>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QtGui/QKeyEvent>
|
||||||
#include <QtGui/QLabel>
|
#include <QtGui/QLabel>
|
||||||
|
#include <QtGui/QToolButton>
|
||||||
#include <QtGui/QVBoxLayout>
|
#include <QtGui/QVBoxLayout>
|
||||||
#include <QtGui/QApplication>
|
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
@@ -72,26 +73,37 @@ namespace Internal {
|
|||||||
|
|
||||||
class FunctionArgumentWidget : public QLabel
|
class FunctionArgumentWidget : public QLabel
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FunctionArgumentWidget();
|
FunctionArgumentWidget();
|
||||||
void showFunctionHint(Function *functionSymbol, const LookupContext &context);
|
void showFunctionHint(QList<Function *> functionSymbols, const LookupContext &context);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *obj, QEvent *e);
|
bool eventFilter(QObject *obj, QEvent *e);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void nextPage();
|
||||||
|
void previousPage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update();
|
void update();
|
||||||
void close();
|
void close();
|
||||||
void updateHintText();
|
void updateHintText();
|
||||||
|
|
||||||
|
Function *currentFunction() const
|
||||||
|
{ return m_items.at(m_current); }
|
||||||
|
|
||||||
int m_startpos;
|
int m_startpos;
|
||||||
int m_currentarg;
|
int m_currentarg;
|
||||||
|
|
||||||
TextEditor::ITextEditor *m_editor;
|
TextEditor::ITextEditor *m_editor;
|
||||||
|
|
||||||
|
QWidget *m_pager;
|
||||||
QFrame *m_popupFrame;
|
QFrame *m_popupFrame;
|
||||||
Function *m_item;
|
QList<Function *> m_items;
|
||||||
LookupContext m_context;
|
LookupContext m_context;
|
||||||
|
int m_current;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConvertToCompletionItem: protected NameVisitor
|
class ConvertToCompletionItem: protected NameVisitor
|
||||||
@@ -180,57 +192,101 @@ protected:
|
|||||||
|
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools::Internal;
|
||||||
|
|
||||||
FunctionArgumentWidget::FunctionArgumentWidget()
|
FunctionArgumentWidget::FunctionArgumentWidget():
|
||||||
: m_item(0)
|
m_current(0)
|
||||||
{
|
{
|
||||||
QObject *editorObject = Core::EditorManager::instance()->currentEditor();
|
QObject *editorObject = Core::EditorManager::instance()->currentEditor();
|
||||||
m_editor = qobject_cast<TextEditor::ITextEditor *>(editorObject);
|
m_editor = qobject_cast<TextEditor::ITextEditor *>(editorObject);
|
||||||
|
|
||||||
m_popupFrame = new QFrame(0, Qt::ToolTip | Qt::WindowStaysOnTopHint);
|
m_popupFrame = new QFrame(m_editor->widget(), Qt::ToolTip | Qt::WindowStaysOnTopHint);
|
||||||
m_popupFrame->setFocusPolicy(Qt::NoFocus);
|
m_popupFrame->setFocusPolicy(Qt::NoFocus);
|
||||||
m_popupFrame->setAttribute(Qt::WA_DeleteOnClose);
|
m_popupFrame->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
setFrameStyle(QFrame::Box);
|
QToolButton *leftArrow = new QToolButton;
|
||||||
setFrameShadow(QFrame::Plain);
|
leftArrow->setArrowType(Qt::LeftArrow);
|
||||||
|
leftArrow->setFixedSize(16, 16);
|
||||||
|
leftArrow->setAutoRaise(true);
|
||||||
|
|
||||||
|
QToolButton *rightArrow = new QToolButton;
|
||||||
|
rightArrow->setArrowType(Qt::RightArrow);
|
||||||
|
rightArrow->setFixedSize(16, 16);
|
||||||
|
rightArrow->setAutoRaise(true);
|
||||||
|
|
||||||
|
m_popupFrame->setFrameStyle(QFrame::Box);
|
||||||
|
m_popupFrame->setFrameShadow(QFrame::Plain);
|
||||||
|
|
||||||
setParent(m_popupFrame);
|
setParent(m_popupFrame);
|
||||||
setFocusPolicy(Qt::NoFocus);
|
setFocusPolicy(Qt::NoFocus);
|
||||||
|
|
||||||
|
m_pager = new QWidget;
|
||||||
|
QHBoxLayout *hbox = new QHBoxLayout(m_pager);
|
||||||
|
hbox->setMargin(0);
|
||||||
|
hbox->setSpacing(0);
|
||||||
|
hbox->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum));
|
||||||
|
hbox->addWidget(leftArrow);
|
||||||
|
hbox->addWidget(rightArrow);
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
layout->addWidget(this);
|
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(m_pager);
|
||||||
|
layout->addWidget(this);
|
||||||
m_popupFrame->setLayout(layout);
|
m_popupFrame->setLayout(layout);
|
||||||
|
|
||||||
QPalette pal = palette();
|
connect(leftArrow, SIGNAL(clicked()), SLOT(previousPage()));
|
||||||
|
connect(rightArrow, SIGNAL(clicked()), SLOT(nextPage()));
|
||||||
|
|
||||||
|
QPalette pal = m_popupFrame->palette();
|
||||||
setAutoFillBackground(true);
|
setAutoFillBackground(true);
|
||||||
pal.setColor(QPalette::Background, QColor(255, 255, 220));
|
pal.setColor(QPalette::Background, QColor(255, 255, 220));
|
||||||
setPalette(pal);
|
m_popupFrame->setPalette(pal);
|
||||||
|
|
||||||
setTextFormat(Qt::RichText);
|
setTextFormat(Qt::RichText);
|
||||||
setMargin(1);
|
setMargin(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionArgumentWidget::showFunctionHint(Function *functionSymbol,
|
void FunctionArgumentWidget::showFunctionHint(QList<Function *> functionSymbols,
|
||||||
const LookupContext &context)
|
const LookupContext &context)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(!functionSymbols.isEmpty());
|
||||||
|
|
||||||
m_popupFrame->hide();
|
m_popupFrame->hide();
|
||||||
|
|
||||||
m_item = functionSymbol;
|
m_items = functionSymbols;
|
||||||
m_context = context;
|
m_context = context;
|
||||||
m_startpos = m_editor->position();
|
m_startpos = m_editor->position();
|
||||||
|
m_current = 0;
|
||||||
|
|
||||||
// update the text
|
// update the text
|
||||||
m_currentarg = -1;
|
m_currentarg = -1;
|
||||||
update();
|
update();
|
||||||
|
|
||||||
|
m_pager->setVisible(functionSymbols.size() > 1);
|
||||||
|
|
||||||
QPoint pos = m_editor->cursorRect().topLeft();
|
QPoint pos = m_editor->cursorRect().topLeft();
|
||||||
pos.setY(pos.y() - sizeHint().height());
|
pos.setY(pos.y() - m_popupFrame->sizeHint().height() - 1);
|
||||||
m_popupFrame->move(pos);
|
m_popupFrame->move(pos);
|
||||||
m_popupFrame->show();
|
m_popupFrame->show();
|
||||||
|
|
||||||
qApp->installEventFilter(this);
|
qApp->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::update()
|
void FunctionArgumentWidget::update()
|
||||||
{
|
{
|
||||||
int curpos = m_editor->position();
|
int curpos = m_editor->position();
|
||||||
@@ -276,22 +332,28 @@ bool FunctionArgumentWidget::eventFilter(QObject *obj, QEvent *e)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QEvent::WindowDeactivate:
|
case QEvent::WindowDeactivate:
|
||||||
case QEvent::Leave:
|
|
||||||
case QEvent::FocusOut:
|
case QEvent::FocusOut:
|
||||||
{
|
{
|
||||||
if (obj != m_editor->widget())
|
if (obj != m_editor->widget())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
qDebug() << e;
|
||||||
|
close();
|
||||||
|
break;
|
||||||
case QEvent::MouseButtonPress:
|
case QEvent::MouseButtonPress:
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
case QEvent::MouseButtonDblClick:
|
case QEvent::MouseButtonDblClick:
|
||||||
case QEvent::Wheel:
|
case QEvent::Wheel: {
|
||||||
close();
|
QWidget *widget = qobject_cast<QWidget *>(obj);
|
||||||
|
if (! (widget == this || m_popupFrame->isAncestorOf(widget))) {
|
||||||
|
qDebug() << e << widget;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,8 +368,8 @@ void FunctionArgumentWidget::updateHintText()
|
|||||||
overview.setShowReturnTypes(true);
|
overview.setShowReturnTypes(true);
|
||||||
overview.setShowArgumentNames(true);
|
overview.setShowArgumentNames(true);
|
||||||
overview.setMarkArgument(m_currentarg + 1);
|
overview.setMarkArgument(m_currentarg + 1);
|
||||||
QString text = overview(m_item->type(), m_item->name());
|
Function *f = currentFunction();
|
||||||
setText(text);
|
setText(overview(f->type(), f->name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CppCodeCompletion::CppCodeCompletion(CppModelManager *manager)
|
CppCodeCompletion::CppCodeCompletion(CppModelManager *manager)
|
||||||
@@ -591,6 +653,8 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
|||||||
o.setShowReturnTypes(true);
|
o.setShowReturnTypes(true);
|
||||||
o.setShowArgumentNames(true);
|
o.setShowArgumentNames(true);
|
||||||
|
|
||||||
|
QList<Function *> functions;
|
||||||
|
|
||||||
foreach (const TypeOfExpression::Result &result, results) {
|
foreach (const TypeOfExpression::Result &result, results) {
|
||||||
FullySpecifiedType exprTy = result.first;
|
FullySpecifiedType exprTy = result.first;
|
||||||
|
|
||||||
@@ -604,8 +668,7 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
|||||||
else if (! member->identity()->isEqualTo(klass->identity()))
|
else if (! member->identity()->isEqualTo(klass->identity()))
|
||||||
continue;
|
continue;
|
||||||
if (TextEditor::CompletionItem item = toCompletionItem(member)) {
|
if (TextEditor::CompletionItem item = toCompletionItem(member)) {
|
||||||
item.m_text = o(member->type(), member->name());
|
functions.append(member->type()->asFunctionType());
|
||||||
m_completions.append(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +676,7 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_completions.isEmpty()) {
|
if (functions.isEmpty()) {
|
||||||
QSet<QString> signatures;
|
QSet<QString> signatures;
|
||||||
|
|
||||||
foreach (const TypeOfExpression::Result &p, results) {
|
foreach (const TypeOfExpression::Result &p, results) {
|
||||||
@@ -628,18 +691,21 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
|||||||
continue;
|
continue;
|
||||||
signatures.insert(signature);
|
signatures.insert(signature);
|
||||||
|
|
||||||
item.m_text = o(ty, fun->name());
|
functions.append(fun);
|
||||||
m_completions.append(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is only one item, show the function argument widget immediately
|
if (! functions.isEmpty()) {
|
||||||
if (m_completions.size() == 1)
|
// Recreate if necessary
|
||||||
complete(m_completions.takeFirst());
|
if (!m_functionArgumentWidget)
|
||||||
|
m_functionArgumentWidget = new FunctionArgumentWidget;
|
||||||
|
|
||||||
return ! m_completions.isEmpty();
|
m_functionArgumentWidget->showFunctionHint(functions, typeOfExpression.lookupContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &results,
|
bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &results,
|
||||||
@@ -1095,7 +1161,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item)
|
|||||||
if (!m_functionArgumentWidget)
|
if (!m_functionArgumentWidget)
|
||||||
m_functionArgumentWidget = new FunctionArgumentWidget;
|
m_functionArgumentWidget = new FunctionArgumentWidget;
|
||||||
|
|
||||||
m_functionArgumentWidget->showFunctionHint(function, typeOfExpression.lookupContext());
|
m_functionArgumentWidget->showFunctionHint(QList<Function*>() << function, typeOfExpression.lookupContext());
|
||||||
}
|
}
|
||||||
} else if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {
|
} else if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {
|
||||||
QString toInsert = item.m_text;
|
QString toInsert = item.m_text;
|
||||||
@@ -1217,3 +1283,5 @@ int CppCodeCompletion::findStartOfName(int pos) const
|
|||||||
|
|
||||||
return pos + 1;
|
return pos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "cppcodecompletion.moc"
|
||||||
|
|||||||
Reference in New Issue
Block a user