Initial work on better function argument widget

Done with Roberto Raggi.
This commit is contained in:
Thorbjørn Lindeijer
2009-03-26 11:14:05 +01:00
parent 5a97436c0c
commit 8912f4db98

View File

@@ -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"