~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to src/groupchatdlg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *
19
19
 */
20
20
 
21
 
#include"groupchatdlg.h"
22
 
 
23
 
#include<qlabel.h>
24
 
#include<qlayout.h>
25
 
#include<qpushbutton.h>
26
 
#include<qgroupbox.h>
27
 
#include<qmessagebox.h>
28
 
#include<qtextedit.h>
29
 
#include<qsplitter.h>
30
 
#include<qtimer.h>
31
 
#include<qheader.h>
32
 
#include<qtoolbutton.h>
33
 
#include<qinputdialog.h>
34
 
#include<qguardedptr.h>
35
 
#include<qaction.h>
36
 
#include<qobjectlist.h>
37
 
#include<qpopupmenu.h>
38
 
#include<qcursor.h>
39
 
#include"psicon.h"
40
 
#include"psiaccount.h"
41
 
#include"userlist.h"
42
 
#include"statusdlg.h"
43
 
#include"busywidget.h"
44
 
#include"common.h"
45
 
#include"msgmle.h"
46
 
#include"iconwidget.h"
47
 
#include"iconselect.h"
48
 
#include"psitoolbar.h"
49
 
#include"iconaction.h"
 
21
// TODO: Move all the 'logic' of groupchats into MUCManager. See MUCManager
 
22
// for more details.
 
23
 
 
24
#include "groupchatdlg.h"
 
25
 
 
26
#include <qlabel.h>
 
27
#include <qlayout.h>
 
28
#include <qpushbutton.h>
 
29
#include <QToolBar>
 
30
#include <qmessagebox.h>
 
31
#include <QPainter>
 
32
#include <QColorGroup>
 
33
#include <qsplitter.h>
 
34
#include <qtimer.h>
 
35
#include <q3header.h>
 
36
#include <qtoolbutton.h>
 
37
#include <qinputdialog.h>
 
38
#include <qpointer.h>
 
39
#include <qaction.h>
 
40
#include <qobject.h>
 
41
#include <q3popupmenu.h>
 
42
#include <Q3TextDrag>
 
43
#include <qcursor.h>
 
44
#include <QCloseEvent>
 
45
#include <QEvent>
 
46
#include <QKeyEvent>
 
47
#include <QResizeEvent>
 
48
#include <QHBoxLayout>
 
49
#include <QFrame>
 
50
#include <QList>
 
51
#include <QVBoxLayout>
 
52
#include <QContextMenuEvent>
 
53
#include <QTextCursor>
 
54
#include <QTextDocument> // for Qt::escape()
 
55
 
 
56
#include "psicon.h"
 
57
#include "psiaccount.h"
 
58
#include "capsmanager.h"
 
59
#include "userlist.h"
 
60
#include "mucconfigdlg.h"
 
61
#include "textutil.h"
 
62
#include "statusdlg.h"
 
63
#include "xmpp_message.h"
 
64
#include "psiiconset.h"
 
65
#include "stretchwidget.h"
 
66
#include "mucmanager.h"
 
67
#include "busywidget.h"
 
68
#include "common.h"
 
69
#include "msgmle.h"
 
70
#include "iconwidget.h"
 
71
#include "iconselect.h"
 
72
#include "psitoolbar.h"
 
73
#include "iconaction.h"
 
74
#include "psitooltip.h"
 
75
#include "psioptions.h"
 
76
#include "shortcutmanager.h"
 
77
#include "psicontactlist.h"
 
78
#include "accountlabel.h"
 
79
#include "gcuserview.h"
50
80
 
51
81
#ifdef Q_WS_WIN
52
 
#include<windows.h>
 
82
#include <windows.h>
53
83
#endif
54
84
 
55
 
 
56
 
//----------------------------------------------------------------------------
57
 
// GCJoinDlg
58
 
//----------------------------------------------------------------------------
59
 
class GCJoinDlg::Private
60
 
{
61
 
public:
62
 
        Private() {}
63
 
 
64
 
        PsiCon *psi;
65
 
        PsiAccount *pa;
66
 
        AccountsComboBox *cb_ident;
67
 
        BusyWidget *busy;
68
 
        QStringList rl;
69
 
        Jid jid;
70
 
};
71
 
 
72
 
GCJoinDlg::GCJoinDlg(PsiCon *psi, PsiAccount *pa)
73
 
:GCJoinUI(0, 0, false, WDestructiveClose)
74
 
{
75
 
        d = new Private;
76
 
        d->psi = psi;
77
 
        d->pa = 0;
78
 
        d->psi->dialogRegister(this);
79
 
        d->busy = busy;
80
 
 
81
 
        updateIdentity(pa);
82
 
 
83
 
        d->cb_ident = d->psi->accountsComboBox(this,true);
84
 
        connect(d->cb_ident, SIGNAL(activated(PsiAccount *)), SLOT(updateIdentity(PsiAccount *)));
85
 
        d->cb_ident->setAccount(pa);
86
 
        replaceWidget(lb_ident, d->cb_ident);
87
 
 
88
 
        d->rl = d->psi->recentGCList();
89
 
        for(QStringList::ConstIterator it = d->rl.begin(); it != d->rl.end(); ++it) {
90
 
                Jid j(*it);
91
 
                QString s = tr("%1 on %2").arg(j.resource()).arg(j.userHost());
92
 
                cb_recent->insertItem(s);
93
 
        }
94
 
 
95
 
        setCaption(CAP(caption()));
96
 
        pb_join->setDefault(true);
97
 
        connect(pb_close, SIGNAL(clicked()), SLOT(close()));
98
 
        connect(pb_join, SIGNAL(clicked()), SLOT(doJoin()));
99
 
        connect(cb_recent, SIGNAL(activated(int)), SLOT(recent_activated(int)));
100
 
        if(d->rl.isEmpty()) {
101
 
                cb_recent->setEnabled(false);
102
 
                le_host->setFocus();
103
 
        }
104
 
        else
105
 
                recent_activated(0);
106
 
}
107
 
 
108
 
GCJoinDlg::~GCJoinDlg()
109
 
{
110
 
        if(d->psi)
111
 
                d->psi->dialogUnregister(this);
112
 
        if(d->pa)
113
 
                d->pa->dialogUnregister(this);
114
 
        delete d;
115
 
}
116
 
 
117
 
/*void GCJoinDlg::closeEvent(QCloseEvent *e)
118
 
{
119
 
        e->ignore();
120
 
        reject();
121
 
}*/
122
 
 
123
 
void GCJoinDlg::done(int r)
124
 
{
125
 
        if(d->busy->isActive()) {
126
 
                int n = QMessageBox::information(this, tr("Warning"), tr("Are you sure you want to cancel joining groupchat?"), tr("&Yes"), tr("&No"));
127
 
                if(n != 0)
128
 
                        return;
129
 
                d->pa->groupChatLeave(d->jid.host(), d->jid.user());
130
 
        }
131
 
        QDialog::done(r);
132
 
}
133
 
 
134
 
void GCJoinDlg::updateIdentity(PsiAccount *pa)
135
 
{
136
 
        if(d->pa)
137
 
                disconnect(d->pa, SIGNAL(disconnected()), this, SLOT(pa_disconnected()));
138
 
 
139
 
        d->pa = pa;
140
 
        pb_join->setEnabled(d->pa);
141
 
 
142
 
        if(!d->pa) {
143
 
                d->busy->stop();
144
 
                return;
145
 
        }
146
 
 
147
 
        connect(d->pa, SIGNAL(disconnected()), this, SLOT(pa_disconnected()));
148
 
}
149
 
 
150
 
void GCJoinDlg::pa_disconnected()
151
 
{
152
 
        if(d->busy->isActive()) {
153
 
                d->busy->stop();
154
 
        }
155
 
}
156
 
 
157
 
void GCJoinDlg::recent_activated(int x)
158
 
{
159
 
        int n = 0;
160
 
        bool found = false;
161
 
        QString str;
162
 
        for(QStringList::ConstIterator it = d->rl.begin(); it != d->rl.end(); ++it) {
163
 
                if(n == x) {
164
 
                        found = true;
165
 
                        str = *it;
166
 
                        break;
167
 
                }
168
 
                ++n;
169
 
        }
170
 
        if(!found)
171
 
                return;
172
 
 
173
 
        Jid j(str);
174
 
        le_host->setText(j.host());
175
 
        le_room->setText(j.user());
176
 
        le_nick->setText(j.resource());
177
 
}
178
 
 
179
 
void GCJoinDlg::doJoin()
180
 
{
181
 
        if(!d->pa->checkConnected(this))
182
 
                return;
183
 
 
184
 
        QString host = le_host->text();
185
 
        QString room = le_room->text();
186
 
        QString nick = le_nick->text();
187
 
 
188
 
        if(host.isEmpty() || room.isEmpty() || nick.isEmpty()) {
189
 
                QMessageBox::information(this, tr("Error"), tr("You must fill out the fields in order to join."));
190
 
                return;
191
 
        }
192
 
 
193
 
        Jid j = room + '@' + host + '/' + nick;
194
 
        if(!j.isValid()) {
195
 
                QMessageBox::information(this, tr("Error"), tr("You entered an invalid room name."));
196
 
                return;
197
 
        }
198
 
 
199
 
        if(!d->pa->groupChatJoin(host, room, nick)) {
200
 
                QMessageBox::information(this, tr("Error"), tr("You are in or joining this room already!"));
201
 
                return;
202
 
        }
203
 
 
204
 
        d->psi->dialogUnregister(this);
205
 
        d->jid = room + '@' + host + '/' + nick;
206
 
        d->pa->dialogRegister(this, d->jid);
207
 
 
208
 
        disableWidgets();
209
 
        d->busy->start();
210
 
}
211
 
 
212
 
void GCJoinDlg::disableWidgets()
213
 
{
214
 
        d->cb_ident->setEnabled(false);
215
 
        cb_recent->setEnabled(false);
216
 
        gb_info->setEnabled(false);
217
 
        pb_join->setEnabled(false);
218
 
}
219
 
 
220
 
void GCJoinDlg::enableWidgets()
221
 
{
222
 
        d->cb_ident->setEnabled(true);
223
 
        if(!d->rl.isEmpty())
224
 
                cb_recent->setEnabled(true);
225
 
        gb_info->setEnabled(true);
226
 
        pb_join->setEnabled(true);
227
 
}
228
 
 
229
 
void GCJoinDlg::joined()
230
 
{
231
 
        d->psi->recentGCAdd(d->jid.full());
232
 
        d->busy->stop();
233
 
 
234
 
        closeDialogs(this);
235
 
        deleteLater();
236
 
}
237
 
 
238
 
void GCJoinDlg::error(int, const QString &str)
239
 
