1
//=============================================================================
3
// File : kvi_iconmanager.cpp
4
// Creation date : Sat Jun 24 2000 14:50:11 by Szymon Stefanek
6
// This file is part of the KVirc irc client distribution
7
// Copyright (C) 2000-2008 Szymon Stefanek (pragma at kvirc dot net)
9
// This program is FREE software. You can redistribute it and/or
10
// modify it under the terms of the GNU General Public License
11
// as published by the Free Software Foundation; either version 2
12
// of the License, or (at your opinion) any later version.
14
// This program is distributed in the HOPE that it will be USEFUL,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
// See the GNU General Public License for more details.
19
// You should have received a copy of the GNU General Public License
20
// along with this program. If not, write to the Free Software Foundation,
21
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
//=============================================================================
26
#define _KVI_ICONMANAGER_CPP_
28
#include "kvi_iconmanager.h"
30
#include "kvi_settings.h"
31
#include "kvi_defaults.h"
32
#include "kvi_locale.h"
33
#include "kvi_fileutils.h"
34
#include "kvi_options.h"
40
#include <QCloseEvent>
45
extern QPixmap * g_pUserChanStatePixmap;
46
extern QPixmap * g_pActivityMeterPixmap;
48
KviIconManager * g_pIconManager = 0;
50
static const char * g_szIconNames[KVI_NUM_SMALL_ICONS]=
64
"parserwarning", // 12
73
"socketmessage", // 21
74
"socketwarning", // 22
78
"systemwarning", // 26
79
"systemmessage", // 27
84
"hidedoubleview", // 32
85
"showdoubleview", // 33
100
"queryprivmsg", // 49
104
"ctcprequestreplied", // 52
105
"ctcprequestignored", // 53
106
"ctcprequestflood", // 54
107
"ctcprequestunknown", // 55
123
"inviteexcept", // 71
124
"inviteunexcept", // 72
126
"chanmodehide", // 74
133
"scriptcenter", // 81
136
"eventnohandlers", // 84
138
"handlerdisabled", // 86
139
"nicknameproblem", // 87
141
"whoischannels", // 89
146
"notifyonline", // 94
147
"notifyoffline", // 95
152
"ownprivmsgcrypted", // 100
153
"chanprivmsgcrypted", // 101
154
"queryprivmsgcrypted", // 102
156
"dccchatmsgcrypted", // 104
167
"cascadewindows", // 115
168
"maxvertical", // 116
169
"maxhorizontal", // 117
170
"tilewindows", // 118
178
"icqlightgreen", // 126
179
"icqlightyellow", // 127
181
"messagesent", // 129
183
"violetsquare", // 131
184
"yellowsquare", // 132
185
"greensquare", // 133
186
"blacksquare", // 134
189
"dkgreensquare", // 137
193
"servernotice", // 141
205
"channelnotice",// 153
206
"channelnoticecrypted", // 154
207
"querynotice", // 155
208
"querynoticecrypted", // 156
213
"sharedfiles", // 161
214
"ctcpreplyunknown", // 162
221
"autotilewindows", // 169
235
"broadcastprivmsg", // 183
236
"broadcastnotice", // 184
239
"raweventnohandlers", // 187
249
"mebanexcept", // 197
250
"mebanunexcept", // 198
251
"meinviteexcept", // 199
252
"meinviteunexcept", // 200
253
"classicwindowlist", // 201
254
"treewindowlist", // 202
267
"heartbroken", // 215
270
"biggringlasses", // 218
271
"biggrineyes", // 219
272
"textexclamative", // 220
284
"deadchannel", // 232
288
"textencoding",// 236
290
"newitembywizard", // 238
293
"filetransfer", // 241
295
"chanunadmin", // 243
296
"mechanadmin", // 244
297
"mechanunadmin", // 245
304
"transparent", // 252
313
"chanunowner", // 261
314
"mechanowner", // 262
315
"mechanunowner", // 263
321
"scriptaction", // 269
324
"servererror", // 272
327
"chanowneraway", // 275
330
"chanadminaway", // 278
333
"classeditor", // 281
334
"demoralized", // 282
339
"themeoptions", // 287
362
"classnotbuilt", // 310
366
KviIconWidget::KviIconWidget()
367
: QWidget(0 /*,WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder | WStyle_SysMenu | WStyle_Minimize*/)
369
setObjectName("global_icon_widget");
373
KviIconWidget::KviIconWidget(QWidget * par)
376
setObjectName("global_icon_widget");
380
void KviIconWidget::init()
382
setWindowTitle(__tr2qs("Icon Table"));
383
setWindowIcon(QIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ICONMANAGER))));
385
int rows = KVI_NUM_SMALL_ICONS / 10;
386
if((rows * 10) < KVI_NUM_SMALL_ICONS)rows++;
387
QGridLayout * g = new QGridLayout(this);
389
for(i = 0;i < 10;i++)
391
KviStr tmp(KviStr::Format,"%d",i);
392
QLabel * l = new QLabel(tmp.ptr(),this);
393
g->addWidget(l,0,i + 1);
395
for(i = 0;i < rows;i++)
397
KviStr tmp(KviStr::Format,"%d",i * 10);
398
QLabel * l = new QLabel(tmp.ptr(),this);
399
g->addWidget(l,i + 1,0);
401
for(i = 0;i < KVI_NUM_SMALL_ICONS;i++)
403
KviStr tmp(KviStr::Format,"%d",i);
404
QLabel * l = new QLabel(this);
405
l->setObjectName(tmp.ptr());
406
l->setPixmap(*(g_pIconManager->getSmallIcon(i)));
407
g->addWidget(l,(i / 10) + 1,(i % 10) + 1);
408
l->installEventFilter(this);
409
l->setAcceptDrops(true);
413
KviIconWidget::~KviIconWidget()
417
void KviIconWidget::closeEvent(QCloseEvent * e)
423
bool KviIconWidget::eventFilter(QObject * o,QEvent *e)
425
if(e->type() == QEvent::MouseButtonPress)
427
if(o->inherits("QLabel"))
429
KviStr szName = ((QLabel *)o)->objectName();
431
int iVal = szName.toInt(&bOk);
432
if(bOk)emit selected(iVal);
434
if(parentWidget() && isVisible() && parentWidget()->inherits("KviTalPopupMenu"))
436
parentWidget()->close();
439
if(const QPixmap * pix = ((QLabel *)o)->pixmap())
441
QDrag *drobj = new QDrag(this);
442
QMimeData *mimeData = new QMimeData;
444
mimeData->setText(o->objectName());
445
mimeData->setImageData(*pix);
446
drobj->setMimeData(mimeData);
447
drobj->setPixmap(*pix);
451
} else if(e->type() == QEvent::DragEnter)
453
((QDragEnterEvent *)e)->setAccepted(true);
456
return QWidget::eventFilter(o,e);
460
KviCachedPixmap::KviCachedPixmap(QPixmap * ptr,const QString &szPath)
463
m_tLastAccess = kvi_unixTime();
465
m_uSize = m_pPixmap->width() * m_pPixmap->height() * (m_pPixmap->depth() / 8);
468
KviCachedPixmap::~KviCachedPixmap()
473
void KviCachedPixmap::updateLastAccessTime()
475
m_tLastAccess = kvi_unixTime();
479
KviIconManager::KviIconManager()
482
for(i=0;i<KVI_NUM_SMALL_ICONS;i++)m_smallIcons[i] = 0;
484
initQResourceBackend();
487
m_pCachedImages = new KviPointerHashTable<QString,KviCachedPixmap>(21,true);
488
m_pCachedImages->setAutoDelete(true);
490
m_uCacheTotalSize = 0;
491
m_uCacheMaxSize = 1024 * 1024; // 1 MB
497
// Load the userchanstate image
498
g_pApp->findImage(buffer,KVI_USERCHANSTATE_IMAGE_NAME);
499
g_pUserChanStatePixmap = new QPixmap(buffer);
501
g_pApp->findImage(buffer,KVI_ACTIVITYMETER_IMAGE_NAME);
502
g_pActivityMeterPixmap = new QPixmap(buffer);
507
KviIconManager::~KviIconManager()
509
delete g_pUserChanStatePixmap;
510
delete g_pActivityMeterPixmap;
512
if(m_pIconWidget)delete m_pIconWidget;
515
for(i=0;i<KVI_NUM_SMALL_ICONS;i++)
517
if(m_smallIcons[i])delete m_smallIcons[i];
519
delete m_pCachedImages;
520
if(m_pIconNames)delete m_pIconNames;
523
void KviIconManager::initQResourceBackend()
527
g_pApp->getLocalKvircDirectory(szPath,KviApp::Pics);
528
QDir::addSearchPath("icons", szPath);
530
g_pApp->getGlobalKvircDirectory(szPath,KviApp::Pics);
531
QDir::addSearchPath("icons", szPath);
533
g_pApp->getLocalKvircDirectory(szPath,KviApp::SmallIcons);
534
QDir::addSearchPath("smallicons", szPath);
536
g_pApp->getGlobalKvircDirectory(szPath,KviApp::SmallIcons);
537
QDir::addSearchPath("smallicons", szPath);
541
QString KviIconManager::getSmallIconResourceName(int idx)
543
QString szName("smallicons:kcs_");
544
szName.append(g_szIconNames[idx]);
545
szName.append(".png");
549
const char * KviIconManager::getSmallIconName(int idx)
551
return g_szIconNames[idx];
554
int KviIconManager::getSmallIconIdFromName(const QString &szName)
558
m_pIconNames = new KviPointerHashTable<QString,int>(257,false);
559
m_pIconNames->setAutoDelete(true);
561
for(int i=0;i<KVI_NUM_SMALL_ICONS;i++)
563
int * pInt = new int;
565
m_pIconNames->replace(QString(g_szIconNames[i]),pInt);
568
int * pInt = m_pIconNames->find(szName);
573
void KviIconManager::showIconWidget()
577
m_pIconWidget = new KviIconWidget();
578
connect(m_pIconWidget,SIGNAL(closed()),this,SLOT(iconWidgetClosed()));
580
m_pIconWidget->show();
581
m_pIconWidget->raise();
582
m_pIconWidget->setFocus();
585
void KviIconManager::iconWidgetClosed()
587
delete m_pIconWidget;
596
image identifier, using builtin images, how kvirc locates image files
600
Semantics of the <image_id> parameter
602
Some KVIrc commands and functions accept
603
the <image_id> as a parameter.
604
The <image_id> indicates an image to be displayed
605
by some gui element. Since KVIrc has a set of
606
builtin icons, we want the user to be able to use it :).[br]
607
The <image_id> can be either a signed integer number
609
If it is a signed integer it is interpreted as
610
index of the internal KVIrc image to use:
611
positive integers (starting at 0) indicate
612
small (16x16) icons (the ones used in the view widget).[br]
613
If <image_id> is anything else than a signed integer,
614
it is interpreted as a filename.
615
The filename can be an absolute file path or a relative one.
616
In this last case KVIrc will look for the file in a predefined set
617
of directories: First in the local "pics" directory (usually
618
in ~/kvirc-version/pics/), then in the local "incoming" directory,
619
then in the global "pics" directory , then in the user home (~)
620
and in the current directory.[br]
623
KviCachedPixmap * KviIconManager::getPixmapWithCache(const QString &szName)
625
if(szName.isEmpty())return 0;
627
KviCachedPixmap * p = m_pCachedImages->find(szName);
631
p->updateLastAccessTime();
639
if(g_pApp->findImage(szRetPath,szName))
641
pix = new QPixmap(szRetPath);
644
delete pix; // it is not an valid image!!! (really bad situation...)
652
p = new KviCachedPixmap(pix,QString(szRetPath));
653
addToCache(szName,p);
658
KviCachedPixmap * KviIconManager::getPixmapWithCacheScaleOnLoad(const QString &szName,int iMaxWidth,int iMaxHeight)
660
if(szName.isEmpty())return 0;
662
KviCachedPixmap * p = m_pCachedImages->find(szName);
666
p->updateLastAccessTime();
674
if(g_pApp->findImage(szRetPath,szName))
676
pix = new QPixmap(szRetPath);
679
delete pix; // it is not an valid image!!! (really bad situation...)
683
if((pix->width() > iMaxWidth) || (pix->height() > iMaxHeight))
686
int scaleW = iMaxWidth;
688
scaleH = (pix->height() * iMaxWidth) / pix->width();
689
if(scaleH > iMaxHeight)
692
scaleW = (scaleH * pix->width()) / pix->height();
695
QImage img = pix->toImage();
696
*pix = QPixmap::fromImage(img.scaled(scaleW,scaleH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
702
p = new KviCachedPixmap(pix,QString(szRetPath));
703
addToCache(szName,p);
708
void KviIconManager::addToCache(const QString &szName,KviCachedPixmap * p)
710
if((m_uCacheTotalSize + p->size()) >= m_uCacheMaxSize)cacheCleanup();
712
m_pCachedImages->insert(szName,p);
713
m_uCacheTotalSize += p->size();
716
QPixmap * KviIconManager::getImage(const QString &id,bool bCanBeNumber,QString* pRetPath)
724
int idx = id.toInt(&bOk);
727
// was a number : this is not a filename
729
return getSmallIcon(idx % KVI_NUM_SMALL_ICONS);
731
if(id.startsWith("$icon"))
733
QString szTmp = id.trimmed();
734
szTmp.replace("$icon(","");
735
szTmp.replace(")","");
736
szTmp = szTmp.trimmed();
737
szTmp.replace("\"","");
738
idx = getSmallIconIdFromName(szTmp.trimmed());
740
return getSmallIcon(idx % KVI_NUM_SMALL_ICONS);
746
KviCachedPixmap * p = getPixmapWithCache(id);
751
*pRetPath = p->path();
757
QPixmap * KviIconManager::getBigIcon(const QString &szName)
759
QPixmap * p = getPixmap(szName);
763
int idx = szName.toInt(&bOk);
764
if(bOk && (idx >= 0))
766
// was a number : this is not a filename
767
// it was a small icon: scale it and cache it
768
QString tmpName = szName;
769
tmpName += ".scaled16to32";
770
p = getPixmap(tmpName);
772
p = getSmallIcon(idx % KVI_NUM_SMALL_ICONS);
775
QImage tmpi = p->toImage();
776
QImage tmp2 = tmpi.scaled(32,32,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
777
QPixmap *pix=new QPixmap();
778
*pix = QPixmap::fromImage(tmp2);
779
KviCachedPixmap * cp = new KviCachedPixmap(pix,QString());
780
addToCache(tmpName,cp);
785
p = getPixmap("kvi_bigicon_unknown.png");
787
KviCachedPixmap * cp = new KviCachedPixmap(new QPixmap(32,32),QString());
788
addToCache(szName,cp);
792
void KviIconManager::urlToCachedFileName(QString &szFName)
794
szFName.replace(":","_");
795
szFName.replace(";","_");
796
szFName.replace("/","_");
797
szFName.replace("\\","_");
798
szFName.replace("\"","_");
799
szFName.replace("\'","_");
800
szFName.replace("(","_");
801
szFName.replace(")","_");
802
szFName.replace("?","_");
803
szFName.replace("___",".");
804
//cut filenames to 255 chars, trying to preserve file name/extension (bug #616)
805
if(szFName.size()>255)
807
QString ext = szFName.right(55);
808
szFName.truncate(200);
813
KviAvatar * KviIconManager::getAvatar(const QString &szLocalPath,const QString &szName)
817
if(szLocalPath.isEmpty())
819
//both path and name empty => fail
822
if(KviQString::equalCIN("http://",szName,7))
824
// it's an url, cache it locally
826
urlToCachedFileName(szN);
827
g_pApp->getLocalKvircDirectory(szP,KviApp::Avatars,szN);
828
szN = szName; // keep the remote url as name
830
//locally cached avatar, called only by its szName
831
szN = KviFileUtils::extractFileName(szName);
832
g_pApp->getLocalKvircDirectory(szP,KviApp::Avatars,szN);
834
} else if(szName.isEmpty())
836
if(szLocalPath.isEmpty())
839
szN = KviFileUtils::extractFileName(szLocalPath);
845
// avatars bigger than 1024x768 just sux: they can't be seen on tooltips anyway
846
//KviCachedPixmap * p = KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad) ? getPixmapWithCacheScaleOnLoad(szP,
847
// KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadWidth)
848
// ,KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadHeight)) : getPixmapWithCache(szP);
852
KviAvatar* result = 0;
854
if(KviFileUtils::fileExists(szP))
856
if(KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad))
858
result = new KviAvatar(szP,szN,
860
KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadWidth),
861
KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadHeight)
865
result = new KviAvatar(szP,szN);
870
if(result && !result->isValid())
879
void KviIconManager::clearCache()
881
m_pCachedImages->clear();
884
void KviIconManager::reloadImages()
887
for(int i=0;i<KVI_NUM_SMALL_ICONS;i++)
889
if(m_smallIcons[i])delete m_smallIcons[i];
895
QPixmap * KviIconManager::loadSmallIcon(int idx)
897
if(idx >= KVI_NUM_SMALL_ICONS)return 0;
902
KviQString::sprintf(szPath,KVI_SMALLICONS_PREFIX "%s.png",g_szIconNames[idx]);
904
g_pApp->findSmallIcon(buffer,szPath);
905
m_smallIcons[idx] = new QPixmap(buffer);
907
//if(m_smallIcon[idx]->isNull())
909
// // load an "unknown" image ?.. but should never happen
911
return m_smallIcons[idx];
914
void KviIconManager::cacheCleanup()
918
KviPointerHashTableIterator<QString,KviCachedPixmap> it(*m_pCachedImages);
921
//#warning "IMPLEMENT CLEANUP"
925
kvi_time_t curTime = kvi_unixTime();
927
if((((unsigned int)it.current()->timestamp) - ((unsigned int)curTime)) > 120)
929
// unused since 2 minutes
930
// time to cleanup it...
931
l.append(new KviStr(it.currentKey()));
936
for(QStringList::Iterator it = l.begin();it != l.end();++it)
938
m_pCachedImages->remove(*it);
942
for(KviStr * p =l.first();p;p = l.next())
944
m_pCachedImages->remove(p->ptr());
946
if(m_pCachedImages->isEmpty())m_pCleanupTimer->stop();
950
#ifndef COMPILE_USE_STANDALONE_MOC_SOURCES
951
#include "kvi_iconmanager.moc"
952
#endif //!COMPILE_USE_STANDALONE_MOC_SOURCES