//================================================================================ // // File : kvi_iconmanager.cpp // Creation date : Sat Jun 24 2000 14:50:11 by Szymon Stefanek // // This file is part of the KVirc irc client distribution // Copyright (C) 1999-2003 Szymon Stefanek (pragma at kvirc dot net) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your opinion) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //================================================================================ #define __KVIRC__ #define _KVI_ICONMANAGER_CPP_ #include "kvi_iconmanager.h" #include "kvi_imagelib.h" #include "kvi_app.h" #include "kvi_settings.h" #include "kvi_defaults.h" #include "kvi_locale.h" #include "kvi_fileutils.h" #include "kvi_options.h" #include #include #ifndef COMPILE_USE_QT4 // In TQt.4 we need to use TQMimeData ? #include #endif #include #ifdef COMPILE_USE_QT4 #include #endif // kvi_app.cpp extern TQPixmap * g_pUserChanStatePixmap; extern TQPixmap * g_pActivityMeterPixmap; KviIconManager * g_pIconManager = 0; static const char * g_szIconNames[KVI_NUM_SMALL_ICONS]= { "none", // 0 "close", // 1 "maximize", // 2 "minimize", // 3 "restore", // 4 "default", // 5 "dock", // 6 "undock", // 7 "quitapp", // 8 "console", // 9 "floppy", // 10 "parsererror", // 11 "parserwarning", // 12 "server", // 13 "world", // 14 "proxy", // 15 "kvirc", // 16 "cut", // 17 "copy", // 18 "paste", // 19 "options", // 20 "socketmessage", // 21 "socketwarning", // 22 "socketerror", // 23 "systemerror", // 24 "raw", // 25 "systemwarning", // 26 "systemmessage", // 27 "unhandled", // 28 "serverinfo", // 29 "motd", // 30 "channel", // 31 "hidedoubleview", // 32 "showdoubleview", // 33 "op", // 34 "voice", // 35 "serverping", // 36 "showlistview", // 37 "hidelistview", // 38 "join", // 39 "part", // 40 "unrecognized", // 41 "topic", // 42 "accept", // 43 "discard", // 44 "ownprivmsg", // 45 "chanprivmsg", // 46 "query", // 48 "queryprivmsg", // 49 "help", // 49 "mdihelp", // 50 "ctcpreply", // 51 "ctcprequestreplied", // 52 "ctcprequestignored", // 53 "ctcprequestflood", // 54 "ctcprequestunknown", // 55 "action", // 56 "avatar", // 57 "quit", // 58 "split", // 59 "quitsplit", // 60 "nick", // 61 "deop", // 62 "devoice", // 63 "mode", // 64 "key", // 65 "limit", // 66 "ban", // 67 "unban", // 68 "banexcept", // 69 "banunexcept", // 70 "inviteexcept", // 71 "inviteunexcept", // 72 "chanmode", // 73 "chanmodehide", // 74 "who", // 75 "editor", // 76 "dccrequest", // 77 "dccmsg", // 78 "dccerror", // 79 "iconmanager", // 80 "scriptcenter", // 81 "bomb", // 82 "event", // 83 "eventnohandlers", // 84 "handler", // 85 "handlerdisabled", // 86 "nicknameproblem", // 87 "whoisuser", // 88 "whoischannels", // 89 "whoisidle", // 90 "whoisserver", // 91 "whoisother", // 92 "time", // 93 "notifyonline", // 94 "notifyoffline", // 95 "locked", // 96 "unlocked", // 97 "lockedoff", // 98 "unlockedoff", // 99 "ownprivmsgcrypted", // 100 "chanprivmsgcrypted", // 101 "queryprivmsgcrypted", // 102 "dccchatmsg", // 103 "dccchatmsgcrypted", // 104 "irc", // 105 "folder", // 106 "home", // 107 "bookmarks", // 108 "spy", // 109 "kick", // 110 "linux", // 111 "links", // 112 "regusers", // 113 "dockwidget", // 114 "cascadewindows", // 115 "maxvertical", // 116 "maxhorizontal", // 117 "tilewindows", // 118 "log", // 119 "spam", // 120 "file", // 121 "icq", // 122 "icqyellow", // 123 "icqred", // 124 "icqblue", // 125 "icqlightgreen", // 126 "icqlightyellow", // 127 "message", // 128 "messagesent", // 129 "bluesquare", // 130 "violetsquare", // 131 "yellowsquare", // 132 "greensquare", // 133 "blacksquare", // 134 "redsquare", // 135 "cyansquare", // 136 "dkgreensquare", // 137 "terminal", // 138 "wallops", // 139 "invisible", // 140 "servernotice", // 141 "gnutella", // 142 "search", // 143 "files", // 144 "transfer", // 145 "package", // 146 "retry", // 147 "idea", // 148 "colors", // 149 "gui", // 150 "ircview", // 151 "alias", // 152 "channelnotice",// 153 "channelnoticecrypted", // 154 "querynotice", // 155 "querynoticecrypted", // 156 "servnotice", // 157 "popup", // 158 "prologue", // 159 "epilogue", // 160 "sharedfiles", // 161 "ctcpreplyunknown", // 162 "canvas", // 163 "nickserv", // 164 "chanserv", // 165 "dccvoice", // 166 "play", // 167 "record", // 168 "autotilewindows", // 169 "away", // 170 "ident", // 171 "homepage", // 172 "list", // 173 "halfop", // 174 "halfdeop", // 175 "invite", // 176 "multimedia", // 177 "look", // 178 "input", // 179 "messages", // 180 "querytrace", // 181 "nochannel", // 182 "broadcastprivmsg", // 183 "broadcastnotice", // 184 "url", // 185 "rawevent", // 186 "raweventnohandlers", // 187 "mekick", // 188 "meop", // 189 "mevoice", // 190 "medeop", // 191 "medevoice", // 192 "mehalfop", // 193 "medehalfop", // 194 "meban", // 195 "meunban", // 196 "mebanexcept", // 197 "mebanunexcept", // 198 "meinviteexcept", // 199 "meinviteunexcept", // 200 "classictaskbar", // 201 "treetaskbar", // 202 "ignore", // 203 "userlist",// 204 "stats", // 205 "popupmenu", // 206 "xy", // 207 "irc0", // 208 "irc1", // 209 "irc2", // 210 "irc3", // 211 "irc4", // 212 "irc5", // 213 "heart", // 214 "heartbroken", // 215 "rose", // 215 "biggrin", // 217 "biggringlasses", // 218 "biggrineyes", // 219 "textexclamative", // 220 "textpoints", // 221 "kiss", // 222 "surprised1", // 223 "ugly", // 224 "angry", // 225 "surprised2", // 226 "smile", // 227 "tongue", // 228 "ssl", // 229 "cry", // 230 "eye", // 231 "deadchannel", // 232 "deadquery", // 233 "sound", // 234 "toolbar", // 235 "textencoding",// 236 "newitem", // 237 "newitembywizard", // 238 "deleteitem", // 239 "edititem", // 240 "filetransfer", // 241 "chanadmin", // 242 "chanunadmin", // 243 "mechanadmin", // 244 "mechanunadmin", // 245 "userop", // 246 "deuserop", // 247 "meuserop", // 248 "medeuserop", // 249 "applet", // 250 "caption", // 251 "transparent", // 252 "alert", // 253 "userwindow", // 254 "statusbar", // 255 "notaway", // 256 "plus", // 257 "minus", // 258 "binarytext", // 259 "chanowner", // 260 "chanunowner", // 261 "mechanowner", // 262 "mechanunowner", // 263 "afraid", // 264 "tongue2", // 265 "sayicon", // 266 "saycolors", // 267 "finger", // 268 "scriptaction", // 269 "tearsmile", // 270 "shy", // 271 "servererror", // 272 "cafe", // 273 "addons", // 274 "chanowneraway", // 275 "opaway", // 276 "voiceaway", // 277 "chanadminaway", // 278 "useropaway", // 279 "halfopaway", // 280 "aliashighlighted", // 281 "demoralized", // 282 "slurp", // 283 "namespace", // 284 "saysmile", // 285 "saykvs", // 286 "themeoptions", // 287 "bug", // 288 "refresh", //289 "theme", // 290 "screenshot" // 291 }; KviIconWidget::KviIconWidget() #ifdef COMPILE_USE_QT4 : TQWidget(0,"global_icon_widget" /*,WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder | WStyle_SysMenu | WStyle_Minimize*/) #else : TQWidget(0,"global_icon_widget",WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder | WStyle_SysMenu | WStyle_Minimize) #endif { init(); } KviIconWidget::KviIconWidget(TQWidget * par) : TQWidget(par,"global_icon_widget") { init(); } void KviIconWidget::init() { setCaption(__tr2qs("Icon Table")); setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ICONMANAGER))); int rows = KVI_NUM_SMALL_ICONS / 10; if((rows * 10) < KVI_NUM_SMALL_ICONS)rows++; TQGridLayout * g = new TQGridLayout(this,rows + 1,11,0,2); int i; for(i = 0;i < 10;i++) { KviStr tmp(KviStr::Format,"%d",i); TQLabel * l = new TQLabel(tmp.ptr(),this); g->addWidget(l,0,i + 1); } for(i = 0;i < rows;i++) { KviStr tmp(KviStr::Format,"%d",i * 10); TQLabel * l = new TQLabel(tmp.ptr(),this); g->addWidget(l,i + 1,0); } for(i = 0;i < KVI_NUM_SMALL_ICONS;i++) { KviStr tmp(KviStr::Format,"%d",i); TQLabel * l = new TQLabel(this,tmp.ptr()); l->setPixmap(*(g_pIconManager->getSmallIcon(i))); g->addWidget(l,(i / 10) + 1,(i % 10) + 1); l->installEventFilter(this); l->setAcceptDrops(true); } } KviIconWidget::~KviIconWidget() { } void KviIconWidget::closeEvent(TQCloseEvent * e) { e->ignore(); emit closed(); } bool KviIconWidget::eventFilter(TQObject * o,TQEvent *e) { if(e->type() == TQEvent::MouseButtonPress) { if(o->inherits(TQLABEL_OBJECT_NAME_STRING)) { KviStr szName = ((TQLabel *)o)->name(); bool bOk; int iVal = szName.toInt(&bOk); if(bOk)emit selected(iVal); if(parentWidget() && isVisible() && parentWidget()->inherits("KviTalPopupMenu")) { parentWidget()->close(); return true; } else { if(const TQPixmap * pix = ((TQLabel *)o)->pixmap()) { // FIXME: In TQt 4.x this stuff needs to be ported to a different api.. which one ? #ifndef COMPILE_USE_QT4 TQDragObject * drobj = new TQTextDrag(o->name(),this); drobj->setPixmap(*pix,((TQLabel *)o)->mapFromGlobal(TQCursor::pos())); drobj->dragCopy(); #endif return true; } } } } else if(e->type() == TQEvent::DragEnter) { ((TQDragEnterEvent *)e)->accept(true); return true; } return TQWidget::eventFilter(o,e); } KviCachedPixmap::KviCachedPixmap(TQPixmap * ptr,const TQString &szPath) { m_szPath = szPath; m_tLastAccess = kvi_unixTime(); m_pPixmap = ptr; m_uSize = m_pPixmap->width() * m_pPixmap->height() * (m_pPixmap->depth() / 8); } KviCachedPixmap::~KviCachedPixmap() { delete m_pPixmap; } void KviCachedPixmap::updateLastAccessTime() { m_tLastAccess = kvi_unixTime(); } KviIconManager::KviIconManager() { int i=0; for(i=0;i(21,true); m_pCachedImages->setAutoDelete(true); m_uCacheTotalSize = 0; m_uCacheMaxSize = 1024 * 1024; // 1 MB m_pIconWidget = 0; KviStr buffer; // Load the userchanstate image g_pApp->findImage(buffer,KVI_USERCHANSTATE_IMAGE_NAME); g_pUserChanStatePixmap = new TQPixmap(TQString(buffer.ptr())); g_pApp->findImage(buffer,KVI_ACTIVITYMETER_IMAGE_NAME); g_pActivityMeterPixmap = new TQPixmap(TQString(buffer.ptr())); m_pIconNames = 0; // TEMP /* for(i=0;iisNull()) { debug("OPS, %s is NULL",nnn.latin1()); } if(!tmp->save(nnn,"PNG",90)) { debug("FAILED TO SAVE %s",nnn.latin1()); } } */ } KviIconManager::~KviIconManager() { delete g_pUserChanStatePixmap; delete g_pActivityMeterPixmap; if(m_pIconWidget)delete m_pIconWidget; int i; for(i=0;i(257,false); m_pIconNames->setAutoDelete(true); for(int i=0;ireplace(TQString(g_szIconNames[i]),pInt); } } int * pInt = m_pIconNames->find(szName); if(!pInt)return 0; return *pInt; } void KviIconManager::showIconWidget() { if(!m_pIconWidget) { m_pIconWidget = new KviIconWidget(); connect(m_pIconWidget,TQT_SIGNAL(closed()),this,TQT_SLOT(iconWidgetClosed())); } m_pIconWidget->show(); m_pIconWidget->raise(); m_pIconWidget->setFocus(); } void KviIconManager::iconWidgetClosed() { delete m_pIconWidget; m_pIconWidget = 0; } /* @doc: image_id @title: The image identifier @keyterms: image identifier, using builtin images, how kvirc locates image files @type: language @short: Semantics of the parameter @body: Some KVIrc commands and functions accept the as a parameter. The indicates an image to be displayed by some gui element. Since KVIrc has a set of builtin icons, we want the user to be able to use it :).[br] The can be either a signed integer number or a filename.[br] If it is a signed integer it is interpreted as index of the internal KVIrc image to use: positive integers (starting at 0) indicate small (16x16) icons (the ones used in the view widget).[br] If is anything else than a signed integer, it is interpreted as a filename. The filename can be an absolute file path or a relative one. In this last case KVIrc will look for the file in a predefined set of directories: First in the local "pics" directory (usually in ~/kvirc-version/pics/), then in the local "incoming" directory, then in the global "pics" directory , then in the user home (~) and in the current directory.[br] */ KviCachedPixmap * KviIconManager::getPixmapWithCache(const TQString &szName) { if(szName.isEmpty())return 0; KviCachedPixmap * p = m_pCachedImages->find(szName); if(p) { p->updateLastAccessTime(); return p; } TQPixmap * pix = 0; TQString szRetPath; if(g_pApp->findImage(szRetPath,szName)) { pix = new TQPixmap(szRetPath); if(pix->isNull()) { delete pix; // it is not an valid image!!! (really bad situation...) pix = 0; return 0; } } else { return 0; } p = new KviCachedPixmap(pix,TQString(szRetPath)); addToCache(szName,p); return p; } KviCachedPixmap * KviIconManager::getPixmapWithCacheScaleOnLoad(const TQString &szName,int iMaxWidth,int iMaxHeight) { if(szName.isEmpty())return 0; KviCachedPixmap * p = m_pCachedImages->find(szName); if(p) { p->updateLastAccessTime(); return p; } TQPixmap * pix = 0; TQString szRetPath; if(g_pApp->findImage(szRetPath,szName)) { pix = new TQPixmap(szRetPath); if(pix->isNull()) { delete pix; // it is not an valid image!!! (really bad situation...) pix = 0; return 0; } if((pix->width() > iMaxWidth) || (pix->height() > iMaxHeight)) { // scale to fit int scaleW = iMaxWidth; int scaleH; scaleH = (pix->height() * iMaxWidth) / pix->width(); if(scaleH > iMaxHeight) { scaleH = iMaxHeight; scaleW = (scaleH * pix->width()) / pix->height(); } TQImage img = pix->convertToImage(); pix->convertFromImage(img.smoothScale(scaleW,scaleH)); } } else { return 0; } p = new KviCachedPixmap(pix,TQString(szRetPath)); addToCache(szName,p); return p; } void KviIconManager::addToCache(const TQString &szName,KviCachedPixmap * p) { if((m_uCacheTotalSize + p->size()) >= m_uCacheMaxSize)cacheCleanup(); m_pCachedImages->insert(szName,p); m_uCacheTotalSize += p->size(); } TQPixmap * KviIconManager::getImage(const char * id,bool bCanBeNumber,TQString* pRetPath) { if(!id)return 0; if(bCanBeNumber) { bool bOk; TQString tmp = id; int idx = tmp.toInt(&bOk); if(bOk) { // was a number : this is not a filename if(idx >= 0)return getSmallIcon(idx % KVI_NUM_SMALL_ICONS); } } KviCachedPixmap * p = getPixmapWithCache(id); if(!p)return 0; if(pRetPath)*pRetPath = p->path(); return p->pixmap(); } TQPixmap * KviIconManager::getBigIcon(const TQString &szName) { TQPixmap * p = getPixmap(szName); if(p)return p; bool bOk; int idx = szName.toInt(&bOk); if(bOk && (idx >= 0)) { // was a number : this is not a filename // it was a small icon: scale it and cache it TQString tmpName = szName; tmpName += ".scaled16to32"; p = getPixmap(tmpName); if(p)return p; p = getSmallIcon(idx % KVI_NUM_SMALL_ICONS); if(p) { TQImage tmpi = p->convertToImage(); TQImage tmp2 = tmpi.smoothScale(32,32); KviCachedPixmap * cp = new KviCachedPixmap(new TQPixmap(tmp2),TQString()); addToCache(tmpName,cp); return cp->pixmap(); } } p = getPixmap("kvi_bigicon_unknown.png"); if(p)return p; KviCachedPixmap * cp = new KviCachedPixmap(new TQPixmap(32,32),TQString()); addToCache(szName,cp); return cp->pixmap(); } void KviIconManager::urlToCachedFileName(KviStr &szFName) { szFName.replaceAll(':',"_"); szFName.replaceAll(';',"_"); szFName.replaceAll('/',"_"); szFName.replaceAll('\\',"_"); szFName.replaceAll("\"","_"); szFName.replaceAll("\'","_"); szFName.replaceAll("(","_"); szFName.replaceAll(")","_"); szFName.replaceAll("?","_"); szFName.replaceAll("___","."); } void KviIconManager::urlToCachedFileName(TQString &szFName) { szFName.replace(":","_"); szFName.replace(";","_"); szFName.replace("/","_"); szFName.replace("\\","_"); szFName.replace("\"","_"); szFName.replace("\'","_"); szFName.replace("(","_"); szFName.replace(")","_"); szFName.replace("?","_"); szFName.replace("___","."); } KviAvatar * KviIconManager::getAvatar(const TQString &szLocalPath,const TQString &szName) { TQString szP,szN; if(szLocalPath.isEmpty()) { if(szName.isEmpty())return 0; if(KviTQString::equalCIN("http://",szName,7)) { szN = szName; szP = szName; urlToCachedFileName(szP); } else { szN = KviFileUtils::extractFileName(szName); szP = szName; } } else if(szName.isEmpty()) { if(szLocalPath.isEmpty())return 0; szP = szLocalPath; szN = KviFileUtils::extractFileName(szLocalPath); } else { szP = szLocalPath; szN = szName; } // avatars bigger than 1024x768 just sux: they can't be seen on tooltips anyway KviCachedPixmap * p = KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad) ? getPixmapWithCacheScaleOnLoad(szP, KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadWidth) ,KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadHeight)) : getPixmapWithCache(szP); if(!p)return 0; return new KviAvatar(p->path(),szN,new TQPixmap(*(p->pixmap()))); } void KviIconManager::clearCache() { m_pCachedImages->clear(); } void KviIconManager::reloadImages() { clearCache(); for(int i=0;i= KVI_NUM_SMALL_ICONS)return 0; if(idx < 0)return 0; // COMPATIBILITY ENTRY: To be removed in some time. // This part loads the old smallicon library format kvi_smallicon_*.png // to preserve backward compatibility with old themes. // We lookup such files ONLY in the themes directories. TQString szFileName = KVI_SMALLICONS_IMAGELIB_PREFIX; int fileidx = idx / 16; if(fileidx >= 10)KviTQString::appendFormatted(szFileName,"%d.png",fileidx); else KviTQString::appendFormatted(szFileName,"0%d.png",fileidx); TQString buffer; if(g_pApp->findImageThemeOnlyCompat(buffer,szFileName)) { KviImageLibrary l1(buffer,16,16); int offset = fileidx * 16; for(int i=0;i<16;i++) { int io = i + offset; if(io >= KVI_NUM_SMALL_ICONS)break; if(m_smallIcons[io])delete m_smallIcons[io]; m_smallIcons[io] = new TQPixmap(l1.getImage(i)); } return m_smallIcons[idx]; } // otherwise we use the NEW method: separate small icons in the "coresmall" subdirectory. TQString szPath; KviTQString::sprintf(szPath,KVI_SMALLICONS_PREFIX "%s.png",g_szIconNames[idx]); g_pApp->findSmallIcon(buffer,szPath); m_smallIcons[idx] = new TQPixmap(buffer); //if(m_smallIcon[idx]->isNull()) //{ // // load an "unknown" image ?.. but should never happen //} return m_smallIcons[idx]; } void KviIconManager::cacheCleanup() { TQStringList l; KviPointerHashTableIterator it(*m_pCachedImages); //#warning "IMPLEMENT CLEANUP" /* while(it.current()) { kvi_time_t curTime = kvi_unixTime(); if((((unsigned int)it.current()->timestamp) - ((unsigned int)curTime)) > 120) { // unused since 2 minutes // time to cleanup it... l.append(new KviStr(it.currentKey())); } ++it; } for(TQStringList::Iterator it = l.begin();it != l.end();++it) { m_pCachedImages->remove(*it); } */ /* for(KviStr * p =l.first();p;p = l.next()) { m_pCachedImages->remove(p->ptr()); } if(m_pCachedImages->isEmpty())m_pCleanupTimer->stop(); */ } #include "kvi_iconmanager.moc"