source: qutecom-2.2/qutecom/src/presentation/qt/profilebar/QtIMProfileWidget.cpp @ 678:2176c0ae8edb

Last change on this file since 678:2176c0ae8edb was 678:2176c0ae8edb, checked in by laurent, 3 years ago

remove undef proto in menu

File size: 15.4 KB
Line 
1/*
2 * QuteCom, a voice over Internet phone
3 * Copyright (C) 2010 Mbdsys
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 "QtIMProfileWidget.h"
21
22#include "ui_IMProfileWidget.h"
23
24#include "QtIMAccountPresenceMenuManager.h"
25
26#include <presentation/qt/QtIMAccountMonitor.h>
27#include <presentation/qt/QtIMAccountHelper.h>
28#include <presentation/qt/profile/QtProfileDetails.h>
29#include <presentation/qt/imaccount/QtIMAccountManager.h>
30#include <presentation/PFactory.h>
31
32#include <control/CQuteCom.h>
33#include <control/profile/CUserProfile.h>
34#include <control/profile/CUserProfileHandler.h>
35
36#include <model/profile/UserProfile.h>
37
38#include <util/Logger.h>
39#include <util/SafeDelete.h>
40#include <thread/ThreadEvent.h>
41
42#include <qtutil/LanguageChangeEventFilter.h>
43#include <qtutil/SafeConnect.h>
44#include <qtutil/PixmapMerging.h>
45
46#include <QtGui/QHBoxLayout>
47#include <QtGui/QMenu>
48#include <QtGui/QPainter>
49
50#include "imaccount/QtIMAccountSettings.h"
51
52const int ACCOUNT_ICON_WIDTH = 28;
53const int ACCOUNT_ICON_HEIGHT = 22;
54
55static QPixmap createAccountButtonPixmap(EnumIMProtocol::IMProtocol imProtocol, QtIMAccountMonitor::ConnectionState connectionState, EnumPresenceState::PresenceState presenceState) {
56        QString name = ":pics/protocols/";
57
58        // Append protocol name
59        switch (imProtocol) {
60        case EnumIMProtocol::IMProtocolMSN:
61                name += "msn";
62                break;
63
64        case EnumIMProtocol::IMProtocolYahoo:
65                name += "yahoo";
66                break;
67
68        case EnumIMProtocol::IMProtocolAIM:
69                name += "aim";
70                break;
71
72        case EnumIMProtocol::IMProtocolICQ:
73                name += "icq";
74                break;
75
76        case EnumIMProtocol::IMProtocolJabber:
77                name += "jabber";
78                break;
79       
80        case EnumIMProtocol::IMProtocolGoogleTalk:
81                name += "google-talk";
82                break;
83
84        case EnumIMProtocol::IMProtocolQuteCom:
85                name += "qutecom";
86                break;
87
88        case EnumIMProtocol::IMProtocolFaceBook:
89                name += "facebook";
90                break;
91
92        case EnumIMProtocol::IMProtocolMySpace:
93                name += "myspace";
94                break;
95
96        case EnumIMProtocol::IMProtocolSkype:
97                name += "skype";
98                break;
99
100        case EnumIMProtocol::IMProtocolTwitter:
101                name += "twitter";
102                break;
103       
104        case EnumIMProtocol::IMProtocolSIPSIMPLE:
105        case EnumIMProtocol::IMProtocolSIP:
106                name += "sip";
107                break;
108       
109        case EnumIMProtocol::IMProtocolUnknown:
110        case EnumIMProtocol::IMProtocolAll:
111                LOG_FATAL("Protocol should not be " + EnumIMProtocol::toString(imProtocol));
112        }
113
114        // Special cases: Disconnected or failure
115        if (connectionState == QtIMAccountMonitor::StateDisconnected
116                || connectionState == QtIMAccountMonitor::StateFailure) {
117                name += "_off";
118        }
119
120        // Load pix
121        name += ".png";
122        QPixmap protocolPix;
123        if (!protocolPix.load(name)) {
124                LOG_WARN(QString("Could not load icon " + name).toUtf8());
125                return QPixmap();
126        }
127
128        // Load overlay
129        QPixmap overlay;
130        // Append connection state
131        switch (connectionState) {
132        case QtIMAccountMonitor::StateConnected:
133                {
134                        QString presenceString = QString::fromUtf8(EnumPresenceState::toString(presenceState).c_str());
135                        overlay.load(
136                                QString(":pics/protocols/overlay_presence_%1.png").arg(presenceString)
137                                );
138                }
139                break;
140
141        case QtIMAccountMonitor::StateConnecting:
142                overlay.load(":pics/protocols/overlay_progress.png");
143                break;
144
145        case QtIMAccountMonitor::StateFailure:
146                overlay.load(":pics/protocols/overlay_error.png");
147                break;
148
149        case QtIMAccountMonitor::StateDisconnected:
150                break;
151        }
152
153        // Paint overlay
154        QPixmap pix(ACCOUNT_ICON_WIDTH, ACCOUNT_ICON_HEIGHT);
155        pix.fill(QColor(0,0,0,0));
156        QPainter painter(&pix);
157        painter.drawPixmap(pix.width() - protocolPix.width(), 0, protocolPix);
158        if (!overlay.isNull()) {
159                painter.drawPixmap(0, pix.height() - overlay.height(), overlay);
160        }
161        painter.end();
162
163        return pix;
164}
165
166
167QtIMProfileWidget::QtIMProfileWidget(QWidget * parent)
168        : QObject(parent)
169        , _cUserProfile(0)
170        , _qtImAccountMonitor(0) {
171
172        _imProfileWidget = new QWidget(parent);
173
174        _ui = new Ui::IMProfileWidget();
175        _ui->setupUi(_imProfileWidget);
176
177        // Init addIMAccountButton
178        // FIXME: This is copied from QtIMAccountManager ctor and should be
179        // factorized
180#ifdef MULTIIMWRAPPER
181        QMenu * addIMAccountMenu = new QMenu(_ui->addIMAccountButton);
182        SAFE_CONNECT(addIMAccountMenu, SIGNAL(triggered(QAction *)), SLOT(addIMAccount(QAction *)));
183
184        addIMAccountMenu->addAction(QIcon(":pics/protocols/msn.png"),
185                                QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolMSN));
186        addIMAccountMenu->addAction(QIcon(":pics/protocols/aim.png"),
187                                QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolAIM));
188        addIMAccountMenu->addAction(QIcon(":pics/protocols/icq.png"),
189                                QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolICQ));
190        addIMAccountMenu->addAction(QIcon(":pics/protocols/yahoo.png"),
191                                QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolYahoo));
192        addIMAccountMenu->addAction(QIcon(":pics/protocols/jabber.png"),
193                                QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolJabber));
194        addIMAccountMenu->addAction(QIcon(":pics/protocols/google-talk.png"),
195                                QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolGoogleTalk));
196
197#ifdef ENABLE_FACEBOOK
198                addIMAccountMenu->addAction(QIcon(":pics/protocols/facebook.png"),
199                                                                        QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolFaceBook));
200#endif
201               
202#ifdef ENABLE_MYSPACE   
203                addIMAccountMenu->addAction(QIcon(":pics/protocols/myspace.png"),
204                                                                        QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolMySpace));
205#endif
206               
207#ifdef ENABLE_SKYPE
208                addIMAccountMenu->addAction(QIcon(":pics/protocols/skype.png"),
209                                                                        QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolSkype));
210#endif
211               
212#ifdef ENABLE_TWITTER
213                addIMAccountMenu->addAction(QIcon(":pics/protocols/twitter.png"),
214                                                                        QtEnumIMProtocol::toString(QtEnumIMProtocol::IMProtocolTwitter));
215#endif
216               
217                _ui->addIMAccountButton->setPopupMode(QToolButton::InstantPopup);
218                _ui->addIMAccountButton->setMenu(addIMAccountMenu);
219#else
220                _ui->addIMAccountButton->hide();
221#endif
222
223        _ui->addIMAccountButton->setPopupMode(QToolButton::InstantPopup);
224        _ui->addIMAccountButton->setMenu(addIMAccountMenu);
225#else
226        _ui->addIMAccountButton->hide();
227#endif
228        ////
229
230        LANGUAGE_CHANGE(_imProfileWidget);
231
232        //Widget connections
233        SAFE_CONNECT(_ui->aliasLineEdit, SIGNAL(returnPressed()), SLOT(aliasTextChanged()));
234        SAFE_CONNECT(_ui->avatarButton, SIGNAL(clicked()), SLOT(changeAvatarClicked()));
235
236        //Init _accountFrame
237        _accountFrame = new QFrame();
238        _accountFrameLayout = new QHBoxLayout(_accountFrame);
239        _accountFrameLayout->setMargin(0);
240        _accountFrameLayout->setSpacing(0);
241
242        // Change size constraint to make sure the frame get resized when we add
243        // buttons to it
244        _accountFrameLayout->setSizeConstraint(QLayout::SetFixedSize);
245        _ui->accountScrollFrame->setChild(_accountFrame);
246        _ui->accountScrollFrame->setScrollStep(ACCOUNT_ICON_WIDTH / 2);
247        _imProfileWidget->setEnabled(false);
248}
249
250QtIMProfileWidget::~QtIMProfileWidget() {
251        OWSAFE_DELETE(_ui);
252}
253
254void QtIMProfileWidget::init(CUserProfile* cUserProfile, QtIMAccountMonitor* qtImAccountMonitor) {
255        _cUserProfile = cUserProfile;
256        _qtImAccountMonitor = qtImAccountMonitor;
257
258        //UserProfile changed event connection
259        _cUserProfile->getUserProfile().profileChangedEvent +=
260                boost::bind(&QtIMProfileWidget::profileChangedEventHandler, this);
261
262        // IMAccountMonitor connections
263        SAFE_CONNECT_TYPE(_qtImAccountMonitor, SIGNAL(imAccountAdded(QString)),
264                SLOT(addAccountButton(QString)), Qt::QueuedConnection);
265        SAFE_CONNECT_TYPE(_qtImAccountMonitor, SIGNAL(imAccountRemoved(QString)),
266                SLOT(removeAccountButton(QString)), Qt::QueuedConnection);
267        SAFE_CONNECT_TYPE(_qtImAccountMonitor, SIGNAL(imAccountUpdated(QString)),
268                SLOT(updateAccountButton(QString)), Qt::QueuedConnection);
269
270        _imProfileWidget->setEnabled(true);
271        updateWidgets();
272}
273
274QWidget * QtIMProfileWidget::getWidget() const {
275        return _imProfileWidget;
276}
277
278void QtIMProfileWidget::addAccountButton(QString imAccountId) {
279        // Check the button does not already exists
280        AccountIdToButton::const_iterator it = _accountIdToButton.find(imAccountId);
281        if (it != _accountIdToButton.end()) {
282                LOG_WARN("there is already a button for account " + imAccountId.toUtf8());
283                return;
284        }
285
286        // Look for the account
287        IMAccount * imAccount =
288        _cUserProfile->getUserProfile().getIMAccountManager().getIMAccount(std::string(imAccountId.toUtf8()));
289
290        if (!imAccount) {
291                LOG_WARN("Account does not exist");
292                return;
293        }
294
295        // Recreate all buttons. This is a bit brutal, but adding an account is not
296        // done very often, so it's not that bad.
297        // If it becomes necessary to just add the button, the
298        // addAccountButton(const IMAccount*) should be modified to insert the
299        // button at the correct position
300        createAccountButtons();
301}
302
303void QtIMProfileWidget::addAccountButton(const IMAccount* account) {
304        // Create button
305
306        QString id = QString::fromUtf8(account->getUUID().c_str());
307        AccountIdToButton::const_iterator it = _accountIdToButton.find(id);
308        if (it != _accountIdToButton.end()) {
309                LOG_WARN("there is already a button for account " + id.toUtf8());
310                return;
311        }
312
313        QToolButton* button = new QToolButton(_accountFrame);
314        button->setAutoRaise(true);
315        button->setIconSize(QSize(ACCOUNT_ICON_WIDTH, ACCOUNT_ICON_HEIGHT));
316        button->setPopupMode(QToolButton::InstantPopup);
317
318        // Add menu
319        QMenu* menu = new QMenu(button);
320        QAction* action = menu->addAction(QString::fromUtf8(account->getLogin().c_str()));
321        action->setEnabled(false);
322        menu->addAction(action);
323        menu->addSeparator();
324
325        QtIMAccountPresenceMenuManager* manager = new QtIMAccountPresenceMenuManager(menu, *_cUserProfile, account->getUUID());
326        manager->addPresenceActions(menu);
327        button->setMenu(menu);
328
329        // Integrate button
330        _accountFrameLayout->addWidget(button);
331
332        _accountIdToButton[id] = button;
333        updateAccountButton(id);
334}
335
336void QtIMProfileWidget::removeAccountButton(QString imAccountId) {
337        AccountIdToButton::iterator it = _accountIdToButton.find(imAccountId);
338        if (it == _accountIdToButton.end()) {
339                LOG_WARN("No button exists for account with id " + imAccountId.toUtf8());
340                return;
341        }
342        OWSAFE_DELETE(it->second);
343        _accountIdToButton.erase(it);
344        updateAddIMAccountButton();
345}
346
347void QtIMProfileWidget::updateAccountButton(QString imAccountId) {
348        // Look for the corresponding button
349        AccountIdToButton::const_iterator it = _accountIdToButton.find(imAccountId);
350        if (it == _accountIdToButton.end()) {
351                // Button does not exist
352                LOG_WARN("There is no button for account " + imAccountId.toUtf8());
353                return;
354        }
355        QToolButton* button = it->second;
356
357        // Look for the account
358        IMAccount * imAccount =
359        _cUserProfile->getUserProfile().getIMAccountManager().getIMAccount(std::string(imAccountId.toUtf8()));
360
361        if (!imAccount) {
362                // Account does not exist, this probably means the account has been
363                // removed
364                LOG_DEBUG("Account " + imAccountId.toUtf8() + " does not exist");
365                return;
366        }
367
368        // Get account info
369        EnumIMProtocol::IMProtocol imProtocol = imAccount->getProtocol();
370        QString protocolString = QString::fromUtf8(EnumIMProtocol::toString(imProtocol).c_str());
371        QString login = QString::fromUtf8(imAccount->getLogin().c_str());
372        EnumPresenceState::PresenceState presenceState = imAccount->getPresenceState();
373
374        OWSAFE_DELETE(imAccount);
375
376        QtIMAccountMonitor::IMAccountInfoAutoPtr info = _qtImAccountMonitor->getIMAccountInfo(imAccountId);
377        QtIMAccountMonitor::ConnectionState connectionState = info->connectionState();
378        QString message = info->message();
379        // Init button
380        QPixmap protocolPix = createAccountButtonPixmap(imProtocol, connectionState, presenceState);
381        button->setIcon(protocolPix);
382
383        QString toolTip = tr("%1 (%2)\n%3", "%1 is login, %2 is protocol, %3 is status")
384                .arg(login)
385                .arg(protocolString)
386                .arg(message);
387        button->setToolTip(toolTip);
388}
389
390void QtIMProfileWidget::changeAvatarClicked() {
391        QtProfileDetails qtProfileDetails(*_cUserProfile, _cUserProfile->getUserProfile(), _imProfileWidget, tr("Edit My Profile"));
392        //TODO UserProfile must be updated if QtProfileDetails was accepted
393        qtProfileDetails.changeUserProfileAvatar();
394        updateAvatar();
395}
396
397void QtIMProfileWidget::updateWidgets() {
398        if (!_cUserProfile) {
399                return;
400        }
401
402        if (!_cUserProfile->getUserProfile().getAlias().empty()) {
403                _ui->aliasLineEdit->setText(QString::fromUtf8(_cUserProfile->getUserProfile().getAlias().c_str()));
404        }
405
406        //aliasTextChanged();
407
408        updateAvatar();
409
410        createAccountButtons();
411}
412
413void QtIMProfileWidget::createAccountButtons() {
414        // Remove existing buttons
415        resetAccountButton();
416
417        // Sort accounts, using the same order as the meta presence
418        IMAccountList imAccountList = _cUserProfile->getUserProfile().getIMAccountManager().getIMAccountListCopy();
419        QtIMAccountHelper::QtIMAccountPtrVector imAccountPtrVector;
420        QtIMAccountHelper::copyListToPtrVector(imAccountList, &imAccountPtrVector);
421        std::sort(imAccountPtrVector.begin(), imAccountPtrVector.end(), QtIMAccountHelper::compareIMAccountPtrs);
422
423        // Updates IMAccounts icons status
424        QtIMAccountHelper::QtIMAccountPtrVector::const_iterator
425                it = imAccountPtrVector.begin(),
426                end = imAccountPtrVector.end();
427
428        for (; it!=end; ++it) {
429                addAccountButton(*it);
430        }
431
432        updateAddIMAccountButton();
433}
434
435// FIXME: This is copied from QtIMAccountManager ctor and should be
436// factorized
437void QtIMProfileWidget::addIMAccount(QAction * action) {
438        QString protocolName = action->text();
439        QtEnumIMProtocol::IMProtocol imProtocol = QtEnumIMProtocol::toIMProtocol(protocolName);
440        QtIMAccountSettings(_cUserProfile->getUserProfile(), imProtocol, _imProfileWidget);
441}
442
443void QtIMProfileWidget::updateAvatar() {
444        std::string backgroundPixmapFilename = ":/pics/avatar_background.png";
445        std::string foregroundPixmapData = _cUserProfile->getUserProfile().getIcon().getData();
446
447        _ui->avatarButton->setIcon(PixmapMerging::merge(foregroundPixmapData, backgroundPixmapFilename));
448}
449
450void QtIMProfileWidget::updateAddIMAccountButton() {
451        IMAccountList imAccountList = _cUserProfile->getUserProfile().getIMAccountManager().getIMAccountListCopy();
452        if (imAccountList.size() >= 2) {
453                _ui->addIMAccountButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
454        } else {
455                _ui->addIMAccountButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
456        }
457       
458}
459
460void QtIMProfileWidget::showImAccountManager() {
461        QtIMAccountManager imAccountManager(_cUserProfile->getUserProfile(),
462                true, _imProfileWidget);
463}
464
465void QtIMProfileWidget::aliasTextChanged() {
466        //Update alias text
467        std::string alias(_ui->aliasLineEdit->text().toUtf8().constData());
468        _cUserProfile->getUserProfile().setAlias(alias, NULL);
469
470        _ui->aliasLineEdit->update();
471}
472
473void QtIMProfileWidget::profileChangedEventHandler() {
474        typedef ThreadEvent0<void ()> MyThreadEvent;
475        MyThreadEvent * event = new MyThreadEvent(boost::bind(&QtIMProfileWidget::updateWidgets, this));
476        PFactory::postEvent(event);
477}
478
479void QtIMProfileWidget::languageChanged() {
480        _ui->retranslateUi(_imProfileWidget);
481        updateWidgets();
482        _ui->aliasLineEdit->setLayoutDirection(QApplication::layoutDirection());
483}
484
485void QtIMProfileWidget::resetAccountButton() 
486{
487        AccountIdToButton::iterator
488                buttonIt = _accountIdToButton.begin(),
489                buttonEnd = _accountIdToButton.end();
490        for (; buttonIt!=buttonEnd; ++buttonIt) {
491                delete buttonIt->second;
492        }
493        _accountIdToButton.clear();
494}
495
496void QtIMProfileWidget::reset() 
497{
498        resetAccountButton();
499
500        _cUserProfile = 0;
501        _qtImAccountMonitor = 0;
502}
Note: See TracBrowser for help on using the repository browser.