Changeset View
Standalone View
src/view/kateviewhelpers.cpp
Show All 21 Lines | 1 | /* This file is part of the KDE libraries | |||
---|---|---|---|---|---|
22 | Boston, MA 02110-1301, USA. | 22 | Boston, MA 02110-1301, USA. | ||
23 | */ | 23 | */ | ||
24 | 24 | | |||
25 | #include "kateviewhelpers.h" | 25 | #include "kateviewhelpers.h" | ||
26 | 26 | | |||
27 | #include "katecmd.h" | 27 | #include "katecmd.h" | ||
28 | #include <ktexteditor/attribute.h> | 28 | #include <ktexteditor/attribute.h> | ||
29 | #include <ktexteditor/annotationinterface.h> | 29 | #include <ktexteditor/annotationinterface.h> | ||
30 | #include <ktexteditor/abstractannotationitemdelegate.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" | ||
35 | #include "kateview.h" | 36 | #include "kateview.h" | ||
36 | #include "kateviewinternal.h" | 37 | #include "kateviewinternal.h" | ||
37 | #include "katelayoutcache.h" | 38 | #include "katelayoutcache.h" | ||
▲ Show 20 Lines • Show All 1579 Lines • ▼ Show 20 Line(s) | 1589 | { | |||
1617 | } else { | 1618 | } else { | ||
1618 | QPointF points[3] = { middle + QPointF(-halfSizeP, -halfSize), middle + QPointF(-halfSizeP, halfSize), middle + QPointF(halfSizeP, 0) }; | 1619 | QPointF points[3] = { middle + QPointF(-halfSizeP, -halfSize), middle + QPointF(-halfSizeP, halfSize), middle + QPointF(halfSizeP, 0) }; | ||
1619 | painter.drawConvexPolygon(points, 3); | 1620 | painter.drawConvexPolygon(points, 3); | ||
1620 | } | 1621 | } | ||
1621 | 1622 | | |||
1622 | painter.setRenderHint(QPainter::Antialiasing, false); | 1623 | painter.setRenderHint(QPainter::Antialiasing, false); | ||
1623 | } | 1624 | } | ||
1624 | 1625 | | |||
1626 | class KateAnnotationGroupIdentifier | ||||
1627 | { | ||||
1628 | public: | ||||
1629 | KateAnnotationGroupIdentifier(const QVariant &identifier) | ||||
1630 | : m_isValid(identifier.isValid() && identifier.canConvert<QString>()) | ||||
1631 | , m_id(m_isValid ? identifier.toString() : QString()) | ||||
1632 | { | ||||
1633 | } | ||||
1634 | KateAnnotationGroupIdentifier() = default; | ||||
1635 | KateAnnotationGroupIdentifier(const KateAnnotationGroupIdentifier &rhs) = default; | ||||
1636 | | ||||
1637 | KateAnnotationGroupIdentifier& operator=(const KateAnnotationGroupIdentifier &rhs) | ||||
1638 | { | ||||
1639 | m_isValid = rhs.m_isValid; | ||||
1640 | m_id = rhs.m_id; | ||||
1641 | return *this; | ||||
1642 | } | ||||
1643 | KateAnnotationGroupIdentifier& operator=(const QVariant &identifier) | ||||
1644 | { | ||||
1645 | m_isValid = (identifier.isValid() && identifier.canConvert<QString>()); | ||||
1646 | if (m_isValid) { | ||||
1647 | m_id = identifier.toString(); | ||||
1648 | } else { | ||||
1649 | m_id.clear(); | ||||
1650 | } | ||||
1651 | return *this; | ||||
1652 | } | ||||
1653 | | ||||
1654 | bool operator==(const KateAnnotationGroupIdentifier &rhs) const | ||||
1655 | { | ||||
1656 | return (m_isValid == rhs.m_isValid) && (!m_isValid || (m_id == rhs.m_id)); | ||||
1657 | } | ||||
1658 | bool operator!=(const KateAnnotationGroupIdentifier &rhs) const | ||||
1659 | { | ||||
1660 | return (m_isValid != rhs.m_isValid) || (m_isValid && (m_id != rhs.m_id)); | ||||
1661 | } | ||||
1662 | | ||||
1663 | void clear() | ||||
1664 | { | ||||
1665 | m_isValid = false; | ||||
1666 | m_id.clear(); | ||||
1667 | } | ||||
1668 | bool isValid() const { return m_isValid; } | ||||
1669 | const QString& id() const { return m_id; } | ||||
1670 | | ||||
1671 | private: | ||||
1672 | bool m_isValid = false; | ||||
1673 | QString m_id; | ||||
1674 | }; | ||||
1675 | | ||||
1676 | class KateAnnotationGroupPositionState | ||||
1677 | { | ||||
1678 | public: | ||||
1679 | KateAnnotationGroupPositionState(KateViewInternal *viewInternal, | ||||
1680 | KTextEditor::AnnotationModel *model, | ||||
1681 | uint startz, | ||||
1682 | bool isUsed); | ||||
1683 | void nextLine(uint z, int realLine, | ||||
1684 | const QString &highlightedAnnotationGroupIdentifier, | ||||
1685 | KTextEditor::StyleOptionAnnotationItem &styleOption); | ||||
1686 | | ||||
1687 | private: | ||||
1688 | KateViewInternal *m_viewInternal; | ||||
1689 | KTextEditor::AnnotationModel *m_model = nullptr; | ||||
1690 | | ||||
1691 | int m_visibleWrappedLineInAnnotationGroup = -1; | ||||
1692 | KateAnnotationGroupIdentifier m_lastAnnotationGroupIdentifier; | ||||
1693 | KateAnnotationGroupIdentifier m_nextAnnotationGroupIdentifier; | ||||
1694 | bool m_isSameAnnotationGroupsSinceLast = false; | ||||
1695 | }; | ||||
1696 | | ||||
1697 | KateAnnotationGroupPositionState::KateAnnotationGroupPositionState(KateViewInternal *viewInternal, | ||||
1698 | KTextEditor::AnnotationModel *model, | ||||
1699 | uint startz, | ||||
1700 | bool isUsed) | ||||
1701 | : m_viewInternal(viewInternal) | ||||
1702 | , m_model(model) | ||||
1703 | { | ||||
1704 | if (!isUsed) { | ||||
1705 | return; | ||||
1706 | } | ||||
1707 | | ||||
1708 | if (!m_model || (startz >= m_viewInternal->cache()->viewCacheLineCount())) { | ||||
1709 | return; | ||||
1710 | } | ||||
1711 | | ||||
1712 | const auto realLineAtStart = m_viewInternal->cache()->viewLine(startz).line(); | ||||
1713 | m_nextAnnotationGroupIdentifier = m_model->data(realLineAtStart, | ||||
1714 | (Qt::ItemDataRole)KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1715 | if (m_nextAnnotationGroupIdentifier.isValid()) { | ||||
1716 | // estimate state of annotation group before first rendered line | ||||
1717 | if (startz == 0) { | ||||
1718 | if (realLineAtStart > 0) { | ||||
1719 | // TODO: here we would want to scan until the next line that would be displayed, | ||||
1720 | // to see if there are any group changes until then | ||||
1721 | // for now simply taking neighbour line into account, not a grave bug on the first displayed line | ||||
1722 | m_lastAnnotationGroupIdentifier = m_model->data(realLineAtStart - 1, | ||||
1723 | (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1724 | m_isSameAnnotationGroupsSinceLast = (m_lastAnnotationGroupIdentifier == m_nextAnnotationGroupIdentifier); | ||||
1725 | } | ||||
1726 | } else { | ||||
1727 | const auto realLineBeforeStart = m_viewInternal->cache()->viewLine(startz-1).line(); | ||||
1728 | m_lastAnnotationGroupIdentifier = m_model->data(realLineBeforeStart, (Qt::ItemDataRole)KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1729 | if (m_lastAnnotationGroupIdentifier.isValid()) { | ||||
1730 | if (m_lastAnnotationGroupIdentifier.id() == m_nextAnnotationGroupIdentifier.id()) { | ||||
1731 | m_isSameAnnotationGroupsSinceLast = true; | ||||
1732 | // estimate m_visibleWrappedLineInAnnotationGroup | ||||
1733 | m_visibleWrappedLineInAnnotationGroup = 0; | ||||
1734 | for (uint z = startz - 1; z > 0; --z) { | ||||
1735 | const auto realLine = m_viewInternal->cache()->viewLine(startz-1).line(); | ||||
1736 | const KateAnnotationGroupIdentifier identifier = m_model->data(realLine, (Qt::ItemDataRole)KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1737 | if (identifier != m_lastAnnotationGroupIdentifier) { | ||||
1738 | break; | ||||
1739 | } | ||||
1740 | ++m_visibleWrappedLineInAnnotationGroup; | ||||
1741 | } | ||||
1742 | } | ||||
1743 | } | ||||
1744 | } | ||||
1745 | } | ||||
1746 | } | ||||
1747 | | ||||
1748 | void KateAnnotationGroupPositionState::nextLine(uint z, int realLine, | ||||
1749 | const QString &highlightedAnnotationGroupIdentifier, | ||||
1750 | KTextEditor::StyleOptionAnnotationItem &styleOption) | ||||
1751 | { | ||||
1752 | styleOption.wrappedLine = m_viewInternal->cache()->viewLine(z).viewLine(); | ||||
1753 | styleOption.wrappedLineCount = m_viewInternal->cache()->viewLineCount(realLine); | ||||
1754 | | ||||
1755 | // Estimate position in group | ||||
1756 | const KateAnnotationGroupIdentifier annotationGroupIdentifier = m_nextAnnotationGroupIdentifier; | ||||
1757 | bool isSameAnnotationGroupsSinceThis = false; | ||||
1758 | // Calculate next line's group identifier | ||||
1759 | // shortcut: assuming wrapped lines are always displayed together, test is simple | ||||
1760 | if (styleOption.wrappedLine+1 < styleOption.wrappedLineCount) { | ||||
1761 | m_nextAnnotationGroupIdentifier = annotationGroupIdentifier; | ||||
1762 | isSameAnnotationGroupsSinceThis = true; | ||||
1763 | } else { | ||||
1764 | if (z+1 < m_viewInternal->cache()->viewCacheLineCount()) { | ||||
1765 | const int realLineAfter = m_viewInternal->cache()->viewLine(z+1).line(); | ||||
1766 | // search for any realLine with a different group id, also the non-displayed | ||||
1767 | int rl = realLine + 1; | ||||
1768 | for (; rl <= realLineAfter; ++rl) { | ||||
1769 | m_nextAnnotationGroupIdentifier = m_model->data(rl, (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1770 | if (!m_nextAnnotationGroupIdentifier.isValid() || | ||||
1771 | (m_nextAnnotationGroupIdentifier.id() != annotationGroupIdentifier.id())) { | ||||
1772 | break; | ||||
1773 | } | ||||
1774 | } | ||||
1775 | isSameAnnotationGroupsSinceThis = (rl > realLineAfter); | ||||
1776 | if (rl < realLineAfter) { | ||||
1777 | m_nextAnnotationGroupIdentifier = m_model->data(realLineAfter, (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole); | ||||
1778 | } | ||||
1779 | } else { | ||||
1780 | // TODO: check next line after display end | ||||
1781 | m_nextAnnotationGroupIdentifier.clear(); | ||||
1782 | isSameAnnotationGroupsSinceThis = false; | ||||
1783 | } | ||||
1784 | } | ||||
1785 | | ||||
1786 | if (annotationGroupIdentifier.isValid()) { | ||||
1787 | styleOption.highlight = (highlightedAnnotationGroupIdentifier == annotationGroupIdentifier.id()); | ||||
1788 | | ||||
1789 | if (m_isSameAnnotationGroupsSinceLast) { | ||||
1790 | ++m_visibleWrappedLineInAnnotationGroup; | ||||
1791 | } else { | ||||
1792 | m_visibleWrappedLineInAnnotationGroup = 0; | ||||
1793 | } | ||||
1794 | | ||||
1795 | styleOption.annotationItemGroupingPosition = | ||||
1796 | (m_isSameAnnotationGroupsSinceLast && isSameAnnotationGroupsSinceThis) ? | ||||
1797 | StyleOptionAnnotationItem::Middle : | ||||
1798 | (m_isSameAnnotationGroupsSinceLast) ? | ||||
1799 | StyleOptionAnnotationItem::End : | ||||
1800 | (isSameAnnotationGroupsSinceThis) ? | ||||
1801 | StyleOptionAnnotationItem::Beginning : | ||||
1802 | /* else */ | ||||
1803 | StyleOptionAnnotationItem::OnlyOne; | ||||
1804 | } else { | ||||
1805 | m_visibleWrappedLineInAnnotationGroup = 0; | ||||
1806 | } | ||||
1807 | styleOption.visibleWrappedLineInGroup = m_visibleWrappedLineInAnnotationGroup; | ||||
1808 | | ||||
1809 | m_lastAnnotationGroupIdentifier = m_nextAnnotationGroupIdentifier; | ||||
1810 | m_isSameAnnotationGroupsSinceLast = isSameAnnotationGroupsSinceThis; | ||||
1811 | } | ||||
1812 | | ||||
1813 | | ||||
1625 | void KateIconBorder::paintBorder(int /*x*/, int y, int /*width*/, int height) | 1814 | void KateIconBorder::paintBorder(int /*x*/, int y, int /*width*/, int height) | ||
1626 | { | 1815 | { | ||
1627 | uint h = m_view->renderer()->lineHeight(); | 1816 | uint h = m_view->renderer()->lineHeight(); | ||
1628 | uint startz = (y / h); | 1817 | uint startz = (y / h); | ||
1629 | uint endz = startz + 1 + (height / h); | 1818 | uint endz = startz + 1 + (height / h); | ||
1630 | uint lineRangesSize = m_viewInternal->cache()->viewCacheLineCount(); | 1819 | uint lineRangesSize = m_viewInternal->cache()->viewCacheLineCount(); | ||
1631 | uint currentLine = m_view->cursorPosition().line(); | 1820 | uint currentLine = m_view->cursorPosition().line(); | ||
1632 | 1821 | | |||
Show All 22 Lines | |||||
1655 | int w(this->width()); // sane value/calc only once | 1844 | int w(this->width()); // sane value/calc only once | ||
1656 | 1845 | | |||
1657 | QPainter p(this); | 1846 | QPainter p(this); | ||
1658 | p.setRenderHints(QPainter::TextAntialiasing); | 1847 | p.setRenderHints(QPainter::TextAntialiasing); | ||
1659 | p.setFont(m_view->renderer()->config()->font()); // for line numbers | 1848 | p.setFont(m_view->renderer()->config()->font()); // for line numbers | ||
1660 | 1849 | | |||
1661 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 1850 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
1662 | m_view->annotationModel() : m_doc->annotationModel(); | 1851 | m_view->annotationModel() : m_doc->annotationModel(); | ||
1852 | KateAnnotationGroupPositionState annotationGroupPositionState(m_viewInternal, model, | ||||
1853 | startz, m_annotationBorderOn); | ||||
1663 | 1854 | | |||
1664 | for (uint z = startz; z <= endz; z++) { | 1855 | for (uint z = startz; z <= endz; z++) { | ||
1665 | int y = h * z; | 1856 | int y = h * z; | ||
1666 | int realLine = -1; | 1857 | int realLine = -1; | ||
1667 | 1858 | | |||
1668 | if (z < lineRangesSize) { | 1859 | if (z < lineRangesSize) { | ||
1669 | realLine = m_viewInternal->cache()->viewLine(z).line(); | 1860 | realLine = m_viewInternal->cache()->viewLine(z).line(); | ||
1670 | } | 1861 | } | ||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | |||||
1716 | } | 1907 | } | ||
1717 | 1908 | | |||
1718 | // annotation information | 1909 | // annotation information | ||
1719 | if (m_annotationBorderOn) { | 1910 | if (m_annotationBorderOn) { | ||
1720 | // Draw a border line between annotations and the line numbers | 1911 | // Draw a border line between annotations and the line numbers | ||
1721 | p.setPen(m_view->renderer()->config()->lineNumberColor()); | 1912 | p.setPen(m_view->renderer()->config()->lineNumberColor()); | ||
1722 | p.setBrush(m_view->renderer()->config()->lineNumberColor()); | 1913 | p.setBrush(m_view->renderer()->config()->lineNumberColor()); | ||
1723 | 1914 | | |||
1724 | int borderWidth = m_annotationBorderWidth; | 1915 | const int borderX = lnX + m_annotationBorderWidth; | ||
1725 | p.drawLine(lnX + borderWidth + 1, y, lnX + borderWidth + 1, y + h); | 1916 | p.drawLine(borderX, y, borderX, y + h); | ||
1726 | 1917 | | |||
1727 | if ((realLine > -1) && model) { | 1918 | if ((realLine > -1) && model) { | ||
1728 | // Fetch data from the model | 1919 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||
1729 | QVariant text = model->data(realLine, Qt::DisplayRole); | 1920 | initStyleOption(&styleOption); | ||
1730 | QVariant foreground = model->data(realLine, Qt::ForegroundRole); | 1921 | styleOption.rect.setRect(lnX, y, m_annotationBorderWidth, h); | ||
1731 | QVariant background = model->data(realLine, Qt::BackgroundRole); | | |||
1732 | // Fill the background | | |||
1733 | if (background.isValid()) { | | |||
1734 | p.fillRect(lnX, y, borderWidth + 1, h, background.value<QBrush>()); | | |||
1735 | } | | |||
1736 | // Set the pen for drawing the foreground | | |||
1737 | if (foreground.isValid()) { | | |||
1738 | p.setPen(foreground.value<QPen>()); | | |||
1739 | } | | |||
1740 | 1922 | | |||
1741 | // Draw a border around all adjacent entries that have the same text as the currently hovered one | 1923 | annotationGroupPositionState.nextLine(z, realLine, m_hoveredAnnotationGroupIdentifier, | ||
1742 | const QVariant identifier = model->data( realLine, (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole ); | 1924 | styleOption); | ||
1743 | if( m_hoveredAnnotationGroupIdentifier == identifier.toString() ) { | | |||
1744 | p.drawLine(lnX, y, lnX, y + h); | | |||
1745 | p.drawLine(lnX + borderWidth, y, lnX + borderWidth, y + h); | | |||
1746 | 1925 | | |||
1747 | QVariant beforeText = model->data(realLine - 1, Qt::DisplayRole); | 1926 | m_view->annotationItemDelegate()->paint(&p, styleOption, model, realLine); | ||
1748 | QVariant afterText = model->data(realLine + 1, Qt::DisplayRole); | | |||
1749 | if (((beforeText.isValid() && beforeText.canConvert<QString>() | | |||
1750 | && text.isValid() && text.canConvert<QString>() | | |||
1751 | && beforeText.toString() != text.toString()) || realLine == 0) | | |||
1752 | && m_viewInternal->cache()->viewLine(z).viewLine() == 0) { | | |||
1753 | p.drawLine(lnX + 1, y, lnX + borderWidth, y); | | |||
1754 | } | 1927 | } | ||
1755 | 1928 | | |||
1756 | if (((afterText.isValid() && afterText.canConvert<QString>() | 1929 | // adjust current X position | ||
1757 | && text.isValid() && text.canConvert<QString>() | 1930 | lnX += m_annotationBorderWidth + /* separator line width */1; | ||
1758 | && afterText.toString() != text.toString()) | | |||
1759 | || realLine == m_view->doc()->lines() - 1) | | |||
1760 | && m_viewInternal->cache()->viewLine(z).viewLine() == m_viewInternal->cache()->viewLineCount(realLine) - 1) { | | |||
1761 | p.drawLine(lnX + 1, y + h - 1, lnX + borderWidth, y + h - 1); | | |||
1762 | } | | |||
1763 | } | | |||
1764 | if (foreground.isValid()) { | | |||
1765 | QPen pen = p.pen(); | | |||
1766 | pen.setWidth(1); | | |||
1767 | p.setPen(pen); | | |||
1768 | } | | |||
1769 | | ||||
1770 | // Now draw the normal text | | |||
1771 | if (text.isValid() && text.canConvert<QString>() && (m_viewInternal->cache()->viewLine(z).startCol() == 0)) { | | |||
1772 | p.drawText(lnX + 3, y, borderWidth - 3, h, Qt::AlignLeft | Qt::AlignVCenter, text.toString()); | | |||
1773 | } | | |||
1774 | } | | |||
1775 | | ||||
1776 | // adjust current X position and reset the pen and brush | | |||
1777 | lnX += borderWidth + 2; | | |||
1778 | } | 1931 | } | ||
1779 | 1932 | | |||
1780 | // line number | 1933 | // line number | ||
1781 | if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { | 1934 | if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { | ||
1782 | if (realLine > -1) { | 1935 | if (realLine > -1) { | ||
1783 | int distanceToCurrent = abs(realLine - static_cast<int>(currentLine)); | 1936 | int distanceToCurrent = abs(realLine - static_cast<int>(currentLine)); | ||
1784 | QColor color; | 1937 | QColor color; | ||
1785 | 1938 | | |||
▲ Show 20 Lines • Show All 315 Lines • ▼ Show 20 Line(s) | 2253 | } else { | |||
2101 | hideBlock(); | 2254 | hideBlock(); | ||
2102 | } | 2255 | } | ||
2103 | if (positionToArea(e->pos()) == AnnotationBorder) { | 2256 | if (positionToArea(e->pos()) == AnnotationBorder) { | ||
2104 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2257 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
2105 | m_view->annotationModel() : m_doc->annotationModel(); | 2258 | m_view->annotationModel() : m_doc->annotationModel(); | ||
2106 | if (model) { | 2259 | if (model) { | ||
2107 | m_hoveredAnnotationGroupIdentifier = model->data( t.line(), | 2260 | m_hoveredAnnotationGroupIdentifier = model->data( t.line(), | ||
2108 | (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole ).toString(); | 2261 | (Qt::ItemDataRole) KTextEditor::AnnotationModel::GroupIdentifierRole ).toString(); | ||
2109 | showAnnotationTooltip(t.line(), e->globalPos()); | 2262 | const QPoint viewRelativePos = m_viewInternal->mapFromGlobal(e->globalPos()); | ||
2263 | QHelpEvent helpEvent(QEvent::ToolTip, viewRelativePos, e->globalPos()); | ||||
2264 | m_view->annotationItemDelegate()->helpEvent(&helpEvent, m_view, model, t.line()); | ||||
2265 | | ||||
2110 | QTimer::singleShot(0, this, SLOT(update())); | 2266 | QTimer::singleShot(0, this, SLOT(update())); | ||
2111 | } | 2267 | } | ||
2112 | } else { | 2268 | } else { | ||
2113 | if (positionToArea(e->pos()) == IconBorder) { | 2269 | if (positionToArea(e->pos()) == IconBorder) { | ||
2114 | m_doc->requestMarkTooltip(t.line(), e->globalPos()); | 2270 | m_doc->requestMarkTooltip(t.line(), e->globalPos()); | ||
2115 | } | 2271 | } | ||
2116 | 2272 | | |||
2117 | m_hoveredAnnotationGroupIdentifier.clear(); | 2273 | m_hoveredAnnotationGroupIdentifier.clear(); | ||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Line(s) | 2318 | if (area == FoldingMarkers) { | |||
2187 | delete m_foldingPreview; | 2343 | delete m_foldingPreview; | ||
2188 | } | 2344 | } | ||
2189 | 2345 | | |||
2190 | if (area == AnnotationBorder) { | 2346 | if (area == AnnotationBorder) { | ||
2191 | const bool singleClick = style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, this); | 2347 | const bool singleClick = style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, this); | ||
2192 | if (e->button() == Qt::LeftButton && singleClick) { | 2348 | if (e->button() == Qt::LeftButton && singleClick) { | ||
2193 | emit m_view->annotationActivated(m_view, cursorOnLine); | 2349 | emit m_view->annotationActivated(m_view, cursorOnLine); | ||
2194 | } else if (e->button() == Qt::RightButton) { | 2350 | } else if (e->button() == Qt::RightButton) { | ||
2195 | showAnnotationMenu(cursorOnLine, e->globalPos()); | 2351 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
2352 | m_view->annotationModel() : m_doc->annotationModel(); | ||||
2353 | const QPoint pos = m_view->mapFromGlobal(e->globalPos()); | ||||
2354 | m_view->annotationItemDelegate()->contextMenuRequested(pos, model, cursorOnLine); | ||||
2196 | } | 2355 | } | ||
2197 | } | 2356 | } | ||
2198 | } | 2357 | } | ||
2199 | 2358 | | |||
2200 | QMouseEvent forward(QEvent::MouseButtonRelease, | 2359 | QMouseEvent forward(QEvent::MouseButtonRelease, | ||
2201 | QPoint(0, e->y()), e->button(), e->buttons(), e->modifiers()); | 2360 | QPoint(0, e->y()), e->button(), e->buttons(), e->modifiers()); | ||
2202 | m_viewInternal->mouseReleaseEvent(&forward); | 2361 | m_viewInternal->mouseReleaseEvent(&forward); | ||
2203 | } | 2362 | } | ||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Line(s) | 2450 | } else { | |||
2293 | if (m_doc->mark(line) & markType) { | 2452 | if (m_doc->mark(line) & markType) { | ||
2294 | m_doc->removeMark(line, markType); | 2453 | m_doc->removeMark(line, markType); | ||
2295 | } else { | 2454 | } else { | ||
2296 | m_doc->addMark(line, markType); | 2455 | m_doc->addMark(line, markType); | ||
2297 | } | 2456 | } | ||
2298 | } | 2457 | } | ||
2299 | } | 2458 | } | ||
2300 | 2459 | | |||
2301 | void KateIconBorder::showAnnotationTooltip(int line, const QPoint &pos) | 2460 | void KateIconBorder::initStyleOption(KTextEditor::StyleOptionAnnotationItem* styleOption) const | ||
2302 | { | 2461 | { | ||
2303 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2462 | styleOption->initFrom(this); | ||
2304 | m_view->annotationModel() : m_doc->annotationModel(); | 2463 | styleOption->view = m_view; | ||
dhaumann: You could do that via QPointer, if the delegate is QObject base. It's a poor man's solution… | |||||
2305 | 2464 | styleOption->contentFontMetrics = m_view->renderer()->config()->fontMetrics(); | |||
2306 | if (model) { | 2465 | // TODO have delegate paint all background or not? | ||
2307 | QVariant data = model->data(line, Qt::ToolTipRole); | 2466 | // styleOption->backgroundBrush = m_view->renderer()->config()->iconBarColor(); | ||
2308 | QString tip = data.toString(); | | |||
2309 | if (!tip.isEmpty()) { | | |||
2310 | QToolTip::showText(pos, data.toString(), this); | | |||
2311 | } | | |||
2312 | } | | |||
2313 | } | 2467 | } | ||
2314 | 2468 | | |||
2315 | int KateIconBorder::annotationLineWidth(int line) | 2469 | void KateIconBorder::updateAnnotationLine(int line) | ||
2316 | { | 2470 | { | ||
2471 | // TODO: where is that magic number from? | ||||
2472 | int width = 8; | ||||
2317 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2473 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
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… | |||||
2318 | m_view->annotationModel() : m_doc->annotationModel(); | 2474 | m_view->annotationModel() : m_doc->annotationModel(); | ||
2319 | 2475 | | |||
2320 | if (model) { | 2476 | if (model) { | ||
2321 | QVariant data = model->data(line, Qt::DisplayRole); | 2477 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||
2322 | return data.toString().length() * m_maxCharWidth + 8; | 2478 | initStyleOption(&styleOption); | ||
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()… | |||||
2323 | } | 2479 | width = m_view->annotationItemDelegate()->sizeHint(styleOption, model, line).width(); | ||
2324 | return 8; | | |||
2325 | } | 2480 | } | ||
2326 | 2481 | | |||
2327 | void KateIconBorder::updateAnnotationLine(int line) | 2482 | if (width > m_annotationBorderWidth) { | ||
2328 | { | 2483 | m_annotationBorderWidth = width; | ||
dhaumann: Maybe 4+4 margin or so? | |||||
2329 | if (annotationLineWidth(line) > m_annotationBorderWidth) { | | |||
2330 | m_annotationBorderWidth = annotationLineWidth(line); | | |||
2331 | updateGeometry(); | 2484 | updateGeometry(); | ||
2332 | 2485 | | |||
2333 | QTimer::singleShot(0, this, SLOT(update())); | 2486 | QTimer::singleShot(0, this, SLOT(update())); | ||
2334 | } | 2487 | } | ||
2335 | } | 2488 | } | ||
2336 | 2489 | | |||
2337 | void KateIconBorder::showAnnotationMenu(int line, const QPoint &pos) | | |||
2338 | { | | |||
2339 | QMenu menu; | | |||
2340 | QAction a(i18n("Disable Annotation Bar"), &menu); | | |||
2341 | a.setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); | | |||
2342 | menu.addAction(&a); | | |||
2343 | emit m_view->annotationContextMenuAboutToShow(m_view, &menu, line); | | |||
2344 | if (menu.exec(pos) == &a) { | | |||
2345 | m_view->setAnnotationBorderVisible(false); | | |||
2346 | } | | |||
2347 | } | | |||
2348 | | ||||
2349 | void KateIconBorder::hideAnnotationTooltip() | 2490 | void KateIconBorder::hideAnnotationTooltip() | ||
2350 | { | 2491 | { | ||
2351 | QToolTip::hideText(); | 2492 | QToolTip::hideText(); | ||
2352 | } | 2493 | } | ||
2353 | 2494 | | |||
2354 | void KateIconBorder::updateAnnotationBorderWidth() | 2495 | void KateIconBorder::updateAnnotationBorderWidth() | ||
2355 | { | 2496 | { | ||
2497 | // TODO: another magic number, not matching the one in updateAnnotationLine() | ||||
2356 | m_annotationBorderWidth = 6; | 2498 | m_annotationBorderWidth = 6; | ||
2357 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | 2499 | KTextEditor::AnnotationModel *model = m_view->annotationModel() ? | ||
2358 | m_view->annotationModel() : m_doc->annotationModel(); | 2500 | m_view->annotationModel() : m_doc->annotationModel(); | ||
2359 | 2501 | | |||
dhaumann: Again, single shot timer needed? | |||||
2360 | if (model) { | 2502 | if (model) { | ||
2361 | for (int i = 0; i < m_view->doc()->lines(); i++) { | 2503 | KTextEditor::StyleOptionAnnotationItem styleOption; | ||
2362 | int curwidth = annotationLineWidth(i); | 2504 | initStyleOption(&styleOption); | ||
2505 | | ||||
2506 | const int lineCount = m_view->doc()->lines(); | ||||
2507 | if (lineCount > 0) { | ||||
2508 | const int checkedLineCount = m_view->uniformAnnotationItemSizes() ? 1 : lineCount; | ||||
2509 | for (int i = 0; i < checkedLineCount; ++i) { | ||||
2510 | const int curwidth = m_view->annotationItemDelegate()->sizeHint(styleOption, model, i).width(); | ||||
2363 | if (curwidth > m_annotationBorderWidth) { | 2511 | if (curwidth > m_annotationBorderWidth) { | ||
2364 | m_annotationBorderWidth = curwidth; | 2512 | m_annotationBorderWidth = curwidth; | ||
2365 | } | 2513 | } | ||
2366 | } | 2514 | } | ||
2367 | } | 2515 | } | ||
2516 | } | ||||
2368 | 2517 | | |||
2369 | updateGeometry(); | 2518 | updateGeometry(); | ||
2370 | 2519 | | |||
2371 | QTimer::singleShot(0, this, SLOT(update())); | 2520 | QTimer::singleShot(0, this, SLOT(update())); | ||
2372 | } | 2521 | } | ||
2373 | 2522 | | |||
2374 | void KateIconBorder::annotationModelChanged(KTextEditor::AnnotationModel *oldmodel, KTextEditor::AnnotationModel *newmodel) | 2523 | void KateIconBorder::annotationModelChanged(KTextEditor::AnnotationModel *oldmodel, KTextEditor::AnnotationModel *newmodel) | ||
2375 | { | 2524 | { | ||
▲ Show 20 Lines • Show All 429 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...