root/trunk/qt4-gui/src/userevents/userviewevent.cpp

Revision 6472, 24.6 kB (checked in by flynd, 4 months ago)

Increased size hint for event view dialog so authorization requests are fully visable by default.

Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of Licq, an instant messaging client for UNIX.
4 * Copyright (C) 2000-2006 Licq developers
5 *
6 * Licq is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Licq is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Licq; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 */
20
21#include "userviewevent.h"
22
23#include "config.h"
24
25#include <QAction>
26#include <QApplication>
27#include <QCheckBox>
28#include <QDesktopWidget>
29#include <QFile>
30#include <QGroupBox>
31#include <QPushButton>
32#include <QShortcut>
33#include <QSplitter>
34#include <QTextCodec>
35#include <QTreeWidgetItem>
36#include <QVBoxLayout>
37
38#ifdef USE_KDE
39#include <KDE/KToolInvocation>
40#endif
41
42#include <licq_events.h>
43#include <licq_icqd.h>
44#include <licq_message.h>
45
46#include "config/chat.h"
47#include "config/iconmanager.h"
48
49#include "core/gui-defines.h"
50#include "core/licqgui.h"
51#include "core/messagebox.h"
52#include "core/signalmanager.h"
53
54#include "dialogs/adduserdlg.h"
55#include "dialogs/authuserdlg.h"
56#include "dialogs/chatdlg.h"
57#include "dialogs/filedlg.h"
58#include "dialogs/forwarddlg.h"
59#include "dialogs/joinchatdlg.h"
60#include "dialogs/refusedlg.h"
61
62#include "widgets/messagelist.h"
63#include "widgets/mlview.h"
64#include "widgets/skinnablebutton.h"
65
66#include "usersendmsgevent.h"
67
68using namespace LicqQtGui;
69/* TRANSLATOR LicqQtGui::UserViewEvent */
70
71UserViewEvent::UserViewEvent(QString id, unsigned long ppid, QWidget* parent)
72  : UserEventCommon(id, ppid, parent, "UserViewEvent")
73{
74  myReadSplitter = new QSplitter(Qt::Vertical);
75  myReadSplitter->setOpaqueResize();
76  myMainWidget->addWidget(myReadSplitter);
77
78  QShortcut* a = new QShortcut(Qt::Key_Escape, this);
79  connect(a, SIGNAL(activated()), SLOT(closeDialog()));
80
81  myMessageList = new MessageList();
82  myReadSplitter->addWidget(myMessageList);
83
84  myMessageView = new MLView();
85  myMessageView->setSizeHintLines(8);
86  myReadSplitter->addWidget(myMessageView);
87
88  myReadSplitter->setStretchFactor(0, 0);
89  myReadSplitter->setStretchFactor(1, 1);
90
91  connect(myMessageList, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
92      SLOT(printMessage(QTreeWidgetItem*)));
93  connect(LicqGui::instance(), SIGNAL(eventSent(const ICQEvent*)),
94      SLOT(sentEvent(const ICQEvent*)));
95
96  myActionsBox = new QGroupBox();
97  myMainWidget->addSpacing(10);
98  myMainWidget->addWidget(myActionsBox);
99
100  QHBoxLayout* h_action_lay = new QHBoxLayout(myActionsBox);
101
102  myRead1Button = new QPushButton();
103  myRead2Button = new QPushButton();
104  myRead3Button = new QPushButton();
105  myRead4Button = new QPushButton();
106
107  myRead1Button->setEnabled(false);
108  myRead2Button->setEnabled(false);
109  myRead3Button->setEnabled(false);
110  myRead4Button->setEnabled(false);
111
112  connect(myRead1Button, SIGNAL(clicked()), SLOT(read1()));
113  connect(myRead2Button, SIGNAL(clicked()), SLOT(read2()));
114  connect(myRead3Button, SIGNAL(clicked()), SLOT(read3()));
115  connect(myRead4Button, SIGNAL(clicked()), SLOT(read4()));
116
117  h_action_lay->addWidget(myRead1Button);
118  h_action_lay->addWidget(myRead2Button);
119  h_action_lay->addWidget(myRead3Button);
120  h_action_lay->addWidget(myRead4Button);
121
122  QHBoxLayout* h_lay = new QHBoxLayout();
123  myTopLayout->addLayout(h_lay);
124
125  if (!myIsOwner)
126  {
127    myAutoCloseCheck = new QCheckBox(tr("Aut&o Close"));
128    myAutoCloseCheck->setChecked(Config::Chat::instance()->autoClose());
129    h_lay->addWidget(myAutoCloseCheck);
130  }
131
132  h_lay->addStretch(1);
133
134  myReadNextButton = new QPushButton(tr("Nex&t"));
135  myReadNextButton->setEnabled(false);
136  connect(myReadNextButton, SIGNAL(clicked()), SLOT(readNext()));
137  h_lay->addWidget(myReadNextButton);
138  setTabOrder(myRead4Button, myReadNextButton);
139
140  myCloseButton = new SkinnableButton(tr("&Close"));
141  myCloseButton->setToolTip(tr("Normal Click - Close Window\n<CTRL>+Click - also delete User"));
142  connect(myCloseButton, SIGNAL(clicked()), SLOT(closeDialog()));
143  h_lay->addWidget(myCloseButton);
144  setTabOrder(myReadNextButton, myCloseButton);
145
146  const ICQUser* u = gUserManager.FetchUser(myUsers.front().c_str(), myPpid, LOCK_R);
147  if (u != NULL && u->NewMessages() > 0)
148  {
149    unsigned short i = 0;
150    // Create an item for the message we're currently viewing.
151    if (Config::Chat::instance()->msgChatView())
152    {
153      for (i = 0; i < u->NewMessages(); i++)
154        if (u->EventPeek(i)->SubCommand() != ICQ_CMDxSUB_MSG &&
155            u->EventPeek(i)->SubCommand() != ICQ_CMDxSUB_URL)
156          break;
157      if (i == u->NewMessages())
158        i = 0;
159    }
160
161    MessageListItem* e = new MessageListItem(u->EventPeek(i), myCodec, myMessageList);
162    myHighestEventId = u->EventPeek(i)->Id();
163
164    /* Create items for all the messages which already await
165     * in the queue. We cannot rely on getting CICQSignals for them
166     * since they might've arrived before the dialog appeared,
167     * possibly being undisplayed messages from previous licq session.
168     */
169    for (i++; i < u->NewMessages(); i++)
170    {
171      const CUserEvent* event = u->EventPeek(i);
172      if (!Config::Chat::instance()->msgChatView() ||
173          (event->SubCommand() != ICQ_CMDxSUB_MSG &&
174           event->SubCommand() != ICQ_CMDxSUB_URL))
175      {
176        new MessageListItem(event, myCodec, myMessageList);
177        // Make sure we don't add this message again,
178        // even if we receive an userUpdated signal for it.
179        if (myHighestEventId < event->Id())
180          myHighestEventId = event->Id();
181      }
182    }
183
184    gUserManager.DropUser(u);
185    for (unsigned short i = 0; i < myMessageList->columnCount(); i++)
186      myMessageList->resizeColumnToContents(i);
187    myMessageList->setCurrentItem(e, 0);
188    myMessageList->scrollToItem(e);
189    printMessage(e);
190  }
191  else
192    if (u != NULL)
193      gUserManager.DropUser(u);
194
195  connect(this, SIGNAL(encodingChanged()), SLOT(setEncoding()));
196}
197
198UserViewEvent::~UserViewEvent()
199{
200  // Empty
201}
202
203void UserViewEvent::generateReply()
204{
205  QString s = QString("> ");
206
207  if (!myMessageView->markedText().trimmed().isEmpty())
208    s += myMessageView->markedText().trimmed();
209  else
210    if (!myMessageView->toPlainText().trimmed().isEmpty())
211      s += myMessageView->toPlainText().trimmed();
212    else
213      s = QString::null;
214
215  s.replace("\n", "\n> ");
216  s = s.trimmed();
217  if (!s.isEmpty())
218    s += "\n\n";
219
220  sendMsg(s);
221}
222
223void UserViewEvent::sendMsg(QString text)
224{
225  UserSendMsgEvent* e = new UserSendMsgEvent(myUsers.front().c_str(), myPpid);
226
227  e->setText(text);
228
229  // Find a good position for the new window
230  if (Config::Chat::instance()->autoPosReplyWin())
231  {
232    int yp = myRead1Button->parentWidget()->mapToGlobal(QPoint(0, 0)).y();
233    if (yp + e->height() + 8 > QApplication::desktop()->height())
234      yp = QApplication::desktop()->height() - e->height() - 8;
235    e->move(x(), yp);
236  }
237
238  QTimer::singleShot(10, e, SLOT(show()));
239
240  connect(e, SIGNAL(autoCloseNotify()), SLOT(autoClose()));
241  connect(e, SIGNAL(msgTypeChanged(UserSendCommon*, UserSendCommon*)),
242      SLOT(msgTypeChanged(UserSendCommon*, UserSendCommon*)));
243}
244
245void UserViewEvent::updateNextButton()
246{
247  int num = myMessageList->getNumUnread();
248  MessageListItem* e = myMessageList->getNextUnread();
249
250  myReadNextButton->setEnabled(num > 0);
251
252  if (num > 1)
253    myReadNextButton->setText(tr("Nex&t (%1)").arg(num));
254  else if (num == 1)
255    myReadNextButton->setText(tr("Nex&t"));
256
257  if (e != NULL && e->msg() != NULL)
258    myReadNextButton->setIcon(IconManager::instance()->iconForEvent(e->msg()->SubCommand()));
259}
260
261void UserViewEvent::userUpdated(CICQSignal* sig, QString id, unsigned long ppid)
262{
263  const ICQUser* u = gUserManager.FetchUser(id.toLatin1(), ppid, LOCK_R);
264
265  if (u == 0)
266    return;
267
268  if (sig->SubSignal() == USER_EVENTS)
269  {
270    if (sig->Argument() > 0)
271    {
272      int eventId = sig->Argument();
273      const CUserEvent* e = u->EventPeekId(eventId);
274      // Making sure we didn't handle this message already.
275      if (e != NULL && myHighestEventId < eventId &&
276          (!Config::Chat::instance()->msgChatView() ||
277           (e->SubCommand() != ICQ_CMDxSUB_MSG &&
278            e->SubCommand() != ICQ_CMDxSUB_URL)))
279      {
280         myHighestEventId = eventId;
281         MessageListItem* m = new MessageListItem(e, myCodec, myMessageList);
282         myMessageList->scrollToItem(m);
283      }
284    }
285
286    if (sig->Argument() != 0)
287      updateNextButton();
288  }
289
290  gUserManager.DropUser(u);
291}
292
293void UserViewEvent::autoClose()
294{
295  if (!myAutoCloseCheck->isChecked())
296    return;
297
298  const ICQUser* u = gUserManager.FetchUser(myUsers.front().c_str(), myPpid, LOCK_R);
299
300  bool doclose = false;
301
302  if (u != NULL)
303  {
304    doclose = (u->NewMessages() == 0);
305    gUserManager.DropUser(u);
306  }
307
308  if (doclose)
309    closeDialog();
310}
311
312void UserViewEvent::read1()
313{
314  if (myCurrentEvent == 0)
315    return;
316
317  switch (myCurrentEvent->SubCommand())
318  {
319    case ICQ_CMDxSUB_MSG:  // reply/quote
320    case ICQ_CMDxSUB_URL:
321    case ICQ_CMDxSUB_CHAT:
322    case ICQ_CMDxSUB_FILE:
323      sendMsg("");
324      break;
325
326    case ICQ_CMDxSUB_AUTHxREQUEST:
327    {
328      CEventAuthRequest* p = dynamic_cast<CEventAuthRequest*>(myCurrentEvent);
329      new AuthUserDlg(p->IdString(), p->PPID(), true);
330      break;
331    }
332
333    case ICQ_CMDxSUB_AUTHxGRANTED:
334    {
335      CEventAuthGranted* p = dynamic_cast<CEventAuthGranted*>(myCurrentEvent);
336      new AddUserDlg(p->IdString(), p->PPID(), this);
337      break;
338    }
339
340    case ICQ_CMDxSUB_ADDEDxTOxLIST:
341    {
342      CEventAdded* p = dynamic_cast<CEventAdded*>(myCurrentEvent);
343      new AddUserDlg(p->IdString(), p->PPID(), this);
344      break;
345    }
346
347    case ICQ_CMDxSUB_CONTACTxLIST:
348    {
349      const ContactList& cl = dynamic_cast<CEventContactList*>(myCurrentEvent)->Contacts();
350      ContactList::const_iterator it;
351
352      for (it = cl.begin(); it != cl.end(); ++it)
353      {
354        new AddUserDlg((*it)->IdString(), (*it)->PPID(), this);
355      }
356
357      myRead1Button->setEnabled(false);
358      break;
359    }
360
361    case ICQ_CMDxSUB_EMAILxALERT:
362    {
363      // FIXME: For now assume MSN protocol, will need to be fixed soon.
364      CEventEmailAlert* p = dynamic_cast<CEventEmailAlert*>(myCurrentEvent);
365
366      // Create the HTML
367      QString url = BASE_DIR;
368      url += "/.msn_email.html";
369
370      QString strUser = p->To();
371      QString strHTML = QString(
372          "<html><head><noscript><meta http-equiv=Refresh content=\"0; url=http://www.hotmail.com\">"
373          "</noscript></head><body onload=\"document.pform.submit(); \"><form name=\"pform\" action=\""
374          "%1\" method=\"POST\"><input type=\"hidden\" name=\"mode\" value=\"ttl\">"
375          "<input type=\"hidden\" name=\"login\" value=\"%2\"><input type=\"hidden\" name=\"username\""
376          "value=\"%3\"><input type=\"hidden\" name=\"sid\" value=\"%4\"><input type=\"hidden\" name=\"kv\" value=\""
377          "%5\"><input type=\"hidden\" name=\"id\" value=\"%6\"><input type=\"hidden\" name=\"sl\" value=\"9\"><input "
378          "type=\"hidden\" name=\"rru\" value=\"%7\"><input type=\"hidden\" name=\"auth\" value=\"%8\""
379          "><input type=\"hidden\" name=\"creds\" value=\"%9\"><input type=\"hidden\" name=\"svc\" value=\"mail\">"
380          "<input type=\"hidden\" name=\"js\"value=\"yes\"></form></body></html>")
381        .arg(p->PostURL())
382        .arg(strUser.left(strUser.indexOf("@")))
383        .arg(strUser)
384        .arg(p->SID())
385        .arg(p->KV())
386        .arg(p->Id())
387        .arg(p->MsgURL())
388        .arg(p->MSPAuth())
389        .arg(p->Creds());
390
391      QFile fileHTML(url);
392      fileHTML.open(QIODevice::WriteOnly);
393      fileHTML.write(strHTML.toAscii(), strHTML.length());
394      fileHTML.close();
395
396      // Now we have to add the file:// after it was created,
397      // but before it is executed.
398      url.prepend("file://");
399
400      LicqGui::instance()->viewUrl(url);
401
402      break;
403    }
404  } // switch
405}
406
407void UserViewEvent::read2()
408{
409  if (myCurrentEvent == NULL)
410    return;
411
412  switch (myCurrentEvent->SubCommand())
413  {
414    case ICQ_CMDxSUB_MSG:  // quote
415    case ICQ_CMDxSUB_URL:
416      generateReply();
417      break;
418
419    case ICQ_CMDxSUB_CHAT:  // accept a chat request
420    {
421      myCurrentEvent->SetPending(false);
422      myRead2Button->setEnabled(false);
423      myRead3Button->setEnabled(false);
424      CEventChat* c = dynamic_cast<CEventChat*>(myCurrentEvent);
425      ChatDlg* chatDlg = new ChatDlg(myUsers.front().c_str(), myPpid);
426      if (c->Port() != 0)  // Joining a multiparty chat (we connect to them)
427      {
428        // FIXME: must have been done in CICQDaemon
429        if (chatDlg->StartAsClient(c->Port()))
430          gLicqDaemon->icqChatRequestAccept(
431              myUsers.front().c_str(),
432              0, c->Clients(), c->Sequence(),
433              c->MessageID(), c->IsDirect());
434      }
435      else  // single party (other side connects to us)
436      {
437        // FIXME: must have been done in CICQDaemon
438        if (chatDlg->StartAsServer())
439          gLicqDaemon->icqChatRequestAccept(
440              myUsers.front().c_str(),
441              chatDlg->LocalPort(), c->Clients(), c->Sequence(),
442              c->MessageID(), c->IsDirect());
443      }
444      break;
445    }
446
447    case ICQ_CMDxSUB_FILE:  // accept a file transfer
448    {
449      myCurrentEvent->SetPending(false);
450      myRead2Button->setEnabled(false);
451      myRead3Button->setEnabled(false);
452      CEventFile* f = dynamic_cast<CEventFile*>(myCurrentEvent);
453      FileDlg* fileDlg = new FileDlg(myUsers.front().c_str(), myPpid);
454
455      if (fileDlg->ReceiveFiles())
456        // FIXME: must have been done in CICQDaemon
457        gLicqDaemon->icqFileTransferAccept(
458            myUsers.front().c_str(),
459            fileDlg->LocalPort(), f->Sequence(), f->MessageID(), f->IsDirect(),
460            f->FileDescription(), f->Filename(), f->FileSize());
461      break;
462    }
463
464    case ICQ_CMDxSUB_AUTHxREQUEST:
465    {
466      CEventAuthRequest* p = dynamic_cast<CEventAuthRequest*>(myCurrentEvent);
467      new AuthUserDlg(p->IdString(), p->PPID(), false);
468      break;
469    }
470  } // switch
471}
472
473void UserViewEvent::read3()
474{
475  if (myCurrentEvent == NULL)
476    return;
477
478  switch (myCurrentEvent->SubCommand())
479  {
480    case ICQ_CMDxSUB_MSG:  // Forward
481    case ICQ_CMDxSUB_URL:
482    {
483      ForwardDlg* f = new ForwardDlg(myCurrentEvent, this);
484      f->show();
485      break;
486    }
487
488    case ICQ_CMDxSUB_CHAT:  // refuse a chat request
489    {
490      RefuseDlg* r = new RefuseDlg(myUsers.front().c_str(), myPpid, tr("Chat"), this);
491
492      if (r->exec())
493      {
494        myCurrentEvent->SetPending(false);
495        CEventChat* c = dynamic_cast<CEventChat*>(myCurrentEvent);
496        myRead2Button->setEnabled(false);
497        myRead3Button->setEnabled(false);
498
499        // FIXME: must have been done in CICQDaemon
500        gLicqDaemon->icqChatRequestRefuse(
501            myUsers.front().c_str(),
502            myCodec->fromUnicode(r->RefuseMessage()), myCurrentEvent->Sequence(),
503            c->MessageID(), c->IsDirect());
504      }
505      delete r;
506      break;
507    }
508
509    case ICQ_CMDxSUB_FILE:  // refuse a file transfer
510    {
511      RefuseDlg* r = new RefuseDlg(myUsers.front().c_str(), myPpid, tr("File Transfer"), this);
512
513      if (r->exec())
514      {
515        myCurrentEvent->SetPending(false);
516        CEventFile* f = dynamic_cast<CEventFile*>(myCurrentEvent);
517        myRead2Button->setEnabled(false);
518        myRead3Button->setEnabled(false);
519
520        // FIXME: must have been done in CICQDaemon
521        gLicqDaemon->icqFileTransferRefuse(
522            myUsers.front().c_str(),
523            myCodec->fromUnicode(r->RefuseMessage()), myCurrentEvent->Sequence(),
524            f->MessageID(), f->IsDirect());
525      }
526      delete r;
527      break;
528    }
529
530    case ICQ_CMDxSUB_AUTHxREQUEST:
531    {
532      CEventAuthRequest* p = dynamic_cast<CEventAuthRequest*>(myCurrentEvent);
533      new AddUserDlg(p->IdString(), p->PPID(), this);
534      break;
535    }
536  } // switch
537}
538
539void UserViewEvent::read4()
540{
541  if (myCurrentEvent == NULL)
542    return;
543
544  switch (myCurrentEvent->SubCommand())
545  {
546    case ICQ_CMDxSUB_MSG:
547      LicqGui::instance()->showEventDialog(ChatEvent, myUsers.front().c_str(), myPpid);
548      break;
549
550    case ICQ_CMDxSUB_CHAT:  // join to current chat
551    {
552      CEventChat* c = dynamic_cast<CEventChat*>(myCurrentEvent);
553      if (c->Port() != 0)  // Joining a multiparty chat (we connect to them)
554      {
555        ChatDlg* chatDlg = new ChatDlg(myUsers.front().c_str(), myPpid);
556        // FIXME: must have been done in CICQDaemon
557        if (chatDlg->StartAsClient(c->Port()))
558          gLicqDaemon->icqChatRequestAccept(
559              myUsers.front().c_str(),
560              0, c->Clients(), c->Sequence(), c->MessageID(), c->IsDirect());
561      }
562      else  // single party (other side connects to us)
563      {
564        ChatDlg* chatDlg = NULL;
565        JoinChatDlg* j = new JoinChatDlg(this);
566        // FIXME: must have been done in CICQDaemon
567        if (j->exec() && (chatDlg = j->JoinedChat()) != NULL)
568          gLicqDaemon->icqChatRequestAccept(
569              myUsers.front().c_str(),
570              chatDlg->LocalPort(), c->Clients(), c->Sequence(), c->MessageID(), c->IsDirect());
571        delete j;
572      }
573      break;
574    }
575
576    case ICQ_CMDxSUB_URL:   // view a url
577      LicqGui::instance()->viewUrl(dynamic_cast<CEventUrl*>(myCurrentEvent)->Url());
578      break;
579
580    case ICQ_CMDxSUB_AUTHxREQUEST: // Fall through
581    case ICQ_CMDxSUB_AUTHxGRANTED:
582    case ICQ_CMDxSUB_ADDEDxTOxLIST:
583    {
584      const char* id;
585      unsigned long ppid;
586#define GETINFO(sub, type) \
587      if (myCurrentEvent->SubCommand() == sub) \
588      { \
589        type* p = dynamic_cast<type*>(myCurrentEvent); \
590        id = p->IdString(); \
591        ppid = p->PPID(); \
592      }
593
594      GETINFO(ICQ_CMDxSUB_AUTHxREQUEST, CEventAuthRequest);
595      GETINFO(ICQ_CMDxSUB_AUTHxGRANTED, CEventAuthGranted);
596      GETINFO(ICQ_CMDxSUB_ADDEDxTOxLIST, CEventAdded);
597#undef GETINFO
598
599      const ICQUser* u = gUserManager.FetchUser(id, ppid, LOCK_R);
600      if (u == NULL)
601        gLicqDaemon->AddUserToList(id, ppid, false, true);
602      else
603        gUserManager.DropUser(u);
604
605      LicqGui::instance()->showInfoDialog(mnuUserGeneral, id, ppid, false, true);
606      break;
607    }
608  } // switch
609}
610
611void UserViewEvent::readNext()
612{
613  MessageListItem* e = myMessageList->getNextUnread();
614
615  updateNextButton();
616
617  if (e != NULL)
618  {
619    myMessageList->setCurrentItem(e, 0);
620    myMessageList->scrollToItem(e);
621    printMessage(e);
622  }
623}
624
625void UserViewEvent::clearEvent()
626{
627  ICQUser* u = gUserManager.FetchUser(myUsers.front().c_str(), myPpid, LOCK_W);
628
629  if (u == NULL)
630    return;
631
632  u->EventClearId(myCurrentEvent->Id());
633  gUserManager.DropUser(u);
634}
635
636void UserViewEvent::closeDialog()
637{
638  myDeleteUser = myCloseButton->modifiersWhenPressed() & Qt::ControlModifier;
639  close();
640}
641
642void UserViewEvent::msgTypeChanged(UserSendCommon* from, UserSendCommon* to)
643{
644  disconnect(from, SIGNAL(autoCloseNotify()), this, SLOT(autoClose()));
645  disconnect(from, SIGNAL(msgTypeChanged(UserSendCommon*, UserSendCommon*)),
646      this, SLOT(msgTypeChanged(UserSendCommon*, UserSendCommon*)));
647
648  connect(to, SIGNAL(autoCloseNotify()), SLOT(autoClose()));
649  connect(to, SIGNAL(msgTypeChanged(UserSendCommon*, UserSendCommon*)),
650      SLOT(msgTypeChanged(UserSendCommon*, UserSendCommon*)));
651}
652
653void UserViewEvent::printMessage(QTreeWidgetItem* item)
654{
655  if (item == NULL)
656    return;
657
658  MessageListItem* e = dynamic_cast<MessageListItem*>(item);
659
660  myRead1Button->setText("");
661  myRead2Button->setText("");
662  myRead3Button->setText("");
663  myRead4Button->setText("");
664  myEncoding->setEnabled(true);
665
666  CUserEvent* m = e->msg();
667  myCurrentEvent = m;
668
669  // Set the color for the message
670  myMessageView->setBackground(QColor(m->Color()->BackRed(), m->Color()->BackGreen(), m->Color()->BackBlue()));
671  myMessageView->setForeground(QColor(m->Color()->ForeRed(), m->Color()->ForeGreen(), m->Color()->ForeBlue()));
672
673  // Set the text
674  if (m->SubCommand() == ICQ_CMDxSUB_SMS)
675     myMessageText = QString::fromUtf8(m->Text());
676  else
677     myMessageText = myCodec->toUnicode(m->Text());
678
679  QString colorAttr;
680  colorAttr.sprintf("#%02lx%02lx%02lx", m->Color()->ForeRed(), m->Color()->ForeGreen(), m->Color()->ForeBlue());
681  myMessageView->setText("<font color=\"" + colorAttr + "\">" + MLView::toRichText(myMessageText, true) + "</font>");
682
683  myMessageView->GotoHome();
684
685  if (m->Direction() == D_RECEIVER &&
686      (m->Command() == ICQ_CMDxTCP_START ||
687       m->Command() == ICQ_CMDxRCV_SYSxMSGxON