File indexing completed on 2024-04-14 03:55:01
0001 /* 0002 SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de> 0003 SPDX-FileCopyrightText: 2022 Waqar Ahmed <waqar.17a@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "katecompletiondelegate.h" 0009 0010 #include <ktexteditor/codecompletionmodel.h> 0011 0012 #include "katecompletionmodel.h" 0013 #include "katepartdebug.h" 0014 0015 #include <QApplication> 0016 #include <QPainter> 0017 0018 KateCompletionDelegate::KateCompletionDelegate(QObject *parent) 0019 : QStyledItemDelegate(parent) 0020 { 0021 } 0022 0023 static void paintItemViewText(QPainter *p, const QString &text, const QStyleOptionViewItem &options, QList<QTextLayout::FormatRange> formats) 0024 { 0025 // set formats 0026 QTextLayout textLayout(text, options.font, p->device()); 0027 auto fmts = textLayout.formats(); 0028 formats.append(fmts); 0029 textLayout.setFormats(formats); 0030 0031 // set alignment, rtls etc 0032 QTextOption textOption; 0033 textOption.setTextDirection(options.direction); 0034 textOption.setAlignment(QStyle::visualAlignment(options.direction, options.displayAlignment)); 0035 textLayout.setTextOption(textOption); 0036 0037 // layout the text 0038 textLayout.beginLayout(); 0039 0040 QTextLine line = textLayout.createLine(); 0041 if (!line.isValid()) 0042 return; 0043 0044 const int lineWidth = options.rect.width(); 0045 line.setLineWidth(lineWidth); 0046 line.setPosition(QPointF(0, 0)); 0047 0048 textLayout.endLayout(); 0049 0050 int y = QStyle::alignedRect(Qt::LayoutDirectionAuto, options.displayAlignment, textLayout.boundingRect().size().toSize(), options.rect).y(); 0051 0052 // draw the text 0053 const auto pos = QPointF(options.rect.x(), y); 0054 textLayout.draw(p, pos); 0055 } 0056 0057 void KateCompletionDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o, const QModelIndex &index) const 0058 { 0059 QStyleOptionViewItem opt = o; 0060 initStyleOption(&opt, index); 0061 QString text = opt.text; 0062 0063 if (text.isEmpty()) { 0064 QStyledItemDelegate::paint(painter, o, index); 0065 return; 0066 } 0067 0068 auto *style = opt.widget->style() ? opt.widget->style() : qApp->style(); 0069 0070 opt.text.clear(); 0071 0072 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); 0073 0074 QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, opt.widget); 0075 0076 const bool isGroup = index.data(KateCompletionModel::IsNonEmptyGroup).toBool(); 0077 if (!isGroup && !opt.features.testFlag(QStyleOptionViewItem::HasDecoration)) { 0078 // 3 because 2 margins for the icon, and one left margin for the text 0079 int hMargins = style->pixelMetric(QStyle::PM_FocusFrameHMargin) * 3; 0080 textRect.adjust(hMargins + opt.decorationSize.width(), 0, 0, 0); 0081 } 0082 0083 #if 0 0084 auto p = painter->pen(); 0085 painter->setPen(Qt::yellow); 0086 painter->drawRect(opt.rect); 0087 0088 painter->setPen(Qt::red); 0089 painter->drawRect(textRect); 0090 painter->setPen(p); 0091 #endif 0092 0093 auto highlightings = createHighlighting(index); 0094 opt.rect = textRect; 0095 opt.displayAlignment = m_alignTop ? Qt::AlignTop : Qt::AlignVCenter; 0096 paintItemViewText(painter, text, opt, std::move(highlightings)); 0097 } 0098 0099 QSize KateCompletionDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0100 { 0101 if (index.data().toString().isEmpty()) { 0102 return QStyledItemDelegate::sizeHint(option, index); 0103 } 0104 0105 QSize size = QStyledItemDelegate::sizeHint(option, index); 0106 if (!index.data(Qt::DecorationRole).isNull()) { 0107 return size; 0108 } 0109 const int hMargins = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) * 3; 0110 size.rwidth() += option.decorationSize.width() + hMargins; 0111 return size; 0112 } 0113 0114 static QList<QTextLayout::FormatRange> highlightingFromVariantList(const QList<QVariant> &customHighlights) 0115 { 0116 QList<QTextLayout::FormatRange> ret; 0117 0118 for (int i = 0; i + 2 < customHighlights.count(); i += 3) { 0119 if (!customHighlights[i].canConvert<int>() || !customHighlights[i + 1].canConvert<int>() || !customHighlights[i + 2].canConvert<QTextFormat>()) { 0120 qCWarning(LOG_KTE) << "Unable to convert triple to custom formatting."; 0121 continue; 0122 } 0123 0124 QTextLayout::FormatRange format; 0125 format.start = customHighlights[i].toInt(); 0126 format.length = customHighlights[i + 1].toInt(); 0127 format.format = customHighlights[i + 2].value<QTextFormat>().toCharFormat(); 0128 0129 if (!format.format.isValid()) { 0130 qCWarning(LOG_KTE) << "Format is not valid"; 0131 } 0132 0133 ret << format; 0134 } 0135 return ret; 0136 } 0137 0138 QList<QTextLayout::FormatRange> KateCompletionDelegate::createHighlighting(const QModelIndex &index) 0139 { 0140 QVariant highlight = index.data(KTextEditor::CodeCompletionModel::HighlightingMethod); 0141 0142 // TODO: config enable specifying no highlight as default 0143 int highlightMethod = KTextEditor::CodeCompletionModel::InternalHighlighting; 0144 if (highlight.canConvert<int>()) { 0145 highlightMethod = highlight.toInt(); 0146 } 0147 0148 if (highlightMethod & KTextEditor::CodeCompletionModel::CustomHighlighting) { 0149 return highlightingFromVariantList(index.data(KTextEditor::CodeCompletionModel::CustomHighlight).toList()); 0150 } 0151 0152 return {}; 0153 }