source: psi/trunk/src/psiiconset.cpp@ 150

Last change on this file since 150 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 13.2 KB
Line 
1/*
2 * psiiconset.cpp - the Psi iconset class
3 * Copyright (C) 2001-2003 Justin Karneges, Michail Pishchagin
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include "psiiconset.h"
22#include "psievent.h"
23#include "common.h"
24#include "userlist.h"
25#include "anim.h"
26
27#include <qfileinfo.h>
28#include <qdict.h>
29#include <qptrlist.h>
30
31//----------------------------------------------------------------------------
32// PsiIconset
33//----------------------------------------------------------------------------
34
35class PsiIconset::Private
36{
37private:
38 PsiIconset *psi;
39public:
40 Iconset system;
41
42 Private(PsiIconset *_psi) {
43 psi = _psi;
44 psi->emoticons.setAutoDelete(true);
45 psi->roster.setAutoDelete(true);
46 }
47
48 QString iconsetPath(QString name) {
49 QStringList dirs;
50 dirs << ".";
51 dirs << g.pathHome;
52 dirs << g.pathBase;
53
54 QStringList::Iterator it = dirs.begin();
55 for ( ; it != dirs.end(); ++it) {
56 QString fileName = *it + "/iconsets/" + name;
57
58 QFileInfo fi(fileName);
59 if ( fi.exists() )
60 return fileName;
61 }
62
63 return QString::null;
64 }
65
66 void stripFirstAnimFrame(Iconset &is) {
67 QPtrListIterator<Icon> it = is.iterator();
68 for ( ; it.current(); ++it) {
69 it.current()->stripFirstAnimFrame();
70 }
71 }
72
73 void loadIconset(Iconset *to, Iconset *from) {
74 if ( !to ) {
75 qWarning("PsiIconset::loadIconset(): 'to' iconset is NULL!");
76 if ( from )
77 qWarning("from->name() = '%s'", from->name().latin1());
78 return;
79 }
80 if ( !from ) {
81 qWarning("PsiIconset::loadIconset(): 'from' iconset is NULL!");
82 if ( to )
83 qWarning("to->name() = '%s'", to->name().latin1());
84 return;
85 }
86
87 QPtrListIterator<Icon> it = from->iterator();
88 for ( ; it.current(); ++it) {
89 Icon *icon = it.current();
90
91 if ( icon && !icon->name().isEmpty() ) {
92 Icon *toIcon = (Icon *)to->icon(icon->name());
93 if ( toIcon ) {
94 if ( icon->anim() ) {
95 toIcon->setAnim ( *icon->anim(), false );
96 toIcon->setImpix ( icon->impix(), false );
97 }
98 else {
99 toIcon->setAnim ( Anim(), false );
100 toIcon->setImpix ( icon->impix(), false );
101 }
102 }
103 else
104 to->setIcon( icon->name(), *icon );
105 }
106 }
107
108 to->setInformation(*from);
109 }
110
111 Icon *jid2icon(const Jid &jid, const QString &iconName)
112 {
113 // first level -- global default icon
114 Icon *icon = (Icon *)IconsetFactory::iconPtr(iconName);
115
116 // second level -- transport icon
117 if ( jid.user().isEmpty() || option.useTransportIconsForContacts ) {
118 QMap<QString, QRegExp> services;
119 services["aim"] = QRegExp("^aim");
120 services["gadugadu"] = QRegExp("^gg");
121 services["icq"] = QRegExp("^icq");
122 services["msn"] = QRegExp("^msn");
123 services["yahoo"] = QRegExp("^yahoo");
124 services["sms"] = QRegExp("^sms");
125
126 bool found = false;
127
128 QMapIterator<QString, QRegExp> it = services.begin();
129 for ( ; it != services.end(); ++it) {
130 QRegExp rx = it.data();
131 if ( rx.search(jid.host()) != -1 ) {
132 // get the iconset name of the current service
133 QMapIterator<QString, QString> it2 = option.serviceRosterIconset.find(it.key());
134 if ( it2 != option.serviceRosterIconset.end() ) {
135 Iconset *is = psi->roster.find(it2.data());
136 if ( is ) {
137 Icon *i = (Icon *)is->icon(iconName);
138 if ( i ) {
139 icon = i;
140 found = true;
141 break;
142 }
143 }
144 }
145 }
146 }
147
148 // let's try the default transport iconset then...
149 if ( !found && jid.user().isEmpty() ) {
150 Iconset *is = psi->roster.find(option.serviceRosterIconset["transport"]);
151 if ( is ) {
152 Icon *i = (Icon *)is->icon(iconName);
153 if ( i )
154 icon = i;
155 }
156 }
157 }
158
159 // third level -- custom icons
160 QMapIterator<QString, QString> it = option.customRosterIconset.begin();
161 for ( ; it != option.customRosterIconset.end(); ++it) {
162 QRegExp rx = QRegExp(it.key());
163 if ( rx.search(jid.userHost()) != -1 ) {
164 Iconset *is = psi->roster.find(it.data());
165 if ( is ) {
166 Icon *i = (Icon *)is->icon(iconName);
167 if ( i )
168 icon = (Icon *)is->icon(iconName);
169 }
170 }
171 }
172
173 return icon;
174 }
175
176 Iconset systemIconset(bool *ok)
177 {
178 Iconset def;
179 *ok = def.load ( iconsetPath("system/default") );
180
181 if ( option.systemIconset != "default" ) {
182 Iconset is;
183 is.load ( iconsetPath("system/" + option.systemIconset) );
184
185 loadIconset(&def, &is);
186 }
187
188 stripFirstAnimFrame( def );
189
190 return def;
191 }
192
193 Iconset *defaultRosterIconset(bool *ok)
194 {
195 Iconset *def = new Iconset;
196 *ok = def->load ( iconsetPath("roster/default") );
197
198 if ( option.defaultRosterIconset != "default" ) {
199 Iconset is;
200 is.load ( iconsetPath("roster/" + option.defaultRosterIconset) );
201
202 loadIconset(def, &is);
203 }
204
205 stripFirstAnimFrame( *def );
206
207 return def;
208 }
209
210 QPtrList<Iconset> emoticons()
211 {
212 QPtrList<Iconset> emo;
213
214 QStringList::Iterator it3 = option.emoticons.begin();
215 for ( ; it3 != option.emoticons.end(); ++it3) {
216 Iconset *is = new Iconset;
217 if ( is->load ( iconsetPath("emoticons/" + *it3) ) ) {
218 PsiIconset::removeAnimation(is);
219 is->addToFactory();
220 emo.append( is );
221 }
222 else
223 delete is;
224 }
225
226 return emo;
227 }
228};
229
230PsiIconset::PsiIconset()
231{
232 d = new Private(this);
233}
234
235PsiIconset::~PsiIconset()
236{
237 delete d;
238}
239
240bool PsiIconset::loadSystem()
241{
242 bool ok;
243 Iconset sys = d->systemIconset(&ok);
244 d->loadIconset( &d->system, &sys );
245
246 //d->system = d->systemIconset();
247 d->system.addToFactory();
248
249 return ok;
250}
251
252bool PsiIconset::loadAll()
253{
254 if ( !loadSystem() )
255 return false;
256
257 bool ok;
258
259 // load roster
260 roster.clear();
261
262 // default roster iconset
263 Iconset *def = d->defaultRosterIconset(&ok);
264 def->addToFactory();
265 roster.insert (option.defaultRosterIconset, def);
266
267 // load only necessary roster iconsets
268 QStringList rosterIconsets;
269
270 QMap<QString, QString>::Iterator it = option.serviceRosterIconset.begin();
271 for ( ; it != option.serviceRosterIconset.end(); ++it)
272 if ( rosterIconsets.findIndex( it.data() ) == -1 )
273 rosterIconsets << it.data();
274
275 it = option.customRosterIconset.begin();
276 for ( ; it != option.customRosterIconset.end(); ++it)
277 if ( rosterIconsets.findIndex( it.data() ) == -1 )
278 rosterIconsets << it.data();
279
280 QStringList::Iterator it2 = rosterIconsets.begin();
281 for ( ; it2 != rosterIconsets.end(); ++it2) {
282 if ( *it2 == option.defaultRosterIconset )
283 continue;
284
285 Iconset *is = new Iconset;
286 if ( is->load (d->iconsetPath("roster/" + *it2)) ) {
287 is->addToFactory ();
288 d->stripFirstAnimFrame( *is );
289 roster.insert (*it2, is);
290 }
291 else
292 delete is;
293 }
294
295 // load emoticons
296 emoticons.clear();
297 emoticons = d->emoticons();
298
299 return ok;
300}
301
302bool PsiIconset::optionsChanged(const Options *old)
303{
304 bool ok = loadSystem();
305
306 // default roster iconset
307 if ( old->defaultRosterIconset != option.defaultRosterIconset ) {
308 Iconset *newDef = d->defaultRosterIconset(&ok);
309 Iconset *oldDef = roster[old->defaultRosterIconset];
310 d->loadIconset( oldDef, newDef );
311
312 roster.setAutoDelete(false);
313 roster.remove(old->defaultRosterIconset);
314 roster.setAutoDelete(true);
315
316 roster.insert (option.defaultRosterIconset, oldDef);
317 delete newDef;
318 }
319
320 // service&custom roster iconsets
321 if ( old->serviceRosterIconset != option.serviceRosterIconset || old->customRosterIconset != option.customRosterIconset ) {
322 QStringList rosterIconsets;
323
324 QMap<QString, QString>::Iterator it = option.serviceRosterIconset.begin();
325 for ( ; it != option.serviceRosterIconset.end(); ++it)
326 if ( rosterIconsets.findIndex( it.data() ) == -1 )
327 rosterIconsets << it.data();
328
329 it = option.customRosterIconset.begin();
330 for ( ; it != option.customRosterIconset.end(); ++it)
331 if ( rosterIconsets.findIndex( it.data() ) == -1 )
332 rosterIconsets << it.data();
333
334 QStringList::Iterator it2 = rosterIconsets.begin();
335 for ( ; it2 != rosterIconsets.end(); ++it2) {
336 if ( *it2 == option.defaultRosterIconset )
337 continue;
338
339 Iconset *is = new Iconset;
340 if ( is->load (d->iconsetPath("roster/" + *it2)) ) {
341 d->stripFirstAnimFrame( *is );
342 Iconset *oldis = roster[*it2];
343
344 if ( oldis )
345 d->loadIconset( oldis, is );
346 else {
347 is->addToFactory ();
348 roster.insert (*it2, is);
349 }
350 }
351 else
352 delete is;
353 }
354
355 bool clear = false;
356 while ( !clear ) {
357 clear = true;
358
359 QDictIterator<Iconset> it3 ( roster );
360 for ( ; it3.current(); ++it3) {
361 QString name = it3.currentKey();
362 if ( name == option.defaultRosterIconset )
363 continue;
364
365 it2 = rosterIconsets.find( name );
366 if ( it2 == rosterIconsets.end() ) {
367 // remove redundant iconset
368 roster.remove( name );
369 clear = false;
370 break;
371 }
372 }
373 }
374 }
375
376 // load emoticons
377 if ( old->emoticons != option.emoticons ) {
378 emoticons.clear();
379 emoticons = d->emoticons();
380 }
381
382 return old->defaultRosterIconset != option.defaultRosterIconset;
383}
384
385Icon *PsiIconset::event2icon(PsiEvent *e)
386{
387 QString icon;
388 if(e->type() == PsiEvent::Message) {
389 MessageEvent *me = (MessageEvent *)e;
390 const Message &m = me->message();
391 if(m.type() == "headline")
392 icon = "psi/headline";
393 else if(m.type() == "chat")
394 icon = "psi/chat";
395 else if(m.type() == "error")
396 icon = "psi/system";
397 else
398 icon = "psi/message";
399 }
400 else if(e->type() == PsiEvent::File) {
401 icon = "psi/file";
402 }
403 else {
404 icon = "psi/system";
405 }
406
407 return d->jid2icon(e->from(), icon);
408}
409
410static QString status2name(int s)
411{
412 QString name;
413 switch ( s ) {
414 case STATUS_OFFLINE:
415 name = "status/offline";
416 break;
417 case STATUS_AWAY:
418 name = "status/away";
419 break;
420 case STATUS_XA:
421 name = "status/xa";
422 break;
423 case STATUS_DND:
424 name = "status/dnd";
425 break;
426 case STATUS_INVISIBLE:
427 name = "status/invisible";
428 break;
429 case STATUS_CHAT:
430 name = "status/chat";
431 break;
432
433 case STATUS_ASK:
434 name = "status/ask";
435 break;
436 case STATUS_NOAUTH:
437 name = "status/noauth";
438 break;
439 case STATUS_ERROR:
440 name = "status/error";
441 break;
442
443 case -1:
444 name = "psi/connect";
445 break;
446
447 case STATUS_ONLINE:
448 default:
449 name = "status/online";
450 }
451
452 return name;
453}
454
455Icon *PsiIconset::statusPtr(int s)
456{
457 return (Icon *)IconsetFactory::iconPtr(status2name(s));
458}
459
460Icon PsiIconset::status(int s)
461{
462 Icon *icon = statusPtr(s);
463 if ( icon )
464 return *icon;
465 return Icon();
466}
467
468Icon *PsiIconset::statusPtr(const XMPP::Status &s)
469{
470 return statusPtr(makeSTATUS(s));
471}
472
473Icon PsiIconset::status(const XMPP::Status &s)
474{
475 return status(makeSTATUS(s));
476}
477
478Icon *PsiIconset::transportStatusPtr(QString name, int s)
479{
480 Icon *icon = 0;
481
482 QMapIterator<QString, QString> it = option.serviceRosterIconset.begin();
483 for ( ; it != option.serviceRosterIconset.end(); ++it) {
484 if (name == it.key()) {
485 Iconset *is = roster.find(it.data());
486 if ( is ) {
487 icon = (Icon *)is->icon(status2name(s));
488 if ( icon )
489 break;
490 }
491 }
492 }
493
494 if ( !icon )
495 icon = statusPtr(s);
496
497 return icon;
498}
499
500Icon *PsiIconset::transportStatusPtr(QString name, const XMPP::Status &s)
501{
502 return transportStatusPtr(name, makeSTATUS(s));
503}
504
505Icon PsiIconset::transportStatus(QString name, int s)
506{
507 Icon *icon = transportStatusPtr(name, s);
508 if ( icon )
509 return *icon;
510 return Icon();
511}
512
513Icon PsiIconset::transportStatus(QString name, const XMPP::Status &s)
514{
515 Icon *icon = transportStatusPtr(name, s);
516 if ( icon )
517 return *icon;
518 return Icon();
519}
520
521Icon *PsiIconset::statusPtr(const XMPP::Jid &jid, int s)
522{
523 return d->jid2icon(jid, status2name(s));
524}
525
526Icon *PsiIconset::statusPtr(const XMPP::Jid &jid, const XMPP::Status &s)
527{
528 return statusPtr(jid, makeSTATUS(s));
529}
530
531Icon PsiIconset::status(const XMPP::Jid &jid, int s)
532{
533 Icon *icon = statusPtr(jid, s);
534 if ( icon )
535 return *icon;
536 return Icon();
537}
538
539Icon PsiIconset::status(const XMPP::Jid &jid, const XMPP::Status &s)
540{
541 Icon *icon = statusPtr(jid, s);
542 if ( icon )
543 return *icon;
544 return Icon();
545}
546
547Icon *PsiIconset::statusPtr(UserListItem *u)
548{
549 if ( !u )
550 return 0;
551
552 int s = 0;
553 if ( !u->presenceError().isEmpty() )
554 s = STATUS_ERROR;
555 else if ( u->isTransport() ) {
556 if ( u->isAvailable() )
557 s = makeSTATUS( (*(u->priority())).status() );
558 else
559 s = STATUS_OFFLINE;
560 }
561 else if ( u->ask() == "subscribe" && !u->isAvailable() && !u->isTransport() )
562 s = STATUS_ASK;
563 else if ( (u->subscription().type() == Subscription::From || u->subscription().type() == Subscription::None) && !u->isAvailable() && !u->isPrivate() )
564 s = STATUS_NOAUTH;
565 else if( !u->isAvailable() )
566 s = STATUS_OFFLINE;
567 else
568 s = makeSTATUS( (*(u->priority())).status() );
569
570 return statusPtr(u->jid(), s);
571}
572
573Icon PsiIconset::status(UserListItem *u)
574{
575 Icon *icon = statusPtr(u);
576 if ( icon )
577 return *icon;
578 return Icon();
579}
580
581const Iconset &PsiIconset::system() const
582{
583 return d->system;
584}
585
586void PsiIconset::stripFirstAnimFrame(Iconset *is)
587{
588 if ( is )
589 d->stripFirstAnimFrame(*is);
590}
591
592void PsiIconset::removeAnimation(Iconset *is)
593{
594 if ( is ) {
595 QPtrListIterator<Icon> it = is->iterator();
596 for ( ; it.current(); ++it) {
597 it.current()->removeAnim(false);
598 }
599 }
600}
Note: See TracBrowser for help on using the repository browser.