KUtils
kemoticons.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 #include "kemoticons.h"
00021 #include "kemoticonsprovider.h"
00022
00023 #include <QFile>
00024 #include <QDir>
00025
00026 #include <kpluginloader.h>
00027 #include <kdebug.h>
00028 #include <kstandarddirs.h>
00029 #include <kconfiggroup.h>
00030 #include <ktar.h>
00031 #include <kzip.h>
00032 #include <kmimetype.h>
00033 #include <kdirwatch.h>
00034
00035 class KEmoticonsPrivate
00036 {
00037 public:
00038 KEmoticonsPrivate(KEmoticons *parent);
00039 ~KEmoticonsPrivate();
00040 void loadServiceList();
00041 KEmoticonsProvider *loadProvider(const KService::Ptr &service);
00042
00043 QList<KService::Ptr> m_loaded;
00044 QHash<QString, KEmoticonsTheme> m_themes;
00045 KDirWatch *m_dirwatch;
00046 KEmoticons *q;
00047
00048
00049 void themeChanged(const QString &path);
00050 };
00051
00052 KEmoticonsPrivate::KEmoticonsPrivate(KEmoticons *parent)
00053 : q(parent)
00054 {
00055 }
00056
00057 KEmoticonsPrivate::~KEmoticonsPrivate()
00058 {
00059 delete m_dirwatch;
00060 }
00061
00062 void KEmoticonsPrivate::loadServiceList()
00063 {
00064 QString constraint("(exist Library)");
00065 m_loaded = KServiceTypeTrader::self()->query("KEmoticons", constraint);
00066 }
00067
00068 KEmoticonsProvider *KEmoticonsPrivate::loadProvider(const KService::Ptr &service)
00069 {
00070 KPluginFactory *factory = KPluginLoader(service->library()).factory();
00071 if (!factory) {
00072 kWarning() << "Invalid plugin factory for" << service->library();
00073 return 0;
00074 }
00075 KEmoticonsProvider *provider = factory->create<KEmoticonsProvider>(0);
00076 return provider;
00077 }
00078
00079 void KEmoticonsPrivate::themeChanged(const QString &path)
00080 {
00081 QFileInfo info(path);
00082 QString name = info.dir().dirName();
00083
00084 if (m_themes.contains(name)) {
00085 q->theme(name);
00086 }
00087 }
00088
00089 KEmoticons::KEmoticons()
00090 : d(new KEmoticonsPrivate(this))
00091 {
00092 d->loadServiceList();
00093 d->m_dirwatch = new KDirWatch;
00094 connect(d->m_dirwatch, SIGNAL(dirty(const QString&)), this, SLOT(themeChanged(const QString&)));
00095 }
00096
00097 KEmoticons::~KEmoticons()
00098 {
00099 delete d;
00100 }
00101
00102 KEmoticonsTheme KEmoticons::theme()
00103 {
00104 return theme(currentThemeName());
00105 }
00106
00107 KEmoticonsTheme KEmoticons::theme(const QString &name)
00108 {
00109 if (d->m_themes.contains(name)) {
00110 return d->m_themes.value(name);
00111 }
00112
00113 for (int i = 0; i < d->m_loaded.size(); ++i) {
00114 QString fName = d->m_loaded.at(i)->property("X-KDE-EmoticonsFileName").toString();
00115 QString path = KGlobal::dirs()->findResource("emoticons", name + '/' + fName);
00116
00117 if (QFile::exists(path)) {
00118 KEmoticonsProvider *provider = d->loadProvider(d->m_loaded.at(i));
00119 KEmoticonsTheme theme(provider);
00120 theme.loadTheme(path);
00121 d->m_themes.insert(name, theme);
00122
00123 if (!d->m_dirwatch->contains(path)) {
00124 d->m_dirwatch->addFile(path);
00125 }
00126 return theme;
00127 }
00128 }
00129 return KEmoticonsTheme();
00130 }
00131
00132 QString KEmoticons::currentThemeName()
00133 {
00134 KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
00135 QString name = config.readEntry("emoticonsTheme", "kde4");
00136 return name;
00137 }
00138
00139 QStringList KEmoticons::themeList()
00140 {
00141 QStringList ls;
00142 const QStringList themeDirs = KGlobal::dirs()->findDirs("emoticons", "");
00143
00144 for (int i = 0; i < themeDirs.count(); ++i) {
00145 QDir themeQDir(themeDirs[i]);
00146 themeQDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
00147 themeQDir.setSorting(QDir::Name);
00148 ls << themeQDir.entryList();
00149 }
00150 return ls;
00151 }
00152
00153 void KEmoticons::setTheme(const KEmoticonsTheme &theme)
00154 {
00155 setTheme(theme.themeName());
00156 }
00157
00158 void KEmoticons::setTheme(const QString &theme)
00159 {
00160 KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
00161 config.writeEntry("emoticonsTheme", theme);
00162 config.sync();
00163 }
00164
00165 KEmoticonsTheme KEmoticons::newTheme(const QString &name, const KService::Ptr &service)
00166 {
00167 KEmoticonsProvider *provider = d->loadProvider(service);
00168 KEmoticonsTheme theme(provider);
00169 theme.setThemeName(name);
00170
00171 theme.createNew();
00172
00173 return theme;
00174 }
00175
00176 QStringList KEmoticons::installTheme(const QString &archiveName)
00177 {
00178 QStringList foundThemes;
00179 KArchiveEntry *currentEntry = 0L;
00180 KArchiveDirectory* currentDir = 0L;
00181 KArchive *archive = 0L;
00182
00183 QString localThemesDir(KStandardDirs::locateLocal("emoticons", QString()));
00184
00185 if (localThemesDir.isEmpty()) {
00186 kError() << "Could not find a suitable place in which to install the emoticon theme";
00187 return QStringList();
00188 }
00189
00190 QString currentBundleMimeType = KMimeType::findByPath(archiveName, 0, false)->name();
00191
00192 if (currentBundleMimeType == "application/zip" ||
00193 currentBundleMimeType == "application/x-zip" ||
00194 currentBundleMimeType == "application/x-zip-compressed") {
00195 archive = new KZip(archiveName);
00196 } else if (currentBundleMimeType == "application/x-compressed-tar" ||
00197 currentBundleMimeType == "application/x-bzip-compressed-tar" ||
00198 currentBundleMimeType == "application/x-gzip" ||
00199 currentBundleMimeType == "application/x-bzip") {
00200 archive = new KTar(archiveName);
00201 } else if (archiveName.endsWith("jisp") || archiveName.endsWith("zip")) {
00202 archive = new KZip(archiveName);
00203 } else {
00204 archive = new KTar(archiveName);
00205 }
00206
00207 if (!archive || !archive->open(QIODevice::ReadOnly)) {
00208 kError() << "Could not open" << archiveName << "for unpacking";
00209 delete archive;
00210 return QStringList();
00211 }
00212
00213 const KArchiveDirectory* rootDir = archive->directory();
00214
00215
00216 const QStringList entries = rootDir->entries();
00217 for (QStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it) {
00218 currentEntry = const_cast<KArchiveEntry*>(rootDir->entry(*it));
00219
00220 if (currentEntry->isDirectory()) {
00221 currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry);
00222
00223 for (int i = 0; i < d->m_loaded.size(); ++i) {
00224 QString fName = d->m_loaded.at(i)->property("X-KDE-EmoticonsFileName").toString();
00225
00226 if (currentDir && currentDir->entry(fName) != NULL) {
00227 foundThemes.append(currentDir->name());
00228 }
00229 }
00230 }
00231 }
00232
00233 if (foundThemes.isEmpty()) {
00234 kError() << "The file" << archiveName << "is not a valid emoticon theme archive";
00235 archive->close();
00236 delete archive;
00237 return QStringList();
00238 }
00239
00240 for (int themeIndex = 0; themeIndex < foundThemes.size(); ++themeIndex) {
00241 const QString &theme = foundThemes[themeIndex];
00242
00243 currentEntry = const_cast<KArchiveEntry *>(rootDir->entry(theme));
00244 if (currentEntry == 0) {
00245 kDebug() << "couldn't get next archive entry";
00246 continue;
00247 }
00248
00249 if (currentEntry->isDirectory()) {
00250 currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry);
00251
00252 if (currentDir == 0) {
00253 kDebug() << "couldn't cast archive entry to KArchiveDirectory";
00254 continue;
00255 }
00256
00257 currentDir->copyTo(localThemesDir + theme);
00258 }
00259 }
00260
00261 archive->close();
00262 delete archive;
00263
00264 return foundThemes;
00265 }
00266
00267 void KEmoticons::setParseMode(KEmoticonsTheme::ParseMode mode)
00268 {
00269 KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
00270 config.writeEntry("parseMode", int(mode));
00271 config.sync();
00272 }
00273
00274 KEmoticonsTheme::ParseMode KEmoticons::parseMode()
00275 {
00276 KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
00277 return (KEmoticonsTheme::ParseMode) config.readEntry("parseMode", int(KEmoticonsTheme::RelaxedParse));
00278 }
00279
00280 #include "kemoticons.moc"
00281
00282