• Skip to content
  • Skip to link menu
KDE 4.5 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

typepluginloader.cpp

00001 /*
00002     Copyright (c) 2007 Till Adam <adam@kde.org>
00003     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to the
00017     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018     02110-1301, USA.
00019 */
00020 
00021 #include "typepluginloader_p.h"
00022 
00023 #include "item.h"
00024 #include "itemserializer_p.h"
00025 #include "itemserializerplugin.h"
00026 
00027 // KDE core
00028 #include <kdebug.h>
00029 #include <kmimetype.h>
00030 
00031 // Qt
00032 #include <QtCore/QHash>
00033 #include <QtCore/QString>
00034 #include <QtCore/QStringList>
00035 
00036 #include <boost/graph/adjacency_list.hpp>
00037 #include <boost/graph/topological_sort.hpp>
00038 
00039 // temporary
00040 #include "pluginloader_p.h"
00041 
00042 namespace Akonadi {
00043 
00044 K_GLOBAL_STATIC( DefaultItemSerializerPlugin, s_defaultItemSerializerPlugin )
00045 
00046 class PluginEntry
00047 {
00048   public:
00049     PluginEntry()
00050       : mPlugin( 0 )
00051     {
00052     }
00053 
00054     explicit PluginEntry( const QString &identifier, QObject *plugin = 0 )
00055       : mIdentifier( identifier ), mPlugin( plugin )
00056     {
00057     }
00058 
00059     inline QObject* plugin() const
00060     {
00061       if ( mPlugin )
00062         return mPlugin;
00063 
00064       QObject *object = PluginLoader::self()->createForName( mIdentifier );
00065       if ( !object ) {
00066         kWarning() << "ItemSerializerPluginLoader: "
00067                    << "plugin" << mIdentifier << "is not valid!" << endl;
00068 
00069         // we try to use the default in that case
00070         mPlugin = s_defaultItemSerializerPlugin;
00071       }
00072 
00073       mPlugin = object;
00074       if ( !qobject_cast<ItemSerializerPlugin*>( mPlugin ) ) {
00075         kWarning() << "ItemSerializerPluginLoader: "
00076                    << "plugin" << mIdentifier << "doesn't provide interface ItemSerializerPlugin!" << endl;
00077 
00078         // we try to use the default in that case
00079         mPlugin = s_defaultItemSerializerPlugin;
00080       }
00081 
00082       Q_ASSERT( mPlugin );
00083 
00084       return mPlugin;
00085     }
00086 
00087     QString type() const
00088     {
00089       return mIdentifier;
00090     }
00091 
00092     bool operator<( const PluginEntry &other ) const
00093     {
00094       return mIdentifier < other.mIdentifier;
00095     }
00096 
00097     bool operator<( const QString &type ) const
00098     {
00099       return mIdentifier < type;
00100     }
00101 
00102   private:
00103     QString mIdentifier;
00104     mutable QObject *mPlugin;
00105 };
00106 
00107 static bool operator<( const QString &type, const PluginEntry &entry )
00108 {
00109   return type < entry.type();
00110 }
00111 
00112 
00113 class PluginRegistry
00114 {
00115   public:
00116     PluginRegistry()
00117       : mDefaultPlugin( PluginEntry( QLatin1String( "application/octet-stream" ), s_defaultItemSerializerPlugin ) )
00118     {
00119       const PluginLoader* pl = PluginLoader::self();
00120       if ( !pl ) {
00121         kWarning() << "Cannot instantiate plugin loader!" << endl;
00122         return;
00123       }
00124       const QStringList types = pl->types();
00125       kDebug() << "ItemSerializerPluginLoader: "
00126                << "found" << types.size() << "plugins." << endl;
00127       allPlugins.reserve( types.size() + 1 );
00128       foreach ( const QString &type, types )
00129         allPlugins.append( PluginEntry( type ) );
00130       allPlugins.append( mDefaultPlugin );
00131       std::sort( allPlugins.begin(), allPlugins.end() );
00132     }
00133 
00134     const PluginEntry& findBestMatch( const QString &type )
00135     {
00136       KMimeType::Ptr mimeType = KMimeType::mimeType( type, KMimeType::ResolveAliases );
00137       if ( mimeType.isNull() )
00138         return mDefaultPlugin;
00139 
00140       // step 1: find all plugins that match at all
00141       QVector<int> matchingIndexes;
00142       for ( int i = 0, end = allPlugins.size(); i < end; ++i ) {
00143         if ( mimeType->is( allPlugins[i].type() ) )
00144           matchingIndexes.append( i );
00145       }
00146 
00147       // 0 matches: no luck (shouldn't happend though, as application/octet-stream matches everything)
00148       if ( matchingIndexes.isEmpty() )
00149         return mDefaultPlugin;
00150       // 1 match: we are done
00151       if ( matchingIndexes.size() == 1 )
00152         return allPlugins[matchingIndexes.first()];
00153 
00154       // step 2: if we have more than one match, find the most specific one using topological sort
00155       boost::adjacency_list<> graph( matchingIndexes.size() );
00156       for ( int i = 0, end = matchingIndexes.size() ; i != end ; ++i ) {
00157         KMimeType::Ptr mimeType = KMimeType::mimeType( allPlugins[matchingIndexes[i]].type(), KMimeType::ResolveAliases );
00158         if ( mimeType.isNull() )
00159           continue;
00160         for ( int j = 0; j != end; ++j ) {
00161           if ( i != j && mimeType->is( allPlugins[matchingIndexes[j]].type() ) )
00162             boost::add_edge( j, i, graph );
00163         }
00164       }
00165 
00166       QVector<int> order;
00167       order.reserve( allPlugins.size() );
00168       try {
00169         boost::topological_sort( graph, std::back_inserter( order ) );
00170       } catch ( boost::not_a_dag &e ) {
00171         kWarning() << "Mimetype tree is not a DAG!";
00172         return mDefaultPlugin;
00173       }
00174 
00175       return allPlugins[matchingIndexes[order.first()]];
00176     }
00177 
00178     QVector<PluginEntry> allPlugins;
00179     QHash<QString, QObject*> cachedPlugins;
00180 
00181   private:
00182     PluginEntry mDefaultPlugin;
00183 };
00184 
00185 K_GLOBAL_STATIC( PluginRegistry, s_pluginRegistry )
00186 
00187 QObject* TypePluginLoader::objectForMimeType( const QString &mimetype )
00188 {
00189   // plugin cached, so let's take that one
00190   if ( s_pluginRegistry->cachedPlugins.contains( mimetype ) )
00191     return s_pluginRegistry->cachedPlugins.value( mimetype );
00192 
00193   QObject *plugin = 0;
00194 
00195   // check if we have one that matches exactly
00196   const QVector<PluginEntry>::const_iterator it
00197     = qBinaryFind( s_pluginRegistry->allPlugins.constBegin(), s_pluginRegistry->allPlugins.constEnd(), mimetype );
00198   if ( it != s_pluginRegistry->allPlugins.constEnd() ) {
00199     plugin = ( *it ).plugin();
00200   } else {
00201     // check if we have a more generic plugin
00202     const PluginEntry &entry = s_pluginRegistry->findBestMatch( mimetype );
00203     kDebug() << "Did not find exactly matching serializer plugin for type" << mimetype
00204              << ", taking" << entry.type() << "as the closest match";
00205     plugin = entry.plugin();
00206   }
00207 
00208   Q_ASSERT(plugin);
00209   s_pluginRegistry->cachedPlugins.insert( mimetype, plugin );
00210   return plugin;
00211 }
00212 
00213 ItemSerializerPlugin* TypePluginLoader::pluginForMimeType( const QString &mimetype )
00214 {
00215   ItemSerializerPlugin* plugin = qobject_cast<ItemSerializerPlugin*>( objectForMimeType( mimetype ) );
00216   Q_ASSERT( plugin );
00217   return plugin;
00218 }
00219 
00220 }

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal