From 8912f4db98153e9b40c35b0300c5196d2a17e56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= <thorbjorn.lindeijer@nokia.com> Date: Thu, 26 Mar 2009 11:14:05 +0100 Subject: [PATCH] Initial work on better function argument widget Done with Roberto Raggi. --- src/plugins/cpptools/cppcodecompletion.cpp | 128 ++++++++++++++++----- 1 file changed, 98 insertions(+), 30 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 6157204867f..8b7f59de17a 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -60,10 +60,11 @@ #include <QtCore/QMap> #include <QtCore/QFile> #include <QtGui/QAction> +#include <QtGui/QApplication> #include <QtGui/QKeyEvent> #include <QtGui/QLabel> +#include <QtGui/QToolButton> #include <QtGui/QVBoxLayout> -#include <QtGui/QApplication> using namespace CPlusPlus; @@ -72,26 +73,37 @@ namespace Internal { class FunctionArgumentWidget : public QLabel { + Q_OBJECT + public: FunctionArgumentWidget(); - void showFunctionHint(Function *functionSymbol, const LookupContext &context); + void showFunctionHint(QList<Function *> functionSymbols, const LookupContext &context); protected: bool eventFilter(QObject *obj, QEvent *e); +private slots: + void nextPage(); + void previousPage(); + private: void update(); void close(); void updateHintText(); + Function *currentFunction() const + { return m_items.at(m_current); } + int m_startpos; int m_currentarg; TextEditor::ITextEditor *m_editor; + QWidget *m_pager; QFrame *m_popupFrame; - Function *m_item; + QList<Function *> m_items; LookupContext m_context; + int m_current; }; class ConvertToCompletionItem: protected NameVisitor @@ -180,57 +192,101 @@ protected: using namespace CppTools::Internal; -FunctionArgumentWidget::FunctionArgumentWidget() - : m_item(0) +FunctionArgumentWidget::FunctionArgumentWidget(): + m_current(0) { QObject *editorObject = Core::EditorManager::instance()->currentEditor(); 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->setAttribute(Qt::WA_DeleteOnClose); - setFrameStyle(QFrame::Box); - setFrameShadow(QFrame::Plain); + QToolButton *leftArrow = new QToolButton; + 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); 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; - layout->addWidget(this); layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(m_pager); + layout->addWidget(this); 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); pal.setColor(QPalette::Background, QColor(255, 255, 220)); - setPalette(pal); + m_popupFrame->setPalette(pal); setTextFormat(Qt::RichText); setMargin(1); } -void FunctionArgumentWidget::showFunctionHint(Function *functionSymbol, +void FunctionArgumentWidget::showFunctionHint(QList<Function *> functionSymbols, const LookupContext &context) { + Q_ASSERT(!functionSymbols.isEmpty()); + m_popupFrame->hide(); - m_item = functionSymbol; + m_items = functionSymbols; m_context = context; m_startpos = m_editor->position(); + m_current = 0; // update the text m_currentarg = -1; update(); + m_pager->setVisible(functionSymbols.size() > 1); + 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->show(); 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() { int curpos = m_editor->position(); @@ -276,22 +332,28 @@ bool FunctionArgumentWidget::eventFilter(QObject *obj, QEvent *e) break; } case QEvent::WindowDeactivate: - case QEvent::Leave: case QEvent::FocusOut: { if (obj != m_editor->widget()) break; } + qDebug() << e; + close(); + break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: - case QEvent::Wheel: - close(); + case QEvent::Wheel: { + QWidget *widget = qobject_cast<QWidget *>(obj); + if (! (widget == this || m_popupFrame->isAncestorOf(widget))) { + qDebug() << e << widget; + close(); + } + } break; default: break; } - return false; } @@ -306,8 +368,8 @@ void FunctionArgumentWidget::updateHintText() overview.setShowReturnTypes(true); overview.setShowArgumentNames(true); overview.setMarkArgument(m_currentarg + 1); - QString text = overview(m_item->type(), m_item->name()); - setText(text); + Function *f = currentFunction(); + setText(overview(f->type(), f->name())); } CppCodeCompletion::CppCodeCompletion(CppModelManager *manager) @@ -591,6 +653,8 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi o.setShowReturnTypes(true); o.setShowArgumentNames(true); + QList<Function *> functions; + foreach (const TypeOfExpression::Result &result, results) { FullySpecifiedType exprTy = result.first; @@ -604,8 +668,7 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi else if (! member->identity()->isEqualTo(klass->identity())) continue; if (TextEditor::CompletionItem item = toCompletionItem(member)) { - item.m_text = o(member->type(), member->name()); - m_completions.append(item); + functions.append(member->type()->asFunctionType()); } } @@ -613,7 +676,7 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi } } - if (m_completions.isEmpty()) { + if (functions.isEmpty()) { QSet<QString> signatures; foreach (const TypeOfExpression::Result &p, results) { @@ -628,18 +691,21 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi continue; signatures.insert(signature); - item.m_text = o(ty, fun->name()); - m_completions.append(item); + functions.append(fun); } } } } - // If there is only one item, show the function argument widget immediately - if (m_completions.size() == 1) - complete(m_completions.takeFirst()); + if (! functions.isEmpty()) { + // Recreate if necessary + 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, @@ -1095,7 +1161,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) if (!m_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) { QString toInsert = item.m_text; @@ -1217,3 +1283,5 @@ int CppCodeCompletion::findStartOfName(int pos) const return pos + 1; } + +#include "cppcodecompletion.moc" -- GitLab