blob: d7da61cbf16bc77ad496c9dfa0b72101f6a851e7 [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 Zhu6bda0bd2012-10-06 23:50:39 -070011#include <stdio.h>
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070012
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -070013#define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/chronos"
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -070014#define LOCAL_PREFIX_QUERY "/local/ndn/prefix"
15#define DEFAULT_LOCAL_PREFIX "/private/local"
16#define CCN_EXEC "ccncat"
Zhenkai Zhu82a62752012-06-04 17:11:04 -070017
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -070018static const int HELLO_INTERVAL = 90; // seconds
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -070019
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070020ChatDialog::ChatDialog(QWidget *parent)
Zhenkai Zhu25e33e52012-09-28 13:00:07 -070021 : QDialog(parent), m_sock(NULL), m_lastMsgTime(0)
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070022{
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -070023 // have to register this, otherwise
24 // the signal-slot system won't recognize this type
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -070025 qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
26 qRegisterMetaType<size_t>("size_t");
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070027 setupUi(this);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070028 m_session = time(NULL);
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -070029 boost::random::random_device rng;
30 boost::random::uniform_int_distribution<> uniform(1, 29000);
31 m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070032
33 readSettings();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070034
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -070035 updateLabels();
36
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -070037 lineEdit->setFocusPolicy(Qt::StrongFocus);
Zhenkai Zhu82a62752012-06-04 17:11:04 -070038 m_scene = new DigestTreeScene(this);
Zhenkai Zhub45e38a2012-06-01 15:44:36 -070039
Zhenkai Zhu82a62752012-06-04 17:11:04 -070040 treeViewer->setScene(m_scene);
41 m_scene->plot("Empty");
42 QRectF rect = m_scene->itemsBoundingRect();
43 m_scene->setSceneRect(rect);
44
Zhenkai Zhu9036e032012-09-27 20:59:33 -070045 listView->setStyleSheet("QListView { alternate-background-color: white; background: #F0F0F0; color: darkGreen; font: bold large; }");
Zhenkai Zhuf55f4382012-09-28 10:58:54 -070046 listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
47 listView->setDragDropMode(QAbstractItemView::NoDragDrop);
48 listView->setSelectionMode(QAbstractItemView::NoSelection);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -070049 m_rosterModel = new QStringListModel(this);
50 listView->setModel(m_rosterModel);
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 Zhu86df7412012-09-27 16:30:20 -070058 connect(this, SIGNAL(dataReceived(QString, const char *, size_t, bool)), this, SLOT(processData(QString, const char *, size_t, bool)));
59 connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070060 connect(m_timer, SIGNAL(timeout()), this, SLOT(replot()));
61 connect(m_scene, SIGNAL(replot()), this, SLOT(replot()));
62 connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showNormal()));
63 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
Zhenkai Zhu25e33e52012-09-28 13:00:07 -070064 connect(m_scene, SIGNAL(rosterChanged(QStringList)), this, SLOT(updateRosterList(QStringList)));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070065
Zhenkai Zhu82a62752012-06-04 17:11:04 -070066 // create sync socket
67 if(!m_user.getChatroom().isEmpty()) {
68 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
69 syncPrefix += "/";
70 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070071 try
72 {
Alexander Afanasyev288edd82012-10-04 17:07:56 -070073 m_sock = new Sync::SyncAppSocket(syncPrefix,
74 bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
75 bind(&ChatDialog::processRemoveWrapper, this, _1));
Zhenkai Zhucf024442012-10-05 10:33:08 -070076 QTimer::singleShot(600, this, SLOT(sendJoin()));
Zhenkai Zhu86df7412012-09-27 16:30:20 -070077 m_timer->start(FRESHNESS * 2000);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -070078 disableTreeDisplay();
79 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -070080 }
81 catch (Sync::CcnxOperationException ex)
82 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -070083 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 -070084 std::exit(1);
85 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -070086 }
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -070087
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -070088}
89
Zhenkai Zhu82a62752012-06-04 17:11:04 -070090ChatDialog::~ChatDialog()
91{
92 if (m_sock != NULL)
93 {
Zhenkai Zhucf024442012-10-05 10:33:08 -070094 sendLeave();
Zhenkai Zhu82a62752012-06-04 17:11:04 -070095 delete m_sock;
96 m_sock = NULL;
97 }
98}
99
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700100void
Zhenkai Zhucf024442012-10-05 10:33:08 -0700101ChatDialog::sendLeave()
102{
103 SyncDemo::ChatMessage msg;
104 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
105 sendMsg(msg);
106 usleep(500000);
107 m_sock->remove(m_user.getPrefix().toStdString());
108 usleep(5000);
109#ifdef __DEBUG
110 std::cout << "Sync REMOVE signal sent" << std::endl;
111#endif
112}
113
114void
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700115ChatDialog::replot()
116{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700117 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700118 m_scene->plot(m_sock->getRootDigest().c_str());
Zhenkai Zhuc9e4e3c2012-10-02 11:47:31 -0700119 fitView();
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700120}
121
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700122void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700123ChatDialog::updateRosterList(QStringList staleUserList)
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700124{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700125 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700126 QStringList rosterList = m_scene->getRosterList();
127 m_rosterModel->setStringList(rosterList);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700128 QString user;
129 QStringListIterator it(staleUserList);
130 while(it.hasNext())
131 {
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700132 std::string nick = it.next().toStdString();
133 if (nick.empty())
134 continue;
135
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700136 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700137 formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
Zhenkai Zhu32cbdce2012-10-02 11:09:38 -0700138 msg.set_from(nick);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700139 appendMessage(msg);
140 }
Zhenkai Zhu6082ede2012-09-27 17:28:46 -0700141}
142
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700143void
144ChatDialog::setVisible(bool visible)
145{
146 minimizeAction->setEnabled(visible);
147 maximizeAction->setEnabled(!isMaximized());
148 restoreAction->setEnabled(isMaximized() || !visible);
149 QDialog::setVisible(visible);
150}
151
152void
153ChatDialog::closeEvent(QCloseEvent *e)
154{
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700155 if (trayIcon->isVisible() && !m_minimaniho)
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700156 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700157 QMessageBox::information(this, tr("Chronos"),
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700158 tr("The program will keep running in the "
159 "system tray. To terminate the program"
160 "choose <b>Quit</b> in the context memu"
161 "of the system tray entry."));
162 hide();
163 e->ignore();
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700164 m_minimaniho = true;
165 writeSettings();
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700166 }
167}
168
169void
170ChatDialog::changeEvent(QEvent *e)
171{
172 switch(e->type())
173 {
174 case QEvent::ActivationChange:
175 if (isActiveWindow())
176 {
177 trayIcon->setIcon(QIcon(":/images/icon_small.png"));
178 }
179 break;
180 default:
181 break;
182 }
183}
184
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700185void
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700186ChatDialog::appendMessage(const SyncDemo::ChatMessage msg)
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700187{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700188 boost::recursive_mutex::scoped_lock lock(m_msgMutex);
Zhenkai Zhub6338822012-05-31 13:27:24 -0700189
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700190 if (msg.type() == SyncDemo::ChatMessage::CHAT)
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700191 {
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700192
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700193 if (!msg.has_data())
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700194 {
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700195 return;
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700196 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700197
198 if (msg.from().empty() || msg.data().empty())
199 {
200 return;
201 }
202
203 if (!msg.has_timestamp())
204 {
205 return;
206 }
207
208 QTextCharFormat nickFormat;
209 nickFormat.setForeground(Qt::darkGreen);
210 nickFormat.setFontWeight(QFont::Bold);
211 nickFormat.setFontUnderline(true);
212 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700213
214 QTextCursor cursor(textEdit->textCursor());
215 cursor.movePosition(QTextCursor::End);
216 QTextTableFormat tableFormat;
217 tableFormat.setBorder(0);
218 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
219 QString from = QString("%1 ").arg(msg.from().c_str());
220 QTextTableCell fromCell = table->cellAt(0, 0);
221 fromCell.setFormat(nickFormat);
222 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700223
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700224 time_t timestamp = msg.timestamp();
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700225 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700226
227 QTextCursor nextCursor(textEdit->textCursor());
228 nextCursor.movePosition(QTextCursor::End);
229 table = nextCursor.insertTable(1, 1, tableFormat);
230 table->cellAt(0, 0).firstCursorPosition().insertText(msg.data().c_str());
231 showMessage(from, msg.data().c_str());
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700232 }
233
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700234 if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE)
235 {
236 QTextCharFormat nickFormat;
237 nickFormat.setForeground(Qt::gray);
238 nickFormat.setFontWeight(QFont::Bold);
239 nickFormat.setFontUnderline(true);
240 nickFormat.setUnderlineColor(Qt::gray);
Zhenkai Zhub98e6022012-09-27 13:48:23 -0700241
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700242 QTextCursor cursor(textEdit->textCursor());
243 cursor.movePosition(QTextCursor::End);
244 QTextTableFormat tableFormat;
245 tableFormat.setBorder(0);
246 QTextTable *table = cursor.insertTable(1, 2, tableFormat);
247 QString action;
248 if (msg.type() == SyncDemo::ChatMessage::JOIN)
249 {
250 action = "enters room";
251 }
252 else
253 {
254 action = "leaves room";
255 }
256
257 QString from = QString("%1 %2 ").arg(msg.from().c_str()).arg(action);
258 QTextTableCell fromCell = table->cellAt(0, 0);
259 fromCell.setFormat(nickFormat);
260 fromCell.firstCursorPosition().insertText(from);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700261
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700262 time_t timestamp = msg.timestamp();
263 printTimeInCell(table, timestamp);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700264 }
265
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700266 QScrollBar *bar = textEdit->verticalScrollBar();
267 bar->setValue(bar->maximum());
268}
269
Zhenkai Zhu560ef1b2012-09-28 14:23:33 -0700270void
271ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
272{
273 QTextCharFormat timeFormat;
274 timeFormat.setForeground(Qt::gray);
275 timeFormat.setFontUnderline(true);
276 timeFormat.setUnderlineColor(Qt::gray);
277 QTextTableCell timeCell = table->cellAt(0, 1);
278 timeCell.setFormat(timeFormat);
279 timeCell.firstCursorPosition().insertText(formatTime(timestamp));
280}
281
282QString
283ChatDialog::formatTime(time_t timestamp)
284{
285 struct tm *tm_time = localtime(&timestamp);
286 int hour = tm_time->tm_hour;
287 QString amOrPM;
288 if (hour > 12)
289 {
290 hour -= 12;
291 amOrPM = "PM";
292 }
293 else
294 {
295 amOrPM = "AM";
296 if (hour == 0)
297 {
298 hour = 12;
299 }
300 }
301
302 char textTime[12];
303 sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
304 return QString(textTime);
305}
306
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700307void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700308ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
309{
310 emit treeUpdated(v);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700311#ifdef __DEBUG
312 std::cout << "<<< Tree update signal emitted" << std::endl;
313#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700314}
315
316void
317ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700318{
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700319#ifdef __DEBUG
320 std::cout << "<<< processing Tree Update" << std::endl;
321#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700322 if (v.empty())
323 {
324 return;
325 }
326
327 // reflect the changes on digest tree
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700328 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700329 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700330 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
331 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700332
333 int n = v.size();
334 int totalMissingPackets = 0;
335 for (int i = 0; i < n; i++)
336 {
337 totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
338 }
339
Zhenkai Zhubb198112012-09-27 11:31:42 -0700340 for (int i = 0; i < n; i++)
341 {
342 if (totalMissingPackets < 4)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700343 {
344 for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
345 {
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700346 m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700347#ifdef __DEBUG
348 std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
349#endif
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700350 }
351 }
Zhenkai Zhubb198112012-09-27 11:31:42 -0700352 else
353 {
354 m_sock->fetchRaw(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1, _2, _3), 2);
355 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700356 }
357
358 // adjust the view
359 fitView();
360
361}
362
363void
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700364ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
365{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700366 char *tempBuf = new char[len];
367 memcpy(tempBuf, buf, len);
368 emit dataReceived(name.c_str(), tempBuf, len, true);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700369#ifdef __DEBUG
370 std::cout <<"<<< " << name << " fetched" << std::endl;
371#endif
Zhenkai Zhu64f9ede2012-06-05 11:32:00 -0700372}
373
374void
Zhenkai Zhubb198112012-09-27 11:31:42 -0700375ChatDialog::processDataNoShowWrapper(std::string name, const char *buf, size_t len)
376{
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700377 char *tempBuf = new char[len];
378 memcpy(tempBuf, buf, len);
379 emit dataReceived(name.c_str(), tempBuf, len, false);
Zhenkai Zhubb198112012-09-27 11:31:42 -0700380}
381
382void
383ChatDialog::processData(QString name, const char *buf, size_t len, bool show)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700384{
385 SyncDemo::ChatMessage msg;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700386 bool corrupted = false;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700387 if (!msg.ParseFromArray(buf, len))
388 {
Zhenkai Zhubb198112012-09-27 11:31:42 -0700389 std::cerr << "Errrrr.. Can not parse msg with name: " << name.toStdString() << ". what is happening?" << std::endl;
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700390 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
391 msg.set_from("inconnu");
392 msg.set_type(SyncDemo::ChatMessage::OTHER);
393 corrupted = true;
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700394 }
395
Zhenkai Zhuae29f5a2012-10-05 17:28:04 -0700396 delete [] buf;
397 buf = NULL;
398
Zhenkai Zhu10ccb5a2012-06-04 21:55:14 -0700399 // display msg received from network
400 // we have to do so; this function is called by ccnd thread
401 // so if we call appendMsg directly
402 // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
403 // the "cannonical" way to is use signal-slot
Zhenkai Zhuef8d0632012-10-05 10:24:55 -0700404 if (show && !corrupted)
Zhenkai Zhubb198112012-09-27 11:31:42 -0700405 {
406 appendMessage(msg);
407 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700408
409 // update the tree view
Zhenkai Zhu097bfe72012-06-05 14:30:17 -0700410 std::string stdStrName = name.toStdString();
411 std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
412 std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
413#ifdef __DEBUG
414 std::cout <<"<<< updating scene for" << prefix << ": " << msg.from() << std::endl;
415#endif
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700416 if (msg.type() == SyncDemo::ChatMessage::LEAVE)
417 {
418 processRemove(prefix.c_str());
419 }
420 else
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700421 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700422 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700423 m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
424 }
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700425 fitView();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700426}
427
428void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700429ChatDialog::processRemoveWrapper(std::string prefix)
430{
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700431#ifdef __DEBUG
432 std::cout << "Sync REMOVE signal received for prefix: " << prefix << std::endl;
433#endif
434 //emit removeReceived(prefix.c_str());
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700435}
436
437void
438ChatDialog::processRemove(QString prefix)
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700439{
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700440#ifdef __DEBUG
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700441 std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700442#endif
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700443 bool removed = m_scene->removeNode(prefix);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700444 if (removed)
445 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700446 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu591e8c32012-09-26 11:57:50 -0700447 m_scene->plot(m_sock->getRootDigest().c_str());
448 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700449}
450
451void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700452ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700453 msg.set_from(m_user.getNick().toStdString());
454 msg.set_to(m_user.getChatroom().toStdString());
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700455 msg.set_data(text.toStdString());
456 time_t seconds = time(NULL);
457 msg.set_timestamp(seconds);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700458 msg.set_type(SyncDemo::ChatMessage::CHAT);
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700459}
460
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700461void
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700462ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700463{
464 msg.set_from(m_user.getNick().toStdString());
465 msg.set_to(m_user.getChatroom().toStdString());
466 time_t seconds = time(NULL);
467 msg.set_timestamp(seconds);
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700468 msg.set_type(type);
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700469}
470
Zhenkai Zhu59245aa2012-09-26 16:07:04 -0700471static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
472
473QString
474ChatDialog::getRandomString()
475{
476 std::string randStr;
477 boost::random::random_device rng;
478 boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
479 for (int i = 0; i < 10; i ++)
480 {
481 randStr += chars[index_dist(rng)];
482 }
483 return randStr.c_str();
484}
485
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700486QString
487ChatDialog::getLocalPrefix()
488{
489 std::string cmd = CCN_EXEC;
490 cmd += " ";
491 cmd += LOCAL_PREFIX_QUERY;
492 QString localPrefix;
493#define MAX_PREFIX_LEN 100
494 FILE *fp = popen(cmd.c_str(), "r");
495 if (fp != NULL)
496 {
497 char prefix[MAX_PREFIX_LEN];
498 if (fgets(prefix, MAX_PREFIX_LEN, fp) != NULL)
499 {
500 localPrefix = prefix;
501 localPrefix.remove('\n');
502 }
503 else
504 {
505 localPrefix = DEFAULT_LOCAL_PREFIX;
506 }
507 pclose(fp);
508 }
509 else
510 {
511 localPrefix = DEFAULT_LOCAL_PREFIX;
512 }
513 return localPrefix;
514}
515
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700516bool
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700517ChatDialog::readSettings()
518{
519 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700520 QString nick = s.value("nick", "").toString();
521 QString chatroom = s.value("chatroom", "").toString();
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700522 //QString originPrefix = s.value("originPrefix", "").toString();
523 QString originPrefix = getLocalPrefix();
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700524 m_minimaniho = s.value("minimaniho", false).toBool();
525 if (nick == "" || chatroom == "" || originPrefix == "") {
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700526 QTimer::singleShot(500, this, SLOT(buttonPressed()));
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700527 return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700528 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700529 else {
530 m_user.setNick(nick);
531 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700532 m_user.setOriginPrefix(originPrefix);
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700533 m_user.setPrefix(originPrefix + "/" + chatroom + "/" + getRandomString());
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700534 return true;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700535 }
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700536
537// QTimer::singleShot(500, this, SLOT(buttonPressed()));
538 // return false;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700539}
540
541void
542ChatDialog::writeSettings()
543{
544 QSettings s(ORGANIZATION, APPLICATION);
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700545 s.setValue("nick", m_user.getNick());
546 s.setValue("chatroom", m_user.getChatroom());
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700547 //s.setValue("originPrefix", m_user.getOriginPrefix());
Zhenkai Zhu3974a492012-09-28 14:39:45 -0700548 s.setValue("minimaniho", m_minimaniho);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700549}
550
551void
552ChatDialog::updateLabels()
553{
Zhenkai Zhu76ff02b2012-09-27 21:11:03 -0700554 QString settingDisp = QString("Chatroom: %1").arg(m_user.getChatroom());
555 infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700556 infoLabel->setText(settingDisp);
Zhenkai Zhu6bda0bd2012-10-06 23:50:39 -0700557 QString prefixDisp;
558 if (m_user.getPrefix().startsWith(DEFAULT_LOCAL_PREFIX))
559 {
560 prefixDisp = QString("<Warning: Auto config prefix failed.>\n <Prefix = %1>").arg(m_user.getPrefix());
561 prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
562 }
563 else
564 {
565 prefixDisp = QString("<Prefix = %1>").arg(m_user.getPrefix());
566 prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
567 }
568 prefixLabel->setText(prefixDisp);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700569}
570
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700571void
572ChatDialog::returnPressed()
573{
574 QString text = lineEdit->text();
575 if (text.isEmpty())
576 return;
577
Zhenkai Zhub6338822012-05-31 13:27:24 -0700578 lineEdit->clear();
579
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700580 SyncDemo::ChatMessage msg;
581 formChatMessage(text, msg);
582
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700583 appendMessage(msg);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700584
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700585 sendMsg(msg);
586
587 fitView();
588}
589
590void
591ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
592{
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700593 // send msg
594 size_t size = msg.ByteSize();
595 char *buf = new char[size];
596 msg.SerializeToArray(buf, size);
597 if (!msg.IsInitialized())
598 {
599 std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
600 abort();
601 }
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700602 m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700603
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700604 delete buf;
605
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700606 m_lastMsgTime = time(NULL);
607
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700608 int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
Zhenkai Zhud1c5a972012-06-05 14:07:41 -0700609 Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
Zhenkai Zhuc5470612012-06-05 12:28:59 -0700610 std::vector<Sync::MissingDataInfo> v;
611 v.push_back(mdi);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700612 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700613 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700614 m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
615 m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
616 }
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700617}
618
619void
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700620ChatDialog::sendJoin()
621{
622 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700623 formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700624 sendMsg(msg);
625 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
626}
627
628void
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700629ChatDialog::sendHello()
630{
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700631 time_t now = time(NULL);
632 int elapsed = now - m_lastMsgTime;
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700633 if (elapsed >= m_randomizedInterval / 1000)
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700634 {
635 SyncDemo::ChatMessage msg;
Zhenkai Zhub5b78462012-09-28 14:10:37 -0700636 formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700637 sendMsg(msg);
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700638 QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700639 }
640 else
641 {
Zhenkai Zhuee5c90f2012-09-27 14:05:41 -0700642 QTimer::singleShot((m_randomizedInterval - elapsed * 1000), this, SLOT(sendHello()));
Zhenkai Zhu3e26bb42012-09-27 11:04:09 -0700643 }
Zhenkai Zhu5a8d5aa2012-05-30 21:25:23 -0700644}
645
646void
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700647ChatDialog::buttonPressed()
648{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700649 SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getOriginPrefix());
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700650 connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
Zhenkai Zhu85845d22012-06-01 23:10:43 -0700651 dialog.exec();
Zhenkai Zhue837f792012-06-05 20:47:54 -0700652 QTimer::singleShot(100, this, SLOT(checkSetting()));
653}
654
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700655void ChatDialog::treeButtonPressed()
656{
657 if (treeViewer->isVisible())
658 {
659 treeViewer->hide();
660 treeButton->setText("Show Sync Tree");
661 }
662 else
663 {
664 treeViewer->show();
665 treeButton->setText("Hide Sync Tree");
666 }
Zhenkai Zhu25e33e52012-09-28 13:00:07 -0700667
668 fitView();
Zhenkai Zhub60b7e12012-09-28 11:34:21 -0700669}
670
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700671void ChatDialog::enableTreeDisplay()
672{
673 treeButton->setEnabled(true);
674 treeViewer->show();
675 fitView();
676}
677
678void ChatDialog::disableTreeDisplay()
679{
680 treeButton->setEnabled(false);
681 treeViewer->hide();
682 fitView();
683}
684
Zhenkai Zhue837f792012-06-05 20:47:54 -0700685void
686ChatDialog::checkSetting()
687{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700688 if (m_user.getOriginPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
Zhenkai Zhue837f792012-06-05 20:47:54 -0700689 {
690 buttonPressed();
691 }
Zhenkai Zhu6d589aa2012-05-29 17:34:35 -0700692}
Zhenkai Zhue08afe02012-05-31 15:49:07 -0700693
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700694void
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700695ChatDialog::settingUpdated(QString nick, QString chatroom, QString originPrefix)
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700696{
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700697 QString randString = getRandomString();
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700698 bool needWrite = false;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700699 bool needFresh = false;
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700700 if (!nick.isEmpty() && nick != m_user.getNick()) {
701 m_user.setNick(nick);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700702 needWrite = true;
703 }
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700704 if (!originPrefix.isEmpty() && originPrefix != m_user.getOriginPrefix()) {
705 m_user.setOriginPrefix(originPrefix);
706 m_user.setPrefix(originPrefix + "/" + m_user.getChatroom() + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700707 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700708 needFresh = true;
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700709 }
Zhenkai Zhu71b42cb2012-06-04 09:42:53 -0700710 if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
711 m_user.setChatroom(chatroom);
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700712 m_user.setPrefix(m_user.getOriginPrefix() + "/" + chatroom + "/" + randString);
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700713 needWrite = true;
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700714 needFresh = true;
715 }
716
717 if (needFresh)
718 {
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700719
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700720 {
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700721 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu44b43752012-06-05 21:18:37 -0700722 m_scene->clearAll();
723 m_scene->plot("Empty");
724 }
Zhenkai Zhucc4c2c02012-09-27 21:24:37 -0700725
726 textEdit->clear();
727
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700728 // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700729 if (m_sock != NULL)
730 {
Zhenkai Zhucf024442012-10-05 10:33:08 -0700731 sendLeave();
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700732 delete m_sock;
733 m_sock = NULL;
734 }
735 std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
736 syncPrefix += "/";
737 syncPrefix += m_user.getChatroom().toStdString();
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700738 try
739 {
Zhenkai Zhu2425b6a2012-09-26 17:11:44 -0700740 m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
Alexander Afanasyev288edd82012-10-04 17:07:56 -0700741 QTimer::singleShot(1000, this, SLOT(sendJoin()));
Zhenkai Zhu86df7412012-09-27 16:30:20 -0700742 m_timer->start(FRESHNESS * 2000);
Zhenkai Zhu0e7a9b22012-10-05 17:55:17 -0700743 disableTreeDisplay();
744 QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
Zhenkai Zhua4fb1242012-06-05 20:26:05 -0700745 }
746 catch (Sync::CcnxOperationException ex)
747 {
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700748 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 -0700749 std::exit(1);
750 }
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700751
752 fitView();
753
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700754 }
Zhenkai Zhue95c64a2012-09-27 21:46:44 -0700755
Zhenkai Zhu7e9b06d2012-06-02 00:44:42 -0700756 if (needWrite) {
757 writeSettings();
758 updateLabels();
759 }
760}
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700761
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700762void
763ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
764{
765 switch (reason)
766 {
767 case QSystemTrayIcon::Trigger:
768 case QSystemTrayIcon::DoubleClick:
769 break;
770 case QSystemTrayIcon::MiddleClick:
771 // showMessage();
772 break;
773 default:;
774 }
775}
776
777void
778ChatDialog::showMessage(QString from, QString data)
779{
780 // std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
781 if (!isActiveWindow())
782 {
783 trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
784 trayIcon->setIcon(QIcon(":/images/note.png"));
785 }
786}
787
788void
789ChatDialog::messageClicked()
790{
791 this->showMaximized();
792}
793
794void
795ChatDialog::createActions()
796{
797 minimizeAction = new QAction(tr("Mi&nimize"), this);
798 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
799
800 maximizeAction = new QAction(tr("Ma&ximize"), this);
801 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
802
803 restoreAction = new QAction(tr("&Restore"), this);
804 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
805
806 quitAction = new QAction(tr("Quit"), this);
807 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
808}
809
810void
811ChatDialog::createTrayIcon()
812{
813 trayIconMenu = new QMenu(this);
814 trayIconMenu->addAction(minimizeAction);
815 trayIconMenu->addAction(maximizeAction);
816 trayIconMenu->addAction(restoreAction);
817 trayIconMenu->addSeparator();
818 trayIconMenu->addAction(quitAction);
819
820 trayIcon = new QSystemTrayIcon(this);
821 trayIcon->setContextMenu(trayIconMenu);
822
823 QIcon icon(":/images/icon_small.png");
824 trayIcon->setIcon(icon);
825 setWindowIcon(icon);
Zhenkai Zhu0b3fa332012-09-27 21:58:43 -0700826 trayIcon->setToolTip("Chronos System Tray Icon");
Zhenkai Zhu3a008fc2012-06-08 17:36:39 -0700827 trayIcon->setVisible(true);
828}
829
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700830void
831ChatDialog::resizeEvent(QResizeEvent *e)
832{
833 fitView();
834}
835
836void
837ChatDialog::showEvent(QShowEvent *e)
838{
839 fitView();
840}
841
842void
843ChatDialog::fitView()
844{
Zhenkai Zhu9036e032012-09-27 20:59:33 -0700845 boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
Zhenkai Zhu21d75f92012-06-04 21:23:34 -0700846 QRectF rect = m_scene->itemsBoundingRect();
847 m_scene->setSceneRect(rect);
Zhenkai Zhu82a62752012-06-04 17:11:04 -0700848 treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
Zhenkai Zhud13acd02012-06-04 15:25:20 -0700849}