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 QString result;
00165
00166 foreach(const Token &token , tokens) {
00167 switch (token.type) {
00168 case Text:
00169 result += token.text;
00170 break;
00171 case Image:
00172 if (!exclude.contains(token.text)) {
00173 result += token.picHTMLCode;
00174 } else {
00175 result += token.text;
00176 }
00177 break;
00178 default:
00179 kWarning() << "Unknown token type. Something's broken.";
00180 break;
00181 }
00182 }
00183 return result;
00184 }
00185
00186 QList<KEmoticonsTheme::Token> KEmoticonsTheme::tokenize(const QString &message, ParseMode mode) const
00187 {
00188 if (!d->provider) {
00189 return QList<KEmoticonsTheme::Token>();
00190 }
00191
00192 if (!(mode & (StrictParse | RelaxedParse))) {
00193
00194 mode |= KEmoticons::parseMode();
00195 }
00196
00197 QList<Token> result;
00198
00199
00200
00201 QChar p = ' ';
00202 QChar c;
00203 QChar n;
00204
00205
00206 typedef QPair<KEmoticonsProvider::Emoticon, int> EmoticonNode;
00207 QList<EmoticonNode> foundEmoticons;
00208
00209 QList<KEmoticonsProvider::Emoticon> emoticonList;
00210 QList<KEmoticonsProvider::Emoticon>::const_iterator it;
00211 int pos;
00212
00213 bool inHTMLTag = false;
00214 bool inHTMLLink = false;
00215 bool inHTMLEntity = false;
00216 QString needle;
00217
00218 for (pos = 0; pos < message.length(); pos++) {
00219 c = message[pos];
00220
00221 if (mode & SkipHTML) {
00222 if (!inHTMLTag) {
00223 if (c == '<') {
00224 inHTMLTag = true;
00225 p = c;
00226 continue;
00227 }
00228 } else {
00229 if (c == '>') {
00230 inHTMLTag = false;
00231
00232 if (p == 'a') {
00233 inHTMLLink = false;
00234 }
00235 } else if (c == 'a' && p == '<') {
00236 inHTMLLink = true;
00237 }
00238 p = c;
00239 continue;
00240 }
00241
00242 if (!inHTMLEntity) {
00243 if (c == '&') {
00244 inHTMLEntity = true;
00245 }
00246 }
00247 }
00248
00249 if (inHTMLLink) {
00250 p = c;
00251 continue;
00252 }
00253
00254 if ((mode & StrictParse) && !p.isSpace() && p != '>') {
00255 p = c;
00256 continue;
00257 }
00258
00259 if (d->provider->emoticonsIndex().contains(c)) {
00260 emoticonList = d->provider->emoticonsIndex().value(c);
00261 bool found = false;
00262 for (it = emoticonList.constBegin(); it != emoticonList.constEnd(); ++it) {
00263
00264
00265 needle = (mode & SkipHTML) ? (*it).matchTextEscaped : (*it).matchText;
00266 if ((pos == message.indexOf(needle, pos))) {
00267 if (mode & StrictParse) {
00268
00269 if (message.length() > pos + needle.length()) {
00270 n = message[pos + needle.length()];
00271
00272 if (n != '<' && !n.isSpace() && !n.isNull() && n != '&') {
00273 break;
00274 }
00275 }
00276 }
00277
00278 foundEmoticons.append(EmoticonNode((*it), pos));
00279 found = true;
00280
00281 pos += needle.length() - 1;
00282 break;
00283 }
00284
00285 if (found) {
00286 break;
00287 }
00288 }
00289
00290 if (!found) {
00291 if (inHTMLEntity) {
00292
00293 int htmlEnd = message.indexOf(';', pos);
00294
00295 if (htmlEnd == -1) {
00296
00297
00298 kDebug() << "Broken HTML entity, trying to recover.";
00299 inHTMLEntity = false;
00300 pos++;
00301 } else {
00302 pos = htmlEnd;
00303 inHTMLEntity = false;
00304 }
00305 }
00306 }
00307 }
00308 p = c;
00309 }
00310
00311
00312 if (foundEmoticons.isEmpty()) {
00313 result.append(Token(Text, message));
00314 return result;
00315 }
00316
00317
00318
00319 pos = 0;
00320 int length;
00321
00322 for (int i = 0; i < foundEmoticons.size(); ++i) {
00323 EmoticonNode itFound = foundEmoticons.at(i);
00324 needle = (mode & SkipHTML) ? itFound.first.matchTextEscaped : itFound.first.matchText;
00325
00326 if ((length = (itFound.second - pos))) {
00327 result.append(Token(Text, message.mid(pos, length)));
00328 result.append(Token(Image, itFound.first.matchTextEscaped, itFound.first.picPath, itFound.first.picHTMLCode));
00329 pos += length + needle.length();
00330 } else {
00331 result.append(Token(Image, itFound.first.matchTextEscaped, itFound.first.picPath, itFound.first.picHTMLCode));
00332 pos += needle.length();
00333 }
00334 }
00335
00336 if (message.length() - pos) {
00337 result.append(Token(Text, message.mid(pos)));
00338 }
00339
00340 return result;
00341 }
00342
00343 bool KEmoticonsTheme::isNull() const
00344 {
00345 return d->provider ? false : true;
00346 }
00347
00348 KEmoticonsTheme& KEmoticonsTheme::operator=(const KEmoticonsTheme &ket)
00349 {
00350 if (d == ket.d) {
00351 return *this;
00352 }
00353
00354 d = ket.d;
00355 return *this;
00356 }
00357
00358