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);
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)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
QIcon fromTheme(const QString &name)
void clear()
void setText(const QString &)
qsizetype count() const const
pointer data()
T value(qsizetype i) const const
QTextDocument * document() const const
void setPlainText(const QString &text)
int & ry()
void setFormat(int start, int count, const QColor &color)
AlignCenter
bool fontItalic() const const
int fontWeight() const const
void setFontUnderline(bool underline)
QTextBlock begin() const const
WrapAtWordBoundaryOrAnywhere
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void hide()
bool isHidden() const const
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 Mon Nov 18 2024 12:11:26 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.