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
40 QVector<QTextLayout::FormatRange> formats;
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);
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 auto block = m_view->document()->begin();
168 int lines = 0;
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((std::max(lines, 1) * 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() -= fm.height();
185 pos.ry() -= 4;
186 move(pos);
187}
188
189void ArgumentHintWidget::positionAndShow()
190{
191 updateGeometry();
192 show();
193}
194
195void ArgumentHintWidget::clearAndHide()
196{
197 m_current = -1;
198 m_currentIndicator->clear();
199 m_view->clear();
200 hide();
201}
@ 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)
QIcon fromTheme(const QString &name)
qsizetype count() const const
pointer data()
T value(qsizetype i) const const
QSyntaxHighlighter(QObject *parent)
void setFormat(int start, int count, const QColor &color)
AlignCenter
bool fontItalic() const const
int fontWeight() const const
void setFontUnderline(bool underline)
WrapAtWordBoundaryOrAnywhere
void hide()
void setFixedHeight(int h)
void setFixedWidth(int w)
void show()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:52:51 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.