File indexing completed on 2024-04-28 03:57:22

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "expandingwidgetmodel.h"
0008 
0009 #include <QApplication>
0010 #include <QBrush>
0011 #include <QModelIndex>
0012 #include <QTextEdit>
0013 #include <QTreeView>
0014 
0015 #include <KColorUtils>
0016 #include <ktexteditor/codecompletionmodel.h>
0017 
0018 #include "katepartdebug.h"
0019 
0020 using namespace KTextEditor;
0021 
0022 inline QModelIndex firstColumn(const QModelIndex &index)
0023 {
0024     return index.sibling(index.row(), 0);
0025 }
0026 
0027 ExpandingWidgetModel::ExpandingWidgetModel(QWidget *parent)
0028     : QAbstractItemModel(parent)
0029 {
0030 }
0031 
0032 ExpandingWidgetModel::~ExpandingWidgetModel()
0033 {
0034 }
0035 
0036 static QColor doAlternate(const QColor &color)
0037 {
0038     QColor background = QApplication::palette().window().color();
0039     return KColorUtils::mix(color, background, 0.15);
0040 }
0041 
0042 uint ExpandingWidgetModel::matchColor(const QModelIndex &index) const
0043 {
0044     int matchQuality = contextMatchQuality(index.sibling(index.row(), 0));
0045 
0046     if (matchQuality > 0) {
0047         bool alternate = index.row() & 1;
0048 
0049         QColor badMatchColor(0xff00aa44); // Blue-ish green
0050         QColor goodMatchColor(0xff00ff00); // Green
0051 
0052         QColor background = treeView()->palette().light().color();
0053 
0054         QColor totalColor = KColorUtils::mix(badMatchColor, goodMatchColor, ((float)matchQuality) / 10.0);
0055 
0056         if (alternate) {
0057             totalColor = doAlternate(totalColor);
0058         }
0059 
0060         const qreal dynamicTint = 0.2;
0061         const qreal minimumTint = 0.2;
0062         qreal tintStrength = (dynamicTint * matchQuality) / 10;
0063         if (tintStrength != 0.0) {
0064             tintStrength += minimumTint; // Some minimum tinting strength, else it's not visible any more
0065         }
0066 
0067         return KColorUtils::tint(background, totalColor, tintStrength).rgb();
0068     } else {
0069         return 0;
0070     }
0071 }
0072 
0073 QVariant ExpandingWidgetModel::data(const QModelIndex &index, int role) const
0074 {
0075     switch (role) {
0076     case Qt::BackgroundRole: {
0077         if (index.column() == 0) {
0078             // Highlight by match-quality
0079             uint color = matchColor(index);
0080             if (color) {
0081                 return QBrush(color);
0082             }
0083         }
0084     }
0085     }
0086     return QVariant();
0087 }
0088 
0089 QList<QVariant> mergeCustomHighlighting(int leftSize, const QList<QVariant> &left, int rightSize, const QList<QVariant> &right)
0090 {
0091     QList<QVariant> ret = left;
0092     if (left.isEmpty()) {
0093         ret << QVariant(0);
0094         ret << QVariant(leftSize);
0095         ret << QTextFormat(QTextFormat::CharFormat);
0096     }
0097 
0098     if (right.isEmpty()) {
0099         ret << QVariant(leftSize);
0100         ret << QVariant(rightSize);
0101         ret << QTextFormat(QTextFormat::CharFormat);
0102     } else {
0103         QList<QVariant>::const_iterator it = right.constBegin();
0104         while (it != right.constEnd()) {
0105             {
0106                 QList<QVariant>::const_iterator testIt = it;
0107                 for (int a = 0; a < 2; a++) {
0108                     ++testIt;
0109                     if (testIt == right.constEnd()) {
0110                         qCWarning(LOG_KTE) << "Length of input is not multiple of 3";
0111                         break;
0112                     }
0113                 }
0114             }
0115 
0116             ret << QVariant((*it).toInt() + leftSize);
0117             ++it;
0118             ret << QVariant((*it).toInt());
0119             ++it;
0120             ret << *it;
0121             if (!(*it).value<QTextFormat>().isValid()) {
0122                 qCDebug(LOG_KTE) << "Text-format is invalid";
0123             }
0124             ++it;
0125         }
0126     }
0127     return ret;
0128 }
0129 
0130 // It is assumed that between each two strings, one space is inserted
0131 QList<QVariant> mergeCustomHighlighting(QStringList strings, QList<QVariantList> highlights, int grapBetweenStrings)
0132 {
0133     if (strings.isEmpty()) {
0134         qCWarning(LOG_KTE) << "List of strings is empty";
0135         return QList<QVariant>();
0136     }
0137 
0138     if (highlights.isEmpty()) {
0139         qCWarning(LOG_KTE) << "List of highlightings is empty";
0140         return QList<QVariant>();
0141     }
0142 
0143     if (strings.count() != highlights.count()) {
0144         qCWarning(LOG_KTE) << "Length of string-list is " << strings.count() << " while count of highlightings is " << highlights.count() << ", should be same";
0145         return QList<QVariant>();
0146     }
0147 
0148     // Merge them together
0149     QString totalString = strings[0];
0150     QVariantList totalHighlighting = highlights[0];
0151 
0152     strings.pop_front();
0153     highlights.pop_front();
0154 
0155     while (!strings.isEmpty()) {
0156         totalHighlighting = mergeCustomHighlighting(totalString.length(), totalHighlighting, strings[0].length(), highlights[0]);
0157         totalString += strings[0];
0158 
0159         for (int a = 0; a < grapBetweenStrings; a++) {
0160             totalString += QLatin1Char(' ');
0161         }
0162 
0163         strings.pop_front();
0164         highlights.pop_front();
0165     }
0166     // Combine the custom-highlightings
0167     return totalHighlighting;
0168 }