{
240
 
        d->busy->stop();
241
 
        enableWidgets();
242
 
 
243
 
        pb_join->setFocus();
244
 
 
245
 
        d->pa->dialogUnregister(this);
246
 
        d->psi->dialogRegister(this);
247
 
 
248
 
        QMessageBox::information(this, tr("Error"), tr("Unable to join groupchat.\nReason: %1").arg(str));
249
 
}
250
 
 
251
 
 
252
 
//----------------------------------------------------------------------------
253
 
// GCUserView
254
 
//----------------------------------------------------------------------------
255
 
GCUserViewItem::GCUserViewItem(QListView *par)
256
 
:QListViewItem(par)
257
 
{
258
 
}
259
 
 
260
 
GCUserView::GCUserView(QWidget *parent, const char *name)
261
 
:QListView(parent, name), QToolTip(viewport())
262
 
{
263
 
        setResizeMode(QListView::AllColumns);
264
 
        setSorting(0);
265
 
        header()->hide();
266
 
        addColumn("");
267
 
 
268
 
        connect(this, SIGNAL(doubleClicked(QListViewItem *)), SLOT(qlv_doubleClicked(QListViewItem *)));
269
 
        connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)), SLOT(qlv_contextMenuRequested(QListViewItem *, const QPoint &, int)));
270
 
}
271
 
 
272
 
GCUserView::~GCUserView()
273
 
{
274
 
}
275
 
 
276
 
void GCUserView::updateAll()
277
 
{
278
 
        for(GCUserViewItem *i = (GCUserViewItem *)firstChild(); i; i = (GCUserViewItem *)i->nextSibling())
279
 
                i->setPixmap(0, is->status(i->s));
280
 
}
281
 
 
282
 
QStringList GCUserView::nickList() const
283
 
{
284
 
        QStringList list;
285
 
 
286
 
        for(QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling())
287
 
                list << lvi->text(0);
288
 
 
289
 
        qstringlistisort(list); // caseless sorting
290
 
        return list;
291
 
}
292
 
 
293
 
QListViewItem *GCUserView::findEntry(const QString &nick)
294
 
{
295
 
        for(QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling()) {
296
 
                if(lvi->text(0) == nick)
297
 
                        return lvi;
298
 
        }
299
 
        return 0;
300
 
}
301
 
 
302
 
void GCUserView::updateEntry(const QString &nick, const Status &s)
303
 
{
304
 
        GCUserViewItem *lvi = (GCUserViewItem *)findEntry(nick);
305
 
        if(!lvi) {
306
 
                lvi = new GCUserViewItem(this);
307
 
                lvi->setText(0, nick);
308
 
        }
309
 
 
310
 
        lvi->s = s;
311
 
        lvi->setPixmap(0, is->status(lvi->s));
312
 
}
313
 
 
314
 
void GCUserView::removeEntry(const QString &nick)
315
 
{
316
 
        QListViewItem *lvi = findEntry(nick);
317
 
        if(lvi)
318
 
                delete lvi;
319
 
}
320
 
 
321
 
void GCUserView::maybeTip(const QPoint &pos)
322
 
{
323
 
        GCUserViewItem *lvi = (GCUserViewItem *)itemAt(pos);
324
 
        if(!lvi)
325
 
                return;
326
 
 
327
 
        QRect r(itemRect(lvi));
328
 
 
329
 
        const QString &nick = lvi->text(0);
330
 
        const Status &s = lvi->s;
331
 
        UserListItem u;
332
 
        // SICK SICK SICK SICK
333
 
        u.setJid(((GCMainDlg *)topLevelWidget())->jid().withResource(nick));
334
 
        u.setName(nick);
335
 
 
336
 
        // make a resource so the contact appears online
337
 
        UserResource ur;
338
 
        ur.setName(nick);
339
 
        ur.setStatus(s);
340
 
        u.userResourceList().append(ur);
341
 
 
342
 
        tip(r, u.makeTip());
343
 
}
344
 
 
345
 
void GCUserView::qlv_doubleClicked(QListViewItem *i)
346
 
{
347
 
        GCUserViewItem *lvi = (GCUserViewItem *)i;
348
 
        if(!lvi)
349
 
                return;
350
 
 
351
 
        if(option.defaultAction == 0)
352
 
                action(lvi->text(0), lvi->s, 0);
353
 
        else
354
 
                action(lvi->text(0), lvi->s, 1);
355
 
}
356
 
 
357
 
void GCUserView::qlv_contextMenuRequested(QListViewItem *i, const QPoint &pos, int)
358
 
{
359
 
        GCUserViewItem *lvi = (GCUserViewItem *)i;
360
 
        if(!lvi)
361
 
                return;
362
 
 
363
 
        QPopupMenu *pm = new QPopupMenu;
364
 
        pm->insertItem(IconsetFactory::icon("psi/sendMessage"), tr("Send &message"), 0);
365
 
        pm->insertItem(IconsetFactory::icon("psi/start-chat"), tr("Open &chat window"), 1);
366
 
        pm->insertSeparator();
367
 
        //pm->insertItem(tr("Send &file"), 4);
368
 
        //pm->insertSeparator();
369
 
        pm->insertItem(tr("Check &Status"), 2);
370
 
        pm->insertItem(IconsetFactory::icon("psi/vCard"), tr("User &Info"), 3);
371
 
        int x = pm->exec(pos);
372
 
        delete pm;
373
 
 
374
 
        if(x == -1)
375
 
                return;
376
 
        action(lvi->text(0), lvi->s, x);
377
 
}
378
 
 
379
 
 
380
85
//----------------------------------------------------------------------------
381
86
// GCMainDlg
382
87
//----------------------------------------------------------------------------
389
94
                dlg = d;
390
95
                nickSeparator = ":";
391
96
                typingStatus = Typing_Normal;
 
97
                nonAnonymous = false;
 
98
                
 
99
                trackBar = false;
 
100
                oldTrackBarPosition = 0;
392
101
        }
393
102
 
394
103
        GCMainDlg *dlg;
395
104
        int state;
396
105
        PsiAccount *pa;
 
106
        MUCManager *mucManager;
397
107
        Jid jid;
398
 
        QString self;
399
 
        ChatView *te_log;
400
 
        ChatEdit *mle;
401
 
        QLineEdit *le_topic;
402
 
        GCUserView *lv_users;
403
 
        QPushButton *pb_topic;
404
 
        PsiToolBar *toolbar;
405
 
        IconAction *act_find, *act_clear, *act_icon;
406
 
        QPopupMenu *pm_settings;
407
 
        bool smallChat;
 
108
        QString self, prev_self;
 
109
        QString password;
 
110
        bool nonAnonymous;     // got status code 100 ?
 
111
        IconAction *act_find, *act_clear, *act_icon, *act_configure;
 
112
#ifdef WHITEBOARDING
 
113
        IconAction *act_whiteboard;
 
114
#endif
 
115
        QAction *act_send, *act_scrollup, *act_scrolldown, *act_close;
 
116
        Q3PopupMenu *pm_settings;
408
117
        int pending;
409
 
 
410
 
        bool trackBar;
411
 
        int  trackBarParagraph;
 
118
        bool connecting;
412
119
 
413
120
        QTimer *flashTimer;
414
121
        int flashCount;
416
123
        QStringList hist;
417
124
        int histAt;
418
125
 
419
 
        QGuardedPtr<GCFindDlg> findDlg;
 
126
        QPointer<GCFindDlg> findDlg;
420
127
        QString lastSearch;
421
128
 
 
129
        QPointer<MUCConfigDlg> configDlg;
 
130
        
 
131
public:
 
132
        bool trackBar;
 
133
protected:
 
134
        int  oldTrackBarPosition;
 
135
 
 
136
private:
 
137
        ChatEdit* mle() const { return dlg->ui_.mle->chatEdit(); }
 
138
        ChatView* te_log() const { return dlg->ui_.log; }
 
139
 
422
140
public slots:
423
 
        void addEmoticon(const Icon *icon) {
 
141
        void addEmoticon(const PsiIcon *icon) {
424
142
                if ( !dlg->isActiveWindow() )
425
143
                     return;
426
144
 
427
145
                QString text;
428
146
 
429
 
                QDict<QString> itext = icon->text();
430
 
                QDictIterator<QString> it ( itext );
431
 
                for ( ; it.current(); ++it) {
432
 
                        if ( it.current() && !it.current()->isEmpty() ) {
433
 
                                text = *(it.current()) + " ";
 
147
                QHash<QString,QString> itext = icon->text();
 
148
                for ( QHash<QString,QString>::ConstIterator it = itext.begin(); it != itext.end(); ++it) {
 
149
                        if (  !it->isEmpty() ) {
 
150
                                text = (*it) + " ";
434
151
                                break;
435
152
                        }
436
153
                }
437
154
 
438
155
                if ( !text.isEmpty() )
439
 
                        mle->insert( text );
 
156
                        mle()->insert( text );
440
157
        }
441
158
 
442
159
        void addEmoticon(QString text) {
443
160
                if ( !dlg->isActiveWindow() )
444
161
                     return;
445
162
 
446
 
                mle->insert( text + " " );
 
163
                mle()->insert( text + " " );
447
164
        }
448
165
 
449
166
        void deferredScroll() {
450
167
                //QTimer::singleShot(250, this, SLOT(slotScroll()));
451
 
                te_log->scrollToBottom();
 
168
                te_log()->scrollToBottom();
452
169
        }
453
170
 
454
171
protected slots:
455
172
        void slotScroll() {
456
 
                te_log->scrollToBottom();
457
 
        }
458
 
 
459
 
public:
 
173
                te_log()->scrollToBottom();
 
174
        }
 
175
 
 
176
public:
 
177
        bool internalFind(QString str, bool startFromBeginning = false)
 
178
        {
 
179
                if (startFromBeginning) {
 
180
                        QTextCursor cursor = te_log()->textCursor();
 
181
                        cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
 
182
                        cursor.clearSelection();
 
183
                        te_log()->setTextCursor(cursor);
 
184
                }
 
185
                
 
186
                bool found = te_log()->find(str);
 
187
                if(!found) {
 
188
                        if (!startFromBeginning)
 
189
                                return internalFind(str, true);
 
190
                        
 
191
                        return false;
 
192
                }
 
193
 
 
194
                return true;
 
195
        }
 
196
        
 
197
private:
 
198
        void removeTrackBar(QTextCursor &cursor)
 
199
        {
 
200
                if (oldTrackBarPosition) {
 
201
                        cursor.setPosition(oldTrackBarPosition, QTextCursor::KeepAnchor);
 
202
                        QTextBlockFormat blockFormat = cursor.blockFormat();
 
203
                        blockFormat.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
 
204
                        cursor.clearSelection();
 
205
                        cursor.setBlockFormat(blockFormat);
 
206
                }
 
207
        }
 
208
                
 
209
        void addTrackBar(QTextCursor &cursor)
 
210
        {
 
211
                cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
 
212
                oldTrackBarPosition = cursor.position();
 
213
                QTextBlockFormat blockFormat = cursor.blockFormat();
 
214
                blockFormat.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, QVariant(true));
 
215
                cursor.clearSelection();
 
216
                cursor.setBlockFormat(blockFormat);
 
217
        }
 
218
 
 
219
public:         
 
220
        void doTrackBar()
 
221
        {
 
222
                trackBar = false;
 
223
 
 
224
                // save position, because our manipulations could change it
 
225
                int scrollbarValue = te_log()->verticalScrollBar()->value();
 
226
 
 
227
                QTextCursor cursor = te_log()->textCursor();
 
228
                cursor.beginEditBlock();
 
229
                PsiTextView::Selection selection = te_log()->saveSelection(cursor);
 
230
 
 
231
                removeTrackBar(cursor);
 
232
                addTrackBar(cursor);
 
233
 
 
234
                te_log()->restoreSelection(cursor, selection);
 
235
                cursor.endEditBlock();
 
236
                te_log()->setTextCursor(cursor);
 
237
 
 
238
                te_log()->verticalScrollBar()->setValue(scrollbarValue);
 
239
        }
 
240
 
 
241
public:
 
242
        QString lastReferrer;  // contains nick of last person, who have said "yourNick: ..."
 
243
protected:              
460
244
        // Nick auto-completion code follows...
461
245
        enum TypingStatus {
462
246
                Typing_Normal = 0,
465
249
                Typing_MultipleSuggestions
466
250
        };
467
251
        TypingStatus typingStatus;
468
 
        QString lastReferrer;  // contains nick of last person, who have said "yourNick: ..."
469
252
        QString nickSeparator; // in case of "nick: ...", it equals ":"
470
253
        QStringList suggestedNicks;
471
254
        int  suggestedIndex;
489
272
                        nickText   = text.mid(beforeNick.length());
490
273
                }
