~ubuntu-branches/ubuntu/edgy/psi/edgy

« back to all changes in this revision

Viewing changes to src/chatdlg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2004-06-15 00:10:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040615001041-enywb6pcpe4sjsw6
Tags: 0.9.2-1
* New upstream release
* Set KDEDIR for ./configure so kde specific files get installed
* Don't install libpsiwidgets.so. It got installed in /usr/share
  where it doesn't belong. May be included (at a better location)
  later.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
** chatdlg.cpp - a single window chat dialog
3
 
** Copyright (C) 2001, 2002  Justin Karneges
4
 
**
5
 
** This program is free software; you can redistribute it and/or
6
 
** modify it under the terms of the GNU General Public License
7
 
** as published by the Free Software Foundation; either version 2
8
 
** of the License, or (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
 
****************************************************************************/
 
1
/*
 
2
 * chatdlg.cpp - dialog for handling chats
 
3
 * Copyright (C) 2001, 2002  Justin Karneges
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (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 library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 */
20
20
 
21
21
#include"chatdlg.h"
22
22
 
 
23
#include<qlabel.h>
 
24
#include<qcursor.h>
 
25
#include<qlineedit.h>
 
26
#include<qtoolbutton.h>
 
27
#include<qlayout.h>
23
28
#include<qsplitter.h>
24
 
#include<qlayout.h>
 
29
#include<qtooltip.h>
 
30
#include<qtimer.h>
25
31
#include<qdatetime.h>
26
 
#include<qtooltip.h>
27
 
#include<qpalette.h>
 
32
#include<qlcdnumber.h>
 
33
#include"profiles.h"
 
34
#include"psiaccount.h"
 
35
#include"common.h"
 
36
#include"userlist.h"
 
37
#include"iconwidget.h"
 
38
#include"fancylabel.h"
 
39
#include"msgmle.h"
 
40
#include"iconselect.h"
 
41
#include"psicon.h"
28
42
 
29
43
#ifdef Q_WS_WIN
30
44
#include<windows.h>
31
45
#endif
32
46
 
33
 
 
34
 
ChatDlg::ChatDlg(UserListItem *item, const QString &_whoami, int _localStatus, QWidget *parent)
35
 
:QWidget(parent, "chatwindow"), UniqueWindow(TRUE, "ChatDlg", this, cleanJid(item->jid))
36
 
{
37
 
        //setWFlags(getWFlags() | WDestructiveClose);
38
 
        resize(option.sizeChatDlg);
39
 
 
40
 
        // save everything locally
41
 
        v_jid = item->jid;
42
 
        v_nick = item->nick;
43
 
        v_status = item->state;
44
 
 
45
 
        whoami = _whoami;
46
 
        localStatus = _localStatus;
47
 
        pending = 0;
48
 
        keepOpen = FALSE;
49
 
        selfDestruct = 0;
50
 
        flashTimer = 0;
51
 
 
52
 
        setIcon(anim_chat->base());
53
 
 
54
 
        QVBoxLayout *vb1 = new QVBoxLayout(this, 4);
55
 
        QSplitter *sp = new QSplitter(Vertical, this);
56
 
        vb1->addWidget(sp);
57
 
 
58
 
        // ---- single
59
 
        lo_single = new QWidget(sp);
60
 
        QVBoxLayout *lo_single_vb = new QVBoxLayout(lo_single, 4);
61
 
        QHBoxLayout *lo_single_hb = new QHBoxLayout(lo_single_vb);
62
 
        lb_statusIcon = new QLabel(lo_single);
63
 
        lo_single_hb->addWidget(lb_statusIcon);
64
 
 
65
 
        le_nick = new QLineEdit(lo_single);
66
 
        le_nick->setReadOnly(TRUE);
67
 
        le_nick->setFixedWidth(120);
68
 
        lo_single_hb->addWidget(le_nick);
69
 
 
70
 
        lo_single_hb->addSpacing(16);
71
 
 
72
 
        QLabel *lo_single_jid = new QLabel(tr("Jabber ID"), lo_single);
73
 
        lo_single_hb->addWidget(lo_single_jid);
74
 
        le_jid = new QLineEdit(lo_single);
75
 
        le_jid->setReadOnly(TRUE);
76
 
        le_jid->setText(v_jid);
77
 
        le_jid->setCursorPosition(0);
78
 
        QToolTip::add(le_jid, v_jid);
79
 
        lo_single_hb->addWidget(le_jid);
80
 
 
81
 
        t = new MsgMle(lo_single);
82
 
        connect(t, SIGNAL(linkClicked(const QString &)), SIGNAL(aOpenURL(const QString &)));
83
 
        t->setReadOnly(TRUE);
84
 
        t->setUndoRedoEnabled(FALSE);
85
 
        lo_single_vb->addWidget(t);
86
 
 
87
 
        //vb1->addWidget(t);
88
 
        QWidget *w = new QWidget(sp);
89
 
        //vb1->addWidget(w);
90
 
        QVBoxLayout *vb2 = new QVBoxLayout(w, 4);
91
 
        QHBoxLayout *hb1 = new QHBoxLayout(vb2);
92
 
 
93
 
        QToolButton *tb_clear = new QToolButton(w);
94
 
        tb_clear->setIconSet(QIconSet(*pix_chatclear));
95
 
        connect(tb_clear, SIGNAL(clicked()), SLOT(doClearButton()));
96
 
        QToolTip::add(tb_clear, tr("Clear chat window"));
97
 
        hb1->addWidget(tb_clear);
98
 
 
99
 
        hb1->addStretch(1);
100
 
 
101
 
        tb_info = new QToolButton(w);
102
 
        tb_info->setIconSet(QIconSet(*pix_info));
103
 
        connect(tb_info, SIGNAL(clicked()), SLOT(doInfo()));
104
 
        QToolTip::add(tb_info, tr("User info"));
105
 
        hb1->addWidget(tb_info);
106
 
 
107
 
        tb_history = new QToolButton(w);
108
 
        tb_history->setIconSet(QIconSet(*pix_history));
109
 
        connect(tb_history, SIGNAL(clicked()), SLOT(doHistory()));
110
 
        QToolTip::add(tb_history, tr("Message history"));
111
 
        hb1->addWidget(tb_history);
112
 
 
 
47
//----------------------------------------------------------------------------
 
48
// ChatDlg
 
49
//----------------------------------------------------------------------------
 
50
class ChatDlg::Private : public QObject
 
51
{
 
52
        Q_OBJECT
 
53
public:
 
54
        Private(ChatDlg *d) {
 
55
                dlg = d;
 
56
        }
 
57
 
 
58
        ChatDlg *dlg;
 
59
        Jid jid;
 
60
        PsiAccount *pa;
 
61
        QString dispNick;
 
62
        int status;
 
63
        QString statusString;
 
64
 
 
65
        ChatView *log;
 
66
        ChatEdit *mle;
 
67
 
 
68
        QLabel *lb_ident;
 
69
        IconLabel *lb_status;
 
70
        QLineEdit *le_jid;
 
71
        QLCDNumber *lcd_count;
 
72
        IconToolButton *tb_send, *tb_clear, *tb_history, *tb_info, *tb_pgp, *tb_icon, *tb_file;
 
73
        QPopupMenu *pm_settings;
 
74
 
 
75
        int pending;
 
76
        bool keepOpen, warnSend;
 
77
 
 
78
        QTimer *selfDestruct;
 
79
        QTimer *flashTimer;
 
80
        int flashCount;
 
81
 
 
82
        QString key;
 
83
        int transid;
 
84
        Message m;
 
85
        bool lastWasEncrypted;
 
86
        bool smallChat;
 
87
 
 
88
public slots:
 
89
        void addEmoticon(const Icon *icon) {
 
90
                if ( !dlg->isActiveWindow() )
 
91
                     return;
 
92
 
 
93
                QString text;
 
94
 
 
95
                QDict<QString> itext = icon->text();
 
96
                QDictIterator<QString> it ( itext );
 
97
                for ( ; it.current(); ++it) {
 
98
                        if ( it.current() && !it.current()->isEmpty() ) {
 
99
                                text = *(it.current()) + " ";
 
100
                                break;
 
101
                        }
 
102
                }
 
103
 
 
104
                if ( !text.isEmpty() )
 
105
                        mle->insert( text );
 
106
        }
 
107
 
 
108
        void addEmoticon(QString text) {
 
109
                if ( !dlg->isActiveWindow() )
 
110
                     return;
 
111
 
 
112
                mle->insert( text + " " );
 
113
        }
 
114
 
 
115
        void updateCounter() {
 
116
                lcd_count->display((int)mle->text().length());
 
117
        }
 
118
};
 
119
 
 
120
ChatDlg::ChatDlg(const Jid &jid, PsiAccount *pa)
 
121
:QWidget(0, 0)
 
122
{
 
123
        d = new Private(this);
 
124
        d->jid = jid;
 
125
        d->pa = pa;
 
126
 
 
127
        d->pending = 0;
 
128
        d->keepOpen = false;
 
129
        d->warnSend = false;
 
130
        d->selfDestruct = 0;
 
131
        d->flashTimer = 0;
 
132
        d->transid = -1;
 
133
        d->key = "";
 
134
        d->lastWasEncrypted = false;
 
135
 
 
136
        QVBoxLayout *vb1 = new QVBoxLayout(this, 4);
 
137
        QSplitter *sp = new QSplitter(Vertical, this);
 
138
        vb1->addWidget(sp);
 
139
 
 
140
        QWidget *sp_top = new QWidget(sp);
 
141
        // first row
 
142
        QVBoxLayout *vb2 = new QVBoxLayout(sp_top, 4);
 
143
        d->lb_ident = d->pa->accountLabel(sp_top, true);
 
144
        d->lb_ident->setSizePolicy(QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ));
 
145
 
 
146
        // second row
113
147
        QHBoxLayout *hb2 = new QHBoxLayout(vb2);
114
 
        mle = new ChatMle(w);
115
 
        mle->setMinimumHeight(48);
116
 
        hb2->addWidget(mle);
117
 
        //hb2->addStretch(1);
118
 
 
119
 
        /*(tb_send = new QToolButton(w);
120
 
        QPalette mypal = tb_send->palette();
121
 
        mypal.setColor(QColorGroup::Button, palette().color(QPalette::Normal, QColorGroup::Background));
122
 
        tb_send->setPalette(mypal);
123
 
 
124
 
        QIconSet is(*pix_chatsend1, QIconSet::Large);
125
 
        //is.setPixmap(*pix_chatsend1, QIconSet::Large, QIconSet::Normal);
126
 
        is.setPixmap(*pix_chatsend2, QIconSet::Large, QIconSet::Active);
127
 
        tb_send->setIconSet(is);
128
 
        tb_send->setAutoRaise(TRUE);
129
 
        tb_send->setUsesBigPixmap(TRUE);
130
 
        //tb_send->setFixedSize(56,56);
131
 
        connect(tb_send, SIGNAL(clicked()), SLOT(doSend()));
132
 
        hb2->addWidget(tb_send);*/
133
 
 
134
 
        vb2->activate();
135
 
 
 
148
        d->lb_status = new IconLabel(sp_top);
 
149
        d->lb_status->setIcon(IconsetFactory::iconPtr("status/noauth"));
 
150
        hb2->addWidget(d->lb_status);
 
151
        d->le_jid = new QLineEdit(sp_top);
 
152
        d->le_jid->setReadOnly(true);
 
153
        d->lcd_count = new QLCDNumber(sp_top);
 
154
        d->le_jid->setFocusPolicy(QWidget::NoFocus);
 
155
        QToolTip::add(d->lcd_count, tr("Message length"));
 
156
        d->lcd_count->setFixedWidth(50);
 
157
        hb2->addWidget(d->le_jid);
 
158
        hb2->addWidget(d->lcd_count);
 
159
        hb2->addWidget(d->lb_ident);
 
160
 
 
161
        // mid area
 
162
        d->log = new ChatView(sp_top);
 
163
        vb2->addWidget(d->log);
 
164
 
 
165
        QWidget *sp_bottom = new QWidget(sp);
 
166
        // tool area
 
167
        QVBoxLayout *vb3 = new QVBoxLayout(sp_bottom, 4);
 
168
        QHBoxLayout *hb3 = new QHBoxLayout(vb3);
 
169
        d->tb_clear = new IconToolButton(sp_bottom);
 
170
        connect(d->tb_clear, SIGNAL(clicked()), SLOT(doClearButton()));
 
171
        QToolTip::add(d->tb_clear, tr("Clear chat window"));
 
172
        hb3->addWidget(d->tb_clear);
 
173
        hb3->addStretch(1);
 
174
 
 
175
        // icon selector
 
176
        //connect(pa->psi()->iconSelectPopup(), SIGNAL(iconSelected(const Icon *)), d, SLOT(addEmoticon(const Icon *)));
 
177
        connect(pa->psi()->iconSelectPopup(), SIGNAL(textSelected(QString)), d, SLOT(addEmoticon(QString)));
 
178
        d->tb_icon = new IconToolButton(sp_bottom);
 
179
        d->tb_icon->setPopup(pa->psi()->iconSelectPopup());
 
180
        d->tb_icon->setPopupDelay (1);
 
181
        QToolTip::add(d->tb_icon, tr("Select icon"));
 
182
        hb3->addWidget(d->tb_icon);
 
183
 
 
184
        d->tb_file = new IconToolButton(sp_bottom);
 
185
        connect(d->tb_file, SIGNAL(clicked()), SLOT(doFile()));
 
186
        QToolTip::add(d->tb_file, tr("Send file"));
 
187
        hb3->addWidget(d->tb_file);
 
188
 
 
189
        d->tb_pgp = new IconToolButton(sp_bottom);
 
190
        d->tb_pgp->setToggleButton(true);
 
191
        QToolTip::add(d->tb_pgp, tr("Toggle encryption"));
 
192
        hb3->addWidget(d->tb_pgp);
 
193
 
 
194
        d->tb_info = new IconToolButton(sp_bottom);
 
195
        connect(d->tb_info, SIGNAL(clicked()), SLOT(doInfo()));
 
196
        QToolTip::add(d->tb_info, tr("User info"));
 
197
        hb3->addWidget(d->tb_info);
 
198
 
 
199
        d->tb_history = new IconToolButton(sp_bottom);
 
200
        connect(d->tb_history, SIGNAL(clicked()), SLOT(doHistory()));
 
201
        QToolTip::add(d->tb_history, tr("Message history"));
 
202
        hb3->addWidget(d->tb_history);
 
203
 
 
204
        d->mle = new ChatEdit(sp_bottom);
 
205
        vb3->addWidget(d->mle);
 
206
        connect(d->mle, SIGNAL(textChanged()), d, SLOT(updateCounter()));
 
207
 
 
208
        d->pm_settings=new QPopupMenu(this);
 
209
 
 
210
        connect(d->pm_settings, SIGNAL(aboutToShow()), SLOT(buildMenu()));
136
211
        QValueList<int> list;
137
 
        //list << 276;
138
 
        //list << 144;
139
212
        list << 324;
140
213
        list << 96;
141
214
        sp->setSizes(list);
142
215
 
143
 
        updateContact(item);
144
 
 
145
 
        mle->setTextFormat(PlainText);
146
 
        t->setTextFormat(RichText);
147
 
        mle->setFocus();
148
 
 
149
 
        //if(localStatus == STATUS_OFFLINE)
150
 
        //      tb_send->setEnabled(FALSE);
151
 
 
 
216
        d->status = -1;
 
217
        d->pa->dialogRegister(this, d->jid);
 
218
 
 
219
        updateContact(d->jid, true);
 
220
 
 
221
        d->smallChat=option.smallChats;
 
222
        X11WM_CLASS("chat");
152
223
        setLooks();
153
224
 
154
 
        QString msg = expandEntities(jidnick(v_jid, v_nick)) + " is " + status2txt(v_status);
155
 
        if(!item->statusString.isEmpty()) {
156
 
                msg += QString(" [%1]").arg(item->statusString);
157
 
        }
158
 
        appendSysMsg(msg);
 
225
        updatePGP();
 
226
        connect(d->pa, SIGNAL(pgpKeyChanged()), SLOT(updatePGP()));
 
227
        connect(d->pa, SIGNAL(encryptedMessageSent(int, bool)), SLOT(encryptedMessageSent(int, bool)));
 
228
#ifdef Q_WS_X11
 
229
        d->le_jid->setFocusPolicy(QWidget::NoFocus);
 
230
        d->log->setFocusPolicy(QWidget::NoFocus);
 
231
#endif
 
232
        d->mle->setFocus();
 
233
        resize(option.sizeChatDlg);
 
234
 
 
235
        UserListItem *u = d->pa->findFirstRelavent(d->jid);
 
236
        if(u && u->isSecure(d->jid.resource()))
 
237
                d->tb_pgp->setOn(true);
159
238
}
160
239
 
161
240
ChatDlg::~ChatDlg()
162
241
{
163
 
}
164
 
 
165
 
QSize ChatDlg::defaultSize()
166
 
{
167
 
        return QSize(380, 420);
168
 
}
169
 
 
170
 
void ChatDlg::resizeEvent(QResizeEvent *e)
171
 
{
172
 
        if(option.keepSizes)
173
 
                option.sizeChatDlg = e->size();
 
242
        d->pa->dialogUnregister(this);
 
243
 
 
244
        //QMimeSourceFactory *m = d->log->mimeSourceFactory();
 
245
        //d->log->setMimeSourceFactory(QMimeSourceFactory::defaultFactory());
 
246
        //delete m;
 
247
 
 
248
        delete d;
 
249
}
 
250
 
 
251
void ChatDlg::contextMenuEvent(QContextMenuEvent *)
 
252
{
 
253
                d->pm_settings->exec(QCursor::pos());
174
254
}
175
255
 
176
256
void ChatDlg::keyPressEvent(QKeyEvent *e)
177
257
{
178
 
        if(e->key() == Key_Escape)
179
 
                close();
180
 
        else if(e->key() == Key_Return || (e->key() == Key_S && (e->state() & AltButton)))
 
258
        if(e->key() == Key_Escape)
 
259
                close();
 
260
#ifdef Q_WS_MAC
 
261
        else if(e->key() == Key_W && e->state() & ControlButton)
 
262
                close();
 
263
#endif
 
264
        else if(e->key() == Key_Return || e->key() == Key_Enter || (e->key() == Key_S && (e->state() & AltButton)))
181
265
                doSend();
182
 
        else if(e->key() == Key_H && (e->state() & ControlButton))
183
 
                doHistory();
 
266
        else if(e->key() == Key_H && (e->state() & ControlButton))
 
267
                doHistory();
184
268
        else if(e->key() == Key_PageUp && (e->state() & ShiftButton))
185
 
                t->setContentsPos(t->contentsX(), t->contentsY() - t->visibleHeight()/2);
 
269
                d->log->setContentsPos(d->log->contentsX(), d->log->contentsY() - d->log->visibleHeight()/2);
186
270
        else if(e->key() == Key_PageDown && (e->state() & ShiftButton))
187
 
                t->setContentsPos(t->contentsX(), t->contentsY() + t->visibleHeight()/2);
188
 
        else
189
 
                e->ignore();
 
271
                d->log->setContentsPos(d->log->contentsX(), d->log->contentsY() + d->log->visibleHeight()/2);
 
272
        else
 
273
                e->ignore();
 
274
}
 
275
 
 
276
void ChatDlg::resizeEvent(QResizeEvent *e)
 
277
{
 
278
        if(option.keepSizes)
 
279
                option.sizeChatDlg = e->size();
190
280
}
191
281
 
192
282
void ChatDlg::closeEvent(QCloseEvent *e)
193
283
{
194
 
        if(keepOpen) {
 
284
        // really lame way of checking if we are encrypting
 
285
        if(!d->mle->isEnabled())
 
286
                return;
 
287
 
 
288
        if(d->keepOpen) {
195
289
                int n = QMessageBox::information(this, tr("Warning"), tr("A new chat message was just received.\nDo you still want to close the window?"), tr("&Yes"), tr("&No"));
196
290
                if(n != 0)
197
291
                        return;
207
301
                        setSelfDestruct(60 * 24);
208
302
        }
209
303
 
210
 
        mle->setFocus();
 
304
        if(d->pending > 0) {
 
305
                d->pending = 0;
 
306
                messagesRead(d->jid);
 
307
                updateCaption();
 
308
        }
 
309
        doFlash(false);
 
310
 
 
311
        d->mle->setFocus();
211
312
        e->accept();
212
313
}
213
314
 
222
323
 
223
324
        // if we're bringing it to the front, get rid of the '*' if necessary
224
325
        if(isActiveWindow()) {
225
 
                if(pending > 0) {
226
 
                        pending = 0;
227
 
                        updateCaption();
228
 
                }
229
 
                doFlash(FALSE);
230
 
 
231
 
                mle->setFocus();
232
 
        }
233
 
}
234
 
 
235
 
/* static */ ChatDlg *ChatDlg::find(const QString &xjid)
236
 
{
237
 
        return (ChatDlg *)UniqueWindowBank::find("ChatDlg", cleanJid(xjid));
238
 
}
239
 
 
240
 
void ChatDlg::localUpdate(const JabRosterEntry &e)
241
 
{
242
 
        localStatus = e.localStatus();
243
 
        whoami = e.nick;
244
 
 
245
 
        //if(localStatus == STATUS_OFFLINE)
246
 
        //      tb_send->setEnabled(FALSE);
247
 
        //else
248
 
        //      tb_send->setEnabled(TRUE);
249
 
}
250
 
 
251
 
void ChatDlg::updateContact(UserListItem *item)
252
 
{
253
 
        if(jidcmp(item->jid, v_jid)) {
254
 
                int oldstate = v_status;
255
 
 
256
 
                v_jid = item->jid;
257
 
                v_nick = item->nick;
258
 
                v_status = item->state;
259
 
 
260
 
                QString nick = jidnick(item->jid, item->nick);
261
 
 
262
 
                if(nick != le_nick->text()) {
263
 
                        le_nick->setText(nick);
264
 
                        le_nick->setCursorPosition(0);
265
 
                        QToolTip::add(le_nick, nick);
266
 
                }
267
 
                if(nick != caption()) {
268
 
                        dispNick = nick;
269
 
                        updateCaption();
270
 
                }
271
 
 
272
 
                lb_statusIcon->setPixmap(jidIsAgent(v_jid) ? transport2icon(v_jid, v_status) : status2pix(v_status));
273
 
 
274
 
                if(oldstate != v_status && !isHidden()) {
275
 
                        QString msg = expandEntities(jidnick(v_jid, v_nick)) + " is " + status2txt(v_status);
276
 
                        if(!item->statusString.isEmpty()) {
277
 
                                msg += QString(" [%1]").arg(item->statusString);
278
 
                        }
279
 
                        appendSysMsg(msg);
280
 
                }
281
 
        }
282
 
}
283
 
 
284
 
void ChatDlg::incomingMessage(const Message &msg)
285
 
{
286
 
        //if(!jidcmp(msg.from, v_jid))
287
 
        //      return;
288
 
 
289
 
        appendMessage(msg);
290
 
}
291
 
 
292
 
void ChatDlg::doSend()
293
 
{
294
 
        if(mle->text().isEmpty())
295
 
                return;
296
 
 
297
 
        if(mle->text() == "/clear") {
298
 
                mle->setText("");
299
 
                doClear();
300
 
                return;
301
 
        }
302
 
 
303
 
        if(localStatus == STATUS_OFFLINE)
304
 
                return;
305
 
 
306
 
        //if(!tb_send->isEnabled())
307
 
        //      return;
308
 
 
309
 
        Message msg;
310
 
        msg.to = v_jid;
311
 
        msg.type = MESSAGE_CHAT;
312
 
        if(option.outgoingAs == 1)
313
 
                msg.type = MESSAGE_NORM;
314
 
        msg.text = mle->text();
315
 
        msg.timeStamp = QDateTime::currentDateTime();
316
 
        msg.originLocal = TRUE;
317
 
        msg.late = FALSE;
318
 
 
319
 
        aSend(msg);
320
 
        appendMessage(msg);
321
 
 
322
 
        mle->setText("");
323
 
}
324
 
 
325
 
void ChatDlg::appendMessage(const Message &msg)
326
 
{
327
 
        QString who, color;
328
 
 
329
 
        if(msg.originLocal) {
330
 
                who = whoami;
331
 
                color = "#FF0000";
332
 
        }
333
 
        else {
334
 
                who = jidnick(v_jid, v_nick);
335
 
                color = "#0000FF";
336
 
        }
337
 
        if(msg.late)
338
 
                color = "#008000";
339
 
 
340
 
        QString timestr;
341
 
        QDateTime time = msg.timeStamp;
342
 
        timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
343
 
 
344
 
        int y = t->contentsHeight() - t->visibleHeight();
345
 
        if(y < 0)
346
 
                y = 0;
347
 
        bool atBottom = (t->contentsY() < y - 32) ? FALSE: TRUE;
348
 
 
349
 
        //t->setUpdatesEnabled(FALSE);
350
 
        if(msg.text.left(4) == "/me ") {
351
 
                QString txt = plain2rich(msg.text.mid(4));
352
 
                t->append(QString("<font color=\"%1\">").arg(color) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(expandEntities(who)) + txt + "</font><br>\n");
353
 
        }
354
 
        else {
355
 
                QString txt = linkify(plain2rich(msg.text));
356
 
                t->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] &lt;").arg(timestr) + expandEntities(who) + QString("&gt;</font> ") + txt + "<br>\n");
357
 
        }
358
 
 
359
 
        if(!(!msg.originLocal && !atBottom)) {
360
 
                // scroll after some event loop processing
361
 
                //QTimer::singleShot(0, this, SLOT(deferredScroll()));
362
 
                deferredScroll();
363
 
        }
364
 
        //if(msg.originLocal)
365
 
        //      deferredScroll();
366
 
 
367
 
        // if we're not active, notify the user by changing the title
368
 
        if(!isActiveWindow()) {
369
 
                ++pending;
370
 
                updateCaption();
371
 
                doFlash(TRUE);
372
 
        }
373
 
 
374
 
        if(!msg.originLocal) {
375
 
                keepOpen = TRUE;
376
 
                QTimer::singleShot(1000, this, SLOT(setKeepOpenFalse()));
377
 
        }
378
 
}
379
 
 
380
 
void ChatDlg::doHistory()
381
 
{
382
 
        aHistory(v_jid);
383
 
}
384
 
 
385
 
void ChatDlg::doAuth()
386
 
{
387
 
}
388
 
 
389
 
void ChatDlg::doAdd()
390
 
{
391
 
}
392
 
 
393
 
void ChatDlg::doInfo()
394
 
{
395
 
        aInfo(v_jid);
 
326
                if(d->pending > 0) {
 
327
                        d->pending = 0;
 
328
                        messagesRead(d->jid);
 
329
                        updateCaption();
 
330
                }
 
331
                doFlash(false);
 
332
 
 
333
                if(option.showCounter && !d->smallChat)
 
334
                        d->lcd_count->show();
 
335
                else
 
336
                        d->lcd_count->hide();
 
337
 
 
338
                d->mle->setFocus();
 
339
        }
 
340
}
 
341
 
 
342
const Jid & ChatDlg::jid() const
 
343
{
 
344
        return d->jid;
 
345
}
 
346
 
 
347
void ChatDlg::setJid(const Jid &jid)
 
348
{
 
349
        if(!jid.compare(d->jid)) {
 
350
                d->pa->dialogUnregister(this);
 
351
                d->jid = jid;
 
352
                d->pa->dialogRegister(this, d->jid);
 
353
                updateContact(d->jid, false);
 
354
        }
 
355
}
 
