blob: 55bbaf1a8b4beadb64dfae50771875f92c9f2610 [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 Zhu10ccb5a2012-06-04 21:55:14 -07007#include <QMetaType>
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -07008#include <QMessageBox>
Zhenkai Zhu59245aa2012-09-26 16:07:04 -07009#include <boost/random/random_device.hpp>
10#include <boost/random/uniform_int_distribution.hpp>
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070011
Zhenkai Zhu82a62752012-06-04 17:11:04 -070012#define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/sync-demo"
13
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -070014static const int FRESHNESS = 60;
15static const int HELLO_INTERVAL = 59;
16
Zhenkai Zhu21d75f92012-06-04 21:23:34 -070017void
18ChatDialog::testDraw()
19{
20 std::string prefix[5] = {"/ndn/1", "/ndn/2", "/ndn/3", "/ndn/4", "/ndn/5"};
21 std::string nick[5] = {"tom", "jerry", "jason", "michael", "hurry"};
22 std::vector<Sync::MissingDataInfo> v;
23 for (int i = 0; i < 5; i++)
24 {
25 Sync::MissingDataInfo mdi = {prefix[i], Sync::SeqNo(0), Sync::SeqNo(i * (2 << i) )};
26 v.push_back(mdi);
27 }
28
29 m_scene->processUpdate(v, "12341234@!#%!@");
30
31 for (int i = 0; i < 5; i++)
32 {
33 m_scene-> msgReceived(prefix[i].c_str(), nick[i].c_str());
34 }
35
36 fitView();
37}
38
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070039ChatDialog::ChatDialog(QWidget *parent)
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -070040 : QDialog(parent), m_sock(NULL), m_lastMsgTime(0)
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070041{
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -070042 // have to register this, otherwise
43 // the signal-slot system won't recognize this type
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -070044 qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
45 qRegisterMetaType<size_t>("size_t");
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070046 setupUi(this);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070047 m_session = time(NULL);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070048
49 readSettings();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070050
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070051 updateLabels();
52
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070053 lineEdit->setFocusPolicy(Qt::StrongFocus);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070054 m_scene = new DigestTreeScene(this);
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070055
Zhenkai Zhu82a62752012-06-04 17:11:04 -070056 treeViewer->setScene(m_scene);
57 m_scene->plot("Empty");
58 QRectF rect = m_scene->itemsBoundingRect();
59 m_scene->setSceneRect(rect);
60
61 // create sync socket
62 if(!m_user.getChatroom().isEmpty()) {
63 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
64 syncPrefix += "/";
65 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070066 try
67 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -070068 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
69 sendHello();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070070 }
71 catch (Sync::CcnxOperationException ex)
72 {
73 QMessageBox::critical(this, tr("Sync-Demo"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
74 std::exit(1);
75 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -070076 }
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070077
78 createActions();
79 createTrayIcon();
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070080 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
Zhenkai Zhu85845d22012-06-01 23:10:43 -070081 connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
Zhenkai Zhubb198112012-09-27 11:31:42 -070082 connect(this, SIGNAL(dataReceived(QString, const char *, size_t, bool)), this, SLOT(processData(QString, const char *, size_t, bool)));
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -070083 connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -070084 connect(this, SIGNAL(removeReceived(QString)), this, SLOT(processRemove(QString)));
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070085 connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showNormal()));
86 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
87
88//testDraw();
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070089}
90
Zhenkai Zhu82a62752012-06-04 17:11:04 -070091ChatDialog::~ChatDialog()
92{
93 if (m_sock != NULL)
94 {
Zhenkai Zhu591e8c32012-09-26 11:57:50 -070095 m_sock->remove(m_user.getPrefix().toStdString());
Zhenkai Zhu82a62752012-06-04 17:11:04 -070096 delete m_sock;
97 m_sock = NULL;
98 }
99}
100
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700101void
102ChatDialog::setVisible(bool visible)
103{
104 minimizeAction->setEnabled(visible);
105 maximizeAction->setEnabled(!isMaximized());
106 restoreAction->setEnabled(isMaximized() || !visible);
107 QDialog::setVisible(visible);
108}
109
110void
111ChatDialog::closeEvent(QCloseEvent *e)
112{
113 if (trayIcon->isVisible())
114 {
115 QMessageBox::information(this, tr("Sync-Demo"),
116 tr("The program will keep running in the "
117 "system tray. To terminate the program"
118 "choose <b>Quit</b> in the context memu"
119 "of the system tray entry."));
120 hide();
121 e->ignore();
122 }
123}
124
125void
126ChatDialog::changeEvent(QEvent *e)
127{
128 switch(e->type())
129 {
130 case QEvent::ActivationChange:
131 if (isActiveWindow())
132 {
133 trayIcon->setIcon(QIcon(":/images/icon_small.png"));
134 }
135 break;
136 default:
137 break;
138 }
139}
140
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700141void
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700142ChatDialog::appendMessage(const SyncDemo::ChatMessage msg)
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700143{
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700144 boost::mutex::scoped_lock lock(m_msgMutex);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700145
146 if (msg.type() != SyncDemo::ChatMessage::CHAT) {
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700147 return;
Zhenkai Zhub6338822012-05-31 13:27:24 -0700148 }
149
150 if (!msg.has_data()) {
151 return;
152 }
153
154 if (msg.from().empty() || msg.data().empty()) {
155 return;
156 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700157
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700158 if (!msg.has_timestamp())
159 {
160 return;
161 }
162
163 QTextCharFormat nickFormat;
164 nickFormat.setForeground(Qt::darkGreen);
165 nickFormat.setFontWeight(QFont::Bold);
166 nickFormat.setFontUnderline(true);
167 nickFormat.setUnderlineColor(Qt::gray);
168 QTextCharFormat timeFormat;
169 timeFormat.setForeground(Qt::gray);
170 timeFormat.setFontUnderline(true);
171 timeFormat.setUnderlineColor(Qt::gray);
172
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700173 QTextCursor cursor(textEdit->textCursor());
174 cursor.movePosition(QTextCursor::End);
175 QTextTableFormat tableFormat;
176 tableFormat.setBorder(0);
177 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700178 QString from = QString("%1 ").arg(msg.from().c_str());
179 QTextTableCell fromCell = table->cellAt(0, 0);
180 fromCell.setFormat(nickFormat);
181 fromCell.firstCursorPosition().insertText(from);
182 QTextTableCell timeCell = table->cellAt(0, 1);
183 timeCell.setFormat(timeFormat);
184 time_t timestamp = msg.timestamp();
185 struct tm *tm_time = localtime(&timestamp);
186 int hour = tm_time->tm_hour;
187 QString amOrPM;
188 if (hour > 12)
189 {
190 hour -= 12;
191 amOrPM = "PM";
192 }
193 else
194 {
195 amOrPM = "AM";
196 if (hour == 0)
197 {
198 hour = 12;
199 }
200 }
201
202 char textTime[12];
203 sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
204 timeCell.firstCursorPosition().insertText(textTime);
205
206
207 QTextCursor nextCursor(textEdit->textCursor());
208 table = nextCursor.insertTable(1, 1, tableFormat);
209 table->cellAt(0, 0).firstCursorPosition().insertText(msg.data().c_str());
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700210 QScrollBar *bar = textEdit->verticalScrollBar();
211 bar->setValue(bar->maximum());
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700212 showMessage(from, msg.data().c_str());
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700213}
214
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700215void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700216ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
217{
218 emit treeUpdated(v);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700219#ifdef __DEBUG
220 std::cout << "<<< Tree update signal emitted" << std::endl;
221#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700222}
223
224void
225ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700226{
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700227#ifdef __DEBUG
228 std::cout << "<<< processing Tree Update" << std::endl;
229#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700230 if (v.empty())
231 {
232 return;
233 }
234
235 // reflect the changes on digest tree
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700236 {
237 boost::mutex::scoped_lock lock(m_sceneMutex);
238 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
239 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700240
241 int n = v.size();
242 int totalMissingPackets = 0;
243 for (int i = 0; i < n; i++)
244 {
245 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
246 }
247
Zhenkai Zhubb198112012-09-27 11:31:42 -0700248 for (int i = 0; i < n; i++)
249 {
250 if (totalMissingPackets < 4)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700251 {
252 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
253 {
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700254 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700255#ifdef __DEBUG
256 std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
257#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700258 }
259 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700260 else
261 {
262 m_sock->fetchRaw(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1, _2, _3), 2);
263 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700264 }
265
266 // adjust the view
267 fitView();
268
269}
270
271void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700272ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
273{
Zhenkai Zhubb198112012-09-27 11:31:42 -0700274 emit dataReceived(name.c_str(), buf, len, true);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700275#ifdef __DEBUG
276 std::cout <<"<<< " << name << " fetched" << std::endl;
277#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700278}
279
280void
Zhenkai Zhubb198112012-09-27 11:31:42 -0700281ChatDialog::processDataNoShowWrapper(std::string name, const char *buf, size_t len)
282{
283 emit dataReceived(name.c_str(), buf, len, false);
284}
285
286void
287ChatDialog::processData(QString name, const char *buf, size_t len, bool show)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700288{
289 SyncDemo::ChatMessage msg;
290 if (!msg.ParseFromArray(buf, len))
291 {
Zhenkai Zhubb198112012-09-27 11:31:42 -0700292 std::cerr << "Errrrr.. Can not parse msg with name: " << name.toStdString() << ". what is happening?" << std::endl;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700293 }
294
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700295 // display msg received from network
296 // we have to do so; this function is called by ccnd thread
297 // so if we call appendMsg directly
298 // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
299 // the "cannonical" way to is use signal-slot
Zhenkai Zhubb198112012-09-27 11:31:42 -0700300 if (show)
301 {
302 appendMessage(msg);
303 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700304
305 // update the tree view
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700306 std::string stdStrName = name.toStdString();
307 std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
308 std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
309#ifdef __DEBUG
310 std::cout <<"<<< updating scene for" << prefix << ": " << msg.from() << std::endl;
311#endif
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700312 {
313 boost::mutex::scoped_lock lock(m_sceneMutex);
314 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
315 }
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700316 fitView();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700317}
318
319void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700320ChatDialog::processRemoveWrapper(std::string prefix)
321{
322 emit removeReceived(prefix.c_str());
323}
324
325void
326ChatDialog::processRemove(QString prefix)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700327{
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700328#ifdef __DEBUG
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700329 std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700330#endif
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700331 bool removed = m_scene->removeNode(prefix);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700332 if (removed)
333 {
334 m_scene->plot(m_sock->getRootDigest().c_str());
335 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700336}
337
338void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700339ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700340 msg.set_from(m_user.getNick().toStdString());
341 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700342 msg.set_data(text.toStdString());
343 time_t seconds = time(NULL);
344 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700345 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700346}
347
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700348void
349ChatDialog::formHelloMessage(SyncDemo::ChatMessage &msg)
350{
351 msg.set_from(m_user.getNick().toStdString());
352 msg.set_to(m_user.getChatroom().toStdString());
353 time_t seconds = time(NULL);
354 msg.set_timestamp(seconds);
355 msg.set_type(SyncDemo::ChatMessage::HELLO);
356}
357
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700358static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
359
360QString
361ChatDialog::getRandomString()
362{
363 std::string randStr;
364 boost::random::random_device rng;
365 boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
366 for (int i = 0; i < 10; i ++)
367 {
368 randStr += chars[index_dist(rng)];
369 }
370 return randStr.c_str();
371}
372
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700373bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700374ChatDialog::readSettings()
375{
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700376#ifndef __DEBUG
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700377 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700378 QString nick = s.value("nick", "").toString();
379 QString chatroom = s.value("chatroom", "").toString();
380 QString prefix = s.value("prefix", "").toString();
381 if (nick == "" || chatroom == "" || prefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700382 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700383 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700384 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700385 else {
386 m_user.setNick(nick);
387 m_user.setChatroom(chatroom);
388 m_user.setPrefix(prefix);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700389 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700390 }
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700391#else
392 QTimer::singleShot(500, this, SLOT(buttonPressed()));
393 return false;
394#endif
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700395}
396
397void
398ChatDialog::writeSettings()
399{
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700400#ifndef __DEBUG
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700401 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700402 s.setValue("nick", m_user.getNick());
403 s.setValue("chatroom", m_user.getChatroom());
404 s.setValue("prefix", m_user.getPrefix());
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700405#endif
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700406}
407
408void
409ChatDialog::updateLabels()
410{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700411 QString settingDisp = QString("<User: %1>, <Chatroom: %2>").arg(m_user.getNick()).arg(m_user.getChatroom());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700412 infoLabel->setText(settingDisp);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700413 QString prefixDisp = QString("<Prefix: %1>").arg(m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700414 prefixLabel->setText(prefixDisp);
415}
416
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700417void
418ChatDialog::returnPressed()
419{
420 QString text = lineEdit->text();
421 if (text.isEmpty())
422 return;
423
Zhenkai Zhub6338822012-05-31 13:27:24 -0700424 lineEdit->clear();
425
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700426 SyncDemo::ChatMessage msg;
427 formChatMessage(text, msg);
428
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700429 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700430
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700431 sendMsg(msg);
432
433 fitView();
434}
435
436void
437ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
438{
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700439 // send msg
440 size_t size = msg.ByteSize();
441 char *buf = new char[size];
442 msg.SerializeToArray(buf, size);
443 if (!msg.IsInitialized())
444 {
445 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
446 abort();
447 }
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700448 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700449
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700450 delete buf;
451
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700452 m_lastMsgTime = time(NULL);
453
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700454 int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700455 Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700456 std::vector<Sync::MissingDataInfo> v;
457 v.push_back(mdi);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700458 {
459 boost::mutex::scoped_lock lock(m_sceneMutex);
460 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
461 m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
462 }
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700463}
464
465void
466ChatDialog::sendHello()
467{
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700468 time_t now = time(NULL);
469 int elapsed = now - m_lastMsgTime;
470 if (elapsed >= HELLO_INTERVAL)
471 {
472 SyncDemo::ChatMessage msg;
473 formHelloMessage(msg);
474 sendMsg(msg);
475 QTimer::singleShot(HELLO_INTERVAL * 1000, this, SLOT(sendHello()));
476 }
477 else
478 {
479 QTimer::singleShot((HELLO_INTERVAL - elapsed) * 1000, this, SLOT(sendHello()));
480 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700481}
482
483void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700484ChatDialog::buttonPressed()
485{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700486 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700487 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700488 dialog.exec();
Zhenkai Zhue837f792012-06-05 20:47:54 -0700489 QTimer::singleShot(100, this, SLOT(checkSetting()));
490}
491
492void
493ChatDialog::checkSetting()
494{
495 if (m_user.getPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
496 {
497 buttonPressed();
498 }
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700499}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700500
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700501void
502ChatDialog::settingUpdated(QString nick, QString chatroom, QString prefix)
503{
504 bool needWrite = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700505 if (!nick.isEmpty() && nick != m_user.getNick()) {
506 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700507 needWrite = true;
508 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700509 if (!prefix.isEmpty() && prefix != m_user.getPrefix()) {
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700510 m_user.setPrefix(prefix + "/" + getRandomString());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700511 needWrite = true;
512 // TODO: set the previous prefix as left?
513 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700514 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
515 m_user.setChatroom(chatroom);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700516 needWrite = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700517
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700518 {
519 boost::mutex::scoped_lock lock(m_sceneMutex);
520 m_scene->clearAll();
521 m_scene->plot("Empty");
522 }
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700523 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700524 if (m_sock != NULL)
525 {
526 delete m_sock;
527 m_sock = NULL;
528 }
529 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
530 syncPrefix += "/";
531 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700532 try
533 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700534 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
535 sendHello();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700536 }
537 catch (Sync::CcnxOperationException ex)
538 {
539 QMessageBox::critical(this, tr("Sync-Demo"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
540 std::exit(1);
541 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700542
543 fitView();
544
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700545 }
546 if (needWrite) {
547 writeSettings();
548 updateLabels();
549 }
550}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700551
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700552void
553ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
554{
555 switch (reason)
556 {
557 case QSystemTrayIcon::Trigger:
558 case QSystemTrayIcon::DoubleClick:
559 break;
560 case QSystemTrayIcon::MiddleClick:
561 // showMessage();
562 break;
563 default:;
564 }
565}
566
567void
568ChatDialog::showMessage(QString from, QString data)
569{
570 // std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
571 if (!isActiveWindow())
572 {
573 trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
574 trayIcon->setIcon(QIcon(":/images/note.png"));
575 }
576}
577
578void
579ChatDialog::messageClicked()
580{
581 this->showMaximized();
582}
583
584void
585ChatDialog::createActions()
586{
587 minimizeAction = new QAction(tr("Mi&nimize"), this);
588 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
589
590 maximizeAction = new QAction(tr("Ma&ximize"), this);
591 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
592
593 restoreAction = new QAction(tr("&Restore"), this);
594 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
595
596 quitAction = new QAction(tr("Quit"), this);
597 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
598}
599
600void
601ChatDialog::createTrayIcon()
602{
603 trayIconMenu = new QMenu(this);
604 trayIconMenu->addAction(minimizeAction);
605 trayIconMenu->addAction(maximizeAction);
606 trayIconMenu->addAction(restoreAction);
607 trayIconMenu->addSeparator();
608 trayIconMenu->addAction(quitAction);
609
610 trayIcon = new QSystemTrayIcon(this);
611 trayIcon->setContextMenu(trayIconMenu);
612
613 QIcon icon(":/images/icon_small.png");
614 trayIcon->setIcon(icon);
615 setWindowIcon(icon);
616 trayIcon->setToolTip("Sync-Demo System Tray Icon");
617 trayIcon->setVisible(true);
618}
619
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700620void
621ChatDialog::resizeEvent(QResizeEvent *e)
622{
623 fitView();
624}
625
626void
627ChatDialog::showEvent(QShowEvent *e)
628{
629 fitView();
630}
631
632void
633ChatDialog::fitView()
634{
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700635 boost::mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700636 QRectF rect = m_scene->itemsBoundingRect();
637 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700638 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700639}