1/*
2 SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "katetextpreview.h"
8#include "kateconfig.h"
9#include "katedocument.h"
10#include "katelayoutcache.h"
11#include "katepartdebug.h"
12#include "katerenderer.h"
13#include "kateview.h"
14#include "kateviewinternal.h"
15
16#include <QPainter>
17
18#include <cmath>
19
20KateTextPreview::KateTextPreview(KTextEditor::ViewPrivate *view, QWidget *parent)
21 : QFrame(parent, Qt::ToolTip | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint)
22 , m_view(view)
23 , m_line(0)
24 , m_showFoldedLines(false)
25 , m_center(true)
26 , m_scale(1.0)
27{
28}
29
30KTextEditor::ViewPrivate *KateTextPreview::view() const
31{
32 return m_view;
33}
34
35void KateTextPreview::setLine(qreal line)
36{
37 if (m_line != line) {
38 m_line = qMax(a: 0.0, b: line);
39 update();
40 }
41}
42
43qreal KateTextPreview::line() const
44{
45 return m_line;
46}
47
48void KateTextPreview::setCenterView(bool center)
49{
50 if (m_center != center) {
51 m_center = center;
52 update();
53 }
54}
55
56bool KateTextPreview::centerView() const
57{
58 return m_center;
59}
60
61void KateTextPreview::setScaleFactor(qreal factor)
62{
63 if (m_scale <= 0.0) {
64 qCWarning(LOG_KTE) << "Negative scale factors are not supported, ignoring.";
65 return;
66 }
67
68 if (m_scale != factor) {
69 m_scale = factor;
70 update();
71 }
72}
73
74qreal KateTextPreview::scaleFactor() const
75{
76 return m_scale;
77}
78
79void KateTextPreview::setShowFoldedLines(bool on)
80{
81 if (m_showFoldedLines != on) {
82 m_showFoldedLines = on;
83 update();
84 }
85}
86
87bool KateTextPreview::showFoldedLines() const
88{
89 return m_showFoldedLines;
90}
91
92void KateTextPreview::paintEvent(QPaintEvent *event)
93{
94 QFrame::paintEvent(event);
95
96 KateRenderer *const renderer = view()->renderer();
97 const int lastLine = showFoldedLines() ? view()->document()->lines() : view()->textFolding().visibleLines();
98
99 const QRectF r = contentsRect(); // already subtracted QFrame's frame width
100 const int xStart = 0;
101 const int xEnd = r.width() / m_scale;
102 const int lineHeight = qMax(a: 1, b: renderer->lineHeight());
103 const int lineCount = ceil(x: static_cast<qreal>(r.height()) / (lineHeight * m_scale));
104 int startLine = qMax(a: 0.0, b: m_line - (m_center ? (ceil(x: lineCount / 2.0)) : 0));
105 // at the very end of the document, make sure the preview is filled
106 if (qMax(a: 0.0, b: m_line - (m_center ? (ceil(x: lineCount / 2.0)) : 0)) + lineCount - 1 > lastLine) {
107 m_line = qMax(a: 0.0, b: lastLine - static_cast<qreal>(r.height()) / (lineHeight * m_scale) + floor(x: lineCount / 2.0) - 1);
108 startLine = qMax(a: 0.0, b: m_line - (m_center ? (ceil(x: lineCount / 2.0)) : 0) + 1);
109 }
110 const int endLine = startLine + lineCount;
111
112 QPainter paint(this);
113 paint.setClipRect(r);
114 paint.fillRect(r, color: m_view->rendererConfig()->backgroundColor());
115
116 // renderer->setShowTabs(doc()->config()->showTabs());
117 // renderer->setShowTrailingSpaces(doc()->config()->showSpaces());
118
119 paint.scale(sx: m_scale, sy: m_scale);
120 paint.translate(offset: r.topLeft());
121 if (m_center && m_line - ceil(x: lineCount / 2.0) > 0.0) {
122 paint.translate(dx: 0, dy: -lineHeight * (m_line - static_cast<int>(m_line)));
123 }
124
125 for (int line = startLine; line <= endLine; ++line) {
126 // get real line, skip if invalid!
127 const int realLine = showFoldedLines() ? line : view()->textFolding().visibleLineToLine(visibleLine: line);
128 if (realLine < 0 || realLine >= renderer->doc()->lines()) {
129 continue;
130 }
131
132 // compute layout WITHOUT cache to not poison it + render it
133 KateLineLayout lineLayout(*renderer);
134 lineLayout.setLine(line: realLine, virtualLine: -1);
135 renderer->layoutLine(line: &lineLayout, maxwidth: -1 /* no wrap */, cacheLayout: false /* no layout cache */);
136 renderer->paintTextLine(paint, range: &lineLayout, xStart, xEnd, textClipRect: QRectF{}, cursor: nullptr, flags: KateRenderer::SkipDrawFirstInvisibleLineUnderlined);
137
138 // translate for next line
139 paint.translate(dx: 0, dy: lineHeight);
140 }
141}
142
143#include "moc_katetextpreview.cpp"
144

source code of ktexteditor/src/view/katetextpreview.cpp