blob: 0704dddbc56c166ac633df77cc9deebb955e0176 [file] [log] [blame]
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -07001#include <QtGui>
2#include "chatdialog.h"
Zhenkai Zhu85845d22012-06-01 23:10:43 -07003#include "settingdialog.h"
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -07004#include <ctime>
Zhenkai Zhub6338822012-05-31 13:27:24 -07005#include <iostream>
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -07006#include <QTimer>
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -07007
Zhenkai Zhu82a62752012-06-04 17:11:04 -07008#define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/sync-demo"
9
Zhenkai Zhu21d75f92012-06-04 21:23:34 -070010void
11ChatDialog::testDraw()
12{
13 std::string prefix[5] = {"/ndn/1", "/ndn/2", "/ndn/3", "/ndn/4", "/ndn/5"};
14 std::string nick[5] = {"tom", "jerry", "jason", "michael", "hurry"};
15 std::vector<Sync::MissingDataInfo> v;
16 for (int i = 0; i < 5; i++)
17 {
18 Sync::MissingDataInfo mdi = {prefix[i], Sync::SeqNo(0), Sync::SeqNo(i * (2 << i) )};
19 v.push_back(mdi);
20 }
21
22 m_scene->processUpdate(v, "12341234@!#%!@");
23
24 for (int i = 0; i < 5; i++)
25 {
26 m_scene-> msgReceived(prefix[i].c_str(), nick[i].c_str());
27 }
28
29 fitView();
30}
31
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070032ChatDialog::ChatDialog(QWidget *parent)
Zhenkai Zhu82a62752012-06-04 17:11:04 -070033 : QDialog(parent), m_sock(NULL)
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070034{
35 setupUi(this);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070036 m_session = time(NULL);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070037
38 readSettings();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070039
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070040 updateLabels();
41
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070042 lineEdit->setFocusPolicy(Qt::StrongFocus);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070043 m_scene = new DigestTreeScene(this);
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070044
Zhenkai Zhu82a62752012-06-04 17:11:04 -070045 treeViewer->setScene(m_scene);
46 m_scene->plot("Empty");
47 QRectF rect = m_scene->itemsBoundingRect();
48 m_scene->setSceneRect(rect);
49
50 // create sync socket
51 if(!m_user.getChatroom().isEmpty()) {
52 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
53 syncPrefix += "/";
54 syncPrefix += m_user.getChatroom().toStdString();
55 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdate, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
56 }
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070057
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070058 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
Zhenkai Zhu85845d22012-06-01 23:10:43 -070059 connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
Zhenkai Zhu21d75f92012-06-04 21:23:34 -070060 testDraw();
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070061}
62
Zhenkai Zhu82a62752012-06-04 17:11:04 -070063ChatDialog::~ChatDialog()
64{
65 if (m_sock != NULL)
66 {
67 delete m_sock;
68 m_sock = NULL;
69 }
70}
71
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070072void
73ChatDialog::appendMessage(const SyncDemo::ChatMessage &msg)
74{
Zhenkai Zhub6338822012-05-31 13:27:24 -070075
76 if (msg.type() != SyncDemo::ChatMessage::CHAT) {
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070077 return;
Zhenkai Zhub6338822012-05-31 13:27:24 -070078 }
79
80 if (!msg.has_data()) {
81 return;
82 }
83
84 if (msg.from().empty() || msg.data().empty()) {
85 return;
86 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070087
88 QTextCursor cursor(textEdit->textCursor());
89 cursor.movePosition(QTextCursor::End);
90 QTextTableFormat tableFormat;
91 tableFormat.setBorder(0);
92 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
Zhenkai Zhub6338822012-05-31 13:27:24 -070093 QString from = QString("<%1>: ").arg(msg.from().c_str());
94 table->cellAt(0, 0).firstCursorPosition().insertText(from);
95 table->cellAt(0, 1).firstCursorPosition().insertText(msg.data().c_str());
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070096 QScrollBar *bar = textEdit->verticalScrollBar();
97 bar->setValue(bar->maximum());
98}
99
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700100void
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700101ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> &v, Sync::SyncAppSocket *)
102{
103 if (v.empty())
104 {
105 return;
106 }
107
108 // reflect the changes on digest tree
109 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
110
111 int n = v.size();
112 int totalMissingPackets = 0;
113 for (int i = 0; i < n; i++)
114 {
115 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
116 }
117
118 if (totalMissingPackets < 10) {
119 for (int i = 0; i < n; i++)
120 {
121 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
122 {
123 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processData, this, _1, _2, _3), 2);
124 }
125 }
126 }
127 else
128 {
129 // too bad; too many missing packets
130 // we may just join a new chatroom
131 // or some network patition just healed
132 // we don't try to fetch any data in this case (for now)
133 }
134
135 // adjust the view
136 fitView();
137
138}
139
140void
141ChatDialog::processData(std::string name, const char *buf, size_t len)
142{
143 SyncDemo::ChatMessage msg;
144 if (!msg.ParseFromArray(buf, len))
145 {
146 std::cerr << "Errrrr.. Can not parse msg at "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
147 abort();
148 }
149
150 // display
151 appendMessage(msg);
152
153 // update the tree view
154 std::string prefix = name.substr(0, name.find_last_of('/'));
155 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
156}
157
158void
159ChatDialog::processRemove(std::string prefix)
160{
161}
162
163void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700164ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700165 msg.set_from(m_user.getNick().toStdString());
166 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700167 msg.set_data(text.toStdString());
168 time_t seconds = time(NULL);
169 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700170 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700171}
172
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700173bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700174ChatDialog::readSettings()
175{
176 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700177 QString nick = s.value("nick", "").toString();
178 QString chatroom = s.value("chatroom", "").toString();
179 QString prefix = s.value("prefix", "").toString();
180 if (nick == "" || chatroom == "" || prefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700181 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700182 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700183 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700184 else {
185 m_user.setNick(nick);
186 m_user.setChatroom(chatroom);
187 m_user.setPrefix(prefix);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700188 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700189 }
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700190}
191
192void
193ChatDialog::writeSettings()
194{
195 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700196 s.setValue("nick", m_user.getNick());
197 s.setValue("chatroom", m_user.getChatroom());
198 s.setValue("prefix", m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700199}
200
201void
202ChatDialog::updateLabels()
203{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700204 QString settingDisp = QString("<User: %1>, <Chatroom: %2>").arg(m_user.getNick()).arg(m_user.getChatroom());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700205 infoLabel->setText(settingDisp);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700206 QString prefixDisp = QString("<Prefix: %1>").arg(m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700207 prefixLabel->setText(prefixDisp);
208}
209
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700210void
211ChatDialog::returnPressed()
212{
213 QString text = lineEdit->text();
214 if (text.isEmpty())
215 return;
216
Zhenkai Zhub6338822012-05-31 13:27:24 -0700217 lineEdit->clear();
218
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700219 SyncDemo::ChatMessage msg;
220 formChatMessage(text, msg);
221
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700222 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700223
224 // send msg
225 size_t size = msg.ByteSize();
226 char *buf = new char[size];
227 msg.SerializeToArray(buf, size);
228 if (!msg.IsInitialized())
229 {
230 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
231 abort();
232 }
233 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, 60);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700234
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700235}
236
237void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700238ChatDialog::buttonPressed()
239{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700240 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700241 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700242 dialog.exec();
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700243}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700244
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700245void
246ChatDialog::settingUpdated(QString nick, QString chatroom, QString prefix)
247{
248 bool needWrite = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700249 if (!nick.isEmpty() && nick != m_user.getNick()) {
250 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700251 needWrite = true;
252 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700253 if (!prefix.isEmpty() && prefix != m_user.getPrefix()) {
254 m_user.setPrefix(prefix);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700255 needWrite = true;
256 // TODO: set the previous prefix as left?
257 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700258 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
259 m_user.setChatroom(chatroom);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700260 needWrite = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700261
262 m_scene->clearAll();
263 m_scene->plot("Empty");
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700264 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700265 if (m_sock != NULL)
266 {
267 delete m_sock;
268 m_sock = NULL;
269 }
270 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
271 syncPrefix += "/";
272 syncPrefix += m_user.getChatroom().toStdString();
273 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdate, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
274
275 fitView();
276
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700277 }
278 if (needWrite) {
279 writeSettings();
280 updateLabels();
281 }
282}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700283
284void
285ChatDialog::resizeEvent(QResizeEvent *e)
286{
287 fitView();
288}
289
290void
291ChatDialog::showEvent(QShowEvent *e)
292{
293 fitView();
294}
295
296void
297ChatDialog::fitView()
298{
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700299 QRectF rect = m_scene->itemsBoundingRect();
300 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700301 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700302}