File indexing completed on 2024-04-28 07:46:50

0001 /*
0002     SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "katetextpreview.h"
0008 #include "kateconfig.h"
0009 #include "katedocument.h"
0010 #include "katelayoutcache.h"
0011 #include "katepartdebug.h"
0012 #include "katerenderer.h"
0013 #include "kateview.h"
0014 #include "kateviewinternal.h"
0015 
0016 #include <QPainter>
0017 
0018 #include <cmath>
0019 
0020 KateTextPreview::KateTextPreview(KTextEditor::ViewPrivate *view, QWidget *parent)
0021     : QFrame(parent, Qt::ToolTip | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint)
0022     , m_view(view)
0023     , m_line(0)
0024     , m_showFoldedLines(false)
0025     , m_center(true)
0026     , m_scale(1.0)
0027 {
0028 }
0029 
0030 KTextEditor::ViewPrivate *KateTextPreview::view() const
0031 {
0032     return m_view;
0033 }
0034 
0035 void KateTextPreview::setLine(qreal line)
0036 {
0037     if (m_line != line) {
0038         m_line = qMax(0.0, line);
0039         update();
0040     }
0041 }
0042 
0043 qreal KateTextPreview::line() const
0044 {
0045     return m_line;
0046 }
0047 
0048 void KateTextPreview::setCenterView(bool center)
0049 {
0050     if (m_center != center) {
0051         m_center = center;
0052         update();
0053     }
0054 }
0055 
0056 bool KateTextPreview::centerView() const
0057 {
0058     return m_center;
0059 }
0060 
0061 void KateTextPreview::setScaleFactor(qreal factor)
0062 {
0063     if (m_scale <= 0.0) {
0064         qCWarning(LOG_KTE) << "Negative scale factors are not supported, ignoring.";
0065         return;
0066     }
0067 
0068     if (m_scale != factor) {
0069         m_scale = factor;
0070         update();
0071     }
0072 }
0073 
0074 qreal KateTextPreview::scaleFactor() const
0075 {
0076     return m_scale;
0077 }
0078 
0079 void KateTextPreview::setShowFoldedLines(bool on)
0080 {
0081     if (m_showFoldedLines != on) {
0082         m_showFoldedLines = on;
0083         update();
0084     }
0085 }
0086 
0087 bool KateTextPreview::showFoldedLines() const
0088 {
0089     return m_showFoldedLines;
0090 }
0091 
0092 void KateTextPreview::paintEvent(QPaintEvent *event)
0093 {
0094     QFrame::paintEvent(event);
0095 
0096     KateRenderer *const renderer = view()->renderer();
0097     const int lastLine = showFoldedLines() ? view()->document()->lines() : view()->textFolding().visibleLines();
0098 
0099     const QRectF r = contentsRect(); // already subtracted QFrame's frame width
0100     const int xStart = 0;
0101     const int xEnd = r.width() / m_scale;
0102     const int lineHeight = qMax(1, renderer->lineHeight());
0103     const int lineCount = ceil(static_cast<qreal>(r.height()) / (lineHeight * m_scale));
0104     int startLine = qMax(0.0, m_line - (m_center ? (ceil(lineCount / 2.0)) : 0));
0105     // at the very end of the document, make sure the preview is filled
0106     if (qMax(0.0, m_line - (m_center ? (ceil(lineCount / 2.0)) : 0)) + lineCount - 1 > lastLine) {
0107         m_line = qMax(0.0, lastLine - static_cast<qreal>(r.height()) / (lineHeight * m_scale) + floor(lineCount / 2.0) - 1);
0108         startLine = qMax(0.0, m_line - (m_center ? (ceil(lineCount / 2.0)) : 0) + 1);
0109     }
0110     const int endLine = startLine + lineCount;
0111 
0112     QPainter paint(this);
0113     paint.setClipRect(r);
0114     paint.fillRect(r, m_view->rendererConfig()->backgroundColor());
0115 
0116     //     renderer->setShowTabs(doc()->config()->showTabs());
0117     //     renderer->setShowTrailingSpaces(doc()->config()->showSpaces());
0118 
0119     paint.scale(m_scale, m_scale);
0120     paint.translate(r.topLeft());
0121     if (m_center && m_line - ceil(lineCount / 2.0) > 0.0) {
0122         paint.translate(0, -lineHeight * (m_line - static_cast<int>(m_line)));
0123     }
0124 
0125     for (int line = startLine; line <= endLine; ++line) {
0126         // get real line, skip if invalid!
0127         const int realLine = showFoldedLines() ? line : view()->textFolding().visibleLineToLine(line);
0128         if (realLine < 0 || realLine >= renderer->doc()->lines()) {
0129             continue;
0130         }
0131 
0132         // compute layout WITHOUT cache to not poison it + render it
0133         KateLineLayout lineLayout(*renderer);
0134         lineLayout.setLine(realLine, -1);
0135         renderer->layoutLine(&lineLayout, -1 /* no wrap */, false /* no layout cache */);
0136         renderer->paintTextLine(paint, &lineLayout, xStart, xEnd, QRectF{}, nullptr, KateRenderer::SkipDrawFirstInvisibleLineUnderlined);
0137 
0138         // translate for next line
0139         paint.translate(0, lineHeight);
0140     }
0141 }
0142 
0143 #include "moc_katetextpreview.cpp"