blob: 6fdc657f561b8b5b9f59921c8e6a73f3cac80a21 [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 Zhuc61dbc22012-10-08 11:36:37 -070019static const int HELLO_INTERVAL = FRESHNESS * 3 / 4; // 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 Zhu7e9b06d2012-06-02 00:44:42 -070030
31 readSettings();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070032
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070033 updateLabels();
34
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070035 lineEdit->setFocusPolicy(Qt::StrongFocus);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070036 m_scene = new DigestTreeScene(this);
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070037
Zhenkai Zhu82a62752012-06-04 17:11:04 -070038 treeViewer->setScene(m_scene);
39 m_scene->plot("Empty");
40 QRectF rect = m_scene->itemsBoundingRect();
41 m_scene->setSceneRect(rect);
42
Zhenkai Zhu9036e032012-09-27 20:59:33 -070043 listView->setStyleSheet("QListView { alternate-background-color: white; background: #F0F0F0; color: darkGreen; font: bold large; }");
Zhenkai Zhuf55f4382012-09-28 10:58:54 -070044 listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
45 listView->setDragDropMode(QAbstractItemView::NoDragDrop);
46 listView->setSelectionMode(QAbstractItemView::NoSelection);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -070047 m_rosterModel = new QStringListModel(this);
48 listView->setModel(m_rosterModel);
49
Zhenkai Zhu4b953d92012-10-08 13:09:40 -070050 refreshButton->setIcon(QIcon(QPixmap(":images/refresh.png")));
51
Zhenkai Zhu86df7412012-09-27 16:30:20 -070052 createActions();
53 createTrayIcon();
54 m_timer = new QTimer(this);
55 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
56 connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
Zhenkai Zhub60b7e12012-09-28 11:34:21 -070057 connect(treeButton, SIGNAL(pressed()), this, SLOT(treeButtonPressed()));
Zhenkai Zhu86581412012-10-08 16:58:39 -070058 connect(refreshButton, SIGNAL(pressed()), this, SLOT(getLocalPrefix()));
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 Zhu86581412012-10-08 16:58:39 -070079 QTimer::singleShot(100, this, SLOT(getLocalPrefix()));
Alexander Afanasyevebe118d2012-10-08 08:56:34 -070080
Zhenkai Zhucf024442012-10-05 10:33:08 -070081 QTimer::singleShot(600, this, SLOT(sendJoin()));
Zhenkai Zhu78799ea2012-10-08 11:51:56 -070082 m_timer->start(FRESHNESS * 1000);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -070083 disableTreeDisplay();
84 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070085 }
86 catch (Sync::CcnxOperationException ex)
87 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -070088 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 -070089 std::exit(1);
90 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -070091 }
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070092
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070093}
94
Zhenkai Zhu82a62752012-06-04 17:11:04 -070095ChatDialog::~ChatDialog()
96{
97 if (m_sock != NULL)
98 {
Zhenkai Zhucf024442012-10-05 10:33:08 -070099 sendLeave();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700100 delete m_sock;
101 m_sock = NULL;
102 }
103}
104
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700105void
Zhenkai Zhucf024442012-10-05 10:33:08 -0700106ChatDialog::sendLeave()
107{
108 SyncDemo::ChatMessage msg;
109 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
110 sendMsg(msg);
111 usleep(500000);
112 m_sock->remove(m_user.getPrefix().toStdString());
113 usleep(5000);
114#ifdef __DEBUG
115 std::cout << "Sync REMOVE signal sent" << std::endl;
116#endif
117}
118
119void
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700120ChatDialog::replot()
121{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700122 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700123 m_scene->plot(m_sock->getRootDigest().c_str());
Zhenkai Zhuc9e4e3c2012-10-02 11:47:31 -0700124 fitView();
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700125}
126
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700127void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700128ChatDialog::updateRosterList(QStringList staleUserList)
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700129{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700130 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700131 QStringList rosterList = m_scene->getRosterList();
132 m_rosterModel->setStringList(rosterList);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700133 QString user;
134 QStringListIterator it(staleUserList);
135 while(it.hasNext())
136 {
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700137 std::string nick = it.next().toStdString();
138 if (nick.empty())
139 continue;
140
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700141 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700142 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700143 msg.set_from(nick);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700144 appendMessage(msg);
145 }
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700146}
147
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700148void
149ChatDialog::setVisible(bool visible)
150{
151 minimizeAction->setEnabled(visible);
152 maximizeAction->setEnabled(!isMaximized());
153 restoreAction->setEnabled(isMaximized() || !visible);
154 QDialog::setVisible(visible);
155}
156
157void
158ChatDialog::closeEvent(QCloseEvent *e)
159{
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700160 if (trayIcon->isVisible() && !m_minimaniho)
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700161 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700162 QMessageBox::information(this, tr("Chronos"),
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700163 tr("The program will keep running in the "
164 "system tray. To terminate the program"
165 "choose <b>Quit</b> in the context memu"
166 "of the system tray entry."));
167 hide();
168 e->ignore();
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700169 m_minimaniho = true;
170 writeSettings();
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700171 }
172}
173
174void
175ChatDialog::changeEvent(QEvent *e)
176{
177 switch(e->type())
178 {
179 case QEvent::ActivationChange:
180 if (isActiveWindow())
181 {
182 trayIcon->setIcon(QIcon(":/images/icon_small.png"));
183 }
184 break;
185 default:
186 break;
187 }
188}
189
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700190void
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700191ChatDialog::appendMessage(const SyncDemo::ChatMessage msg, bool isHistory)
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700192{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700193 boost::recursive_mutex::scoped_lock lock(m_msgMutex);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700194
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700195 if (msg.type() == SyncDemo::ChatMessage::CHAT)
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700196 {
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700197
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700198 if (!msg.has_data())
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700199 {
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700200 return;
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700201 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700202
203 if (msg.from().empty() || msg.data().empty())
204 {
205 return;
206 }
207
208 if (!msg.has_timestamp())
209 {
210 return;
211 }
212
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700213 if (m_history.size() == MAX_HISTORY_ENTRY)
214 {
215 m_history.dequeue();
216 }
217
218 m_history.enqueue(msg);
219
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700220 QTextCharFormat nickFormat;
221 nickFormat.setForeground(Qt::darkGreen);
222 nickFormat.setFontWeight(QFont::Bold);
223 nickFormat.setFontUnderline(true);
224 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700225
226 QTextCursor cursor(textEdit->textCursor());
227 cursor.movePosition(QTextCursor::End);
228 QTextTableFormat tableFormat;
229 tableFormat.setBorder(0);
230 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
231 QString from = QString("%1 ").arg(msg.from().c_str());
232 QTextTableCell fromCell = table->cellAt(0, 0);
233 fromCell.setFormat(nickFormat);
234 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700235
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700236 time_t timestamp = msg.timestamp();
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700237 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700238
239 QTextCursor nextCursor(textEdit->textCursor());
240 nextCursor.movePosition(QTextCursor::End);
241 table = nextCursor.insertTable(1, 1, tableFormat);
Zhenkai Zhu767eac72012-10-08 11:20:57 -0700242 table->cellAt(0, 0).firstCursorPosition().insertText(QString::fromUtf8(msg.data().c_str()));
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700243 if (!isHistory)
244 {
Zhenkai Zhu767eac72012-10-08 11:20:57 -0700245 showMessage(from, QString::fromUtf8(msg.data().c_str()));
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700246 }
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700247 }
248
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700249 if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE)
250 {
251 QTextCharFormat nickFormat;
252 nickFormat.setForeground(Qt::gray);
253 nickFormat.setFontWeight(QFont::Bold);
254 nickFormat.setFontUnderline(true);
255 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700256
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700257 QTextCursor cursor(textEdit->textCursor());
258 cursor.movePosition(QTextCursor::End);
259 QTextTableFormat tableFormat;
260 tableFormat.setBorder(0);
261 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
262 QString action;
263 if (msg.type() == SyncDemo::ChatMessage::JOIN)
264 {
265 action = "enters room";
266 }
267 else
268 {
269 action = "leaves room";
270 }
271
272 QString from = QString("%1 %2 ").arg(msg.from().c_str()).arg(action);
273 QTextTableCell fromCell = table->cellAt(0, 0);
274 fromCell.setFormat(nickFormat);
275 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700276
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700277 time_t timestamp = msg.timestamp();
278 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700279 }
280
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700281 QScrollBar *bar = textEdit->verticalScrollBar();
282 bar->setValue(bar->maximum());
283}
284
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700285void
286ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
287{
288 QTextCharFormat timeFormat;
289 timeFormat.setForeground(Qt::gray);
290 timeFormat.setFontUnderline(true);
291 timeFormat.setUnderlineColor(Qt::gray);
292 QTextTableCell timeCell = table->cellAt(0, 1);
293 timeCell.setFormat(timeFormat);
294 timeCell.firstCursorPosition().insertText(formatTime(timestamp));
295}
296
297QString
298ChatDialog::formatTime(time_t timestamp)
299{
300 struct tm *tm_time = localtime(&timestamp);
301 int hour = tm_time->tm_hour;
302 QString amOrPM;
303 if (hour > 12)
304 {
305 hour -= 12;
306 amOrPM = "PM";
307 }
308 else
309 {
310 amOrPM = "AM";
311 if (hour == 0)
312 {
313 hour = 12;
314 }
315 }
316
317 char textTime[12];
318 sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
319 return QString(textTime);
320}
321
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700322void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700323ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
324{
325 emit treeUpdated(v);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700326#ifdef __DEBUG
327 std::cout << "<<< Tree update signal emitted" << std::endl;
328#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700329}
330
331void
332ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700333{
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700334#ifdef __DEBUG
335 std::cout << "<<< processing Tree Update" << std::endl;
336#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700337 if (v.empty())
338 {
339 return;
340 }
341
342 // reflect the changes on digest tree
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700343 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700344 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700345 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
346 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700347
348 int n = v.size();
349 int totalMissingPackets = 0;
350 for (int i = 0; i < n; i++)
351 {
352 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
353 }
354
Zhenkai Zhubb198112012-09-27 11:31:42 -0700355 for (int i = 0; i < n; i++)
356 {
357 if (totalMissingPackets < 4)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700358 {
359 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
360 {
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700361 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700362#ifdef __DEBUG
363 std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
364#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700365 }
366 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700367 else
368 {
369 m_sock->fetchRaw(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1, _2, _3), 2);
370 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700371 }
372
373 // adjust the view
374 fitView();
375
376}
377
378void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700379ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
380{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700381 char *tempBuf = new char[len];
382 memcpy(tempBuf, buf, len);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700383 emit dataReceived(name.c_str(), tempBuf, len, true, false);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700384#ifdef __DEBUG
385 std::cout <<"<<< " << name << " fetched" << std::endl;
386#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700387}
388
389void
Zhenkai Zhubb198112012-09-27 11:31:42 -0700390ChatDialog::processDataNoShowWrapper(std::string name, const char *buf, size_t len)
391{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700392 char *tempBuf = new char[len];
393 memcpy(tempBuf, buf, len);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700394 emit dataReceived(name.c_str(), tempBuf, len, false, false);
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700395
396 if (!m_historyInitialized)
397 {
398 fetchHistory(name);
399 m_historyInitialized = true;
400 }
401}
402
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700403void
404ChatDialog::processDataHistoryWrapper(std::string name, const char *buf, size_t len)
405{
406 char *tempBuf = new char[len];
407 memcpy(tempBuf, buf, len);
408 emit dataReceived(name.c_str(), tempBuf, len, true, true);
409}
410
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700411void
412ChatDialog::fetchHistory(std::string name)
413{
414 std::string nameWithoutSeq = name.substr(0, name.find_last_of('/'));
415 std::string prefix = nameWithoutSeq.substr(0, nameWithoutSeq.find_last_of('/'));
416 prefix += "/history";
417 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
418 QString randomString = getRandomString();
419 for (int i = 0; i < MAX_HISTORY_ENTRY; i++)
420 {
421 QString interest = QString("%1/%2/%3").arg(prefix.c_str()).arg(randomString).arg(i);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700422 handle->sendInterest(interest.toStdString(), bind(&ChatDialog::processDataHistoryWrapper, this, _1, _2, _3));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700423 }
424}
425
426void
427ChatDialog::respondHistoryRequest(std::string interest)
428{
429 std::string seqStr = interest.substr(interest.find_last_of('/') + 1);
430 int seq = boost::lexical_cast<int>(seqStr);
431 if (seq >= 0 && seq < m_history.size())
432 {
433 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
434 SyncDemo::ChatMessage msg = m_history.at(seq);
435 size_t size = msg.ByteSize();
436 char *buf = new char[size];
437 msg.SerializeToArray(buf, size);
438 handle->publishRawData(interest, buf, size, 1);
439 delete buf;
440 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700441}
442
443void
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700444ChatDialog::processData(QString name, const char *buf, size_t len, bool show, bool isHistory)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700445{
446 SyncDemo::ChatMessage msg;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700447 bool corrupted = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700448 if (!msg.ParseFromArray(buf, len))
449 {
Zhenkai Zhubb198112012-09-27 11:31:42 -0700450 std::cerr << "Errrrr.. Can not parse msg with name: " << name.toStdString() << ". what is happening?" << std::endl;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700451 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
452 msg.set_from("inconnu");
453 msg.set_type(SyncDemo::ChatMessage::OTHER);
454 corrupted = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700455 }
456
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700457 delete [] buf;
458 buf = NULL;
459
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700460 // display msg received from network
461 // we have to do so; this function is called by ccnd thread
462 // so if we call appendMsg directly
463 // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
464 // the "cannonical" way to is use signal-slot
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700465 if (show && !corrupted)
Zhenkai Zhubb198112012-09-27 11:31:42 -0700466 {
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700467 appendMessage(msg, isHistory);
Zhenkai Zhubb198112012-09-27 11:31:42 -0700468 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700469
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700470 if (!isHistory)
471 {
472 // update the tree view
473 std::string stdStrName = name.toStdString();
474 std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
475 std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700476#ifdef __DEBUG
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700477 std::cout <<"<<< updating scene for" << prefix << ": " << msg.from() << std::endl;
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700478#endif
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700479 if (msg.type() == SyncDemo::ChatMessage::LEAVE)
480 {
481 processRemove(prefix.c_str());
482 }
483 else
484 {
485 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
486 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
487 }
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700488 }
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700489 fitView();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700490}
491
492void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700493ChatDialog::processRemoveWrapper(std::string prefix)
494{
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700495#ifdef __DEBUG
496 std::cout << "Sync REMOVE signal received for prefix: " << prefix << std::endl;
497#endif
498 //emit removeReceived(prefix.c_str());
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700499}
500
501void
502ChatDialog::processRemove(QString prefix)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700503{
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700504#ifdef __DEBUG
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700505 std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700506#endif
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700507 bool removed = m_scene->removeNode(prefix);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700508 if (removed)
509 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700510 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700511 m_scene->plot(m_sock->getRootDigest().c_str());
512 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700513}
514
515void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700516ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700517 msg.set_from(m_user.getNick().toStdString());
518 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu767eac72012-10-08 11:20:57 -0700519 msg.set_data(text.toUtf8().constData());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700520 time_t seconds = time(NULL);
521 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700522 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700523}
524
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700525void
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700526ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700527{
528 msg.set_from(m_user.getNick().toStdString());
529 msg.set_to(m_user.getChatroom().toStdString());
530 time_t seconds = time(NULL);
531 msg.set_timestamp(seconds);
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700532 msg.set_type(type);
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700533}
534
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700535static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
536
537QString
538ChatDialog::getRandomString()
539{
540 std::string randStr;
541 boost::random::random_device rng;
542 boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
543 for (int i = 0; i < 10; i ++)
544 {
545 randStr += chars[index_dist(rng)];
546 }
547 return randStr.c_str();
548}
549
Zhenkai Zhu86581412012-10-08 16:58:39 -0700550void
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700551ChatDialog::getLocalPrefix()
552{
Zhenkai Zhu86581412012-10-08 16:58:39 -0700553// /*
554// * this method tries to use ccncat
555// * however, it does not work in Mac OS X app bundle
556// * it works well in command line though
557// */
558
559// std::string cmd = CCN_EXEC;
560// cmd += " -c -v ";
561// cmd += LOCAL_PREFIX_QUERY;
562// QString localPrefix;
563// #define MAX_PREFIX_LEN 100
564// FILE *fp = popen(cmd.c_str(), "r");
565// if (fp != NULL)
566// {
567// char prefix[MAX_PREFIX_LEN];
568// if (fgets(prefix, MAX_PREFIX_LEN, fp) != NULL)
569// {
570// localPrefix = prefix;
571// localPrefix.remove('\n');
572// }
573// else
574// {
575// localPrefix = DEFAULT_LOCAL_PREFIX;
576// }
577// pclose(fp);
578// }
579// else
580// {
581// localPrefix = DEFAULT_LOCAL_PREFIX;
582// }
583// return localPrefix;
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700584 std::cerr << "trying to get local prefix" << std::endl;
585
Zhenkai Zhu86581412012-10-08 16:58:39 -0700586 if (m_sock != NULL)
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700587 {
Zhenkai Zhu86581412012-10-08 16:58:39 -0700588 std::cerr << "trying to get local prefix2" << std::endl;
589 QString originPrefix = QString::fromStdString (m_sock->getLocalPrefix()).trimmed ();
590 std::cerr << "got: " << originPrefix.toStdString () << std::endl;
Zhenkai Zhuba707342012-10-08 16:20:15 -0700591
Zhenkai Zhu86581412012-10-08 16:58:39 -0700592 if (originPrefix != "" && m_user.getOriginPrefix () != originPrefix)
593 {
594 // m_user.setOriginPrefix(originPrefix);
595 emit settingUpdated(m_user.getNick (), m_user.getChatroom (), originPrefix);
596 // connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT());
597 }
598 }
599 else
600 {
601 std::cerr << "socket is not availble" << std::endl;
602 // QTimer::singleShot(1000, this, SLOT(getLocalPrefix())); // try again
603 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700604}
605
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700606bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700607ChatDialog::readSettings()
608{
609 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700610 QString nick = s.value("nick", "").toString();
611 QString chatroom = s.value("chatroom", "").toString();
Zhenkai Zhu86581412012-10-08 16:58:39 -0700612 // QString originPrefix = s.value("originPrefix", "").toString();
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700613
Zhenkai Zhu86581412012-10-08 16:58:39 -0700614 // Sync::CcnxWrapperPtr wrapper = Sync::CcnxWrapper::Create ();
615 // QString originPrefix = QString::fromStdString (wrapper->getLocalPrefix());
616 // Sync::CcnxWrapper::Destroy ();
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700617
Zhenkai Zhu86581412012-10-08 16:58:39 -0700618 QString originPrefix = DEFAULT_LOCAL_PREFIX;
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700619
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700620 m_minimaniho = s.value("minimaniho", false).toBool();
621 if (nick == "" || chatroom == "" || originPrefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700622 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700623 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700624 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700625 else {
626 m_user.setNick(nick);
627 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700628 m_user.setOriginPrefix(originPrefix);
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700629 m_user.setPrefix(originPrefix + "/" + chatroom + "/" + getRandomString());
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700630 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700631 }
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700632
633// QTimer::singleShot(500, this, SLOT(buttonPressed()));
634 // return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700635}
636
637void
638ChatDialog::writeSettings()
639{
640 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700641 s.setValue("nick", m_user.getNick());
642 s.setValue("chatroom", m_user.getChatroom());
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700643 //s.setValue("originPrefix", m_user.getOriginPrefix());
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700644 s.setValue("minimaniho", m_minimaniho);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700645}
646
647void
648ChatDialog::updateLabels()
649{
Zhenkai Zhu76ff02b2012-09-27 21:11:03 -0700650 QString settingDisp = QString("Chatroom: %1").arg(m_user.getChatroom());
651 infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700652 infoLabel->setText(settingDisp);
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700653 QString prefixDisp;
654 if (m_user.getPrefix().startsWith(DEFAULT_LOCAL_PREFIX))
655 {
656 prefixDisp = QString("<Warning: Auto config prefix failed.>\n <Prefix = %1>").arg(m_user.getPrefix());
657 prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
658 }
659 else
660 {
661 prefixDisp = QString("<Prefix = %1>").arg(m_user.getPrefix());
662 prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
663 }
664 prefixLabel->setText(prefixDisp);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700665}
666
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700667void
668ChatDialog::returnPressed()
669{
670 QString text = lineEdit->text();
671 if (text.isEmpty())
672 return;
673
Zhenkai Zhub6338822012-05-31 13:27:24 -0700674 lineEdit->clear();
675
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700676 SyncDemo::ChatMessage msg;
677 formChatMessage(text, msg);
678
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700679 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700680
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700681 sendMsg(msg);
682
683 fitView();
684}
685
686void
687ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
688{
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700689 // send msg
690 size_t size = msg.ByteSize();
691 char *buf = new char[size];
692 msg.SerializeToArray(buf, size);
693 if (!msg.IsInitialized())
694 {
695 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
696 abort();
697 }
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700698 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700699
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700700 delete buf;
701
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700702 m_lastMsgTime = time(NULL);
703
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700704 int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700705 Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700706 std::vector<Sync::MissingDataInfo> v;
707 v.push_back(mdi);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700708 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700709 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700710 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
711 m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
712 }
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700713}
714
715void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700716ChatDialog::sendJoin()
717{
718 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700719 formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700720 sendMsg(msg);
Zhenkai Zhuc61dbc22012-10-08 11:36:37 -0700721 boost::random::random_device rng;
722 boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
723 m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700724 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
725}
726
727void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700728ChatDialog::sendHello()
729{
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700730 time_t now = time(NULL);
731 int elapsed = now - m_lastMsgTime;
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700732 if (elapsed >= m_randomizedInterval / 1000)
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700733 {
734 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700735 formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700736 sendMsg(msg);
Zhenkai Zhuc61dbc22012-10-08 11:36:37 -0700737 boost::random::random_device rng;
738 boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
739 m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700740 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700741 }
742 else
743 {
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700744 QTimer::singleShot((m_randomizedInterval - elapsed * 1000), this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700745 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700746}
747
748void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700749ChatDialog::buttonPressed()
750{
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700751 Sync::SyncLogic &logic = m_sock->getLogic ();
752 logic.printState ();
753
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700754 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getOriginPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700755 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700756 dialog.exec();
Zhenkai Zhue837f792012-06-05 20:47:54 -0700757 QTimer::singleShot(100, this, SLOT(checkSetting()));
758}
759
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700760void ChatDialog::treeButtonPressed()
761{
762 if (treeViewer->isVisible())
763 {
764 treeViewer->hide();
765 treeButton->setText("Show Sync Tree");
766 }
767 else
768 {
769 treeViewer->show();
770 treeButton->setText("Hide Sync Tree");
771 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700772
773 fitView();
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700774}
775
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700776void ChatDialog::enableTreeDisplay()
777{
778 treeButton->setEnabled(true);
779 treeViewer->show();
780 fitView();
781}
782
783void ChatDialog::disableTreeDisplay()
784{
785 treeButton->setEnabled(false);
786 treeViewer->hide();
787 fitView();
788}
789
Zhenkai Zhue837f792012-06-05 20:47:54 -0700790void
791ChatDialog::checkSetting()
792{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700793 if (m_user.getOriginPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
Zhenkai Zhue837f792012-06-05 20:47:54 -0700794 {
795 buttonPressed();
796 }
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700797}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700798
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700799void
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700800ChatDialog::settingUpdated(QString nick, QString chatroom, QString originPrefix)
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700801{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700802 QString randString = getRandomString();
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700803 bool needWrite = false;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700804 bool needFresh = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700805 if (!nick.isEmpty() && nick != m_user.getNick()) {
806 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700807 needWrite = true;
808 }
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700809 QString oldPrefix = m_user.getPrefix();
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700810 if (!originPrefix.isEmpty() && originPrefix != m_user.getOriginPrefix()) {
811 m_user.setOriginPrefix(originPrefix);
812 m_user.setPrefix(originPrefix + "/" + m_user.getChatroom() + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700813 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700814 needFresh = true;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700815 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700816 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
817 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700818 m_user.setPrefix(m_user.getOriginPrefix() + "/" + chatroom + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700819 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700820 needFresh = true;
821 }
822
823 if (needFresh)
824 {
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700825
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700826 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700827 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700828 m_scene->clearAll();
829 m_scene->plot("Empty");
830 }
Zhenkai Zhucc4c2c02012-09-27 21:24:37 -0700831
832 textEdit->clear();
833
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700834 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700835 if (m_sock != NULL)
836 {
Zhenkai Zhu77fc8f22012-10-08 15:12:56 -0700837 // keep the new prefix
838 QString newPrefix = m_user.getPrefix();
839 // send leave for the old
840 m_user.setPrefix(oldPrefix);
Zhenkai Zhucf024442012-10-05 10:33:08 -0700841 sendLeave();
Zhenkai Zhu77fc8f22012-10-08 15:12:56 -0700842 // resume new prefix
843 m_user.setPrefix(newPrefix);
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700844 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
845 handle->clearInterestFilter(oldPrefix.toStdString());
846 m_history.clear();
847 m_historyInitialized = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700848 delete m_sock;
849 m_sock = NULL;
850 }
851 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
852 syncPrefix += "/";
853 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700854 try
855 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700856 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700857 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
858 handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
Alexander Afanasyev288edd82012-10-04 17:07:56 -0700859 QTimer::singleShot(1000, this, SLOT(sendJoin()));
Zhenkai Zhu78799ea2012-10-08 11:51:56 -0700860 m_timer->start(FRESHNESS * 1000);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700861 disableTreeDisplay();
862 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700863 }
864 catch (Sync::CcnxOperationException ex)
865 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700866 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 -0700867 std::exit(1);
868 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700869
870 fitView();
871
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700872 }
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700873
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700874 if (needWrite) {
875 writeSettings();
876 updateLabels();
877 }
878}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700879
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700880void
881ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
882{
883 switch (reason)
884 {
885 case QSystemTrayIcon::Trigger:
886 case QSystemTrayIcon::DoubleClick:
887 break;
888 case QSystemTrayIcon::MiddleClick:
889 // showMessage();
890 break;
891 default:;
892 }
893}
894
895void
896ChatDialog::showMessage(QString from, QString data)
897{
898 // std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
899 if (!isActiveWindow())
900 {
901 trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
902 trayIcon->setIcon(QIcon(":/images/note.png"));
903 }
904}
905
906void
907ChatDialog::messageClicked()
908{
909 this->showMaximized();
910}
911
912void
913ChatDialog::createActions()
914{
915 minimizeAction = new QAction(tr("Mi&nimize"), this);
916 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
917
918 maximizeAction = new QAction(tr("Ma&ximize"), this);
919 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
920
921 restoreAction = new QAction(tr("&Restore"), this);
922 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
923
924 quitAction = new QAction(tr("Quit"), this);
925 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
926}
927
928void
929ChatDialog::createTrayIcon()
930{
931 trayIconMenu = new QMenu(this);
932 trayIconMenu->addAction(minimizeAction);
933 trayIconMenu->addAction(maximizeAction);
934 trayIconMenu->addAction(restoreAction);
935 trayIconMenu->addSeparator();
936 trayIconMenu->addAction(quitAction);
937
938 trayIcon = new QSystemTrayIcon(this);
939 trayIcon->setContextMenu(trayIconMenu);
940
941 QIcon icon(":/images/icon_small.png");
942 trayIcon->setIcon(icon);
943 setWindowIcon(icon);
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700944 trayIcon->setToolTip("Chronos System Tray Icon");
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700945 trayIcon->setVisible(true);
946}
947
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700948void
949ChatDialog::resizeEvent(QResizeEvent *e)
950{
951 fitView();
952}
953
954void
955ChatDialog::showEvent(QShowEvent *e)
956{
957 fitView();
958}
959
960void
961ChatDialog::fitView()
962{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700963 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700964 QRectF rect = m_scene->itemsBoundingRect();
965 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700966 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700967}