1 | #include <LineNumberArea.h> |
2 | |
3 | #include <FileDiffView.h> |
4 | #include <GitQlientStyles.h> |
5 | #include <Colors.h> |
6 | |
7 | #include <QPainter> |
8 | #include <QTextBlock> |
9 | #include <QIcon> |
10 | |
11 | LineNumberArea::LineNumberArea(FileDiffView *editor, bool ) |
12 | : QWidget(editor) |
13 | , mCommentsAllowed(allowComments) |
14 | { |
15 | fileDiffWidget = editor; |
16 | setMouseTracking(true); |
17 | } |
18 | |
19 | int LineNumberArea::widthInDigitsSize() |
20 | { |
21 | return 3; |
22 | } |
23 | |
24 | QSize LineNumberArea::sizeHint() const |
25 | { |
26 | return { fileDiffWidget->lineNumberAreaWidth(), 0 }; |
27 | } |
28 | |
29 | void LineNumberArea::setEditor(FileDiffView *editor) |
30 | { |
31 | fileDiffWidget = editor; |
32 | setParent(editor); |
33 | } |
34 | |
35 | void LineNumberArea::paintEvent(QPaintEvent *event) |
36 | { |
37 | QPainter painter(this); |
38 | |
39 | const auto fontWidth = fileDiffWidget->fontMetrics().horizontalAdvance(QLatin1Char(' ')); |
40 | const auto offset = fontWidth * (mCommentsAllowed ? 4 : 1); |
41 | auto block = fileDiffWidget->firstVisibleBlock(); |
42 | auto blockNumber = block.blockNumber() + fileDiffWidget->mStartingLine; |
43 | auto top = fileDiffWidget->blockBoundingGeometry(block).translated(fileDiffWidget->contentOffset()).top(); |
44 | auto bottom = top + fileDiffWidget->blockBoundingRect(block).height(); |
45 | auto lineCorrection = 0; |
46 | |
47 | while (block.isValid() && top <= event->rect().bottom()) |
48 | { |
49 | |
50 | if (block.isVisible() && bottom >= event->rect().top()) |
51 | { |
52 | const auto skipDeletion |
53 | = fileDiffWidget->mUnified && !block.text().startsWith("-" ) && !block.text().startsWith("@" ); |
54 | |
55 | if (!fileDiffWidget->mUnified || skipDeletion) |
56 | { |
57 | const auto height = fileDiffWidget->fontMetrics().height(); |
58 | const auto number = blockNumber + 1 + lineCorrection; |
59 | painter.setPen(GitQlientStyles::getTextColor()); |
60 | |
61 | if (mBookmarks.contains(number)) |
62 | { |
63 | painter.drawPixmap(6, static_cast<int>(top), height, height, |
64 | QIcon(":/icons/comments" ).pixmap(height, height)); |
65 | |
66 | painter.setPen(gitQlientOrange); |
67 | } |
68 | else if (fileDiffWidget->mRow == number) |
69 | { |
70 | painter.drawPixmap(width() - height - fontWidth, static_cast<int>(top), height, height, |
71 | QIcon(":/icons/add_comment" ).pixmap(height, height)); |
72 | |
73 | painter.setPen(gitQlientOrange); |
74 | } |
75 | |
76 | painter.drawText(0, static_cast<int>(top), width() - offset, height, Qt::AlignRight, |
77 | QString::number(number)); |
78 | } |
79 | else |
80 | --lineCorrection; |
81 | } |
82 | |
83 | block = block.next(); |
84 | top = bottom; |
85 | bottom = top + fileDiffWidget->blockBoundingRect(block).height(); |
86 | ++blockNumber; |
87 | } |
88 | } |
89 | |
90 | void LineNumberArea::mouseMoveEvent(QMouseEvent *e) |
91 | { |
92 | if (mCommentsAllowed) |
93 | { |
94 | if (rect().contains(e->pos())) |
95 | { |
96 | const auto height = width(); |
97 | const auto helpPos = mapFromGlobal(QCursor::pos()); |
98 | const auto x = helpPos.x(); |
99 | if (x >= 0 && x <= height) |
100 | { |
101 | QTextCursor cursor = fileDiffWidget->cursorForPosition(helpPos); |
102 | const auto textRow = cursor.block().blockNumber(); |
103 | auto found = false; |
104 | |
105 | for (const auto &diff : qAsConst(fileDiffWidget->mFileDiffInfo)) |
106 | { |
107 | if (textRow + 1 >= diff.startLine && textRow + 1 <= diff.endLine) |
108 | { |
109 | fileDiffWidget->mRow = textRow + fileDiffWidget->mStartingLine + 1; |
110 | found = true; |
111 | break; |
112 | } |
113 | } |
114 | |
115 | if (!found) |
116 | fileDiffWidget->mRow = -1; |
117 | |
118 | repaint(); |
119 | } |
120 | } |
121 | else |
122 | { |
123 | fileDiffWidget->mRow = -1; |
124 | repaint(); |
125 | } |
126 | } |
127 | } |
128 | |
129 | void LineNumberArea::mousePressEvent(QMouseEvent *e) |
130 | { |
131 | if (mCommentsAllowed) |
132 | mPressed = rect().contains(e->pos()); |
133 | } |
134 | |
135 | void LineNumberArea::mouseReleaseEvent(QMouseEvent *e) |
136 | { |
137 | if (mCommentsAllowed && mPressed && rect().contains(e->pos())) |
138 | { |
139 | const auto height = width(); |
140 | const auto helpPos = mapFromGlobal(QCursor::pos()); |
141 | const auto x = helpPos.x(); |
142 | if (x >= 0 && x <= height) |
143 | { |
144 | const auto cursor = fileDiffWidget->cursorForPosition(helpPos); |
145 | const auto position = cursor.block().blockNumber() + 1; |
146 | const auto row = position + fileDiffWidget->mStartingLine; |
147 | const auto linkId = mBookmarks.value(row, -1); |
148 | |
149 | if (linkId == -1) |
150 | emit addComment(row); |
151 | else |
152 | emit gotoReview(linkId); |
153 | } |
154 | } |
155 | |
156 | mPressed = false; |
157 | } |
158 | |