Changeset View
Standalone View
src/view/kateviewhelpers.cpp
1 | /* This file is part of the KDE libraries | 1 | /* This file is part of the KDE libraries | ||
---|---|---|---|---|---|
2 | Copyright (C) 2008, 2009 Matthew Woehlke <mw_triad@users.sourceforge.net> | 2 | Copyright (C) 2008, 2009 Matthew Woehlke <mw_triad@users.sourceforge.net> | ||
3 | Copyright (C) 2007 Mirko Stocker <me@misto.ch> | 3 | Copyright (C) 2007 Mirko Stocker <me@misto.ch> | ||
4 | Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> | 4 | Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> | ||
5 | Copyright (C) 2001 Anders Lund <anders@alweb.dk> | 5 | Copyright (C) 2001 Anders Lund <anders@alweb.dk> | ||
6 | Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> | 6 | Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> | ||
7 | Copyright (C) 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com> | 7 | Copyright (C) 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com> | ||
8 | Copyright (C) 2012 Kåre Särs <kare.sars@iki.fi> (Minimap) | 8 | Copyright (C) 2012 Kåre Särs <kare.sars@iki.fi> (Minimap) | ||
9 | Copyright 2017-2018 Friedrich W. H. Kossebau <kossebau@kde.org> | ||||
9 | 10 | | |||
10 | This library is free software; you can redistribute it and/or | 11 | This library is free software; you can redistribute it and/or | ||
11 | modify it under the terms of the GNU Library General Public | 12 | modify it under the terms of the GNU Library General Public | ||
12 | License version 2 as published by the Free Software Foundation. | 13 | License version 2 as published by the Free Software Foundation. | ||
13 | 14 | | |||
14 | This library is distributed in the hope that it will be useful, | 15 | This library is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Show All 10 Lines | |||||
27 | #include "katecmd.h" | 28 | #include "katecmd.h" | ||
28 | #include <ktexteditor/attribute.h> | 29 | #include <ktexteditor/attribute.h> | ||
29 | #include <ktexteditor/annotationinterface.h> | 30 | #include <ktexteditor/annotationinterface.h> | ||
30 | #include <ktexteditor/movingrange.h> | 31 | #include <ktexteditor/movingrange.h> | ||
31 | #include "kateconfig.h" | 32 | #include "kateconfig.h" | ||
32 | #include "katedocument.h" | 33 | #include "katedocument.h" | ||
33 | #include <katebuffer.h> | 34 | #include <katebuffer.h> | ||
34 | #include "katerenderer.h" | 35 | #include "katerenderer.h" | ||
36 | #include "kateannotationitemdelegate.h" | ||||
35 | #include "kateview.h" | 37 | #include "kateview.h" | ||
36 | #include "kateviewinternal.h" | 38 | #include "kateviewinternal.h" | ||
37 | #include "katelayoutcache.h" | 39 | #include "katelayoutcache.h" | ||
38 | #include "katetextlayout.h" | 40 | #include "katetextlayout.h" | ||
39 | #include "kateglobal.h" | 41 | #include "kateglobal.h" | ||
40 | #include "katepartdebug.h" | 42 | #include "katepartdebug.h" | ||
41 | #include "katecommandrangeexpressionparser.h" | 43 | #include "katecommandrangeexpressionparser.h" | ||
42 | #include "kateabstractinputmode.h" | 44 | #include "kateabstractinputmode.h" | ||
▲ Show 20 Lines • Show All 1388 Lines • ▼ Show 20 Line(s) | 1423 | KateIconBorder::KateIconBorder(KateViewInternal *internalView, QWidget *parent) | |||
1431 | , m_dynWrapIndicatorsOn(false) | 1433 | , m_dynWrapIndicatorsOn(false) | ||
1432 | , m_annotationBorderOn(false) | 1434 | , m_annotationBorderOn(false) | ||
1433 | , m_dynWrapIndicators(0) | 1435 | , m_dynWrapIndicators(0) | ||
1434 | , m_lastClickedLine(-1) | 1436 | , m_lastClickedLine(-1) | ||
1435 | , m_cachedLNWidth(0) | 1437 | , m_cachedLNWidth(0) | ||
1436 | , m_maxCharWidth(0.0) | 1438 | , m_maxCharWidth(0.0) | ||
1437 | , iconPaneWidth(16) | 1439 | , iconPaneWidth(16) | ||
1438 | , m_annotationBorderWidth(6) | 1440 | , m_annotationBorderWidth(6) | ||
1441 | , m_annotationItemDelegate(new KateAnnotationItemDelegate(m_viewInternal, this)) | ||||
1439 | , m_foldingPreview(nullptr) | 1442 | , m_foldingPreview(nullptr) | ||
1440 | , m_foldingRange(nullptr) | 1443 | , m_foldingRange(nullptr) | ||
1441 | , m_nextHighlightBlock(-2) | 1444 | , m_nextHighlightBlock(-2) | ||
1442 | , m_currentBlockLine(-1) | 1445 | , m_currentBlockLine(-1) | ||
1443 | { | 1446 | { | ||
1444 | setAttribute(Qt::WA_StaticContents); | 1447 | setAttribute(Qt::WA_StaticContents); | ||
1445 | setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); | 1448 | setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); | ||
1446 | setMouseTracking(true); | 1449 | setMouseTracking(true); | ||
1447 | m_doc->setMarkDescription(MarkInterface::markType01, i18n("Bookmark")); | 1450 | m_doc->setMarkDescription(MarkInterface::markType01, i18n("Bookmark")); | ||
1448 | m_doc->setMarkPixmap(MarkInterface::markType01, QIcon::fromTheme(QStringLiteral("bookmarks")).pixmap(32, 32)); | 1451 | m_doc->setMarkPixmap(MarkInterface::markType01, QIcon::fromTheme(QStringLiteral("bookmarks")).pixmap(32, 32)); | ||
1449 | 1452 | | |||
1453 | connect(m_annotationItemDelegate, &AbstractAnnotationItemDelegate::sizeHintChanged, | ||||
1454 | this, &KateIconBorder::updateAnnotationBorderWidth); | ||||
1455 | | ||||
1450 | updateFont(); | 1456 | updateFont(); | ||
1451 | 1457 | | |||
1452 | m_delayFoldingHlTimer.setSingleShot(true); | 1458 | m_delayFoldingHlTimer.setSingleShot(true); | ||
1453 | m_delayFoldingHlTimer.setInterval(150); | 1459 | m_delayFoldingHlTimer.setInterval(150); | ||
1454 | connect(&m_delayFoldingHlTimer, SIGNAL(timeout()), this, SLOT(showBlock())); | 1460 | connect(&m_delayFoldingHlTimer, SIGNAL(timeout()), this, SLOT(showBlock())); | ||
1455 | 1461 | | |||
1456 | // user interaction (scrolling) hides e.g. preview | 1462 | // user interaction (scrolling) hides e.g. preview | ||
1457 | connect(m_view, SIGNAL(displayRangeChanged(KTextEditor::ViewPrivate*)), this, SLOT(displayRangeChanged())); | 1463 | connect(m_view, SIGNAL(displayRangeChanged(KTextEditor::ViewPrivate*)), this, SLOT(displayRangeChanged())); | ||
Show All 21 Lines | |||||
1479 | void KateIconBorder::setAnnotationBorderOn(bool enable) | 1485 | void KateIconBorder::setAnnotationBorderOn(bool enable) | ||
1480 | { | 1486 | { | ||
1481 | if (enable == m_annotationBorderOn) { | 1487 | if (enable == m_annotationBorderOn) { | ||
1482 | return; | 1488 | return; | ||
1483 | } | 1489 | } | ||
1484 | 1490 | | |||
1485 | m_annotationBorderOn = enable; | 1491 | m_annotationBorderOn = enable; | ||
1486 | 1492 | | |||
1493 | // make sure the tooltip is hidden | ||||
1494 | if (!m_annotationBorderOn && !m_hoveredAnnotationGroupIdentifier.isEmpty()) { | ||||
1495 | m_hoveredAnnotationGroupIdentifier.clear(); | ||||
1496 | hideAnnotationTooltip(); | ||||
1497 | } | ||||
1498 | | ||||
1487 | emit m_view->annotationBorderVisibilityChanged(m_view, enable); | 1499 | emit m_view->annotationBorderVisibilityChanged(m_view, enable); | ||
1488 | 1500 | | |||
1489 | updateGeometry(); | 1501 | updateGeometry(); | ||
1490 | 1502 | | |||
1491 | QTimer::singleShot(0, this, SLOT(update())); | 1503 | QTimer::singleShot(0, this, SLOT(update())); | ||
1492 | } | 1504 | } | ||
1493 | 1505 | | |||
1494 | void KateIconBorder::removeAnnotationHovering() | 1506 | void KateIconBorder::removeAnnotationHovering() | ||
1495 | { | 1507 | { | ||
1496 | // remove hovering if it's still there | 1508 | // remove hovering if it's still there | ||
1497 | if (m_annotationBorderOn && !m_hoveredAnnotationGroupIdentifier.isEmpty()) { | 1509 | if (m_annotationBorderOn && !m_hoveredAnnotationGroupIdentifier.isEmpty()) { | ||
1498 | m_hoveredAnnotationGroupIdentifier.clear(); | 1510 | m_hoveredAnnotationGroupIdentifier.clear(); | ||
1499 | hideAnnotationTooltip(); | | |||
1500 | QTimer::singleShot(0, this, SLOT(update())); | 1511 | QTimer::singleShot(0, this, SLOT(update())); | ||
1501 | } | 1512 | } | ||
1502 | } | 1513 | } | ||
1503 | 1514 | | |||
1504 | void KateIconBorder::setLineNumbersOn(bool enable) | 1515 | void KateIconBorder::setLineNumbersOn(bool enable) | ||
1505 | { | 1516 | { | ||
1506 | if (enable == m_lineNumbersOn) { | 1517 | if (enable == m_lineNumbersOn) { | ||
1507 | return; | 1518 | return; | ||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Line(s) | 1616 | { | |||
1610 | for (int i = 48; i < 58; i++) { | 1621 | for (int i = 48; i < 58; i++) { | ||
1611 | const qreal charWidth = ceil(fm.width(QChar(i))); | 1622 | const qreal charWidth = ceil(fm.width(QChar(i))); | ||
1612 | m_maxCharWidth = qMax(m_maxCharWidth, charWidth); | 1623 | m_maxCharWidth = qMax(m_maxCharWidth, charWidth); | ||
1613 | } | 1624 | } | ||
1614 | 1625 | | |||
1615 | // the icon pane scales with the font... | 1626 | // the icon pane scales with the font... | ||
1616 | iconPaneWidth = fm.height(); | 1627 | iconPaneWidth = fm.height(); | ||
1617 | 1628 | | |||
1629 | calcAnnotationBorderWidth(); | ||||
1630 | | ||||
1618 | updateGeometry(); | 1631 | updateGeometry(); | ||
1619 | 1632 | | |||
1620 | QTimer::singleShot(0, this, SLOT(update())); | 1633 | QTimer::singleShot(0, this, SLOT(update())); | ||
1621 | } | 1634 | } | ||
1622 | 1635 | | |||
1623 | int KateIconBorder::lineNumberWidth() const | 1636 | int KateIconBorder::lineNumberWidth() const | ||
1624 | { | 1637 | { | ||
1625 | // width = (number of digits + 1) * char width | 1638 | // width = (number of digits + 1) * char width | ||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Line(s) | 1687 | { | |||
1703 | } else { | 1716 | } else { | ||
1704 | QPointF points[3] = { middle + QPointF(-halfSizeP, -halfSize), middle + QPointF(-halfSizeP, halfSize), middle + QPointF(halfSizeP, 0) }; | 1717 | QPointF points[3] = { middle + QPointF(-halfSizeP, -halfSize), middle + QPointF(-halfSizeP, halfSize), middle + QPointF(halfSizeP, 0) }; | ||
1705 | painter.drawConvexPolygon(points, 3); | 1718 | painter.drawConvexPolygon(points, 3); | ||
1706 | } | 1719 | } | ||
1707 | 1720 | | |||
1708 | painter.setRenderHint(QPainter::Antialiasing, false); | 1721 | painter.setRenderHint(QPainter::Antialiasing, false); | ||
1709 | } | 1722 | } | ||
1710 | 1723 | | |||
1724 | /** | ||||
1725 | * Helper class for an identifier which can be an empty or non-empty string or invalid. | ||||
1726 | * Avoids complicated explicit statements in code dealing with the identifier | ||||
1727 | * received as QVariant from a model. | ||||
1728 | */ | ||||
1729 | class KateAnnotationGroupIdentifier | ||||
1730 | { | ||||
1731 | public: | ||||
1732 | KateAnnotationGroupIdentifier(const QVariant &identifier) | ||||
1733 | : m_isValid(identifier.isValid() && identifier.canConvert<QString>()) | ||||
1734 | , m_id(m_isValid ? identifier.toString() : QString()) | ||||
1735 | { | ||||
1736 | } | ||||
1737 | KateAnnotationGroupIdentifier() = default; | ||||
1738 | KateAnnotationGroupIdentifier(const KateAnnotationGroupIdentifier &rhs) = default; | ||||
1739 | | ||||
1740 | KateAnnotationGroupIdentifier& operator=(const KateAnnotationGroupIdentifier &rhs) | ||||
1741 | { | ||||
1742 | m_isValid = rhs.m_isValid; | ||||
1743 | m_id = rhs.m_id; | ||||
1744 | return *this; | ||||
1745 | } | ||||
1746 | KateAnnotationGroupIdentifier& operator=(const QVariant &identifier) | ||||
1747 | { | ||||
1748 | m_isValid = (identifier.isValid() && identifier.canConvert<QString>()); | ||||
1749 | if (m_isValid) { | ||||
1750 | m_id = identifier.toString(); | ||||
1751 | } else { | ||||
1752 | m_id.clear(); | ||||
1753 | } | ||||
1754 | return *this; | ||||
1755 | } | ||||
1756 | | ||||
1757 | bool operator==(const KateAnnotationGroupIdentifier &rhs) const | ||||
1758 | { | ||||
1759 | return (m_isValid == rhs.m_isValid) && (!m_isValid || (m_id == rhs.m_id)); | ||||
1760 | } | ||||
1761 | bool operator!=(const KateAnnotationGroupIdentifier &rhs) const | ||||
1762 | { | ||||
1763 | return (m_isValid != rhs.m_isValid) || (m_isValid && (m_id != rhs.m_id)); | ||||
1764 | } | ||||
1765 | | ||||
1766 | void clear() | ||||
1767 | { | ||||
1768 | m_isValid = false; | ||||
1769 | m_id.clear(); | ||||
1770 | } | ||||
1771 | bool isValid() const { return m_isValid; } | ||||
1772 | const QString& id() const { return m_id; } | ||||
1773 | | ||||
1774 | private: | ||||
1775 | bool m_isValid = false; | ||||
1776 | QString m_id; | ||||
1777 | }; | ||||
1778 | | ||||
1779 | /** | ||||
1780 | * Helper class for iterative calculation of data regarding the position | ||||
1781 | * of a line with regard to annotation item grouping. | ||||
1782 | */ | ||||
1783 | class KateAnnotationGroupPositionState | ||||
1784 | { | ||||
1785 | public: | ||||
1786 | /** | ||||
1787 | * @param startz first rendered displayed line | ||||
1788 | * @param isUsed flag whether the KateAnnotationGroupPositionState object will | ||||
1789 | * be used or is just created due to being on the stack | ||||
1790 | */ | ||||
1791 | KateAnnotationGroupPositionState(KateViewInternal *viewInternal, | ||||
1792 | const KTextEditor::AnnotationModel *model, | ||||
1793 | const QString &hoveredAnnotationGroupIdentifier, | ||||
1794 | uint startz, | ||||
1795 | bool isUsed); | ||||
1796 | /** | ||||
1797 | * @param styleOption option to fill with data for the given line | ||||
1798 | * @param z rendered displayed line | ||||
1799 | * @param realLine real line which is rendered here (passed to avoid another look-up) | ||||
1800 | */ | ||||
1801 | void nextLine(KTextEditor::StyleOptionAnnotationItem &styleOption, uint z, int realLine); | ||||
1802 | | ||||
1803 | private: | ||||
1804 | KateViewInternal *m_viewInternal; | ||||
1805 | const KTextEditor::AnnotationModel * const m_model; | ||||
1806 | const QString m_hoveredAnnotationGroupIdentifier; | ||||
1807 | | ||||
1808 | int m_visibleWrappedLineInAnnotationGroup = -1; | ||||
1809 | KateAnnotationGroupIdentifier m_lastAnnotationGroupIdentifier; | ||||
1810 | KateAnnotationGroupIdentifier m_nextAnnotationGroupIdentifier; | ||||
1811 | bool m_isSameAnnotationGroupsSinceLast = false; | ||||
1812 | }; | ||||
1813 | | ||||
1814 | KateAnnotationGroupPositionState::KateAnnotationGroupPositionState(KateViewInternal *viewInternal, | ||||
1815 | const KTextEditor::AnnotationModel *model, | ||||
1816 | const QString &hoveredAnnotationGroupIdentifier, | ||||
1817 | uint startz, | ||||
1818 | bool isUsed) | ||||
1819 | : m_viewInternal(viewInternal) | ||||
1820 | , m_model(model) | ||||
1821 | , m_hoveredAnnotationGroupIdentifier(hoveredAnnotationGroupIdentifier) | ||||
1822 | { | ||||
1823 | if (!isUsed) { | ||||
1824 | return; | ||||
1825 | } | ||||
1826 | | ||||
1827 | if (!m_model || (static_cast<int>(startz) >= m_viewInternal->cache()->viewCacheLineCount())) { | ||||
1828 | return; | ||||
1829 | } | ||||
1830 | | ||||
1831 | const auto realLineAtStart = m_viewInternal->cache()->viewLine(startz).line(); | ||||
1832 | m_nextAnnotationGroupIdentifier = m_model->data(realLineAtStart, | ||||
1833 | (Qt::ItemDataRole)KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1834 | if (m_nextAnnotationGroupIdentifier.isValid()) { | ||||
1835 | // estimate state of annotation group before first rendered line | ||||
1836 | if (startz == 0) { | ||||
1837 | if (realLineAtStart > 0) { | ||||
1838 | // TODO: here we would want to scan until the next line that would be displayed, | ||||
1839 | // to see if there are any group changes until then | ||||
1840 | // for now simply taking neighbour line into account, not a grave bug on the first displayed line | ||||
1841 | m_lastAnnotationGroupIdentifier = m_model->data(realLineAtStart - 1, | ||||
1842 | (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1843 | m_isSameAnnotationGroupsSinceLast = (m_lastAnnotationGroupIdentifier == m_nextAnnotationGroupIdentifier); | ||||
1844 | } | ||||
1845 | } else { | ||||
1846 | const auto realLineBeforeStart = m_viewInternal->cache()->viewLine(startz-1).line(); | ||||
1847 | m_lastAnnotationGroupIdentifier = m_model->data(realLineBeforeStart, (Qt::ItemDataRole)KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1848 | if (m_lastAnnotationGroupIdentifier.isValid()) { | ||||
1849 | if (m_lastAnnotationGroupIdentifier.id() == m_nextAnnotationGroupIdentifier.id()) { | ||||
1850 | m_isSameAnnotationGroupsSinceLast = true; | ||||
1851 | // estimate m_visibleWrappedLineInAnnotationGroup from lines before startz | ||||
1852 | for (uint z = startz; z > 0; --z) { | ||||
1853 | const auto realLine = m_viewInternal->cache()->viewLine(z-1).line(); | ||||
1854 | const KateAnnotationGroupIdentifier identifier = m_model->data(realLine, (Qt::ItemDataRole)KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1855 | if (identifier != m_lastAnnotationGroupIdentifier) { | ||||
1856 | break; | ||||
1857 | } | ||||
1858 | ++m_visibleWrappedLineInAnnotationGroup; | ||||
1859 | } | ||||
1860 | } | ||||
1861 | } | ||||
1862 | } | ||||
1863 | } | ||||
1864 | } | ||||
1865 | | ||||
1866 | void KateAnnotationGroupPositionState::nextLine(KTextEditor::StyleOptionAnnotationItem &styleOption, | ||||
1867 | uint z, int realLine) | ||||
1868 | { | ||||
1869 | styleOption.wrappedLine = m_viewInternal->cache()->viewLine(z).viewLine(); | ||||
1870 | styleOption.wrappedLineCount = m_viewInternal->cache()->viewLineCount(realLine); | ||||
1871 | | ||||
1872 | // Estimate position in group | ||||
1873 | const KateAnnotationGroupIdentifier annotationGroupIdentifier = m_nextAnnotationGroupIdentifier; | ||||
1874 | bool isSameAnnotationGroupsSinceThis = false; | ||||
1875 | // Calculate next line's group identifier | ||||
1876 | // shortcut: assuming wrapped lines are always displayed together, test is simple | ||||
1877 | if (styleOption.wrappedLine+1 < styleOption.wrappedLineCount) { | ||||
1878 | m_nextAnnotationGroupIdentifier = annotationGroupIdentifier; | ||||
1879 | isSameAnnotationGroupsSinceThis = true; | ||||
1880 | } else { | ||||
1881 | if (static_cast<int>(z+1) < m_viewInternal->cache()->viewCacheLineCount()) { | ||||
1882 | const int realLineAfter = m_viewInternal->cache()->viewLine(z+1).line(); | ||||
1883 | // search for any realLine with a different group id, also the non-displayed | ||||
1884 | int rl = realLine + 1; | ||||
1885 | for (; rl <= realLineAfter; ++rl) { | ||||
1886 | m_nextAnnotationGroupIdentifier = m_model->data(rl, (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1887 | if (!m_nextAnnotationGroupIdentifier.isValid() || | ||||
1888 | (m_nextAnnotationGroupIdentifier.id() != annotationGroupIdentifier.id())) { | ||||
1889 | break; | ||||
1890 | } | ||||
1891 | } | ||||
1892 | isSameAnnotationGroupsSinceThis = (rl > realLineAfter); | ||||
1893 | if (rl < realLineAfter) { | ||||
1894 | m_nextAnnotationGroupIdentifier = m_model->data(realLineAfter, (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1895 | } | ||||
1896 | } else { | ||||
1897 | // TODO: check next line after display end | ||||
1898 | m_nextAnnotationGroupIdentifier.clear(); | ||||
1899 | isSameAnnotationGroupsSinceThis = false; | ||||
1900 | } | ||||
1901 | } | ||||
1902 | | ||||
1903 | if (annotationGroupIdentifier.isValid()) { | ||||
1904 | if (m_hoveredAnnotationGroupIdentifier == annotationGroupIdentifier.id()) { | ||||
1905 | styleOption.state |= QStyle::State_MouseOver; | ||||
1906 | } else { | ||||
1907 | styleOption.state &= ~QStyle::State_MouseOver; | ||||
1908 | } | ||||
1909 | | ||||
1910 | if (m_isSameAnnotationGroupsSinceLast) { | ||||
1911 | ++m_visibleWrappedLineInAnnotationGroup; | ||||
1912 | } else { | ||||
1913 | m_visibleWrappedLineInAnnotationGroup = 0; | ||||
1914 | } | ||||
1915 | | ||||
1916 | styleOption.annotationItemGroupingPosition = StyleOptionAnnotationItem::InGroup; | ||||
1917 | if (!m_isSameAnnotationGroupsSinceLast) { | ||||
1918 | styleOption.annotationItemGroupingPosition |= StyleOptionAnnotationItem::GroupBegin; | ||||
1919 | } | ||||
1920 | if (!isSameAnnotationGroupsSinceThis) { | ||||
1921 | styleOption.annotationItemGroupingPosition |= StyleOptionAnnotationItem::GroupEnd; | ||||
1922 | } | ||||
1923 | } else { | ||||
1924 | m_visibleWrappedLineInAnnotationGroup = 0; | ||||
1925 | } | ||||
1926 | styleOption.visibleWrappedLineInGroup = m_visibleWrappedLineInAnnotationGroup; | ||||
1927 | | ||||
1928 | m_lastAnnotationGroupIdentifier = m_nextAnnotationGroupIdentifier; | ||||
1929 | m_isSameAnnotationGroupsSinceLast = isSameAnnotationGroupsSinceThis; | ||||
1930 | } | ||||
1931 | | ||||
1932 | | ||||
1711 | void KateIconBorder::paintBorder(int /*x*/, int y, int /*width*/, int height) | 1933 | void KateIconBorder::paintBorder(int /*x*/, int y, int /*width*/, int height) | ||
1712 | { | 1934 | { | ||
1713 | uint h = m_view->renderer()->lineHeight(); | 1935 | uint h = m_view->renderer()->lineHeight(); | ||
1714 | uint startz = (y / h); | 1936 | uint startz = (y / h); | ||
1715 | uint endz = startz + 1 + (height / h); | 1937 | uint endz = startz + 1 + (height / h); | ||
1716 | uint lineRangesSize = m_viewInternal->cache()->viewCacheLineCount(); | 1938 | uint lineRangesSize = m_viewInternal->cache()->viewCacheLineCount(); | ||
1717 | uint currentLine = m_view->cursorPosition().line(); | 1939 | uint currentLine = m_view->cursorPosition().line(); | ||
1718 | 1940 | | |||
Show All 22 Lines | |||||
1741 | int w(this->width()); // sane value/calc only once | 1963 | int w(this->width()); // sane value/calc only once | ||
1742 | 1964 | | |||
1743 | QPainter p(this); | 1965 | QPainter p(this); | ||
1744 | p.setRenderHints(QPainter::TextAntialiasing); | 1966 | p.setRenderHints(QPainter::TextAntialiasing); | ||
1745 | p.setFont(m_view->renderer()->config()->font()); // for line numbers | 1967 | p.setFont(m_view->renderer()->config()->font()); // for line numbers | ||
1746 | 1968 | | |||
1747 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 1969 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
1748 | m_view->annotationModel() : m_doc->annotationModel(); | 1970 | m_view->annotationModel() : m_doc->annotationModel(); | ||
1971 | KateAnnotationGroupPositionState annotationGroupPositionState(m_viewInternal, model, | ||||
1972 | m_hoveredAnnotationGroupIdentifier, | ||||
1973 | startz, m_annotationBorderOn); | ||||
1749 | 1974 | | |||
1750 | for (uint z = startz; z <= endz; z++) { | 1975 | for (uint z = startz; z <= endz; z++) { | ||
1751 | int y = h * z; | 1976 | int y = h * z; | ||
1752 | int realLine = -1; | 1977 | int realLine = -1; | ||
1753 | 1978 | | |||
1754 | if (z < lineRangesSize) { | 1979 | if (z < lineRangesSize) { | ||
1755 | realLine = m_viewInternal->cache()->viewLine(z).line(); | 1980 | realLine = m_viewInternal->cache()->viewLine(z).line(); | ||
1756 | } | 1981 | } | ||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | |||||
1802 | } | 2027 | } | ||
1803 | 2028 | | |||
1804 | // annotation information | 2029 | // annotation information | ||
1805 | if (m_annotationBorderOn) { | 2030 | if (m_annotationBorderOn) { | ||
1806 | // Draw a border line between annotations and the line numbers | 2031 | // Draw a border line between annotations and the line numbers | ||
1807 | p.setPen(m_view->renderer()->config()->lineNumberColor()); | 2032 | p.setPen(m_view->renderer()->config()->lineNumberColor()); | ||
1808 | p.setBrush(m_view->renderer()->config()->lineNumberColor()); | 2033 | p.setBrush(m_view->renderer()->config()->lineNumberColor()); | ||
1809 | 2034 | | |||
1810 | int borderWidth = m_annotationBorderWidth; | 2035 | const qreal borderX = lnX + m_annotationBorderWidth + 0.5; | ||
1811 | p.drawLine(lnX + borderWidth + 1, y, lnX + borderWidth + 1, y + h); | 2036 | p.drawLine(QPointF(borderX, y+0.5), QPointF(borderX, y + h - 0.5)); | ||
1812 | 2037 | | |||
1813 | if ((realLine > -1) && model) { | 2038 | if ((realLine > -1) && model) { | ||
1814 | // Fetch data from the model | 2039 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||
1815 | QVariant text = model->data(realLine, Qt::DisplayRole); | 2040 | initStyleOption(&styleOption); | ||
1816 | QVariant foreground = model->data(realLine, Qt::ForegroundRole); | 2041 | styleOption.rect.setRect(lnX, y, m_annotationBorderWidth, h); | ||
1817 | QVariant background = model->data(realLine, Qt::BackgroundRole); | 2042 | annotationGroupPositionState.nextLine(styleOption, z, realLine); | ||
1818 | // Fill the background | | |||
1819 | if (background.isValid()) { | | |||
1820 | p.fillRect(lnX, y, borderWidth + 1, h, background.value<QBrush>()); | | |||
1821 | } | | |||
1822 | // Set the pen for drawing the foreground | | |||
1823 | if (foreground.isValid()) { | | |||
1824 | p.setPen(foreground.value<QPen>()); | | |||
1825 | } | | |||
1826 | | ||||
1827 | // Draw a border around all adjacent entries that have the same text as the currently hovered one | | |||
1828 | const QVariant identifier = model->data( realLine, (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole ); | | |||
1829 | if( m_hoveredAnnotationGroupIdentifier == identifier.toString() ) { | | |||
1830 | p.drawLine(lnX, y, lnX, y + h); | | |||
1831 | p.drawLine(lnX + borderWidth, y, lnX + borderWidth, y + h); | | |||
1832 | | ||||
1833 | QVariant beforeText = model->data(realLine - 1, Qt::DisplayRole); | | |||
1834 | QVariant afterText = model->data(realLine + 1, Qt::DisplayRole); | | |||
1835 | if (((beforeText.isValid() && beforeText.canConvert<QString>() | | |||
1836 | && text.isValid() && text.canConvert<QString>() | | |||
1837 | && beforeText.toString() != text.toString()) || realLine == 0) | | |||
1838 | && m_viewInternal->cache()->viewLine(z).viewLine() == 0) { | | |||
1839 | p.drawLine(lnX + 1, y, lnX + borderWidth, y); | | |||
1840 | } | | |||
1841 | | ||||
1842 | if (((afterText.isValid() && afterText.canConvert<QString>() | | |||
1843 | && text.isValid() && text.canConvert<QString>() | | |||
1844 | && afterText.toString() != text.toString()) | | |||
1845 | || realLine == m_view->doc()->lines() - 1) | | |||
1846 | && m_viewInternal->cache()->viewLine(z).viewLine() == m_viewInternal->cache()->viewLineCount(realLine) - 1) { | | |||
1847 | p.drawLine(lnX + 1, y + h - 1, lnX + borderWidth, y + h - 1); | | |||
1848 | } | | |||
1849 | } | | |||
1850 | if (foreground.isValid()) { | | |||
1851 | QPen pen = p.pen(); | | |||
1852 | pen.setWidth(1); | | |||
1853 | p.setPen(pen); | | |||
1854 | } | | |||
1855 | 2043 | | |||
1856 | // Now draw the normal text | 2044 | m_annotationItemDelegate->paint(&p, styleOption, model, realLine); | ||
1857 | if (text.isValid() && text.canConvert<QString>() && (m_viewInternal->cache()->viewLine(z).startCol() == 0)) { | | |||
1858 | p.drawText(lnX + 3, y, borderWidth - 3, h, Qt::AlignLeft | Qt::AlignVCenter, text.toString()); | | |||
1859 | } | | |||
1860 | } | 2045 | } | ||
1861 | 2046 | | |||
1862 | // adjust current X position and reset the pen and brush | 2047 | // adjust current X position | ||
1863 | lnX += borderWidth + 2; | 2048 | lnX += m_annotationBorderWidth + /* separator line width */1; | ||
1864 | } | 2049 | } | ||
1865 | 2050 | | |||
1866 | // line number | 2051 | // line number | ||
1867 | if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { | 2052 | if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { | ||
1868 | if (realLine > -1) { | 2053 | if (realLine > -1) { | ||
1869 | int distanceToCurrent = abs(realLine - static_cast<int>(currentLine)); | 2054 | int distanceToCurrent = abs(realLine - static_cast<int>(currentLine)); | ||
1870 | QColor color; | 2055 | QColor color; | ||
1871 | 2056 | | |||
▲ Show 20 Lines • Show All 324 Lines • ▼ Show 20 Line(s) | 2380 | } else { | |||
2196 | hideBlock(); | 2381 | hideBlock(); | ||
2197 | } | 2382 | } | ||
2198 | if (positionToArea(e->pos()) == AnnotationBorder) { | 2383 | if (positionToArea(e->pos()) == AnnotationBorder) { | ||
2199 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2384 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
2200 | m_view->annotationModel() : m_doc->annotationModel(); | 2385 | m_view->annotationModel() : m_doc->annotationModel(); | ||
2201 | if (model) { | 2386 | if (model) { | ||
2202 | m_hoveredAnnotationGroupIdentifier = model->data( t.line(), | 2387 | m_hoveredAnnotationGroupIdentifier = model->data( t.line(), | ||
2203 | (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole ).toString(); | 2388 | (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole ).toString(); | ||
2204 | showAnnotationTooltip(t.line(), e->globalPos()); | 2389 | const QPoint viewRelativePos = m_view->mapFromGlobal(e->globalPos()); | ||
2390 | QHelpEvent helpEvent(QEvent::ToolTip, viewRelativePos, e->globalPos()); | ||||
2391 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||||
2392 | initStyleOption(&styleOption); | ||||
2393 | styleOption.rect = annotationLineRectInView(t.line()); | ||||
2394 | setStyleOptionLineData(&styleOption, e->y(), t.line(), model, m_hoveredAnnotationGroupIdentifier); | ||||
2395 | m_annotationItemDelegate->helpEvent(&helpEvent, m_view, styleOption, model, t.line()); | ||||
2396 | | ||||
2205 | QTimer::singleShot(0, this, SLOT(update())); | 2397 | QTimer::singleShot(0, this, SLOT(update())); | ||
2206 | } | 2398 | } | ||
2207 | } else { | 2399 | } else { | ||
2208 | if (positionToArea(e->pos()) == IconBorder) { | 2400 | if (positionToArea(e->pos()) == IconBorder) { | ||
2209 | m_doc->requestMarkTooltip(t.line(), e->globalPos()); | 2401 | m_doc->requestMarkTooltip(t.line(), e->globalPos()); | ||
2210 | } | 2402 | } | ||
2211 | 2403 | | |||
2212 | m_hoveredAnnotationGroupIdentifier.clear(); | 2404 | m_hoveredAnnotationGroupIdentifier.clear(); | ||
2213 | hideAnnotationTooltip(); | | |||
2214 | QTimer::singleShot(0, this, SLOT(update())); | 2405 | QTimer::singleShot(0, this, SLOT(update())); | ||
2215 | } | 2406 | } | ||
2216 | if (positionToArea(e->pos()) != IconBorder) { | 2407 | if (positionToArea(e->pos()) != IconBorder) { | ||
2217 | QPoint p = m_viewInternal->mapFromGlobal(e->globalPos()); | 2408 | QPoint p = m_viewInternal->mapFromGlobal(e->globalPos()); | ||
2218 | QMouseEvent forward(QEvent::MouseMove, p, e->button(), e->buttons(), e->modifiers()); | 2409 | QMouseEvent forward(QEvent::MouseMove, p, e->button(), e->buttons(), e->modifiers()); | ||
2219 | m_viewInternal->mouseMoveEvent(&forward); | 2410 | m_viewInternal->mouseMoveEvent(&forward); | ||
2220 | } | 2411 | } | ||
2221 | } else { | 2412 | } else { | ||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Line(s) | 2577 | } else { | |||
2388 | if (m_doc->mark(line) & markType) { | 2579 | if (m_doc->mark(line) & markType) { | ||
2389 | m_doc->removeMark(line, markType); | 2580 | m_doc->removeMark(line, markType); | ||
2390 | } else { | 2581 | } else { | ||
2391 | m_doc->addMark(line, markType); | 2582 | m_doc->addMark(line, markType); | ||
2392 | } | 2583 | } | ||
2393 | } | 2584 | } | ||
2394 | } | 2585 | } | ||
2395 | 2586 | | |||
2396 | void KateIconBorder::showAnnotationTooltip(int line, const QPoint &pos) | 2587 | KTextEditor::AbstractAnnotationItemDelegate* KateIconBorder::annotationItemDelegate() const | ||
2397 | { | 2588 | { | ||
2398 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2589 | return m_annotationItemDelegate; | ||
2399 | m_view->annotationModel() : m_doc->annotationModel(); | 2590 | } | ||
2400 | 2591 | | |||
2401 | if (model) { | 2592 | void KateIconBorder::setAnnotationItemDelegate(KTextEditor::AbstractAnnotationItemDelegate *delegate) | ||
2402 | QVariant data = model->data(line, Qt::ToolTipRole); | 2593 | { | ||
2403 | QString tip = data.toString(); | 2594 | if (delegate == m_annotationItemDelegate) { | ||
2404 | if (!tip.isEmpty()) { | 2595 | return; | ||
2405 | QToolTip::showText(pos, data.toString(), this); | 2596 | } | ||
2597 | | ||||
2598 | // reset to default, but already on that? | ||||
2599 | if (!delegate && m_isDefaultAnnotationItemDelegate) { | ||||
2600 | // nothing to do | ||||
2601 | return; | ||||
2602 | } | ||||
2603 | | ||||
2604 | // make sure the tooltip is hidden | ||||
2605 | if (m_annotationBorderOn && !m_hoveredAnnotationGroupIdentifier.isEmpty()) { | ||||
2606 | m_hoveredAnnotationGroupIdentifier.clear(); | ||||
2607 | hideAnnotationTooltip(); | ||||
2608 | } | ||||
2609 | | ||||
2610 | disconnect(m_annotationItemDelegate, &AbstractAnnotationItemDelegate::sizeHintChanged, | ||||
2611 | this, &KateIconBorder::updateAnnotationBorderWidth); | ||||
2612 | if (!m_isDefaultAnnotationItemDelegate) { | ||||
2613 | disconnect(m_annotationItemDelegate, &QObject::destroyed, | ||||
2614 | this, &KateIconBorder::handleDestroyedAnnotationItemDelegate); | ||||
2615 | } | ||||
2616 | | ||||
2617 | if (!delegate) { | ||||
2618 | // reset to a default delegate | ||||
2619 | m_annotationItemDelegate = new KateAnnotationItemDelegate(m_viewInternal, this); | ||||
2620 | m_isDefaultAnnotationItemDelegate = true; | ||||
2621 | } else { | ||||
2622 | // drop any default delegate | ||||
2623 | if (m_isDefaultAnnotationItemDelegate) { | ||||
2624 | delete m_annotationItemDelegate; | ||||
2625 | m_isDefaultAnnotationItemDelegate = false; | ||||
2626 | } | ||||
2627 | | ||||
2628 | m_annotationItemDelegate = delegate; | ||||
dhaumann: You could do that via QPointer, if the delegate is QObject base. It's a poor man's solution… | |||||
2629 | // catch delegate being destroyed | ||||
2630 | connect(delegate, &QObject::destroyed, | ||||
2631 | this, &KateIconBorder::handleDestroyedAnnotationItemDelegate); | ||||
2632 | } | ||||
2633 | | ||||
2634 | connect(m_annotationItemDelegate, &AbstractAnnotationItemDelegate::sizeHintChanged, | ||||
2635 | this, &KateIconBorder::updateAnnotationBorderWidth); | ||||
2636 | | ||||
2637 | if (m_annotationBorderOn) { | ||||
2638 | updateGeometry(); | ||||
Do you really need the timer here? I thought update() goes through the event queue anyways? dhaumann: Do you really need the timer here? I thought update() goes through the event queue anyways? | |||||
I copied existing code here, for consistency. No really sure when to call it directly and when to go via event loop. kossebau: I copied existing code here, for consistency. No really sure when to call it directly and when… | |||||
2639 | | ||||
2640 | QTimer::singleShot(0, this, SLOT(update())); | ||||
2406 | } | 2641 | } | ||
2407 | } | 2642 | } | ||
2643 | | ||||
2644 | void KateIconBorder::handleDestroyedAnnotationItemDelegate() | ||||
2645 | { | ||||
2646 | setAnnotationItemDelegate(nullptr); | ||||
2408 | } | 2647 | } | ||
2409 | 2648 | | |||
2410 | int KateIconBorder::annotationLineWidth(int line) | 2649 | void KateIconBorder::initStyleOption(KTextEditor::StyleOptionAnnotationItem* styleOption) const | ||
2411 | { | 2650 | { | ||
2nd time this comment pops up. Do you have an answer? In Qt, this would be an extra setAutoFillBackgroundEnabled(bool) , or something similar... In any case - this needs to be decided before the interface goes live :-) dhaumann: 2nd time this comment pops up. Do you have an answer? In Qt, this would be an extra… | |||||
Yes, this is a TODO question to you Kate developers :) p.fillRect(0, y, w - 5, h, m_view->renderer()->config()->iconBarColor()); before starting to draw the annotation stuff and icons, which also cares for the displayed lines with no content. kossebau: Yes, this is a TODO question to you Kate developers :)
Currently KateIconBorder::paintBorder()… | |||||
2412 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2651 | styleOption->initFrom(this); | ||
2413 | m_view->annotationModel() : m_doc->annotationModel(); | 2652 | styleOption->view = m_view; | ||
2653 | styleOption->decorationSize = QSize(iconPaneWidth, iconPaneWidth); | ||||
2654 | styleOption->contentFontMetrics = m_view->renderer()->config()->fontMetrics(); | ||||
2655 | } | ||||
2414 | 2656 | | |||
2415 | if (model) { | 2657 | void KateIconBorder::setStyleOptionLineData(KTextEditor::StyleOptionAnnotationItem* styleOption, | ||
2416 | QVariant data = model->data(line, Qt::DisplayRole); | 2658 | int y, | ||
2417 | return data.toString().length() * m_maxCharWidth + 8; | 2659 | int realLine, | ||
2660 | const KTextEditor::AnnotationModel *model, | ||||
2661 | const QString &annotationGroupIdentifier) const | ||||
2662 | { | ||||
2663 | // calculate rendered displayed line | ||||
2664 | const uint h = m_view->renderer()->lineHeight(); | ||||
2665 | const uint z = (y / h); | ||||
2666 | | ||||
2667 | KateAnnotationGroupPositionState annotationGroupPositionState(m_viewInternal, model, | ||||
2668 | annotationGroupIdentifier, | ||||
2669 | z, true); | ||||
2670 | annotationGroupPositionState.nextLine(*styleOption, z, realLine); | ||||
2671 | } | ||||
2672 | | ||||
2673 | | ||||
2674 | QRect KateIconBorder::annotationLineRectInView(int line) const | ||||
2675 | { | ||||
2676 | int x = 0; | ||||
2677 | if (m_iconBorderOn) { | ||||
2678 | x += iconPaneWidth + 2; | ||||
2418 | } | 2679 | } | ||
2419 | return 8; | 2680 | const int y = m_view->m_viewInternal->lineToY(line); | ||
2681 | | ||||
2682 | return QRect(x, y, m_annotationBorderWidth, m_view->renderer()->lineHeight()); | ||||
2420 | } | 2683 | } | ||
2421 | 2684 | | |||
2422 | void KateIconBorder::updateAnnotationLine(int line) | 2685 | void KateIconBorder::updateAnnotationLine(int line) | ||
2423 | { | 2686 | { | ||
2424 | if (annotationLineWidth(line) > m_annotationBorderWidth) { | 2687 | // TODO: why has the default value been 8, where is that magic number from? | ||
2425 | m_annotationBorderWidth = annotationLineWidth(line); | 2688 | int width = 8; | ||
2689 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||||
2690 | m_view->annotationModel() : m_doc->annotationModel(); | ||||
2691 | | ||||
2692 | if (model) { | ||||
2693 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||||
2694 | initStyleOption(&styleOption); | ||||
2695 | width = m_annotationItemDelegate->sizeHint(styleOption, model, line).width(); | ||||
2696 | } | ||||
2697 | | ||||
2698 | if (width > m_annotationBorderWidth) { | ||||
2699 | m_annotationBorderWidth = width; | ||||
dhaumann: Maybe 4+4 margin or so? | |||||
2426 | updateGeometry(); | 2700 | updateGeometry(); | ||
2427 | 2701 | | |||
2428 | QTimer::singleShot(0, this, SLOT(update())); | 2702 | QTimer::singleShot(0, this, SLOT(update())); | ||
2429 | } | 2703 | } | ||
2430 | } | 2704 | } | ||
2431 | 2705 | | |||
2432 | void KateIconBorder::showAnnotationMenu(int line, const QPoint &pos) | 2706 | void KateIconBorder::showAnnotationMenu(int line, const QPoint &pos) | ||
2433 | { | 2707 | { | ||
2434 | QMenu menu; | 2708 | QMenu menu; | ||
2435 | QAction a(i18n("Disable Annotation Bar"), &menu); | 2709 | QAction a(i18n("Disable Annotation Bar"), &menu); | ||
2436 | a.setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); | 2710 | a.setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); | ||
2437 | menu.addAction(&a); | 2711 | menu.addAction(&a); | ||
2438 | emit m_view->annotationContextMenuAboutToShow(m_view, &menu, line); | 2712 | emit m_view->annotationContextMenuAboutToShow(m_view, &menu, line); | ||
2439 | if (menu.exec(pos) == &a) { | 2713 | if (menu.exec(pos) == &a) { | ||
2440 | m_view->setAnnotationBorderVisible(false); | 2714 | m_view->setAnnotationBorderVisible(false); | ||
2441 | } | 2715 | } | ||
2442 | } | 2716 | } | ||
2443 | 2717 | | |||
2444 | void KateIconBorder::hideAnnotationTooltip() | 2718 | void KateIconBorder::hideAnnotationTooltip() | ||
2445 | { | 2719 | { | ||
2446 | QToolTip::hideText(); | 2720 | m_annotationItemDelegate->hideTooltip(m_view); | ||
2447 | } | 2721 | } | ||
2448 | 2722 | | |||
2449 | void KateIconBorder::updateAnnotationBorderWidth() | 2723 | void KateIconBorder::updateAnnotationBorderWidth() | ||
2450 | { | 2724 | { | ||
2725 | calcAnnotationBorderWidth(); | ||||
2726 | | ||||
2727 | updateGeometry(); | ||||
2728 | | ||||
2729 | QTimer::singleShot(0, this, SLOT(update())); | ||||
dhaumann: Again, single shot timer needed? | |||||
2730 | } | ||||
2731 | | ||||
2732 | void KateIconBorder::calcAnnotationBorderWidth() | ||||
2733 | { | ||||
2734 | // TODO: another magic number, not matching the one in updateAnnotationLine() | ||||
2451 | m_annotationBorderWidth = 6; | 2735 | m_annotationBorderWidth = 6; | ||
2452 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2736 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
2453 | m_view->annotationModel() : m_doc->annotationModel(); | 2737 | m_view->annotationModel() : m_doc->annotationModel(); | ||
2454 | 2738 | | |||
2455 | if (model) { | 2739 | if (model) { | ||
2456 | for (int i = 0; i < m_view->doc()->lines(); i++) { | 2740 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||
2457 | int curwidth = annotationLineWidth(i); | 2741 | initStyleOption(&styleOption); | ||
2742 | | ||||
2743 | const int lineCount = m_view->doc()->lines(); | ||||
2744 | if (lineCount > 0) { | ||||
2745 | const int checkedLineCount = m_hasUniformAnnotationItemSizes ? 1 : lineCount; | ||||
2746 | for (int i = 0; i < checkedLineCount; ++i) { | ||||
2747 | const int curwidth = m_annotationItemDelegate->sizeHint(styleOption, model, i).width(); | ||||
2458 | if (curwidth > m_annotationBorderWidth) { | 2748 | if (curwidth > m_annotationBorderWidth) { | ||
2459 | m_annotationBorderWidth = curwidth; | 2749 | m_annotationBorderWidth = curwidth; | ||
2460 | } | 2750 | } | ||
2461 | } | 2751 | } | ||
2462 | } | 2752 | } | ||
2463 | 2753 | } | |||
2464 | updateGeometry(); | | |||
2465 | | ||||
2466 | QTimer::singleShot(0, this, SLOT(update())); | | |||
2467 | } | 2754 | } | ||
2468 | 2755 | | |||
2469 | void KateIconBorder::annotationModelChanged(KTextEditor::AnnotationModel *oldmodel, KTextEditor::AnnotationModel *newmodel) | 2756 | void KateIconBorder::annotationModelChanged(KTextEditor::AnnotationModel *oldmodel, KTextEditor::AnnotationModel *newmodel) | ||
2470 | { | 2757 | { | ||
2471 | if (oldmodel) { | 2758 | if (oldmodel) { | ||
2472 | oldmodel->disconnect(this); | 2759 | oldmodel->disconnect(this); | ||
2473 | } | 2760 | } | ||
2474 | if (newmodel) { | 2761 | if (newmodel) { | ||
▲ Show 20 Lines • Show All 425 Lines • Show Last 20 Lines |
You could do that via QPointer, if the delegate is QObject base. It's a poor man's solution which has many issues on its own, though. Maybe it's better to simply assume the user uses the interface correctly...