491
274
 
492
 
                QStringList nicks = lv_users->nickList();
 
275
                QStringList nicks = dlg->ui_.lv_users->nickList();
493
276
                QStringList::Iterator it = nicks.begin();
494
277
                QStringList suggestedNicks;
495
278
                for ( ; it != nicks.end(); ++it) {
528
311
        QString insertNick(bool fromStart, QString beforeNick = "") {
529
312
                typingStatus = Typing_MultipleSuggestions;
530
313
                suggestedFromStart = fromStart;
531
 
                suggestedNicks = lv_users->nickList();
 
314
                suggestedNicks = dlg->ui_.lv_users->nickList();
532
315
                QStringList::Iterator it = suggestedNicks.begin();
533
316
                for ( ; it != suggestedNicks.end(); ++it)
534
317
                        *it = beforeNick + *it;
580
363
                return newText;
581
364
        }
582
365
 
 
366
public:         
583
367
        void doAutoNickInsertion() {
584
 
                int para, index;
585
 
                mle->getCursorPosition(&para, &index);
586
 
                QString paraText = mle->text(para);
 
368
                QTextCursor cursor = mle()->textCursor();
 
369
                
 
370
                // we need to get index from beginning of current block
 
371
                int index = cursor.position();
 
372
                cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
 
373
                index -= cursor.position();
 
374
                
 
375
                QString paraText = cursor.block().text();
587
376
                QString origText = paraText.left(index);
588
377
                QString newText;
589
 
 
 
378
                
590
379
                bool replaced = false;
591
380
 
592
381
                if ( typingStatus == Typing_MultipleSuggestions ) {
603
392
                        replaced = true;
604
393
                }
605
394
 
606
 
                if ( !para && !replaced ) {
 
395
                if ( !cursor.block().position() && !replaced ) {
607
396
                        if ( !index && typingStatus == Typing_TabbingNicks ) {
608
397
                                newText = insertNick(true, "");
609
398
                                replaced = true;
624
413
                }
625
414
 
626
415
                if ( replaced ) {
627
 
                        mle->setUpdatesEnabled( false );
628
 
                        QString newParaText = newText + paraText.mid(index, paraText.length() - index - 1);
629
 
                        mle->insertParagraph(newParaText, para);
630
 
                        mle->removeParagraph(para+1);
631
 
                        mle->setCursorPosition(para, newText.length());
632
 
                        mle->setUpdatesEnabled( true );
633
 
                        mle->viewport()->update();
 
416
                        mle()->setUpdatesEnabled( false );
 
417
                        int position = cursor.position() + newText.length();
 
418
                        
 
419
                        cursor.beginEditBlock();
 
420
                        cursor.select(QTextCursor::BlockUnderCursor);
 
421
                        cursor.insertText(newText + paraText.mid(index, paraText.length() - index));
 
422
                        cursor.setPosition(position, QTextCursor::KeepAnchor);
 
423
                        cursor.clearSelection();
 
424
                        cursor.endEditBlock();
 
425
                        mle()->setTextCursor(cursor);
 
426
                        
 
427
                        mle()->setUpdatesEnabled( true );
 
428
                        mle()->viewport()->update();
634
429
                }
635
430
        }
636
431
 
637
432
        bool eventFilter( QObject *obj, QEvent *ev ) {
638
 
                if ( obj == mle && ev->type() == QEvent::KeyPress ) {
 
433
                if (te_log()->handleCopyEvent(obj, ev, mle()))
 
434
                        return true;
 
435
        
 
436
                if ( obj == mle() && ev->type() == QEvent::KeyPress ) {
639
437
                        QKeyEvent *e = (QKeyEvent *)ev;
640
438
 
641
 
                        if ( e->key() == Key_Tab ) {
 
439
                        if ( e->key() == Qt::Key_Tab ) {
642
440
                                switch ( typingStatus ) {
643
441
                                case Typing_Normal:
644
442
                                        typingStatus = Typing_TabPressed;
664
462
};
665
463
 
666
464
GCMainDlg::GCMainDlg(PsiAccount *pa, const Jid &j)
667
 
:AdvancedWidget<QWidget>(0, 0, WDestructiveClose)
 
465
        : AdvancedWidget<QWidget>(0)
668
466
{
 
467
        setAttribute(Qt::WA_DeleteOnClose);
 
468
        if ( option.brushedMetal )
 
469
                setAttribute(Qt::WA_MacMetalStyle);
669
470
        nicknumber=0;
670
471
        d = new Private(this);
671
472
        d->pa = pa;
672
473
        d->jid = j.userHost();
673
 
        d->self = j.resource();
 
474
        d->self = d->prev_self = j.resource();
674
475
        d->pa->dialogRegister(this, d->jid);
675
476
        connect(d->pa, SIGNAL(updatedActivity()), SLOT(pa_updatedActivity()));
 
477
        d->mucManager = new MUCManager(d->pa->client(),d->jid);
 
478
 
 
479
        options_ = PsiOptions::instance();
676
480
 
677
481
        d->pending = 0;
678
482
        d->flashTimer = 0;
 
483
        d->connecting = false;
679
484
 
680
485
        d->histAt = 0;
681
486
        d->findDlg = 0;
682
 
 
683
 
        d->trackBar = false;
684
 
        d->trackBarParagraph = 0;
 
487
        d->configDlg = 0;
685
488
 
686
489
        d->state = Private::Connected;
687
490
 
 
491
        setAcceptDrops(true);
 
492
 
688
493
#ifndef Q_WS_MAC
689
 
        setIcon(IconsetFactory::icon("psi/groupChat"));
 
494
        setWindowIcon(IconsetFactory::icon("psi/groupChat").icon());
690
495
#endif
691
496
 
692
 
        QVBoxLayout *dlg_layout = new QVBoxLayout(this, 4);
693
 
 
694
 
        QWidget *vsplit;
695
 
        if ( !option.chatLineEdit ) {
696
 
                vsplit = new QSplitter(this);
697
 
                ((QSplitter *)vsplit)->setOrientation( QSplitter::Vertical );
698
 
                dlg_layout->addWidget(vsplit);
699
 
        }
700
 
        else
701
 
                vsplit = this;
702
 
 
703
 
        // --- top part ---
704
 
        QWidget *sp_top = new QWidget(vsplit);
705
 
        sp_top->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
706
 
        if ( option.chatLineEdit )
707
 
                dlg_layout->addWidget( sp_top );
708
 
        QVBoxLayout *vb_top = new QVBoxLayout(sp_top, 0, 4);
709
 
 
710
 
        // top row
711
 
        QWidget *sp_top_top = new QWidget( sp_top );
712
 
        vb_top->addWidget( sp_top_top );
713
 
        QHBoxLayout *hb_top = new QHBoxLayout( sp_top_top, 0, 4 );
714
 
 
715
 
        d->pb_topic = new QPushButton(tr("Topic:"), sp_top_top);
716
 
        connect(d->pb_topic, SIGNAL(clicked()), SLOT(doTopic()));
717
 
        hb_top->addWidget(d->pb_topic);
718
 
 
719
 
        d->le_topic = new QLineEdit(sp_top_top);
720
 
        d->le_topic->setReadOnly(true);
721
 
        hb_top->addWidget(d->le_topic);
722
 
 
723
 
        d->act_find = new IconAction(tr("Find"), "psi/search", tr("&Find"), CTRL+Key_F, this);
 
497
        ui_.setupUi(this);
 
498
        ui_.lb_ident->setAccount(d->pa);
 
499
        ui_.lb_ident->setShowJid(false);
 
500
 
 
501
        connect(ui_.pb_topic, SIGNAL(clicked()), SLOT(doTopic()));
 
502
        PsiToolTip::install(ui_.le_topic);
 
503
 
 
504
        connect(d->pa->psi(), SIGNAL(accountCountChanged()), this, SLOT(updateIdentityVisibility()));
 
505
        updateIdentityVisibility();
 
506
 
 
507
        d->act_find = new IconAction(tr("Find"), "psi/search", tr("&Find"), 0, this);
724
508
        connect(d->act_find, SIGNAL(activated()), SLOT(openFind()));
725
 
        d->act_find->addTo( sp_top_top );
726
 
 
727
 
        QLabel *lb_ident = d->pa->accountLabel(sp_top_top, true);
728
 
        lb_ident->setSizePolicy(QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ));
729
 
        hb_top->addWidget(lb_ident);
730
 
 
731
 
        // bottom row
732
 
        QSplitter *hsp = new QSplitter(sp_top);
733
 
        hsp->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
734
 
        vb_top->addWidget(hsp);
735
 
        hsp->setOrientation(QSplitter::Horizontal);
736
 
 
737
 
        d->te_log = new ChatView(hsp);
738
 
        d->te_log->setTextFormat( RichText );
 
509
        ui_.tb_find->setDefaultAction(d->act_find);
 
510
 
 
511
        ui_.tb_emoticons->setIcon(IconsetFactory::icon("psi/smile").icon());
 
512
 
739
513
#ifdef Q_WS_MAC
740
 
        connect(d->te_log,SIGNAL(selectionChanged()),SLOT(logSelectionChanged()));
741
 
        d->te_log->setFocusPolicy(QWidget::NoFocus);
 
514
        connect(ui_.log, SIGNAL(selectionChanged()), SLOT(logSelectionChanged()));
742
515
#endif
743
516
 
744
 
        d->lv_users = new GCUserView(hsp);
745
 
        d->lv_users->setMinimumWidth(20);
746
 
        connect(d->lv_users, SIGNAL(action(const QString &, const Status &, int)), SLOT(lv_action(const QString &, const Status &, int)));
747
 
 
748
 
        // --- bottom part ---
749
 
        QWidget *sp_bottom = new QWidget(vsplit);
750
 
        sp_bottom->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Maximum );
751
 
        if ( option.chatLineEdit )
752
 
                dlg_layout->addWidget( sp_bottom );
753
 
        QVBoxLayout *vb_bottom = new QVBoxLayout(sp_bottom);
754
 
 
755
 
        // toolbar
 
517
        ui_.lv_users->setMainDlg(this);
 
518
        connect(ui_.lv_users, SIGNAL(action(const QString &, const Status &, int)), SLOT(lv_action(const QString &, const Status &, int)));
 
519
 
756
520
        d->act_clear = new IconAction (tr("Clear chat window"), "psi/clearChat", tr("Clear chat window"), 0, this);
757
521
        connect( d->act_clear, SIGNAL( activated() ), SLOT( doClearButton() ) );
 
522
        
 
523
        d->act_configure = new IconAction(tr("Configure Room"), "psi/configure-room", tr("&Configure Room"), 0, this);
 
524
        connect(d->act_configure, SIGNAL(activated()), SLOT(configureRoom()));
 
525
 
 
526
#ifdef WHITEBOARDING
 
527
        d->act_whiteboard = new IconAction(tr("Open a whiteboard"), "psi/whiteboard", tr("Open a &whiteboard"), 0, this);
 
528
        connect(d->act_whiteboard, SIGNAL(activated()), SLOT(openWhiteboard()));
 
529
#endif
758
530
 
759
531
        connect(pa->psi()->iconSelectPopup(), SIGNAL(textSelected(QString)), d, SLOT(addEmoticon(QString)));
760
532
        d->act_icon = new IconAction( tr( "Select icon" ), "psi/smile", tr( "Select icon" ), 0, this );
761
 
        d->act_icon->setPopup( pa->psi()->iconSelectPopup() );
762
 
 
763
 
        d->toolbar = new PsiToolBar( tr("Groupchat toolbar"), 0, sp_bottom );
764
 
        d->toolbar->setCustomizeable( false ); // it isn't ready now, and we don't want segfaults
765
 
        d->toolbar->setFrameShape( QFrame::NoFrame );
766
 
        vb_bottom->addWidget( d->toolbar );
767
 
 
768
 
        d->act_clear->addTo( d->toolbar );
769
 
        d->toolbar->setStretchableWidget(new StretchWidget(d->toolbar));
770
 
        d->act_icon->addTo( d->toolbar );
771
 
 
772
 
        // chat edit
773
 
        if ( !option.chatLineEdit ) {
774
 
                d->mle = new ChatEdit(sp_bottom);
775
 
                vb_bottom->addWidget(d->mle);
776
 
        }
777
 
        else {
778
 
                QHBoxLayout *hb5 = new QHBoxLayout( dlg_layout );
779
 
                d->mle = new LineEdit( vsplit );
780
 
#ifdef Q_WS_MAC
781
 
                hb5->addSpacing( 16 );
782
 
#endif
783
 
                hb5->addWidget( d->mle );
784
 
#ifdef Q_WS_MAC
785
 
                hb5->addSpacing( 16 );
786
 
#endif
787
 
        }
788
 
 
789
 
        d->mle->installEventFilter( d );
790
 
 
791
 
        d->pm_settings = new QPopupMenu(this);
 
533
        d->act_icon->setMenu( pa->psi()->iconSelectPopup() );
 
534
        ui_.tb_emoticons->setMenu(pa->psi()->iconSelectPopup());
 
535
 
 
536
        ui_.toolbar->setIconSize(QSize(16,16));
 
537
        ui_.toolbar->addAction(d->act_clear);
 
538
        ui_.toolbar->addAction(d->act_configure);
 
539
#ifdef WHITEBOARDING
 
540
        ui_.toolbar->addAction(d->act_whiteboard);
 
541
#endif
 
542
        ui_.toolbar->addWidget(new StretchWidget(ui_.toolbar));
 
543
        ui_.toolbar->addAction(d->act_icon);
 
544
        ui_.toolbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum);
 
545
 
 
546
        // Common actions
 
547
        d->act_send = new QAction(this);
 
548
        addAction(d->act_send);
 
549
        connect(d->act_send,SIGNAL(activated()), SLOT(mle_returnPressed()));
 
550
        d->act_close = new QAction(this);
 
551
        addAction(d->act_close);
 
552
        connect(d->act_close,SIGNAL(activated()), SLOT(close()));
 
553
        d->act_scrollup = new QAction(this);
 
554
        addAction(d->act_scrollup);
 
555
        connect(d->act_scrollup,SIGNAL(activated()), SLOT(scrollUp()));
 
556
        d->act_scrolldown = new QAction(this);
 
557
        addAction(d->act_scrolldown);
 
558
        connect(d->act_scrolldown,SIGNAL(activated()), SLOT(scrollDown()));
 
559
 
 
560
        connect(ui_.mle, SIGNAL(textEditCreated(QTextEdit*)), SLOT(chatEditCreated()));
 
561
        chatEditCreated();
 
562
 
 
563
        d->pm_settings = new Q3PopupMenu(this);
792
564
        connect(d->pm_settings, SIGNAL(aboutToShow()), SLOT(buildMenu()));
 
565
        ui_.tb_actions->setMenu(d->pm_settings);
793
566
 
794
567
        // resize the horizontal splitter
795
 
        QValueList<int> list;
 
568
        QList<int> list;
796
569
        list << 500;
797
570
        list << 80;
798
 
        hsp->setSizes(list);
 
571
        ui_.hsplitter->setSizes(list);
799
572
 
800
573
        list.clear();
801
574
        list << 324;
802
575
        list << 10;
803
 
        if ( !option.chatLineEdit )
804
 
                (( QSplitter *)vsplit)->setSizes(list);
805
 
 
806
 
        resize(580,420);
807
 
 
808
 
        d->smallChat = option.smallChats;
 
576
        ui_.vsplitter->setSizes(list);
 
577
 
809
578
        X11WM_CLASS("groupchat");
810
579
 
811
 
        d->mle->setFocus();
 
580
        ui_.mle->chatEdit()->setFocus();
 
581
        resize(PsiOptions::instance()->getOption("options.ui.muc.size").toSize());
 
582
 
 
583
        // Connect signals from MUC manager
 
584
        connect(d->mucManager,SIGNAL(action_error(MUCManager::Action, int, const QString&)), SLOT(action_error(MUCManager::Action, int, const QString&)));
812
585
 
813
586
        setLooks();
 
587
        setShortcuts();
814
588
        updateCaption();
 
589
        setConnecting();
815
590
}
816
591
 
817
592
GCMainDlg::~GCMainDlg()
819
594
        if(d->state != Private::Idle)
820
595
                d->pa->groupChatLeave(d->jid.host(), d->jid.user());
821
596
 
822
 
        //QMimeSourceFactory *m = d->te_log->mimeSourceFactory();
823
 
        //d->te_log->setMimeSourceFactory(0);
 
597
        //QMimeSourceFactory *m = ui_.log->mimeSourceFactory();
 
598
        //ui_.log->setMimeSourceFactory(0);
824
599
        //delete m;
825
600
 
826
601
        d->pa->dialogUnregister(this);
 
602
        delete d->mucManager;
827
603
        delete d;
828
604
}
829
605
 
 
606
void GCMainDlg::setShortcuts()
 
607
{
 
608
        d->act_clear->setShortcuts(ShortcutManager::instance()->shortcuts("chat.clear"));
 
609
        d->act_find->setShortcuts(ShortcutManager::instance()->shortcuts("chat.find"));
 
610
        //d->act_send->setShortcuts(ShortcutManager::instance()->shortcuts("chat.send"));
 
611
        //d->act_close->setShortcuts(ShortcutManager::instance()->shortcuts("common.close"));
 
612
        d->act_scrollup->setShortcuts(ShortcutManager::instance()->shortcuts("common.scroll-up"));
 
613
        d->act_scrolldown->setShortcuts(ShortcutManager::instance()->shortcuts("common.scroll-down"));
 
614
}
 
615
 
 
616
void GCMainDlg::scrollUp() {
 
617
        ui_.log->verticalScrollBar()->setValue(ui_.log->verticalScrollBar()->value() - ui_.log->verticalScrollBar()->pageStep()/2);
 
618
}
 
619
 
 
620
void GCMainDlg::scrollDown() {
 
621
        ui_.log->verticalScrollBar()->setValue(ui_.log->verticalScrollBar()->value() + ui_.log->verticalScrollBar()->pageStep()/2);
 
622
}
 
623
 
 
624
// FIXME: This should be unnecessary, since these keys are all registered as
 
625
// actions in the constructor. Somehow, Qt ignores this.
830
626
void GCMainDlg::keyPressEvent(QKeyEvent *e)
831
627
{
832
 
        if(e->key() == Key_Return || e->key() == Key_Enter || (e->key() == Key_S && (e->state() & AltButton)))
 
628
        QKeySequence key = e->key() + ( e->modifiers() & ~Qt::KeypadModifier);
 
629
        if(!option.useTabs && ShortcutManager::instance()->shortcuts("common.close").contains(key))
 
630
                close();
 
631
        else if(ShortcutManager::instance()->shortcuts("chat.send").contains(key))
833
632
                mle_returnPressed();
834
 
        else if(e->key() == Key_PageUp && (e->state() & ShiftButton))
835
 
                d->te_log->setContentsPos(d->te_log->contentsX(), d->te_log->contentsY() - d->te_log->visibleHeight()/2);
836
 
        else if(e->key() == Key_PageDown && (e->state() & ShiftButton))
837
 
                d->te_log->setContentsPos(d->te_log->contentsX(), d->te_log->contentsY() + d->te_log->visibleHeight()/2);
 
633
        else if(ShortcutManager::instance()->shortcuts("common.scroll-up").contains(key))
 
634
                scrollUp();
 
635
        else if(ShortcutManager::instance()->shortcuts("common.scroll-down").contains(key))
 
636
                scrollDown();
838
637
        else
839
638
                e->ignore();
840
639
}
844
643
        e->accept();
845
644
}
846
645
 
 
646
void GCMainDlg::resizeEvent(QResizeEvent* e)
 
647
{
 
648
        if (option.keepSizes)
 
649
                PsiOptions::instance()->setOption("options.ui.muc.size", e->size());
 
650
}
 
651
 
847
652
void GCMainDlg::windowActivationChange(bool oldstate)
848
653
{
849
654
        QWidget::windowActivationChange(oldstate);
856
661
                }
857
662
                doFlash(false);
858
663
 
859
 
                d->mle->setFocus();
 
664
                ui_.mle->chatEdit()->setFocus();
860
665
                d->trackBar = false;
861
666
        } else {
862
667
                d->trackBar = true;
863
668
        }
864
669
}
865
670
 
 
671
void GCMainDlg::mucInfoDialog(const QString& title, const QString& message, const Jid& actor, const QString& reason)
 
672
{
 
673
        QString m = message;
 
674
        
 
675
        if (!actor.isEmpty())
 
676
                m += tr(" by %1").arg(actor.full());
 
677
        m += ".";
 
678
        
 
679
        if (!reason.isEmpty())
 
680
                m += tr("\nReason: %1").arg(reason);
 
681
 
 
682
        QMessageBox::information(this, title, m);
 
683
}
866
684
 
867
685
void GCMainDlg::logSelectionChanged()
868
686
{
869
687
#ifdef Q_WS_MAC
870
688
        // A hack to only give the message log focus when text is selected
871
 
        if (d->te_log->hasSelectedText()) 
872
 
                d->te_log->setFocus();
 
689
        if (ui_.log->hasSelectedText()) 
 
690
                ui_.log->setFocus();
873
691
        else 
874
 
                d->mle->setFocus();
875
 
#endif
 
692
                ui_.mle->chatEdit()->setFocus();
 
693
#endif
 
694
}
 
695
 
 
696
void GCMainDlg::setConnecting()
 
697
{
 
698
        d->connecting = true;
 
699
        QTimer::singleShot(5000,this,SLOT(unsetConnecting()));
 
700
}
 
701
 
 
702
void GCMainDlg::updateIdentityVisibility()
 
703
{
 
704
        ui_.lb_ident->setVisible(d->pa->psi()->contactList()->enabledAccounts().count() > 1);
 
705
}
 
706
 
 
707
#ifdef WHITEBOARDING
 
708
void GCMainDlg::openWhiteboard()
 
709
{
 
710
        d->pa->actionOpenWhiteboardSpecific(d->jid, d->jid.withResource(d->self), true);
 
711
}
 
712
#endif
 
713
 
 
714
void GCMainDlg::unsetConnecting()
 
715
{
 
716
        d->connecting = false;
 
717
}
 
718
 
 
719
void GCMainDlg::action_error(MUCManager::Action, int, const QString& err) 
 
720
{
 
721
        appendSysMsg(err, false);
876
722
}
877
723
 
878
724
void GCMainDlg::mle_returnPressed()
879
725
{
880
 
        if(d->mle->text().isEmpty())
 
726
        if(ui_.mle->chatEdit()->text().isEmpty())
881
727
                return;
882
728
 
883
 
        QString str = d->mle->text();
 
729
        QString str = ui_.mle->chatEdit()->text();
884
730
        if(str == "/clear") {
885
731
                doClear();
886
732
 
887
733
                d->histAt = 0;
888
734
                d->hist.prepend(str);
889
 
                d->mle->setText("");
 
735
                ui_.mle->chatEdit()->setText("");
890
736
                return;
891
737
        }
892
738
 
893
739
        if(str.lower().startsWith("/nick ")) {
894
740
                QString nick = str.mid(6).stripWhiteSpace();
895
741
                if ( !nick.isEmpty() ) {
 
742
                        d->prev_self = d->self;
896
743
                        d->self = nick;
897
744
                        d->pa->groupChatChangeNick(d->jid.host(), d->jid.user(), d->self, d->pa->status());
898
745
                }
899
 
                d->mle->setText("");
 
746
                ui_.mle->chatEdit()->setText("");
900
747
                return;
901
748
        }
902
749
 
912
759
 
913
760
        d->histAt = 0;
914
761
        d->hist.prepend(str);
915
 
        d->mle->setText("");
 
762
        ui_.mle->chatEdit()->setText("");
916
763
}
917
764
 
918
765
/*void GCMainDlg::le_upPressed()
940
787
        QString str = QInputDialog::getText(
941
788
                tr("Set Groupchat Topic"),
942
789
                tr("Enter a topic:"),
943
 
                QLineEdit::Normal, d->le_topic->text(), &ok, this);
 
790
                QLineEdit::Normal, ui_.le_topic->text(), &ok, this);
944
791
 
945
792
        if(ok) {
946
793
                Message m(d->jid);
947
794
                m.setType("groupchat");
948
795
                m.setSubject(str);
949
 
                m.setBody(QString("/me ") + tr("has set the topic to: %1").arg(str));
950
796
                m.setTimeStamp(QDateTime::currentDateTime());
951
797
                aSend(m);
952
798
        }
954
800
 
955
801
void GCMainDlg::doClear()
956
802
{
957
 
        d->te_log->setText("");
 
803
        ui_.log->setText("");
958
804
}
959
805
 
960
806
void GCMainDlg::doClearButton()
969
815
        if(d->findDlg)
970
816
                bringToFront(d->findDlg);
971
817
        else {
972
 
                d->findDlg = new GCFindDlg(0, 0, d->lastSearch, this);
973
 
                connect(d->findDlg, SIGNAL(find(int, int, const QString &)), SLOT(doFind(int, int, const QString &)));
 
818
                d->findDlg = new GCFindDlg(d->lastSearch, this);
 
819
                connect(d->findDlg, SIGNAL(find(const QString &)), SLOT(doFind(const QString &)));
974
820
                d->findDlg->show();
975
821
        }
976
822
}
977
823
 
978
 
void GCMainDlg::doFind(int para, int index, const QString &str)
 
824
void GCMainDlg::configureRoom()
 
825
{
 
826
        if(d->configDlg)
 
827
                bringToFront(d->configDlg);
 
828
        else {
 
829
                GCUserViewItem* c = (GCUserViewItem*)ui_.lv_users->findEntry(d->self);
 
830
                d->configDlg = new MUCConfigDlg(d->mucManager, this);
 
831
                d->configDlg->setRoleAffiliation(c->s.mucItem().role(), c->s.mucItem().affiliation());
 
832
                d->configDlg->show();
 
833
        }
 
834
}
 
835
 
 
836
void GCMainDlg::doFind(const QString &str)
979
837
{
980
838
        d->lastSearch = str;
981
 
 
982
 
        if(!d->te_log->find(str, false, false, true, &para, &index))
 
839
        if (d->internalFind(str))
 
840
                d->findDlg->found();
 
841
        else
983
842
                d->findDlg->error(str);
984
 
        else {
985
 
                // pass one character over
986
 
                d->findDlg->found(para, index+1);
987
 
        }
988
843
}
989
844
 
990
845
void GCMainDlg::goDisc()
991
846
{
992
847
        if(d->state != Private::Idle) {
993
848
                d->state = Private::Idle;
994
 
                d->pb_topic->setEnabled(false);
 
849
                ui_.pb_topic->setEnabled(false);
995
850
                appendSysMsg(tr("Disconnected."), true);
 
851
                ui_.mle->chatEdit()->setEnabled(false);
996
852
        }
997
853
}
998
854
 
1006
862
                QString room = d->jid.user();
1007
863
                QString nick = d->self;
1008
864
 
1009
 
                if(!d->pa->groupChatJoin(host, room, nick)) {
 
865
                if(!d->pa->groupChatJoin(host, room, nick, d->password)) {
1010
866
                        appendSysMsg(tr("Error: You are in or joining this room already!"), true);
1011
867
                        d->state = Private::Idle;
1012
868
                }
1013
869
        }
1014
870
}
1015
871
 
 
872
void GCMainDlg::dragEnterEvent(QDragEnterEvent *e)
 
873
{
 
874
        e->accept(e->mimeData()->hasText());
 
875
}
 
876
 
 
877
void GCMainDlg::dropEvent(QDropEvent *e)
 
878
{
 
879
        Jid jid(e->mimeData()->text());
 
880
        if (jid.isValid() && !ui_.lv_users->hasJid(jid)) {
 
881
                Message m;
 
882
                m.setTo(d->jid);
 
883
                m.addMUCInvite(MUCInvite(jid));
 
884
                if (!d->password.isEmpty())
 
885
                        m.setMUCPassword(d->password);
 
886
                m.setTimeStamp(QDateTime::currentDateTime());
 
887
                d->pa->dj_sendMessage(m);
 
888
        }
 
889
}
 
890
 
 
891
 
1016
892
void GCMainDlg::pa_updatedActivity()
1017
893
{
1018
894
        if(!d->pa->loggedIn())
1020
896
        else {
1021
897
                if(d->state == Private::Idle)
1022
898
                        goConn();
1023
 
                else if(d->state == Private::Connected)
1024
 
                        d->pa->groupChatSetStatus(d->jid.host(), d->jid.user(), d->pa->status());
 
899
                else if(d->state == Private::Connected) {
 
900
                        Status s = d->pa->status();
 
901
                        s.setXSigned("");
 
902
                        d->pa->groupChatSetStatus(d->jid.host(), d->jid.user(), s);
 
903
                }
1025
904
        }
1026
905
}
1027
906
 
1030
909
        return d->jid;
1031
910
}
1032
911
 
 
912
PsiAccount* GCMainDlg::account() const
 
913
{
 
914
        return d->pa;
 
915
}
 
916
 
1033
917
void GCMainDlg::error(int, const QString &str)
1034
918
{
1035
 
        d->pb_topic->setEnabled(false);
 
919
        ui_.pb_topic->setEnabled(false);
1036
920
 
1037
921
        if(d->state == Private::Connecting)
1038
922
                appendSysMsg(tr("Unable to join groupchat.  Reason: %1").arg(str), true);
1044
928
 
1045
929
void GCMainDlg::presence(const QString &nick, const Status &s)
1046
930
{
 
931
        if(s.hasError()) {
 
932
                QString message;
 
933
                if (s.errorCode() == 409) {
 
934
                        message = tr("Please choose a different nickname");
 
935
                        d->self = d->prev_self;
 
936
                }
 
937
                else
 
938
                        message = tr("An error occurred");
 
939
                appendSysMsg(message, false, QDateTime::currentDateTime());
 
940
                return;
 
941
        }
 
942
 
 
943
        if ((nick == "") && (s.mucStatus() == 100)) {
 
944
                d->nonAnonymous = true;
 
945
        }
 
946
 
 
947
        if (nick == d->self) {
 
948
                // Update configuration dialog
 
949
                if (d->configDlg) 
 
950
                        d->configDlg->setRoleAffiliation(s.mucItem().role(),s.mucItem().affiliation());
 
951
                d->act_configure->setEnabled(s.mucItem().affiliation() >= MUCItem::Member);
 
952
        }
 
953
        
1047
954
        if(s.isAvailable()) {
1048
 
                /*if ((option.showJoins)&&(d->lv_users->findEntry(nick)==0)) {
 
955
                // Available
 
956
                if (s.mucStatus() == 201) {
 
957
                        appendSysMsg(tr("New room created"), false, QDateTime::currentDateTime());
 
958
                        if (options_->getOption("options.muc.accept-defaults").toBool())
 
959
                                d->mucManager->setDefaultConfiguration();
 
960
                        else if (options_->getOption("options.muc.auto-configure").toBool())
 
961
                                QTimer::singleShot(0, this, SLOT(configureRoom()));
 
962
                }
 
963
 
 
964
                GCUserViewItem* contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
965
                if (contact == NULL) {
1049
966
                        //contact joining
1050
 
                        QString m=nick+tr(" has joined the channel");
1051
 
                        appendSysMsg(m, false, QDateTime::currentDateTime());
1052
 
                }*/
1053
 
                d->lv_users->updateEntry(nick, s);
1054
 
        } else {
1055
 
                /*if (option.showJoins) {
1056
 
                        //contact leaving
1057
 
                        QString m=nick+tr(" has left the channel");
1058
 
                        appendSysMsg(m, false, QDateTime::currentDateTime());
1059
 
                }*/
1060
 
                d->lv_users->removeEntry(nick);
1061
 
        }
 
967
                        if ( !d->connecting && options_->getOption("options.muc.show-joins").toBool() ) {
 
968
                                QString message = tr("%1 has joined the room");
 
969
 
 
970
                                if ( options_->getOption("options.muc.show-role-affiliation").toBool() ) {
 
971
                                        if (s.mucItem().role() != MUCItem::NoRole) {
 
972
                                                if (s.mucItem().affiliation() != MUCItem::NoAffiliation) {
 
973
                                                        message = tr("%3 has joined the room as %1 and %2").arg(MUCManager::roleToString(s.mucItem().role(),true)).arg(MUCManager::affiliationToString(s.mucItem().affiliation(),true));
 
974
                                                }
 
975
                                                else {
 
976
                                                        message = tr("%2 has joined the room as %1").arg(MUCManager::roleToString(s.mucItem().role(),true));
 
977
                                                }
 
978
                                        }
 
979
                                        else if (s.mucItem().affiliation() != MUCItem::NoAffiliation) {
 
980
                                                message = tr("%2 has joined the room as %1").arg(MUCManager::affiliationToString(s.mucItem().affiliation(),true));
 
981
                                        }
 
982
                                }
 
983
                                if (!s.mucItem().jid().isEmpty())
 
984
                                        message = message.arg(QString("%1 (%2)").arg(nick).arg(s.mucItem().jid().full()));
 
985
                                else
 
986
                                        message = message.arg(nick);
 
987
                                appendSysMsg(message, false, QDateTime::currentDateTime());
 
988
                        }
 
989
                }
 
990
                else {
 
991
                        // Status change
 
992
                        if ( !d->connecting && options_->getOption("options.muc.show-role-affiliation").toBool() ) {
 
993
                                QString message;
 
994
                                if (contact->s.mucItem().role() != s.mucItem().role() && s.mucItem().role() != MUCItem::NoRole) {
 
995
                                        if (contact->s.mucItem().affiliation() != s.mucItem().affiliation()) {
 
996
                                                message = tr("%1 is now %2 and %3").arg(nick).arg(MUCManager::roleToString(s.mucItem().role(),true)).arg(MUCManager::affiliationToString(s.mucItem().affiliation(),true));
 
997
                                        }
 
998
                                        else {
 
999
                                                message = tr("%1 is now %2").arg(nick).arg(MUCManager::roleToString(s.mucItem().role(),true));
 
1000
                                        }
 
1001
                                }
 
1002
                                else if (contact->s.mucItem().affiliation() != s.mucItem().affiliation()) {
 
1003
                                        message += tr("%1 is now %2").arg(nick).arg(MUCManager::affiliationToString(s.mucItem().affiliation(),true));
 
1004
                                }
 
1005
 
 
1006
                                if (!message.isEmpty())
 
1007
                                        appendSysMsg(message, false, QDateTime::currentDateTime());
 
1008
                        }
 
1009
                        if ( !d->connecting && options_->getOption("options.muc.show-status-changes").toBool() ) {
 
1010
                                if (s.status() != contact->s.status() || s.show() != contact->s.show()) {
 
1011
                                        QString message;
 
1012
                                        QString st;
 
1013
                                        if (s.show().isEmpty()) 
 
1014
                                                st=tr("online");
 
1015
                                        else
 
1016
                                                st=s.show();
 
1017
                                        message = tr("%1 is now %2").arg(nick).arg(st);
 
1018
                                        if (!s.status().isEmpty())
 
1019
                                                message+=QString(" (%1)").arg(s.status());
 
1020
                                        appendSysMsg(message, false, QDateTime::currentDateTime());
 
1021
                                }
 
1022
                        }
 
1023
                }
 
1024
                ui_.lv_users->updateEntry(nick, s);
 
1025
        } 
 
1026
        else {
 
1027
                // Unavailable
 
1028
                if (s.hasMUCDestroy()) {
 
1029
                        // Room was destroyed
 
1030
                        QString message = tr("This room has been destroyed.");
 
1031
                        if (!s.mucDestroy().reason().isEmpty()) {
 
1032
                                message += "\n";
 
1033
                                message += tr("Reason: %1").arg(s.mucDestroy().reason());
 
1034
                        }
 
1035
                        if (!s.mucDestroy().jid().isEmpty()) {
 
1036
                                message += "\n";
 
1037
                                message += tr("Do you want to join the alternate venue '%1' ?").arg(s.mucDestroy().jid().full());
 
1038
                                int ret = QMessageBox::information(this, tr("Room Destroyed"), message, QMessageBox::Yes, QMessageBox::No);
 
1039
                                if (ret == QMessageBox::Yes) {
 
1040
                                        d->pa->actionJoin(s.mucDestroy().jid().full());
 
1041
                                }
 
1042
                        }
 
1043
                        else {
 
1044
                                QMessageBox::information(this,tr("Room Destroyed"), message);
 
1045
                        }
 
1046
                        close();
 
1047
                }
 
1048
                if ( !d->connecting && options_->getOption("options.muc.show-joins").toBool() ) {
 
1049
                        QString message;
 
1050
                        QString nickJid;
 
1051
                        GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1052
                        if (contact && !contact->s.mucItem().jid().isEmpty())
 
1053
                                nickJid = QString("%1 (%2)").arg(nick).arg(contact->s.mucItem().jid().full());
 
1054
                        else
 
1055
                                nickJid = nick;
 
1056
 
 
1057
                        switch (s.mucStatus()) {
 
1058
                                case 301:
 
1059
                                        // Ban
 
1060
                                        if (nick == d->self) {
 
1061
                                                mucInfoDialog(tr("Banned"), tr("You have been banned from the room"), s.mucItem().actor(), s.mucItem().reason());
 
1062
                                                close();
 
1063
                                        }
 
1064
 
 
1065
                                        if (!s.mucItem().actor().isEmpty())
 
1066
                                                message = tr("%1 has been banned by %2").arg(nickJid, s.mucItem().actor().full());
 
1067
                                        else
 
1068
                                                message = tr("%1 has been banned").arg(nickJid);
 
1069
 
 
1070
                                        if (!s.mucItem().reason().isEmpty()) 
 
1071
                                                message += QString(" (%1)").arg(s.mucItem().reason());
 
1072
                                        break;
 
1073
 
 
1074
                                case 303:
 
1075
                                        message = tr("%1 is now known as %2").arg(nick).arg(s.mucItem().nick());
 
1076
                                        ui_.lv_users->updateEntry(s.mucItem().nick(), s);
 
1077
                                        break;
 
1078
                                        
 
1079
                                case 307:
 
1080
                                        // Kick
 
1081
                                        if (nick == d->self) {
 
1082
                                                mucInfoDialog(tr("Kicked"), tr("You have been kicked from the room"), s.mucItem().actor(), s.mucItem().reason());
 
1083
                                                close();
 
1084
                                        }
 
1085
 
 
1086
                                        if (!s.mucItem().actor().isEmpty())
 
1087
                                                message = tr("%1 has been kicked by %2").arg(nickJid).arg(s.mucItem().actor().full());
 
1088
                                        else
 
1089
                                                message = tr("%1 has been kicked").arg(nickJid);
 
1090
                                        if (!s.mucItem().reason().isEmpty()) 
 
1091
                                                message += QString(" (%1)").arg(s.mucItem().reason());
 
1092
                                        break;
 
1093
                                        
 
1094
                                case 321:
 
1095
                                        // Remove due to affiliation change
 
1096
                                        if (nick == d->self) {
 
1097
                                                mucInfoDialog(tr("Removed"), tr("You have been removed from the room due to an affiliation change"), s.mucItem().actor(), s.mucItem().reason());
 
1098
                                                close();
 
1099
                                        }
 
1100
 
 
1101
                                        if (!s.mucItem().actor().isEmpty())
 
1102
                                                message = tr("%1 has been removed from the room by %2 due to an affilliation change").arg(nickJid).arg(s.mucItem().actor().full());
 
1103
                                        else
 
1104
                                                message = tr("%1 has been removed from the room due to an affilliation change").arg(nickJid);
 
1105
 
 
1106
                                        if (!s.mucItem().reason().isEmpty()) 
 
1107
                                                message += QString(" (%1)").arg(s.mucItem().reason());
 
1108
                                        break;
 
1109
                                        
 
1110
                                case 322:
 
1111
                                        // Remove due to members only
 
1112
                                        if (nick == d->self) {
 
1113
                                                mucInfoDialog(tr("Removed"), tr("You have been removed from the room because the room was made members only"), s.mucItem().actor(), s.mucItem().reason());
 
1114
                                                close();
 
1115
                                        }
 
1116
 
 
1117
                                        if (!s.mucItem().actor().isEmpty())
 
1118
                                                message = tr("%1 has been removed from the room by %2 because the room was made members-only").arg(nickJid).arg(s.mucItem().actor().full());
 
1119
                                        else
 
1120
                                                message = tr("%1 has been removed from the room because the room was made members-only").arg(nickJid);
 
1121
 
 
1122
                                        if (!s.mucItem().reason().isEmpty()) 
 
1123
                                                message += QString(" (%1)").arg(s.mucItem().reason());
 
1124
                                        break;
 
1125
 
 
1126
                                default:
 
1127
                                        //contact leaving
 
1128
                                        message = tr("%1 has left the room").arg(nickJid);
 
1129
                                        if (!s.status().isEmpty())
 
1130
                                                message += QString(" (%1)").arg(s.status());
 
1131
                        }
 
1132
                        appendSysMsg(message, false, QDateTime::currentDateTime());
 
1133
                }
 
1134
                ui_.lv_users->removeEntry(nick);
 
1135
        }
 
1136
        
 
1137
        if (!s.capsNode().isEmpty()) {
 
1138
                Jid caps_jid(s.mucItem().jid().isEmpty() || !d->nonAnonymous ? Jid(d->jid).withResource(nick) : s.mucItem().jid());
 
1139
                d->pa->capsManager()->updateCaps(caps_jid,s.capsNode(),s.capsVersion(),s.capsExt());
 
1140
        }
 
1141
 
1062
1142
}
1063
1143
 
1064
 
void GCMainDlg::message(const Message &m)
 
1144
void GCMainDlg::message(const Message &_m)
1065
1145
{
 
1146
        Message m = _m;
1066
1147
        QString from = m.from().resource();
1067
1148
        bool alert = false;
1068
1149
 
1069
1150
        if(!m.subject().isEmpty()) {
1070
 
                d->le_topic->setText(m.subject());
1071
 
                d->le_topic->setCursorPosition(0);
1072
 
                QToolTip::add(d->le_topic, QString("<qt><p>%1</p></qt>").arg(m.subject()));
 
1151
                ui_.le_topic->setText(m.subject());
 
1152
                ui_.le_topic->setCursorPosition(0);
 
1153
                ui_.le_topic->setToolTip(QString("<qt><p>%1</p></qt>").arg(m.subject()));
 
1154
                if(m.body().isEmpty()) {
 
1155
                        if (!from.isEmpty())
 
1156
                                m.setBody(QString("/me ") + tr("has set the topic to: %1").arg(m.subject()));
 
1157
                        else
 
1158
                                // The topic was set by the server
 
1159
                                m.setBody(tr("The topic has been set to: %1").arg(m.subject()));
 
1160
                }
1073
1161
        }
1074
1162
 
 
1163
        if(m.body().isEmpty())
 
1164
                return;
 
1165
 
1075
1166
        // code to determine if the speaker was addressing this client in chat
1076
 
        if(m.body().contains(d->self) > 0)
 
1167
        if(m.body().contains(d->self))
1077
1168
                alert = true;
1078
1169
 
1079
1170
        if (m.body().left(d->self.length()) == d->self)
1081
1172
 
1082
1173
        if(option.gcHighlighting) {
1083
1174
                for(QStringList::Iterator it=option.gcHighlights.begin();it!=option.gcHighlights.end();it++) {
1084
 
                        if(m.body().contains((*it),false) > 0) {
 
1175
                        if(m.body().contains((*it), Qt::CaseInsensitive)) {
1085
1176
                                alert = true;
1086
1177
                        }
1087
1178
                }
1106
1197
void GCMainDlg::joined()
1107
1198
{
1108
1199
        if(d->state == Private::Connecting) {
1109
 
                d->lv_users->QListView::clear();
 
1200
                ui_.lv_users->clear();
1110
1201
                d->state = Private::Connected;
1111
 
                d->pb_topic->setEnabled(true);
 
1202
                ui_.pb_topic->setEnabled(true);
 
1203
                ui_.mle->chatEdit()->setEnabled(true);
 
1204
                setConnecting();
1112
1205
                appendSysMsg(tr("Connected."), true);
1113
1206
        }
1114
1207
}
1115
1208
 
 
1209
void GCMainDlg::setPassword(const QString& p)
 
1210
{
 
1211
        d->password = p;
 
1212
}
 
1213
 
 
1214
const QString& GCMainDlg::nick() const
 
1215
{
 
1216
        return d->self;
 
1217
}
 
1218
 
1116
1219
void GCMainDlg::appendSysMsg(const QString &str, bool alert, const QDateTime &ts)
1117
1220
{
1118
 
        bool atBottom = d->te_log->contentsY() >= d->te_log->contentsHeight() - d->te_log->visibleHeight();
1119
 
 
1120
 
        QString hr ="";
1121
 
        if (d->trackBar) {
1122
 
                hr = QString("<hr>");
1123
 
                d->trackBar = false;
1124
 
 
1125
 
                if ( d->trackBarParagraph ) {
1126
 
                        d->te_log->setUpdatesEnabled( false );
1127
 
                        d->te_log->setSelection(d->trackBarParagraph, 0, d->trackBarParagraph, 1, 1);
1128
 
                        d->te_log->removeSelectedText(1);
1129
 
                        d->te_log->setUpdatesEnabled( true );
1130
 
                }
1131
 
                d->trackBarParagraph = d->te_log->paragraphs();
1132
 
        }
1133
 
 
1134
 
        QString timestr;
 
1221
        if (d->trackBar)
 
1222
                d->doTrackBar();
 
1223
 
1135
1224
        if (!option.gcHighlighting)
1136
1225
                alert=false;
1137
1226
 
1138
 
        QDateTime time;
 
1227
        QDateTime time = QDateTime::currentDateTime();
1139
1228
        if(!ts.isNull())
1140
1229
                time = ts;
1141
 
        else
1142
 
                time = QDateTime::currentDateTime();
1143
 
 
1144
 
        //timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
1145
 
        timestr = time.time().toString(LocalDate);
1146
 
 
1147
 
        /*int y = d->te_log->contentsHeight() - d->te_log->visibleHeight();
1148
 
        if(y < 0)
1149
 
                y = 0;
1150
 
        bool atBottom = (d->te_log->contentsY() < y - 32) ? false: true;*/
1151
 
 
1152
 
        d->te_log->append(hr + QString("<font color=\"#00A000\">[%1]").arg(timestr) + QString(" *** %1</font>").arg(expandEntities(str)));
1153
 
 
1154
 
        if(atBottom)
1155
 
                d->deferredScroll();
 
1230
 
 
1231
        QString timestr = ui_.log->formatTimeStamp(time);
 
1232
        ui_.log->appendText(QString("<font color=\"#00A000\">[%1]").arg(timestr) + QString(" *** %1</font>").arg(Qt::escape(str)));
1156
1233
 
1157
1234
        if(alert)
1158
1235
                doAlert();
1191
1268
                alert=false;
1192
1269
        QString who, textcolor, nickcolor,alerttagso,alerttagsc;
1193
1270
 
1194
 
        bool atBottom = d->te_log->contentsY() >= d->te_log->contentsHeight() - d->te_log->visibleHeight();
1195
 
 
1196
1271
        who = m.from().resource();
1197
 
        QString hr = "";
1198
 
        if (d->trackBar&&m.from().resource() != d->self&&!m.spooled()) {
1199
 
                hr = QString("<hr>");
1200
 
                d->trackBar = false;
1201
 
 
1202
 
                if ( d->trackBarParagraph ) {
1203
 
                        d->te_log->setUpdatesEnabled( false );
1204
 
                        d->te_log->setSelection(d->trackBarParagraph, 0, d->trackBarParagraph, 1, 1);
1205
 
                        d->te_log->removeSelectedText(1);
1206
 
                        d->te_log->setUpdatesEnabled( true );
1207
 
                }
1208
 
                d->trackBarParagraph = d->te_log->paragraphs();
1209
 
        }
 
1272
        if (d->trackBar&&m.from().resource() != d->self&&!m.spooled())
 
1273
                d->doTrackBar();
1210
1274
        /*if(local) {
1211
1275
                color = "#FF0000";
1212
1276
        }
1214
1278
                color = "#0000FF";
1215
1279
        }*/
1216
1280
        nickcolor = getNickColor(who);
1217
 
        textcolor = d->te_log->palette().active().text().name();
 
1281
        textcolor = ui_.log->palette().active().text().name();
1218
1282
        if(alert) {
1219
1283
                textcolor = "#FF0000";
1220
1284
                alerttagso = "<b>";
1223
1287
        if(m.spooled())
1224
1288
                nickcolor = "#008000"; //color = "#008000";
1225
1289
 
1226
 
        QString timestr;
1227
 
        QDateTime time = m.timeStamp();
1228
 
        //timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
1229
 
        timestr = time.time().toString(LocalDate);
1230
 
 
1231
 
        /*int y = d->te_log->contentsHeight() - d->te_log->visibleHeight();
1232
 
        if(y < 0)
1233
 
                y = 0;
1234
 
        bool atBottom = (d->te_log->contentsY() < y - 32) ? false: true;*/
 
1290
        QString timestr = ui_.log->formatTimeStamp(m.timeStamp());
1235
1291
 
1236
1292
        bool emote = false;
1237
1293
        if(m.body().left(4) == "/me ")
1239
1295
 
1240
1296
        QString txt;
1241
1297
        if(emote)
1242
 
                txt = plain2rich(m.body().mid(4));
 
1298
                txt = TextUtil::plain2rich(m.body().mid(4));
1243
1299
        else
1244
 
                txt = plain2rich(m.body());
 
1300
                txt = TextUtil::plain2rich(m.body());
1245
1301
 
1246
 
        txt = linkify(txt);
 
1302
        txt = TextUtil::linkify(txt);
1247
1303
 
1248
1304
        if(option.useEmoticons)
1249
 
                txt = emoticonify(txt);
 
1305
                txt = TextUtil::emoticonify(txt);
 
1306
        if( PsiOptions::instance()->getOption("options.ui.chat.legacy-formatting").toBool() )
 
1307
                txt = TextUtil::legacyFormat(txt);
1250
1308
 
1251
1309
        if(emote) {
1252
 
                //d->te_log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(expandEntities(who)) + txt + "</font>");
1253
 
                d->te_log->append(hr + QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(expandEntities(who)) + alerttagso + txt + alerttagsc + "</font>");
 
1310
                //ui_.log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(Qt::escape(who)) + txt + "</font>");
 
1311
                ui_.log->appendText(QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(Qt::escape(who)) + alerttagso + txt + alerttagsc + "</font>");
1254
1312
        }
1255
1313
        else {
1256
1314
                if(option.chatSays) {
1257
 
                        //d->te_log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] ").arg(timestr) + QString("%1 says:").arg(expandEntities(who)) + "</font><br>" + txt);
1258
 
                        d->te_log->append(hr + QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1] ").arg(timestr) + QString("%1 says:").arg(expandEntities(who)) + "</font><br>" + QString("<font color=\"%1\">").arg(textcolor) + alerttagso + txt + alerttagsc + "</font>");
 
1315
                        //ui_.log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] ").arg(timestr) + QString("%1 says:").arg(Qt::escape(who)) + "</font><br>" + txt);
 
1316
                        ui_.log->appendText(QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1] ").arg(timestr) + QString("%1 says:").arg(Qt::escape(who)) + "</font><br>" + QString("<font color=\"%1\">").arg(textcolor) + alerttagso + txt + alerttagsc + "</font>");
1259
1317
                }
1260
1318
                else {
1261
 
                        //d->te_log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] &lt;").arg(timestr) + expandEntities(who) + QString("&gt;</font> ") + txt);
1262
 
                        d->te_log->append(hr + QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1] &lt;").arg(timestr) + expandEntities(who) + QString("&gt;</font> ") + QString("<font color=\"%1\">").arg(textcolor) + alerttagso + txt + alerttagsc +"</font>");
 
1319
                        //ui_.log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] &lt;").arg(timestr) + Qt::escape(who) + QString("&gt;</font> ") + txt);
 
1320
                        ui_.log->appendText(QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1] &lt;").arg(timestr) + Qt::escape(who) + QString("&gt;</font> ") + QString("<font color=\"%1\">").arg(textcolor) + alerttagso + txt + alerttagsc +"</font>");
