source: qutecom-2.2/wengophone/src/presentation/qt/chat/QtChatWindow.cpp @ 499:1bf0eda7d082

Last change on this file since 499:1bf0eda7d082 was 499:1bf0eda7d082, checked in by laurent@…, 3 years ago

use webkit with chat

File size: 28.4 KB
Line 
1/*
2 * WengoPhone, a voice over Internet phone
3 * Copyright (C) 2004-2007  Wengo
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20#include "QtChatWindow.h"
21#include "QtChatWidget.h"
22#include "QtChatTabWidget.h"
23#include "ui_ChatMainWindow.h"
24#include "emoticons/QtEmoticonsManager.h"
25
26#include <model/config/Config.h>
27#include <model/config/ConfigManager.h>
28#include <model/contactlist/ContactProfile.h>
29#include <model/profile/AvatarList.h>
30#include <model/profile/UserProfile.h>
31#include <model/webservices/url/WsUrl.h>
32
33#include <control/CWengoPhone.h>
34#include <control/profile/CUserProfile.h>
35#include <control/profile/CUserProfileHandler.h>
36
37#include <presentation/qt/QtWengoPhone.h>
38#include <presentation/qt/QtToolBar.h>
39#include <presentation/qt/contactlist/QtContactList.h>
40#include <presentation/qt/contactlist/QtContactListManager.h>
41#include <presentation/qt/toaster/QtChatToaster.h>
42#include <presentation/qt/profile/QtUserProfileHandler.h>
43#include <presentation/qt/webservices/sms/QtSms.h>
44#include <presentation/qt/profile/QtProfileDetails.h>
45#include <presentation/qt/filetransfer/QtFileTransfer.h>
46
47#include <imwrapper/IMChatSession.h>
48#include <imwrapper/IMAccount.h>
49#include <imwrapper/IMContact.h>
50#include <imwrapper/EnumIMProtocol.h>
51#include <imwrapper/IMContactSet.h>
52
53#include <cutil/global.h>
54#include <qtutil/Object.h>
55#include <qtutil/SafeConnect.h>
56#include <qtutil/WidgetUtils.h>
57#include <util/Logger.h>
58#include <util/SafeDelete.h>
59
60#include <sound/Sound.h>
61
62#if defined(OS_WINDOWS)
63        #include <windows.h>
64#endif
65
66#include <QtCore/QDir>
67#include <QtCore/QFileInfo>
68
69#include <QtGui/QClipboard>
70
71/**
72 * Finds an QAction and copies its properties to another QAction.
73 *
74 * @param actionParent where to find the original QAction
75 * @param action QAction to modify
76 */
77static void copyQAction(QObject * actionParent, QAction * action) {
78        QString name = action->objectName();
79        QAction * tmp = actionParent->findChild<QAction *>(name);
80        if (!tmp) {
81                LOG_ERROR("Couldn't find action named '" + name.toStdString() + "', cannot copy it");
82                return;
83        }
84        action->setIcon(tmp->icon());
85        action->setIconText(tmp->iconText());
86        action->setText(tmp->text());
87        action->setToolTip(tmp->toolTip());
88        action->setShortcut(tmp->shortcut());
89}
90
91/**
92 * Connect an action to show a web page to its slot if the web page has been
93 * defined
94 */
95static void connectOrHide(WsUrl::Page page, QMenu* menu, QAction* action, QtToolBar* qtToolBar, const char* slot) {
96        if (WsUrl::hasPage(page)) {
97                copyQAction(qtToolBar->getWidget(), action);
98                SAFE_CONNECT_RECEIVER(action, SIGNAL(triggered()), qtToolBar, slot);
99        } else {
100                menu->removeAction(action);
101        }
102}
103
104QtChatWindow::QtChatWindow(QWidget * parent, CChatHandler & cChatHandler, IMChatSession & imChatSession, QtWengoPhone & qtWengoPhone)
105        : QMainWindow(parent),
106        _cChatHandler(cChatHandler),
107        _qtWengoPhone(qtWengoPhone) {
108
109        _imChatSession = &imChatSession;
110
111        _ui = new Ui::ChatMainWindow();
112        _ui->setupUi(this);
113        setupMenuBarActions();
114        setupToolBarActions();
115
116        // bind to IMChatSession events
117        _imChatSession->messageReceivedEvent +=
118                boost::bind(&QtChatWindow::messageReceivedEventHandler, this, _1);
119        _imChatSession->imChatSessionWillDieEvent +=
120                boost::bind(&QtChatWindow::imChatSessionWillDieEventHandler, this, _1);
121        _imChatSession->typingStateChangedEvent +=
122                boost::bind(&QtChatWindow::typingStateChangedEventHandler, this, _1, _2, _3);
123        ////
124
125        // create the tab widget and connect to its signals
126        _tabWidget = new QtChatTabWidget(this);
127        _tabWidget->removeTab(0);
128        setCentralWidget(_tabWidget);
129        SAFE_CONNECT(_tabWidget, SIGNAL(closeButtonClicked()), SLOT(closeActiveTab()));
130        SAFE_CONNECT(_tabWidget, SIGNAL(currentChanged(int)), SLOT(activeTabChanged(int)));
131        ////
132
133        // create instance of QtEmoticonsManager
134        QtEmoticonsManager::getInstance();
135
136        // thread safe code
137        SAFE_CONNECT_TYPE(this, SIGNAL(typingStateChangedSignal(const IMChatSession *, const IMContact *, const  IMChat::TypingState *)),
138                SLOT(typingStateChangedThreadSafe(const IMChatSession *, const IMContact *, const IMChat::TypingState *)), Qt::QueuedConnection);
139        SAFE_CONNECT_TYPE(this, SIGNAL(messageReceivedSignal(IMChatSession *)),
140                SLOT(messageReceivedSlot(IMChatSession *)), Qt::QueuedConnection);
141        ////
142
143    // Clipboard actions
144    SAFE_CONNECT(_ui->actionCut, SIGNAL(triggered()),
145        SLOT(cut()) );
146    SAFE_CONNECT(_ui->actionCopy, SIGNAL(triggered()),
147        SLOT(copy()) );
148    SAFE_CONNECT(_ui->actionPaste, SIGNAL(triggered()),
149        SLOT(paste()) );
150        SAFE_CONNECT(QApplication::clipboard(), SIGNAL(dataChanged()),
151                SLOT(updateClipboardActions()) );
152        updateClipboardActions();
153    ////
154
155        _qtWengoPhone.setChatWindow(this);
156        resize(490, 470);
157        setWindowTitle(tr("@product@ Chat"));
158
159#ifdef OS_LINUX
160        const std::string & applicationIconPath = ConfigManager::getInstance().getCurrentConfig().getApplicationIconPath();
161        setWindowIcon(QIcon(QString::fromStdString(applicationIconPath)));
162#endif
163
164        // add a tab widget
165        IMContact from = *_imChatSession->getIMContactSet().begin();
166        addChatWidgetTab(_imChatSession, from);
167        ////
168               
169#if defined(OS_MACOSX)
170        setUnifiedTitleAndToolBarOnMac(true);
171#endif
172}
173
174QtChatWindow::~QtChatWindow() {
175
176        //destroyed tabWidget so that chat are saved
177        while(_tabWidget->count()>0) {
178                closeActiveTab();
179        }
180        ////
181        QtEmoticonsManager * m = QtEmoticonsManager::getInstance();
182        OWSAFE_DELETE(m);
183
184        OWSAFE_DELETE(_ui);
185}
186
187QtChatWidget * QtChatWindow::getActiveTabWidget() {
188        return dynamic_cast<QtChatWidget *>(_tabWidget->widget(_tabWidget->currentIndex()));
189}
190
191void QtChatWindow::activeTabChanged(int index) {
192        _tabWidget->stopBlinkingTab(index);
193        setWindowTitle(_tabWidget->tabText(_tabWidget->currentIndex()));
194        updateToolBarActions();
195        updateClipboardActions();
196        statusBar()->showMessage(QString::null);
197}
198
199const QString QtChatWindow::getActiveTabContactId() {
200        QString contactId;
201        QtChatWidget * widget = getActiveTabWidget();
202        if (widget) {
203                contactId = widget->getContactId();
204        }
205        return contactId;
206}
207
208ContactProfile QtChatWindow::getContactProfileFromContactId(const QString & contactId) {
209        return _qtWengoPhone.getQtContactList()->getCContactList().getContactProfile(contactId.toStdString());
210}
211
212void QtChatWindow::closeActiveTab() {
213        QtChatWidget * widget = getActiveTabWidget();
214        _tabWidget->removeTab(_tabWidget->indexOf(widget));
215        OWSAFE_DELETE(widget);
216        if (_tabWidget->count() == 0) {
217                close();
218                _qtWengoPhone.setChatWindow(NULL);
219        }
220        activeTabChanged(_tabWidget->currentIndex());
221}
222
223void QtChatWindow::showMinimized() {
224#if !defined(OS_MACOSX)
225
226#ifdef OS_WINDOWS
227        HWND topWindow = GetForegroundWindow();
228#endif
229        QMainWindow::showMinimized();
230#ifdef OS_WINDOWS
231        SetForegroundWindow(topWindow);
232#endif
233
234#else
235        showNormal();
236#endif
237}
238
239void QtChatWindow::show() {
240        showNormal();
241        activateWindow();
242        raise();
243}
244
245void QtChatWindow::createChatConference() {
246        QtChatWidget * widget = getActiveTabWidget();
247        if (widget) {
248                widget->showInviteDialog();
249        }
250}
251
252void QtChatWindow::typingStateChangedEventHandler(IMChatSession & sender, const IMContact & imContact, IMChat::TypingState state) {
253        IMChat::TypingState * tmpState = new IMChat::TypingState;
254        *tmpState = state;
255        typingStateChangedSignal(&sender,&imContact,tmpState);
256}
257
258void QtChatWindow::typingStateChangedThreadSafe(const IMChatSession * sender, const IMContact * from,const IMChat::TypingState * state) {
259        int tabs = _tabWidget->count();
260        for (int i = 0; i < tabs; i++) {
261                QtChatWidget * widget = (QtChatWidget *) _tabWidget->widget(i);
262                if (widget->getSessionId() == sender->getId()) {
263               
264                        //only display mssage if IMChatSessio is active
265                        if (!widget->isVisible()) {
266                                return;
267                        }
268               
269                        QString remoteName = QString::fromUtf8(from->getDisplayContactId().c_str());
270                        switch (*state) {
271                        case IMChat::TypingStateNotTyping:
272                                statusBar()->showMessage(QString::null);
273                                break;
274                        case IMChat::TypingStateTyping:
275                                statusBar()->showMessage(tr("%1 is typing").arg(remoteName));
276                                break;
277                        case IMChat::TypingStateStopTyping:
278                                statusBar()->showMessage(QString::null);
279                                break;
280                        default:
281                                break;
282                        }
283                }
284        }
285        OWSAFE_DELETE(state);
286}
287
288void QtChatWindow::messageReceivedEventHandler(IMChatSession & sender) {
289        messageReceivedSignal(&sender);
290}
291
292QString QtChatWindow::getShortDisplayName(const QString & contactId, const QString & defaultName) const {
293        QtContactList * qtContactList = _qtWengoPhone.getQtContactList();
294        CContactList & cContactList = qtContactList->getCContactList();
295        std::string tmpSendername = cContactList.getContactProfile(contactId.toStdString()).getShortDisplayName();
296        if (tmpSendername.empty()) {
297                tmpSendername = defaultName.toStdString();
298        }
299
300        return QString::fromUtf8(tmpSendername.c_str());
301}
302
303void QtChatWindow::statusChangedSlot(QString contactId) {
304        QtContactList * qtContactList = _qtWengoPhone.getQtContactList();
305        std::string sdname = qtContactList->getCContactList().getContactProfile(contactId.toStdString()).getDisplayName();
306        EnumPresenceState::PresenceState pstate = qtContactList->getCContactList().getContactProfile(contactId.toStdString()).getPresenceState();
307        QString displayName = QString::fromStdString(sdname);
308
309        // search for the tab that contain sender
310        // FIXME: the contact could be in several tabs: for instance when
311        // we do a single-chat and a multi-chat with this contact
312        for (int i = 0; i < _tabWidget->count(); i++) {
313                QtChatWidget * widget = (QtChatWidget *) _tabWidget->widget(i);
314                if (widget) {
315                        if (widget->getContactId() == contactId) {
316                                switch(pstate) {
317                                case EnumPresenceState::PresenceStateOnline:
318                                        _tabWidget->setTabIcon(i, QIcon(QPixmap(":/pics/status/online.png")));
319                                        widget->setContactConnected(true);
320                                        break;
321                                case EnumPresenceState::PresenceStateOffline:
322                                        _tabWidget->setTabIcon(i, QIcon(QPixmap(":/pics/status/offline.png")));
323                                        widget->setContactConnected(false);
324                                        break;
325                                case EnumPresenceState::PresenceStateDoNotDisturb:
326                                        _tabWidget->setTabIcon(i, QIcon(QPixmap(":/pics/status/donotdisturb.png")));
327                                        widget->setContactConnected(true);
328                                        break;
329                                case EnumPresenceState::PresenceStateAway:
330                                        _tabWidget->setTabIcon(i, QIcon(QPixmap(":/pics/status/away.png")));
331                                        widget->setContactConnected(true);
332                                        break;
333                                default:
334                                        _tabWidget->setTabIcon(i, QIcon(QPixmap(":/pics/contact/chat.png")));
335                                        if (!displayName.isEmpty()) {
336                                                // If Display name is empty, it means that the Contact is not in the ContactList.
337                                                // Thus we should not say that the contact is offline as we don't really know its
338                                                // status.
339                                                widget->setContactConnected(false);
340                                        }
341                                        break;
342                                }
343                                break;
344                        }
345                }
346        }
347
348        updateToolBarActions();
349}
350
351void QtChatWindow::setupMenuBarActions() {
352        QtToolBar * qtToolBar = &_qtWengoPhone.getQtToolBar();
353        QWidget * toolBar = qtToolBar->getWidget();
354
355        // setup "Wengo" menu
356        connectOrHide(WsUrl::Account, _ui->menuWengo, _ui->actionShowWengoAccount, qtToolBar, SLOT(showWengoAccount()));
357
358        copyQAction(toolBar, _ui->actionEditMyProfile);
359        SAFE_CONNECT_RECEIVER(_ui->actionEditMyProfile, SIGNAL(triggered()), qtToolBar, SLOT(editMyProfile()));
360        connectOrHide(WsUrl::CallOut, _ui->menuWengo, _ui->actionWengoServices, qtToolBar, SLOT(showWengoServices()));
361
362        copyQAction(toolBar, _ui->actionClose);
363        SAFE_CONNECT(_ui->actionClose, SIGNAL(triggered()), SLOT(close()));
364        ////
365
366        // setup "contact" menubar
367        copyQAction(toolBar, _ui->actionAddContact);
368        SAFE_CONNECT_RECEIVER(_ui->actionAddContact, SIGNAL(triggered()), qtToolBar, SLOT(addContact()));
369        copyQAction(toolBar, _ui->actionSearchWengoContact);
370        SAFE_CONNECT_RECEIVER(_ui->actionSearchWengoContact, SIGNAL(triggered()), qtToolBar, SLOT(searchWengoContact()));
371        ////
372
373        // setup "actions" menu
374        copyQAction(toolBar, _ui->actionCreateConferenceCall);
375        SAFE_CONNECT_RECEIVER(_ui->actionCreateConferenceCall, SIGNAL(triggered()), qtToolBar, SLOT(createConferenceCall()));
376        copyQAction(toolBar, _ui->actionSendSms);
377        SAFE_CONNECT_RECEIVER(_ui->actionSendSms, SIGNAL(triggered()), qtToolBar, SLOT(sendSms()));
378        SAFE_CONNECT(_ui->actionSaveHistoryAs, SIGNAL(triggered()), SLOT(saveActiveTabChatHistory()));
379        ////
380
381        // setup "tools" menu
382        copyQAction(toolBar, _ui->actionShowFileTransfer);
383        SAFE_CONNECT_RECEIVER(_ui->actionShowFileTransfer, SIGNAL(triggered()), qtToolBar, SLOT(showFileTransferWindow()));
384
385        // clone "help" menu
386        QMenu* menuHelp = _qtWengoPhone.getWidget()->findChild<QMenu*>("menuHelp");
387        if (menuHelp) {
388                menuBar()->addMenu(menuHelp);
389        } else {
390                LOG_ERROR("Couldn't find a menu named 'menuHelp' in main window");
391        }
392        ////
393}
394
395void QtChatWindow::setupToolBarActions() {
396        SAFE_CONNECT(_ui->actionCallContact, SIGNAL(triggered()), SLOT(callActiveTabContact()));
397        SAFE_CONNECT(_ui->actionSendSms, SIGNAL(triggered()), SLOT(sendSmsToActiveTabContact()));
398        SAFE_CONNECT(_ui->actionSendFile, SIGNAL(triggered()), SLOT(sendFileToActiveTabContact()));
399        SAFE_CONNECT(_ui->actionCreateChatConf, SIGNAL(triggered()), SLOT(createChatConference()));
400        SAFE_CONNECT(_ui->actionContactInfo, SIGNAL(triggered()), SLOT(showActiveTabContactInfo()));
401        SAFE_CONNECT(_ui->actionBlockContact, SIGNAL(triggered()), SLOT(blockActiveTabContact()));
402
403/*#if defined(OS_MACOSX)
404        // Add a stretch, so that the close tab button is aligned on the right
405        QWidget* dummyWidget = new QWidget();
406        dummyWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
407        _ui->toolBar->addWidget(dummyWidget);
408
409        // Add the close tab button
410        QIcon icon(":/pics/chat/chat_close.png");
411        QAction* action = _ui->toolBar->addAction(icon, tr("Close Chat"));
412        SAFE_CONNECT(action, SIGNAL(triggered()), SLOT(closeActiveTab()));
413
414        // For some unknown reason the close tab button is a bit off the screen.
415        // Adding some fixed spacing fixes this.
416        dummyWidget = new QWidget();
417        dummyWidget->setFixedHeight(10);
418        _ui->toolBar->addWidget(dummyWidget);
419#endif*/
420}
421
422void QtChatWindow::updateToolBarActions() {
423        //FIXME: this code assume that there is only one contact in the session
424
425        QtChatWidget * widget = getActiveTabWidget();
426        QString contactId;
427        QtContactList * qtContactList;
428        ContactProfile contactProfile;
429
430        if (widget) {
431                contactId = widget->getContactId();
432                qtContactList = _qtWengoPhone.getQtContactList();
433                if (qtContactList)
434                {
435                    contactProfile = qtContactList->getCContactList().getContactProfile(contactId.toStdString());
436
437                    _ui->actionCallContact->setEnabled(contactProfile.hasCall()
438                            && contactProfile.isAvailable());
439                   
440                                        _ui->actionSendSms->setEnabled(!contactProfile.getMobilePhone().empty());
441                                #ifdef DISABLE_SMS
442                                        _ui->actionSendSms->setVisible(false);
443                                #endif
444
445                                        _ui->actionSendFile->setEnabled(widget->canDoFileTransfer());
446                                #ifdef DISABLE_FILETRANSFER     
447                                        _ui->actionSendFile->setVisible(false);
448                                        _ui->actionShowFileTransfer->setVisible(false);
449                                        _ui->menuTools->menuAction()->setVisible(false);
450                                #endif
451
452                    _ui->actionCreateChatConf->setEnabled(widget->canDoMultiChat());
453                    _ui->actionContactInfo->setEnabled(true);
454                    //TODO: uncomment when block a contact will be implemented
455                    //_ui->actionBlockContact->setEnabled(!contactProfile.isBlocked());
456                    _ui->actionBlockContact->setEnabled(false);
457                    ////
458                }
459                else
460                {
461                    _ui->actionCallContact->setEnabled(false);
462                    _ui->actionSendSms->setEnabled(false);
463                    _ui->actionSendFile->setEnabled(false);
464
465                    _ui->actionCreateChatConf->setEnabled(false);
466                    _ui->actionContactInfo->setEnabled(false);
467                   _ui->actionBlockContact->setEnabled(false);
468                }
469
470        }
471}
472
473void QtChatWindow::messageReceivedSlot(IMChatSession * sender) {
474        if (!isActiveWindow()) {
475                if (!isVisible()) {
476                        // Make sure the window appears on the taskbar,
477                        // otherwise it won't flash...
478                        showMinimized();
479                }
480                WidgetUtils::flashWindow(this);
481        }
482
483        // new way to get messages
484        IMChatSession::IMChatMessageList imChatMessageList = sender->getReceivedMessage(_lastReceivedMessageIndex[sender->getId()] + 1);
485        if (imChatMessageList.size() > 0) {
486                _lastReceivedMessageIndex[sender->getId()] += imChatMessageList.size();
487                IMChatSession::IMChatMessageList::iterator imChatMessageListIterator = imChatMessageList.begin();
488                while (imChatMessageListIterator < imChatMessageList.end()) {
489                        IMChatSession::IMChatMessage * imChatMessage = * imChatMessageListIterator;
490                        const IMContact & from = imChatMessage->getIMContact();
491                        std::string message = imChatMessage->getMessage();
492                        QString senderName = QString::fromStdString(from.getContactId());
493
494                        QtContactList * qtContactList = _qtWengoPhone.getQtContactList();
495                        CContactList & cContactList = qtContactList->getCContactList();
496                        QString contactId = QString::fromStdString(cContactList.findContactThatOwns(from));
497                        QString senderDisplayName = getShortDisplayName(contactId, QString::fromStdString(from.getDisplayContactId()));
498                        QString msg = QString::fromUtf8(message.c_str());
499
500                        int tabs = _tabWidget->count();
501                        for (int i = 0; i < tabs; i++) {
502                                QtChatWidget * widget = dynamic_cast<QtChatWidget *>(_tabWidget->widget(i));
503                                if (widget->getSessionId() == sender->getId()) {
504                                        _chatWidget = qobject_cast<QtChatWidget *>(_tabWidget->widget(i));
505                                        _chatWidget->addToHistory(contactId, senderDisplayName, msg);
506                                        if (_tabWidget->currentWidget() != _chatWidget) {
507                                                if (isMinimized()) {
508                                                        _tabWidget->setCurrentIndex(i);
509                                                } else {
510                                                        _tabWidget->setBlinkingTab(i);
511                                                }
512                                        }
513                                        break;
514                                }
515                        }
516                        imChatMessageListIterator++;
517                }
518        }
519        ////
520}
521
522void QtChatWindow::imChatSessionCreatedHandler(IMChatSession * imChatSession) {
523        // If this chat session already exists, display the tab
524        int tabs = _tabWidget->count();
525        for (int i = 0; i < tabs; i++) {
526                QtChatWidget * widget = dynamic_cast<QtChatWidget *>(_tabWidget->widget(i));
527                if (widget->getSessionId() == imChatSession->getId()) {
528                        _tabWidget->setCurrentIndex(i);
529                        show();
530                        return;
531                }
532        }
533
534        // bind to IMChatSession events
535        imChatSession->messageReceivedEvent +=
536                boost::bind(&QtChatWindow::messageReceivedEventHandler, this, _1);
537        imChatSession->imChatSessionWillDieEvent +=
538                boost::bind(&QtChatWindow::imChatSessionWillDieEventHandler, this, _1);
539        imChatSession->typingStateChangedEvent +=
540                boost::bind(&QtChatWindow::typingStateChangedEventHandler, this, _1, _2, _3);
541        ////
542
543        if (imChatSession->getIMContactSet().size() != 0 ) {
544                IMContact from = *imChatSession->getIMContactSet().begin();
545                addChatWidgetTab(imChatSession, from);
546        } else {
547                LOG_FATAL("New chat session is empty!");
548        }
549        _qtWengoPhone.setChatWindow(this);
550}
551
552void QtChatWindow::addChatWidgetTab(IMChatSession * imChatSession, const IMContact & from) {
553
554        QtContactList * qtContactList = _qtWengoPhone.getQtContactList();
555        if (qtContactList) {
556                CContactList & cContactList = qtContactList->getCContactList();
557
558                QString contactId = QString::fromStdString(cContactList.findContactThatOwns(from));
559                std::string tmpNickName;
560                IMAccount * imAccount =
561                        _cChatHandler.getCUserProfile().getUserProfile().getIMAccountManager().getIMAccount(imChatSession->getIMChat().getIMAccountId());
562                if (imAccount) 
563                {
564                        if(imAccount->getDisplayName() != "")
565                                tmpNickName = imAccount->getDisplayName();
566                        else
567                                tmpNickName = imAccount->getLogin();
568                        OWSAFE_DELETE(imAccount);
569                } else {
570                        LOG_ERROR("cannot get associated IMAccount");
571                }
572               
573                QString nickName = QString::fromUtf8(tmpNickName.c_str());
574
575                QString senderName = getShortDisplayName(contactId, QString::fromStdString(from.getDisplayContactId()));
576
577                _chatWidget = new QtChatWidget(_cChatHandler, &_qtWengoPhone, imChatSession->getId(), 0 /*parent*/);
578                SAFE_CONNECT_RECEIVER(_chatWidget, SIGNAL(ctrlTabPressed()), _tabWidget, SLOT(goToNextTab()));
579                _chatWidget->setNickName(nickName);
580                _chatWidget->setIMChatSession(imChatSession);
581                _chatWidget->setContactId(QString::fromStdString(qtContactList->getCContactList().findContactThatOwns(from)));
582                Q_FOREACH(QTextEdit* textEdit, _chatWidget->findChildren<QTextEdit*>()) {
583                        SAFE_CONNECT(textEdit, SIGNAL(selectionChanged()),
584                                SLOT(updateClipboardActions()) );
585                        textEdit->installEventFilter(this);
586                }
587
588                SAFE_CONNECT(qtContactList, SIGNAL(contactChangedEventSignal(QString )), SLOT(statusChangedSlot(QString)));
589
590                int tabNumber;
591                if (_tabWidget->count() > 0) {
592                        tabNumber = _tabWidget->insertTab(_tabWidget->count(), _chatWidget, senderName);
593                } else {
594                        tabNumber = _tabWidget->insertTab(0, _chatWidget, senderName);
595                }
596
597                if (imChatSession->isUserCreated()) {
598                        _tabWidget->setCurrentIndex(tabNumber);
599                        updateClipboardActions();
600                }
601
602                statusChangedSlot(QString::fromStdString(cContactList.findContactThatOwns(from)));
603               
604                activeTabChanged(_tabWidget->currentIndex());
605
606                // Adding probably missed message
607                _lastReceivedMessageIndex[imChatSession->getId()] = -1;
608                IMChatSession::IMChatMessageList imChatMessageList = 
609                        imChatSession->getReceivedMessage(_lastReceivedMessageIndex[imChatSession->getId()] + 1);
610                if (imChatMessageList.size() > 0) {
611                        _lastReceivedMessageIndex[imChatSession->getId()] += imChatMessageList.size();
612                        IMChatSession::IMChatMessageList::iterator imChatMessageListIterator = imChatMessageList.begin();
613                        while (imChatMessageListIterator != imChatMessageList.end()){
614                                IMChatSession::IMChatMessage * imChatMessage = * imChatMessageListIterator;
615
616                                //history chat message are reconstructed with no protocol
617                                QString displayName;
618                                QTime time;
619                                if(imChatMessage->getIMContact().getProtocol() != EnumIMProtocol::IMProtocolUnknown) {
620                                        displayName = getShortDisplayName(contactId, QString::fromStdString(from.getDisplayContactId()));
621                                } else {
622                                        displayName = QString::fromStdString(imChatMessage->getIMContact().cleanContactId());
623                                        Time messageTime = imChatMessage->getTime();
624                                        time = QTime(messageTime.getHour(), messageTime.getMinute());
625                                }
626                                _chatWidget->addToHistory(contactId, displayName,
627                                                QString::fromUtf8(imChatMessage->getMessage().c_str()),
628                                                time);
629
630                                imChatMessageListIterator++;
631                        }
632                }
633                ////
634
635                if (imChatSession->isUserCreated()) {
636                        show();
637                } else {
638                        if (isActiveWindow() || _qtWengoPhone.getWidget()->isActiveWindow()) {
639                                if (tabNumber != _tabWidget->currentIndex()) {
640                                        _tabWidget->setBlinkingTab(tabNumber);
641                                }
642                                show();
643                        } else {
644                                if (!isVisible()) {
645                                        // Make sure the window appears on the taskbar,
646                                        // otherwise it won't flash...
647                                        showMinimized();
648                                }
649
650                                if (isMinimized()) {
651                                        _tabWidget->setCurrentIndex(tabNumber);
652                                } else if (tabNumber != _tabWidget->currentIndex()) {
653                                        _tabWidget->setBlinkingTab(tabNumber);
654                                }
655
656                                WidgetUtils::flashWindow(this);
657                                showToaster(imChatSession);
658                        }
659                }
660
661                updateToolBarActions();
662        }
663}
664
665void QtChatWindow::showToaster(IMChatSession * imChatSession) {
666        QtContactList * qtContactList = _qtWengoPhone.getQtContactList();
667        if (qtContactList) {
668                CContactList & cContactList = qtContactList->getCContactList();
669                QPixmap avatar;
670                QtChatToaster * toaster = new QtChatToaster();
671
672                if (imChatSession->getIMContactSet().size() > 0) {
673                        QString message;
674                        for (IMContactSet::const_iterator it = imChatSession->getIMContactSet().begin();
675                                it != imChatSession->getIMContactSet().end(); ++it) {
676
677                                if (it != imChatSession->getIMContactSet().begin()) {
678                                        message += ", ";
679                                }
680                                QString contactId = QString::fromStdString(cContactList.findContactThatOwns((*it)));
681                                message += getShortDisplayName(contactId, QString::fromStdString((*it).getDisplayContactId()));
682
683                                std::string contact =  _cChatHandler.getCUserProfile().getCContactList().findContactThatOwns((*it));
684                                if (!contact.empty()) {
685                                        ContactProfile contactProfile = _cChatHandler.getCUserProfile().getCContactList().getContactProfile(contact);
686                                        OWPicture picture = contactProfile.getIcon();
687                                        std::string data = picture.getData();
688                                        if (!data.empty()) {
689                                                avatar.loadFromData((uchar *) data.c_str(), data.size());
690                                        }
691                                }
692                        }
693                        toaster->setMessage(message);
694                }
695
696                if (avatar.isNull()) {
697                        std::string data = AvatarList::getInstance().getDefaultAvatarPicture().getData();
698                        avatar.loadFromData((uchar*)data.c_str(), data.size());
699                }
700
701                toaster->setPixmap(avatar);
702
703                Config & config = ConfigManager::getInstance().getCurrentConfig();
704                Sound::play(config.getAudioIncomingChatFile());
705                SAFE_CONNECT(toaster, SIGNAL(chatButtonClicked()), SLOT(show()));
706                toaster->show();
707        }
708}
709
710void QtChatWindow::imChatSessionWillDieEventHandler(IMChatSession & sender) {
711        _lastReceivedMessageIndex.erase(sender.getId());
712}
713
714void QtChatWindow::sendSmsToActiveTabContact() {
715        // retrieve mobile phone number.
716        QString phoneNumber;
717        const QString contactId = getActiveTabContactId();
718        if (!contactId.isEmpty()) {
719                ContactProfile contactProfile =  getContactProfileFromContactId(contactId);
720                phoneNumber = QString::fromStdString(contactProfile.getMobilePhone());
721        }
722        ////
723
724        // configure & show the sms widget
725        QtSms * sms = _qtWengoPhone.getQtSms();
726        if (sms) {
727                sms->setPhoneNumber(phoneNumber);
728                sms->getWidget()->show();
729        }
730        ////
731}
732
733void QtChatWindow::sendFileToActiveTabContact() {
734
735        Config & config = ConfigManager::getInstance().getCurrentConfig();
736        QtFileTransfer * qtFileTransfer = _qtWengoPhone.getFileTransfer();
737        if (!qtFileTransfer) {
738                return;
739        }
740
741        QString filename = qtFileTransfer->getChosenFile();
742        if (!filename.isEmpty()) {
743                QFileInfo fileInfo(filename);
744                config.set(Config::FILETRANSFER_LASTUPLOADEDFILE_FOLDER_KEY, fileInfo.dir().absolutePath().toStdString());
745        }
746
747        if (!filename.isEmpty()) {
748                QtChatWidget * widget = getActiveTabWidget();
749                if (widget) {
750                        widget->sendFileToSession(filename);
751                }
752        }
753}
754
755void QtChatWindow::callActiveTabContact() {
756        const QString contactId = getActiveTabContactId();
757        if (!contactId.isEmpty()) {
758                QtContactListManager::getInstance()->startCall(contactId);
759                if (_qtWengoPhone.getWidget()->isMinimized()) {
760                        _qtWengoPhone.getWidget()->showNormal();
761                }
762#if defined(OS_WINDOWS)
763                SetForegroundWindow(_qtWengoPhone.getWidget()->winId());
764#endif
765        }
766}
767
768void QtChatWindow::showActiveTabContactInfo() {
769        const QString contactId = getActiveTabContactId();
770        if (!contactId.isEmpty()) {
771                ContactProfile contactProfile =  getContactProfileFromContactId(contactId);
772                QtProfileDetails qtProfileDetails(
773                                *_qtWengoPhone.getCWengoPhone().getCUserProfileHandler().getCUserProfile(),
774                contactProfile, this, tr("Edit Contact"));
775                if (qtProfileDetails.show()) {
776                        _qtWengoPhone.getCWengoPhone().getCUserProfileHandler().getCUserProfile()->getCContactList().updateContact(contactProfile);
777                }
778        }
779}
780
781void QtChatWindow::saveActiveTabChatHistory() {
782        QtChatWidget * chatWidget = getActiveTabWidget();
783        if (chatWidget) {
784                chatWidget->saveHistoryAsHtml();
785        }
786}
787
788void QtChatWindow::closeEvent(QCloseEvent *event) {
789        //closeAllTabs();
790}
791
792void QtChatWindow::closeAllTabs() {
793        LOG_DEBUG("closing all Chat tabs");
794        while(_tabWidget->count()>0) {
795                closeActiveTab();
796        }
797}
798
799static QTextEdit* getActiveTextEdit() {
800        return qobject_cast<QTextEdit*>(QApplication::focusWidget());
801}
802
803void QtChatWindow::updateClipboardActions() {
804        QTextEdit* textEdit = getActiveTextEdit();
805        bool modifiable = false;
806        bool hasSelection = false;
807        if (textEdit) {
808                hasSelection = !textEdit->textCursor().selectedText().isEmpty();
809                modifiable = !textEdit->isReadOnly();
810        }
811        bool clipboardFilled = !QApplication::clipboard()->text().isEmpty();
812        _ui->actionCut->setEnabled(modifiable && hasSelection);
813        _ui->actionCopy->setEnabled(hasSelection);
814        _ui->actionPaste->setEnabled(modifiable && clipboardFilled);
815}
816
817void QtChatWindow::cut() {
818        QTextEdit* textEdit = getActiveTextEdit();
819        if (textEdit) {
820                textEdit->cut();
821        }
822}
823
824void QtChatWindow::copy() {
825        QTextEdit* textEdit = getActiveTextEdit();
826        if (textEdit) {
827                textEdit->copy();
828        }
829}
830
831void QtChatWindow::paste() {
832        QTextEdit* textEdit = getActiveTextEdit();
833        if (textEdit) {
834                textEdit->paste();
835        }
836}
837
838bool QtChatWindow::eventFilter(QObject* object, QEvent* event) {
839        if (!qobject_cast<QTextEdit*>(object)) {
840                return false;
841        }
842
843        if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) {
844                updateClipboardActions();
845        }
846        return false;
847}
Note: See TracBrowser for help on using the repository browser.