代码拉取完成,页面将自动刷新
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "colorpreviewhoverhandler.h"
#include "texteditor.h"
#include <coreplugin/icore.h>
#include <utils/executeondestruction.h>
#include <utils/tooltip/tooltip.h>
#include <utils/qtcassert.h>
#include <QPoint>
#include <QColor>
#include <QTextBlock>
using namespace Core;
namespace TextEditor {
/*
* Attempts to find a color string such as "#112233" from the word at
* the given position in the string. Also looks for "Qt::" for recognizing
* Qt::GlobalColor types (although there cannot be any spaces such as
* "Qt:: yellow")
*/
static QString extractColorString(const QString &s, int pos)
{
if (s.length() < 3 || pos < 0 || pos >= s.length())
return QString();
int firstPos = pos;
do {
QChar c = s[firstPos];
if (c == QLatin1Char('#'))
break;
if (c == QLatin1Char(':')
&& (firstPos > 3)
&& (s.mid(firstPos-3, 4) == QLatin1String("Qt::"))) {
firstPos -= 3;
break;
}
if (!c.isLetterOrNumber())
return QString();
--firstPos;
} while (firstPos >= 0);
if (firstPos < 0)
return QString();
int lastPos = firstPos + 1;
do {
QChar c = s[lastPos];
if (!(c.isLetterOrNumber() || c == QLatin1Char(':')))
break;
lastPos++;
} while (lastPos < s.length());
return s.mid(firstPos, lastPos - firstPos);
}
static QColor fromEnumString(const QString &s)
{
const struct EnumColorMap {
QLatin1String name;
QColor color;
} table[] = {
{QLatin1String("white") , QColor(Qt::white)},
{QLatin1String("black"), QColor(Qt::black)},
{QLatin1String("red"), QColor(Qt::red)},
{QLatin1String("darkRed"), QColor(Qt::darkRed)},
{QLatin1String("green"), QColor(Qt::green)},
{QLatin1String("darkGreen"), QColor(Qt::darkGreen)},
{QLatin1String("blue"), QColor(Qt::blue)},
{QLatin1String("darkBlue"), QColor(Qt::darkBlue)},
{QLatin1String("cyan"), QColor(Qt::cyan)},
{QLatin1String("darkCyan"), QColor(Qt::darkCyan)},
{QLatin1String("magenta"), QColor(Qt::magenta)},
{QLatin1String("darkMagenta"), QColor(Qt::darkMagenta)},
{QLatin1String("yellow"), QColor(Qt::yellow)},
{QLatin1String("darkYellow"), QColor(Qt::darkYellow)},
{QLatin1String("gray"), QColor(Qt::gray)},
{QLatin1String("darkGray"), QColor(Qt::darkGray)},
{QLatin1String("lightGray"), QColor(Qt::lightGray)},
{QLatin1String("transparent"), QColor(Qt::transparent)}
};
for (const auto &enumColor : table) {
if (s == enumColor.name)
return enumColor.color;
}
return QColor();
}
static QColor checkColorText(const QString &str)
{
if (str.startsWith(QLatin1Char('#')))
return QColor(str);
if (str.startsWith(QLatin1String("Qt::"))) {
QString colorStr = str;
colorStr.remove(0, 4);
return fromEnumString(colorStr);
}
return QColor();
}
// looks backwards through a string for the opening brace of a function
static int findOpeningBrace(const QString &s, int startIndex)
{
QTC_ASSERT(startIndex >= 0 && startIndex <= s.length(), return -1);
int index = startIndex == s.length() ? startIndex - 1 : startIndex;
while (index > 0) {
const QChar c = s[index];
if (c == QLatin1Char('(') || c == QLatin1Char('{'))
return index;
--index;
}
return index;
}
static int findClosingBrace(const QString &s, int startIndex)
{
QTC_ASSERT(startIndex >= 0 && startIndex <= s.length(), return -1);
int index = startIndex == s.length() ? startIndex - 1 : startIndex;
const int len = s.length();
while (index < len) {
const QChar c = s[index];
if (c == QLatin1Char(')') || c == QLatin1Char('}'))
return index;
++index;
}
return -1;
}
// returns the index of the first character of the func, or negative if not valid
static int findFuncStart(const QString &s, int startIndex)
{
QTC_ASSERT(startIndex >= 0 && startIndex <= s.length(), return -1);
int index = startIndex == s.length() ? startIndex - 1 : startIndex;
while (index >= 0) {
const QChar c = s[index];
if (!c.isLetterOrNumber()) {
if (index == startIndex)
return -1;
return qMin(index + 1, startIndex);
}
--index;
}
return index;
}
static QString removeWhitespace(const QString &s)
{
QString ret;
ret.reserve(s.size());
for (QChar c : s) {
if (!c.isSpace())
ret += c;
}
return ret;
}
/*
* Parses the string looking for a function and its arguments.
* The starting position is assumed to be within the braces.
*/
static bool extractFuncAndArgs(const QString &s,
int pos,
QString &retFuncName,
QStringList &retArgs)
{
int openBrace = findOpeningBrace(s, pos);
if (openBrace <= 0)
return false;
int closeBrace = findClosingBrace(s, openBrace + 1);
if (closeBrace < 0)
return false;
int funcEnd = openBrace - 1;
int funcStart = findFuncStart(s, funcEnd);
if (funcStart < 0 || funcEnd <= funcStart)
return false;
retFuncName = removeWhitespace(s.mid(funcStart, funcEnd - funcStart + 1));
QString argStr = s.mid(openBrace + 1, closeBrace - openBrace - 1);
retArgs = argStr.split(',');
return true;
}
static QColor::Spec specForFunc(const QString &func)
{
if ((func == QLatin1String("QColor"))
|| (func == QLatin1String("QRgb"))
|| (func == QLatin1String("rgb"))
|| func.startsWith(QLatin1String("setRgb"))
|| func.startsWith(QLatin1String("setRgba"))){
return QColor::Rgb;
}
if (func.startsWith(QLatin1String("setCmyk")))
return QColor::Cmyk;
if (func.startsWith(QLatin1String("setHsv")))
return QColor::Hsv;
if (func.startsWith(QLatin1String("setHsl")))
return QColor::Hsv;
return QColor::Invalid;
}
static QColor colorFromArgs(const QStringList &args, QColor::Spec spec)
{
const int maxArgs = 5;
int vals[maxArgs];
vals[3] = 0xff;
vals[4] = 0xff;
bool allOk = true;
for (int ii = 0; ii < qMin(args.size(), maxArgs); ++ii) {
bool ok;
vals[ii] = args[ii].toInt(&ok, 0);
allOk &= ok;
}
if (!allOk)
return QColor();
QColor c;
switch (spec) {
case QColor::Rgb:
c.setRgb(vals[0], vals[1], vals[2], vals[3]);
break;
case QColor::Cmyk:
c.setCmyk(vals[0], vals[1], vals[2], vals[3], vals[4]);
break;
case QColor::Hsv:
c.setHsv(vals[0], vals[1], vals[2], vals[3]);
break;
case QColor::Hsl:
c.setHsl(vals[0], vals[1], vals[2], vals[3]);
break;
default:
break;
}
return c;
}
static QColor colorFromArgsF(const QStringList &args, QColor::Spec spec)
{
const int maxArgs = 5;
qreal vals[maxArgs];
vals[3] = 1.0;
vals[4] = 1.0;
bool allOk = true;
for (int ii = 0; ii < qMin(args.size(), maxArgs); ++ii) {
bool ok;
vals[ii] = args[ii].toDouble(&ok);
allOk &= ok;
}
if (!allOk)
return QColor();
QColor c;
switch (spec) {
case QColor::Rgb:
c.setRgbF(vals[0], vals[1], vals[2], vals[3]);
break;
case QColor::Cmyk:
c.setCmykF(vals[0], vals[1], vals[2], vals[3], vals[4]);
break;
case QColor::Hsv:
c.setHsvF(vals[0], vals[1], vals[2], vals[3]);
break;
case QColor::Hsl:
c.setHslF(vals[0], vals[1], vals[2], vals[3]);
break;
default:
break;
}
return c;
}
static QColor colorFromFuncAndArgs(const QString &func, const QStringList &args)
{
if (args.isEmpty())
return QColor();
if (args.size() < 3) {
QString arg0 = removeWhitespace(args[0]);
arg0.remove(QLatin1Char('\"'));
if (func == QLatin1String("setNamedColor"))
return QColor(arg0);
if (arg0.startsWith(QLatin1Char('#')))
return QColor(arg0);
if (arg0.startsWith(QLatin1String("Qt::"))) {
arg0.remove(0, 4);
return fromEnumString(arg0);
}
return QColor();
}
QColor::Spec spec = specForFunc(func);
if (spec == QColor::Invalid)
return QColor();
if (func.endsWith(QLatin1Char('F')))
return colorFromArgsF(args, spec);
return colorFromArgs(args, spec);
}
void ColorPreviewHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
int pos,
ReportPriority report)
{
Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); });
if (editorWidget->extraSelectionTooltip(pos).isEmpty()) {
const QTextBlock tb = editorWidget->document()->findBlock(pos);
const int tbpos = pos - tb.position();
const QString tbtext = tb.text();
QString colorString = extractColorString(tbtext, tbpos);
m_colorTip = checkColorText(colorString);
if (!m_colorTip.isValid()) {
QString funcName;
QStringList args;
if (extractFuncAndArgs(tbtext, tbpos, funcName, args))
m_colorTip = colorFromFuncAndArgs(funcName, args);
}
setPriority(m_colorTip.isValid() ? Priority_Help - 1 : Priority_None);
}
}
void ColorPreviewHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoint &point)
{
if (m_colorTip.isValid())
Utils::ToolTip::show(point, m_colorTip, editorWidget);
else
Utils::ToolTip::hide();
}
} // namespace TextEditor
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。