1263
1321
                }
1264
1322
        }
1265
1323
 
1266
 
        //if(local || atBottom)
1267
 
        if(m.from().resource() == d->self || atBottom)
 
1324
        //if(local)
 
1325
        if(m.from().resource() == d->self)
1268
1326
                d->deferredScroll();
1269
1327
 
1270
1328
        // if we're not active, notify the user by changing the title
1288
1346
void GCMainDlg::doAlert()
1289
1347
{
1290
1348
        if(!isActiveWindow())
1291
 
                doFlash(true);
 
1349
                if (PsiOptions::instance()->getOption("options.ui.flash-windows").toBool())
 
1350
                        doFlash(true);
1292
1351
}
1293
1352
 
1294
1353
void GCMainDlg::updateCaption()
1310
1369
        if(on)
1311
1370
                FlashWindow(winId(), true);
1312
1371
#endif
1313
 
        setCaption(cap);
 
1372
        setWindowTitle(cap);
1314
1373
#ifdef Q_WS_WIN
1315
1374
        if(on)
1316
1375
                FlashWindow(winId(), true);
1355
1414
 
1356
1415
void GCMainDlg::setLooks()
1357
1416
{
 
1417
        ui_.vsplitter->optionsChanged();
 
1418
        ui_.mle->optionsChanged();
 
1419
 
1358
1420
        // update the fonts
1359
1421
        QFont f;
1360
1422
        f.fromString(option.font[fChat]);
1361
 
        d->te_log->setFont(f);
1362
 
        d->mle->setFont(f);
 
1423
        ui_.log->setFont(f);
 
1424
        ui_.mle->chatEdit()->setFont(f);
1363
1425
 
1364
1426
        f.fromString(option.font[fRoster]);
1365
 
        d->lv_users->QListView::setFont(f);
 
1427
        ui_.lv_users->Q3ListView::setFont(f);
1366
1428
 
1367
 
        if ( d->smallChat ) {
1368
 
                d->toolbar->hide();
 
1429
        if (PsiOptions::instance()->getOption("options.ui.chat.central-toolbar").toBool()) {
 
1430
                ui_.toolbar->show();
 
1431
                ui_.tb_actions->hide();
 
1432
                ui_.tb_emoticons->hide();
1369
1433
        }
1370
1434
        else {
1371
 
                d->toolbar->show();
 
1435
                ui_.toolbar->hide();
 
1436
                ui_.tb_emoticons->setVisible(option.useEmoticons);
 
1437
                ui_.tb_actions->show();
1372
1438
        }
1373
1439
 
 
1440
        setWindowOpacity(double(qMax(MINIMUM_OPACITY,PsiOptions::instance()->getOption("options.ui.chat.opacity").toInt()))/100);
 
1441
 
1374
1442
        // update the widget icon
1375
1443
#ifndef Q_WS_MAC
1376
 
        setIcon(IconsetFactory::icon("psi/groupChat"));
 
1444
        setWindowIcon(IconsetFactory::icon("psi/groupChat").icon());
1377
1445
#endif
1378
1446
}
1379
1447
 
1380
1448
void GCMainDlg::optionsUpdate()
1381
1449
{
1382
 
        /*QMimeSourceFactory *m = d->te_log->mimeSourceFactory();
1383
 
        d->te_log->setMimeSourceFactory(is->emoticons.generateFactory());
 
1450
        /*QMimeSourceFactory *m = ui_.log->mimeSourceFactory();
 
1451
        ui_.log->setMimeSourceFactory(PsiIconset::instance()->emoticons.generateFactory());
1384
1452
        delete m;*/
1385
1453
 
1386
1454
        setLooks();
 
1455
        setShortcuts();
1387
1456
 
1388
1457
        // update status icons
1389
 
        d->lv_users->updateAll();
 
1458
        ui_.lv_users->updateAll();
1390
1459
}
1391
1460
 
1392
1461
void GCMainDlg::lv_action(const QString &nick, const Status &s, int x)
1417
1486
        else if(x == 4) {
1418
1487
                d->pa->invokeGCFile(d->jid.withResource(nick));
1419
1488
        }
 
1489
        else if(x == 10) {
 
1490
                d->mucManager->kick(nick);
 
1491
        }
 
1492
        else if(x == 11) {
 
1493
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1494
                d->mucManager->ban(contact->s.mucItem().jid());
 
1495
        }
 
1496
        else if(x == 12) {
 
1497
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1498
                if (contact->s.mucItem().role() != MUCItem::Visitor)
 
1499
                        d->mucManager->setRole(nick, MUCItem::Visitor);
 
1500
        }
 
1501
        else if(x == 13) {
 
1502
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1503
                if (contact->s.mucItem().role() != MUCItem::Participant)
 
1504
                        d->mucManager->setRole(nick, MUCItem::Participant);
 
1505
        }
 
1506
        else if(x == 14) {
 
1507
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1508
                if (contact->s.mucItem().role() != MUCItem::Moderator)
 
1509
                        d->mucManager->setRole(nick, MUCItem::Moderator);
 
1510
        }
 
1511
        /*else if(x == 15) {
 
1512
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1513
                if (contact->s.mucItem().affiliation() != MUCItem::NoAffiliation)
 
1514
                        d->mucManager->setAffiliation(contact->s.mucItem().jid(), MUCItem::NoAffiliation);
 
1515
        }
 
1516
        else if(x == 16) {
 
1517
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1518
                if (contact->s.mucItem().affiliation() != MUCItem::Member)
 
1519
                        d->mucManager->setAffiliation(contact->s.mucItem().jid(), MUCItem::Member);
 
1520
        }
 
1521
        else if(x == 17) {
 
1522
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1523
                if (contact->s.mucItem().affiliation() != MUCItem::Admin)
 
1524
                        d->mucManager->setAffiliation(contact->s.mucItem().jid(), MUCItem::Admin);
 
1525
        }
 
1526
        else if(x == 18) {
 
1527
                GCUserViewItem *contact = (GCUserViewItem*) ui_.lv_users->findEntry(nick);
 
1528
                if (contact->s.mucItem().affiliation() != MUCItem::Owner)
 
1529
                        d->mucManager->setAffiliation(contact->s.mucItem().jid(), MUCItem::Owner);
 
1530
        }*/
1420
1531
}
1421
1532
 
1422
1533
void GCMainDlg::contextMenuEvent(QContextMenuEvent *)
1428
1539
{
1429
1540
        // Dialog menu
1430
1541
        d->pm_settings->clear();
1431
 
        d->pm_settings->insertItem(tr("Toggle Compact/Full Size"), this, SLOT(toggleSmallChat()));
1432
1542
 
1433
1543
        d->act_clear->addTo( d->pm_settings );
 
1544
        d->act_configure->addTo( d->pm_settings );
 
1545
#ifdef WHITEBOARDING
 
1546
        d->act_whiteboard->addTo( d->pm_settings );
 
1547
#endif
1434
1548
        d->pm_settings->insertSeparator();
1435
1549
 
1436
1550
        d->act_icon->addTo( d->pm_settings );
1437
1551
}
1438
1552
 
1439
 
void GCMainDlg::toggleSmallChat()
 
1553
void GCMainDlg::chatEditCreated()
1440
1554
{
1441
 
        d->smallChat = !d->smallChat;
1442
 
        setLooks();
 
1555
        ui_.log->setDialog(this);
 
1556
        ui_.mle->chatEdit()->setDialog(this);
 
1557
 
 
1558
        ui_.mle->chatEdit()->installEventFilter(d);
1443
1559
}
1444
1560
 
1445
1561
//----------------------------------------------------------------------------
1446
1562
// GCFindDlg
1447
1563
//----------------------------------------------------------------------------
1448
 
GCFindDlg::GCFindDlg(int startPara, int startIndex, const QString &str, QWidget *parent, const char *name)
1449
 
:QDialog(parent, name, false, WDestructiveClose)
 
1564
GCFindDlg::GCFindDlg(const QString &str, QWidget *parent, const char *name)
 
1565
        : QDialog(parent, name, false)
1450
1566
{
1451
 
        para = startPara;
1452
 
        index = startIndex;
1453
 
 
1454
 
        setCaption(tr("Find"));
 
1567
        setAttribute(Qt::WA_DeleteOnClose);
 
1568
        setWindowTitle(tr("Find"));
1455
1569
        QVBoxLayout *vb = new QVBoxLayout(this, 4);
1456
1570
        QHBoxLayout *hb = new QHBoxLayout(vb);
1457
1571
        QLabel *l = new QLabel(tr("Find:"), this);
1477
1591
        hb->addWidget(pb_find);
1478
1592
        pb_find->setAutoDefault(true);
1479
1593
 
1480
 
        resize(200, minimumSize().height());
 
1594
        resize(200, minimumSizeHint().height());
1481
1595
 
1482
1596
        le_input->setText(str);
1483
1597
        le_input->setFocus();
1487
1601
{
1488
1602
}
1489
1603
 
1490
 
void GCFindDlg::found(int _para, int _index)
 
1604
void GCFindDlg::found()
1491
1605
{
1492
 
        para = _para;
1493
 
        index = _index;
 
1606
        // nothing here to do...
1494
1607
}
1495
1608
 
1496
1609
void GCFindDlg::error(const QString &str)
1501
1614
 
1502
1615
void GCFindDlg::doFind()
1503
1616
{
1504
 
        emit find(para, index, le_input->text());
 
1617
        emit find(le_input->text());
1505
1618
}
1506
1619
 
1507
1620
#include "groupchatdlg.moc"