356
 
 
357
QSize ChatDlg::defaultSize()
 
358
{
 
359
        return QSize(380, 420);
 
360
}
 
361
 
 
362
void ChatDlg::updateContact(const Jid &jid, bool fromPresence)
 
363
{
 
364
        // if groupchat, only update if the resource matches
 
365
        if(d->pa->findGCContact(jid) && !d->jid.compare(jid))
 
366
                return;
 
367
 
 
368
        if(d->jid.compare(jid, false)) {
 
369
                QString rname = d->jid.resource();
 
370
                QPtrList<UserListItem> ul = d->pa->findRelavent(jid);
 
371
                UserListItem *u = 0;
 
372
                int status = -1;
 
373
                QString statusString, key;
 
374
                if(!ul.isEmpty()) {
 
375
                        u = ul.first();
 
376
                        if(rname.isEmpty()) {
 
377
                                // use priority
 
378
                                if(!u->isAvailable())
 
379
                                        status = STATUS_OFFLINE;
 
380
                                else {
 
381
                                        const UserResource &r = *u->userResourceList().priority();
 
382
                                        status = makeSTATUS(r.status());
 
383
                                        statusString = r.status().status();
 
384
                                        key = r.publicKeyID();
 
385
                                }
 
386
                        }
 
387
                        else {
 
388
                                // use specific
 
389
                                UserResourceList::ConstIterator rit = u->userResourceList().find(rname);
 
390
                                if(rit != u->userResourceList().end()) {
 
391
                                        status = makeSTATUS((*rit).status());
 
392
                                        statusString = (*rit).status().status();
 
393
                                        key = (*rit).publicKeyID();
 
394
                                }
 
395
                                else {
 
396
                                        status = STATUS_OFFLINE;
 
397
                                        statusString = u->lastUnavailableStatus().status();
 
398
                                        key = "";
 
399
                                }
 
400
                        }
 
401
                }
 
402
 
 
403
                bool statusChanged = false;
 
404
                if(d->status != status || d->statusString != statusString) {
 
405
                        statusChanged = true;
 
406
                        d->status = status;
 
407
                        d->statusString = statusString;
 
408
                }
 
409
 
 
410
                //if(statusChanged) {
 
411
                        if(status == -1 || !u)
 
412
                                d->lb_status->setIcon(IconsetFactory::iconPtr("status/noauth"));
 
413
                        else
 
414
                                d->lb_status->setIcon(is->statusPtr(jid, status));
 
415
                //}
 
416
 
 
417
                if(u)
 
418
                        QToolTip::add(d->lb_status, u->makeTip(true, false));
 
419
                else
 
420
                        QToolTip::remove(d->lb_status);
 
421
 
 
422
                if(u) {
 
423
                        QString name;
 
424
                        QString j;
 
425
                        if(rname.isEmpty())
 
426
                                j = u->jid().full();
 
427
                        else
 
428
                                j = u->jid().userHost() + '/' + rname;
 
429
 
 
430
                        if(!u->name().isEmpty())
 
431
                                name = u->name() + QString(" <%1>").arg(j);
 
432
                        else
 
433
                                name = j;
 
434
 
 
435
                        d->le_jid->setText(name);
 
436
                        d->le_jid->setCursorPosition(0);
 
437
                        QToolTip::add(d->le_jid, name);
 
438
 
 
439
                        d->dispNick = jidnick(u->jid().full(), u->name());
 
440
                        updateCaption();
 
441
 
 
442
                        d->key = key;
 
443
                        updatePGP();
 
444
 
 
445
                        if(fromPresence && statusChanged) {
 
446
                                QString msg = tr("%1 is %2").arg(expandEntities(d->dispNick)).arg(status2txt(d->status));
 
447
                                if(!statusString.isEmpty()) {
 
448
                                        QString ss = linkify(plain2rich(statusString));
 
449
                                        if(option.useEmoticons)
 
450
                                                ss = emoticonify(ss);
 
451
 
 
452
                                        msg += QString(" [%1]").arg(ss);
 
453
                                }
 
454
                                appendSysMsg(msg);
 
455
                        }
 
456
                }
 
457
        }
396
458
}
397
459
 
398
460
void ChatDlg::setLooks()
400
462
        // update the font
401
463
        QFont f;
402
464
        f.fromString(option.font[fChat]);
403
 
        t->setFont(f);
404
 
        mle->setFont(f);
405
 
 
406
 
        // update the status icon
407
 
        lb_statusIcon->setPixmap(jidIsAgent(v_jid) ? transport2icon(v_jid, v_status) : status2pix(v_status));
 
465
        d->log->setFont(f);
 
466
        d->mle->setFont(f);
 
467
 
 
468
        if (d->smallChat) {
 
469
                //hide the first row
 
470
                d->lb_ident->hide();
 
471
                d->lb_status->hide();
 
472
                d->le_jid->hide();
 
473
                d->lcd_count->hide();
 
474
                //hide the toolbar row
 
475
                d->tb_clear->hide();
 
476
                d->tb_file->hide();
 
477
                d->tb_pgp->hide();
 
478
                d->tb_info->hide();
 
479
                d->tb_history->hide();
 
480
        }
 
481
        else {
 
482
                //show the first row
 
483
                d->lb_ident->show();
 
484
                d->lb_status->show();
 
485
                d->le_jid->show();
 
486
                //show the toolbar row
 
487
                d->tb_clear->show();
 
488
                d->tb_file->show();
 
489
                d->tb_pgp->show();
 
490
                d->tb_info->show();
 
491
                d->tb_history->show();
 
492
        }
 
