KTextEditor

kateargumenthinttree.cpp
1/*
2 SPDX-FileCopyrightText: 2024 Waqar Ahmed <waqar.17a@gmail.com>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "kateargumenthinttree.h"
7
8#include "kateargumenthintmodel.h"
9#include "katecompletionwidget.h"
10
11#include <QHBoxLayout>
12#include <QLabel>
13#include <QModelIndex>
14#include <QPlainTextEdit>
15#include <QSyntaxHighlighter>
16#include <QTextBlock>
17#include <QToolButton>
18
19class ArgumentHighlighter : public QSyntaxHighlighter
20{
21public:
22 ArgumentHighlighter(QTextDocument *doc)
24 {
25 }
26
27 void highlightBlock(const QString &) override
28 {
29 for (const auto &f : std::as_const(formats)) {
30 QTextCharFormat fmt = f.format;
31 if (fmt.fontWeight() == QFont::Bold || fmt.fontItalic()) {
32 // bold doesn't work with some fonts for whatever reason
33 // so we just underline as well for fonts where bold won't work
34 fmt.setFontUnderline(true);
35 }
36 setFormat(f.start, f.length, fmt);
37 }
38 }
39
41};
42
43static QList<QTextLayout::FormatRange> highlightingFromVariantList(const QList<QVariant> &customHighlights)
44{
46
47 for (int i = 0; i + 2 < customHighlights.count(); i += 3) {
48 if (!customHighlights[i].canConvert<int>() || !customHighlights[i + 1].canConvert<int>() || !customHighlights[i + 2].canConvert<QTextFormat>()) {
49 continue;
50 }
51
53 format.start = customHighlights[i].toInt();
54 format.length = customHighlights[i + 1].toInt();
55 format.format = customHighlights[i + 2].value<QTextFormat>().toCharFormat();
56
57 if (!format.format.isValid()) {
58 qWarning() << "Format is not valid";
59 continue;
60 }
61
62 ret << format;
63 }
64 return ret;
65}
66
67ArgumentHintWidget::ArgumentHintWidget(KateArgumentHintModel *model, const QFont &font, KateCompletionWidget *completion, QWidget *parent)
68 : QFrame(parent)
69 , m_completionWidget(completion)
70 , m_view(new QPlainTextEdit(this))
71 , m_currentIndicator(new QLabel(this))
72 , m_model(model)
73 , m_highlighter(new ArgumentHighlighter(m_view->document()))
74 , m_leftSide(new QWidget(this))
75{
76 setAutoFillBackground(true);
77 // we have only 1 top level frame
78 setFrameStyle(QFrame::Box | QFrame::Raised);
79 m_view->setFrameStyle(QFrame::NoFrame);
80
81 auto upButton = new QToolButton(this);
82 upButton->setAutoRaise(true);
83 upButton->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up")));
84 connect(upButton, &QAbstractButton::clicked, this, &ArgumentHintWidget::selectPrevious);
85
86 auto downButton = new QToolButton(this);
87 downButton->setAutoRaise(true);
88 downButton->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down")));
89 connect(downButton, &QAbstractButton::clicked, this, &ArgumentHintWidget::selectNext);
90
91 auto vLayout = new QVBoxLayout(m_leftSide);
92 vLayout->setContentsMargins({});
93 vLayout->setAlignment(Qt::AlignCenter);
94 vLayout->addWidget(upButton);
95 vLayout->addWidget(m_currentIndicator);
96 vLayout->addWidget(downButton);
97
98 auto layout = new QHBoxLayout(this);
99 layout->setContentsMargins({});
100 layout->setSpacing(0);
101 layout->addWidget(m_leftSide);
102 layout->addWidget(m_view);
103 setFixedWidth(380);
104 m_view->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
105 m_view->document()->setDefaultFont(font);
106
107 connect(m_model, &QAbstractItemModel::modelReset, this, [this]() {
108 m_current = -1;
109 selectNext();
110 });
111 setVisible(false);
112}
113
114void ArgumentHintWidget::selectNext()
115{
116 int rowCount = m_model->rowCount();
117 if (rowCount == 0) {
118 clearAndHide();
119 return;
120 }
121 m_current = m_current + 1;
122 if (m_current >= rowCount) {
123 m_current = 0;
124 }
125
126 activateHint(m_current, rowCount);
127}
128
129void ArgumentHintWidget::selectPrevious()
130{
131 int rowCount = m_model->rowCount();
132 if (rowCount == 0) {
133 clearAndHide();
134 return;
135 }
136
137 m_current = m_current - 1;
138 if (m_current <= 0) {
139 m_current = rowCount - 1;
140 }
141
142 activateHint(m_current, rowCount);
143}
144
145void ArgumentHintWidget::activateHint(int i, int rowCount)
146{
147 const auto index = m_model->index(i);
148 const auto list = index.data(KTextEditor::CodeCompletionModel::CustomHighlight).toList();
149 const auto highlights = highlightingFromVariantList(list);
150 m_highlighter->formats = highlights;
151
152 if (rowCount == 1) {
153 m_leftSide->setVisible(false);
154 } else {
155 if (m_leftSide->isHidden()) {
156 m_leftSide->setVisible(true);
157 }
158 m_currentIndicator->setText(QStringLiteral("%1/%2").arg(i + 1).arg(rowCount));
159 }
160
161 m_view->setPlainText(index.data().toString());
162 updateGeometry();
163}
164
165void ArgumentHintWidget::updateGeometry()
166{
167 int lines = 1;
168 auto block = m_view->document()->begin();
169 QFontMetrics fm(m_view->document()->defaultFont());
170 int maxWidth = 0;
171 while (block.isValid()) {
172 maxWidth = std::max((int)block.layout()->maximumWidth(), maxWidth);
173 lines += block.layout()->lineCount();
174 block = block.next();
175 }
176 setFixedHeight((lines * fm.height()) + 10 + m_view->document()->documentMargin());
177 // limit the width to between 400 - 600
178 int width = std::max(maxWidth, 400);
179 width = std::min(width, 600);
181
182 QPoint pos = m_completionWidget->pos();
183 pos.ry() -= this->height();
184 pos.ry() -= 4;
185 move(pos);
186}
187
188void ArgumentHintWidget::positionAndShow()
189{
190 updateGeometry();
191 show();
192}
193
194void ArgumentHintWidget::clearAndHide()
195{
196 m_current = -1;
197 m_currentIndicator->clear();
198 m_view->clear();
199 hide();
200}
@ CustomHighlight
Allows an item to provide custom highlighting.
This is the code completion's main widget, and also contains the core interface logic.
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const QList< QKeySequence > & completion()
void clicked(bool checked)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
QIcon fromTheme(const QString &name)
void clear()
void setText(const QString &)
int count(const T &value) const const
T value(int i) const const
QTextDocument * document() const const
void setPlainText(const QString &text)
int & ry()
void setFormat(int start, int count, const QTextCharFormat &format)
AlignCenter
bool fontItalic() const const
int fontWeight() const const
void setFontUnderline(bool underline)
QTextBlock begin() const const
WrapAtWordBoundaryOrAnywhere
void hide()
bool isHidden() const const
void move(int x, int y)
void setFixedHeight(int h)
void setFixedWidth(int w)
void show()
virtual void setVisible(bool visible)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Feb 24 2024 20:00:58 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.