blob: d987633d94cfce79452cc6bb5b5634f710eaf62e [file] [log] [blame]
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -07001#include <QtGui>
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -07002#include <vector>
3#include <iostream>
4#include <assert.h>
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -07005#include <boost/lexical_cast.hpp>
Zhenkai Zhu21d75f92012-06-04 21:23:34 -07006#include <memory>
7#include "digesttreescene.h"
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -07008
9static const double Pi = 3.14159265358979323846264338327950288419717;
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -070010
Zhenkai Zhud13acd02012-06-04 15:25:20 -070011
12DigestTreeScene::DisplayUserPtr DigestTreeScene::DisplayUserNullPtr;
13
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -070014DigestTreeScene::DigestTreeScene(QWidget *parent)
15 : QGraphicsScene(parent)
16{
Zhenkai Zhud13acd02012-06-04 15:25:20 -070017 previouslyUpdatedUser = DisplayUserNullPtr;
Zhenkai Zhu6fcdee42012-05-30 17:02:49 -070018}
19
20void
Zhenkai Zhu82a62752012-06-04 17:11:04 -070021DigestTreeScene::processUpdate(const std::vector<Sync::MissingDataInfo> &v, QString digest)
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070022{
23 int n = v.size();
24 bool rePlot = false;
25 for (int i = 0; i < n; i++)
26 {
27 Roster_iterator it = m_roster.find(v[i].prefix.c_str());
28 if (it == m_roster.end()) {
29 rePlot = true;
30 DisplayUserPtr p(new DisplayUser());
31 p->setPrefix(v[i].prefix.c_str());
32 p->setSeq(v[i].high);
33 m_roster.insert(p->getPrefix(), p);
34 }
35 }
36
37 if (rePlot)
38 {
39 plot(digest);
40 }
41 else
42 {
43 for (int i = 0; i < n; i++)
44 {
45 Roster_iterator it = m_roster.find(v[i].prefix.c_str());
46 if (it != m_roster.end()) {
47 DisplayUserPtr p = it.value();
48 QGraphicsTextItem *item = p->getSeqTextItem();
Zhenkai Zhud13acd02012-06-04 15:25:20 -070049 QGraphicsRectItem *rectItem = p->getInnerRectItem();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070050 std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
51 item->setPlainText(s.c_str());
Zhenkai Zhud13acd02012-06-04 15:25:20 -070052 QRectF textBR = item->boundingRect();
53 QRectF rectBR = rectItem->boundingRect();
54 item->setPos(rectBR.x() + (rectBR.width() - textBR.width())/2, rectBR.y() + (rectBR.height() - textBR.height())/2);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070055 }
56 }
57 m_rootDigest->setPlainText(digest);
58 }
59}
60
61void
62DigestTreeScene::msgReceived(QString prefix, QString nick)
63{
64 Roster_iterator it = m_roster.find(prefix);
65 if (it != m_roster.end())
66 {
67 DisplayUserPtr p = it.value();
68 if (nick != p->getNick()) {
69 p->setNick(nick);
70 QGraphicsTextItem *nickItem = p->getNickTextItem();
Zhenkai Zhud13acd02012-06-04 15:25:20 -070071 QGraphicsRectItem *nickRectItem = p->getNickRectItem();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070072 nickItem->setPlainText(p->getNick());
Zhenkai Zhud13acd02012-06-04 15:25:20 -070073 QRectF rectBR = nickRectItem->boundingRect();
74 QRectF nickBR = nickItem->boundingRect();
75 nickItem->setPos(rectBR.x() + (rectBR.width() - nickBR.width())/2, rectBR.y() + 5);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070076 }
Zhenkai Zhud13acd02012-06-04 15:25:20 -070077
78 reDrawNode(p, Qt::red);
79
80 if (previouslyUpdatedUser != DisplayUserNullPtr)
81 {
82 reDrawNode(previouslyUpdatedUser, Qt::darkBlue);
83 }
84
85 previouslyUpdatedUser = p;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070086 }
87}
88
89void
Zhenkai Zhu82a62752012-06-04 17:11:04 -070090DigestTreeScene::clearAll()
91{
92 clear();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070093 m_roster.clear();
94}
95
96void
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070097DigestTreeScene::plot(QString digest)
98{
Zhenkai Zhu6fcdee42012-05-30 17:02:49 -070099 clear();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700100
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700101 int nodeSize = 40;
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700102
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700103 int siblingDistance = 100, levelDistance = 100;
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700104 std::auto_ptr<TreeLayout> layout(new OneLevelTreeLayout());
105 layout->setSiblingDistance(siblingDistance);
106 layout->setLevelDistance(levelDistance);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700107
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700108 int n = m_roster.size();
109 std::vector<TreeLayout::Coordinate> childNodesCo(n);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700110
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700111 layout->setOneLevelLayout(childNodesCo);
112
113 plotEdge(childNodesCo, nodeSize);
114 plotNode(childNodesCo, digest, nodeSize);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700115
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700116 previouslyUpdatedUser = DisplayUserNullPtr;
117
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700118}
119
120void
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700121DigestTreeScene::plotEdge(const std::vector<TreeLayout::Coordinate> &childNodesCo, int nodeSize)
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700122{
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700123 int n = childNodesCo.size();
124 for (int i = 0; i < n; i++) {
125 double x1 = 0.0, y1 = 0.0;
126 double x2 = childNodesCo[i].x, y2 = childNodesCo[i].y;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700127 QPointF src(x1 + nodeSize/2, y1 + nodeSize/2);
128 QPointF dest(x2 + nodeSize/2, y2 + nodeSize/2);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700129 QLineF line(src, dest);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700130 double angle = ::acos(line.dx() / line.length());
131
132 double arrowSize = 10;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700133 QPointF sourceArrowP0 = src + QPointF((nodeSize/2 + 10) * line.dx() / line.length(), (nodeSize/2 +10) * line.dy() / line.length());
134 QPointF sourceArrowP1 = sourceArrowP0 + QPointF(cos(angle + Pi / 3 - Pi/2) * arrowSize,
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700135 sin(angle + Pi / 3 - Pi/2) * arrowSize);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700136 QPointF sourceArrowP2 = sourceArrowP0 + QPointF(cos(angle + Pi - Pi / 3 - Pi/2) * arrowSize,
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700137 sin(angle + Pi - Pi / 3 - Pi/2) * arrowSize);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700138
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700139 addLine(QLineF(sourceArrowP0, dest), QPen(Qt::black));
140 addPolygon(QPolygonF() << sourceArrowP0<< sourceArrowP1 << sourceArrowP2, QPen(Qt::black), QBrush(Qt::black));
141 }
142}
143
144void
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700145DigestTreeScene::plotNode(const std::vector<TreeLayout::Coordinate> &childNodesCo, QString digest, int nodeSize)
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700146{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700147 RosterIterator it(m_roster);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700148 int n = childNodesCo.size();
149 int rim = 3;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700150
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700151 // plot root node
152 QRectF rootBoundingRect(0, 0, nodeSize, nodeSize);
153 QRectF rootInnerBoundingRect(rim, rim, nodeSize - rim * 2, nodeSize - rim * 2);
154 addRect(rootBoundingRect, QPen(Qt::black), QBrush(Qt::darkRed));
155 addRect(rootInnerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
156 QRectF digestRect(- nodeSize, - nodeSize, 3 * nodeSize, 30);
157 addRect(digestRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
158 QGraphicsTextItem *digestItem = addText(digest);
159 QRectF digestBoundingRect = digestItem->boundingRect();
160 digestItem->setDefaultTextColor(Qt::white);
161 digestItem->setFont(QFont("Cursive", 12, QFont::Bold));
162 digestItem->setPos(- nodeSize + (3 * nodeSize - digestBoundingRect.width()) / 2, - nodeSize + 5);
163 m_rootDigest = digestItem;
164
165 // plot child nodes
166 for (int i = 0; i < n; i++)
167 {
168 if (it.hasNext())
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700169 {
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700170 it.next();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700171 }
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700172 else
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700173 {
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700174 abort();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700175 }
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700176
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700177 double x = childNodesCo[i].x;
178 double y = childNodesCo[i].y;
179 QRectF boundingRect(x, y, nodeSize, nodeSize);
180 QRectF innerBoundingRect(x + rim, y + rim, nodeSize - rim * 2, nodeSize - rim * 2);
181 DisplayUserPtr p = it.value();
182 QGraphicsRectItem *rectItem = addRect(boundingRect, QPen(Qt::black), QBrush(Qt::darkBlue));
183 p->setRimRectItem(rectItem);
184
185 QGraphicsRectItem *innerRectItem = addRect(innerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
186 p->setInnerRectItem(innerRectItem);
187
188 std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
189 QGraphicsTextItem *seqItem = addText(s.c_str());
190 seqItem->setFont(QFont("Cursive", 12, QFont::Bold));
191 QRectF seqBoundingRect = seqItem->boundingRect();
192 seqItem->setPos(x + nodeSize / 2 - seqBoundingRect.width() / 2, y + nodeSize / 2 - seqBoundingRect.height() / 2);
193 p->setSeqTextItem(seqItem);
194
195 QRectF textRect(x - nodeSize / 2, y + nodeSize, 2 * nodeSize, 30);
196 QGraphicsRectItem *nickRectItem = addRect(textRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
197 p->setNickRectItem(nickRectItem);
198 QGraphicsTextItem *nickItem = addText(p->getNick());
199 QRectF textBoundingRect = nickItem->boundingRect();
200 nickItem->setDefaultTextColor(Qt::white);
201 nickItem->setFont(QFont("Cursive", 12, QFont::Bold));
202 nickItem->setPos(x + nodeSize / 2 - textBoundingRect.width() / 2, y + nodeSize + 5);
203 p->setNickTextItem(nickItem);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700204 }
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700205
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700206}
207
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700208void
209DigestTreeScene::reDrawNode(DisplayUserPtr p, QColor rimColor)
210{
211 QGraphicsRectItem *rimItem = p->getRimRectItem();
212 rimItem->setBrush(QBrush(rimColor));
213 QGraphicsRectItem *innerItem = p->getInnerRectItem();
214 innerItem->setBrush(QBrush(Qt::lightGray));
215 QGraphicsTextItem *seqTextItem = p->getSeqTextItem();
216 std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
217 seqTextItem->setPlainText(s.c_str());
218 QRectF textBR = seqTextItem->boundingRect();
219 QRectF innerBR = innerItem->boundingRect();
220 seqTextItem->setPos(innerBR.x() + (innerBR.width() - textBR.width())/2, innerBR.y() + (innerBR.height() - textBR.height())/2);
221}
222