/********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #define QTOPIA_INTERNAL_MIMEEXT #include "mimetype.h" #include "applnk.h" #include "resource.h" #include #include "config.h" #include #include static void cleanupMime() { MimeType::clear(); } class MimeTypeData { public: MimeTypeData(const QString& i) : id(i) { apps.setAutoDelete(TRUE); } QString id; QString extension; QList apps; QString description() { if ( desc.isEmpty() ) desc = QPEApplication::tr("%1 document").arg(apps.first()->name()); return desc; } QPixmap regIcon() { if ( regicon.isNull() ) loadPixmaps(); return regicon; } QPixmap bigIcon() { if ( bigicon.isNull() ) loadPixmaps(); return bigicon; } private: void loadPixmaps() { if ( apps.count() ) { QString icon; for (AppLnk* lnk = apps.first(); icon.isNull() && lnk; lnk=apps.next()) { QStringList icons = lnk->mimeTypeIcons(); if ( icons.count() ) { QStringList types = lnk->mimeTypes(); for (QStringList::ConstIterator t=types.begin(),i=icons.begin(); t!=types.end() && i!=icons.end(); ++i,++t) { if ( *t == id ) { icon = *i; break; } } } } if ( icon.isNull() ) { AppLnk* lnk = apps.first(); regicon = lnk->pixmap(); bigicon = lnk->bigPixmap(); } else { QImage unscaledIcon = Resource::loadImage( icon ); regicon.convertFromImage( unscaledIcon.smoothScale( AppLnk::smallIconSize(), AppLnk::smallIconSize() ) ); bigicon.convertFromImage( unscaledIcon.smoothScale( AppLnk::bigIconSize(), AppLnk::bigIconSize() ) ); } } } QPixmap regicon; QPixmap bigicon; QString desc; }; class MimeType::Private : public QDict { public: Private() {} ~Private() {} // ... }; MimeType::Private* MimeType::d=0; static QMap *typeFor = 0; static QMap *extFor = 0; static bool appsUpdated = FALSE; MimeType::Private& MimeType::data() { if ( !d ) { d = new Private; d->setAutoDelete(TRUE); static bool setCleanup = FALSE; if ( !setCleanup ) { qAddPostRoutine( cleanupMime ); setCleanup = TRUE; } } return *d; } /*! \class MimeType mimetype.h \brief The MimeType class provides MIME type information. A MimeType object is a light-weight value which provides information about a MIME type. \ingroup qtopiaemb */ /*! Constructs a MimeType. Normally, \a ext_or_id is a MIME type, but if \a ext_or_id starts with / or contains no /, it is interpretted as a filename and the extension (eg. .txt) is used as the MIME type. */ MimeType::MimeType( const QString& ext_or_id ) { init(ext_or_id); } /*! Constructs a MimeType from the type() of \a lnk. */ MimeType::MimeType( const DocLnk& lnk ) { init(lnk.type()); } /*! Returns the MIME type identifier. */ QString MimeType::id() const { return i; } /*! Returns a description of the MIME Type. This is usually based on the application() associated with the type. */ QString MimeType::description() const { MimeTypeData* d = data(i); return d ? d->description() : QString::null; } /*! Returns a small QPixmap appropriate for the MIME type. */ QPixmap MimeType::pixmap() const { MimeTypeData* d = data(i); return d ? d->regIcon() : QPixmap(); } /*! \internal This function is not generally available. */ QString MimeType::extension() const { return extensions().first(); } /*! \internal This function is not generally available. */ QStringList MimeType::extensions() const { loadExtensions(); return *(*extFor).find(i); } /*! Returns a larger QPixmap appropriate for the MIME type. */ QPixmap MimeType::bigPixmap() const { MimeTypeData* d = data(i); return d ? d->bigIcon() : QPixmap(); } /*! Returns the AppLnk defining the application associated with this MIME type, or 0 if none is associated. The caller must not retain the pointer, but of course you can dereference it to take a copy if needed. \sa Service::binding() */ const AppLnk* MimeType::application() const { MimeTypeData* d = data(i); return d ? d->apps.first() : 0; } static QString serviceBinding(const QString& service) { // Copied from qtopiaservices QString svrc = service; for (int i=0; i<(int)svrc.length(); i++) if ( svrc[i]=='/' ) svrc[i] = '-'; return "Service-"+svrc; } /*! \internal */ void MimeType::registerApp( const AppLnk& lnk ) { QStringList list = lnk.mimeTypes(); for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { MimeTypeData* cur = data()[*it]; AppLnk* l = new AppLnk(lnk); if ( !cur ) { cur = new MimeTypeData( *it ); data().insert( *it, cur ); cur->apps.append(l); } else if ( cur->apps.count() ) { Config binding(serviceBinding("Open/"+*it)); binding.setGroup("Service"); QString def = binding.readEntry("default"); if ( l->exec() == def ) cur->apps.prepend(l); else cur->apps.append(l); } else { cur->apps.append(l); } } } /*! \internal */ void MimeType::clear() { delete d; d = 0; delete typeFor; typeFor = 0; delete extFor ; extFor = 0; appsUpdated = FALSE; } void MimeType::loadExtensions() { if ( !typeFor ) { extFor = new QMap; typeFor = new QMap; loadExtensions("/etc/mime.types"); loadExtensions(QPEApplication::qpeDir()+"etc/mime.types"); } } void MimeType::loadExtensions(const QString& filename) { QFile file(filename); if ( file.open(IO_ReadOnly) ) { QTextStream in(&file); QRegExp space("[ \t]+"); while (!in.atEnd()) { QStringList tokens = QStringList::split(space, in.readLine()); QStringList::ConstIterator it = tokens.begin(); if ( it != tokens.end() ) { QString id = *it; ++it; // new override old (though left overrides right) QStringList exts = (*extFor)[id]; QStringList newexts; while ( it != tokens.end() ) { exts.remove(*it); if ( !newexts.contains(*it) ) newexts.append(*it); (*typeFor)[*it] = id; ++it; } (*extFor)[id] = newexts + exts; } } } } void MimeType::init( const QString& ext_or_id ) { if ( ext_or_id[0] != '/' && ext_or_id.contains('/') ) { i = ext_or_id.lower(); } else { loadExtensions(); int dot = ext_or_id.findRev('.'); QString ext = dot >= 0 ? ext_or_id.mid(dot+1) : ext_or_id; i = (*typeFor)[ext.lower()]; if ( i.isNull() ) i = "application/octet-stream"; } if ( !appsUpdated ) { updateApplications(); } } MimeTypeData* MimeType::data(const QString& id) { MimeTypeData* d = data()[id]; if ( !d ) { int s = id.find('/'); QString idw = id.left(s)+"/*"; d = data()[idw]; } return d; } /*! Returns a Qtopia folder containing application definitions. */ QString MimeType::appsFolderName() { return QPEApplication::qpeDir() + "apps"; } /*! Reloads application definitions. */ void MimeType::updateApplications() { // clear(); appsUpdated = true; AppLnkSet apps( appsFolderName() ); updateApplications(&apps); } void MimeType::updateApplications(AppLnkSet* folder) { for ( QListIterator it( folder->children() ); it.current(); ++it ) { registerApp(*it.current()); } }