~adamreichold/qpdfview/trunk

1840 by Adam Reichold
Move the search item delegate into a separate module.
1
/*
2
2073 by Adam Reichold
Fix highlighting of matched text when part of it is elided and silence unused argument warning.
3
Copyright 2018 S. Razi Alavizadeh
1840 by Adam Reichold
Move the search item delegate into a separate module.
4
Copyright 2015 Adam Reichold
5
6
This file is part of qpdfview.
7
8
qpdfview is free software: you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation, either version 2 of the License, or
11
(at your option) any later version.
12
13
qpdfview is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
18
You should have received a copy of the GNU General Public License
19
along with qpdfview.  If not, see <http://www.gnu.org/licenses/>.
20
21
*/
22
23
#include "searchitemdelegate.h"
24
25
#include <QApplication>
26
#include <qmath.h>
27
#include <QPainter>
28
#include <QTextLayout>
29
30
#include "searchmodel.h"
31
32
namespace qpdfview
33
{
34
35
SearchItemDelegate::SearchItemDelegate(QObject* parent) : QStyledItemDelegate(parent)
36
{
37
}
38
39
void SearchItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
40
{
41
    QStyledItemDelegate::paint(painter, option, index);
42
2053 by Adam Reichold
Use a second column in the extend search results view to display the result count and the occurence page.
43
    if(index.column() != 0)
44
    {
45
        return;
46
    }
47
1840 by Adam Reichold
Move the search item delegate into a separate module.
48
    const int progress = index.data(SearchModel::ProgressRole).toInt();
49
50
    if(progress != 0)
51
    {
52
        paintProgress(painter, option, progress);
53
        return;
54
    }
55
56
    const QString matchedText = index.data(SearchModel::MatchedTextRole).toString();
57
    const QString surroundingText = index.data(SearchModel::SurroundingTextRole).toString();
58
59
    if(!matchedText.isEmpty() && !surroundingText.isEmpty())
60
    {
61
        paintText(painter, option, matchedText, surroundingText);
62
        return;
63
    }
64
}
65
66
void SearchItemDelegate::paintProgress(QPainter* painter, const QStyleOptionViewItem& option,
67
                                       int progress) const
68
{
69
    QRect highlightedRect = option.rect;
70
    highlightedRect.setWidth(progress * highlightedRect.width() / 100);
71
72
    painter->save();
73
74
    painter->setCompositionMode(QPainter::CompositionMode_Multiply);
75
    painter->fillRect(highlightedRect, option.palette.highlight());
76
77
    painter->restore();
78
}
79
80
void SearchItemDelegate::paintText(QPainter* painter, const QStyleOptionViewItem& option,
81
                                   const QString& matchedText, const QString& surroundingText) const
82
{
83
    const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
84
    const QRect textRect = option.rect.adjusted(textMargin, 0, -textMargin, 0);
85
    const QString elidedText = option.fontMetrics.elidedText(surroundingText, option.textElideMode, textRect.width());
86
87
    QTextOption textOption;
88
    textOption.setWrapMode(QTextOption::NoWrap);
89
    textOption.setTextDirection(elidedText.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight);
90
    textOption.setAlignment(QStyle::visualAlignment(textOption.textDirection(), option.displayAlignment));
91
92
    QTextLayout textLayout;
93
    textLayout.setTextOption(textOption);
94
    textLayout.setText(elidedText);
95
    textLayout.setFont(option.font);
96
97
    QFont font = textLayout.font();
98
    font.setWeight(QFont::Light);
99
    textLayout.setFont(font);
100
101
102
    QList< QTextLayout::FormatRange > additionalFormats;
103
2073 by Adam Reichold
Fix highlighting of matched text when part of it is elided and silence unused argument warning.
104
    for(int index = 0; (index = surroundingText.indexOf(matchedText, index)) != -1; index += matchedText.length())
1840 by Adam Reichold
Move the search item delegate into a separate module.
105
    {
106
        QTextLayout::FormatRange formatRange;
107
        formatRange.start = index;
108
        formatRange.length = matchedText.length();
109
        formatRange.format.setFontWeight(QFont::Bold);
110
111
        additionalFormats.append(formatRange);
112
    }
113
114
    textLayout.setAdditionalFormats(additionalFormats);
115
116
117
    textLayout.beginLayout();
118
119
    QTextLine textLine = textLayout.createLine();
120
121
    if(!textLine.isValid())
122
    {
123
        return;
124
    }
125
126
    textLine.setLineWidth(textRect.width());
127
128
    textLayout.endLayout();
129
130
131
    const QSize layoutSize(textRect.width(), qFloor(textLine.height()));
132
    const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment, layoutSize, textRect);
133
134
    painter->save();
135
136
    painter->setClipping(true);
137
    painter->setClipRect(layoutRect);
138
139
    textLine.draw(painter, layoutRect.topLeft());
140
141
    painter->restore();
142
}
143
144
} // qpdfview