You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ksquirrel/ksquirrel/ksquirrelpart/sq_libraryhandler.cpp

578 lines
14 KiB

/***************************************************************************
sq_libraryhandler.cpp - description
-------------------
begin : Mar 5 2004
copyright : (C) 2004 by Baryshev Dmitry
email : ksquirrel.iv@gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <tqlibrary.h>
#include <tqfileinfo.h>
#include <tqstringlist.h>
#include <tqfile.h>
#include <tqdir.h>
#include <kstringhandler.h>
#include <ktempfile.h>
#include <kconfig.h>
#include <klocale.h>
#include <kdebug.h>
#include <kurl.h>
#include <kmimetype.h>
#include "sq_libraryhandler.h"
#include "sq_config.h"
#include <ksquirrel-libs/fmt_codec_base.h>
#include <iostream>
#include <iomanip>
static const int buffer_size = 10;
SQ_LibraryHandler * SQ_LibraryHandler::m_instance = 0;
// SQ_LibraryHandler
SQ_LibraryHandler::SQ_LibraryHandler(TQObject *parent)
: TQObject(parent), TQValueVector<SQ_LIBRARY>()
{
m_instance = this;
kdDebug() << "+SQ_LibraryHandler" << endl;
kconf = new TDEConfig("ksquirrel-codec-settings");
load();
}
SQ_LibraryHandler::~SQ_LibraryHandler()
{
clear();
delete kconf;
kdDebug() << "-SQ_LibraryHandler" << endl;
}
/*
* Find appropriate SQ_LIBRARY by filename. If
* not found, return NULL.
*/
SQ_LIBRARY* SQ_LibraryHandler::libraryForFile(const KURL &url)
{
KMimeType::Ptr mime = KMimeType::findByURL(url);
iterator itEnd = end();
SQ_LIBRARY *l = 0;
// go through array and compare names
for(iterator it = begin();it != itEnd;++it)
{
if((*it).mime_multi)
{
if((*it).mimetype.find(mime->name()) != -1)
{
l = &(*it);
break;
}
}
else if((*it).mimetype == mime->name())
{
l = &(*it);
break;
}
}
#if 0
if(l)
kdDebug() << KStringHandler::lsqueeze(url.prettyURL())
<< "\" => "
<< l->quickinfo
<< endl;
#endif
return l;
}
SQ_LIBRARY* SQ_LibraryHandler::libraryForFile(const TQString &path)
{
KURL u;
u.setPath(path);
return libraryForFile(u);
}
/*
* Get all filters as one string.
*/
TQString SQ_LibraryHandler::allFiltersString() const
{
TQString ret;
const_iterator itEnd = end();
// construct string
for(const_iterator it = begin();it != itEnd;++it)
{
if(!(*it).filter.isEmpty())
ret = ret + (*it).filter + ' ';
}
return ret;
}
TQString SQ_LibraryHandler::allFiltersFileDialogString(bool r, bool allfiles) const
{
TQString ret;
const_iterator itEnd = end();
// construct string
for(const_iterator it = begin();it != itEnd;++it)
{
if(!r)
if((*it).writestatic)
ret = ret + (*it).filter + '|' + (*it).quickinfo + '\n';
else;
else if((*it).readable)
ret = ret + (*it).filter + '|' + (*it).quickinfo + '\n';
}
return allfiles ? (ret + "*.*|" + i18n("All files")) : ret.left(ret.length() - 1);
}
/*
* Fill 'filters' with all found filters, and
* 'quick' with appropriate information.
*/
void SQ_LibraryHandler::allFilters(TQStringList &filters, TQStringList &quick) const
{
// clear rubbish
filters.clear();
quick.clear();
// no found libraries ?
if(empty())
return;
const_iterator itEnd = end();
// go through array and fill TQStringLists
for(const_iterator it = begin();it != itEnd;++it)
if(!(*it).filter.isEmpty())
{
filters.append((*it).filter);
quick.append((*it).quickinfo);
}
}
void SQ_LibraryHandler::allWritableFilters(TQStringList &filters, TQStringList &quick) const
{
// clear rubbish
filters.clear();
quick.clear();
// no libraries ?
if(empty())
return;
const_iterator itEnd = end();
// go through array and fill TQStringLists
for(const_iterator it = begin();it != itEnd;++it)
if((*it).writestatic && !(*it).filter.isEmpty())
{
filters.append((*it).filter);
quick.append((*it).quickinfo);
}
}
/*
* Remove and unload all libraries.
*/
void SQ_LibraryHandler::clear()
{
kdDebug() << "SQ_LibraryHandler::clear()" << endl;
iterator itEnd = end();
// unload libraries on clear()
for(iterator it = begin();it != itEnd;++it)
{
writeSettings(&(*it));
// delete temp file
if((*it).needtempfile)
{
delete (*it).tmp_il;
delete (*it).tmp;
}
(*it).codec_destroy((*it).codec_il);
(*it).codec_destroy((*it).codec);
delete (*it).lib;
(*it).lib = 0;
}
TQValueVector<SQ_LIBRARY>::clear();
}
/*
* Add new libraries.
*/
void SQ_LibraryHandler::add(TQStringList &foundLibraries)
{
codec_options o;
TQStringList::iterator itEnd = foundLibraries.end();
for(TQStringList::iterator it = foundLibraries.begin();it != itEnd;++it)
{
TQFileInfo ff(*it);
SQ_LIBRARY libtmp;
// create TQLibrary object
libtmp.lib = new TQLibrary(*it);
libtmp.libpath = *it;
libtmp.lib->load();
// resolve create() and destroy() functions
libtmp.codec_create = (fmt_codec_base*(*)())(libtmp.lib)->resolve(TQString::fromLatin1("codec_create"));
libtmp.codec_destroy = (void (*)(fmt_codec_base*))(libtmp.lib)->resolve(TQString::fromLatin1("codec_destroy"));
// couldn't resolve - corrupted library ?
if(!libtmp.codec_create || !libtmp.codec_destroy)
{
libtmp.lib->unload();
delete libtmp.lib;
}
else
{
// create codec !
fmt_codec_base *codeK = libtmp.codec_create();
// read options
codeK->options(&o);
TQString q = o.name;
// Yet unknown library ?
if(!alreadyInMap(q))
{
libtmp.mime = TQPixmap(reinterpret_cast<const char **>(o.pixmap));
libtmp.mimetype = o.mimetype;
libtmp.mime_multi = libtmp.mimetype.find(';') != -1;
libtmp.quickinfo = q;
libtmp.filter = o.filter;
libtmp.version = o.version;
libtmp.regexp_str = o.mime;
libtmp.config = o.config;
libtmp.regexp.setPattern(libtmp.regexp_str);
libtmp.regexp.setCaseSensitive(true);
libtmp.writestatic = o.writestatic;
libtmp.writeanimated = o.writeanimated;
libtmp.readable = o.readable;
libtmp.canbemultiple = o.canbemultiple;
libtmp.needtempfile = o.needtempfile;
libtmp.tmp = 0;
libtmp.codec_il = libtmp.codec_create();
if(libtmp.needtempfile)
{
libtmp.tmp = new KTempFile;
libtmp.tmp->setAutoDelete(true);
libtmp.tmp->close();
codeK->settempfile(libtmp.tmp->name().ascii());
libtmp.tmp_il = new KTempFile;
libtmp.tmp_il->setAutoDelete(true);
libtmp.tmp_il->close();
libtmp.codec_il->settempfile(libtmp.tmp_il->name().ascii());
}
if(libtmp.writestatic)
codeK->getwriteoptions(&libtmp.opt);
libtmp.codec = codeK;
readSettings(&libtmp);
append(libtmp);
}
else // already known library
{
// destroy codec
libtmp.codec_destroy(codeK);
// unload library
libtmp.lib->unload();
delete libtmp.lib;
}
}
}
// print some information
dump();
}
/*
* Is library named 'quick' already been handled ?
*/
bool SQ_LibraryHandler::alreadyInMap(const TQString &quick) const
{
const_iterator itEnd = end();
// go through array and find 'quick'
for(const_iterator it = begin();it != itEnd;++it)
if((*it).quickinfo == quick)
return true;
return false;
}
/*
* Print some information on found libraries.
*/
void SQ_LibraryHandler::dump() const
{
std::cerr << "SQ_LibraryHandler: memory dump (total " << count() << ")" << endl;
const_iterator itEnd = end();
std::cerr.setf(ios::left);
for(const_iterator it = begin();it != itEnd;++it)
{
std::cerr << std::setw(30)
<< KStringHandler::csqueeze(TQFileInfo((*it).libpath).fileName(), 30)
<< std::setw(0)
<< " ["
<< KStringHandler::rsqueeze((*it).quickinfo, 45)
<< "]"
<< endl;
}
}
/*
* Does any of found libraries handle given extension ?
*/
bool SQ_LibraryHandler::knownExtension(const TQString &ext)
{
iterator itEnd = end();
// go through array and compare extensions
for(iterator it = begin();it != itEnd;++it)
{
if((*it).filter.contains(ext, false))
return true;
}
return false;
}
/*
* Find appropriate SQ_LIBRARY by its name. If
* not found, return NULL.
*
* Name is a string, returned by fmt_quickinfo()
*/
SQ_LIBRARY* SQ_LibraryHandler::libraryByName(const TQString &name)
{
SQ_LIBRARY *l;
iterator itEnd = end();
// go through array and compare names
for(iterator it = begin();it != itEnd;++it)
{
l = &(*it);
if(l->quickinfo == name)
return l;
}
return 0;
}
void SQ_LibraryHandler::writeSettings(SQ_LIBRARY *lib)
{
// no config - no settings
if(lib->config.isEmpty())
return;
kconf->setGroup(lib->quickinfo);
fmt_settings::iterator itEnd = lib->settings.end();
TQString k;
for(fmt_settings::iterator it = lib->settings.begin();it != itEnd;++it)
{
k = (*it).first;
if((*it).second.type == settings_value::v_bool) // boolean
{
k.prepend("b");
kconf->writeEntry(k, (*it).second.bVal);
}
else if((*it).second.type == settings_value::v_int) // integer
{
k.prepend("i");
kconf->writeEntry(k, (*it).second.iVal);
}
else if((*it).second.type == settings_value::v_double) // double
{
k.prepend("d");
kconf->writeEntry(k, (*it).second.dVal);
}
else // string
{
k.prepend("s");
kconf->writeEntry(k, (*it).second.sVal);
}
}
}
void SQ_LibraryHandler::readSettings(SQ_LIBRARY *lib)
{
// no config - no settings
if(lib->config.isEmpty())
return;
TQMap<TQString, TQString> map = kconf->entryMap(lib->quickinfo);
if(!map.size())
{
lib->codec->fill_default_settings();
lib->settings = lib->codec->settings();
return;
}
TQMap<TQString, TQString>::iterator mapEnd = map.end();
fmt_settings &sett = lib->settings;
TQString d, k;
settings_value val;
for(TQMap<TQString, TQString>::iterator mapIt = map.begin();mapIt != mapEnd;++mapIt)
{
k = mapIt.key();
d = mapIt.data();
if(k.startsWith(TQChar('i')))
{
val.type = settings_value::v_int;
val.iVal = d.toInt();
}
else if(k.startsWith(TQChar('d')))
{
val.type = settings_value::v_double;
val.dVal = d.toDouble();
}
else if(k.startsWith(TQChar('b')))
{
val.type = settings_value::v_bool;
val.bVal = (d == "true");
}
else // all other values are treated as strings
{
val.type = settings_value::v_string;
val.sVal = d.ascii();
}
k = k.right(k.length() - 1);
sett[k.ascii()] = val;
}
lib->codec->set_settings(sett);
}
void SQ_LibraryHandler::reload()
{
clear();
load();
}
void SQ_LibraryHandler::load()
{
TQStringList libs;
TQDir dir(SQ_KLIBS, TQString(), TQDir::Unsorted, TQDir::Files);
const TQFileInfoList *list = dir.entryInfoList();
if(list)
{
TQFileInfoListIterator it(*list);
TQFileInfo *fi;
while((fi = it.current()) != 0)
{
libs.append(fi->absFilePath());
++it;
}
}
// just show dump, if no libs were found
add(libs);
}
SQ_LibraryHandler::Support SQ_LibraryHandler::maybeSupported(const KURL &u, const TQString &mime) const
{
const_iterator itEnd = constEnd();
SQ_Config::instance()->setGroup("Main");
bool treat = SQ_Config::instance()->readBoolEntry("treat", true);
// we can determine mimetype by hand or use "mime"
TQString mimeDet = mime.isEmpty() ? KMimeType::findByURL(u)->name() : mime;
// mimetype by magic is not determined automatically
// for non-local urls - we may support this file type or may not
// (we don't know exactly at this moment)
if(!u.isLocalFile() && mimeDet == KMimeType::defaultMimeType())
return (treat ? SQ_LibraryHandler::No : SQ_LibraryHandler::Maybe);
// go through array and compare mimetype names
for(const_iterator it = constBegin();it != itEnd;++it)
{
if((*it).mime_multi)
{
if((*it).mimetype.find(mimeDet, 0, false) != -1)
return SQ_LibraryHandler::Yes;
}
else if((*it).mimetype == mimeDet) // don't waste CPU time with find()
return SQ_LibraryHandler::Yes;
}
// we don't know about given mimetype
return SQ_LibraryHandler::No;
}
void SQ_LibraryHandler::sync()
{
iterator itEnd = end();
// unload libraries on clear()
for(iterator it = begin();it != itEnd;++it)
writeSettings(&(*it));
kconf->sync();
}