493
 
 
494
        if ( option.showCounter && !d->smallChat )
 
495
                d->lcd_count->show();
 
496
        else
 
497
                d->lcd_count->hide();
 
498
 
 
499
        if ( option.useEmoticons&& !d->smallChat )
 
500
                d->tb_icon->show();
 
501
        else
 
502
                d->tb_icon->hide();
 
503
 
 
504
        // update contact info
 
505
        d->status = -2; // sick way of making it redraw the status
 
506
        updateContact(d->jid, false);
408
507
 
409
508
        // toolbuttons
410
 
        tb_info->setIconSet(QIconSet(*pix_info));
 
509
        d->tb_clear->setIcon(IconsetFactory::iconPtr("psi/clearChat"));
 
510
        d->tb_info->setIcon(IconsetFactory::iconPtr("psi/vCard"));
 
511
        d->tb_history->setIcon(IconsetFactory::iconPtr("psi/history"));
 
512
        d->tb_icon->setIcon(IconsetFactory::iconPtr("psi/smile"));
 
513
        QIconSet i;
 
514
        i.setPixmap(IconsetFactory::icon("psi/cryptoNo"),  QIconSet::Automatic, QIconSet::Normal, QIconSet::Off);
 
515
        i.setPixmap(IconsetFactory::icon("psi/cryptoYes"), QIconSet::Automatic, QIconSet::Normal, QIconSet::On);
 
516
        d->tb_pgp->setIconSet( i );
 
517
        d->tb_file->setIcon(IconsetFactory::iconPtr("psi/upload"));
411
518
 
412
519
        // update the widget icon
413
 
        setIcon(anim_chat->base());
 
520
        setIcon(IconsetFactory::icon("psi/chat"));
414
521
}
415
522
 
416
523
void ChatDlg::optionsUpdate()
433
540
        }
434
541
}
435
542
 
436
 
void ChatDlg::appendSysMsg(const QString &str)
437
 
{
438
 
        QString timestr;
439
 
        QDateTime time = QDateTime::currentDateTime();
440
 
        timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
441
 
 
442
 
        //t->setUpdatesEnabled(FALSE);
443
 
        t->append(QString("<font color=\"#00A000\">[%1]").arg(timestr) + QString(" *** %1</font><br>\n").arg(str));
444
 
 
445
 
        deferredScroll();
446
 
 
447
 
        // scroll after some event loop processing
448
 
        //QTimer::singleShot(0, this, SLOT(deferredScroll()));
449
 
}
450
 
 
451
 
void ChatDlg::updateCaption()
452
 
{
453
 
        QString cap = "";
454
 
 
455
 
        if(pending > 0) {
456
 
                cap += "* ";
457
 
                if(pending > 1)
458
 
                        cap += QString("[%1] ").arg(pending);
459
 
        }
460
 
        cap += dispNick;
461
 
 
462
 
        // if taskbar flash, then we need to erase first and redo
463
 
#ifdef Q_WS_WIN
464
 
        bool on = FALSE;
465
 
        if(flashTimer)
466
 
                on = flashCount & 1;
467
 
        if(on)
468
 
                FlashWindow(winId(), TRUE);
469
 
#endif
470
 
        setCaption(cap);
471
 
#ifdef Q_WS_WIN
472
 
        if(on)
473
 
                FlashWindow(winId(), TRUE);
474
 
#endif
475
 
}
476
 
 
477
 
void ChatDlg::deferredScroll()
478
 
