| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-03-05 11:25:49 +01:00
										 |  |  | ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Commercial Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Licensees holding valid Qt Commercial licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the Qt Commercial License Agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ** a written agreement between you and Nokia. | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Alternatively, 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.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** If you are unsure which license is appropriate for your use, please | 
					
						
							| 
									
										
										
										
											2009-08-14 09:30:56 +02:00
										 |  |  | ** contact the sales department at http://qt.nokia.com/contact.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 16:19:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "completionwidget.h"
 | 
					
						
							|  |  |  | #include "completionsupport.h"
 | 
					
						
							|  |  |  | #include "icompletioncollector.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <texteditor/itexteditable.h>
 | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <utils/faketooltip.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QtCore/QEvent>
 | 
					
						
							|  |  |  | #include <QtGui/QApplication>
 | 
					
						
							| 
									
										
										
										
											2008-12-18 16:56:43 +01:00
										 |  |  | #include <QtGui/QDesktopWidget>
 | 
					
						
							|  |  |  | #include <QtGui/QKeyEvent>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QtGui/QVBoxLayout>
 | 
					
						
							| 
									
										
										
										
											2010-02-19 16:26:17 +01:00
										 |  |  | #include <QtGui/QScrollBar>
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | #include <QtGui/QLabel>
 | 
					
						
							|  |  |  | #include <QtGui/QStylePainter>
 | 
					
						
							| 
									
										
										
										
											2010-04-09 13:27:43 +02:00
										 |  |  | #include <QtGui/QToolTip>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <limits.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace TextEditor; | 
					
						
							|  |  |  | using namespace TextEditor::Internal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define NUMBER_OF_VISIBLE_ITEMS 10
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | namespace TextEditor { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | class AutoCompletionModel : public QAbstractListModel | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     AutoCompletionModel(QObject *parent); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     inline const CompletionItem &itemAt(const QModelIndex &index) const | 
					
						
							|  |  |  |     { return m_items.at(index.row()); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void setItems(const QList<CompletionItem> &items); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int rowCount(const QModelIndex &parent = QModelIndex()) const; | 
					
						
							|  |  |  |     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QList<CompletionItem> m_items; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  | class CompletionInfoFrame : public Utils::FakeToolTip | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | public: | 
					
						
							|  |  |  |     CompletionInfoFrame(QWidget *parent = 0) : | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  |         Utils::FakeToolTip(parent), | 
					
						
							|  |  |  |         m_label(new QLabel(this)) | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  |         QVBoxLayout *layout = new QVBoxLayout(this); | 
					
						
							|  |  |  |         layout->setMargin(0); | 
					
						
							|  |  |  |         layout->setSpacing(0); | 
					
						
							|  |  |  |         layout->addWidget(m_label); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  |         m_label->setForegroundRole(QPalette::ToolTipText); | 
					
						
							|  |  |  |         m_label->setBackgroundRole(QPalette::ToolTipBase); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void setText(const QString &text) | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  |         m_label->setText(text); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-04-14 17:24:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QLabel *m_label; | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace TextEditor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AutoCompletionModel::AutoCompletionModel(QObject *parent) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     : QAbstractListModel(parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AutoCompletionModel::setItems(const QList<CompletionItem> &items) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_items = items; | 
					
						
							|  |  |  |     reset(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AutoCompletionModel::rowCount(const QModelIndex &) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_items.count(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QVariant AutoCompletionModel::data(const QModelIndex &index, int role) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (index.row() >= m_items.count()) | 
					
						
							|  |  |  |         return QVariant(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (role == Qt::DisplayRole) { | 
					
						
							| 
									
										
										
										
											2009-10-05 18:32:08 +02:00
										 |  |  |         return itemAt(index).text; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else if (role == Qt::DecorationRole) { | 
					
						
							| 
									
										
										
										
											2009-10-05 18:32:08 +02:00
										 |  |  |         return itemAt(index).icon; | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |     } else if (role == Qt::WhatsThisRole) { | 
					
						
							| 
									
										
										
										
											2009-10-05 18:32:08 +02:00
										 |  |  |         return itemAt(index).details; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return QVariant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | CompletionWidget::CompletionWidget(CompletionSupport *support, ITextEditable *editor) | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     : QFrame(0, Qt::Popup), | 
					
						
							|  |  |  |       m_support(support), | 
					
						
							| 
									
										
										
										
											2010-02-17 15:18:36 +01:00
										 |  |  |       m_editor(editor), | 
					
						
							|  |  |  |       m_completionListView(new CompletionListView(support, editor, this)) | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // We disable the frame on this list view and use a QFrame around it instead.
 | 
					
						
							|  |  |  |     // This improves the look with QGTKStyle.
 | 
					
						
							|  |  |  | #ifndef Q_WS_MAC
 | 
					
						
							| 
									
										
										
										
											2010-02-17 15:18:36 +01:00
										 |  |  |     setFrameStyle(m_completionListView->frameStyle()); | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-02-17 15:18:36 +01:00
										 |  |  |     m_completionListView->setFrameStyle(QFrame::NoFrame); | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     setObjectName(QLatin1String("m_popupFrame")); | 
					
						
							|  |  |  |     setAttribute(Qt::WA_DeleteOnClose); | 
					
						
							|  |  |  |     setMinimumSize(1, 1); | 
					
						
							| 
									
										
										
										
											2010-05-17 18:21:27 +02:00
										 |  |  |     setFont(editor->widget()->font()); | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QVBoxLayout *layout = new QVBoxLayout(this); | 
					
						
							|  |  |  |     layout->setMargin(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     layout->addWidget(m_completionListView); | 
					
						
							|  |  |  |     setFocusProxy(m_completionListView); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(m_completionListView, SIGNAL(itemSelected(TextEditor::CompletionItem)), | 
					
						
							|  |  |  |             this, SIGNAL(itemSelected(TextEditor::CompletionItem))); | 
					
						
							|  |  |  |     connect(m_completionListView, SIGNAL(completionListClosed()), | 
					
						
							|  |  |  |             this, SIGNAL(completionListClosed())); | 
					
						
							|  |  |  |     connect(m_completionListView, SIGNAL(activated(QModelIndex)), | 
					
						
							|  |  |  |             SLOT(closeList(QModelIndex))); | 
					
						
							| 
									
										
										
										
											2010-03-29 14:20:12 +02:00
										 |  |  |     connect(editor, SIGNAL(contentsChangedBecauseOfUndo()), | 
					
						
							|  |  |  |             this, SLOT(closeList())); | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CompletionWidget::~CompletionWidget() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CompletionWidget::setQuickFix(bool quickFix) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_completionListView->setQuickFix(quickFix); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CompletionWidget::setCompletionItems(const QList<TextEditor::CompletionItem> &completionitems) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_completionListView->setCompletionItems(completionitems); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CompletionWidget::closeList(const QModelIndex &index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_completionListView->closeList(index); | 
					
						
							|  |  |  |     close(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CompletionWidget::showCompletions(int startPos) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-29 12:19:53 +02:00
										 |  |  |     ensurePolished(); | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     updatePositionAndSize(startPos); | 
					
						
							|  |  |  |     show(); | 
					
						
							|  |  |  |     setFocus(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CompletionWidget::updatePositionAndSize(int startPos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Determine size by calculating the space of the visible items
 | 
					
						
							|  |  |  |     QAbstractItemModel *model = m_completionListView->model(); | 
					
						
							|  |  |  |     int visibleItems = model->rowCount(); | 
					
						
							|  |  |  |     if (visibleItems > NUMBER_OF_VISIBLE_ITEMS) | 
					
						
							|  |  |  |         visibleItems = NUMBER_OF_VISIBLE_ITEMS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QStyleOptionViewItem &option = m_completionListView->viewOptions(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QSize shint; | 
					
						
							|  |  |  |     for (int i = 0; i < visibleItems; ++i) { | 
					
						
							|  |  |  |         QSize tmp = m_completionListView->itemDelegate()->sizeHint(option, model->index(i, 0)); | 
					
						
							|  |  |  |         if (shint.width() < tmp.width()) | 
					
						
							|  |  |  |             shint = tmp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int fw = frameWidth(); | 
					
						
							|  |  |  |     const int width = shint.width() + fw * 2 + 30; | 
					
						
							|  |  |  |     const int height = shint.height() * visibleItems + fw * 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Determine the position, keeping the popup on the screen
 | 
					
						
							|  |  |  |     const QRect cursorRect = m_editor->cursorRect(startPos); | 
					
						
							|  |  |  |     const QDesktopWidget *desktop = QApplication::desktop(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QWidget *editorWidget = m_editor->widget(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef Q_WS_MAC
 | 
					
						
							|  |  |  |     const QRect screen = desktop->availableGeometry(desktop->screenNumber(editorWidget)); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     const QRect screen = desktop->screenGeometry(desktop->screenNumber(editorWidget)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QPoint pos = cursorRect.bottomLeft(); | 
					
						
							|  |  |  |     pos.rx() -= 16 + fw;    // Space for the icons
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pos.y() + height > screen.bottom()) | 
					
						
							|  |  |  |         pos.setY(cursorRect.top() - height); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pos.x() + width > screen.right()) | 
					
						
							|  |  |  |         pos.setX(screen.right() - width); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setGeometry(pos.x(), pos.y(), width, height); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CompletionListView::CompletionListView(CompletionSupport *support, ITextEditable *editor, CompletionWidget *completionWidget) | 
					
						
							|  |  |  |     : QListView(completionWidget), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |       m_blockFocusOut(false), | 
					
						
							| 
									
										
										
										
											2009-06-08 14:32:42 +02:00
										 |  |  |       m_quickFix(false), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |       m_editor(editor), | 
					
						
							|  |  |  |       m_editorWidget(editor->widget()), | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |       m_completionWidget(completionWidget), | 
					
						
							|  |  |  |       m_model(new AutoCompletionModel(this)), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |       m_support(support) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(m_editorWidget, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 14:34:31 +02:00
										 |  |  |     m_infoTimer.setInterval(1000); | 
					
						
							|  |  |  |     m_infoTimer.setSingleShot(true); | 
					
						
							|  |  |  |     connect(&m_infoTimer, SIGNAL(timeout()), SLOT(maybeShowInfoTip())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-21 11:11:02 +01:00
										 |  |  |     setAttribute(Qt::WA_MacShowFocusRect, false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setUniformItemSizes(true); | 
					
						
							|  |  |  |     setSelectionBehavior(QAbstractItemView::SelectItems); | 
					
						
							|  |  |  |     setSelectionMode(QAbstractItemView::SingleSelection); | 
					
						
							|  |  |  |     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							| 
									
										
										
										
											2008-12-18 16:56:43 +01:00
										 |  |  |     setMinimumSize(1, 1); | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     setModel(m_model); | 
					
						
							| 
									
										
										
										
											2010-02-19 16:26:17 +01:00
										 |  |  | #ifdef Q_WS_MAC
 | 
					
						
							|  |  |  |     if (horizontalScrollBar()) | 
					
						
							|  |  |  |         horizontalScrollBar()->setAttribute(Qt::WA_MacMiniSize); | 
					
						
							|  |  |  |     if (verticalScrollBar()) | 
					
						
							|  |  |  |         verticalScrollBar()->setAttribute(Qt::WA_MacMiniSize); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CompletionListView::~CompletionListView() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | void CompletionListView::maybeShowInfoTip() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QModelIndex current = currentIndex(); | 
					
						
							|  |  |  |     if (!current.isValid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     QString infoTip = current.data(Qt::WhatsThisRole).toString(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (infoTip.isEmpty()) { | 
					
						
							|  |  |  |         delete m_infoFrame.data(); | 
					
						
							| 
									
										
										
										
											2010-04-15 14:34:31 +02:00
										 |  |  |         m_infoTimer.setInterval(200); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_infoFrame.isNull()) | 
					
						
							|  |  |  |         m_infoFrame = new CompletionInfoFrame(this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QRect r = rectForIndex(current); | 
					
						
							|  |  |  |     m_infoFrame->move( | 
					
						
							|  |  |  |             (parentWidget()->mapToGlobal( | 
					
						
							| 
									
										
										
										
											2010-04-15 14:34:31 +02:00
										 |  |  |                     parentWidget()->rect().topRight())).x() + 3, | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  |             mapToGlobal(r.topRight()).y() - verticalOffset() | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |     m_infoFrame->setText(infoTip); | 
					
						
							|  |  |  |     m_infoFrame->adjustSize(); | 
					
						
							|  |  |  |     m_infoFrame->show(); | 
					
						
							| 
									
										
										
										
											2010-04-09 14:15:21 +02:00
										 |  |  |     m_infoFrame->raise(); | 
					
						
							| 
									
										
										
										
											2010-04-15 14:34:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_infoTimer.setInterval(0); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CompletionListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QListView::currentChanged(current, previous); | 
					
						
							| 
									
										
										
										
											2010-04-15 14:34:31 +02:00
										 |  |  |     m_infoTimer.start(); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:59:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | bool CompletionListView::event(QEvent *e) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_blockFocusOut) | 
					
						
							|  |  |  |         return QListView::event(e); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool forwardKeys = true; | 
					
						
							|  |  |  |     if (e->type() == QEvent::FocusOut) { | 
					
						
							| 
									
										
										
										
											2009-11-20 15:07:10 +01:00
										 |  |  |         QModelIndex index; | 
					
						
							|  |  |  | #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.
 | 
					
						
							|  |  |  |             index = currentIndex(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |         m_completionWidget->closeList(index); | 
					
						
							| 
									
										
										
										
											2010-05-31 11:48:18 +02:00
										 |  |  |         if (m_infoFrame) | 
					
						
							|  |  |  |             m_infoFrame->close(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2010-01-05 18:23:36 +01:00
										 |  |  |     } else if (e->type() == QEvent::ShortcutOverride) { | 
					
						
							|  |  |  |         QKeyEvent *ke = static_cast<QKeyEvent *>(e); | 
					
						
							|  |  |  |         switch (ke->key()) { | 
					
						
							|  |  |  |         case Qt::Key_N: | 
					
						
							|  |  |  |         case Qt::Key_P: | 
					
						
							|  |  |  |             // select next/previous completion
 | 
					
						
							|  |  |  |             if (ke->modifiers() == Qt::ControlModifier) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 e->accept(); | 
					
						
							|  |  |  |                 int change = (ke->key() == Qt::Key_N) ? 1 : -1; | 
					
						
							|  |  |  |                 int nrows = model()->rowCount(); | 
					
						
							|  |  |  |                 int row = currentIndex().row(); | 
					
						
							|  |  |  |                 int newRow = (row + change + nrows) % nrows; | 
					
						
							|  |  |  |                 if (newRow == row + change || !ke->isAutoRepeat()) | 
					
						
							|  |  |  |                     setCurrentIndex(m_model->index(newRow)); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else if (e->type() == QEvent::KeyPress) { | 
					
						
							|  |  |  |         QKeyEvent *ke = static_cast<QKeyEvent *>(e); | 
					
						
							|  |  |  |         switch (ke->key()) { | 
					
						
							| 
									
										
										
										
											2010-01-05 18:23:36 +01:00
										 |  |  |         case Qt::Key_N: | 
					
						
							|  |  |  |         case Qt::Key_P: | 
					
						
							|  |  |  |             // select next/previous completion - so don't pass on to editor
 | 
					
						
							|  |  |  |             if (ke->modifiers() == Qt::ControlModifier) | 
					
						
							|  |  |  |                 forwardKeys = false; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case Qt::Key_Escape: | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |             m_completionWidget->closeList(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case Qt::Key_Right: | 
					
						
							|  |  |  |         case Qt::Key_Left: | 
					
						
							| 
									
										
										
										
											2010-04-16 16:49:29 +02:00
										 |  |  |         case Qt::Key_Home: | 
					
						
							|  |  |  |         case Qt::Key_End: | 
					
						
							|  |  |  |             // We want these navigation keys to work in the editor, so forward them
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case Qt::Key_Tab: | 
					
						
							|  |  |  |         case Qt::Key_Return: | 
					
						
							|  |  |  |             //independently from style, accept current entry if return is pressed
 | 
					
						
							| 
									
										
										
										
											2009-11-20 15:07:10 +01:00
										 |  |  |             if (qApp->focusWidget() == this) | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |                 m_completionWidget->closeList(currentIndex()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case Qt::Key_Up: | 
					
						
							| 
									
										
										
										
											2009-11-23 20:42:31 +01:00
										 |  |  |             if (!ke->isAutoRepeat() | 
					
						
							|  |  |  |                 && currentIndex().row() == 0) { | 
					
						
							| 
									
										
										
										
											2009-09-11 11:19:33 +02:00
										 |  |  |                 setCurrentIndex(model()->index(model()->rowCount()-1, 0)); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             forwardKeys = false; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case Qt::Key_Down: | 
					
						
							| 
									
										
										
										
											2009-11-23 20:42:31 +01:00
										 |  |  |             if (!ke->isAutoRepeat() | 
					
						
							|  |  |  |                 && currentIndex().row() == model()->rowCount()-1) { | 
					
						
							| 
									
										
										
										
											2009-09-11 11:19:33 +02:00
										 |  |  |                 setCurrentIndex(model()->index(0, 0)); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |             forwardKeys = false; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case Qt::Key_Enter: | 
					
						
							|  |  |  |         case Qt::Key_PageDown: | 
					
						
							|  |  |  |         case Qt::Key_PageUp: | 
					
						
							|  |  |  |             forwardKeys = false; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         default: | 
					
						
							| 
									
										
										
										
											2010-01-11 17:54:02 +01:00
										 |  |  |             // if a key is forwarded, completion widget is re-opened and selected item is reset to first,
 | 
					
						
							|  |  |  |             // so only forward keys that insert text and refine the completed item
 | 
					
						
							|  |  |  |             forwardKeys = !ke->text().isEmpty(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 14:32:42 +02:00
										 |  |  |         if (forwardKeys && ! m_quickFix) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             m_blockFocusOut = true; | 
					
						
							|  |  |  |             QApplication::sendEvent(m_editorWidget, e); | 
					
						
							|  |  |  |             m_blockFocusOut = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Have the completion support update the list of items
 | 
					
						
							|  |  |  |             m_support->autoComplete(m_editor, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return QListView::event(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | void CompletionListView::keyboardSearch(const QString &search) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-13 17:35:17 +02:00
										 |  |  |     Q_UNUSED(search) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | void CompletionListView::setQuickFix(bool quickFix) | 
					
						
							| 
									
										
										
										
											2009-06-08 14:32:42 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     m_quickFix = quickFix; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | void CompletionListView::setCompletionItems(const QList<TextEditor::CompletionItem> &completionItems) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     m_model->setItems(completionItems); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Select the first of the most relevant completion items
 | 
					
						
							|  |  |  |     int relevance = INT_MIN; | 
					
						
							|  |  |  |     int mostRelevantIndex = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < completionItems.size(); ++i) { | 
					
						
							|  |  |  |         const CompletionItem &item = completionItems.at(i); | 
					
						
							| 
									
										
										
										
											2009-10-05 18:32:08 +02:00
										 |  |  |         if (item.relevance > relevance) { | 
					
						
							|  |  |  |             relevance = item.relevance; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             mostRelevantIndex = i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setCurrentIndex(m_model->index(mostRelevantIndex)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  | void CompletionListView::closeList(const QModelIndex &index) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     m_blockFocusOut = true; | 
					
						
							| 
									
										
										
										
											2008-12-18 16:56:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     if (index.isValid()) | 
					
						
							|  |  |  |         emit itemSelected(m_model->itemAt(index)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     emit completionListClosed(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 10:46:19 +01:00
										 |  |  |     m_blockFocusOut = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } |