2
* groupchatdlg.cpp - dialogs for handling groupchat
3
* Copyright (C) 2001, 2002 Justin Karneges
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.
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.
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
21
#include"groupchatdlg.h"
25
#include<qpushbutton.h>
27
#include<qmessagebox.h>
32
#include<qtoolbutton.h>
33
#include<qinputdialog.h>
34
#include<qguardedptr.h>
36
#include<qobjectlist.h>
37
#include<qpopupmenu.h>
39
#include"psiaccount.h"
42
#include"busywidget.h"
45
#include"iconwidget.h"
46
#include"iconselect.h"
47
#include"iconaction.h"
54
//----------------------------------------------------------------------------
56
//----------------------------------------------------------------------------
57
class GCJoinDlg::Private
64
AccountsComboBox *cb_ident;
70
GCJoinDlg::GCJoinDlg(PsiCon *psi, PsiAccount *pa)
71
:GCJoinUI(0, 0, false, WDestructiveClose)
76
d->psi->dialogRegister(this);
81
d->cb_ident = d->psi->accountsComboBox(this,true);
82
connect(d->cb_ident, SIGNAL(activated(PsiAccount *)), SLOT(updateIdentity(PsiAccount *)));
83
d->cb_ident->setAccount(pa);
84
replaceWidget(lb_ident, d->cb_ident);
86
d->rl = d->psi->recentGCList();
87
for(QStringList::ConstIterator it = d->rl.begin(); it != d->rl.end(); ++it) {
89
QString s = tr("%1 on %2").arg(j.resource()).arg(j.userHost());
90
cb_recent->insertItem(s);
93
setCaption(CAP(caption()));
94
pb_join->setDefault(true);
95
connect(pb_close, SIGNAL(clicked()), SLOT(close()));
96
connect(pb_join, SIGNAL(clicked()), SLOT(doJoin()));
97
connect(cb_recent, SIGNAL(activated(int)), SLOT(recent_activated(int)));
99
cb_recent->setEnabled(false);
106
GCJoinDlg::~GCJoinDlg()
109
d->psi->dialogUnregister(this);
111
d->pa->dialogUnregister(this);
115
/*void GCJoinDlg::closeEvent(QCloseEvent *e)
121
void GCJoinDlg::done(int r)
123
if(d->busy->isActive()) {
124
int n = QMessageBox::information(this, tr("Warning"), tr("Are you sure you want to cancel joining groupchat?"), tr("&Yes"), tr("&No"));
127
d->pa->groupChatLeave(d->jid.host(), d->jid.user());
132
void GCJoinDlg::updateIdentity(PsiAccount *pa)
135
disconnect(d->pa, SIGNAL(disconnected()), this, SLOT(pa_disconnected()));
138
pb_join->setEnabled(d->pa);
145
connect(d->pa, SIGNAL(disconnected()), this, SLOT(pa_disconnected()));
148
void GCJoinDlg::pa_disconnected()
150
if(d->busy->isActive()) {
155
void GCJoinDlg::recent_activated(int x)
160
for(QStringList::ConstIterator it = d->rl.begin(); it != d->rl.end(); ++it) {
172
le_host->setText(j.host());
173
le_room->setText(j.user());
174
le_nick->setText(j.resource());
177
void GCJoinDlg::doJoin()
179
if(!d->pa->checkConnected(this))
182
QString host = le_host->text();
183
QString room = le_room->text();
184
QString nick = le_nick->text();
186
if(host.isEmpty() || room.isEmpty() || nick.isEmpty()) {
187
QMessageBox::information(this, tr("Error"), tr("You must fill out the fields in order to join."));
191
Jid j = room + '@' + host + '/' + nick;
193
QMessageBox::information(this, tr("Error"), tr("You entered an invalid room name."));
197
if(!d->pa->groupChatJoin(host, room, nick)) {
198
QMessageBox::information(this, tr("Error"), tr("You are in or joining this room already!"));
202
d->psi->dialogUnregister(this);
203
d->jid = room + '@' + host + '/' + nick;
204
d->pa->dialogRegister(this, d->jid);
210
void GCJoinDlg::disableWidgets()
212
d->cb_ident->setEnabled(false);
213
cb_recent->setEnabled(false);
214
gb_info->setEnabled(false);
215
pb_join->setEnabled(false);
218
void GCJoinDlg::enableWidgets()
220
d->cb_ident->setEnabled(true);
222
cb_recent->setEnabled(true);
223
gb_info->setEnabled(true);
224
pb_join->setEnabled(true);
227
void GCJoinDlg::joined()
229
d->psi->recentGCAdd(d->jid.full());
236
void GCJoinDlg::error(int, const QString &str)
243
d->pa->dialogUnregister(this);
244
d->psi->dialogRegister(this);
246
QMessageBox::information(this, tr("Error"), tr("Unable to join groupchat.\nReason: %1").arg(str));
250
//----------------------------------------------------------------------------
252
//----------------------------------------------------------------------------
253
GCUserViewItem::GCUserViewItem(QListView *par)
258
GCUserView::GCUserView(QWidget *parent, const char *name)
259
:QListView(parent, name), QToolTip(viewport())
261
setResizeMode(QListView::AllColumns);
266
connect(this, SIGNAL(doubleClicked(QListViewItem *)), SLOT(qlv_doubleClicked(QListViewItem *)));
267
connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)), SLOT(qlv_contextMenuRequested(QListViewItem *, const QPoint &, int)));
270
GCUserView::~GCUserView()
274
void GCUserView::updateAll()
276
for(GCUserViewItem *i = (GCUserViewItem *)firstChild(); i; i = (GCUserViewItem *)i->nextSibling())
277
i->setPixmap(0, is->status(i->s));
280
QStringList GCUserView::nickList() const
284
for(QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling())
285
list << lvi->text(0);
287
qstringlistisort(list); // caseless sorting
291
QListViewItem *GCUserView::findEntry(const QString &nick)
293
for(QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling()) {
294
if(lvi->text(0) == nick)
300
void GCUserView::updateEntry(const QString &nick, const Status &s)
302
GCUserViewItem *lvi = (GCUserViewItem *)findEntry(nick);
304
lvi = new GCUserViewItem(this);
305
lvi->setText(0, nick);
309
lvi->setPixmap(0, is->status(lvi->s));
312
void GCUserView::removeEntry(const QString &nick)
314
QListViewItem *lvi = findEntry(nick);
319
void GCUserView::maybeTip(const QPoint &pos)
321
GCUserViewItem *lvi = (GCUserViewItem *)itemAt(pos);
325
QRect r(itemRect(lvi));
327
const QString &nick = lvi->text(0);
328
const Status &s = lvi->s;
330
// SICK SICK SICK SICK
331
u.setJid(((GCMainDlg *)topLevelWidget())->jid().withResource(nick));
334
// make a resource so the contact appears online
338
u.userResourceList().append(ur);
343
void GCUserView::qlv_doubleClicked(QListViewItem *i)
345
GCUserViewItem *lvi = (GCUserViewItem *)i;
349
if(option.defaultAction == 0)
350
action(lvi->text(0), lvi->s, 0);
352
action(lvi->text(0), lvi->s, 1);
355
void GCUserView::qlv_contextMenuRequested(QListViewItem *i, const QPoint &pos, int)
357
GCUserViewItem *lvi = (GCUserViewItem *)i;
361
QPopupMenu *pm = new QPopupMenu;
362
pm->insertItem(IconsetFactory::icon("psi/sendMessage"), tr("Send &message"), 0);
363
pm->insertItem(IconsetFactory::icon("psi/chat"), tr("Open &chat window"), 1);
364
pm->insertSeparator();
365
//pm->insertItem(tr("Send &file"), 4);
366
//pm->insertSeparator();
367
pm->insertItem(tr("Check &Status"), 2);
368
pm->insertItem(IconsetFactory::icon("psi/vCard"), tr("User &Info"), 3);
369
int x = pm->exec(pos);
374
action(lvi->text(0), lvi->s, x);
378
//----------------------------------------------------------------------------
380
//----------------------------------------------------------------------------
381
class GCMainDlg::Private : public QObject
385
enum { Connecting, Connected, Idle };
386
Private(GCMainDlg *d) {
389
typingStatus = Typing_Normal;
400
GCUserView *lv_users;
401
QPushButton *pb_topic;
402
IconAction *act_find;
403
IconToolButton *tb_clear, *tb_icon;
407
int trackBarParagraph;
415
QGuardedPtr<GCFindDlg> findDlg;
419
void addEmoticon(const Icon *icon) {
420
if ( !dlg->isActiveWindow() )
425
QDict<QString> itext = icon->text();
426
QDictIterator<QString> it ( itext );
427
for ( ; it.current(); ++it) {
428
if ( it.current() && !it.current()->isEmpty() ) {
429
text = *(it.current()) + " ";
434
if ( !text.isEmpty() )
438
void addEmoticon(QString text) {
439
if ( !dlg->isActiveWindow() )
442
mle->insert( text + " " );
445
void deferredScroll() {
446
//QTimer::singleShot(250, this, SLOT(slotScroll()));
447
te_log->scrollToBottom();
452
te_log->scrollToBottom();
456
// Nick auto-completion code follows...
461
Typing_MultipleSuggestions
463
TypingStatus typingStatus;
464
QString lastReferrer; // contains nick of last person, who have said "yourNick: ..."
465
QString nickSeparator; // in case of "nick: ...", it equals ":"
466
QStringList suggestedNicks;
468
bool suggestedFromStart;
470
QString beforeNickText(QString text) {
472
for (i = text.length() - 1; i >= 0; --i)
473
if ( text[i].isSpace() )
476
QString beforeNick = text.left(i+1);
480
QStringList suggestNicks(QString text, bool fromStart) {
481
QString nickText = text;
484
beforeNick = beforeNickText(text);
485
nickText = text.mid(beforeNick.length());
488
QStringList nicks = lv_users->nickList();
489
QStringList::Iterator it = nicks.begin();
490
QStringList suggestedNicks;
491
for ( ; it != nicks.end(); ++it) {
492
if ( (*it).left(nickText.length()).lower() == nickText.lower() ) {
494
suggestedNicks << *it;
496
suggestedNicks << beforeNick + *it;
500
return suggestedNicks;
503
QString longestSuggestedString(QStringList suggestedNicks) {
504
QString testString = suggestedNicks.first();
505
while ( testString.length() > 0 ) {
507
QStringList::Iterator it = suggestedNicks.begin();
508
for ( ; it != suggestedNicks.end(); ++it) {
509
if ( (*it).left(testString.length()).lower() != testString.lower() ) {
518
testString = testString.left( testString.length() - 1 );
524
QString insertNick(bool fromStart, QString beforeNick = "") {
525
typingStatus = Typing_MultipleSuggestions;
526
suggestedFromStart = fromStart;
527
suggestedNicks = lv_users->nickList();
528
QStringList::Iterator it = suggestedNicks.begin();
529
for ( ; it != suggestedNicks.end(); ++it)
530
*it = beforeNick + *it;
533
if ( !lastReferrer.isEmpty() ) {
534
newText = beforeNick + lastReferrer;
538
newText = suggestedNicks.first();
543
newText += nickSeparator;
550
QString suggestNick(bool fromStart, QString origText, bool *replaced) {
551
suggestedFromStart = fromStart;
552
suggestedNicks = suggestNicks(origText, fromStart);
556
if ( suggestedNicks.count() ) {
557
if ( suggestedNicks.count() == 1 ) {
558
newText = suggestedNicks.first();
560
newText += nickSeparator;
565
newText = longestSuggestedString(suggestedNicks);
566
if ( !newText.length() )
569
typingStatus = Typing_MultipleSuggestions;
570
// TODO: display a tooltip that will contain all suggestedNicks
579
void doAutoNickInsertion() {
581
mle->getCursorPosition(¶, &index);
582
QString paraText = mle->text(para);
583
QString origText = paraText.left(index);
586
bool replaced = false;
588
if ( typingStatus == Typing_MultipleSuggestions ) {
590
if ( suggestedIndex >= (int)suggestedNicks.count() )
593
newText = suggestedNicks[suggestedIndex];
594
if ( suggestedFromStart ) {
595
newText += nickSeparator;
602
if ( !para && !replaced ) {
603
if ( !index && typingStatus == Typing_TabbingNicks ) {
604
newText = insertNick(true, "");
608
newText = suggestNick(true, origText, &replaced);
613
if ( (!index || origText[index-1].isSpace()) && typingStatus == Typing_TabbingNicks ) {
614
newText = insertNick(false, beforeNickText(origText));
618
newText = suggestNick(false, origText, &replaced);
623
mle->setUpdatesEnabled( false );
624
QString newParaText = newText + paraText.mid(index, paraText.length() - index - 1);
625
mle->insertParagraph(newParaText, para);
626
mle->removeParagraph(para+1);
627
mle->setCursorPosition(para, newText.length());
628
mle->setUpdatesEnabled( true );
629
mle->viewport()->update();
633
bool eventFilter( QObject *obj, QEvent *ev ) {
634
if ( obj == mle && ev->type() == QEvent::KeyPress ) {
635
QKeyEvent *e = (QKeyEvent *)ev;
637
if ( e->key() == Key_Tab ) {
638
switch ( typingStatus ) {
640
typingStatus = Typing_TabPressed;
642
case Typing_TabPressed:
643
typingStatus = Typing_TabbingNicks;
649
doAutoNickInsertion();
653
typingStatus = Typing_Normal;
658
return QObject::eventFilter( obj, ev );
662
GCMainDlg::GCMainDlg(PsiAccount *pa, const Jid &j)
663
:QWidget(0, 0, WDestructiveClose)
666
d = new Private(this);
668
d->jid = j.userHost();
669
d->self = j.resource();
670
d->pa->dialogRegister(this, d->jid);
671
connect(d->pa, SIGNAL(updatedActivity()), SLOT(pa_updatedActivity()));
680
d->trackBarParagraph = 0;
682
d->state = Private::Connected;
685
setIcon(IconsetFactory::icon("psi/groupChat"));
688
d->act_find = new IconAction(tr("Find"), "psi/search", tr("&Find"), CTRL+Key_F, this);
689
connect(d->act_find, SIGNAL(activated()), SLOT(openFind()));
691
QVBoxLayout *dlg_layout = new QVBoxLayout(this);
693
QSplitter *vsplit = new QSplitter(this);
694
vsplit->setOrientation( QSplitter::Vertical );
695
dlg_layout->addWidget(vsplit);
698
QWidget *sp_top = new QWidget(vsplit);
699
QVBoxLayout *vb_top = new QVBoxLayout(sp_top, 4);
702
QHBoxLayout *hb_top = new QHBoxLayout(vb_top);
704
d->pb_topic = new QPushButton(tr("Topic:"), sp_top);
705
connect(d->pb_topic, SIGNAL(clicked()), SLOT(doTopic()));
706
hb_top->addWidget(d->pb_topic);
708
d->le_topic = new QLineEdit(sp_top);
709
d->le_topic->setReadOnly(true);
710
hb_top->addWidget(d->le_topic);
712
IconToolButton *tb_find = new IconToolButton(sp_top);
713
tb_find->setIcon(IconsetFactory::iconPtr("psi/search"));
714
connect(tb_find, SIGNAL(clicked()), SLOT(openFind()));
715
hb_top->addWidget(tb_find);
717
QLabel *lb_ident = d->pa->accountLabel(sp_top, true);
718
lb_ident->setSizePolicy(QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ));
719
hb_top->addWidget(lb_ident);
722
QSplitter *hsp = new QSplitter(sp_top);
723
hsp->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
724
vb_top->addWidget(hsp);
725
hsp->setOrientation(QSplitter::Horizontal);
727
d->te_log = new ChatView(hsp);
728
d->te_log->setTextFormat( RichText );
730
d->lv_users = new GCUserView(hsp);
731
d->lv_users->setMinimumWidth(20);
732
connect(d->lv_users, SIGNAL(action(const QString &, const Status &, int)), SLOT(lv_action(const QString &, const Status &, int)));
734
// --- bottom part ---
735
QWidget *sp_bottom = new QWidget(vsplit);
736
QVBoxLayout *vb_bottom = new QVBoxLayout(sp_bottom, 4);
740
//connect(pa->psi->iconSelectPopup(), SIGNAL(iconSelected(const Icon *)), d, SLOT(addEmoticon(const Icon *)));
741
connect(pa->psi()->iconSelectPopup(), SIGNAL(textSelected(QString)), d, SLOT(addEmoticon(QString)));
743
d->tb_clear = new IconToolButton(sp_bottom) ;
744
d->tb_clear->setIcon(IconsetFactory::iconPtr("psi/clearChat"));
745
connect(d->tb_clear, SIGNAL(clicked()), SLOT(doClearButton()));
747
d->tb_icon = new IconToolButton(sp_bottom);
748
d->tb_icon->setIcon(IconsetFactory::iconPtr("psi/smile"));
749
d->tb_icon->setPopup(pa->psi()->iconSelectPopup());
750
d->tb_icon->setPopupDelay (1);
752
QHBoxLayout *toolbox = new QHBoxLayout(vb_bottom);
753
toolbox->addWidget(d->tb_clear);
754
toolbox->addStretch();
755
toolbox->addWidget(d->tb_icon);
758
d->mle = new ChatEdit(sp_bottom);
759
//d->mle->setFixedHeight(48);
760
vb_bottom->addWidget(d->mle);
761
d->mle->installEventFilter( d );
763
// resize the horizontal splitter
764
QValueList<int> list;
772
vsplit->setSizes(list);
776
X11WM_CLASS("groupchat");
784
GCMainDlg::~GCMainDlg()
786
if(d->state != Private::Idle)
787
d->pa->groupChatLeave(d->jid.host(), d->jid.user());
789
//QMimeSourceFactory *m = d->te_log->mimeSourceFactory();
790
//d->te_log->setMimeSourceFactory(0);
793
d->pa->dialogUnregister(this);
797
void GCMainDlg::keyPressEvent(QKeyEvent *e)
799
if(e->key() == Key_Return || e->key() == Key_Enter || (e->key() == Key_S && (e->state() & AltButton)))
801
else if(e->key() == Key_PageUp && (e->state() & ShiftButton))
802
d->te_log->setContentsPos(d->te_log->contentsX(), d->te_log->contentsY() - d->te_log->visibleHeight()/2);
803
else if(e->key() == Key_PageDown && (e->state() & ShiftButton))
804
d->te_log->setContentsPos(d->te_log->contentsX(), d->te_log->contentsY() + d->te_log->visibleHeight()/2);
809
void GCMainDlg::closeEvent(QCloseEvent *e)
814
void GCMainDlg::windowActivationChange(bool oldstate)
816
QWidget::windowActivationChange(oldstate);
818
// if we're bringing it to the front, get rid of the '*' if necessary
819
if(isActiveWindow()) {
833
void GCMainDlg::mle_returnPressed()
835
if(d->mle->text().isEmpty())
838
QString str = d->mle->text();
839
if(str == "/clear") {
843
d->hist.prepend(str);
848
if(str.lower().startsWith("/nick ")) {
849
QString nick = str.mid(6).stripWhiteSpace();
850
if ( !nick.isEmpty() ) {
852
d->pa->groupChatChangeNick(d->jid.host(), d->jid.user(), d->self, d->pa->status());
858
if(d->state != Private::Connected)
862
m.setType("groupchat");
864
m.setTimeStamp(QDateTime::currentDateTime());
869
d->hist.prepend(str);
873
/*void GCMainDlg::le_upPressed()
875
if(d->histAt < (int)d->hist.count()) {
877
d->le_input->setText(d->hist[d->histAt-1]);
881
void GCMainDlg::le_downPressed()
886
d->le_input->setText("");
888
d->le_input->setText(d->hist[d->histAt-1]);
892
void GCMainDlg::doTopic()
895
QString str = QInputDialog::getText(
896
tr("Set Groupchat Topic"),
897
tr("Enter a topic:"),
898
QLineEdit::Normal, d->le_topic->text(), &ok, this);
902
m.setType("groupchat");
904
m.setBody(QString("/me ") + tr("has set the topic to: %1").arg(str));
905
m.setTimeStamp(QDateTime::currentDateTime());
910
void GCMainDlg::doClear()
912
d->te_log->setText("");
915
void GCMainDlg::doClearButton()
917
int n = QMessageBox::information(this, tr("Warning"), tr("Are you sure you want to clear the chat window?\n(note: does not affect saved history)"), tr("&Yes"), tr("&No"));
922
void GCMainDlg::openFind()
925
bringToFront(d->findDlg);
927
d->findDlg = new GCFindDlg(0, 0, d->lastSearch, this);
928
connect(d->findDlg, SIGNAL(find(int, int, const QString &)), SLOT(doFind(int, int, const QString &)));
933
void GCMainDlg::doFind(int para, int index, const QString &str)
937
if(!d->te_log->find(str, false, false, true, ¶, &index))
938
d->findDlg->error(str);
940
// pass one character over
941
d->findDlg->found(para, index+1);
945
void GCMainDlg::goDisc()
947
if(d->state != Private::Idle) {
948
d->state = Private::Idle;
949
d->pb_topic->setEnabled(false);
950
appendSysMsg(tr("Disconnected."), true);
954
void GCMainDlg::goConn()
956
if(d->state == Private::Idle) {
957
d->state = Private::Connecting;
958
appendSysMsg(tr("Reconnecting..."), true);
960
QString host = d->jid.host();
961
QString room = d->jid.user();
962
QString nick = d->self;
964
if(!d->pa->groupChatJoin(host, room, nick)) {
965
appendSysMsg(tr("Error: You are in or joining this room already!"), true);
966
d->state = Private::Idle;
971
void GCMainDlg::pa_updatedActivity()
973
if(!d->pa->loggedIn())
976
if(d->state == Private::Idle)
978
else if(d->state == Private::Connected)
979
d->pa->groupChatSetStatus(d->jid.host(), d->jid.user(), d->pa->status());
983
Jid GCMainDlg::jid() const
988
void GCMainDlg::error(int, const QString &str)
990
d->pb_topic->setEnabled(false);
992
if(d->state == Private::Connecting)
993
appendSysMsg(tr("Unable to join groupchat. Reason: %1").arg(str), true);
995
appendSysMsg(tr("Unexpected groupchat error: %1").arg(str), true);
997
d->state = Private::Idle;
1000
void GCMainDlg::presence(const QString &nick, const Status &s)
1002
if(s.isAvailable()) {
1003
/*if ((option.showJoins)&&(d->lv_users->findEntry(nick)==0)) {
1005
QString m=nick+tr(" has joined the channel");
1006
appendSysMsg(m, false, QDateTime::currentDateTime());
1008
d->lv_users->updateEntry(nick, s);
1010
/*if (option.showJoins) {
1012
QString m=nick+tr(" has left the channel");
1013
appendSysMsg(m, false, QDateTime::currentDateTime());
1015
d->lv_users->removeEntry(nick);
1019
void GCMainDlg::message(const Message &m)
1021
QString from = m.from().resource();
1024
if(!m.subject().isEmpty()) {
1025
d->le_topic->setText(m.subject());
1026
d->le_topic->setCursorPosition(0);
1027
QToolTip::add(d->le_topic, QString("<qt><p>%1</p></qt>").arg(m.subject()));
1030
// code to determine if the speaker was addressing this client in chat
1031
if(m.body().contains(d->self) > 0)
1034
if (m.body().left(d->self.length()) == d->self)
1035
d->lastReferrer = m.from().resource();
1037
if(option.gcHighlighting) {
1038
for(QStringList::Iterator it=option.gcHighlights.begin();it!=option.gcHighlights.end();it++) {
1039
if(m.body().contains((*it),false) > 0) {
1046
if(from == d->self) {
1048
d->pa->playSound(option.onevent[eSend]);
1051
if(alert || (!option.noGCSound && !m.spooled() && !from.isEmpty()) )
1052
d->pa->playSound(option.onevent[eChat2]);
1056
appendSysMsg(m.body(), alert, m.timeStamp());
1058
appendMessage(m, alert);
1061
void GCMainDlg::joined()
1063
if(d->state == Private::Connecting) {
1064
d->lv_users->QListView::clear();
1065
d->state = Private::Connected;
1066
d->pb_topic->setEnabled(true);
1067
appendSysMsg(tr("Connected."), true);
1071
void GCMainDlg::appendSysMsg(const QString &str, bool alert, const QDateTime &ts)
1073
bool atBottom = d->te_log->contentsY() >= d->te_log->contentsHeight() - d->te_log->visibleHeight();
1077
hr = QString("<hr>");
1078
d->trackBar = false;
1080
if ( d->trackBarParagraph ) {
1081
d->te_log->setUpdatesEnabled( false );
1082
d->te_log->setSelection(d->trackBarParagraph, 0, d->trackBarParagraph, 1, 1);
1083
d->te_log->removeSelectedText(1);
1084
d->te_log->setUpdatesEnabled( true );
1086
d->trackBarParagraph = d->te_log->paragraphs();
1090
if (!option.gcHighlighting)
1097
time = QDateTime::currentDateTime();
1099
//timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
1100
timestr = time.time().toString(LocalDate);
1102
/*int y = d->te_log->contentsHeight() - d->te_log->visibleHeight();
1105
bool atBottom = (d->te_log->contentsY() < y - 32) ? false: true;*/
1107
d->te_log->append(hr + QString("<font color=\"#00A000\">[%1]").arg(timestr) + QString(" *** %1</font>").arg(expandEntities(str)));
1110
d->deferredScroll();
1116
QString GCMainDlg::getNickColor(QString nick)
1119
if(nick == d->self||nick.isEmpty())
1122
if (!nicks.contains(nick)) {
1124
nicks.insert(nick,nicknumber);
1130
if(!option.gcNickColoring || option.gcNickColors.empty()) {
1133
else if(sender == -1 || option.gcNickColors.size() == 1) {
1134
return option.gcNickColors[option.gcNickColors.size()-1];
1137
int n = sender % (option.gcNickColors.size()-1);
1138
return option.gcNickColors[n];
1142
void GCMainDlg::appendMessage(const Message &m, bool alert)
1144
//QString who, color;
1145
if (!option.gcHighlighting)
1147
QString who, textcolor, nickcolor,alerttagso,alerttagsc;
1149
bool atBottom = d->te_log->contentsY() >= d->te_log->contentsHeight() - d->te_log->visibleHeight();
1151
who = m.from().resource();
1153
if (d->trackBar&&m.from().resource() != d->self&&!m.spooled()) {
1154
hr = QString("<hr>");
1155
d->trackBar = false;
1157
if ( d->trackBarParagraph ) {
1158
d->te_log->setUpdatesEnabled( false );
1159
d->te_log->setSelection(d->trackBarParagraph, 0, d->trackBarParagraph, 1, 1);
1160
d->te_log->removeSelectedText(1);
1161
d->te_log->setUpdatesEnabled( true );
1163
d->trackBarParagraph = d->te_log->paragraphs();
1171
nickcolor = getNickColor(who);
1172
textcolor = d->te_log->palette().active().text().name();
1174
textcolor = "#FF0000";
1176
alerttagsc = "</b>";
1179
nickcolor = "#008000"; //color = "#008000";
1182
QDateTime time = m.timeStamp();
1183
//timestr.sprintf("%02d:%02d:%02d", time.time().hour(), time.time().minute(), time.time().second());
1184
timestr = time.time().toString(LocalDate);
1186
/*int y = d->te_log->contentsHeight() - d->te_log->visibleHeight();
1189
bool atBottom = (d->te_log->contentsY() < y - 32) ? false: true;*/
1192
if(m.body().left(4) == "/me ")
1197
txt = plain2rich(m.body().mid(4));
1199
txt = plain2rich(m.body());
1203
if(option.useEmoticons)
1204
txt = emoticonify(txt);
1207
//d->te_log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(expandEntities(who)) + txt + "</font>");
1208
d->te_log->append(hr + QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1]").arg(timestr) + QString(" *%1 ").arg(expandEntities(who)) + alerttagso + txt + alerttagsc + "</font>");
1211
if(option.chatSays) {
1212
//d->te_log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] ").arg(timestr) + QString("%1 says:").arg(expandEntities(who)) + "</font><br>" + txt);
1213
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>");
1216
//d->te_log->append(QString("<font color=\"%1\">").arg(color) + QString("[%1] <").arg(timestr) + expandEntities(who) + QString("></font> ") + txt);
1217
d->te_log->append(hr + QString("<font color=\"%1\">").arg(nickcolor) + QString("[%1] <").arg(timestr) + expandEntities(who) + QString("></font> ") + QString("<font color=\"%1\">").arg(textcolor) + alerttagso + txt + alerttagsc +"</font>");
1221
//if(local || atBottom)
1222
if(m.from().resource() == d->self || atBottom)
1223
d->deferredScroll();
1225
// if we're not active, notify the user by changing the title
1226
if(!isActiveWindow()) {
1231
//if someone directed their comments to us, notify the user
1235
//if the message spoke to us, alert the user before closing this window
1236
//except that keepopen doesn't seem to be implemented for this class yet.
1239
QTimer::singleShot(1000, this, SLOT(setKeepOpenFalse()));
1243
void GCMainDlg::doAlert()
1245
if(!isActiveWindow())
1249
void GCMainDlg::updateCaption()
1253
if(d->pending > 0) {
1256
cap += QString("[%1] ").arg(d->pending);
1258
cap += d->jid.full();
1260
// if taskbar flash, then we need to erase first and redo
1264
on = d->flashCount & 1;
1266
FlashWindow(winId(), true);
1271
FlashWindow(winId(), true);
1276
void GCMainDlg::doFlash(bool yes)
1281
d->flashTimer = new QTimer(this);
1282
connect(d->flashTimer, SIGNAL(timeout()), SLOT(flashAnimate()));
1284
flashAnimate(); // kick the first one immediately
1285
d->flashTimer->start(500);
1289
delete d->flashTimer;
1291
FlashWindow(winId(), false);
1296
void GCMainDlg::doFlash(bool)
1301
void GCMainDlg::flashAnimate()
1304
FlashWindow(winId(), true);
1306
if(d->flashCount == 5)
1307
d->flashTimer->stop();
1311
void GCMainDlg::setLooks()
1315
f.fromString(option.font[fChat]);
1316
d->te_log->setFont(f);
1319
f.fromString(option.font[fRoster]);
1320
d->lv_users->QListView::setFont(f);
1322
if ( option.useEmoticons ) {
1323
//d->tb_clear->show();
1327
//d->tb_clear->hide();
1331
// update the widget icon
1333
setIcon(IconsetFactory::icon("psi/groupChat"));
1337
void GCMainDlg::optionsUpdate()
1339
/*QMimeSourceFactory *m = d->te_log->mimeSourceFactory();
1340
d->te_log->setMimeSourceFactory(is->emoticons.generateFactory());
1345
// update status icons
1346
d->lv_users->updateAll();
1349
void GCMainDlg::lv_action(const QString &nick, const Status &s, int x)
1352
d->pa->invokeGCMessage(d->jid.withResource(nick));
1355
d->pa->invokeGCChat(d->jid.withResource(nick));
1359
u.setJid(d->jid.withResource(nick));
1362
// make a resource so the contact appears online
1366
u.userResourceList().append(ur);
1368
StatusShowDlg *w = new StatusShowDlg(u);
1372
d->pa->invokeGCInfo(d->jid.withResource(nick));
1375
d->pa->invokeGCFile(d->jid.withResource(nick));
1380
//----------------------------------------------------------------------------
1382
//----------------------------------------------------------------------------
1383
GCFindDlg::GCFindDlg(int startPara, int startIndex, const QString &str, QWidget *parent, const char *name)
1384
:QDialog(parent, name, false, WDestructiveClose)
1389
setCaption(tr("Find"));
1390
QVBoxLayout *vb = new QVBoxLayout(this, 4);
1391
QHBoxLayout *hb = new QHBoxLayout(vb);
1392
QLabel *l = new QLabel(tr("Find:"), this);
1394
le_input = new QLineEdit(this);
1395
hb->addWidget(le_input);
1398
QFrame *Line1 = new QFrame(this);
1399
Line1->setFrameShape( QFrame::HLine );
1400
Line1->setFrameShadow( QFrame::Sunken );
1401
Line1->setFrameShape( QFrame::HLine );
1402
vb->addWidget(Line1);
1404
hb = new QHBoxLayout(vb);
1406
QPushButton *pb_close = new QPushButton(tr("&Close"), this);
1407
connect(pb_close, SIGNAL(clicked()), SLOT(close()));
1408
hb->addWidget(pb_close);
1409
QPushButton *pb_find = new QPushButton(tr("&Find"), this);
1410
pb_find->setDefault(true);
1411
connect(pb_find, SIGNAL(clicked()), SLOT(doFind()));
1412
hb->addWidget(pb_find);
1413
pb_find->setAutoDefault(true);
1415
resize(200, minimumSize().height());
1417
le_input->setText(str);
1418
le_input->setFocus();
1421
GCFindDlg::~GCFindDlg()
1425
void GCFindDlg::found(int _para, int _index)
1431
void GCFindDlg::error(const QString &str)
1433
QMessageBox::warning(this, tr("Find"), tr("Search string '%1' not found.").arg(str));
1434
le_input->setFocus();
1437
void GCFindDlg::doFind()
1439
find(para, index, le_input->text());
1442
#include "groupchatdlg.moc"