kdelibs/kutils/kemoticons/kemoticons.cpp
2015-06-14 18:49:20 +03:00

299 lines
9.6 KiB
C++

/**********************************************************************************
* Copyright (C) 2007 by Carlo Segato <brandon.ml@gmail.com> *
* Copyright (C) 2008 Montel Laurent <montel@kde.org> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library. If not, see <http://www.gnu.org/licenses/>.*
* *
**********************************************************************************/
#include "kemoticons.h"
#include "kemoticonsprovider.h"
#include <QFile>
#include <QDir>
#include <kpluginloader.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kconfiggroup.h>
#include <ktar.h>
#include <kzip.h>
#include <kmimetype.h>
#include <kdirwatch.h>
class KEmoticonsPrivate
{
public:
KEmoticonsPrivate(KEmoticons *parent);
~KEmoticonsPrivate();
void loadServiceList();
KEmoticonsProvider *loadProvider(const KService::Ptr &service);
KEmoticonsTheme loadTheme(const QString &name);
QList<KService::Ptr> m_loaded;
QHash<QString, KEmoticonsTheme> m_themes;
KDirWatch *m_dirwatch;
KEmoticons *q;
//private slots
void themeChanged(const QString &path);
};
KEmoticonsPrivate::KEmoticonsPrivate(KEmoticons *parent)
: q(parent)
{
}
KEmoticonsPrivate::~KEmoticonsPrivate()
{
delete m_dirwatch;
}
bool priorityLessThan(const KService::Ptr &s1, const KService::Ptr &s2)
{
return (s1->property("X-KDE-Priority").toInt() > s2->property("X-KDE-Priority").toInt());
}
void KEmoticonsPrivate::loadServiceList()
{
QString constraint("(exist Library)");
m_loaded = KServiceTypeTrader::self()->query("KEmoticons", constraint);
qSort(m_loaded.begin(), m_loaded.end(), priorityLessThan);
}
KEmoticonsProvider *KEmoticonsPrivate::loadProvider(const KService::Ptr &service)
{
KPluginFactory *factory = KPluginLoader(service->library()).factory();
if (!factory) {
kWarning() << "Invalid plugin factory for" << service->library();
return 0;
}
KEmoticonsProvider *provider = factory->create<KEmoticonsProvider>(0);
return provider;
}
void KEmoticonsPrivate::themeChanged(const QString &path)
{
QFileInfo info(path);
QString name = info.dir().dirName();
if (m_themes.contains(name)) {
loadTheme(name);
}
}
KEmoticonsTheme KEmoticonsPrivate::loadTheme(const QString &name)
{
const int numberOfTheme = m_loaded.size();
for (int i = 0; i < numberOfTheme; ++i) {
const QString fName = m_loaded.at(i)->property("X-KDE-EmoticonsFileName").toString();
const QString path = KGlobal::dirs()->findResource("emoticons", name + '/' + fName);
if (QFile::exists(path)) {
KEmoticonsProvider *provider = loadProvider(m_loaded.at(i));
KEmoticonsTheme theme(provider);
theme.loadTheme(path);
m_themes.insert(name, theme);
if (!m_dirwatch->contains(path)) {
m_dirwatch->addFile(path);
}
return theme;
}
}
return KEmoticonsTheme();
}
KEmoticons::KEmoticons()
: d(new KEmoticonsPrivate(this))
{
d->loadServiceList();
d->m_dirwatch = new KDirWatch;
connect(d->m_dirwatch, SIGNAL(dirty(QString)), this, SLOT(themeChanged(QString)));
}
KEmoticons::~KEmoticons()
{
delete d;
}
KEmoticonsTheme KEmoticons::theme()
{
return theme(currentThemeName());
}
KEmoticonsTheme KEmoticons::theme(const QString &name)
{
if (d->m_themes.contains(name)) {
return d->m_themes.value(name);
}
return d->loadTheme(name);
}
QString KEmoticons::currentThemeName()
{
KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
QString name = config.readEntry("emoticonsTheme", "kde4");
return name;
}
QStringList KEmoticons::themeList()
{
QStringList ls;
const QStringList themeDirs = KGlobal::dirs()->findDirs("emoticons", "");
for (int i = 0; i < themeDirs.count(); ++i) {
QDir themeQDir(themeDirs[i]);
themeQDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
themeQDir.setSorting(QDir::Name);
ls << themeQDir.entryList();
}
return ls;
}
void KEmoticons::setTheme(const KEmoticonsTheme &theme)
{
setTheme(theme.themeName());
}
void KEmoticons::setTheme(const QString &theme)
{
KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
config.writeEntry("emoticonsTheme", theme);
config.sync();
}
KEmoticonsTheme KEmoticons::newTheme(const QString &name, const KService::Ptr &service)
{
KEmoticonsProvider *provider = d->loadProvider(service);
KEmoticonsTheme theme(provider);
theme.setThemeName(name);
theme.createNew();
return theme;
}
QStringList KEmoticons::installTheme(const QString &archiveName)
{
QStringList foundThemes;
KArchiveEntry *currentEntry = 0L;
KArchiveDirectory* currentDir = 0L;
KArchive *archive = 0L;
QString localThemesDir(KStandardDirs::locateLocal("emoticons", QString()));
if (localThemesDir.isEmpty()) {
kError() << "Could not find a suitable place in which to install the emoticon theme";
return QStringList();
}
const QString currentBundleMimeType = KMimeType::findByPath(archiveName, 0, false)->name();
if (currentBundleMimeType == "application/zip" ||
currentBundleMimeType == "application/x-zip" ||
currentBundleMimeType == "application/x-zip-compressed") {
archive = new KZip(archiveName);
} else if (currentBundleMimeType == "application/x-compressed-tar" ||
currentBundleMimeType == "application/x-bzip-compressed-tar" ||
currentBundleMimeType == "application/x-lzma-compressed-tar" ||
currentBundleMimeType == "application/x-xz-compressed-tar" ||
currentBundleMimeType == "application/x-gzip" ||
currentBundleMimeType == "application/x-bzip" ||
currentBundleMimeType == "application/x-lzma" ||
currentBundleMimeType == "application/x-xz") {
archive = new KTar(archiveName);
} else if (archiveName.endsWith(QLatin1String("jisp")) || archiveName.endsWith(QLatin1String("zip"))) {
archive = new KZip(archiveName);
} else {
archive = new KTar(archiveName);
}
if (!archive || !archive->open(QIODevice::ReadOnly)) {
kError() << "Could not open" << archiveName << "for unpacking";
delete archive;
return QStringList();
}
const KArchiveDirectory* rootDir = archive->directory();
// iterate all the dirs looking for an emoticons.xml file
const QStringList entries = rootDir->entries();
for (QStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it) {
currentEntry = const_cast<KArchiveEntry*>(rootDir->entry(*it));
if (currentEntry->isDirectory()) {
currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry);
for (int i = 0; i < d->m_loaded.size(); ++i) {
QString fName = d->m_loaded.at(i)->property("X-KDE-EmoticonsFileName").toString();
if (currentDir && currentDir->entry(fName) != NULL) {
foundThemes.append(currentDir->name());
}
}
}
}
if (foundThemes.isEmpty()) {
kError() << "The file" << archiveName << "is not a valid emoticon theme archive";
archive->close();
delete archive;
return QStringList();
}
for (int themeIndex = 0; themeIndex < foundThemes.size(); ++themeIndex) {
const QString &theme = foundThemes[themeIndex];
currentEntry = const_cast<KArchiveEntry *>(rootDir->entry(theme));
if (currentEntry == 0) {
kDebug() << "couldn't get next archive entry";
continue;
}
if (currentEntry->isDirectory()) {
currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry);
if (currentDir == 0) {
kDebug() << "couldn't cast archive entry to KArchiveDirectory";
continue;
}
currentDir->copyTo(localThemesDir + theme);
}
}
archive->close();
delete archive;
return foundThemes;
}
void KEmoticons::setParseMode(KEmoticonsTheme::ParseMode mode)
{
KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
config.writeEntry("parseMode", int(mode));
config.sync();
}
KEmoticonsTheme::ParseMode KEmoticons::parseMode()
{
KConfigGroup config(KSharedConfig::openConfig("kdeglobals"), "Emoticons");
return (KEmoticonsTheme::ParseMode) config.readEntry("parseMode", int(KEmoticonsTheme::RelaxedParse));
}
#include "moc_kemoticons.cpp"
// kate: space-indent on; indent-width 4; replace-tabs on;