forked from qt-creator/qt-creator
Locator: Fix diverse issues with drawing highlighted text
To draw the result items with highlighted parts, we split the text to draw into "before highlight", "highlight" and "after highlight", and painted them separately. This had several issues: It breaks the text layout. Characters within a text are often started at subpixels, which was not so visible in the static search results, but lead to ugly artifacts while typing in Locator (enter a search term, and then continue adding characters that still match the first found item, and watch the effect in the "after highlight" part). It needs a lot of custom painting code. Properly supporting text elide modes is hard, scaling to more than one highlight as well. Reusing parts of the QItemDelegate base functions also has its issues, e.g. that clipping doesn't work well. Instead, QItemDelegate::drawDisplay should make it possible to set format ranges for the text it draws. This patch copies part of QItemDelegate to be able to add this parameter. Unfortunately Qt currently has a bug (QTBUG-62019) that character backgrounds are not painted far enough (1 pixel to the right has the wrong background), which looks very ugly in selected items in the search results. So we use the new delegate only for Locator for now, to be used later for the search results too, when that bug is fixed. Task-number: QTCREATORBUG-18532 Change-Id: Idf59b2c2bcfa6b188a810f7a3128a81e7e6fffb1 Reviewed-by: André Hartmann <aha_1980@gmx.de> Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
305
src/libs/utils/highlightingitemdelegate.cpp
Normal file
305
src/libs/utils/highlightingitemdelegate.cpp
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "highlightingitemdelegate.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
const int kMinimumLineNumberDigits = 6;
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
HighlightingItemDelegate::HighlightingItemDelegate(int tabWidth, QObject *parent)
|
||||||
|
: QItemDelegate(parent)
|
||||||
|
{
|
||||||
|
setTabWidth(tabWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightingItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
static const int iconSize = 16;
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
const QStyleOptionViewItem opt = setOptions(index, option);
|
||||||
|
painter->setFont(opt.font);
|
||||||
|
|
||||||
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
|
|
||||||
|
// ---- do the layout
|
||||||
|
QRect checkRect;
|
||||||
|
QRect pixmapRect;
|
||||||
|
QRect textRect;
|
||||||
|
|
||||||
|
// check mark
|
||||||
|
const bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable);
|
||||||
|
Qt::CheckState checkState = Qt::Unchecked;
|
||||||
|
if (checkable) {
|
||||||
|
QVariant checkStateData = index.data(Qt::CheckStateRole);
|
||||||
|
checkState = static_cast<Qt::CheckState>(checkStateData.toInt());
|
||||||
|
checkRect = doCheck(opt, opt.rect, checkStateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// icon
|
||||||
|
const QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>();
|
||||||
|
if (!icon.isNull()) {
|
||||||
|
const QSize size = icon.actualSize(QSize(iconSize, iconSize));
|
||||||
|
pixmapRect = QRect(0, 0, size.width(), size.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
// text
|
||||||
|
textRect = opt.rect.adjusted(0, 0, checkRect.width() + pixmapRect.width(), 0);
|
||||||
|
|
||||||
|
// do layout
|
||||||
|
doLayout(opt, &checkRect, &pixmapRect, &textRect, false);
|
||||||
|
// ---- draw the items
|
||||||
|
// icon
|
||||||
|
if (!icon.isNull())
|
||||||
|
icon.paint(painter, pixmapRect, option.decorationAlignment);
|
||||||
|
|
||||||
|
// line numbers
|
||||||
|
const int lineNumberAreaWidth = drawLineNumber(painter, opt, textRect, index);
|
||||||
|
textRect.adjust(lineNumberAreaWidth, 0, 0, 0);
|
||||||
|
|
||||||
|
// text and focus/selection
|
||||||
|
drawText(painter, opt, textRect, index);
|
||||||
|
QItemDelegate::drawFocus(painter, opt, opt.rect);
|
||||||
|
|
||||||
|
// check mark
|
||||||
|
if (checkable)
|
||||||
|
QItemDelegate::drawCheck(painter, opt, checkRect, checkState);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightingItemDelegate::setTabWidth(int width)
|
||||||
|
{
|
||||||
|
m_tabString = QString(width, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the width of the line number area
|
||||||
|
int HighlightingItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QRect &rect,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
static const int lineNumberAreaHorizontalPadding = 4;
|
||||||
|
const int lineNumber = index.model()->data(index, int(HighlightingItemRole::LineNumber)).toInt();
|
||||||
|
if (lineNumber < 1)
|
||||||
|
return 0;
|
||||||
|
const bool isSelected = option.state & QStyle::State_Selected;
|
||||||
|
const QString lineText = QString::number(lineNumber);
|
||||||
|
const int minimumLineNumberDigits = qMax(kMinimumLineNumberDigits, lineText.count());
|
||||||
|
const int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, '0'));
|
||||||
|
const int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth
|
||||||
|
+ lineNumberAreaHorizontalPadding;
|
||||||
|
QRect lineNumberAreaRect(rect);
|
||||||
|
lineNumberAreaRect.setWidth(lineNumberAreaWidth);
|
||||||
|
|
||||||
|
QPalette::ColorGroup cg = QPalette::Normal;
|
||||||
|
if (!(option.state & QStyle::State_Active))
|
||||||
|
cg = QPalette::Inactive;
|
||||||
|
else if (!(option.state & QStyle::State_Enabled))
|
||||||
|
cg = QPalette::Disabled;
|
||||||
|
|
||||||
|
painter->fillRect(lineNumberAreaRect, QBrush(isSelected ?
|
||||||
|
option.palette.brush(cg, QPalette::Highlight) :
|
||||||
|
option.palette.color(cg, QPalette::Base).darker(111)));
|
||||||
|
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||||
|
opt.palette.setColor(cg, QPalette::Text, Qt::darkGray);
|
||||||
|
|
||||||
|
const QStyle *style = QApplication::style();
|
||||||
|
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
|
||||||
|
|
||||||
|
const QRect rowRect
|
||||||
|
= lineNumberAreaRect.adjusted(-textMargin, 0,
|
||||||
|
textMargin - lineNumberAreaHorizontalPadding, 0);
|
||||||
|
QItemDelegate::drawDisplay(painter, opt, rowRect, lineText);
|
||||||
|
|
||||||
|
return lineNumberAreaWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightingItemDelegate::drawText(QPainter *painter,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QRect &rect,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QString text = index.model()->data(index, Qt::DisplayRole).toString();
|
||||||
|
// show number of subresults in displayString
|
||||||
|
if (index.model()->hasChildren(index))
|
||||||
|
text += " (" + QString::number(index.model()->rowCount(index)) + ')';
|
||||||
|
|
||||||
|
int searchTermStart = index.model()->data(index, int(HighlightingItemRole::StartColumn)).toInt();
|
||||||
|
int searchTermLength = index.model()->data(index, int(HighlightingItemRole::Length)).toInt();
|
||||||
|
if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
|
||||||
|
drawDisplay(painter, option, rect, text.replace('\t', m_tabString), {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace tabs with searchTerm bookkeeping
|
||||||
|
int searchTermEnd = searchTermStart + searchTermLength;
|
||||||
|
const int tabDiff = m_tabString.size() - 1;
|
||||||
|
for (int i = 0; i < text.length(); i++) {
|
||||||
|
if (text.at(i) == '\t') {
|
||||||
|
text.replace(i, 1, m_tabString);
|
||||||
|
if (i < searchTermStart) {
|
||||||
|
searchTermStart += tabDiff;
|
||||||
|
searchTermEnd += tabDiff;
|
||||||
|
} else if (i < searchTermEnd) {
|
||||||
|
searchTermEnd += tabDiff;
|
||||||
|
searchTermLength += tabDiff;
|
||||||
|
}
|
||||||
|
i += tabDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QColor highlightForeground =
|
||||||
|
index.model()->data(index, int(HighlightingItemRole::Foreground)).value<QColor>();
|
||||||
|
const QColor highlightBackground =
|
||||||
|
index.model()->data(index, int(HighlightingItemRole::Background)).value<QColor>();
|
||||||
|
QTextCharFormat highlightFormat;
|
||||||
|
highlightFormat.setForeground(highlightForeground);
|
||||||
|
highlightFormat.setBackground(highlightBackground);
|
||||||
|
|
||||||
|
drawDisplay(painter, option, rect, text, {{searchTermStart, searchTermLength, highlightFormat}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from QItemDelegate for drawDisplay
|
||||||
|
static QString replaceNewLine(QString text)
|
||||||
|
{
|
||||||
|
static const QChar nl = '\n';
|
||||||
|
for (int i = 0; i < text.count(); ++i)
|
||||||
|
if (text.at(i) == nl)
|
||||||
|
text[i] = QChar::LineSeparator;
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from QItemDelegate for drawDisplay
|
||||||
|
QSizeF doTextLayout(QTextLayout *textLayout, int lineWidth)
|
||||||
|
{
|
||||||
|
qreal height = 0;
|
||||||
|
qreal widthUsed = 0;
|
||||||
|
textLayout->beginLayout();
|
||||||
|
while (true) {
|
||||||
|
QTextLine line = textLayout->createLine();
|
||||||
|
if (!line.isValid())
|
||||||
|
break;
|
||||||
|
line.setLineWidth(lineWidth);
|
||||||
|
line.setPosition(QPointF(0, height));
|
||||||
|
height += line.height();
|
||||||
|
widthUsed = qMax(widthUsed, line.naturalTextWidth());
|
||||||
|
}
|
||||||
|
textLayout->endLayout();
|
||||||
|
return QSizeF(widthUsed, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from QItemDelegate to be able to add the 'format' parameter
|
||||||
|
void HighlightingItemDelegate::drawDisplay(QPainter *painter,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QRect &rect, const QString &text,
|
||||||
|
const QVector<QTextLayout::FormatRange> &format) const
|
||||||
|
{
|
||||||
|
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
|
||||||
|
? QPalette::Normal : QPalette::Disabled;
|
||||||
|
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
|
||||||
|
cg = QPalette::Inactive;
|
||||||
|
if (option.state & QStyle::State_Selected) {
|
||||||
|
painter->fillRect(rect, option.palette.brush(cg, QPalette::Highlight));
|
||||||
|
painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
|
||||||
|
} else {
|
||||||
|
painter->setPen(option.palette.color(cg, QPalette::Text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (option.state & QStyle::State_Editing) {
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(option.palette.color(cg, QPalette::Text));
|
||||||
|
painter->drawRect(rect.adjusted(0, 0, -1, -1));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStyleOptionViewItem opt = option;
|
||||||
|
|
||||||
|
const QWidget *widget = option.widget;
|
||||||
|
QStyle *style = widget ? widget->style() : QApplication::style();
|
||||||
|
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
|
||||||
|
QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
|
||||||
|
const bool wrapText = opt.features & QStyleOptionViewItem::WrapText;
|
||||||
|
QTextOption textOption;
|
||||||
|
textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
|
||||||
|
textOption.setTextDirection(option.direction);
|
||||||
|
textOption.setAlignment(QStyle::visualAlignment(option.direction, option.displayAlignment));
|
||||||
|
QTextLayout textLayout;
|
||||||
|
textLayout.setTextOption(textOption);
|
||||||
|
textLayout.setFont(option.font);
|
||||||
|
textLayout.setText(replaceNewLine(text));
|
||||||
|
|
||||||
|
QSizeF textLayoutSize = doTextLayout(&textLayout, textRect.width());
|
||||||
|
|
||||||
|
if (textRect.width() < textLayoutSize.width()
|
||||||
|
|| textRect.height() < textLayoutSize.height()) {
|
||||||
|
QString elided;
|
||||||
|
int start = 0;
|
||||||
|
int end = text.indexOf(QChar::LineSeparator, start);
|
||||||
|
if (end == -1) {
|
||||||
|
elided += option.fontMetrics.elidedText(text, option.textElideMode, textRect.width());
|
||||||
|
} else {
|
||||||
|
while (end != -1) {
|
||||||
|
elided += option.fontMetrics.elidedText(text.mid(start, end - start),
|
||||||
|
option.textElideMode, textRect.width());
|
||||||
|
elided += QChar::LineSeparator;
|
||||||
|
start = end + 1;
|
||||||
|
end = text.indexOf(QChar::LineSeparator, start);
|
||||||
|
}
|
||||||
|
// let's add the last line (after the last QChar::LineSeparator)
|
||||||
|
elided += option.fontMetrics.elidedText(text.mid(start),
|
||||||
|
option.textElideMode, textRect.width());
|
||||||
|
}
|
||||||
|
textLayout.setText(elided);
|
||||||
|
textLayoutSize = doTextLayout(&textLayout, textRect.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
const QSize layoutSize(textRect.width(), int(textLayoutSize.height()));
|
||||||
|
const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment,
|
||||||
|
layoutSize, textRect);
|
||||||
|
// if we still overflow even after eliding the text, enable clipping
|
||||||
|
if (!hasClipping() && (textRect.width() < textLayoutSize.width()
|
||||||
|
|| textRect.height() < textLayoutSize.height())) {
|
||||||
|
painter->save();
|
||||||
|
painter->setClipRect(layoutRect);
|
||||||
|
textLayout.draw(painter, layoutRect.topLeft(), format, layoutRect);
|
||||||
|
painter->restore();
|
||||||
|
} else {
|
||||||
|
textLayout.draw(painter, layoutRect.topLeft(), format, layoutRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Utils
|
61
src/libs/utils/highlightingitemdelegate.h
Normal file
61
src/libs/utils/highlightingitemdelegate.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include <QItemDelegate>
|
||||||
|
#include <QTextLayout>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
enum class HighlightingItemRole {
|
||||||
|
LineNumber = Qt::UserRole,
|
||||||
|
StartColumn,
|
||||||
|
Length,
|
||||||
|
Foreground,
|
||||||
|
Background,
|
||||||
|
User
|
||||||
|
};
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT HighlightingItemDelegate : public QItemDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HighlightingItemDelegate(int tabWidth, QObject *parent = 0);
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||||
|
void setTabWidth(int width);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const;
|
||||||
|
void drawText(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QRect &rect, const QModelIndex &index) const;
|
||||||
|
using QItemDelegate::drawDisplay;
|
||||||
|
void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect,
|
||||||
|
const QString &text, const QVector<QTextLayout::FormatRange> &format) const;
|
||||||
|
QString m_tabString;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Utils
|
@@ -113,7 +113,8 @@ SOURCES += $$PWD/environment.cpp \
|
|||||||
$$PWD/port.cpp \
|
$$PWD/port.cpp \
|
||||||
$$PWD/runextensions.cpp \
|
$$PWD/runextensions.cpp \
|
||||||
$$PWD/utilsicons.cpp \
|
$$PWD/utilsicons.cpp \
|
||||||
$$PWD/guard.cpp
|
$$PWD/guard.cpp \
|
||||||
|
$$PWD/highlightingitemdelegate.cpp
|
||||||
|
|
||||||
win32:SOURCES += $$PWD/consoleprocess_win.cpp
|
win32:SOURCES += $$PWD/consoleprocess_win.cpp
|
||||||
else:SOURCES += $$PWD/consoleprocess_unix.cpp
|
else:SOURCES += $$PWD/consoleprocess_unix.cpp
|
||||||
@@ -239,8 +240,9 @@ HEADERS += \
|
|||||||
$$PWD/asconst.h \
|
$$PWD/asconst.h \
|
||||||
$$PWD/smallstringfwd.h \
|
$$PWD/smallstringfwd.h \
|
||||||
$$PWD/optional.h \
|
$$PWD/optional.h \
|
||||||
|
$$PWD/../3rdparty/optional/optional.hpp \
|
||||||
$$PWD/qtcfallthrough.h \
|
$$PWD/qtcfallthrough.h \
|
||||||
$$PWD/../3rdparty/optional/optional.hpp
|
$$PWD/highlightingitemdelegate.cpp
|
||||||
|
|
||||||
FORMS += $$PWD/filewizardpage.ui \
|
FORMS += $$PWD/filewizardpage.ui \
|
||||||
$$PWD/projectintropage.ui \
|
$$PWD/projectintropage.ui \
|
||||||
|
@@ -117,6 +117,8 @@ Project {
|
|||||||
"functiontraits.h",
|
"functiontraits.h",
|
||||||
"guard.cpp",
|
"guard.cpp",
|
||||||
"guard.h",
|
"guard.h",
|
||||||
|
"highlightingitemdelegate.cpp",
|
||||||
|
"highlightingitemdelegate.h",
|
||||||
"historycompleter.cpp",
|
"historycompleter.cpp",
|
||||||
"historycompleter.h",
|
"historycompleter.h",
|
||||||
"hostosinfo.h",
|
"hostosinfo.h",
|
||||||
|
@@ -33,14 +33,13 @@
|
|||||||
#include <coreplugin/modemanager.h>
|
#include <coreplugin/modemanager.h>
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <coreplugin/fileiconprovider.h>
|
#include <coreplugin/fileiconprovider.h>
|
||||||
#include <coreplugin/find/searchresulttreeitemdelegate.h>
|
|
||||||
#include <coreplugin/find/searchresulttreeitemroles.h>
|
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
#include <coreplugin/mainwindow.h>
|
#include <coreplugin/mainwindow.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/appmainwindow.h>
|
#include <utils/appmainwindow.h>
|
||||||
#include <utils/asconst.h>
|
#include <utils/asconst.h>
|
||||||
#include <utils/fancylineedit.h>
|
#include <utils/fancylineedit.h>
|
||||||
|
#include <utils/highlightingitemdelegate.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/itemviews.h>
|
#include <utils/itemviews.h>
|
||||||
#include <utils/progressindicator.h>
|
#include <utils/progressindicator.h>
|
||||||
@@ -67,6 +66,10 @@
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(Core::LocatorFilterEntry)
|
Q_DECLARE_METATYPE(Core::LocatorFilterEntry)
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
const int LocatorEntryRole = int(HighlightingItemRole::User);
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -99,7 +102,7 @@ private:
|
|||||||
QColor mBackgroundColor;
|
QColor mBackgroundColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CompletionDelegate : public SearchResultTreeItemDelegate
|
class CompletionDelegate : public HighlightingItemDelegate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompletionDelegate(QObject *parent);
|
CompletionDelegate(QObject *parent);
|
||||||
@@ -193,7 +196,6 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
|
|||||||
+ QLatin1String("\n\n") + mEntries.at(index.row()).extraInfo);
|
+ QLatin1String("\n\n") + mEntries.at(index.row()).extraInfo);
|
||||||
break;
|
break;
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
case ItemDataRoles::ResultIconRole:
|
|
||||||
if (index.column() == DisplayNameColumn) {
|
if (index.column() == DisplayNameColumn) {
|
||||||
LocatorFilterEntry &entry = mEntries[index.row()];
|
LocatorFilterEntry &entry = mEntries[index.row()];
|
||||||
if (!entry.displayIcon && !entry.fileName.isEmpty())
|
if (!entry.displayIcon && !entry.fileName.isEmpty())
|
||||||
@@ -205,21 +207,21 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
|
|||||||
if (index.column() == ExtraInfoColumn)
|
if (index.column() == ExtraInfoColumn)
|
||||||
return QColor(Qt::darkGray);
|
return QColor(Qt::darkGray);
|
||||||
break;
|
break;
|
||||||
case ItemDataRoles::ResultItemRole:
|
case LocatorEntryRole:
|
||||||
return qVariantFromValue(mEntries.at(index.row()));
|
return qVariantFromValue(mEntries.at(index.row()));
|
||||||
case ItemDataRoles::ResultBeginColumnNumberRole:
|
case int(HighlightingItemRole::StartColumn):
|
||||||
case ItemDataRoles::SearchTermLengthRole: {
|
case int(HighlightingItemRole::Length): {
|
||||||
LocatorFilterEntry &entry = mEntries[index.row()];
|
LocatorFilterEntry &entry = mEntries[index.row()];
|
||||||
const int highlightColumn = entry.highlightInfo.dataType == LocatorFilterEntry::HighlightInfo::DisplayName
|
const int highlightColumn = entry.highlightInfo.dataType == LocatorFilterEntry::HighlightInfo::DisplayName
|
||||||
? DisplayNameColumn
|
? DisplayNameColumn
|
||||||
: ExtraInfoColumn;
|
: ExtraInfoColumn;
|
||||||
if (highlightColumn == index.column()) {
|
if (highlightColumn == index.column()) {
|
||||||
const bool startIndexRole = role == ItemDataRoles::ResultBeginColumnNumberRole;
|
const bool startIndexRole = role == int(HighlightingItemRole::StartColumn);
|
||||||
return startIndexRole ? entry.highlightInfo.startIndex : entry.highlightInfo.length;
|
return startIndexRole ? entry.highlightInfo.startIndex : entry.highlightInfo.length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ItemDataRoles::ResultHighlightBackgroundColor:
|
case int(HighlightingItemRole::Background):
|
||||||
return mBackgroundColor;
|
return mBackgroundColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -843,7 +845,7 @@ void LocatorWidget::acceptEntry(int row)
|
|||||||
const QModelIndex index = m_locatorModel->index(row, 0);
|
const QModelIndex index = m_locatorModel->index(row, 0);
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
const LocatorFilterEntry entry = m_locatorModel->data(index, ItemDataRoles::ResultItemRole).value<LocatorFilterEntry>();
|
const LocatorFilterEntry entry = m_locatorModel->data(index, LocatorEntryRole).value<LocatorFilterEntry>();
|
||||||
Q_ASSERT(entry.filter != nullptr);
|
Q_ASSERT(entry.filter != nullptr);
|
||||||
QString newText;
|
QString newText;
|
||||||
int selectionStart = -1;
|
int selectionStart = -1;
|
||||||
@@ -926,13 +928,13 @@ LocatorPopup *createLocatorPopup(Locator *locator, QWidget *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompletionDelegate::CompletionDelegate(QObject *parent)
|
CompletionDelegate::CompletionDelegate(QObject *parent)
|
||||||
: SearchResultTreeItemDelegate(0, parent)
|
: HighlightingItemDelegate(0, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize CompletionDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
QSize CompletionDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
return SearchResultTreeItemDelegate::sizeHint(option, index) + QSize(0, 2);
|
return HighlightingItemDelegate::sizeHint(option, index) + QSize(0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user