blob: 26226d90699c731e7630ae19ad34ab924b8d53f5 [file] [log] [blame]
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -07001#include <QtGui>
2#include "chatdialog.h"
Zhenkai Zhu85845d22012-06-01 23:10:43 -07003#include "settingdialog.h"
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -07004#include <ctime>
Zhenkai Zhub6338822012-05-31 13:27:24 -07005#include <iostream>
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -07006#include <QTimer>
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -07007#include <QMetaType>
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -07008#include <QMessageBox>
Zhenkai Zhu59245aa2012-09-26 16:07:04 -07009#include <boost/random/random_device.hpp>
10#include <boost/random/uniform_int_distribution.hpp>
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070011
Zhenkai Zhu82a62752012-06-04 17:11:04 -070012#define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/sync-demo"
13
Zhenkai Zhu21d75f92012-06-04 21:23:34 -070014void
15ChatDialog::testDraw()
16{
17 std::string prefix[5] = {"/ndn/1", "/ndn/2", "/ndn/3", "/ndn/4", "/ndn/5"};
18 std::string nick[5] = {"tom", "jerry", "jason", "michael", "hurry"};
19 std::vector<Sync::MissingDataInfo> v;
20 for (int i = 0; i < 5; i++)
21 {
22 Sync::MissingDataInfo mdi = {prefix[i], Sync::SeqNo(0), Sync::SeqNo(i * (2 << i) )};
23 v.push_back(mdi);
24 }
25
26 m_scene->processUpdate(v, "12341234@!#%!@");
27
28 for (int i = 0; i < 5; i++)
29 {
30 m_scene-> msgReceived(prefix[i].c_str(), nick[i].c_str());
31 }
32
33 fitView();
34}
35
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070036ChatDialog::ChatDialog(QWidget *parent)
Zhenkai Zhu82a62752012-06-04 17:11:04 -070037 : QDialog(parent), m_sock(NULL)
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070038{
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -070039 // have to register this, otherwise
40 // the signal-slot system won't recognize this type
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -070041 qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
42 qRegisterMetaType<size_t>("size_t");
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070043 setupUi(this);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070044 m_session = time(NULL);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070045
46 readSettings();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070047
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070048 updateLabels();
49
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070050 lineEdit->setFocusPolicy(Qt::StrongFocus);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070051 m_scene = new DigestTreeScene(this);
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070052
Zhenkai Zhu82a62752012-06-04 17:11:04 -070053 treeViewer->setScene(m_scene);
54 m_scene->plot("Empty");
55 QRectF rect = m_scene->itemsBoundingRect();
56 m_scene->setSceneRect(rect);
57
58 // create sync socket
59 if(!m_user.getChatroom().isEmpty()) {
60 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
61 syncPrefix += "/";
62 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070063 try
64 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -070065 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
66 sendHello();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070067 }
68 catch (Sync::CcnxOperationException ex)
69 {
70 QMessageBox::critical(this, tr("Sync-Demo"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
71 std::exit(1);
72 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -070073 }
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070074
75 createActions();
76 createTrayIcon();
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070077 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
Zhenkai Zhu85845d22012-06-01 23:10:43 -070078 connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -070079 connect(this, SIGNAL(dataReceived(QString, const char *, size_t)), this, SLOT(processData(QString, const char *, size_t)));
80 connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -070081 connect(this, SIGNAL(removeReceived(QString)), this, SLOT(processRemove(QString)));
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070082 connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showNormal()));
83 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
84
85//testDraw();
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070086}
87
Zhenkai Zhu82a62752012-06-04 17:11:04 -070088ChatDialog::~ChatDialog()
89{
90 if (m_sock != NULL)
91 {
Zhenkai Zhu591e8c32012-09-26 11:57:50 -070092 m_sock->remove(m_user.getPrefix().toStdString());
Zhenkai Zhu82a62752012-06-04 17:11:04 -070093 delete m_sock;
94 m_sock = NULL;
95 }
96}
97
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070098void
99ChatDialog::setVisible(bool visible)
100{
101 minimizeAction->setEnabled(visible);
102 maximizeAction->setEnabled(!isMaximized());
103 restoreAction->setEnabled(isMaximized() || !visible);
104 QDialog::setVisible(visible);
105}
106
107void
108ChatDialog::closeEvent(QCloseEvent *e)
109{
110 if (trayIcon->isVisible())
111 {
112 QMessageBox::information(this, tr("Sync-Demo"),
113 tr("The program will keep running in the "
114 "system tray. To terminate the program"
115 "choose <b>Quit</b> in the context memu"
116 "of the system tray entry."));
117 hide();
118 e->ignore();
119 }
120}
121
122void
123ChatDialog::changeEvent(QEvent *e)
124{
125 switch(e->type())
126 {
127 case QEvent::ActivationChange:
128 if (isActiveWindow())
129 {
130 trayIcon->setIcon(QIcon(":/images/icon_small.png"));
131 }
132 break;
133 default:
134 break;
135 }
136}
137
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700138void
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700139ChatDialog::appendMessage(const SyncDemo::ChatMessage msg)
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700140{
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700141 boost::mutex::scoped_lock lock(m_msgMutex);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700142
143 if (msg.type() != SyncDemo::ChatMessage::CHAT) {
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700144 return;
Zhenkai Zhub6338822012-05-31 13:27:24 -0700145 }
146
147 if (!msg.has_data()) {
148 return;
149 }
150
151 if (msg.from().empty() || msg.data().empty()) {
152 return;
153 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700154
155 QTextCursor cursor(textEdit->textCursor());
156 cursor.movePosition(QTextCursor::End);
157 QTextTableFormat tableFormat;
158 tableFormat.setBorder(0);
159 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700160 QString from = QString("<%1>: ").arg(msg.from().c_str());
161 table->cellAt(0, 0).firstCursorPosition().insertText(from);
162 table->cellAt(0, 1).firstCursorPosition().insertText(msg.data().c_str());
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700163 QScrollBar *bar = textEdit->verticalScrollBar();
164 bar->setValue(bar->maximum());
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700165 showMessage(from, msg.data().c_str());
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700166}
167
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700168void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700169ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
170{
171 emit treeUpdated(v);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700172#ifdef __DEBUG
173 std::cout << "<<< Tree update signal emitted" << std::endl;
174#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700175}
176
177void
178ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700179{
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700180#ifdef __DEBUG
181 std::cout << "<<< processing Tree Update" << std::endl;
182#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700183 if (v.empty())
184 {
185 return;
186 }
187
188 // reflect the changes on digest tree
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700189 {
190 boost::mutex::scoped_lock lock(m_sceneMutex);
191 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
192 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700193
194 int n = v.size();
195 int totalMissingPackets = 0;
196 for (int i = 0; i < n; i++)
197 {
198 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
199 }
200
201 if (totalMissingPackets < 10) {
202 for (int i = 0; i < n; i++)
203 {
204 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
205 {
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700206 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700207#ifdef __DEBUG
208 std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
209#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700210 }
211 }
212 }
213 else
214 {
215 // too bad; too many missing packets
216 // we may just join a new chatroom
217 // or some network patition just healed
218 // we don't try to fetch any data in this case (for now)
219 }
220
221 // adjust the view
222 fitView();
223
224}
225
226void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700227ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
228{
229 emit dataReceived(name.c_str(), buf, len);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700230#ifdef __DEBUG
231 std::cout <<"<<< " << name << " fetched" << std::endl;
232#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700233}
234
235void
236ChatDialog::processData(QString name, const char *buf, size_t len)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700237{
238 SyncDemo::ChatMessage msg;
239 if (!msg.ParseFromArray(buf, len))
240 {
241 std::cerr << "Errrrr.. Can not parse msg at "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
242 abort();
243 }
244
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700245 // display msg received from network
246 // we have to do so; this function is called by ccnd thread
247 // so if we call appendMsg directly
248 // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
249 // the "cannonical" way to is use signal-slot
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700250 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700251
252 // update the tree view
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700253 std::string stdStrName = name.toStdString();
254 std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
255 std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
256#ifdef __DEBUG
257 std::cout <<"<<< updating scene for" << prefix << ": " << msg.from() << std::endl;
258#endif
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700259 {
260 boost::mutex::scoped_lock lock(m_sceneMutex);
261 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
262 }
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700263 fitView();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700264}
265
266void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700267ChatDialog::processRemoveWrapper(std::string prefix)
268{
269 emit removeReceived(prefix.c_str());
270}
271
272void
273ChatDialog::processRemove(QString prefix)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700274{
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700275#ifdef __DEBUG
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700276 std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700277#endif
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700278 bool removed = m_scene->removeNode(prefix);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700279 if (removed)
280 {
281 m_scene->plot(m_sock->getRootDigest().c_str());
282 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700283}
284
285void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700286ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700287 msg.set_from(m_user.getNick().toStdString());
288 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700289 msg.set_data(text.toStdString());
290 time_t seconds = time(NULL);
291 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700292 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700293}
294
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700295void
296ChatDialog::formHelloMessage(SyncDemo::ChatMessage &msg)
297{
298 msg.set_from(m_user.getNick().toStdString());
299 msg.set_to(m_user.getChatroom().toStdString());
300 time_t seconds = time(NULL);
301 msg.set_timestamp(seconds);
302 msg.set_type(SyncDemo::ChatMessage::HELLO);
303}
304
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700305static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
306
307QString
308ChatDialog::getRandomString()
309{
310 std::string randStr;
311 boost::random::random_device rng;
312 boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
313 for (int i = 0; i < 10; i ++)
314 {
315 randStr += chars[index_dist(rng)];
316 }
317 return randStr.c_str();
318}
319
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700320bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700321ChatDialog::readSettings()
322{
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700323#ifndef __DEBUG
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700324 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700325 QString nick = s.value("nick", "").toString();
326 QString chatroom = s.value("chatroom", "").toString();
327 QString prefix = s.value("prefix", "").toString();
328 if (nick == "" || chatroom == "" || prefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700329 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700330 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700331 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700332 else {
333 m_user.setNick(nick);
334 m_user.setChatroom(chatroom);
335 m_user.setPrefix(prefix);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700336 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700337 }
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700338#else
339 QTimer::singleShot(500, this, SLOT(buttonPressed()));
340 return false;
341#endif
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700342}
343
344void
345ChatDialog::writeSettings()
346{
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700347#ifndef __DEBUG
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700348 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700349 s.setValue("nick", m_user.getNick());
350 s.setValue("chatroom", m_user.getChatroom());
351 s.setValue("prefix", m_user.getPrefix());
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700352#endif
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700353}
354
355void
356ChatDialog::updateLabels()
357{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700358 QString settingDisp = QString("<User: %1>, <Chatroom: %2>").arg(m_user.getNick()).arg(m_user.getChatroom());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700359 infoLabel->setText(settingDisp);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700360 QString prefixDisp = QString("<Prefix: %1>").arg(m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700361 prefixLabel->setText(prefixDisp);
362}
363
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700364void
365ChatDialog::returnPressed()
366{
367 QString text = lineEdit->text();
368 if (text.isEmpty())
369 return;
370
Zhenkai Zhub6338822012-05-31 13:27:24 -0700371 lineEdit->clear();
372
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700373 SyncDemo::ChatMessage msg;
374 formChatMessage(text, msg);
375
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700376 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700377
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700378 sendMsg(msg);
379
380 fitView();
381}
382
383void
384ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
385{
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700386 // send msg
387 size_t size = msg.ByteSize();
388 char *buf = new char[size];
389 msg.SerializeToArray(buf, size);
390 if (!msg.IsInitialized())
391 {
392 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
393 abort();
394 }
395 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, 60);
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700396
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700397 delete buf;
398
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700399 int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700400 Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700401 std::vector<Sync::MissingDataInfo> v;
402 v.push_back(mdi);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700403 {
404 boost::mutex::scoped_lock lock(m_sceneMutex);
405 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
406 m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
407 }
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700408}
409
410void
411ChatDialog::sendHello()
412{
413 SyncDemo::ChatMessage msg;
414 formHelloMessage(msg);
415 sendMsg(msg);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700416}
417
418void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700419ChatDialog::buttonPressed()
420{
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700421 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700422 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700423 dialog.exec();
Zhenkai Zhue837f792012-06-05 20:47:54 -0700424 QTimer::singleShot(100, this, SLOT(checkSetting()));
425}
426
427void
428ChatDialog::checkSetting()
429{
430 if (m_user.getPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
431 {
432 buttonPressed();
433 }
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700434}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700435
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700436void
437ChatDialog::settingUpdated(QString nick, QString chatroom, QString prefix)
438{
439 bool needWrite = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700440 if (!nick.isEmpty() && nick != m_user.getNick()) {
441 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700442 needWrite = true;
443 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700444 if (!prefix.isEmpty() && prefix != m_user.getPrefix()) {
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700445 m_user.setPrefix(prefix + "/" + getRandomString());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700446 needWrite = true;
447 // TODO: set the previous prefix as left?
448 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700449 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
450 m_user.setChatroom(chatroom);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700451 needWrite = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700452
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700453 {
454 boost::mutex::scoped_lock lock(m_sceneMutex);
455 m_scene->clearAll();
456 m_scene->plot("Empty");
457 }
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700458 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700459 if (m_sock != NULL)
460 {
461 delete m_sock;
462 m_sock = NULL;
463 }
464 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
465 syncPrefix += "/";
466 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700467 try
468 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700469 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
470 sendHello();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700471 }
472 catch (Sync::CcnxOperationException ex)
473 {
474 QMessageBox::critical(this, tr("Sync-Demo"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
475 std::exit(1);
476 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700477
478 fitView();
479
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700480 }
481 if (needWrite) {
482 writeSettings();
483 updateLabels();
484 }
485}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700486
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700487void
488ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
489{
490 switch (reason)
491 {
492 case QSystemTrayIcon::Trigger:
493 case QSystemTrayIcon::DoubleClick:
494 break;
495 case QSystemTrayIcon::MiddleClick:
496 // showMessage();
497 break;
498 default:;
499 }
500}
501
502void
503ChatDialog::showMessage(QString from, QString data)
504{
505 // std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
506 if (!isActiveWindow())
507 {
508 trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
509 trayIcon->setIcon(QIcon(":/images/note.png"));
510 }
511}
512
513void
514ChatDialog::messageClicked()
515{
516 this->showMaximized();
517}
518
519void
520ChatDialog::createActions()
521{
522 minimizeAction = new QAction(tr("Mi&nimize"), this);
523 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
524
525 maximizeAction = new QAction(tr("Ma&ximize"), this);
526 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
527
528 restoreAction = new QAction(tr("&Restore"), this);
529 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
530
531 quitAction = new QAction(tr("Quit"), this);
532 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
533}
534
535void
536ChatDialog::createTrayIcon()
537{
538 trayIconMenu = new QMenu(this);
539 trayIconMenu->addAction(minimizeAction);
540 trayIconMenu->addAction(maximizeAction);
541 trayIconMenu->addAction(restoreAction);
542 trayIconMenu->addSeparator();
543 trayIconMenu->addAction(quitAction);
544
545 trayIcon = new QSystemTrayIcon(this);
546 trayIcon->setContextMenu(trayIconMenu);
547
548 QIcon icon(":/images/icon_small.png");
549 trayIcon->setIcon(icon);
550 setWindowIcon(icon);
551 trayIcon->setToolTip("Sync-Demo System Tray Icon");
552 trayIcon->setVisible(true);
553}
554
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700555void
556ChatDialog::resizeEvent(QResizeEvent *e)
557{
558 fitView();
559}
560
561void
562ChatDialog::showEvent(QShowEvent *e)
563{
564 fitView();
565}
566
567void
568ChatDialog::fitView()
569{
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700570 boost::mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700571 QRectF rect = m_scene->itemsBoundingRect();
572 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700573 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700574}