blob: b0b3d7cec54ad44695b41f95495448eef6ad120a [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());
Zhenkai Zhud1c5a972012-06-05 14:07:41 -070028 if (it == m_roster.end())
29 {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070030 rePlot = true;
31 DisplayUserPtr p(new DisplayUser());
32 p->setPrefix(v[i].prefix.c_str());
33 p->setSeq(v[i].high);
34 m_roster.insert(p->getPrefix(), p);
35 }
Zhenkai Zhud1c5a972012-06-05 14:07:41 -070036 else
37 {
38 it.value()->setSeq(v[i].high);
39 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070040 }
41
42 if (rePlot)
43 {
44 plot(digest);
45 }
46 else
47 {
48 for (int i = 0; i < n; i++)
49 {
50 Roster_iterator it = m_roster.find(v[i].prefix.c_str());
51 if (it != m_roster.end()) {
52 DisplayUserPtr p = it.value();
53 QGraphicsTextItem *item = p->getSeqTextItem();
Zhenkai Zhud13acd02012-06-04 15:25:20 -070054 QGraphicsRectItem *rectItem = p->getInnerRectItem();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070055 std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
56 item->setPlainText(s.c_str());
Zhenkai Zhud13acd02012-06-04 15:25:20 -070057 QRectF textBR = item->boundingRect();
58 QRectF rectBR = rectItem->boundingRect();
59 item->setPos(rectBR.x() + (rectBR.width() - textBR.width())/2, rectBR.y() + (rectBR.height() - textBR.height())/2);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070060 }
61 }
62 m_rootDigest->setPlainText(digest);
63 }
64}
65
66void
67DigestTreeScene::msgReceived(QString prefix, QString nick)
68{
Zhenkai Zhu097bfe72012-06-05 14:30:17 -070069#ifdef __DEBUG
70 std::cout << "Finding " << prefix.toStdString() << std::endl;
71#endif
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070072 Roster_iterator it = m_roster.find(prefix);
73 if (it != m_roster.end())
74 {
75 DisplayUserPtr p = it.value();
76 if (nick != p->getNick()) {
77 p->setNick(nick);
78 QGraphicsTextItem *nickItem = p->getNickTextItem();
Zhenkai Zhud13acd02012-06-04 15:25:20 -070079 QGraphicsRectItem *nickRectItem = p->getNickRectItem();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070080 nickItem->setPlainText(p->getNick());
Zhenkai Zhud13acd02012-06-04 15:25:20 -070081 QRectF rectBR = nickRectItem->boundingRect();
82 QRectF nickBR = nickItem->boundingRect();
83 nickItem->setPos(rectBR.x() + (rectBR.width() - nickBR.width())/2, rectBR.y() + 5);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070084 }
Zhenkai Zhud13acd02012-06-04 15:25:20 -070085
86 reDrawNode(p, Qt::red);
87
Zhenkai Zhud1c5a972012-06-05 14:07:41 -070088 if (previouslyUpdatedUser != DisplayUserNullPtr && previouslyUpdatedUser != p)
Zhenkai Zhud13acd02012-06-04 15:25:20 -070089 {
90 reDrawNode(previouslyUpdatedUser, Qt::darkBlue);
91 }
92
93 previouslyUpdatedUser = p;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -070094 }
Zhenkai Zhu097bfe72012-06-05 14:30:17 -070095#ifdef __DEBUG
96 else
97 {
Zhenkai Zhu59245aa2012-09-26 16:07:04 -070098 std::cout << "Couldn't find prefix, " << prefix.toStdString() << ": let's check"<< std::endl;
Zhenkai Zhu097bfe72012-06-05 14:30:17 -070099 Roster_iterator ii = m_roster.begin();
100 while (ii != m_roster.end())
101 {
102 std::cout <<"Prefix: " << ii.key().toStdString() << std::endl;
103 ++ii;
104 }
105 }
106#endif
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700107}
108
109void
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700110DigestTreeScene::clearAll()
111{
112 clear();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700113 m_roster.clear();
114}
115
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700116bool
117DigestTreeScene::removeNode(const QString prefix)
118{
119 int removedCount = m_roster.remove(prefix);
120 return (removedCount > 0);
121}
122
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700123void
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700124DigestTreeScene::plot(QString digest)
125{
Zhenkai Zhu6fcdee42012-05-30 17:02:49 -0700126 clear();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700127
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700128 int nodeSize = 40;
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700129
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700130 int siblingDistance = 100, levelDistance = 100;
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700131 std::auto_ptr<TreeLayout> layout(new OneLevelTreeLayout());
132 layout->setSiblingDistance(siblingDistance);
133 layout->setLevelDistance(levelDistance);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700134
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700135 int n = m_roster.size();
136 std::vector<TreeLayout::Coordinate> childNodesCo(n);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700137
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700138 layout->setOneLevelLayout(childNodesCo);
139
140 plotEdge(childNodesCo, nodeSize);
141 plotNode(childNodesCo, digest, nodeSize);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700142
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700143 previouslyUpdatedUser = DisplayUserNullPtr;
144
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700145}
146
147void
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700148DigestTreeScene::plotEdge(const std::vector<TreeLayout::Coordinate> &childNodesCo, int nodeSize)
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700149{
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700150 int n = childNodesCo.size();
151 for (int i = 0; i < n; i++) {
152 double x1 = 0.0, y1 = 0.0;
153 double x2 = childNodesCo[i].x, y2 = childNodesCo[i].y;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700154 QPointF src(x1 + nodeSize/2, y1 + nodeSize/2);
155 QPointF dest(x2 + nodeSize/2, y2 + nodeSize/2);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700156 QLineF line(src, dest);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700157 double angle = ::acos(line.dx() / line.length());
158
159 double arrowSize = 10;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700160 QPointF sourceArrowP0 = src + QPointF((nodeSize/2 + 10) * line.dx() / line.length(), (nodeSize/2 +10) * line.dy() / line.length());
161 QPointF sourceArrowP1 = sourceArrowP0 + QPointF(cos(angle + Pi / 3 - Pi/2) * arrowSize,
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700162 sin(angle + Pi / 3 - Pi/2) * arrowSize);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700163 QPointF sourceArrowP2 = sourceArrowP0 + QPointF(cos(angle + Pi - Pi / 3 - Pi/2) * arrowSize,
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700164 sin(angle + Pi - Pi / 3 - Pi/2) * arrowSize);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700165
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700166 addLine(QLineF(sourceArrowP0, dest), QPen(Qt::black));
167 addPolygon(QPolygonF() << sourceArrowP0<< sourceArrowP1 << sourceArrowP2, QPen(Qt::black), QBrush(Qt::black));
168 }
169}
170
171void
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700172DigestTreeScene::plotNode(const std::vector<TreeLayout::Coordinate> &childNodesCo, QString digest, int nodeSize)
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700173{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700174 RosterIterator it(m_roster);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700175 int n = childNodesCo.size();
176 int rim = 3;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700177
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700178 // plot root node
179 QRectF rootBoundingRect(0, 0, nodeSize, nodeSize);
180 QRectF rootInnerBoundingRect(rim, rim, nodeSize - rim * 2, nodeSize - rim * 2);
181 addRect(rootBoundingRect, QPen(Qt::black), QBrush(Qt::darkRed));
182 addRect(rootInnerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700183 QRectF digestRect(- 5.5 * nodeSize , - nodeSize, 12 * nodeSize, 30);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700184 addRect(digestRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
Zhenkai Zhu27df8d42012-06-05 12:04:04 -0700185
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700186 QGraphicsTextItem *digestItem = addText(digest);
187 QRectF digestBoundingRect = digestItem->boundingRect();
Zhenkai Zhu27df8d42012-06-05 12:04:04 -0700188 digestItem->setDefaultTextColor(Qt::black);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700189 digestItem->setFont(QFont("Cursive", 12, QFont::Bold));
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700190 digestItem->setPos(- 4.5 * nodeSize + (12 * nodeSize - digestBoundingRect.width()) / 2, - nodeSize + 5);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700191 m_rootDigest = digestItem;
192
193 // plot child nodes
194 for (int i = 0; i < n; i++)
195 {
196 if (it.hasNext())
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700197 {
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700198 it.next();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700199 }
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700200 else
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700201 {
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700202 abort();
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700203 }
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700204
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700205 double x = childNodesCo[i].x;
206 double y = childNodesCo[i].y;
207 QRectF boundingRect(x, y, nodeSize, nodeSize);
208 QRectF innerBoundingRect(x + rim, y + rim, nodeSize - rim * 2, nodeSize - rim * 2);
209 DisplayUserPtr p = it.value();
210 QGraphicsRectItem *rectItem = addRect(boundingRect, QPen(Qt::black), QBrush(Qt::darkBlue));
211 p->setRimRectItem(rectItem);
212
213 QGraphicsRectItem *innerRectItem = addRect(innerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
214 p->setInnerRectItem(innerRectItem);
215
216 std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
217 QGraphicsTextItem *seqItem = addText(s.c_str());
218 seqItem->setFont(QFont("Cursive", 12, QFont::Bold));
219 QRectF seqBoundingRect = seqItem->boundingRect();
220 seqItem->setPos(x + nodeSize / 2 - seqBoundingRect.width() / 2, y + nodeSize / 2 - seqBoundingRect.height() / 2);
221 p->setSeqTextItem(seqItem);
222
223 QRectF textRect(x - nodeSize / 2, y + nodeSize, 2 * nodeSize, 30);
224 QGraphicsRectItem *nickRectItem = addRect(textRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
225 p->setNickRectItem(nickRectItem);
226 QGraphicsTextItem *nickItem = addText(p->getNick());
227 QRectF textBoundingRect = nickItem->boundingRect();
228 nickItem->setDefaultTextColor(Qt::white);
229 nickItem->setFont(QFont("Cursive", 12, QFont::Bold));
230 nickItem->setPos(x + nodeSize / 2 - textBoundingRect.width() / 2, y + nodeSize + 5);
231 p->setNickTextItem(nickItem);
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700232 }
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700233
Zhenkai Zhuf474a0a2012-05-30 15:06:29 -0700234}
235
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700236void
237DigestTreeScene::reDrawNode(DisplayUserPtr p, QColor rimColor)
238{
239 QGraphicsRectItem *rimItem = p->getRimRectItem();
240 rimItem->setBrush(QBrush(rimColor));
241 QGraphicsRectItem *innerItem = p->getInnerRectItem();
242 innerItem->setBrush(QBrush(Qt::lightGray));
243 QGraphicsTextItem *seqTextItem = p->getSeqTextItem();
244 std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
245 seqTextItem->setPlainText(s.c_str());
246 QRectF textBR = seqTextItem->boundingRect();
247 QRectF innerBR = innerItem->boundingRect();
248 seqTextItem->setPos(innerBR.x() + (innerBR.width() - textBR.width())/2, innerBR.y() + (innerBR.height() - textBR.height())/2);
249}
250