blob: 0067fd1bc6cc656ff3aa80309ba55be90e21a094 [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 Zhu6c4fc112012-10-07 17:07:43 -070011#include <boost/lexical_cast.hpp>
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -070012#include <stdio.h>
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070013
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -070014#define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/chronos"
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -070015#define LOCAL_PREFIX_QUERY "/local/ndn/prefix"
16#define DEFAULT_LOCAL_PREFIX "/private/local"
Zhenkai Zhu756666a2012-10-07 00:24:35 -070017#define CCN_EXEC "/usr/local/bin/ccnpeek"
Zhenkai Zhu82a62752012-06-04 17:11:04 -070018
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -070019static const int HELLO_INTERVAL = 90; // seconds
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -070020
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070021ChatDialog::ChatDialog(QWidget *parent)
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -070022 : QDialog(parent), m_sock(NULL), m_lastMsgTime(0), m_historyInitialized(false)
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070023{
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -070024 // have to register this, otherwise
25 // the signal-slot system won't recognize this type
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -070026 qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
27 qRegisterMetaType<size_t>("size_t");
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070028 setupUi(this);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070029 m_session = time(NULL);
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -070030 boost::random::random_device rng;
31 boost::random::uniform_int_distribution<> uniform(1, 29000);
32 m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070033
34 readSettings();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070035
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070036 updateLabels();
37
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070038 lineEdit->setFocusPolicy(Qt::StrongFocus);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070039 m_scene = new DigestTreeScene(this);
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070040
Zhenkai Zhu82a62752012-06-04 17:11:04 -070041 treeViewer->setScene(m_scene);
42 m_scene->plot("Empty");
43 QRectF rect = m_scene->itemsBoundingRect();
44 m_scene->setSceneRect(rect);
45
Zhenkai Zhu9036e032012-09-27 20:59:33 -070046 listView->setStyleSheet("QListView { alternate-background-color: white; background: #F0F0F0; color: darkGreen; font: bold large; }");
Zhenkai Zhuf55f4382012-09-28 10:58:54 -070047 listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
48 listView->setDragDropMode(QAbstractItemView::NoDragDrop);
49 listView->setSelectionMode(QAbstractItemView::NoSelection);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -070050 m_rosterModel = new QStringListModel(this);
51 listView->setModel(m_rosterModel);
52
Zhenkai Zhu86df7412012-09-27 16:30:20 -070053 createActions();
54 createTrayIcon();
55 m_timer = new QTimer(this);
56 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
57 connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
Zhenkai Zhub60b7e12012-09-28 11:34:21 -070058 connect(treeButton, SIGNAL(pressed()), this, SLOT(treeButtonPressed()));
Zhenkai Zhu24ec4722012-10-07 17:56:38 -070059 connect(this, SIGNAL(dataReceived(QString, const char *, size_t, bool, bool)), this, SLOT(processData(QString, const char *, size_t, bool, bool)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070060 connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070061 connect(m_timer, SIGNAL(timeout()), this, SLOT(replot()));
62 connect(m_scene, SIGNAL(replot()), this, SLOT(replot()));
63 connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showNormal()));
64 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
Zhenkai Zhu25e33e52012-09-28 13:00:07 -070065 connect(m_scene, SIGNAL(rosterChanged(QStringList)), this, SLOT(updateRosterList(QStringList)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070066
Zhenkai Zhu82a62752012-06-04 17:11:04 -070067 // create sync socket
68 if(!m_user.getChatroom().isEmpty()) {
69 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
70 syncPrefix += "/";
71 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070072 try
73 {
Alexander Afanasyev288edd82012-10-04 17:07:56 -070074 m_sock = new Sync::SyncAppSocket(syncPrefix,
75 bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
76 bind(&ChatDialog::processRemoveWrapper, this, _1));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -070077 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
78 handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
Zhenkai Zhucf024442012-10-05 10:33:08 -070079 QTimer::singleShot(600, this, SLOT(sendJoin()));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070080 m_timer->start(FRESHNESS * 2000);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -070081 disableTreeDisplay();
82 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070083 }
84 catch (Sync::CcnxOperationException ex)
85 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -070086 QMessageBox::critical(this, tr("Chronos"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070087 std::exit(1);
88 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -070089 }
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070090
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070091}
92
Zhenkai Zhu82a62752012-06-04 17:11:04 -070093ChatDialog::~ChatDialog()
94{
95 if (m_sock != NULL)
96 {
Zhenkai Zhucf024442012-10-05 10:33:08 -070097 sendLeave();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070098 delete m_sock;
99 m_sock = NULL;
100 }
101}
102
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700103void
Zhenkai Zhucf024442012-10-05 10:33:08 -0700104ChatDialog::sendLeave()
105{
106 SyncDemo::ChatMessage msg;
107 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
108 sendMsg(msg);
109 usleep(500000);
110 m_sock->remove(m_user.getPrefix().toStdString());
111 usleep(5000);
112#ifdef __DEBUG
113 std::cout << "Sync REMOVE signal sent" << std::endl;
114#endif
115}
116
117void
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700118ChatDialog::replot()
119{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700120 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700121 m_scene->plot(m_sock->getRootDigest().c_str());
Zhenkai Zhuc9e4e3c2012-10-02 11:47:31 -0700122 fitView();
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700123}
124
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700125void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700126ChatDialog::updateRosterList(QStringList staleUserList)
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700127{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700128 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700129 QStringList rosterList = m_scene->getRosterList();
130 m_rosterModel->setStringList(rosterList);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700131 QString user;
132 QStringListIterator it(staleUserList);
133 while(it.hasNext())
134 {
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700135 std::string nick = it.next().toStdString();
136 if (nick.empty())
137 continue;
138
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700139 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700140 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700141 msg.set_from(nick);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700142 appendMessage(msg);
143 }
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700144}
145
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700146void
147ChatDialog::setVisible(bool visible)
148{
149 minimizeAction->setEnabled(visible);
150 maximizeAction->setEnabled(!isMaximized());
151 restoreAction->setEnabled(isMaximized() || !visible);
152 QDialog::setVisible(visible);
153}
154
155void
156ChatDialog::closeEvent(QCloseEvent *e)
157{
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700158 if (trayIcon->isVisible() && !m_minimaniho)
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700159 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700160 QMessageBox::information(this, tr("Chronos"),
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700161 tr("The program will keep running in the "
162 "system tray. To terminate the program"
163 "choose <b>Quit</b> in the context memu"
164 "of the system tray entry."));
165 hide();
166 e->ignore();
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700167 m_minimaniho = true;
168 writeSettings();
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700169 }
170}
171
172void
173ChatDialog::changeEvent(QEvent *e)
174{
175 switch(e->type())
176 {
177 case QEvent::ActivationChange:
178 if (isActiveWindow())
179 {
180 trayIcon->setIcon(QIcon(":/images/icon_small.png"));
181 }
182 break;
183 default:
184 break;
185 }
186}
187
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700188void
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700189ChatDialog::appendMessage(const SyncDemo::ChatMessage msg, bool isHistory)
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700190{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700191 boost::recursive_mutex::scoped_lock lock(m_msgMutex);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700192
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700193 if (msg.type() == SyncDemo::ChatMessage::CHAT)
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700194 {
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700195
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700196 if (!msg.has_data())
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700197 {
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700198 return;
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700199 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700200
201 if (msg.from().empty() || msg.data().empty())
202 {
203 return;
204 }
205
206 if (!msg.has_timestamp())
207 {
208 return;
209 }
210
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700211 if (m_history.size() == MAX_HISTORY_ENTRY)
212 {
213 m_history.dequeue();
214 }
215
216 m_history.enqueue(msg);
217
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700218 QTextCharFormat nickFormat;
219 nickFormat.setForeground(Qt::darkGreen);
220 nickFormat.setFontWeight(QFont::Bold);
221 nickFormat.setFontUnderline(true);
222 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700223
224 QTextCursor cursor(textEdit->textCursor());
225 cursor.movePosition(QTextCursor::End);
226 QTextTableFormat tableFormat;
227 tableFormat.setBorder(0);
228 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
229 QString from = QString("%1 ").arg(msg.from().c_str());
230 QTextTableCell fromCell = table->cellAt(0, 0);
231 fromCell.setFormat(nickFormat);
232 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700233
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700234 time_t timestamp = msg.timestamp();
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700235 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700236
237 QTextCursor nextCursor(textEdit->textCursor());
238 nextCursor.movePosition(QTextCursor::End);
239 table = nextCursor.insertTable(1, 1, tableFormat);
240 table->cellAt(0, 0).firstCursorPosition().insertText(msg.data().c_str());
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700241 if (!isHistory)
242 {
243 showMessage(from, msg.data().c_str());
244 }
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700245 }
246
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700247 if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE)
248 {
249 QTextCharFormat nickFormat;
250 nickFormat.setForeground(Qt::gray);
251 nickFormat.setFontWeight(QFont::Bold);
252 nickFormat.setFontUnderline(true);
253 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700254
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700255 QTextCursor cursor(textEdit->textCursor());
256 cursor.movePosition(QTextCursor::End);
257 QTextTableFormat tableFormat;
258 tableFormat.setBorder(0);
259 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
260 QString action;
261 if (msg.type() == SyncDemo::ChatMessage::JOIN)
262 {
263 action = "enters room";
264 }
265 else
266 {
267 action = "leaves room";
268 }
269
270 QString from = QString("%1 %2 ").arg(msg.from().c_str()).arg(action);
271 QTextTableCell fromCell = table->cellAt(0, 0);
272 fromCell.setFormat(nickFormat);
273 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700274
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700275 time_t timestamp = msg.timestamp();
276 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700277 }
278
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700279 QScrollBar *bar = textEdit->verticalScrollBar();
280 bar->setValue(bar->maximum());
281}
282
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700283void
284ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
285{
286 QTextCharFormat timeFormat;
287 timeFormat.setForeground(Qt::gray);
288 timeFormat.setFontUnderline(true);
289 timeFormat.setUnderlineColor(Qt::gray);
290 QTextTableCell timeCell = table->cellAt(0, 1);
291 timeCell.setFormat(timeFormat);
292 timeCell.firstCursorPosition().insertText(formatTime(timestamp));
293}
294
295QString
296ChatDialog::formatTime(time_t timestamp)
297{
298 struct tm *tm_time = localtime(&timestamp);
299 int hour = tm_time->tm_hour;
300 QString amOrPM;
301 if (hour > 12)
302 {
303 hour -= 12;
304 amOrPM = "PM";
305 }
306 else
307 {
308 amOrPM = "AM";
309 if (hour == 0)
310 {
311 hour = 12;
312 }
313 }
314
315 char textTime[12];
316 sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
317 return QString(textTime);
318}
319
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700320void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700321ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
322{
323 emit treeUpdated(v);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700324#ifdef __DEBUG
325 std::cout << "<<< Tree update signal emitted" << std::endl;
326#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700327}
328
329void
330ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700331{
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700332#ifdef __DEBUG
333 std::cout << "<<< processing Tree Update" << std::endl;
334#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700335 if (v.empty())
336 {
337 return;
338 }
339
340 // reflect the changes on digest tree
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700341 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700342 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700343 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
344 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700345
346 int n = v.size();
347 int totalMissingPackets = 0;
348 for (int i = 0; i < n; i++)
349 {
350 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
351 }
352
Zhenkai Zhubb198112012-09-27 11:31:42 -0700353 for (int i = 0; i < n; i++)
354 {
355 if (totalMissingPackets < 4)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700356 {
357 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
358 {
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700359 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700360#ifdef __DEBUG
361 std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
362#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700363 }
364 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700365 else
366 {
367 m_sock->fetchRaw(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1, _2, _3), 2);
368 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700369 }
370
371 // adjust the view
372 fitView();
373
374}
375
376void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700377ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
378{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700379 char *tempBuf = new char[len];
380 memcpy(tempBuf, buf, len);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700381 emit dataReceived(name.c_str(), tempBuf, len, true, false);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700382#ifdef __DEBUG
383 std::cout <<"<<< " << name << " fetched" << std::endl;
384#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700385}
386
387void
Zhenkai Zhubb198112012-09-27 11:31:42 -0700388ChatDialog::processDataNoShowWrapper(std::string name, const char *buf, size_t len)
389{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700390 char *tempBuf = new char[len];
391 memcpy(tempBuf, buf, len);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700392 emit dataReceived(name.c_str(), tempBuf, len, false, false);
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700393
394 if (!m_historyInitialized)
395 {
396 fetchHistory(name);
397 m_historyInitialized = true;
398 }
399}
400
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700401void
402ChatDialog::processDataHistoryWrapper(std::string name, const char *buf, size_t len)
403{
404 char *tempBuf = new char[len];
405 memcpy(tempBuf, buf, len);
406 emit dataReceived(name.c_str(), tempBuf, len, true, true);
407}
408
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700409void
410ChatDialog::fetchHistory(std::string name)
411{
412 std::string nameWithoutSeq = name.substr(0, name.find_last_of('/'));
413 std::string prefix = nameWithoutSeq.substr(0, nameWithoutSeq.find_last_of('/'));
414 prefix += "/history";
415 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
416 QString randomString = getRandomString();
417 for (int i = 0; i < MAX_HISTORY_ENTRY; i++)
418 {
419 QString interest = QString("%1/%2/%3").arg(prefix.c_str()).arg(randomString).arg(i);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700420 handle->sendInterest(interest.toStdString(), bind(&ChatDialog::processDataHistoryWrapper, this, _1, _2, _3));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700421 }
422}
423
424void
425ChatDialog::respondHistoryRequest(std::string interest)
426{
427 std::string seqStr = interest.substr(interest.find_last_of('/') + 1);
428 int seq = boost::lexical_cast<int>(seqStr);
429 if (seq >= 0 && seq < m_history.size())
430 {
431 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
432 SyncDemo::ChatMessage msg = m_history.at(seq);
433 size_t size = msg.ByteSize();
434 char *buf = new char[size];
435 msg.SerializeToArray(buf, size);
436 handle->publishRawData(interest, buf, size, 1);
437 delete buf;
438 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700439}
440
441void
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700442ChatDialog::processData(QString name, const char *buf, size_t len, bool show, bool isHistory)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700443{
444 SyncDemo::ChatMessage msg;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700445 bool corrupted = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700446 if (!msg.ParseFromArray(buf, len))
447 {
Zhenkai Zhubb198112012-09-27 11:31:42 -0700448 std::cerr << "Errrrr.. Can not parse msg with name: " << name.toStdString() << ". what is happening?" << std::endl;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700449 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
450 msg.set_from("inconnu");
451 msg.set_type(SyncDemo::ChatMessage::OTHER);
452 corrupted = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700453 }
454
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700455 delete [] buf;
456 buf = NULL;
457
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700458 // display msg received from network
459 // we have to do so; this function is called by ccnd thread
460 // so if we call appendMsg directly
461 // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
462 // the "cannonical" way to is use signal-slot
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700463 if (show && !corrupted)
Zhenkai Zhubb198112012-09-27 11:31:42 -0700464 {
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700465 appendMessage(msg, isHistory);
Zhenkai Zhubb198112012-09-27 11:31:42 -0700466 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700467
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700468 if (!isHistory)
469 {
470 // update the tree view
471 std::string stdStrName = name.toStdString();
472 std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
473 std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700474#ifdef __DEBUG
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700475 std::cout <<"<<< updating scene for" << prefix << ": " << msg.from() << std::endl;
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700476#endif
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700477 if (msg.type() == SyncDemo::ChatMessage::LEAVE)
478 {
479 processRemove(prefix.c_str());
480 }
481 else
482 {
483 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
484 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
485 }
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700486 }
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700487 fitView();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700488}
489
490void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700491ChatDialog::processRemoveWrapper(std::string prefix)
492{
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700493#ifdef __DEBUG
494 std::cout << "Sync REMOVE signal received for prefix: " << prefix << std::endl;
495#endif
496 //emit removeReceived(prefix.c_str());
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700497}
498
499void
500ChatDialog::processRemove(QString prefix)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700501{
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700502#ifdef __DEBUG
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700503 std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700504#endif
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700505 bool removed = m_scene->removeNode(prefix);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700506 if (removed)
507 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700508 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700509 m_scene->plot(m_sock->getRootDigest().c_str());
510 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700511}
512
513void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700514ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700515 msg.set_from(m_user.getNick().toStdString());
516 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700517 msg.set_data(text.toStdString());
518 time_t seconds = time(NULL);
519 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700520 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700521}
522
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700523void
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700524ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700525{
526 msg.set_from(m_user.getNick().toStdString());
527 msg.set_to(m_user.getChatroom().toStdString());
528 time_t seconds = time(NULL);
529 msg.set_timestamp(seconds);
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700530 msg.set_type(type);
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700531}
532
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700533static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
534
535QString
536ChatDialog::getRandomString()
537{
538 std::string randStr;
539 boost::random::random_device rng;
540 boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
541 for (int i = 0; i < 10; i ++)
542 {
543 randStr += chars[index_dist(rng)];
544 }
545 return randStr.c_str();
546}
547
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700548void
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700549ChatDialog::getLocalPrefix()
550{
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700551// /*
552// * this method tries to use ccncat
553// * however, it does not work in Mac OS X app bundle
554// * it works well in command line though
555// */
Zhenkai Zhu756666a2012-10-07 00:24:35 -0700556
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700557// std::string cmd = CCN_EXEC;
558// cmd += " -c -v ";
559// cmd += LOCAL_PREFIX_QUERY;
560// QString localPrefix;
561// #define MAX_PREFIX_LEN 100
562// FILE *fp = popen(cmd.c_str(), "r");
563// if (fp != NULL)
564// {
565// char prefix[MAX_PREFIX_LEN];
566// if (fgets(prefix, MAX_PREFIX_LEN, fp) != NULL)
567// {
568// localPrefix = prefix;
569// localPrefix.remove('\n');
570// }
571// else
572// {
573// localPrefix = DEFAULT_LOCAL_PREFIX;
574// }
575// pclose(fp);
576// }
577// else
578// {
579// localPrefix = DEFAULT_LOCAL_PREFIX;
580// }
581// return localPrefix;
582
583 if (m_sock != NULL)
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700584 {
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700585 QString originPrefix = QString::fromStdString (m_sock->getLocalPrefix());
586 if (originPrefix != "" && m_user.getOriginPrefix () != originPrefix)
587 {
588 m_user.setOriginPrefix(originPrefix);
589 emit settingUpdated(m_user.getNick (), m_user.getChatroom (), m_user.getOriginPrefix ());
590 // connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT());
591 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700592 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700593 else
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700594 {
595 // QTimer::singleShot(1000, this, SLOT(getLocalPrefix())); // try again
596 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700597}
598
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700599bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700600ChatDialog::readSettings()
601{
602 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700603 QString nick = s.value("nick", "").toString();
604 QString chatroom = s.value("chatroom", "").toString();
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700605 QString originPrefix = s.value("originPrefix", "").toString();
606
607 // Sync::CcnxWrapperPtr wrapper = Sync::CcnxWrapper::Create ();
608 // QString originPrefix = QString::fromStdString (wrapper->getLocalPrefix());
609 // Sync::CcnxWrapper::Destroy ();
610 // QString originPrefix = DEFAULT_LOCAL_PREFIX;
611
612 QTimer::singleShot(500, this, SLOT(getLocalPrefix()));
613
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700614 m_minimaniho = s.value("minimaniho", false).toBool();
615 if (nick == "" || chatroom == "" || originPrefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700616 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700617 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700618 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700619 else {
620 m_user.setNick(nick);
621 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700622 m_user.setOriginPrefix(originPrefix);
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700623 m_user.setPrefix(originPrefix + "/" + chatroom + "/" + getRandomString());
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700624 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700625 }
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700626
627// QTimer::singleShot(500, this, SLOT(buttonPressed()));
628 // return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700629}
630
631void
632ChatDialog::writeSettings()
633{
634 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700635 s.setValue("nick", m_user.getNick());
636 s.setValue("chatroom", m_user.getChatroom());
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700637 //s.setValue("originPrefix", m_user.getOriginPrefix());
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700638 s.setValue("minimaniho", m_minimaniho);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700639}
640
641void
642ChatDialog::updateLabels()
643{
Zhenkai Zhu76ff02b2012-09-27 21:11:03 -0700644 QString settingDisp = QString("Chatroom: %1").arg(m_user.getChatroom());
645 infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700646 infoLabel->setText(settingDisp);
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700647 QString prefixDisp;
648 if (m_user.getPrefix().startsWith(DEFAULT_LOCAL_PREFIX))
649 {
650 prefixDisp = QString("<Warning: Auto config prefix failed.>\n <Prefix = %1>").arg(m_user.getPrefix());
651 prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
652 }
653 else
654 {
655 prefixDisp = QString("<Prefix = %1>").arg(m_user.getPrefix());
656 prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
657 }
658 prefixLabel->setText(prefixDisp);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700659}
660
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700661void
662ChatDialog::returnPressed()
663{
664 QString text = lineEdit->text();
665 if (text.isEmpty())
666 return;
667
Zhenkai Zhub6338822012-05-31 13:27:24 -0700668 lineEdit->clear();
669
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700670 SyncDemo::ChatMessage msg;
671 formChatMessage(text, msg);
672
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700673 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700674
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700675 sendMsg(msg);
676
677 fitView();
678}
679
680void
681ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
682{
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700683 // send msg
684 size_t size = msg.ByteSize();
685 char *buf = new char[size];
686 msg.SerializeToArray(buf, size);
687 if (!msg.IsInitialized())
688 {
689 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
690 abort();
691 }
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700692 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700693
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700694 delete buf;
695
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700696 m_lastMsgTime = time(NULL);
697
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700698 int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700699 Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700700 std::vector<Sync::MissingDataInfo> v;
701 v.push_back(mdi);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700702 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700703 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700704 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
705 m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
706 }
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700707}
708
709void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700710ChatDialog::sendJoin()
711{
712 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700713 formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700714 sendMsg(msg);
715 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
716}
717
718void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700719ChatDialog::sendHello()
720{
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700721 time_t now = time(NULL);
722 int elapsed = now - m_lastMsgTime;
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700723 if (elapsed >= m_randomizedInterval / 1000)
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700724 {
725 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700726 formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700727 sendMsg(msg);
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700728 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700729 }
730 else
731 {
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700732 QTimer::singleShot((m_randomizedInterval - elapsed * 1000), this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700733 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700734}
735
736void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700737ChatDialog::buttonPressed()
738{
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700739 Sync::SyncLogic &logic = m_sock->getLogic ();
740 logic.printState ();
741
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700742 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getOriginPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700743 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700744 dialog.exec();
Zhenkai Zhue837f792012-06-05 20:47:54 -0700745 QTimer::singleShot(100, this, SLOT(checkSetting()));
746}
747
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700748void ChatDialog::treeButtonPressed()
749{
750 if (treeViewer->isVisible())
751 {
752 treeViewer->hide();
753 treeButton->setText("Show Sync Tree");
754 }
755 else
756 {
757 treeViewer->show();
758 treeButton->setText("Hide Sync Tree");
759 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700760
761 fitView();
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700762}
763
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700764void ChatDialog::enableTreeDisplay()
765{
766 treeButton->setEnabled(true);
767 treeViewer->show();
768 fitView();
769}
770
771void ChatDialog::disableTreeDisplay()
772{
773 treeButton->setEnabled(false);
774 treeViewer->hide();
775 fitView();
776}
777
Zhenkai Zhue837f792012-06-05 20:47:54 -0700778void
779ChatDialog::checkSetting()
780{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700781 if (m_user.getOriginPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
Zhenkai Zhue837f792012-06-05 20:47:54 -0700782 {
783 buttonPressed();
784 }
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700785}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700786
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700787void
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700788ChatDialog::settingUpdated(QString nick, QString chatroom, QString originPrefix)
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700789{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700790 QString randString = getRandomString();
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700791 bool needWrite = false;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700792 bool needFresh = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700793 if (!nick.isEmpty() && nick != m_user.getNick()) {
794 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700795 needWrite = true;
796 }
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700797 QString oldPrefix = m_user.getPrefix();
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700798 if (!originPrefix.isEmpty() && originPrefix != m_user.getOriginPrefix()) {
799 m_user.setOriginPrefix(originPrefix);
800 m_user.setPrefix(originPrefix + "/" + m_user.getChatroom() + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700801 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700802 needFresh = true;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700803 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700804 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
805 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700806 m_user.setPrefix(m_user.getOriginPrefix() + "/" + chatroom + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700807 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700808 needFresh = true;
809 }
810
811 if (needFresh)
812 {
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700813
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700814 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700815 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700816 m_scene->clearAll();
817 m_scene->plot("Empty");
818 }
Zhenkai Zhucc4c2c02012-09-27 21:24:37 -0700819
820 textEdit->clear();
821
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700822 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700823 if (m_sock != NULL)
824 {
Zhenkai Zhucf024442012-10-05 10:33:08 -0700825 sendLeave();
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700826 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
827 handle->clearInterestFilter(oldPrefix.toStdString());
828 m_history.clear();
829 m_historyInitialized = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700830 delete m_sock;
831 m_sock = NULL;
832 }
833 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
834 syncPrefix += "/";
835 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700836 try
837 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700838 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700839 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
840 handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
Alexander Afanasyev288edd82012-10-04 17:07:56 -0700841 QTimer::singleShot(1000, this, SLOT(sendJoin()));
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700842 m_timer->start(FRESHNESS * 2000);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700843 disableTreeDisplay();
844 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700845 }
846 catch (Sync::CcnxOperationException ex)
847 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700848 QMessageBox::critical(this, tr("Chronos"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700849 std::exit(1);
850 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700851
852 fitView();
853
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700854 }
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700855
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700856 if (needWrite) {
857 writeSettings();
858 updateLabels();
859 }
860}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700861
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700862void
863ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
864{
865 switch (reason)
866 {
867 case QSystemTrayIcon::Trigger:
868 case QSystemTrayIcon::DoubleClick:
869 break;
870 case QSystemTrayIcon::MiddleClick:
871 // showMessage();
872 break;
873 default:;
874 }
875}
876
877void
878ChatDialog::showMessage(QString from, QString data)
879{
880 // std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
881 if (!isActiveWindow())
882 {
883 trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
884 trayIcon->setIcon(QIcon(":/images/note.png"));
885 }
886}
887
888void
889ChatDialog::messageClicked()
890{
891 this->showMaximized();
892}
893
894void
895ChatDialog::createActions()
896{
897 minimizeAction = new QAction(tr("Mi&nimize"), this);
898 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
899
900 maximizeAction = new QAction(tr("Ma&ximize"), this);
901 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
902
903 restoreAction = new QAction(tr("&Restore"), this);
904 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
905
906 quitAction = new QAction(tr("Quit"), this);
907 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
908}
909
910void
911ChatDialog::createTrayIcon()
912{
913 trayIconMenu = new QMenu(this);
914 trayIconMenu->addAction(minimizeAction);
915 trayIconMenu->addAction(maximizeAction);
916 trayIconMenu->addAction(restoreAction);
917 trayIconMenu->addSeparator();
918 trayIconMenu->addAction(quitAction);
919
920 trayIcon = new QSystemTrayIcon(this);
921 trayIcon->setContextMenu(trayIconMenu);
922
923 QIcon icon(":/images/icon_small.png");
924 trayIcon->setIcon(icon);
925 setWindowIcon(icon);
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700926 trayIcon->setToolTip("Chronos System Tray Icon");
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700927 trayIcon->setVisible(true);
928}
929
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700930void
931ChatDialog::resizeEvent(QResizeEvent *e)
932{
933 fitView();
934}
935
936void
937ChatDialog::showEvent(QShowEvent *e)
938{
939 fitView();
940}
941
942void
943ChatDialog::fitView()
944{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700945 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700946 QRectF rect = m_scene->itemsBoundingRect();
947 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700948 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700949}