Chris@57
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@46
|
2
|
Chris@57
|
3 /*
|
Chris@57
|
4 EasyMercurial
|
Chris@57
|
5
|
Chris@57
|
6 Based on HgExplorer by Jari Korhonen
|
Chris@57
|
7 Copyright (c) 2010 Jari Korhonen
|
Chris@644
|
8 Copyright (c) 2013 Chris Cannam
|
Chris@644
|
9 Copyright (c) 2013 Queen Mary, University of London
|
Chris@57
|
10
|
Chris@57
|
11 This program is free software; you can redistribute it and/or
|
Chris@57
|
12 modify it under the terms of the GNU General Public License as
|
Chris@57
|
13 published by the Free Software Foundation; either version 2 of the
|
Chris@57
|
14 License, or (at your option) any later version. See the file
|
Chris@57
|
15 COPYING included with this distribution for more information.
|
Chris@57
|
16 */
|
Chris@46
|
17
|
Chris@46
|
18 #include "connectionitem.h"
|
Chris@145
|
19 #include "uncommitteditem.h"
|
Chris@46
|
20
|
Chris@46
|
21 #include "changesetitem.h"
|
Chris@53
|
22 #include "changeset.h"
|
Chris@53
|
23 #include "colourset.h"
|
Chris@516
|
24 #include "textabbrev.h"
|
Chris@678
|
25 #include "common.h"
|
Chris@46
|
26
|
Chris@46
|
27 #include <QPainter>
|
Chris@516
|
28 #include <QFont>
|
Chris@46
|
29
|
Chris@46
|
30 QRectF
|
Chris@46
|
31 ConnectionItem::boundingRect() const
|
Chris@46
|
32 {
|
Chris@516
|
33 if (!(m_child || m_uncommitted)) return QRectF();
|
Chris@678
|
34 float xscale = scalePixelSize(100);
|
Chris@678
|
35 float yscale = scalePixelSize(90);
|
Chris@678
|
36 float size = scalePixelSize(50);
|
Chris@145
|
37
|
Chris@145
|
38 int c_col, c_row;
|
Chris@145
|
39 if (m_child) {
|
Chris@145
|
40 c_col = m_child->column(); c_row = m_child->row();
|
Chris@145
|
41 } else {
|
Chris@145
|
42 c_col = m_uncommitted->column(); c_row = m_uncommitted->row();
|
Chris@145
|
43 }
|
Chris@145
|
44
|
Chris@516
|
45 int p_col, p_row;
|
Chris@516
|
46 if (m_parent) {
|
Chris@516
|
47 p_col = m_parent->column(); p_row = m_parent->row();
|
Chris@516
|
48 } else {
|
Chris@516
|
49 p_col = c_col - 1; p_row = c_row + 1;
|
Chris@516
|
50 }
|
Chris@516
|
51
|
Chris@678
|
52 return QRectF(xscale * c_col + size/2 - scalePixelSize(2),
|
Chris@678
|
53 yscale * c_row + size - scalePixelSize(22),
|
Chris@678
|
54 xscale * p_col - xscale * c_col + scalePixelSize(6),
|
Chris@678
|
55 yscale * p_row - yscale * c_row - size + scalePixelSize(44))
|
Chris@46
|
56 .normalized();
|
Chris@46
|
57 }
|
Chris@46
|
58
|
Chris@46
|
59 void
|
Chris@46
|
60 ConnectionItem::paint(QPainter *paint, const QStyleOptionGraphicsItem *, QWidget *)
|
Chris@46
|
61 {
|
Chris@516
|
62 if (!(m_child || m_uncommitted)) return;
|
Chris@46
|
63 QPainterPath p;
|
Chris@53
|
64
|
Chris@53
|
65 paint->save();
|
Chris@53
|
66
|
Chris@506
|
67 int alpha = 255;
|
Chris@506
|
68 if (m_child && m_child->isClosed()) alpha = 90;
|
Chris@506
|
69
|
Chris@53
|
70 ColourSet *colourSet = ColourSet::instance();
|
Chris@145
|
71 QString branch;
|
Chris@145
|
72 if (m_child) branch = m_child->getChangeset()->branch();
|
Chris@145
|
73 else branch = m_uncommitted->branch();
|
Chris@145
|
74 QColor branchColour = colourSet->getColourFor(branch);
|
Chris@145
|
75
|
Chris@506
|
76 branchColour.setAlpha(alpha);
|
Chris@506
|
77
|
Chris@145
|
78 Qt::PenStyle ls = Qt::SolidLine;
|
Chris@145
|
79 if (!m_child) ls = Qt::DashLine;
|
Chris@54
|
80
|
Chris@54
|
81 QTransform t = paint->worldTransform();
|
Chris@54
|
82 float scale = std::min(t.m11(), t.m22());
|
Chris@145
|
83 if (scale < 0.2) {
|
Chris@145
|
84 paint->setPen(QPen(branchColour, 0, ls));
|
Chris@54
|
85 } else {
|
Chris@145
|
86 paint->setPen(QPen(branchColour, 2, ls));
|
Chris@54
|
87 }
|
Chris@53
|
88
|
Chris@678
|
89 float xscale = scalePixelSize(100);
|
Chris@678
|
90 float yscale = scalePixelSize(90);
|
Chris@678
|
91 float size = scalePixelSize(50);
|
Chris@153
|
92 float ygap = yscale - size - 2;
|
Chris@53
|
93
|
Chris@145
|
94 int c_col, c_row;
|
Chris@145
|
95 if (m_child) {
|
Chris@145
|
96 c_col = m_child->column(); c_row = m_child->row();
|
Chris@145
|
97 } else {
|
Chris@145
|
98 c_col = m_uncommitted->column(); c_row = m_uncommitted->row();
|
Chris@145
|
99 }
|
Chris@53
|
100
|
Chris@516
|
101 int p_col, p_row;
|
Chris@516
|
102 if (m_parent) {
|
Chris@516
|
103 p_col = m_parent->column(); p_row = m_parent->row();
|
Chris@516
|
104 } else {
|
Chris@516
|
105 p_col = c_col - 1; p_row = c_row + 1;
|
Chris@516
|
106 }
|
Chris@516
|
107
|
Chris@53
|
108 float c_x = xscale * c_col + size/2;
|
Chris@53
|
109 float p_x = xscale * p_col + size/2;
|
Chris@53
|
110
|
Chris@250
|
111 // ensure line reaches the box, even if it's in a small height --
|
Chris@250
|
112 // doesn't matter if we overshoot as the box is opaque and has a
|
Chris@250
|
113 // greater Z value
|
Chris@678
|
114 p.moveTo(c_x, yscale * c_row + size - scalePixelSize(20));
|
Chris@250
|
115
|
Chris@250
|
116 p.lineTo(c_x, yscale * c_row + size);
|
Chris@53
|
117
|
Chris@53
|
118 if (p_col == c_col) {
|
Chris@53
|
119
|
Chris@53
|
120 p.lineTo(p_x, yscale * p_row);
|
Chris@53
|
121
|
Chris@53
|
122 } else if (m_type == Split || m_type == Normal) {
|
Chris@53
|
123
|
Chris@53
|
124 // place the bulk of the line on the child (i.e. branch) row
|
Chris@53
|
125
|
Chris@53
|
126 if (abs(p_row - c_row) > 1) {
|
Chris@53
|
127 p.lineTo(c_x, yscale * p_row - ygap);
|
Chris@53
|
128 }
|
Chris@53
|
129
|
Chris@53
|
130 p.cubicTo(c_x, yscale * p_row,
|
Chris@53
|
131 p_x, yscale * p_row - ygap,
|
Chris@53
|
132 p_x, yscale * p_row);
|
Chris@53
|
133
|
Chris@53
|
134 } else if (m_type == Merge) {
|
Chris@53
|
135
|
Chris@53
|
136 // place bulk of the line on the parent row
|
Chris@53
|
137
|
Chris@53
|
138 p.cubicTo(c_x, yscale * c_row + size + ygap,
|
Chris@53
|
139 p_x, yscale * c_row + size,
|
Chris@53
|
140 p_x, yscale * c_row + size + ygap);
|
Chris@53
|
141
|
Chris@53
|
142 if (abs(p_row - c_row) > 1) {
|
Chris@53
|
143 p.lineTo(p_x, yscale * p_row);
|
Chris@46
|
144 }
|
Chris@46
|
145 }
|
Chris@53
|
146
|
Chris@516
|
147 if (m_parent) {
|
Chris@387
|
148
|
Chris@516
|
149 // ensure line reaches the node -- again doesn't matter if we
|
Chris@516
|
150 // overshoot
|
Chris@678
|
151 p.lineTo(p_x, yscale * p_row + scalePixelSize(20));
|
Chris@516
|
152
|
Chris@516
|
153 } else {
|
Chris@516
|
154
|
Chris@516
|
155 // no parent: merge from closed branch: draw only half the line
|
Chris@678
|
156 paint->setClipRect(QRectF((c_x + p_x)/2,
|
Chris@678
|
157 yscale * c_row + size - scalePixelSize(22),
|
Chris@516
|
158 xscale, yscale));
|
Chris@516
|
159 }
|
Chris@516
|
160
|
Chris@46
|
161 paint->drawPath(p);
|
Chris@516
|
162
|
Chris@516
|
163 if (!m_parent) {
|
Chris@516
|
164
|
Chris@516
|
165 // merge from closed branch: draw branch name
|
Chris@516
|
166
|
Chris@516
|
167 paint->setClipping(false);
|
Chris@516
|
168
|
Chris@516
|
169 QFont f;
|
Chris@678
|
170 f.setPixelSize(scalePixelSize(11));
|
Chris@516
|
171 f.setBold(true);
|
Chris@516
|
172 f.setItalic(false);
|
Chris@516
|
173 paint->setFont(f);
|
Chris@516
|
174
|
Chris@516
|
175 QString branch = m_mergedBranch;
|
Chris@516
|
176 if (branch == "") branch = "default";
|
Chris@516
|
177 int wid = xscale;
|
Chris@516
|
178 branch = TextAbbrev::abbreviate(branch, QFontMetrics(f), wid);
|
Chris@516
|
179 paint->drawText((c_x + p_x)/2 - wid - 2,
|
Chris@516
|
180 yscale * c_row + size + ygap/2 + 2,
|
Chris@516
|
181 branch);
|
Chris@516
|
182 }
|
Chris@516
|
183
|
Chris@53
|
184 paint->restore();
|
Chris@46
|
185 }
|
Chris@46
|
186
|
Chris@46
|
187
|