2
* psipopup.cpp - the Psi passive popup class
3
* Copyright (C) 2003 Michail Pishchagin
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
23
#include "fancypopup.h"
24
#include "fancylabel.h"
26
#include "alerticon.h"
30
#include "psiaccount.h"
32
#include <qapplication.h>
35
//----------------------------------------------------------------------------
37
//----------------------------------------------------------------------------
39
class PsiPopupList : public QObject, public QPtrList<PsiPopup>
56
return QPtrList<PsiPopup>::first();
59
void prepend(const PsiPopup *d)
64
connect(d, SIGNAL(destroyed(QObject *)), SLOT(popupDestroyed(QObject *)));
65
QPtrList<PsiPopup>::prepend(d);
73
void popupDestroyed(QObject *p)
76
remove((PsiPopup *)p);
84
static PsiPopupList *psiPopupList = 0;
86
//----------------------------------------------------------------------------
88
//----------------------------------------------------------------------------
90
class PsiPopup::Private : public QObject
97
void init(const Icon *titleIcon, QString titleText, PsiAccount *_acc, PopupType type);
98
QString clipText(QString);
99
QBoxLayout *createContactInfo(const Icon *icon, QString text);
102
void popupDestroyed();
103
void popupClicked(int);
104
void eventDestroyed();
120
PsiPopup::Private::Private(PsiPopup *p)
124
popupType = AlertNone;
129
PsiPopup::Private::~Private()
138
void PsiPopup::Private::init(const Icon *_titleIcon, QString titleText, PsiAccount *acc, PopupType type)
145
psiPopupList = new PsiPopupList();
147
FancyPopup *last = 0;
148
if ( psiPopupList->last() )
149
last = psiPopupList->last()->popup();
151
if ( type != AlertNone )
152
titleIcon = new AlertIcon(_titleIcon);
154
titleIcon = new Icon(*_titleIcon);
156
FancyPopup::setHideTimeout( option.ppHideTime );
157
FancyPopup::setBorderColor( option.ppBorderColor );
159
popup = new FancyPopup(titleText, titleIcon, last, false);
160
connect(popup, SIGNAL(clicked(int)), SLOT(popupClicked(int)));
161
connect(popup, SIGNAL(destroyed()), SLOT(popupDestroyed()));
165
id += _titleIcon->name();
169
void PsiPopup::Private::popupDestroyed()
172
psiPopup->deleteLater();
175
void PsiPopup::Private::popupClicked(int button)
177
if ( button == (int)LeftButton ) {
179
psi->processEvent( event );
180
else if ( account ) {
181
// FIXME: it should work in most cases, but
182
// maybe it's better to fix UserList::find()?
183
Jid j( jid.userHost() );
184
account->actionDefault( j );
192
void PsiPopup::Private::eventDestroyed()
194
if ( (popupType == AlertMessage || popupType == AlertHeadline) && !option.popupMsgs )
196
if ( popupType == AlertChat && !option.popupChats /*&& option.alertOpenChats*/ )
198
if ( popupType == AlertHeadline && !option.popupHeadlines)
204
QString PsiPopup::Private::clipText(QString text)
206
if ( option.ppTextClip > 0 ) {
207
// richtext will give us trouble here
208
if ( ((int)text.length()) > option.ppTextClip ) {
209
text = text.left( option.ppTextClip );
211
// delete last unclosed tag
212
/*if ( text.find("</") > text.find(">") ) {
214
text = text.left( text.find("</") );
224
QBoxLayout *PsiPopup::Private::createContactInfo(const Icon *icon, QString text)
226
QHBoxLayout *dataBox = new QHBoxLayout(0);
229
IconLabel *iconLabel = new IconLabel(popup);
230
iconLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
231
iconLabel->setIcon(icon);
232
dataBox->addWidget(iconLabel);
234
dataBox->addSpacing(5);
237
IconLabel *textLabel = new IconLabel(popup);
239
font.fromString( option.font[fPopup] );
240
textLabel->setFont(font);
242
textLabel->setText(QString("<qt>%1</qt>").arg(clipText(text)));
243
textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
244
dataBox->addWidget(textLabel);
249
//----------------------------------------------------------------------------
251
//----------------------------------------------------------------------------
253
PsiPopup::PsiPopup(const Icon *titleIcon, QString titleText, PsiAccount *acc)
255
d = new Private(this);
256
d->init(titleIcon, titleText, acc, AlertNone);
259
PsiPopup::~PsiPopup()
264
PsiPopup::PsiPopup(PopupType type, PsiAccount *acc)
266
d = new Private(this);
270
QString text = "Psi: ";
271
bool doAlertIcon = false;
275
text += PsiPopup::tr("Contact online");
276
icon = (Icon *)IconsetFactory::iconPtr("status/online");
279
text += PsiPopup::tr("Contact offline");
280
icon = (Icon *)IconsetFactory::iconPtr("status/offline");
282
case AlertStatusChange:
283
text += PsiPopup::tr("Status change");
284
icon = (Icon *)IconsetFactory::iconPtr("status/online");
287
text += PsiPopup::tr("Incoming message");
288
icon = (Icon *)IconsetFactory::iconPtr("psi/message");
292
text += PsiPopup::tr("Incoming chat message");
293
icon= (Icon *)IconsetFactory::iconPtr("psi/chat");
297
text += PsiPopup::tr("Headline");
298
icon= (Icon *)IconsetFactory::iconPtr("psi/headline");
305
d->init(icon, text, acc, doAlertIcon ? type : AlertNone);
308
void PsiPopup::setData(const Icon *icon, QString text)
315
d->popup->addLayout( d->createContactInfo(icon, text) );
319
d->id += icon->name();
325
void PsiPopup::setData(const Jid &j, const Resource &r, const UserListItem *u, const PsiEvent *event)
333
d->status = r.status();
334
d->event = (PsiEvent *)event;
337
connect(event, SIGNAL(destroyed()), d, SLOT(eventDestroyed()));
339
Icon *icon = is->statusPtr(j, r.status());
342
QString jid = j.full();
343
if ( option.ppJidClip > 0 && ((int)jid.length()) > option.ppJidClip )
344
jid = jid.left( option.ppJidClip ) + "...";
347
if ( option.ppStatusClip != 0 )
348
status = r.status().status();
349
if ( option.ppStatusClip > 0 )
350
if ( ((int)status.length()) > option.ppStatusClip )
351
status = status.left ( option.ppStatusClip ) + "...";
354
if ( u && !u->name().isEmpty() ) {
355
if ( !option.ppJidClip )
356
name = "<nobr>" + u->name() + "</nobr>";
358
name = "<nobr>" + u->name() + " <" + jid + ">" + "</nobr>";
361
name = "<nobr><" + jid + "></nobr>";
363
QString statusString = plain2rich(status);
364
if ( option.useEmoticons )
365
statusString = emoticonify(statusString);
367
if ( !statusString.isEmpty() )
368
statusString = "<br>" + statusString;
370
QString contactText = "<font size=\"+1\">" + name + "</font>" + statusString;
372
// hack for duplicate "Contact Online"/"Status Change" popups
373
PsiPopup *pp = psiPopupList->first();
375
if ( d->jid.full() == pp->d->jid.full() && d->status.show() == pp->d->status.show() && d->status.status() == d->status.status() ) {
376
if ( d->popupType == AlertStatusChange && pp->d->popupType == AlertOnline ) {
383
pp = psiPopupList->next();
387
if ( d->popupType != AlertHeadline )
388
setData(icon, contactText);
389
else if ( d->popupType == AlertHeadline ) {
390
QVBoxLayout *vbox = new QVBoxLayout(0);
391
vbox->addLayout( d->createContactInfo(icon, contactText) );
395
const Message *jmessage = &((MessageEvent *)event)->message();
397
if ( !jmessage->subject().isEmpty() )
398
message += "<font color=\"red\"><b>" + tr("Subject:") + " " + jmessage->subject() + "</b></font><br>";
399
message += plain2rich( jmessage->body() );
401
QLabel *messageLabel = new QLabel(d->popup);
402
QFont font = messageLabel->font();
403
font.setPointSize(option.smallFontSize);
404
messageLabel->setFont(font);
406
messageLabel->setTextFormat(RichText);
407
messageLabel->setText( d->clipText(linkify( message )) );
408
messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
409
vbox->addWidget(messageLabel);
413
d->id += icon->name();
414
d->id += contactText;
417
d->popup->addLayout( vbox );
422
void PsiPopup::show()
424
if ( !d->popup || !option.ppIsOn ) {
429
if ( !d->id.isEmpty() /*&& option.ppNoDupes*/ ) {
430
PsiPopup *pp = psiPopupList->first();
432
if ( d->id == pp->id() ) {
433
pp->popup()->restartHideTimer();
439
pp = psiPopupList->next();
443
// do not show popups when DND
444
if ( d->account->status().show() == "dnd" )
448
psiPopupList->prepend( this );
456
QString PsiPopup::id() const
461
FancyPopup *PsiPopup::popup()
466
void PsiPopup::deleteAll()
471
psiPopupList->clear();
476
#include "psipopup.moc"