{
479
 
        //t->moveCursor(QTextEdit::MoveEnd, FALSE);
480
 
        t->scrollToBottom();
481
 
        //t->setUpdatesEnabled(TRUE);
482
 
        //t->update();
 
543
void ChatDlg::updatePGP()
 
544
{
 
545
        if(!d->pa->pgpKey().isEmpty()) {
 
546
                d->tb_pgp->setEnabled(true);
 
547
        }
 
548
        else {
 
549
                d->tb_pgp->setOn(false);
 
550
                d->tb_pgp->setEnabled(false);
 
551
        }
 
552
}
 
553
 
 
554
void ChatDlg::doInfo()
 
555
{
 
556
        aInfo(d->jid);
 
557
}
 
558
 
 
559
void ChatDlg::doHistory()
 
560
{
 
561
        aHistory(d->jid);
 
562
}
 
563
 
 
564
void ChatDlg::doFile()
 
565
{
 
566
        aFile(d->jid);
483
567
}
484
568
 
485
569
void ChatDlg::doClearButton()
491
575
 
492
576
void ChatDlg::doClear()
493
577
{
494
 
        t->setText("");
 
578
        d->log->setText("");
495
579
}
496
580
 
497
581
void ChatDlg::setKeepOpenFalse()
498
582
{
499
 
        keepOpen = FALSE;
 
583
        d->keepOpen = false;
 
584
}
 
585
 
 
586
void ChatDlg::setWarnSendFalse()
 
587
{
 
588
        d->warnSend = false;
500
589
}
501
590
 
502
591
void ChatDlg::setSelfDestruct(int minutes)
503
592
{
504
593
        if(minutes <= 0) {
505
 
                if(selfDestruct) {
506
 
                        delete selfDestruct;
507
 
                        selfDestruct = 0;
 
594
                if(d->selfDestruct) {
 
595
                        delete d->selfDestruct;
 
596
                        d->selfDestruct = 0;
508
597
                }
509
598
                return;
510
599
        }
511
600
 
512
 
        if(!selfDestruct) {
513
 
                selfDestruct = new QTimer(this);
514
 
                connect(selfDestruct, SIGNAL(timeout()), SLOT(deleteLater()));
515
 
        }
516
 
 
517
 
        selfDestruct->start(minutes * 60000);
 
601
        if(!d->selfDestruct) {
 
602
                d->selfDestruct = new QTimer(this);
 
603
                connect(d->selfDestruct, SIGNAL(timeout()), SLOT(deleteLater()));
 
604
        }
 
605
 
 
606
        d->selfDestruct->start(minutes * 60000);
 
607
}
 
608
 
 
609
void ChatDlg::updateCaption()
 
610
{
 
611
        QString cap = "";
 
612
 
 
613
        if(d->pending > 0) {
 
614
                cap += "* ";
 
615
                if(d->pending > 1)
 
616
                        cap += QString("[%1] ").arg(d->pending);
 
617
        }
 
618
        cap += d->dispNick;
 
619
 
 
620
        // if taskbar flash, then we need to erase first and redo
 
621
#ifdef Q_WS_WIN
 
622
        bool on = false;
 
623
        if(d->flashTimer)
 
624
                on = d->flashCount & 1;
 
625
        if(on)
 
626
                FlashWindow(winId(), true);
 
627
#endif
 
628
        setCaption(cap);
 
629
#ifdef Q_WS_WIN
 
630
        if(on)
 
631
                FlashWindow(winId(), true);
 
632
#endif
518
633
}
519
634
 
520
635
#ifdef Q_WS_WIN
521
636
void ChatDlg::doFlash(bool yes)
522
637
{
523
638
        if(yes) {
524
 
                if(flashTimer)
 
639
                if(d->flashTimer)
525
640
                        return;
526
 
                flashTimer = new QTimer(this);
527
 
                connect(flashTimer, SIGNAL(timeout()), SLOT(flashAnimate()));
528
 
                flashCount = 0;
 
641
                d->flashTimer = new QTimer(this);
 
642
                connect(d->flashTimer, SIGNAL(timeout()), SLOT(flashAnimate()));
 
643
                d->flashCount = 0;
529
644
                flashAnimate(); // kick the first one immediately
530
 
                flashTimer->start(500);
 
645
                d->flashTimer->start(500);
531
646
        }
532
647
        else {
533
 
                if(flashTimer) {
534
 
                        delete flashTimer;
535
 
                        flashTimer = 0;
536
 
                        FlashWindow(winId(), FALSE);
 
648
                if(d->flashTimer) {
 
649
                        delete d->flashTimer;
 
650
                        d->flashTimer = 0;
 
651
                        // comment this out to fix titlebar repaint on Windows??
 
652
                        //FlashWindow(winId(), false);
537
653
                }
538
654
        }
539
655
}
546
662
void ChatDlg::flashAnimate()
547
663
{
548
664
#ifdef Q_WS_WIN
549
 
        FlashWindow(winId(), TRUE);
550
 
        ++flashCount;
551
 
        //if(flashCount == 10)
552
 
        //      flashCount = 0;
553
 
        if(flashCount == 5)
554
 
                flashTimer->stop();
 
665
        FlashWindow(winId(), true);
 
666
        ++d->flashCount;
 
667
        if(d->flashCount == 5)
 
668
                d->flashTimer->stop();
555
669
#endif
556
670
}
557
671
 
 
672
void ChatDlg::doSend()
 
673
{
 
674
        if(!d->mle->isEnabled())
 
675
                return;
 
676
 
 
677
        if(d->mle->text().isEmpty())
 
678
                return;
 
679
 
 
680
        if(d->mle->text() == "/clear") {
 
681
                d->mle->setText("");
 
682
                doClear();
 
683
                return;
 
684
        }
 
685
 
 
686
        if(!d->pa->loggedIn())
 
687
                return;
 
688
 
 
689
        if(d->warnSend) {
 
690
                d->warnSend = false;
 
691
                int n = QMessageBox::information(this, tr("Warning"), tr(
 
692
                        "<p>Encryption was recently disabled by the remote contact.  "
 
693
                        "Are you sure you want to send this message without encryption?</p>"
 
694
                        ), tr("&Yes"), tr("&No"));
 
695
                if(n != 0)
 
696
                        return;
 
697
        }
 
698
 
 
699
        Message m(d->jid);
 
700
        m.setType("chat");
 
701
        m.setBody(d->mle->text());
 
702
        m.setTimeStamp(QDateTime::currentDateTime());
 
703
        if(d->tb_pgp->isOn())
 
704
                m.setWasEncrypted(true);
 
705
        d->m = m;
 
706
 
 
707
        if(d->tb_pgp->isOn()) {
 
708
                d->mle->setEnabled(false);
 
709
                d->transid = d->pa->sendMessageEncrypted(m);
 
710
                if(d->transid == -1) {
 
711
                        d->mle->setEnabled(true);
 
712
                        d->mle->setFocus();
 
713
                        return;
 
714
                }
 
715
        }
 
716
        else {
 
717
                aSend(m);
 
718
                doneSend();
 
719
        }
 
720
}
 
721
 
 
722
void ChatDlg::doneSend()
 
723
{
 
724
        appendMessage(d->m, true);
 
725
        d->mle->setText("");
 
726
}
 
727
 
 
728
void ChatDlg::encryptedMessageSent(int x, bool b)
 
729
{
 
730
        if(d->transid == -1)
 
731
                return;
 
732
        if(d->transid != x)
 
733
                return;
 
734
        d->transid = -1;
 
735
        if(b)
 
736
                doneSend();
 
737
        else
 
738
                QMessageBox::information(this, tr("Error"), tr("There was an error trying to send the message encrypted.\nCheck your OpenPGP application/settings."));
 
739
        d->mle->setEnabled(true);
 
740
        d->mle->setFocus();
 
741
}
 
742
 
 
743
void ChatDlg::incomingMessage(const Message &m)
 
744
{
 
745
        appendMessage(m);
 
746
}
 
747
 
 
748
void ChatDlg::appendSysMsg(const QString &str)
 
749
{
 
750
        QString timestr;
 
751
        QDateTime time = QDateTime::currentDateTime();
 
752
        //timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
 
753
        timestr = time.time().toString(LocalDate);
 
754
 
 
755
        int y = d->log->contentsHeight() - d->log->visibleHeight();
 
756
        if(y < 0)
 
757
                y = 0;
 
758
        bool atBottom = (d->log->contentsY() < y - 32) ? false: true;
 
759
 
 
760
        d->log->append(QString("<font color=\"#00A000\">[%1]").arg(timestr) + QString(" *** %1</font>").arg(str));
 
761
        if(atBottom)
 
762
                deferredScroll();
 
763
}
 
764
 
 
765
void ChatDlg::appendMessage(const Message &m, bool local)
 
766
{
 
767
        QString who, color;
 
768
 
 
769
        if(local) {
 
770
                who = d->pa->nick();
 
771
                color = "#FF0000";
 
772
        }
 
773
        else {
 
774
                who = d->dispNick;
 
775
                color = "#0000FF";
 
776
        }
 
777
        if(m.spooled())
 
778
                color = "#008000";
 
779
 
 
780
        // figure out the encryption state
 
781
        bool encChanged = false;
 
782
        bool encEnabled = false;
 
783
        if(d->lastWasEncrypted != m.wasEncrypted())
 
784
                encChanged = true;
 
785
        d->lastWasEncrypted = m.wasEncrypted();
 
786
        encEnabled = d->lastWasEncrypted;
 
787
 
 
788
        if(encChanged) {
 
789
                if(encEnabled) {
 
790
                        appendSysMsg(QString("<icon name=\"psi/cryptoYes\"> ") + tr("Encryption Enabled"));
 
791
                        if(!local)
 
792
                                d->tb_pgp->setOn(true);
 
793
                }
 
794
                else {
 
795
                        appendSysMsg(QString("<icon name=\"psi/cryptoNo\"> ") + tr("Encryption Disabled"));
 
796
                        if(!local) {
 
797
                                d->tb_pgp->setOn(false);
 
798
 
 
799
                                // enable warning
 
800
                                d->warnSend = true;
 
801
                                QTimer::singleShot(3000, this, SLOT(setWarnSendFalse()));
 
802
                        }
 
803
                }
 
804
        }
 
805
 
 
806
        QString timestr;
 
807
        QDateTime time = m.timeStamp();
 
808
        //timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
 
809
        timestr = time.time().toString(LocalDate);
 
810
 
 
811
        int y = d->log->contentsHeight() - d->log->visibleHeight();
 
812
        if(y < 0)
 
813
                y = 0;
 
814
        bool atBottom = (d->log->contentsY() < y - 32) ? false: true;
 
815
 
 
816
        bool emote = false;
 
817
        if(m.body().left(4) == "/me ")
 
818
                emote = true;
 
819
 
 
820
        QString txt;
 
821
        if(emote)
 
822
                txt = plain2rich(m.body().mid(4));
 
823
        else
 
824
                txt = plain2rich(m.body());
 
825
 
 
826
        txt = linkify(txt);
 
827
 
 
828
        if(option.useEmoticons)
 
829
                txt = emoticonify(txt);
 
830
 
 
831
        who = expandEntities(who);
 
832
 
 
833
        if(emote) {
 
834
                d->log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(who) + txt + "</font>");
 
835
        }
 
836
        else {
 
837
                if(option.chatSays)
 
838
                        d->log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] ").arg(timestr) + tr("%1 says:").arg(who) + "</font><br>" + txt);
 
839
                else
 
840
                        d->log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] &lt;").arg(timestr) + who + QString("&gt;</font> ") + txt);
 
841
        }
 
842
        if(!m.subject().isEmpty()) {
 
843
                d->log->append(QString("<b>") + tr("Subject:") + "</b> " + QString("%1").arg(expandEntities(m.subject())));
 
844
        }
 
845
        if(!m.urlList().isEmpty()) {
 
846
                UrlList urls = m.urlList();
 
847
                d->log->append(QString("<i>") + tr("-- Attached URL(s) --") + "</i>");
 
848
                for(QValueList<Url>::ConstIterator it = urls.begin(); it != urls.end(); ++it) {
 
849
                        const Url &u = *it;
 
850
                        d->log->append(QString("<b>") + tr("URL:") + "</b> " + QString("%1").arg( linkify(expandEntities(u.url())) ));
 
851
                        d->log->append(QString("<b>") + tr("Desc:") + "</b> " + QString("%1").arg(u.desc()));
 
852
                }
 
853
        }
 
854
 
 
855
        if(local || atBottom)
 
856
                deferredScroll();
 
857
 
 
858
        // if we're not active, notify the user by changing the title
 
859
        if(!isActiveWindow()) {
 
860
                ++d->pending;
 
861
                updateCaption();
 
862
                doFlash(true);
 
863
                if(option.raiseChatWindow)
 
864
                        bringToFront(this, false);
 
865
        }
 
866
        //else {
 
867
        //      messagesRead(d->jid);
 
868
        //}
 
869
 
 
870
        if(!local) {
 
871
                d->keepOpen = true;
 
872
                QTimer::singleShot(1000, this, SLOT(setKeepOpenFalse()));
 
873
        }
 
874
}
 
