Hi, this patch adds a new feature: emoticons (nobody seems to use this word...all is about smiles) can be seen as pictures. Which emoticons do we translate? User-defined ones. That means that you can map what ever you want to an image. How do you define a new theme? The theme is defined in an XML file. The format is the same as kopete. Why? Because i didn't want to find images to test.
The patch still has some room to performance gain. Also i didn't test if it compiles on another version of QT of my system ( qt2 handles XML?). If you like the patch, and you want it on qt2, we can add in configure a test for libxml2 and implement it also over that. Also, I thought in building an finite state machine (with output) dinamicaly (at SetTheme) to parse the message in O(n) where n = characters of message, instead of O(n*m) where m is the number of files available in the theme (i consider m lineal because i bet that each QRegExp is an state machine). To apply please do: [EMAIL PROTECTED]:/tmp$ cd licq [EMAIL PROTECTED]:/tmp/licq$ tar vxjf ../emoticons.tar.bz2 plugins/qt-gui/share/qt-gui/emoticons/ plugins/qt-gui/share/qt-gui/emoticons/None/ plugins/qt-gui/share/qt-gui/emoticons/None/emoticon .... [EMAIL PROTECTED]:/tmp/licq$ patch -p0 < ../emoticons.diff patching file plugins/qt-gui/share/Makefile.am patching file plugins/qt-gui/src/Makefile.am patching file plugins/qt-gui/src/gui-defines.h ... [EMAIL PROTECTED]:/tmp/licq$ cd plugins/qt-gui/ [EMAIL PROTECTED]:/tmp/licq/plugins/qt-gui$ make ... [EMAIL PROTECTED]:/tmp/licq/plugins/qt-gui$ make install (so the emoticons themes are installed). To disable this, just select the theme None. What format are available? I don't know. It depends of your qt installation. Maybe it support animated gifs. I have 15 icons themes in my harddisk that came from kopete. Some dont have a license notice in them, and some do (an even somes says you can redistribute it only for noncomercial ...). So for this mail i have only included the few that made sense. Now that i remember...emoticons at ~/.licq/qt-gui... are not supported (hey! i install licq on my home). -- Buenos Aires, Argentina 8°C with winds at 25 km/h ESE
? plugins/qt-gui/src/emoticon.cpp ? plugins/qt-gui/src/emoticon.h Index: plugins/qt-gui/share/Makefile.am =================================================================== RCS file: /cvsroot/licq/qt-gui/share/Makefile.am,v retrieving revision 1.11 diff -u -d -p -r1.11 Makefile.am --- plugins/qt-gui/share/Makefile.am 8 Nov 2002 01:01:01 -0000 1.11 +++ plugins/qt-gui/share/Makefile.am 23 Aug 2003 01:26:29 -0000 @@ -55,4 +55,12 @@ install-data-local: fi \ done; \ done - + @for j in qt-gui/emoticons/*; do \ + echo "Installing emoticon $$j"; \ + $(mkinstalldirs) $(DESTDIR)$(sharedir)/$$j; \ + for i in $$j/*; do \ + if test -f $$i; then \ + $(INSTALL_DATA) $$i $(DESTDIR)$(sharedir)/$$j; \ + fi \ + done; \ + done Index: plugins/qt-gui/src/Makefile.am =================================================================== RCS file: /cvsroot/licq/qt-gui/src/Makefile.am,v retrieving revision 1.39 diff -u -d -p -r1.39 Makefile.am --- plugins/qt-gui/src/Makefile.am 11 Feb 2003 19:40:25 -0000 1.39 +++ plugins/qt-gui/src/Makefile.am 23 Aug 2003 01:26:42 -0000 @@ -9,6 +9,8 @@ INCLUDES = -D_REENTRANT \ EXTRA_LTLIBRARIES = licq_qt-gui.la licq_kde-gui.la +# EXTRA_PROGRAMS = testemoticons + lib_LTLIBRARIES = @LIB_NAME@ noinst_HEADERS = adduserdlg.h authuserdlg.h awaymsgdlg.h refusedlg.h \ @@ -20,7 +22,7 @@ noinst_HEADERS = adduserdlg.h authuserdl utilitydlg.h wharf.h randomchatdlg.h forwarddlg.h chatjoin.h \ mmlistview.h mmsenddlg.h userinfodlg.h usereventdlg.h keyrequestdlg.h \ jfcstyle.h usercodec.h reqauthdlg.h licqdialog.h userselectdlg.h \ - editfilelistdlg.h + editfilelistdlg.h emoticon.h licq_gui = adduserdlg.cpp authuserdlg.cpp awaymsgdlg.cpp \ refusedlg.cpp chatdlg.cpp editgrp.cpp editfile.cpp eventdesc.cpp \ @@ -32,7 +34,7 @@ licq_gui = adduserdlg.cpp authuserdlg.cp wharf.cpp randomchatdlg.cpp forwarddlg.cpp chatjoin.cpp mmlistview.cpp \ mmsenddlg.cpp userinfodlg.cpp usereventdlg.cpp keyrequestdlg.cpp \ jfcstyle.cpp usercodec.cpp reqauthdlg.cpp licqdialog.cpp userselectdlg.cpp \ - editfilelistdlg.cpp + editfilelistdlg.cpp emoticon.cpp licq_qt_gui_la_SOURCES = $(licq_gui) licq_kde_gui_la_SOURCES = $(licq_gui) wrap_kde_malloc.cpp @@ -49,3 +51,7 @@ licq_kde_gui_la_LIBADD = $(KDE_LIBS) $(X METASOURCES = AUTO KDE_OPTIONS = qtonly + +# testemoticons_SOURCES = emoticon.cpp ../../../src/log.cpp +# testemoticons_CFLAGS = -DEMOTICON_TEST_DRIVER $(LICQ_INCLUDES) +# testemoticons_LDADD = -L$(QT_LIBDIR) $(LIB_QT) Index: plugins/qt-gui/src/gui-defines.h =================================================================== RCS file: /cvsroot/licq/qt-gui/src/gui-defines.h,v retrieving revision 1.20 diff -u -d -p -r1.20 gui-defines.h --- plugins/qt-gui/src/gui-defines.h 11 Sep 2002 01:50:47 -0000 1.20 +++ plugins/qt-gui/src/gui-defines.h 23 Aug 2003 01:26:42 -0000 @@ -2,6 +2,7 @@ #define GUIDEFINES_H #define QTGUI_DIR "qt-gui/" +#define EMOTICONS_DIR "emoticons/" #define NUM_MSG_PER_HISTORY 40 #define COLOR_SENT "blue" Index: plugins/qt-gui/src/licq_qt-gui.conf.h =================================================================== RCS file: /cvsroot/licq/qt-gui/src/licq_qt-gui.conf.h,v retrieving revision 1.8 diff -u -d -p -r1.8 licq_qt-gui.conf.h --- plugins/qt-gui/src/licq_qt-gui.conf.h 8 Nov 2002 00:59:41 -0000 1.8 +++ plugins/qt-gui/src/licq_qt-gui.conf.h 23 Aug 2003 01:26:42 -0000 @@ -2,6 +2,7 @@ static const char QTGUI_CONF[] = "[appearance]\n" "Skin = basic\n" "Icons = computer\n" +"Emoticons = Default\n" "ExtendedIcons = basic\n" "Font = default\n" "GridLines = 0\n" Index: plugins/qt-gui/src/mainwin.cpp =================================================================== RCS file: /cvsroot/licq/qt-gui/src/mainwin.cpp,v retrieving revision 1.294 diff -u -d -p -r1.294 mainwin.cpp --- plugins/qt-gui/src/mainwin.cpp 9 Jul 2003 16:33:26 -0000 1.294 +++ plugins/qt-gui/src/mainwin.cpp 23 Aug 2003 01:26:44 -0000 @@ -80,6 +80,7 @@ #include "wharf.h" #include "keyrequestdlg.h" #include "usercodec.h" +#include "emoticon.h" #include "xpm/history.xpm" #include "xpm/info.xpm" @@ -93,7 +94,6 @@ #include "xpm/pixCellular.xpm" #include "xpm/pixBirthday.xpm" #include "xpm/pixInvisible.xpm" - #include "licq_qt-gui.conf.h" extern "C" { @@ -367,8 +367,7 @@ CMainWindow::CMainWindow(CICQDaemon *the licqConf.ReadBool("showPopLastOnelin",m_bPopLastOnline, false); licqConf.ReadBool("showPopOnlineSince", m_bPopOnlineSince, false); licqConf.ReadBool("showPopIdleTime", m_bPopIdleTime, true); - - + unsigned short nFlash; licqConf.ReadNum("Flash", nFlash, FLASH_URGENT); m_nFlash = (FlashType)nFlash; @@ -448,6 +447,15 @@ CMainWindow::CMainWindow(CICQDaemon *the strcpy(szExtendedIcons, extendedIconsName); m_szExtendedIconSet = NULL; + // Load the Emoticons + char szEmoticons[MAX_FILENAME_LEN]; + licqConf.ReadStr("Emoticons", szEmoticons, "Default" ); + QString s = QString::fromAscii(SHARE_DIR) + QTGUI_DIR + EMOTICONS_DIR; + emoticons = new CEmoticons(s.latin1()); + if( *szEmoticons ) + if( emoticons->SetTheme(szEmoticons) < 0 ) + gLog.Error("%s Loading emoticons theme `%s'",L_ERRORxSTR, szEmoticons); + // Load the skin char szSkin[MAX_FILENAME_LEN] = "basic"; if (strlen(skinName) == 0) @@ -3297,6 +3305,8 @@ void CMainWindow::saveOptions() licqConf.WriteStr("Skin", skin->szSkinName); licqConf.WriteStr("Icons", m_szIconSet); licqConf.WriteStr("ExtendedIcons", m_szExtendedIconSet); + licqConf.WriteStr("Emoticons", emoticons->Theme() ? emoticons->Theme() : ""); + #if QT_VERSION >= 300 licqConf.WriteStr("Font", qApp->font() == defaultFont ? "default" : qApp->font().toString().latin1()); Index: plugins/qt-gui/src/mainwin.h =================================================================== RCS file: /cvsroot/licq/qt-gui/src/mainwin.h,v retrieving revision 1.112 diff -u -d -p -r1.112 mainwin.h --- plugins/qt-gui/src/mainwin.h 8 Jul 2003 11:37:52 -0000 1.112 +++ plugins/qt-gui/src/mainwin.h 23 Aug 2003 01:26:44 -0000 @@ -32,6 +32,7 @@ class QTextView; class CSignalManager; class CQtLogWindow; class CSkin; +class CEmoticons; class CICQDaemon; class ICQEvent; class OptionsDlg; @@ -96,7 +97,6 @@ public: m_nUserMenuPPID = n; m_nUserMenuUin = strtoul(s, (char **)NULL, 10); } - static QPixmap &iconForStatus(unsigned long FullStatus); static QPixmap &iconForEvent(unsigned short SubCommand); @@ -143,6 +143,7 @@ public: ColumnInfos colInfo; FlashType m_nFlash; CSkin *skin; + CEmoticons *emoticons; unsigned long m_nCurrentGroup, m_nGroupStates; unsigned short m_nSortByStatus, @@ -209,7 +210,8 @@ public: QPixmap pmOnline, pmOffline, pmAway, pmDnd, pmOccupied, pmNa, pmPrivate, pmFFC, pmMessage, pmUrl, pmChat, pmFile, pmContact, pmSms, pmAuthorize, pmSMS, pmSecureOn, pmSecureOff, pmHistory, pmInfo, pmEncoding, - pmBirthday, pmPhone, pmCellular, pmInvisible, pmCustomAR, pmCollapsed, pmExpanded; + pmBirthday, pmPhone, pmCellular, pmInvisible, pmCustomAR, pmCollapsed, + pmExpanded; unsigned long m_nUserMenuUin; unsigned int positionChanges; unsigned long m_nProtoNum; Index: plugins/qt-gui/src/mlview3.cpp =================================================================== RCS file: /cvsroot/licq/qt-gui/src/mlview3.cpp,v retrieving revision 1.15 diff -u -d -p -r1.15 mlview3.cpp --- plugins/qt-gui/src/mlview3.cpp 2 Jul 2003 04:41:02 -0000 1.15 +++ plugins/qt-gui/src/mlview3.cpp 23 Aug 2003 01:26:46 -0000 @@ -73,6 +73,9 @@ void MLView::append(const QString& s) } } +#include "emoticon.h" +#include "mainwin.h" // for the CEmoticon instance + QString MLView::toRichText(const QString& s, bool highlightURLs) { // We cannot use QStyleSheet::convertFromPlainText @@ -123,6 +126,8 @@ QString MLView::toRichText(const QString text.replace(pos+1, longSpaces.matchedLength()-1, cap); } text.replace(QRegExp("\t"), " "); + + gMainWindow->emoticons->ParseMessage(text); return text; } Index: plugins/qt-gui/src/skinbrowser.cpp =================================================================== RCS file: /cvsroot/licq/qt-gui/src/skinbrowser.cpp,v retrieving revision 1.23 diff -u -d -p -r1.23 skinbrowser.cpp --- plugins/qt-gui/src/skinbrowser.cpp 24 Mar 2003 15:33:53 -0000 1.23 +++ plugins/qt-gui/src/skinbrowser.cpp 23 Aug 2003 01:26:46 -0000 @@ -35,6 +35,12 @@ #include "mainwin.h" #include "skin.h" #include "skinbrowser.h" +#include "mainwin.h" /* to get the CMainWindow::emoticons */ +#include "emoticon.h" + +enum { + MAX_HEIGHT = 170 +}; SkinBrowserDlg::SkinBrowserDlg(CMainWindow *_mainwin, QWidget *parent) : LicqDialog(parent, "SkinBrowserDialog") @@ -43,9 +49,10 @@ SkinBrowserDlg::SkinBrowserDlg(CMainWind pmSkin = new QPixmap(); lstIcons = new QValueList<QPixmap>; lstExtIcons = new QValueList<QPixmap>; + lstEmoticons = new QValueList<QPixmap>; lstAIcons = new QStringList(); lstAExtIcons = new QStringList(); - + // Setup a list of previewable icons // The strings reflect what we exptect to find in the *.icons files. // The result of these two lists is used to load the icons, the order of @@ -76,22 +83,30 @@ SkinBrowserDlg::SkinBrowserDlg(CMainWind cmbSkin = new QComboBox(boxSkin); QWhatsThis::add(cmbSkin, tr("Use this combo box to select one of the available skins")); lblSkin->setBuddy(cmbSkin); + QLabel *lblIcon = new QLabel(tr("&Icons:"), boxSkin); cmbIcon = new QComboBox(boxSkin); QWhatsThis::add(cmbIcon, tr("Use this combo box to select one of the available icon sets")); lblIcon->setBuddy(cmbIcon); + QLabel *lblExtIcon = new QLabel(tr("E&xtended Icons:"), boxSkin); cmbExtIcon = new QComboBox(boxSkin); QWhatsThis::add(cmbExtIcon, tr("Use this combo box to select one of the available extended icon sets")); lblExtIcon->setBuddy(cmbExtIcon); - + + QLabel *lblEmoticons = new QLabel(tr("E&moticons"), boxSkin); + cmbEmoticon = new QComboBox(boxSkin); + QWhatsThis::add(cmbEmoticon, tr("Use this combo box to select one of " + "the available emoticon icon sets")); + lblEmoticons->setBuddy(cmbEmoticon); + // Preview Box QFrame *frmPrevSkin = new QFrame(boxPreview); QVBoxLayout *layPrevSkin = new QVBoxLayout(frmPrevSkin); QLabel *lblPrevSkin = new QLabel(tr("Skin:"), frmPrevSkin); lblPrevSkin->setAlignment(Qt::AlignHCenter); lblPaintSkin = new QLabel(frmPrevSkin); - lblPaintSkin->setFixedSize(75, 130); + lblPaintSkin->setFixedSize(75, MAX_HEIGHT); layPrevSkin->addWidget(lblPrevSkin, 0, Qt::AlignHCenter); layPrevSkin->addWidget(lblPaintSkin, 0, Qt::AlignHCenter); layPrevSkin->addStretch(); @@ -101,7 +116,7 @@ SkinBrowserDlg::SkinBrowserDlg(CMainWind QLabel *lblPrevIcon = new QLabel(tr("Icons:"), frmPrevIcon); lblPrevIcon->setAlignment(Qt::AlignHCenter); lblPaintIcon = new SkinBrowserPreviewArea(frmPrevIcon); - lblPaintIcon->setFixedSize(54, 130); + lblPaintIcon->setFixedSize(54, MAX_HEIGHT); layPrevIcon->addWidget(lblPrevIcon, 0, Qt::AlignHCenter); layPrevIcon->addWidget(lblPaintIcon, 0, Qt::AlignHCenter); layPrevIcon->addStretch(); @@ -111,10 +126,20 @@ SkinBrowserDlg::SkinBrowserDlg(CMainWind QLabel *lblPrevExtIcon = new QLabel(tr("Extended Icons:"), frmPrevExtIcon); lblPrevExtIcon->setAlignment(Qt::AlignHCenter); lblPaintExtIcon = new SkinBrowserPreviewArea(frmPrevExtIcon); - lblPaintExtIcon->setFixedSize(54, 130); + lblPaintExtIcon->setFixedSize(54, MAX_HEIGHT); layPrevExtIcon->addWidget(lblPrevExtIcon, 0, Qt::AlignHCenter); layPrevExtIcon->addWidget(lblPaintExtIcon, 0, Qt::AlignHCenter); layPrevExtIcon->addStretch(); + + QFrame *frmPrevEmoticon= new QFrame(boxPreview); + QVBoxLayout *layPrevEmoticon = new QVBoxLayout(frmPrevEmoticon); + QLabel *lblPrevEmoticon = new QLabel(tr("Emoticons:"), frmPrevEmoticon); + lblPrevEmoticon->setAlignment(Qt::AlignHCenter); + lblPaintEmoticon= new SkinBrowserPreviewArea(frmPrevEmoticon); + lblPaintEmoticon->setFixedSize(54, MAX_HEIGHT); + layPrevEmoticon->addWidget(lblPrevEmoticon, 0, Qt::AlignHCenter); + layPrevEmoticon->addWidget(lblPaintEmoticon, 0, Qt::AlignHCenter); + layPrevEmoticon->addStretch(); // Buttons QHBoxLayout *layButtons = new QHBoxLayout(frmButtons, 8, 4); @@ -301,6 +326,19 @@ SkinBrowserDlg::SkinBrowserDlg(CMainWind } } } + + CEmoticons *emoticons = gMainWindow->emoticons; + QStringList themes = emoticons->Themes(); + const char *selected = emoticons->Theme(); + int i=0, emoticonid= 0; + for ( QStringList::Iterator it = themes.begin(); + it != themes.end(); ++it, i++ ) + { + cmbEmoticon->insertItem(*it, i); + if( selected && !strcmp(selected, (*it).ascii() )) + emoticonid = i; + } + cmbEmoticon->setCurrentItem(emoticonid); // setup connections connect(btnEdit, SIGNAL(clicked()), this, SLOT(slot_edtSkin())); @@ -310,11 +348,13 @@ SkinBrowserDlg::SkinBrowserDlg(CMainWind connect(cmbSkin, SIGNAL(highlighted(const QString &)), this, SLOT(slot_loadSkin(const QString &))); connect(cmbIcon, SIGNAL(highlighted(const QString &)), this, SLOT(slot_loadIcons(const QString &))); connect(cmbExtIcon, SIGNAL(highlighted(const QString &)), this, SLOT(slot_loadExtIcons(const QString &))); + connect(cmbEmoticon, SIGNAL(highlighted(const QString&)), this, SLOT(slot_loadEmoticons(const QString &))); // Create initial preview slot_loadSkin(cmbSkin->currentText()); slot_loadIcons(cmbIcon->currentText()); slot_loadExtIcons(cmbExtIcon->currentText()); + slot_loadEmoticons(cmbEmoticon->currentText()); setCaption(tr("Licq Skin Browser")); show(); @@ -357,6 +397,8 @@ void SkinBrowserDlg::slot_apply() if (cmbExtIcon->currentText() != mainwin->m_szExtendedIconSet) mainwin->ApplyExtendedIcons(cmbExtIcon->currentText().local8Bit()); + if (cmbEmoticon->currentText() != mainwin->emoticons->Theme()) + mainwin->emoticons->SetTheme(cmbEmoticon->currentText()); } /*! \brief Creates a new skin editor dialog @@ -456,6 +498,36 @@ void SkinBrowserDlg::slot_loadExtIcons(c } lblPaintExtIcon->setPixmapList(lstExtIcons); } +/*! \brief Reloads the current preview emoticons + * + * This slot reloads all preview emoicons. It loads the complete + * set of emoticons that is currently highlighted in the relevant combo + * box. + * If it was successful it makes these icons to be rendered in the preview. + */ +void SkinBrowserDlg::slot_loadEmoticons(const QString &emoticon) +{ + lstEmoticons->clear(); + CEmoticons *e = gMainWindow->emoticons; + QStringList files = e->fileList(emoticon); + for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it) + { + QImage img = QImage(*it); + /* hack: SkinBrowserPreviewArea only draws the + * first 16 pixels + */ + int max_area = 16; + QSize size = img.size(); + if( size.isValid() && + size.width() > max_area && size.height() > max_area ) + img = img.scale(max_area, max_area, QImage::ScaleFree); + + QPixmap pm(img); + if( ! pm.isNull()) + lstEmoticons->append(pm); + } + lblPaintEmoticon->setPixmapList(lstEmoticons); +} /*! \brief provide correct repainting when resizing the main widget * @@ -661,7 +733,7 @@ QPixmap SkinBrowserDlg::renderSkin(const QPixmap tmp(QPixmap::grabWidget(&w)); QPixmap ret; - ret.convertFromImage(QImage(tmp.convertToImage().smoothScale(75, 130))); + ret.convertFromImage(QImage(tmp.convertToImage().smoothScale(75, MAX_HEIGHT))); // Reset origin colors userView.setColors(c_online, c_away, c_offline, c_newuser, c_background, c_gridlines); Index: plugins/qt-gui/src/skinbrowser.h =================================================================== RCS file: /cvsroot/licq/qt-gui/src/skinbrowser.h,v retrieving revision 1.8 diff -u -d -p -r1.8 skinbrowser.h --- plugins/qt-gui/src/skinbrowser.h 18 Jan 2003 16:25:07 -0000 1.8 +++ plugins/qt-gui/src/skinbrowser.h 23 Aug 2003 01:26:46 -0000 @@ -42,12 +42,16 @@ private: QComboBox *cmbIcon; /*! This Combo contains all available extended icon packs */ QComboBox *cmbExtIcon; + /*! This Combo contains all available emoticons themes */ + QComboBox *cmbEmoticon; /*! This QLabel contains the skin preview pixmap (75 x 130 Pixel)*/ QLabel *lblPaintSkin; /*! This SkinBrowserPreviewArea contains the icon pixmaps (54 x 130 Pixel)*/ SkinBrowserPreviewArea *lblPaintIcon; /*! This SkinBrowserPreviewArea contains the extended icons pixmaps (54 x 130 Pixel)*/ SkinBrowserPreviewArea *lblPaintExtIcon; + /*! This SkinBrowserPreviewArea contains the emoticons pixmaps (54x130 Px) */ + SkinBrowserPreviewArea *lblPaintEmoticon; /*! Holds the list of possible themeable icons in normal icon sets */ QStringList *lstAIcons; /*! Holds the list of possible themeable icons in extended icon sets */ @@ -58,6 +62,8 @@ private: QValueList<QPixmap> *lstIcons; /*! Stores the list of the current QPixmaps for the Extended Icons preview */ QValueList<QPixmap> *lstExtIcons; + /*! Stores the list of the current QPixmaps for the emoticons preview */ + QValueList<QPixmap> *lstEmoticons; /*! Renders a dynamic skin preview */ QPixmap renderSkin(const QString &skin); CSkin *skin; @@ -73,6 +79,7 @@ protected slots: void slot_loadSkin(const QString &skin); void slot_loadIcons(const QString &icon); void slot_loadExtIcons(const QString &extIcon); + void slot_loadEmoticons(const QString &emoticon); }; /*! \brief Helper class to provide a preview area for our icons using a modified QFrame --- /dev/null 1969-12-31 21:00:00.000000000 -0300 +++ plugins/qt-gui/src/emoticon.h 2003-08-19 21:41:47.000000000 -0300 @@ -0,0 +1,40 @@ +#ifndef zE1D68C95080DE073514FA90C07628F92 +#define zE1D68C95080DE073514FA90C07628F92 + +#include <qstring.h> +#include <qstringlist.h> + +class CEmoticons { + +public: + /*! + * \param basedir base dir for icons + * \param theme sets the current theme + */ + CEmoticons(const char *basedir, const char *theme = 0 ); + ~CEmoticons(); + + /*! \returns the list of themes available */ + QStringList Themes(); + + /*! + * sets the current theme + * \retuns a negative number on error + */ + int SetTheme(const char *theme); + + /*! \returns the current theme */ + const char *Theme(void); + + /*! \returns the list of files of the current emoticon theme */ + QStringList fileList(); + + /*! \returns the list of files for `theme` */ + QStringList fileList(const char *theme); + + void ParseMessage(QString &msg); + +private: + struct Emoticons *data; +}; +#endif --- /dev/null 1969-12-31 21:00:00.000000000 -0300 +++ plugins/qt-gui/src/emoticon.cpp 2003-08-22 20:08:12.000000000 -0300 @@ -0,0 +1,314 @@ +/* + * Licq - A ICQ Client for Unix + * + * Copyright (C) 2003 Licq developers <[EMAIL PROTECTED]> + * + * This program is licensed under the terms found in the LICENSE file. + * + * \file support for emoticons themes. Compatible with kopete 0.6 format. + * \todo lot of improvents (memory vs time) + */ + +#include <list> +#include <qmap.h> +#include <qdir.h> +#include <qdom.h> +#include <qregexp.h> + +#include "licq_log.h" + +#include "emoticon.h" + +struct node +{ QStringList emoticon; + QString file; + QRegExp reg; +}; + +typedef std::list<struct node> node_list_t; + +/*! private definition of CEmotions */ +struct Emoticons +{ + QString basedir; /* base directory for resourses */ + QString theme; /* current theme */ + + node_list_t emoticons; +}; + +CEmoticons::CEmoticons(const char *basedir, const char *theme ) +{ + this->data = new struct Emoticons; + data->basedir = basedir; +} + +CEmoticons::~CEmoticons() +{ + delete this->data; +} + +QStringList CEmoticons::Themes() +{ + QDir dir(data->basedir, "*", 0, QDir::Dirs); + + return dir.entryList().grep(QRegExp("^[^.].*")); +} + +/*! + * helper funcction of #loadFile. Try to add file to the list of emoticons + * + * \returns true on success + */ +static QString realFile(const struct Emoticons *data, const QString &theme, + const QString &file) +{ + QString s; + + if( file != QString::null ) + { + s= data->basedir + "/" + theme + "/" + file + ".png"; + + if( !QFile(s).exists() ) + { gLog.Warn("%sWarning unknown file `%s'\n", L_WARNxSTR, + s.ascii()); + s = QString::null; + } + } + + return s; +} + +/*! + * helper function for #loadFile + * + * \return a list of characters + * + * <string>:^)</string> + * <string>:)</string> + * <string>:-)</string> + */ +static QStringList loadStrings(const struct Emoticons *data, QDomNode node, + unsigned *n) +{ QStringList ret; + + *n = 0U; + + for( ; !node.isNull() ; node=node.nextSibling() ) + { + QDomElement emo = node.toElement(); + if( !emo.isNull() && emo.tagName() == "string" ) + { + (*n) +=1; + ret << emo.text(); + } + else + gLog.Warn("%sWarning element `%s'", L_WARNxSTR, + emo.tagName().ascii()); + } + + return ret; +} + +static void create_regexp(QStringList &list, QRegExp ®) +{ + unsigned n = 0; + QString s = "(^|\\W)("; + + for ( QStringList::Iterator it = list.begin(); it!=list.end(); ++it) + { + if( n != 0) + s += "|"; + s += QRegExp::escape(*it); + n++; + } + s += ")($|\\W)"; + + reg = QRegExp(s); +} + +static unsigned loadFile(const struct Emoticons *data, + const QString &theme, const char *szfile, + node_list_t &list) +{ + struct node node; + unsigned size; + QDomDocument doc("doc"); + QFile file(szfile); + unsigned ret = 0; + + if ( file.open( IO_ReadOnly ) && doc.setContent( &file ) ) + { + QDomElement elem = doc.documentElement(); + QDomNode n = elem.firstChild(); + for( ; !n.isNull() ; n= n.nextSibling() ) + { + if ( n.isElement() ) + { + elem = n.toElement(); + if( !elem.isNull() && elem.tagName() == + QString::fromAscii("emoticon") ) + { + QString file = elem.attribute("file"); + QString f; + QStringList items= loadStrings(data, + n.firstChild(), + &size); + if( size && + (f=realFile(data,theme, file)) + !=QString::null) + { + + node.emoticon = items; + node.file = f; + create_regexp(items, node.reg); + list.push_back(node); + ret +=size; + } + } + } + } + } + + file.close(); + return ret; +}; + +int CEmoticons::SetTheme(const char *theme) +{ QString szdir = data->basedir + "/" + theme + "/"; + node_list_t list; + QDir d(szdir); + int ret = -1; + unsigned n; + + if( d.exists() ) + { + szdir += "emoticons.xml"; + n = loadFile(data, theme, szdir.ascii(), list); + ret = n; + data->theme = theme; + data->emoticons = list; + } + + return ret; +} + +const char *CEmoticons::Theme(void) +{ + return data->theme == QString::null ? 0 : data->theme.ascii() ; +} + +QStringList CEmoticons::fileList() +{ + node_list_t::iterator iter; + QStringList ret; + struct node n; + + for( iter = data->emoticons.begin(); + iter != data->emoticons.end() ; + iter++ ) + { + n = *iter; + ret << n.file; + } + + return ret; +} + +QStringList CEmoticons::fileList(const char *theme) +{ QString szdir = data->basedir + "/" + theme + "/"; + QStringList ret; + QDir d(szdir); + node_list_t list; + node_list_t::iterator iter; + struct node n; + + if( d.exists() ) + { + szdir += "emoticons.xml"; + loadFile(data, theme, szdir.ascii(), list); + + for( iter = list.begin(); + iter != list.end() ; iter++ ) + { + n = *iter; + ret << n.file; + } + } + + return ret; +} + +void CEmoticons::ParseMessage(QString &msg) +{ + /** + * \todo this sucks: solution create a finite state machine to parse + * the message + */ + node_list_t::iterator iter; + struct node n; + + if( data->theme != QString::null ) + { + QString r; + for( iter = data->emoticons.begin(); + iter != data->emoticons.end() ; iter++ ) + { + n = *iter; + for ( QStringList::Iterator it = n.emoticon.begin(); + it != n.emoticon.end(); ++it) + { + msg.replace(n.reg," <img src=\""+n.file+"\"/> "); + } + } + } +} + +#ifdef EMOTICON_TEST_DRIVER +#include <stdio.h> +#include <iostream> + +int +main(int argc, char **argv) +{ + CEmoticons e = CEmoticons("/tmp/emoticons/"); + QStringList themes = e.Themes(); + + std::cout << "Themes available:\n"; + for ( QStringList::Iterator it = themes.begin(); + it != themes.end(); ++it ) + std::cout << "\t" << *it << "\n"; + + std::cout << "\n"; + printf("Current theme %s\n",e.Theme()); + std::cout << "Set Theme: to abcde(" << e.SetTheme("abcde") << ")\n"; + printf("Current theme %s\n",e.Theme()); + + std::cout << "\n"; + printf("Current theme %s\n",e.Theme()); + + const char *d = argc != 1 ? argv[1] :"Default"; + std::cout << "Set Theme: to (" << d << e.SetTheme(d) << ")\n"; + printf("Current theme %s\n",e.Theme()); + + std::cout << "\n"; + std::cout << "Filelist:\n"; + QStringList files = e.fileList(); + for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it) + std::cout << "\t" << *it << "\n"; + + std::cout << "\nFilelist for theme: KMess\n"; + files = e.fileList("KMess"); + for( QStringList::Iterator it = files.begin(); it != files.end(); ++it) + std::cout << "\t" << *it << "\n"; + + QString s = "hello word :) :( :P :-) :P"; + std::cout << "-- Before\n"; + std::cout << s; + e.ParseMessage(s); + std::cout << "\n-- After\n"; + std::cout << s; + std::cout << "\n"; + + return 0; +} +#endif
emoticons.tar.bz2
Description: application/tbz
<<inline: 82.png>>
<<inline: 81.png>>
pgp00000.pgp
Description: signature