KUtils
kemoticonstheme.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00197 mode |= KEmoticons::parseMode();
00198 }
00199
00200 QList<Token> result;
00201
00202
00203
00204 QChar p = ' ';
00205 QChar c;
00206 QChar n;
00207
00208
00209 typedef QPair<KEmoticonsProvider::Emoticon, int> EmoticonNode;
00210 QList<EmoticonNode> foundEmoticons;
00211
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;
00220
00221 for (pos = 0; pos < message.length(); ++pos) {
00222 c = message[pos];
00223
00224 if (mode & SkipHTML) {
00225 if (!inHTMLTag) {
00226 if (c == '<') {
00227 inHTMLTag = true;
00228 p = c;
00229 continue;
00230 }
00231 } else {
00232 if (c == '>') {
00233 inHTMLTag = false;
00234
00235 if (p == 'a') {
00236 inHTMLLink = false;
00237 }
00238 } else if (c == 'a' && p == '<') {
00239 inHTMLLink = true;
00240 }
00241 p = c;
00242 continue;
00243 }
00244
00245 if (!inHTMLEntity) {
00246 if (c == '&') {
00247 inHTMLEntity = true;
00248 }
00249 }
00250 }
00251
00252 if (inHTMLLink) {
00253 p = c;
00254 continue;
00255 }
00256
00257 if ((mode & StrictParse) && !p.isSpace() && p != '>') {
00258 p = c;
00259 continue;
00260 }
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
00267
00268 needle = (mode & SkipHTML) ? (*it).matchTextEscaped : (*it).matchText;
00269 if ((pos == message.indexOf(needle, pos))) {
00270 if (mode & StrictParse) {
00271
00272 if (message.length() > pos + needle.length()) {
00273 n = message[pos + needle.length()];
00274
00275 if (n != '<' && !n.isSpace() && !n.isNull() && n != '&') {
00276 break;
00277 }
00278 }
00279 }
00280
00281 foundEmoticons.append(EmoticonNode((*it), pos));
00282 found = true;
00283
00284 pos += needle.length() - 1;
00285 break;
00286 }
00287
00288 if (found) {
00289 break;
00290 }
00291 }
00292
00293 if (!found) {
00294 if (inHTMLEntity) {
00295
00296 int htmlEnd = message.indexOf(';', pos);
00297
00298 if (htmlEnd == -1) {
00299
00300
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 }
00311 p = c;
00312 }
00313
00314
00315 if (foundEmoticons.isEmpty()) {
00316 result.append(Token(Text, message));
00317 return result;
00318 }
00319
00320
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) {
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