875
 
 
876
void ChatDlg::deferredScroll()
 
877
{
 
878
        QTimer::singleShot(250, this, SLOT(slotScroll()));
 
879
}
 
880
 
 
881
void ChatDlg::slotScroll()
 
882
{
 
883
        d->log->scrollToBottom();
 
884
}
 
885
 
 
886
void ChatDlg::toggleSmallChat()
 
887
{
 
888
        if (d->smallChat)
 
889
                d->smallChat=false;
 
890
        else
 
891
                d->smallChat=true;
 
892
        setLooks();
 
893
}
 
894
 
 
895
void ChatDlg::toggleEncryption()
 
896
{
 
897
        d->tb_pgp->setOn(1-d->tb_pgp->isOn());
 
898
}
 
899
 
 
900
void ChatDlg::buildMenu()
 
901
{
 
902
        d->pm_settings->clear();
 
903
        d->pm_settings->insertItem("Toggle Compact/Full Size", this, SLOT(toggleSmallChat()));
 
904
        d->pm_settings->insertItem(IconsetFactory::iconPtr("psi/clearChat")->pixmap(),"Clear Chat", this, SLOT(doClearButton()));
 
905
        d->pm_settings->insertSeparator();
 
906
        if (d->tb_pgp->isEnabled()) {
 
907
                if (d->tb_pgp->isOn())
 
908
                        d->pm_settings->insertItem(IconsetFactory::icon("psi/cryptoYes").pixmap(),"Toggle Encryption", this, SLOT(toggleEncryption()));
 
909
                else
 
910
                        d->pm_settings->insertItem(IconsetFactory::icon("psi/cryptoNo").pixmap(),"Toggle Encryption", this, SLOT(toggleEncryption()));
 
911
        }
 
912
        d->pm_settings->insertSeparator();
 
913
        d->pm_settings->insertItem(IconsetFactory::iconPtr("psi/vCard")->pixmap(),"View User Profile", this, SLOT(doInfo()));
 
914
        d->pm_settings->insertItem(IconsetFactory::iconPtr("psi/history")->pixmap(),"View History", this, SLOT(doHistory()));
 
915
}
 
916
#include "chatdlg.moc"