blob: 845ccfb2b4650c58f31d1dc5f69d02bda4f70d95 [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 Zhu86df7412012-09-27 16:30:20 -070050 createActions();
51 createTrayIcon();
52 m_timer = new QTimer(this);
53 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
54 connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
Zhenkai Zhub60b7e12012-09-28 11:34:21 -070055 connect(treeButton, SIGNAL(pressed()), this, SLOT(treeButtonPressed()));
Zhenkai Zhu24ec4722012-10-07 17:56:38 -070056 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 -070057 connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070058 connect(m_timer, SIGNAL(timeout()), this, SLOT(replot()));
59 connect(m_scene, SIGNAL(replot()), this, SLOT(replot()));
60 connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showNormal()));
61 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
Zhenkai Zhu25e33e52012-09-28 13:00:07 -070062 connect(m_scene, SIGNAL(rosterChanged(QStringList)), this, SLOT(updateRosterList(QStringList)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070063
Zhenkai Zhu82a62752012-06-04 17:11:04 -070064 // create sync socket
65 if(!m_user.getChatroom().isEmpty()) {
66 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
67 syncPrefix += "/";
68 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070069 try
70 {
Alexander Afanasyev288edd82012-10-04 17:07:56 -070071 m_sock = new Sync::SyncAppSocket(syncPrefix,
72 bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
73 bind(&ChatDialog::processRemoveWrapper, this, _1));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -070074 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
75 handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
Alexander Afanasyevebe118d2012-10-08 08:56:34 -070076 QTimer::singleShot(100, this, SLOT(getLocalPrefix()));
77
Zhenkai Zhucf024442012-10-05 10:33:08 -070078 QTimer::singleShot(600, this, SLOT(sendJoin()));
Zhenkai Zhuc61dbc22012-10-08 11:36:37 -070079 m_timer->start(FRESHNESS);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -070080 disableTreeDisplay();
81 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070082 }
83 catch (Sync::CcnxOperationException ex)
84 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -070085 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 -070086 std::exit(1);
87 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -070088 }
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070089
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070090}
91
Zhenkai Zhu82a62752012-06-04 17:11:04 -070092ChatDialog::~ChatDialog()
93{
94 if (m_sock != NULL)
95 {
Zhenkai Zhucf024442012-10-05 10:33:08 -070096 sendLeave();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070097 delete m_sock;
98 m_sock = NULL;
99 }
100}
101
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700102void
Zhenkai Zhucf024442012-10-05 10:33:08 -0700103ChatDialog::sendLeave()
104{
105 SyncDemo::ChatMessage msg;
106 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
107 sendMsg(msg);
108 usleep(500000);
109 m_sock->remove(m_user.getPrefix().toStdString());
110 usleep(5000);
111#ifdef __DEBUG
112 std::cout << "Sync REMOVE signal sent" << std::endl;
113#endif
114}
115
116void
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700117ChatDialog::replot()
118{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700119 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700120 m_scene->plot(m_sock->getRootDigest().c_str());
Zhenkai Zhuc9e4e3c2012-10-02 11:47:31 -0700121 fitView();
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700122}
123
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700124void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700125ChatDialog::updateRosterList(QStringList staleUserList)
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700126{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700127 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700128 QStringList rosterList = m_scene->getRosterList();
129 m_rosterModel->setStringList(rosterList);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700130 QString user;
131 QStringListIterator it(staleUserList);
132 while(it.hasNext())
133 {
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700134 std::string nick = it.next().toStdString();
135 if (nick.empty())
136 continue;
137
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700138 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700139 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700140 msg.set_from(nick);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700141 appendMessage(msg);
142 }
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700143}
144
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700145void
146ChatDialog::setVisible(bool visible)
147{
148 minimizeAction->setEnabled(visible);
149 maximizeAction->setEnabled(!isMaximized());
150 restoreAction->setEnabled(isMaximized() || !visible);
151 QDialog::setVisible(visible);
152}
153
154void
155ChatDialog::closeEvent(QCloseEvent *e)
156{
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700157 if (trayIcon->isVisible() && !m_minimaniho)
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700158 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700159 QMessageBox::information(this, tr("Chronos"),
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700160 tr("The program will keep running in the "
161 "system tray. To terminate the program"
162 "choose <b>Quit</b> in the context memu"
163 "of the system tray entry."));
164 hide();
165 e->ignore();
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700166 m_minimaniho = true;
167 writeSettings();
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700168 }
169}
170
171void
172ChatDialog::changeEvent(QEvent *e)
173{
174 switch(e->type())
175 {
176 case QEvent::ActivationChange:
177 if (isActiveWindow())
178 {
179 trayIcon->setIcon(QIcon(":/images/icon_small.png"));
180 }
181 break;
182 default:
183 break;
184 }
185}
186
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700187void
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700188ChatDialog::appendMessage(const SyncDemo::ChatMessage msg, bool isHistory)
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700189{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700190 boost::recursive_mutex::scoped_lock lock(m_msgMutex);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700191
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700192 if (msg.type() == SyncDemo::ChatMessage::CHAT)
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700193 {
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700194
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700195 if (!msg.has_data())
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700196 {
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700197 return;
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700198 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700199
200 if (msg.from().empty() || msg.data().empty())
201 {
202 return;
203 }
204
205 if (!msg.has_timestamp())
206 {
207 return;
208 }
209
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700210 if (m_history.size() == MAX_HISTORY_ENTRY)
211 {
212 m_history.dequeue();
213 }
214
215 m_history.enqueue(msg);
216
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700217 QTextCharFormat nickFormat;
218 nickFormat.setForeground(Qt::darkGreen);
219 nickFormat.setFontWeight(QFont::Bold);
220 nickFormat.setFontUnderline(true);
221 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700222
223 QTextCursor cursor(textEdit->textCursor());
224 cursor.movePosition(QTextCursor::End);
225 QTextTableFormat tableFormat;
226 tableFormat.setBorder(0);
227 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
228 QString from = QString("%1 ").arg(msg.from().c_str());
229 QTextTableCell fromCell = table->cellAt(0, 0);
230 fromCell.setFormat(nickFormat);
231 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700232
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700233 time_t timestamp = msg.timestamp();
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700234 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700235
236 QTextCursor nextCursor(textEdit->textCursor());
237 nextCursor.movePosition(QTextCursor::End);
238 table = nextCursor.insertTable(1, 1, tableFormat);
Zhenkai Zhu767eac72012-10-08 11:20:57 -0700239 table->cellAt(0, 0).firstCursorPosition().insertText(QString::fromUtf8(msg.data().c_str()));
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700240 if (!isHistory)
241 {
Zhenkai Zhu767eac72012-10-08 11:20:57 -0700242 showMessage(from, QString::fromUtf8(msg.data().c_str()));
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700243 }
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700244 }
245
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700246 if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE)
247 {
248 QTextCharFormat nickFormat;
249 nickFormat.setForeground(Qt::gray);
250 nickFormat.setFontWeight(QFont::Bold);
251 nickFormat.setFontUnderline(true);
252 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700253
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700254 QTextCursor cursor(textEdit->textCursor());
255 cursor.movePosition(QTextCursor::End);
256 QTextTableFormat tableFormat;
257 tableFormat.setBorder(0);
258 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
259 QString action;
260 if (msg.type() == SyncDemo::ChatMessage::JOIN)
261 {
262 action = "enters room";
263 }
264 else
265 {
266 action = "leaves room";
267 }
268
269 QString from = QString("%1 %2 ").arg(msg.from().c_str()).arg(action);
270 QTextTableCell fromCell = table->cellAt(0, 0);
271 fromCell.setFormat(nickFormat);
272 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700273
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700274 time_t timestamp = msg.timestamp();
275 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700276 }
277
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700278 QScrollBar *bar = textEdit->verticalScrollBar();
279 bar->setValue(bar->maximum());
280}
281
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700282void
283ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
284{
285 QTextCharFormat timeFormat;
286 timeFormat.setForeground(Qt::gray);
287 timeFormat.setFontUnderline(true);
288 timeFormat.setUnderlineColor(Qt::gray);
289 QTextTableCell timeCell = table->cellAt(0, 1);
290 timeCell.setFormat(timeFormat);
291 timeCell.firstCursorPosition().insertText(formatTime(timestamp));
292}
293
294QString
295ChatDialog::formatTime(time_t timestamp)
296{
297 struct tm *tm_time = localtime(&timestamp);
298 int hour = tm_time->tm_hour;
299 QString amOrPM;
300 if (hour > 12)
301 {
302 hour -= 12;
303 amOrPM = "PM";
304 }
305 else
306 {
307 amOrPM = "AM";
308 if (hour == 0)
309 {
310 hour = 12;
311 }
312 }
313
314 char textTime[12];
315 sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
316 return QString(textTime);
317}
318
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700319void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700320ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
321{
322 emit treeUpdated(v);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700323#ifdef __DEBUG
324 std::cout << "<<< Tree update signal emitted" << std::endl;
325#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700326}
327
328void
329ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700330{
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700331#ifdef __DEBUG
332 std::cout << "<<< processing Tree Update" << std::endl;
333#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700334 if (v.empty())
335 {
336 return;
337 }
338
339 // reflect the changes on digest tree
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700340 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700341 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700342 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
343 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700344
345 int n = v.size();
346 int totalMissingPackets = 0;
347 for (int i = 0; i < n; i++)
348 {
349 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
350 }
351
Zhenkai Zhubb198112012-09-27 11:31:42 -0700352 for (int i = 0; i < n; i++)
353 {
354 if (totalMissingPackets < 4)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700355 {
356 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
357 {
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700358 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700359#ifdef __DEBUG
360 std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
361#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700362 }
363 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700364 else
365 {
366 m_sock->fetchRaw(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1, _2, _3), 2);
367 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700368 }
369
370 // adjust the view
371 fitView();
372
373}
374
375void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700376ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
377{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700378 char *tempBuf = new char[len];
379 memcpy(tempBuf, buf, len);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700380 emit dataReceived(name.c_str(), tempBuf, len, true, false);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700381#ifdef __DEBUG
382 std::cout <<"<<< " << name << " fetched" << std::endl;
383#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700384}
385
386void
Zhenkai Zhubb198112012-09-27 11:31:42 -0700387ChatDialog::processDataNoShowWrapper(std::string name, const char *buf, size_t len)
388{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700389 char *tempBuf = new char[len];
390 memcpy(tempBuf, buf, len);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700391 emit dataReceived(name.c_str(), tempBuf, len, false, false);
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700392
393 if (!m_historyInitialized)
394 {
395 fetchHistory(name);
396 m_historyInitialized = true;
397 }
398}
399
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700400void
401ChatDialog::processDataHistoryWrapper(std::string name, const char *buf, size_t len)
402{
403 char *tempBuf = new char[len];
404 memcpy(tempBuf, buf, len);
405 emit dataReceived(name.c_str(), tempBuf, len, true, true);
406}
407
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700408void
409ChatDialog::fetchHistory(std::string name)
410{
411 std::string nameWithoutSeq = name.substr(0, name.find_last_of('/'));
412 std::string prefix = nameWithoutSeq.substr(0, nameWithoutSeq.find_last_of('/'));
413 prefix += "/history";
414 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
415 QString randomString = getRandomString();
416 for (int i = 0; i < MAX_HISTORY_ENTRY; i++)
417 {
418 QString interest = QString("%1/%2/%3").arg(prefix.c_str()).arg(randomString).arg(i);
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700419 handle->sendInterest(interest.toStdString(), bind(&ChatDialog::processDataHistoryWrapper, this, _1, _2, _3));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700420 }
421}
422
423void
424ChatDialog::respondHistoryRequest(std::string interest)
425{
426 std::string seqStr = interest.substr(interest.find_last_of('/') + 1);
427 int seq = boost::lexical_cast<int>(seqStr);
428 if (seq >= 0 && seq < m_history.size())
429 {
430 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
431 SyncDemo::ChatMessage msg = m_history.at(seq);
432 size_t size = msg.ByteSize();
433 char *buf = new char[size];
434 msg.SerializeToArray(buf, size);
435 handle->publishRawData(interest, buf, size, 1);
436 delete buf;
437 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700438}
439
440void
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700441ChatDialog::processData(QString name, const char *buf, size_t len, bool show, bool isHistory)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700442{
443 SyncDemo::ChatMessage msg;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700444 bool corrupted = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700445 if (!msg.ParseFromArray(buf, len))
446 {
Zhenkai Zhubb198112012-09-27 11:31:42 -0700447 std::cerr << "Errrrr.. Can not parse msg with name: " << name.toStdString() << ". what is happening?" << std::endl;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700448 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
449 msg.set_from("inconnu");
450 msg.set_type(SyncDemo::ChatMessage::OTHER);
451 corrupted = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700452 }
453
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700454 delete [] buf;
455 buf = NULL;
456
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700457 // display msg received from network
458 // we have to do so; this function is called by ccnd thread
459 // so if we call appendMsg directly
460 // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
461 // the "cannonical" way to is use signal-slot
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700462 if (show && !corrupted)
Zhenkai Zhubb198112012-09-27 11:31:42 -0700463 {
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700464 appendMessage(msg, isHistory);
Zhenkai Zhubb198112012-09-27 11:31:42 -0700465 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700466
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700467 if (!isHistory)
468 {
469 // update the tree view
470 std::string stdStrName = name.toStdString();
471 std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
472 std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700473#ifdef __DEBUG
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700474 std::cout <<"<<< updating scene for" << prefix << ": " << msg.from() << std::endl;
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700475#endif
Zhenkai Zhu24ec4722012-10-07 17:56:38 -0700476 if (msg.type() == SyncDemo::ChatMessage::LEAVE)
477 {
478 processRemove(prefix.c_str());
479 }
480 else
481 {
482 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
483 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
484 }
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700485 }
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700486 fitView();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700487}
488
489void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700490ChatDialog::processRemoveWrapper(std::string prefix)
491{
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700492#ifdef __DEBUG
493 std::cout << "Sync REMOVE signal received for prefix: " << prefix << std::endl;
494#endif
495 //emit removeReceived(prefix.c_str());
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700496}
497
498void
499ChatDialog::processRemove(QString prefix)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700500{
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700501#ifdef __DEBUG
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700502 std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700503#endif
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700504 bool removed = m_scene->removeNode(prefix);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700505 if (removed)
506 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700507 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700508 m_scene->plot(m_sock->getRootDigest().c_str());
509 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700510}
511
512void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700513ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700514 msg.set_from(m_user.getNick().toStdString());
515 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu767eac72012-10-08 11:20:57 -0700516 msg.set_data(text.toUtf8().constData());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700517 time_t seconds = time(NULL);
518 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700519 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700520}
521
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700522void
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700523ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700524{
525 msg.set_from(m_user.getNick().toStdString());
526 msg.set_to(m_user.getChatroom().toStdString());
527 time_t seconds = time(NULL);
528 msg.set_timestamp(seconds);
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700529 msg.set_type(type);
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700530}
531
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700532static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
533
534QString
535ChatDialog::getRandomString()
536{
537 std::string randStr;
538 boost::random::random_device rng;
539 boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
540 for (int i = 0; i < 10; i ++)
541 {
542 randStr += chars[index_dist(rng)];
543 }
544 return randStr.c_str();
545}
546
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700547void
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700548ChatDialog::getLocalPrefix()
549{
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700550// /*
551// * this method tries to use ccncat
552// * however, it does not work in Mac OS X app bundle
553// * it works well in command line though
554// */
Zhenkai Zhu756666a2012-10-07 00:24:35 -0700555
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700556// std::string cmd = CCN_EXEC;
557// cmd += " -c -v ";
558// cmd += LOCAL_PREFIX_QUERY;
559// QString localPrefix;
560// #define MAX_PREFIX_LEN 100
561// FILE *fp = popen(cmd.c_str(), "r");
562// if (fp != NULL)
563// {
564// char prefix[MAX_PREFIX_LEN];
565// if (fgets(prefix, MAX_PREFIX_LEN, fp) != NULL)
566// {
567// localPrefix = prefix;
568// localPrefix.remove('\n');
569// }
570// else
571// {
572// localPrefix = DEFAULT_LOCAL_PREFIX;
573// }
574// pclose(fp);
575// }
576// else
577// {
578// localPrefix = DEFAULT_LOCAL_PREFIX;
579// }
580// return localPrefix;
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700581 std::cerr << "trying to get local prefix" << std::endl;
582
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700583 if (m_sock != NULL)
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700584 {
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700585 std::cerr << "trying to get local prefix2" << std::endl;
586 QString originPrefix = QString::fromStdString (m_sock->getLocalPrefix()).trimmed ();
587 std::cerr << "got: " << originPrefix.toStdString () << std::endl;
588
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700589 if (originPrefix != "" && m_user.getOriginPrefix () != originPrefix)
590 {
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700591 // m_user.setOriginPrefix(originPrefix);
592 emit settingUpdated(m_user.getNick (), m_user.getChatroom (), originPrefix);
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700593 // connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT());
594 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700595 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700596 else
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700597 {
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700598 std::cerr << "socket is not availble" << std::endl;
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700599 // QTimer::singleShot(1000, this, SLOT(getLocalPrefix())); // try again
600 }
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700601}
602
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700603bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700604ChatDialog::readSettings()
605{
606 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700607 QString nick = s.value("nick", "").toString();
608 QString chatroom = s.value("chatroom", "").toString();
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700609 // QString originPrefix = s.value("originPrefix", "").toString();
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700610
611 // Sync::CcnxWrapperPtr wrapper = Sync::CcnxWrapper::Create ();
612 // QString originPrefix = QString::fromStdString (wrapper->getLocalPrefix());
613 // Sync::CcnxWrapper::Destroy ();
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700614
Alexander Afanasyevebe118d2012-10-08 08:56:34 -0700615 QString originPrefix = DEFAULT_LOCAL_PREFIX;
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700616
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700617 m_minimaniho = s.value("minimaniho", false).toBool();
618 if (nick == "" || chatroom == "" || originPrefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700619 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700620 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700621 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700622 else {
623 m_user.setNick(nick);
624 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700625 m_user.setOriginPrefix(originPrefix);
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700626 m_user.setPrefix(originPrefix + "/" + chatroom + "/" + getRandomString());
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700627 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700628 }
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700629
630// QTimer::singleShot(500, this, SLOT(buttonPressed()));
631 // return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700632}
633
634void
635ChatDialog::writeSettings()
636{
637 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700638 s.setValue("nick", m_user.getNick());
639 s.setValue("chatroom", m_user.getChatroom());
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700640 //s.setValue("originPrefix", m_user.getOriginPrefix());
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700641 s.setValue("minimaniho", m_minimaniho);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700642}
643
644void
645ChatDialog::updateLabels()
646{
Zhenkai Zhu76ff02b2012-09-27 21:11:03 -0700647 QString settingDisp = QString("Chatroom: %1").arg(m_user.getChatroom());
648 infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700649 infoLabel->setText(settingDisp);
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700650 QString prefixDisp;
651 if (m_user.getPrefix().startsWith(DEFAULT_LOCAL_PREFIX))
652 {
653 prefixDisp = QString("<Warning: Auto config prefix failed.>\n <Prefix = %1>").arg(m_user.getPrefix());
654 prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
655 }
656 else
657 {
658 prefixDisp = QString("<Prefix = %1>").arg(m_user.getPrefix());
659 prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
660 }
661 prefixLabel->setText(prefixDisp);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700662}
663
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700664void
665ChatDialog::returnPressed()
666{
667 QString text = lineEdit->text();
668 if (text.isEmpty())
669 return;
670
Zhenkai Zhub6338822012-05-31 13:27:24 -0700671 lineEdit->clear();
672
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700673 SyncDemo::ChatMessage msg;
674 formChatMessage(text, msg);
675
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700676 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700677
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700678 sendMsg(msg);
679
680 fitView();
681}
682
683void
684ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
685{
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700686 // send msg
687 size_t size = msg.ByteSize();
688 char *buf = new char[size];
689 msg.SerializeToArray(buf, size);
690 if (!msg.IsInitialized())
691 {
692 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
693 abort();
694 }
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700695 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700696
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700697 delete buf;
698
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700699 m_lastMsgTime = time(NULL);
700
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700701 int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700702 Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700703 std::vector<Sync::MissingDataInfo> v;
704 v.push_back(mdi);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700705 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700706 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700707 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
708 m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
709 }
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700710}
711
712void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700713ChatDialog::sendJoin()
714{
715 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700716 formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700717 sendMsg(msg);
Zhenkai Zhuc61dbc22012-10-08 11:36:37 -0700718 boost::random::random_device rng;
719 boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
720 m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700721 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
722}
723
724void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700725ChatDialog::sendHello()
726{
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700727 time_t now = time(NULL);
728 int elapsed = now - m_lastMsgTime;
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700729 if (elapsed >= m_randomizedInterval / 1000)
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700730 {
731 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700732 formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700733 sendMsg(msg);
Zhenkai Zhuc61dbc22012-10-08 11:36:37 -0700734 boost::random::random_device rng;
735 boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
736 m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700737 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700738 }
739 else
740 {
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700741 QTimer::singleShot((m_randomizedInterval - elapsed * 1000), this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700742 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700743}
744
745void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700746ChatDialog::buttonPressed()
747{
Alexander Afanasyev5ddc68b2012-10-08 00:21:40 -0700748 Sync::SyncLogic &logic = m_sock->getLogic ();
749 logic.printState ();
750
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700751 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getOriginPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700752 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700753 dialog.exec();
Zhenkai Zhue837f792012-06-05 20:47:54 -0700754 QTimer::singleShot(100, this, SLOT(checkSetting()));
755}
756
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700757void ChatDialog::treeButtonPressed()
758{
759 if (treeViewer->isVisible())
760 {
761 treeViewer->hide();
762 treeButton->setText("Show Sync Tree");
763 }
764 else
765 {
766 treeViewer->show();
767 treeButton->setText("Hide Sync Tree");
768 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700769
770 fitView();
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700771}
772
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700773void ChatDialog::enableTreeDisplay()
774{
775 treeButton->setEnabled(true);
776 treeViewer->show();
777 fitView();
778}
779
780void ChatDialog::disableTreeDisplay()
781{
782 treeButton->setEnabled(false);
783 treeViewer->hide();
784 fitView();
785}
786
Zhenkai Zhue837f792012-06-05 20:47:54 -0700787void
788ChatDialog::checkSetting()
789{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700790 if (m_user.getOriginPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
Zhenkai Zhue837f792012-06-05 20:47:54 -0700791 {
792 buttonPressed();
793 }
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700794}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700795
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700796void
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700797ChatDialog::settingUpdated(QString nick, QString chatroom, QString originPrefix)
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700798{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700799 QString randString = getRandomString();
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700800 bool needWrite = false;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700801 bool needFresh = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700802 if (!nick.isEmpty() && nick != m_user.getNick()) {
803 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700804 needWrite = true;
805 }
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700806 QString oldPrefix = m_user.getPrefix();
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700807 if (!originPrefix.isEmpty() && originPrefix != m_user.getOriginPrefix()) {
808 m_user.setOriginPrefix(originPrefix);
809 m_user.setPrefix(originPrefix + "/" + m_user.getChatroom() + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700810 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700811 needFresh = true;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700812 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700813 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
814 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700815 m_user.setPrefix(m_user.getOriginPrefix() + "/" + chatroom + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700816 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700817 needFresh = true;
818 }
819
820 if (needFresh)
821 {
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700822
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700823 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700824 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700825 m_scene->clearAll();
826 m_scene->plot("Empty");
827 }
Zhenkai Zhucc4c2c02012-09-27 21:24:37 -0700828
829 textEdit->clear();
830
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700831 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700832 if (m_sock != NULL)
833 {
Zhenkai Zhucf024442012-10-05 10:33:08 -0700834 sendLeave();
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700835 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
836 handle->clearInterestFilter(oldPrefix.toStdString());
837 m_history.clear();
838 m_historyInitialized = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700839 delete m_sock;
840 m_sock = NULL;
841 }
842 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
843 syncPrefix += "/";
844 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700845 try
846 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700847 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
Zhenkai Zhu6c4fc112012-10-07 17:07:43 -0700848 Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
849 handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
Alexander Afanasyev288edd82012-10-04 17:07:56 -0700850 QTimer::singleShot(1000, this, SLOT(sendJoin()));
Zhenkai Zhuc61dbc22012-10-08 11:36:37 -0700851 m_timer->start(FRESHNESS);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700852 disableTreeDisplay();
853 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700854 }
855 catch (Sync::CcnxOperationException ex)
856 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700857 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 -0700858 std::exit(1);
859 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700860
861 fitView();
862
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700863 }
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700864
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700865 if (needWrite) {
866 writeSettings();
867 updateLabels();
868 }
869}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700870
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700871void
872ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
873{
874 switch (reason)
875 {
876 case QSystemTrayIcon::Trigger:
877 case QSystemTrayIcon::DoubleClick:
878 break;
879 case QSystemTrayIcon::MiddleClick:
880 // showMessage();
881 break;
882 default:;
883 }
884}
885
886void
887ChatDialog::showMessage(QString from, QString data)
888{
889 // std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
890 if (!isActiveWindow())
891 {
892 trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
893 trayIcon->setIcon(QIcon(":/images/note.png"));
894 }
895}
896
897void
898ChatDialog::messageClicked()
899{
900 this->showMaximized();
901}
902
903void
904ChatDialog::createActions()
905{
906 minimizeAction = new QAction(tr("Mi&nimize"), this);
907 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
908
909 maximizeAction = new QAction(tr("Ma&ximize"), this);
910 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
911
912 restoreAction = new QAction(tr("&Restore"), this);
913 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
914
915 quitAction = new QAction(tr("Quit"), this);
916 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
917}
918
919void
920ChatDialog::createTrayIcon()
921{
922 trayIconMenu = new QMenu(this);
923 trayIconMenu->addAction(minimizeAction);
924 trayIconMenu->addAction(maximizeAction);
925 trayIconMenu->addAction(restoreAction);
926 trayIconMenu->addSeparator();
927 trayIconMenu->addAction(quitAction);
928
929 trayIcon = new QSystemTrayIcon(this);
930 trayIcon->setContextMenu(trayIconMenu);
931
932 QIcon icon(":/images/icon_small.png");
933 trayIcon->setIcon(icon);
934 setWindowIcon(icon);
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700935 trayIcon->setToolTip("Chronos System Tray Icon");
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700936 trayIcon->setVisible(true);
937}
938
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700939void
940ChatDialog::resizeEvent(QResizeEvent *e)
941{
942 fitView();
943}
944
945void
946ChatDialog::showEvent(QShowEvent *e)
947{
948 fitView();
949}
950
951void
952ChatDialog::fitView()
953{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700954 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700955 QRectF rect = m_scene->itemsBoundingRect();
956 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700957 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700958}