• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KUtils

kemoticonstheme.cpp

Go to the documentation of this file.
00001 /**********************************************************************************
00002  *   Copyright (C) 2008 by Carlo Segato <brandon.ml@gmail.com>                    *
00003  *   Copyright (c) 2002-2003 by Stefan Gehn            <metz@gehn.net>            *
00004  *   Kopete    (c) 2002-2008 by the Kopete developers  <kopete-devel@kde.org>     *
00005  *   Copyright (c) 2005      by Engin AYDOGAN          <engin@bzzzt.biz>          *
00006  *                                                                                *
00007  *   This library is free software; you can redistribute it and/or                *
00008  *   modify it under the terms of the GNU Lesser General Public                   *
00009  *   License as published by the Free Software Foundation; either                 *
00010  *   version 2.1 of the License, or (at your option) any later version.           *
00011  *                                                                                *
00012  *   This library is distributed in the hope that it will be useful,              *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of               *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU            *
00015  *   Lesser General Public License for more details.                              *
00016  *                                                                                *
00017  *   You should have received a copy of the GNU Lesser General Public             *
00018  *   License along with this library.  If not, see <http://www.gnu.org/licenses/>.*
00019  *                                                                                *
00020  **********************************************************************************/
00021 
00022 #include "kemoticonstheme.h"
00023 #include "kemoticons.h"
00024 
00025 #include <QtCore/QFileInfo>
00026 #include <QtCore/QDir>
00027 #include <QtGui/QTextDocument>
00028 
00029 #include <kio/netaccess.h>
00030 #include <kstandarddirs.h>
00031 #include <kdebug.h>
00032 
00033 class KEmoticonsTheme::KEmoticonsThemeData : public QSharedData
00034 {
00035 public:
00036     KEmoticonsThemeData();
00037     ~KEmoticonsThemeData();
00038     KEmoticonsProvider *provider;
00039 };
00040 
00041 KEmoticonsTheme::KEmoticonsThemeData::KEmoticonsThemeData()
00042 {
00043     provider = 0;
00044 }
00045 
00046 KEmoticonsTheme::KEmoticonsThemeData::~KEmoticonsThemeData()
00047 {
00048 //     delete provider;
00049 }
00050 
00051 KEmoticonsTheme::KEmoticonsTheme()
00052 {
00053     d = new KEmoticonsThemeData;
00054 }
00055 
00056 KEmoticonsTheme::KEmoticonsTheme(const KEmoticonsTheme &ket)
00057 {
00058     d = ket.d;
00059 }
00060 
00061 KEmoticonsTheme::KEmoticonsTheme(KEmoticonsProvider *p)
00062 {
00063     d = new KEmoticonsThemeData;
00064     d->provider = p;
00065 }
00066 
00067 KEmoticonsTheme::~KEmoticonsTheme()
00068 {
00069 }
00070 
00071 bool KEmoticonsTheme::loadTheme(const QString &path)
00072 {
00073     if (!d->provider) {
00074         return false;
00075     }
00076 
00077     return d->provider->loadTheme(path);
00078 }
00079 
00080 bool KEmoticonsTheme::removeEmoticon(const QString &emo)
00081 {
00082     if (!d->provider) {
00083         return false;
00084     }
00085 
00086     return d->provider->removeEmoticon(emo);
00087 }
00088 
00089 bool KEmoticonsTheme::addEmoticon(const QString &emo, const QString &text, KEmoticonsProvider::AddEmoticonOption option)
00090 {
00091     if (!d->provider) {
00092         return false;
00093     }
00094 
00095     return d->provider->addEmoticon(emo, text, option);
00096 }
00097 
00098 void KEmoticonsTheme::save()
00099 {
00100     if (!d->provider) {
00101         return;
00102     }
00103 
00104     d->provider->save();
00105 }
00106 
00107 QString KEmoticonsTheme::themeName() const
00108 {
00109     if (!d->provider) {
00110         return QString();
00111     }
00112 
00113     return d->provider->themeName();
00114 }
00115 
00116 void KEmoticonsTheme::setThemeName(const QString &name)
00117 {
00118     if (!d->provider) {
00119         return;
00120     }
00121 
00122     d->provider->setThemeName(name);
00123 }
00124 
00125 QString KEmoticonsTheme::themePath() const
00126 {
00127     if (!d->provider) {
00128         return QString();
00129     }
00130 
00131     return d->provider->themePath();
00132 }
00133 
00134 QString KEmoticonsTheme::fileName() const
00135 {
00136     if (!d->provider) {
00137         return QString();
00138     }
00139 
00140     return d->provider->fileName();
00141 }
00142 
00143 QHash<QString, QStringList> KEmoticonsTheme::emoticonsMap() const
00144 {
00145     if (!d->provider) {
00146         return QHash<QString, QStringList>();
00147     }
00148 
00149     return d->provider->emoticonsMap();
00150 }
00151 
00152 void KEmoticonsTheme::createNew()
00153 {
00154     if (!d->provider) {
00155         return;
00156     }
00157 
00158     d->provider->createNew();
00159 }
00160 
00161 QString KEmoticonsTheme::parseEmoticons(const QString &text, ParseMode mode, const QStringList &exclude) const
00162 {
00163     QList<Token> tokens = tokenize(text, mode | SkipHTML);
00164     if (tokens.isEmpty() && !text.isEmpty())
00165         return text;
00166 
00167     QString result;
00168 
00169     foreach(const Token &token , tokens) {
00170         switch (token.type) {
00171         case Text:
00172             result += token.text;
00173             break;
00174         case Image:
00175             if (!exclude.contains(token.text)) {
00176                 result += token.picHTMLCode;
00177             } else {
00178                 result += token.text;
00179             }
00180             break;
00181         default:
00182             kWarning() << "Unknown token type. Something's broken.";
00183             break;
00184         }
00185     }
00186     return result;
00187 }
00188 
00189 QList<KEmoticonsTheme::Token> KEmoticonsTheme::tokenize(const QString &message, ParseMode mode) const
00190 {
00191     if (!d->provider) {
00192         return QList<KEmoticonsTheme::Token>();
00193     }
00194 
00195     if (!(mode & (StrictParse | RelaxedParse))) {
00196         //if none of theses two mode are selected, use the mode from the config
00197         mode |=  KEmoticons::parseMode();
00198     }
00199 
00200     QList<Token> result;
00201 
00202     /* previous char, in the firs iteration assume that it is space since we want
00203      * to let emoticons at the beginning, the very first previous QChar must be a space. */
00204     QChar p = ' ';
00205     QChar c; /* current char */
00206     QChar n;
00207 
00208     /* This is the EmoticonNode container, it will represent each matched emoticon */
00209     typedef QPair<KEmoticonsProvider::Emoticon, int> EmoticonNode;
00210     QList<EmoticonNode> foundEmoticons;
00211     /* First-pass, store the matched emoticon locations in foundEmoticons */
00212     QList<KEmoticonsProvider::Emoticon> emoticonList;
00213     QList<KEmoticonsProvider::Emoticon>::const_iterator it;
00214     int pos;
00215 
00216     bool inHTMLTag = false;
00217     bool inHTMLLink = false;
00218     bool inHTMLEntity = false;
00219     QString needle; // search for this
00220 
00221     for (pos = 0; pos < message.length(); ++pos) {
00222         c = message[pos];
00223 
00224         if (mode & SkipHTML) { // Shall we skip HTML ?
00225             if (!inHTMLTag) { // Are we already in an HTML tag ?
00226                 if (c == '<') { // If not check if are going into one
00227                     inHTMLTag = true; // If we are, change the state to inHTML
00228                     p = c;
00229                     continue;
00230                 }
00231             } else { // We are already in a HTML tag
00232                 if (c == '>') { // Check if it ends
00233                     inHTMLTag = false;   // If so, change the state
00234 
00235                     if (p == 'a') {
00236                         inHTMLLink = false;
00237                     }
00238                 } else if (c == 'a' && p == '<') { // check if we just entered an achor tag
00239                     inHTMLLink = true; // don't put smileys in urls
00240                 }
00241                 p = c;
00242                 continue;
00243             }
00244 
00245             if (!inHTMLEntity) { // are we
00246                 if (c == '&') {
00247                     inHTMLEntity = true;
00248                 }
00249             }
00250         }
00251 
00252         if (inHTMLLink) { // i can't think of any situation where a link address might need emoticons
00253             p = c;
00254             continue;
00255         }
00256 
00257         if ((mode & StrictParse)  &&  !p.isSpace() && p != '>') {  // '>' may mark the end of an html tag
00258             p = c;
00259             continue;
00260         } /* strict requires space before the emoticon */
00261 
00262         if (d->provider->emoticonsIndex().contains(c)) {
00263             emoticonList = d->provider->emoticonsIndex().value(c);
00264             bool found = false;
00265             for (it = emoticonList.constBegin(); it != emoticonList.constEnd(); ++it) {
00266                 // If this is an HTML, then search for the HTML form of the emoticon.
00267                 // For instance <o) => &gt;o)
00268                 needle = (mode & SkipHTML) ? (*it).matchTextEscaped : (*it).matchText;
00269                 if ((pos == message.indexOf(needle, pos))) {
00270                     if (mode & StrictParse) {
00271                         /* check if the character after this match is space or end of string*/
00272                         if (message.length() > pos + needle.length()) {
00273                             n = message[pos + needle.length()];
00274                             //<br/> marks the end of a line
00275                             if (n != '<' && !n.isSpace() &&  !n.isNull() && n != '&') {
00276                                 break;
00277                             }
00278                         }
00279                     }
00280                     /* Perfect match */
00281                     foundEmoticons.append(EmoticonNode((*it), pos));
00282                     found = true;
00283                     /* Skip the matched emoticon's matchText */
00284                     pos += needle.length() - 1;
00285                     break;
00286                 }
00287 
00288                 if (found) {
00289                     break;
00290                 }
00291             }
00292 
00293             if (!found) {
00294                 if (inHTMLEntity) {
00295                     // If we are in an HTML entitiy such as &gt;
00296                     int htmlEnd = message.indexOf(';', pos);
00297                     // Search for where it ends
00298                     if (htmlEnd == -1) {
00299                         // Apparently this HTML entity isn't ended, something is wrong, try skip the '&'
00300                         // and continue
00301                         kDebug() << "Broken HTML entity, trying to recover.";
00302                         inHTMLEntity = false;
00303                         pos++;
00304                     } else {
00305                         pos = htmlEnd;
00306                         inHTMLEntity = false;
00307                     }
00308                 }
00309             }
00310         } /* else no emoticons begin with this character, so don't do anything */
00311         p = c;
00312     }
00313 
00314     /* if no emoticons found just return the text */
00315     if (foundEmoticons.isEmpty()) {
00316         result.append(Token(Text, message));
00317         return result;
00318     }
00319 
00320     /* Second-pass, generate tokens based on the matches */
00321 
00322     pos = 0;
00323     int length;
00324 
00325     for (int i = 0; i < foundEmoticons.size(); ++i) {
00326         EmoticonNode itFound = foundEmoticons.at(i);
00327         needle = (mode & SkipHTML) ? itFound.first.matchTextEscaped : itFound.first.matchText;
00328 
00329         if ((length = (itFound.second - pos))) {
00330             result.append(Token(Text, message.mid(pos, length)));
00331             result.append(Token(Image, itFound.first.matchTextEscaped, itFound.first.picPath, itFound.first.picHTMLCode));
00332             pos += length + needle.length();
00333         } else {
00334             result.append(Token(Image, itFound.first.matchTextEscaped, itFound.first.picPath, itFound.first.picHTMLCode));
00335             pos += needle.length();
00336         }
00337     }
00338 
00339     if (message.length() - pos) { // if there is remaining regular text
00340         result.append(Token(Text, message.mid(pos)));
00341     }
00342 
00343     return result;
00344 }
00345 
00346 bool KEmoticonsTheme::isNull() const
00347 {
00348     return d->provider ? false : true;
00349 }
00350 
00351 KEmoticonsTheme& KEmoticonsTheme::operator=(const KEmoticonsTheme &ket)
00352 {
00353     if (d == ket.d) {
00354         return *this;
00355     }
00356 
00357     d = ket.d;
00358     return *this;
00359 }
00360 
00361 // kate: space-indent on; indent-width 4; replace-tabs on;

KUtils

Skip menu "KUtils"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal