kio Library API Documentation

kfilemetainfo.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 2001-2002 Rolf Magnus <ramagnus@kde.org>
00004  *  Copyright (C) 2001-2002 Carsten Pfeiffer <pfeiffer@kde.org>
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation version 2.0.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public 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
00017  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  *  Boston, MA 02111-1307, USA.
00019  *
00020  *  $Id: kfilemetainfo.cpp,v 1.81.2.1 2004/08/24 22:36:36 mardelle Exp $
00021  */
00022 
00023 #include <assert.h>
00024 
00025 #include <qshared.h>
00026 #include <qdict.h>
00027 
00028 #include <ktrader.h>
00029 #include <kstaticdeleter.h>
00030 #include <kparts/componentfactory.h>
00031 #include <kuserprofile.h>
00032 #include <kdebug.h>
00033 #include <kmimetype.h>
00034 #include <kdatastream.h> // needed for serialization of bool
00035 #include <klocale.h>
00036 #include <kio/global.h>
00037 
00038 #include "kfilemetainfo.h"
00039 
00040 // shared data of a KFileMetaInfoItem
00041 class KFileMetaInfoItem::Data : public QShared
00042 {
00043 public:
00044     Data( const KFileMimeTypeInfo::ItemInfo* mti, const QString& _key,
00045           const QVariant& _value )
00046         : QShared(),
00047           mimeTypeInfo( mti ),
00048           key( _key ),
00049           value( _value ),
00050           dirty( false ),
00051           added( false ),
00052           removed( false )
00053     {}
00054 
00055     // we use this one for the streaming operators
00056     Data() : mimeTypeInfo( 0L )
00057     {}
00058 
00059     ~Data()
00060     {
00061         if ( this == null ) // only the null item owns its mimeTypeInfo
00062             delete mimeTypeInfo;
00063     }
00064 
00065     const KFileMimeTypeInfo::ItemInfo*  mimeTypeInfo;
00066     // mimeTypeInfo has the key, too, but only for non-variable ones
00067     QString                             key;
00068     QVariant                            value;
00069     bool                                dirty    :1;
00070     bool                                added    :1;
00071     bool                                removed  :1;
00072 
00073     static Data* null;
00074     static Data* makeNull();
00075 };
00076 
00077 //this is our null data
00078 KFileMetaInfoItem::Data* KFileMetaInfoItem::Data::null;
00079 static KStaticDeleter<KFileMetaInfoItem::Data> sd_KFileMetaInfoItemData;
00080 
00081 KFileMetaInfoItem::Data* KFileMetaInfoItem::Data::makeNull()
00082 {
00083     if (!null)
00084     {
00085         // We deliberately do not reset "null" after it has been destroyed!
00086         // Otherwise we will run into problems later in ~KFileMetaInfoItem
00087         // where the d-pointer is compared against null.
00088 
00089         KFileMimeTypeInfo::ItemInfo* info = new KFileMimeTypeInfo::ItemInfo();
00090         null = new Data(info, QString::null, QVariant());
00091         sd_KFileMetaInfoItemData.setObject( null );
00092     }
00093     return null;
00094 }
00095 
00096 KFileMetaInfoItem::KFileMetaInfoItem( const KFileMimeTypeInfo::ItemInfo* mti,
00097                                       const QString& key, const QVariant& value )
00098     : d( new Data( mti, key, value ) )
00099 {
00100 }
00101 
00102 KFileMetaInfoItem::KFileMetaInfoItem( const KFileMetaInfoItem& item )
00103 {
00104     // operator= does everything that's necessary
00105     d = Data::makeNull();
00106     *this = item;
00107 }
00108 
00109 KFileMetaInfoItem::KFileMetaInfoItem()
00110 {
00111     d = Data::makeNull();
00112 }
00113 
00114 KFileMetaInfoItem::~KFileMetaInfoItem()
00115 {
00116     deref();
00117 }
00118 
00119 const KFileMetaInfoItem& KFileMetaInfoItem::operator=
00120                                               (const KFileMetaInfoItem & item )
00121 {
00122     if (d != item.d)
00123     {
00124         // first deref the old one
00125         deref();
00126         d = item.d;
00127         // and now ref the new one
00128         ref();
00129     }
00130 
00131     return *this;
00132 }
00133 
00134 bool KFileMetaInfoItem::setValue( const QVariant& value )
00135 {
00136     // We don't call makeNull here since it isn't necassery, see deref()
00137     if ( d == Data::null ) return false;
00138 
00139     if ( ! (d->mimeTypeInfo->attributes() & KFileMimeTypeInfo::Modifiable ) ||
00140          ! (value.canCast(d->mimeTypeInfo->type())))
00141     {
00142         kdDebug(7033) << "setting the value of " << key() << "failed\n";
00143         return false;
00144     }
00145 
00146 //    kdDebug(7033) << key() << ".setValue()\n";
00147 
00148     if ( d->value == value )
00149         return true;
00150 
00151     d->dirty = true;
00152     d->value = value;
00153     // If we don't cast (and test for canCast in the above if), QVariant is
00154     // very picky about types (e.g. QString vs. QCString or int vs. uint)
00155     d->value.cast(d->mimeTypeInfo->type());
00156 
00157     return true;
00158 }
00159 
00160 bool KFileMetaInfoItem::isRemoved() const
00161 {
00162     return d->removed;
00163 }
00164 
00165 QString KFileMetaInfoItem::key() const
00166 {
00167     return d->key;
00168 }
00169 
00170 QString KFileMetaInfoItem::translatedKey() const
00171 {
00172     // are we a variable key?
00173     if (d->mimeTypeInfo->key().isNull())
00174     {
00175         // then try if we have luck with i18n()
00176         return i18n(d->key.utf8());
00177     }
00178 
00179     return d->mimeTypeInfo->translatedKey();
00180 }
00181 
00182 const QVariant& KFileMetaInfoItem::value() const
00183 {
00184     return d->value;
00185 }
00186 
00187 QString KFileMetaInfoItem::string( bool mangle ) const
00188 {
00189     return d->mimeTypeInfo->string(d->value, mangle);
00190 }
00191 
00192 QVariant::Type KFileMetaInfoItem::type() const
00193 {
00194     return d->mimeTypeInfo->type();
00195 }
00196 
00197 uint KFileMetaInfoItem::unit() const
00198 {
00199     return d->mimeTypeInfo->unit();
00200 }
00201 
00202 bool KFileMetaInfoItem::isModified() const
00203 {
00204     return d->dirty;
00205 }
00206 
00207 QString KFileMetaInfoItem::prefix() const
00208 {
00209     return d->mimeTypeInfo->prefix();
00210 }
00211 
00212 QString KFileMetaInfoItem::suffix() const
00213 {
00214     return d->mimeTypeInfo->suffix();
00215 }
00216 
00217 uint KFileMetaInfoItem::hint() const
00218 {
00219     return d->mimeTypeInfo->hint();
00220 }
00221 
00222 uint KFileMetaInfoItem::attributes() const
00223 {
00224     return d->mimeTypeInfo->attributes();
00225 }
00226 
00227 bool KFileMetaInfoItem::isEditable() const
00228 {
00229     return d->mimeTypeInfo->attributes() & KFileMimeTypeInfo::Modifiable;
00230 }
00231 
00232 bool KFileMetaInfoItem::isValid() const
00233 {
00234     // We don't call makeNull here since it isn't necassery:
00235     // If d is equal to null it means that null is initialized already.
00236     // null is 0L when it hasn't been initialized and d is never 0L.
00237     return d != Data::null;
00238 }
00239 
00240 void KFileMetaInfoItem::setAdded()
00241 {
00242     d->added = true;
00243 }
00244 
00245 void KFileMetaInfoItem::setRemoved()
00246 {
00247     d->removed = true;
00248 }
00249 
00250 void KFileMetaInfoItem::ref()
00251 {
00252     if (d != Data::null) d->ref();
00253 }
00254 
00255 void KFileMetaInfoItem::deref()
00256 {
00257     // We don't call makeNull here since it isn't necassery:
00258     // If d is equal to null it means that null is initialized already.
00259     // null is 0L when it hasn't been initialized and d is never 0L.
00260     if ((d != Data::null) && d->deref())
00261     {
00262 //        kdDebug(7033) << "item " << d->key
00263 //                      << " is finally deleted\n";
00264         delete d;
00265         d=0;
00266     }
00267 }
00268 
00271 
00272 // shared data of a KFileMetaInfo
00273 class KFileMetaInfo::Data : public QShared
00274 {
00275 public:
00276     Data(const KURL& _url, uint _what)
00277         : QShared(),
00278           url(_url),
00279           what(_what),
00280           mimeTypeInfo( 0L )
00281     {}
00282 
00283     // wee use this one for the streaming operators
00284     Data() {};
00285 
00286     KURL                              url;
00287     uint                              what;
00288     QMap<QString, KFileMetaInfoGroup> groups;
00289     const KFileMimeTypeInfo*          mimeTypeInfo;
00290     QStringList                       removedGroups;
00291 
00292     static Data* null;
00293     static Data* makeNull();
00294 
00295 };
00296 
00297 KFileMetaInfo::KFileMetaInfo( const QString& path, const QString& mimeType,
00298                               uint what )
00299 {
00300     KURL u;
00301 
00302     u.setPath(path);
00303     init(u, mimeType, what);
00304 }
00305 
00306 KFileMetaInfo::KFileMetaInfo( const KURL& url, const QString& mimeType,
00307                               uint what )
00308 {
00309     init(url, mimeType, what);
00310 }
00311 
00312 void KFileMetaInfo::init( const KURL& url, const QString& mimeType,
00313                           uint what )
00314 {
00315     d = new Data( url, what );
00316 
00317     QString mT;
00318     if (mimeType.isEmpty())
00319         mT = KMimeType::findByURL(url)->name();
00320     else
00321         mT = mimeType;
00322 
00323     // let's "share our property"
00324     KFileMetaInfo item(*this);
00325 
00326     d->mimeTypeInfo = KFileMetaInfoProvider::self()->mimeTypeInfo(mT);
00327     if ( d->mimeTypeInfo )
00328     {
00329 //        kdDebug(7033) << "Found mimetype info for " << mT << endl;
00330         KFilePlugin *p = plugin();
00331         if (p && !p->readInfo( item, what))
00332             *this=KFileMetaInfo();
00333     }
00334     else
00335     {
00336 //        kdDebug(7033) << "No mimetype info for " << mimeType << endl;
00337         d = Data::makeNull();
00338     }
00339 }
00340 
00341 KFileMetaInfo::KFileMetaInfo( const KFileMetaInfo& original )
00342 {
00343     // operator= does everything that's necessary
00344     d = Data::makeNull();
00345     *this = original;
00346 }
00347 
00348 KFileMetaInfo::KFileMetaInfo()
00349 {
00350     d = Data::makeNull();
00351 }
00352 
00353 KFileMetaInfo::~KFileMetaInfo()
00354 {
00355     deref();
00356 }
00357 
00358 QStringList KFileMetaInfo::supportedGroups() const
00359 {
00360     assert(isValid());
00361     return d->mimeTypeInfo->supportedGroups();
00362 }
00363 
00364 QStringList KFileMetaInfo::supportedKeys() const
00365 {
00366     assert(isValid());
00367     return d->mimeTypeInfo->supportedKeys();
00368 }
00369 
00370 QStringList KFileMetaInfo::groups() const
00371 {
00372     QStringList list;
00373     QMapConstIterator<QString, KFileMetaInfoGroup> it = d->groups.begin();
00374     for ( ; it != d->groups.end(); ++it )
00375         list += (*it).name();
00376 
00377     return list;
00378 }
00379 
00380 QStringList KFileMetaInfo::editableGroups() const
00381 {
00382     QStringList list;
00383     QStringList supported = supportedGroups();
00384     QStringList::ConstIterator it = supported.begin();
00385     for ( ; it != supported.end(); ++it ) {
00386         const KFileMimeTypeInfo::GroupInfo * groupInfo = d->mimeTypeInfo->groupInfo( *it );
00387         if ( groupInfo && groupInfo->attributes() &
00388              (KFileMimeTypeInfo::Addable | KFileMimeTypeInfo::Removable) )
00389             list.append( *it );
00390     }
00391 
00392     return list;
00393 }
00394 
00395 QStringList KFileMetaInfo::preferredGroups() const
00396 {
00397     assert(isValid());
00398     QStringList list = groups();
00399     QStringList newlist;
00400     QStringList preferred = d->mimeTypeInfo->preferredGroups();
00401     QStringList::Iterator pref;
00402 
00403     // move all keys from the preferred groups that are in our list to a new list
00404     for ( pref = preferred.begin(); pref != preferred.end(); pref++ )
00405     {
00406         QStringList::Iterator group = list.find(*pref);
00407         if ( group != list.end() )
00408         {
00409              newlist.append( *group );
00410              list.remove(group);
00411         }
00412     }
00413 
00414     // now the old list only contains the non-preferred items, so we
00415     // add the remaining ones to newlist
00416     newlist += list;
00417 
00418     return newlist;
00419 }
00420 
00421 QStringList KFileMetaInfo::preferredKeys() const
00422 {
00423     QStringList newlist;
00424 
00425     QStringList list = preferredGroups();
00426     for (QStringList::Iterator git = list.begin(); git != list.end(); ++git)
00427     {
00428         newlist += d->groups[*git].preferredKeys();
00429     }
00430 
00431     return newlist;
00432 }
00433 
00434 KFileMetaInfoGroup KFileMetaInfo::group(const QString& key) const
00435 {
00436     QMapIterator<QString,KFileMetaInfoGroup> it = d->groups.find( key );
00437     if ( it != d->groups.end() )
00438         return it.data();
00439     else
00440         return KFileMetaInfoGroup();
00441 }
00442 
00443 bool KFileMetaInfo::addGroup( const QString& name )
00444 {
00445     assert(isValid());
00446     if ( d->mimeTypeInfo->supportedGroups().contains(name) &&
00447          ! d->groups.contains(name) )
00448     {
00449         KFileMetaInfoGroup group( name, d->mimeTypeInfo );
00450 
00451         // add all the items that can't be added by the user later
00452         const KFileMimeTypeInfo::GroupInfo* ginfo = d->mimeTypeInfo->groupInfo(name);
00453         Q_ASSERT(ginfo);
00454         if (!ginfo) return false;
00455 
00456         QStringList keys = ginfo->supportedKeys();
00457         for (QStringList::Iterator it = keys.begin(); it != keys.end(); ++it)
00458         {
00459             const KFileMimeTypeInfo::ItemInfo* iteminfo = ginfo->itemInfo(*it);
00460             Q_ASSERT(ginfo);
00461             if (!iteminfo) return false;
00462 
00463             if ( !(iteminfo->attributes() & KFileMimeTypeInfo::Addable) &&
00464                   (iteminfo->attributes() & KFileMimeTypeInfo::Modifiable))
00465             {
00466                 // append it now or never
00467                 group.appendItem(iteminfo->key(), QVariant());
00468             }
00469 
00470         }
00471 
00472         d->groups.insert(name, group);
00473         group.setAdded();
00474         return true;
00475     }
00476 
00477     return false;
00478 }
00479 
00480 bool KFileMetaInfo::removeGroup( const QString& name )
00481 {
00482     QMapIterator<QString, KFileMetaInfoGroup> it = d->groups.find(name);
00483     if ( (it==d->groups.end()) ||
00484         !((*it).attributes() & KFileMimeTypeInfo::Removable))
00485         return false;
00486 
00487     d->groups.remove(it);
00488     d->removedGroups.append(name);
00489     return true;
00490 }
00491 
00492 QStringList KFileMetaInfo::removedGroups()
00493 {
00494     return d->removedGroups;
00495 }
00496 
00497 const KFileMetaInfo& KFileMetaInfo::operator= (const KFileMetaInfo& info )
00498 {
00499     if (d != info.d)
00500     {
00501         deref();
00502         // first deref the old one
00503         d = info.d;
00504         // and now ref the new one
00505         ref();
00506     }
00507     return *this;
00508 }
00509 
00510 bool KFileMetaInfo::isValid() const
00511 {
00512     // We don't call makeNull here since it isn't necassery, see deref()
00513     return d != Data::null;
00514 }
00515 
00516 bool KFileMetaInfo::isEmpty() const
00517 {
00518     for (QMapIterator<QString, KFileMetaInfoGroup> it = d->groups.begin();
00519          it!=d->groups.end(); ++it)
00520         if (!(*it).isEmpty())
00521             return false;
00522     return true;
00523 }
00524 
00525 bool KFileMetaInfo::applyChanges()
00526 {
00527     bool doit = false;
00528 
00529 //    kdDebug(7033) << "KFileMetaInfo::applyChanges()\n";
00530 
00531     // look up if we need to write to the file
00532     QMapConstIterator<QString, KFileMetaInfoGroup> it;
00533     for (it = d->groups.begin(); it!=d->groups.end() && !doit; ++it)
00534     {
00535         if ( (*it).isModified() )
00536             doit = true;
00537 
00538         else
00539         {
00540             QStringList keys = it.data().keys();
00541             for (QStringList::Iterator it2 = keys.begin(); it2!=keys.end(); ++it2)
00542             {
00543                 if ( (*it)[*it2].isModified() )
00544                 {
00545                     doit = true;
00546                     break;
00547                 }
00548             }
00549         }
00550     }
00551 
00552     if (!doit)
00553     {
00554         kdDebug(7033) << "Don't need to write, nothing changed\n";
00555         return true;
00556     }
00557 
00558     KFilePlugin* p = plugin();
00559     if (!p) return false;
00560 
00561 //    kdDebug(7033) << "Ok, trying to write the info\n";
00562 
00563     return p->writeInfo(*this);
00564 }
00565 
00566 KFilePlugin * const KFileMetaInfo::plugin() const
00567 {
00568     assert(isValid());
00569     KFileMetaInfoProvider* prov = KFileMetaInfoProvider::self();
00570     return prov->plugin( d->mimeTypeInfo->mimeType() );
00571 }
00572 
00573 QString KFileMetaInfo::mimeType() const
00574 {
00575     assert(isValid());
00576     return d->mimeTypeInfo->mimeType();
00577 }
00578 
00579 bool KFileMetaInfo::contains(const QString& key) const
00580 {
00581     QStringList glist = groups();
00582     for (QStringList::Iterator it = glist.begin(); it != glist.end(); ++it)
00583     {
00584         KFileMetaInfoGroup g = d->groups[*it];
00585         if (g.contains(key)) return true;
00586     }
00587     return false;
00588 }
00589 
00590 bool KFileMetaInfo::containsGroup(const QString& key) const
00591 {
00592     return groups().contains(key);
00593 }
00594 
00595 KFileMetaInfoItem KFileMetaInfo::item( const QString& key) const
00596 {
00597     QStringList groups = preferredGroups();
00598     for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
00599     {
00600         KFileMetaInfoItem i = d->groups[*it][key];
00601         if (i.isValid()) return i;
00602     }
00603     return KFileMetaInfoItem();
00604 }
00605 
00606 KFileMetaInfoItem KFileMetaInfo::item(const KFileMetaInfoItem::Hint hint) const
00607 {
00608     QStringList groups = preferredGroups();
00609     QStringList::ConstIterator it;
00610     for (it = groups.begin(); it != groups.end(); ++it)
00611     {
00612         KFileMetaInfoItem i = d->groups[*it].item(hint);
00613         if (i.isValid()) return i;
00614     }
00615     return KFileMetaInfoItem();
00616 }
00617 
00618 KFileMetaInfoItem KFileMetaInfo::saveItem( const QString& key,
00619                                            const QString& preferredGroup,
00620                                            bool createGroup )
00621 {
00622     assert(isValid());
00623     // try the preferred groups first
00624     if ( !preferredGroup.isEmpty() ) {
00625         QMapIterator<QString,KFileMetaInfoGroup> it =
00626             d->groups.find( preferredGroup );
00627 
00628         // try to create the preferred group, if necessary
00629         if ( it == d->groups.end() && createGroup ) {
00630             const KFileMimeTypeInfo::GroupInfo *groupInfo =
00631                 d->mimeTypeInfo->groupInfo( preferredGroup );
00632             if ( groupInfo && groupInfo->supportedKeys().contains( key ) ) {
00633                 if ( addGroup( preferredGroup ) )
00634                     it = d->groups.find( preferredGroup );
00635             }
00636         }
00637 
00638         if ( it != d->groups.end() ) {
00639             KFileMetaInfoItem item = it.data().addItem( key );
00640             if ( item.isValid() )
00641                 return item;
00642         }
00643     }
00644 
00645     QStringList groups = preferredGroups();
00646 
00647     KFileMetaInfoItem item;
00648 
00649     QStringList::ConstIterator groupIt = groups.begin();
00650     for ( ; groupIt != groups.end(); ++groupIt )
00651     {
00652         QMapIterator<QString,KFileMetaInfoGroup> it = d->groups.find( *groupIt );
00653         if ( it != d->groups.end() )
00654         {
00655             KFileMetaInfoGroup group = it.data();
00656             item = findEditableItem( group, key );
00657             if ( item.isValid() )
00658                 return item;
00659         }
00660         else // not existant -- try to create the group
00661         {
00662             const KFileMimeTypeInfo::GroupInfo *groupInfo =
00663                 d->mimeTypeInfo->groupInfo( *groupIt );
00664             if ( groupInfo && groupInfo->supportedKeys().contains( key ) )
00665             {
00666                 if ( addGroup( *groupIt ) )
00667                 {
00668                     KFileMetaInfoGroup group = d->groups[*groupIt];
00669                     KFileMetaInfoItem item = group.addItem( key );
00670                     if ( item.isValid() )
00671                         return item;
00672 //                     else ### add when removeGroup() is implemented :)
00673 //                         removeGroup( *groupIt ); // couldn't add item -> remove
00674                 }
00675             }
00676         }
00677     }
00678 
00679     // finally check for variable items
00680 
00681     return item;
00682 }
00683 
00684 KFileMetaInfoItem KFileMetaInfo::findEditableItem( KFileMetaInfoGroup& group,
00685                                                    const QString& key )
00686 {
00687     assert(isValid());
00688     KFileMetaInfoItem item = group.addItem( key );
00689     if ( item.isValid() && item.isEditable() )
00690          return item;
00691 
00692     if ( (d->mimeTypeInfo->groupInfo( group.name() )->attributes() & KFileMimeTypeInfo::Addable) )
00693         return item;
00694 
00695     return KFileMetaInfoItem();
00696 }
00697 
00698 KFileMetaInfoGroup KFileMetaInfo::appendGroup(const QString& name)
00699 {
00700     assert(isValid());
00701     if ( d->mimeTypeInfo->supportedGroups().contains(name) &&
00702          ! d->groups.contains(name) )
00703     {
00704         KFileMetaInfoGroup group( name, d->mimeTypeInfo );
00705         d->groups.insert(name, group);
00706         return group;
00707     }
00708 
00709     else {
00710         kdWarning(7033) << "Someone's trying to add a KFileMetaInfoGroup which is not supported or already existing: " << name << endl;
00711         return KFileMetaInfoGroup();
00712     }
00713 }
00714 
00715 QString KFileMetaInfo::path() const
00716 {
00717     return d->url.isLocalFile() ? d->url.path() : QString::null;
00718 }
00719 
00720 KURL KFileMetaInfo::url() const
00721 {
00722     return d->url;
00723 }
00724 
00725 void KFileMetaInfo::ref()
00726 {
00727     if (d != Data::null) d->ref();
00728 
00729 }
00730 
00731 void KFileMetaInfo::deref()
00732 {
00733     // We don't call makeNull here since it isn't necassery:
00734     // If d is equal to null it means that null is initialized already.
00735     // null is 0L when it hasn't been initialized and d is never 0L.
00736     if ((d != Data::null) && d->deref())
00737     {
00738 //        kdDebug(7033) << "metainfo object for " << d->url.path << " is finally deleted\n";
00739         delete d;
00740         d=0;
00741     }
00742 
00743 }
00744 
00745 
00746 KFileMetaInfo::Data* KFileMetaInfo::Data::null = 0L;
00747 static KStaticDeleter<KFileMetaInfo::Data> sd_KFileMetaInfoData;
00748 
00749 KFileMetaInfo::Data* KFileMetaInfo::Data::makeNull()
00750 {
00751     if (!null)
00752         // We deliberately do not reset "null" after it has been destroyed!
00753         // Otherwise we will run into problems later in ~KFileMetaInfoItem
00754         // where the d-pointer is compared against null.
00755     null = sd_KFileMetaInfoData.setObject( new KFileMetaInfo::Data(KURL(), 0) );
00756     return null;
00757 }
00758 
00761 
00762 KFilePlugin::KFilePlugin( QObject *parent, const char *name,
00763                           const QStringList& /*args*/)
00764     : QObject( parent, name )
00765 {
00766 //    kdDebug(7033) << "loaded a plugin for " << name << endl;
00767 }
00768 
00769 KFilePlugin::~KFilePlugin()
00770 {
00771     kdDebug(7033) << "unloaded a plugin for " << name() << endl;
00772 }
00773 
00774 KFileMimeTypeInfo * KFilePlugin::addMimeTypeInfo( const QString& mimeType )
00775 {
00776     KFileMimeTypeInfo* info;
00777 
00778     info = KFileMetaInfoProvider::self()-> addMimeTypeInfo( mimeType );
00779     return info;
00780 }
00781 
00782 void KFilePlugin::virtual_hook( int, void* )
00783 { /*BASE::virtual_hook( id, data );*/ }
00784 
00785 
00786 KFileMimeTypeInfo::GroupInfo*  KFilePlugin::addGroupInfo(KFileMimeTypeInfo* info,
00787                   const QString& key, const QString& translatedKey) const
00788 {
00789     return info->addGroupInfo(key, translatedKey);
00790 }
00791 
00792 void KFilePlugin::setAttributes(KFileMimeTypeInfo::GroupInfo* gi, uint attr) const
00793 {
00794     gi->m_attr = attr;
00795 }
00796 
00797 void KFilePlugin::addVariableInfo(KFileMimeTypeInfo::GroupInfo* gi,
00798                                   QVariant::Type type, uint attr) const
00799 {
00800     gi->addVariableInfo(type, attr);
00801 }
00802 
00803 KFileMimeTypeInfo::ItemInfo* KFilePlugin::addItemInfo(KFileMimeTypeInfo::GroupInfo* gi,
00804                                                      const QString& key,
00805                                                      const QString& translatedKey,
00806                                                      QVariant::Type type)
00807 {
00808     return gi->addItemInfo(key, translatedKey, type);
00809 }
00810 
00811 void KFilePlugin::setAttributes(KFileMimeTypeInfo::ItemInfo* item, uint attr)
00812 {
00813     item->m_attr = attr;
00814 }
00815 
00816 void KFilePlugin::setHint(KFileMimeTypeInfo::ItemInfo* item, uint hint)
00817 {
00818     item->m_hint = hint;
00819 }
00820 
00821 void KFilePlugin::setUnit(KFileMimeTypeInfo::ItemInfo* item, uint unit)
00822 {
00823     item->m_unit = unit;
00824     // set prefix and suffix
00825     switch (unit)
00826     {
00827         case KFileMimeTypeInfo::Seconds:
00828             item->m_suffix = i18n("s"); break;
00829 
00830         case KFileMimeTypeInfo::MilliSeconds:
00831             item->m_suffix = i18n("ms"); break;
00832 
00833         case KFileMimeTypeInfo::BitsPerSecond:
00834             item->m_suffix = i18n("bps"); break;
00835 
00836         case KFileMimeTypeInfo::Pixels:
00837             item->m_suffix = i18n("pixels"); break;
00838 
00839         case KFileMimeTypeInfo::Inches:
00840             item->m_suffix = i18n("in"); break;
00841 
00842         case KFileMimeTypeInfo::Centimeters:
00843             item->m_suffix = i18n("cm"); break;
00844 
00845         case KFileMimeTypeInfo::Bytes:
00846             item->m_suffix = i18n("B"); break;
00847 
00848         case KFileMimeTypeInfo::KiloBytes:
00849             item->m_suffix = i18n("KB"); break;
00850 
00851         case KFileMimeTypeInfo::FramesPerSecond:
00852             item->m_suffix = i18n("fps"); break;
00853 
00854         case KFileMimeTypeInfo::DotsPerInch:
00855             item->m_suffix = i18n("dpi"); break;
00856 
00857         case KFileMimeTypeInfo::BitsPerPixel:
00858             item->m_suffix = i18n("bpp"); break;
00859 
00860         case KFileMimeTypeInfo::Hertz:
00861             item->m_suffix = i18n("Hz"); break;
00862 
00863         case KFileMimeTypeInfo::Millimeters:
00864             item->m_suffix = i18n("mm");
00865     }
00866 }
00867 
00868 void KFilePlugin::setPrefix(KFileMimeTypeInfo::ItemInfo* item, const QString& prefix)
00869 {
00870     item->m_prefix = prefix;
00871 }
00872 
00873 void KFilePlugin::setSuffix(KFileMimeTypeInfo::ItemInfo* item, const QString& suffix)
00874 {
00875     item->m_suffix = suffix;
00876 }
00877 
00878 KFileMetaInfoGroup KFilePlugin::appendGroup(KFileMetaInfo& info, const QString& key)
00879 {
00880     return info.appendGroup(key);
00881 }
00882 
00883 void KFilePlugin::appendItem(KFileMetaInfoGroup& group, const QString& key, QVariant value)
00884 {
00885     group.appendItem(key, value);
00886 }
00887 
00890 
00891 
00892 KFileMetaInfoProvider * KFileMetaInfoProvider::s_self;
00893 static KStaticDeleter<KFileMetaInfoProvider> sd;
00894 
00895 KFileMetaInfoProvider * KFileMetaInfoProvider::self()
00896 {
00897     if ( !s_self )
00898         s_self = sd.setObject( s_self, new KFileMetaInfoProvider() );
00899 
00900     return s_self;
00901 }
00902 
00903 KFileMetaInfoProvider::KFileMetaInfoProvider()
00904 {
00905     m_plugins.setAutoDelete( true );
00906     m_mimeTypeDict.setAutoDelete( true );
00907 }
00908 
00909 KFileMetaInfoProvider::~KFileMetaInfoProvider()
00910 {
00911     sd.setObject( 0 );
00912 }
00913 
00914 KFilePlugin * KFileMetaInfoProvider::plugin(const QString& mimeType)
00915 {
00916     KFilePlugin *p = m_plugins.find( mimeType );
00917 
00918 //    kdDebug(7033) << "mimetype is " << mimeType << endl;
00919 
00920     if ( !p )
00921     {
00922 //        kdDebug(7033) << "need to look for a plugin to load\n";
00923 
00924         KService::Ptr service =
00925             KServiceTypeProfile::preferredService( mimeType, "KFilePlugin");
00926 
00927         if ( !service || !service->isValid() )
00928         {
00929 //            kdDebug(7033) << "no valid service found\n";
00930             return 0;
00931         }
00932 
00933         p = KParts::ComponentFactory::createInstanceFromService<KFilePlugin>
00934                  ( service, this, mimeType.local8Bit() );
00935 
00936         if (!p)
00937         {
00938             kdWarning(7033) << "error loading the plugin\n";
00939             return 0;
00940         }
00941 
00942 //        kdDebug(7033) << "found a plugin\n";
00943         m_plugins.insert( mimeType, p );
00944 
00945     }
00946 //    else
00947 //        kdDebug(7033) << "plugin already loaded\n";
00948 
00949 //    kdDebug(7033) << "currently loaded plugins:\n";
00950 
00951 //    QDictIterator<KFilePlugin> it( m_plugins );
00952 //    for( ; it.current(); ++it )
00953 //        kdDebug(7033) << it.currentKey() << ": " << it.current()->className() << endl;
00954 
00955     return p;
00956 }
00957 
00958 QStringList KFileMetaInfoProvider::preferredKeys( const QString& mimeType ) const
00959 {
00960     KService::Ptr service =
00961         KServiceTypeProfile::preferredService( mimeType, "KFilePlugin");
00962 
00963     if ( !service || !service->isValid() )
00964     {
00965 //        kdDebug(7033) << "no valid service found\n";
00966         return QStringList();
00967     }
00968     return service->property("PreferredItems").toStringList();
00969 }
00970 
00971 QStringList KFileMetaInfoProvider::preferredGroups( const QString& mimeType ) const
00972 {
00973     KService::Ptr service =
00974         KServiceTypeProfile::preferredService( mimeType, "KFilePlugin");
00975 
00976     if ( !service || !service->isValid() )
00977     {
00978 //        kdDebug(7033) << "no valid service found\n";
00979         return QStringList();
00980     }
00981     return service->property("PreferredGroups").toStringList();
00982 }
00983 
00984 const KFileMimeTypeInfo * KFileMetaInfoProvider::mimeTypeInfo( const QString& mimeType )
00985 {
00986     KFileMimeTypeInfo *info = m_mimeTypeDict.find( mimeType );
00987     if ( !info ) {
00988         // create the plugin (adds the mimeTypeInfo, if possible)
00989         KFilePlugin *p = plugin( mimeType );
00990         if ( p )
00991             info = m_mimeTypeDict.find( mimeType );
00992     }
00993 
00994     return info;
00995 }
00996 
00997 KFileMimeTypeInfo * KFileMetaInfoProvider::addMimeTypeInfo(
00998         const QString& mimeType )
00999 {
01000     KFileMimeTypeInfo *info = m_mimeTypeDict.find( mimeType );
01001     if ( !info )
01002     {
01003         info = new KFileMimeTypeInfo( mimeType );
01004         m_mimeTypeDict.replace( mimeType, info );
01005     }
01006 
01007     info->m_preferredKeys    = preferredKeys( mimeType );
01008     info->m_preferredGroups  = preferredGroups( mimeType );
01009 
01010     return info;
01011 }
01012 
01013 QStringList KFileMetaInfoProvider::supportedMimeTypes() const
01014 {
01015     QStringList allMimeTypes;
01016     QString kfilePlugin = "KFilePlugin";
01017 
01018     KTrader::OfferList offers = KTrader::self()->query( "KFilePlugin" );
01019     KTrader::OfferListIterator it = offers.begin();
01020     for ( ; it != offers.end(); ++it )
01021     {
01022         QStringList mimeTypes = (*it)->serviceTypes();
01023         QStringList::ConstIterator it2 = mimeTypes.begin();
01024         for ( ; it2 != mimeTypes.end(); ++it2 )
01025             if ( allMimeTypes.find( *it2 ) == allMimeTypes.end() &&
01026                  *it2 != kfilePlugin ) // also in serviceTypes()
01027                 allMimeTypes.append( *it2 );
01028     }
01029 
01030     return allMimeTypes;
01031 }
01032 
01037 
01038 
01039 // shared data of a KFileMetaInfoGroup
01040 class KFileMetaInfoGroup::Data : public QShared
01041 {
01042 public:
01043     Data(const QString& _name)
01044         : QShared(),
01045           name(_name),
01046           mimeTypeInfo(0L),
01047           dirty( false ),
01048           added( false )
01049     {}
01050 
01051     // we use this one for the streaming operators
01052     Data() : mimeTypeInfo(0L) {}
01053     ~Data() {
01054         if ( this == null )
01055             delete mimeTypeInfo;
01056     };
01057 
01058     QString                             name;
01059     QMap<QString, KFileMetaInfoItem>    items;
01060     const KFileMimeTypeInfo*            mimeTypeInfo;
01061     QStringList                         removedItems;
01062     bool                                dirty   :1;
01063     bool                                added   :1;
01064 
01065     static Data* null;
01066     static Data* makeNull();
01067 
01068 };
01069 
01070 KFileMetaInfoGroup::KFileMetaInfoGroup( const QString& name,
01071                                         const KFileMimeTypeInfo* info )
01072     : d(new Data( name ) )
01073 {
01074       d->mimeTypeInfo = info;
01075 }
01076 
01077 KFileMetaInfoGroup::KFileMetaInfoGroup( const KFileMetaInfoGroup& original )
01078 {
01079     // operator= does everything that's necessary
01080     d = Data::makeNull();
01081     *this = original;
01082 }
01083 
01084 KFileMetaInfoGroup::KFileMetaInfoGroup()
01085 {
01086     d = Data::makeNull();
01087 }
01088 
01089 KFileMetaInfoGroup::~KFileMetaInfoGroup()
01090 {
01091     deref();
01092 }
01093 
01094 const KFileMetaInfoGroup& KFileMetaInfoGroup::operator= (const KFileMetaInfoGroup& info )
01095 {
01096     if (d != info.d)
01097     {
01098         deref();
01099         // first deref the old one
01100         d = info.d;
01101         // and now ref the new one
01102         ref();
01103     }
01104     return *this;
01105 }
01106 
01107 bool KFileMetaInfoGroup::isValid() const
01108 {
01109     // We don't call makeNull here since it isn't necassery, see deref()
01110     return d != Data::null;
01111 }
01112 
01113 bool KFileMetaInfoGroup::isEmpty() const
01114 {
01115     return d->items.isEmpty();
01116 }
01117 
01118 QStringList KFileMetaInfoGroup::preferredKeys() const
01119 {
01120     assert(isValid());
01121     QStringList list = keys();
01122     QStringList newlist;
01123     QStringList preferredKeys = d->mimeTypeInfo->preferredKeys();
01124     QStringList::Iterator pref;
01125     QStringList::Iterator begin = preferredKeys.begin();
01126     QStringList::Iterator end   = preferredKeys.end();
01127 
01128     // move all keys from the preferred keys that are in our list to a new list
01129     for ( pref = begin; pref!=end; pref++ )
01130     {
01131         QStringList::Iterator item = list.find(*pref);
01132         if ( item != list.end() )
01133         {
01134              newlist.append( *item );
01135              list.remove(item);
01136         }
01137     }
01138 
01139     // now the old list only contains the non-preferred items, so we
01140     // add the remaining ones to newlist
01141     newlist += list;
01142 
01143     return newlist;
01144 }
01145 
01146 QStringList KFileMetaInfoGroup::keys() const
01147 {
01148     if (d == Data::makeNull())
01149         kdWarning(7033) << "attempt to get the keys of "
01150                            "an invalid metainfo group";
01151 
01152     QStringList list;
01153 
01154     // make a QStringList with all available keys
01155     QMapConstIterator<QString, KFileMetaInfoItem> it;
01156     for (it = d->items.begin(); it!=d->items.end(); ++it)
01157     {
01158         list.append(it.data().key());
01159 //        kdDebug(7033) << "Item " << it.data().key() << endl;
01160     }
01161     return list;
01162 }
01163 
01164 QString KFileMetaInfoGroup::translatedName() const
01165 {
01166     assert(isValid());
01167     return d->mimeTypeInfo->groupInfo(d->name)->translatedName();
01168 }
01169 
01170 QStringList KFileMetaInfoGroup::supportedKeys() const
01171 {
01172     assert(isValid());
01173     return d->mimeTypeInfo->groupInfo(d->name)->supportedKeys();
01174 }
01175 
01176 bool KFileMetaInfoGroup::supportsVariableKeys() const
01177 {
01178     assert(isValid());
01179     return d->mimeTypeInfo->groupInfo(d->name)->supportsVariableKeys();
01180 }
01181 
01182 bool KFileMetaInfoGroup::contains( const QString& key ) const
01183 {
01184     return d->items.contains(key);
01185 }
01186 
01187 KFileMetaInfoItem KFileMetaInfoGroup::item( const QString& key) const
01188 {
01189     QMapIterator<QString,KFileMetaInfoItem> it = d->items.find( key );
01190     if ( it != d->items.end() )
01191         return it.data();
01192 
01193     return KFileMetaInfoItem();
01194 }
01195 
01196 KFileMetaInfoItem KFileMetaInfoGroup::item(uint hint) const
01197 {
01198     QMapIterator<QString, KFileMetaInfoItem> it;
01199 
01200     for (it = d->items.begin(); it!=d->items.end(); ++it)
01201         if (it.data().hint() == hint)
01202             return it.data();
01203 
01204     return KFileMetaInfoItem();
01205 }
01206 
01207 QString KFileMetaInfoGroup::name() const
01208 {
01209     return d->name;
01210 }
01211 
01212 uint KFileMetaInfoGroup::attributes() const
01213 {
01214     assert(isValid());
01215     return d->mimeTypeInfo->groupInfo(d->name)->attributes();
01216 }
01217 
01218 void KFileMetaInfoGroup::setAdded()
01219 {
01220     d->added = true;
01221 }
01222 
01223 bool KFileMetaInfoGroup::isModified() const
01224 {
01225     return d->dirty;
01226 }
01227 
01228 void KFileMetaInfoGroup::ref()
01229 {
01230     if (d != Data::null) d->ref();
01231 
01232 }
01233 
01234 void KFileMetaInfoGroup::deref()
01235 {
01236     // We don't call makeNull here since it isn't necassery:
01237     // If d is equal to null it means that null is initialized already.
01238     // null is 0L when it hasn't been initialized and d is never 0L.
01239     if ((d != Data::null) && d->deref())
01240     {
01241 //        kdDebug(7033) << "metainfo group " << d->name
01242 //                      << " is finally deleted\n";
01243         delete d;
01244         d=0;
01245     }
01246 
01247 }
01248 
01249 KFileMetaInfoItem KFileMetaInfoGroup::addItem( const QString& key )
01250 {
01251     assert(isValid());
01252     QMapIterator<QString,KFileMetaInfoItem> it = d->items.find( key );
01253     if ( it != d->items.end() )
01254         return it.data();
01255 
01256     const KFileMimeTypeInfo::GroupInfo* ginfo = d->mimeTypeInfo->groupInfo(d->name);
01257 
01258     if ( !ginfo ) {
01259         Q_ASSERT( ginfo );
01260         return KFileMetaInfoItem();
01261     }
01262 
01263     const KFileMimeTypeInfo::ItemInfo* info = ginfo->itemInfo(key);
01264 
01265     if ( !info ) {
01266         Q_ASSERT( info );
01267         return KFileMetaInfoItem();
01268     }
01269 
01270     KFileMetaInfoItem item;
01271 
01272     if (info->isVariableItem())
01273         item = KFileMetaInfoItem(ginfo->variableItemInfo(), key, QVariant());
01274     else
01275         item = KFileMetaInfoItem(info, key, QVariant());
01276 
01277     d->items.insert(key, item);
01278     item.setAdded();           // mark as added
01279     d->dirty = true;           // mark ourself as dirty, too
01280     return item;
01281 }
01282 
01283 bool KFileMetaInfoGroup::removeItem( const QString& key )
01284 {
01285     if (!isValid())
01286     {
01287           kdDebug(7033) << "trying to remove an item from an invalid group\n";
01288           return false;
01289     }
01290 
01291     QMapIterator<QString, KFileMetaInfoItem> it = d->items.find(key);
01292     if ( it==d->items.end() )
01293     {
01294           kdDebug(7033) << "trying to remove the non existant item " << key << "\n";
01295           return false;
01296     }
01297 
01298     if (!((*it).attributes() & KFileMimeTypeInfo::Removable))
01299     {
01300         kdDebug(7033) << "trying to remove a non removable item\n";
01301         return false;
01302     }
01303 
01304     (*it).setRemoved();
01305     d->items.remove(it);
01306     d->removedItems.append(key);
01307     d->dirty = true;
01308     return true;
01309 }
01310 
01311 QStringList KFileMetaInfoGroup::removedItems()
01312 {
01313     return d->removedItems;
01314 }
01315 
01316 KFileMetaInfoItem KFileMetaInfoGroup::appendItem(const QString& key,
01317                                                  const QVariant& value)
01318 {
01319     //KDE4 enforce (value.type() == d->mimeTypeInfo->type())
01320     assert(isValid());
01321     const KFileMimeTypeInfo::GroupInfo* ginfo = d->mimeTypeInfo->groupInfo(d->name);
01322     if ( !ginfo ) {
01323         kdWarning() << "Trying to append a Metadata item for a non-existant group:" << d->name << endl;
01324         return KFileMetaInfoItem();
01325     }
01326     const KFileMimeTypeInfo::ItemInfo* info = ginfo->itemInfo(key);
01327     if ( !info ) {
01328         kdWarning() << "Trying to append a Metadata item for an unknown key (no ItemInfo): " << key << endl;
01329         return KFileMetaInfoItem();
01330     }
01331 
01332     KFileMetaInfoItem item;
01333 
01334     if (info->key().isNull())
01335         item = KFileMetaInfoItem(ginfo->variableItemInfo(), key, value);
01336     else
01337         item = KFileMetaInfoItem(info, key, value);
01338 
01339     kdDebug(7033) << "KFileMetaInfogroup inserting a " << key << endl;
01340 
01341     d->items.insert(key, item);
01342     return item;
01343 }
01344 
01345 KFileMetaInfoGroup::Data* KFileMetaInfoGroup::Data::null = 0L;
01346 static KStaticDeleter<KFileMetaInfoGroup::Data> sd_KFileMetaInfoGroupData;
01347 
01348 KFileMetaInfoGroup::Data* KFileMetaInfoGroup::Data::makeNull()
01349 {
01350     if (!null)
01351     {
01352         // We deliberately do not reset "null" after it has been destroyed!
01353         // Otherwise we will run into problems later in ~KFileMetaInfoItem
01354         // where the d-pointer is compared against null.
01355         null = new Data(QString::null);
01356         null->mimeTypeInfo = new KFileMimeTypeInfo();
01357         sd_KFileMetaInfoGroupData.setObject( null );
01358     }
01359     return null;
01360 }
01361 
01362 
01365 
01366 KFileMimeTypeInfo::KFileMimeTypeInfo( const QString& mimeType )
01367     : m_mimeType( mimeType )
01368 {
01369     m_groups.setAutoDelete( true );
01370 }
01371 
01372 KFileMimeTypeInfo::~KFileMimeTypeInfo()
01373 {
01374 }
01375 
01376 const KFileMimeTypeInfo::GroupInfo * KFileMimeTypeInfo::groupInfo( const QString& group ) const
01377 {
01378     return m_groups.find( group );
01379 }
01380 
01381 KFileMimeTypeInfo::GroupInfo * KFileMimeTypeInfo::addGroupInfo(
01382                            const QString& name, const QString& translatedName )
01383 {
01384     GroupInfo* group = new GroupInfo( name, translatedName );
01385     m_groups.insert(name, group);
01386     return group;
01387 }
01388 
01389 QStringList KFileMimeTypeInfo::supportedGroups() const
01390 {
01391     QStringList list;
01392     QDictIterator<GroupInfo> it( m_groups );
01393     for ( ; it.current(); ++it )
01394         list.append( it.current()->name() );
01395 
01396     return list;
01397 }
01398 
01399 QStringList KFileMimeTypeInfo::translatedGroups() const
01400 {
01401     QStringList list;
01402     QDictIterator<GroupInfo> it( m_groups );
01403     for ( ; it.current(); ++it )
01404         list.append( it.current()->translatedName() );
01405 
01406     return list;
01407 }
01408 
01409 QStringList KFileMimeTypeInfo::supportedKeys() const
01410 {
01411     // not really efficient, but not those are not large lists, probably.
01412     // maybe cache the result?
01413     QStringList keys;
01414     QStringList::ConstIterator lit;
01415     QDictIterator<GroupInfo> it( m_groups );
01416     for ( ; it.current(); ++it ) { // need to nuke dupes
01417         QStringList list = it.current()->supportedKeys();
01418         for ( lit = list.begin(); lit != list.end(); ++lit ) {
01419             if ( keys.find( *lit ) == keys.end() )
01420                 keys.append( *lit );
01421         }
01422     }
01423 
01424     return keys;
01425 }
01426 
01427 QValidator * KFileMimeTypeInfo::createValidator(const QString& group,
01428                                                 const QString& key,
01429                                                 QObject *parent,
01430                                                 const char *name) const
01431 {
01432     KFilePlugin* plugin = KFileMetaInfoProvider::self()->plugin(m_mimeType);
01433     if (plugin) return plugin->createValidator(mimeType(), group, key,
01434                                                parent, name);
01435     return 0;
01436 }
01437 
01438 
01441 
01442 KFileMimeTypeInfo::GroupInfo::GroupInfo( const QString& name,
01443                                          const QString& translatedName )
01444     : m_name( name ),
01445       m_translatedName( translatedName ),
01446       m_attr( 0 ),
01447       m_variableItemInfo( 0 )
01448 
01449 {
01450     m_itemDict.setAutoDelete( true );
01451 }
01452 
01453 const KFileMimeTypeInfo::ItemInfo * KFileMimeTypeInfo::GroupInfo::itemInfo( const QString& key ) const
01454 {
01455     ItemInfo* item = m_itemDict.find( key );
01456 
01457     // if we the item isn't found and variable keys are supported, we need to
01458     // return the default variable key iteminfo.
01459     if (!item && m_variableItemInfo)
01460     {
01461         return m_variableItemInfo;
01462     }
01463     return item;
01464 }
01465 
01466 KFileMimeTypeInfo::ItemInfo* KFileMimeTypeInfo::GroupInfo::addItemInfo(
01467                   const QString& key, const QString& translatedKey,
01468                   QVariant::Type type)
01469 {
01470 //    kdDebug(7034) << key << "(" << translatedKey << ") -> " << QVariant::typeToName(type) << endl;
01471 
01472     ItemInfo* item = new ItemInfo(key, translatedKey, type);
01473     m_supportedKeys.append(key);
01474     m_itemDict.insert(key, item);
01475     return item;
01476 }
01477 
01478 
01479 void KFileMimeTypeInfo::GroupInfo::addVariableInfo( QVariant::Type type,
01480                                                    uint attr )
01481 {
01482     // just make sure that it's not already there
01483     delete m_variableItemInfo;
01484     m_variableItemInfo = new ItemInfo(QString::null, QString::null, type);
01485     m_variableItemInfo->m_attr = attr;
01486 }
01487 
01490 
01491 QString KFileMimeTypeInfo::ItemInfo::string(const QVariant& value, bool mangle) const
01492 {
01493     QString s;
01494 
01495     switch (value.type())
01496     {
01497         case QVariant::Invalid :
01498             return "---";
01499 
01500         case QVariant::Bool :
01501             s = value.toBool() ? i18n("Yes") : i18n("No");
01502             break;
01503 
01504         case QVariant::Int :
01505             if (unit() == KFileMimeTypeInfo::Seconds)
01506             {
01507               int seconds = value.toInt() % 60;
01508               int minutes = value.toInt() / 60 % 60;
01509               int hours   = value.toInt() / 3600;
01510               s = hours ? QString().sprintf("%d:%02d:%02d",hours, minutes, seconds)
01511                         : QString().sprintf("%02d:%02d", minutes, seconds);
01512               return s; // no suffix wanted
01513             }
01514             else if (unit() == KFileMimeTypeInfo::Bytes)
01515             {
01516                 // convertSize already adds the correct suffix
01517                 return KIO::convertSize(value.toInt());
01518             }
01519             else if (unit() == KFileMimeTypeInfo::KiloBytes)
01520             {
01521                 // convertSizeFromKB already adds the correct suffix
01522                 return KIO::convertSizeFromKB(value.toInt());
01523             }
01524             else
01525                 s = KGlobal::locale()->formatNumber( value.toInt() , 0);
01526             break;
01527 
01528 #if QT_VERSION >= 0x030200
01529         case QVariant::LongLong :
01530             s = KGlobal::locale()->formatNumber( value.toLongLong(), 0 );
01531             break;
01532 
01533     case QVariant::ULongLong :
01534             if ( unit() == KFileMimeTypeInfo::Bytes )
01535                 return KIO::convertSize( value.toULongLong() );
01536             else if ( unit() == KFileMimeTypeInfo::KiloBytes )
01537                 return KIO::convertSizeFromKB( value.toULongLong() );
01538             else
01539                 s = KGlobal::locale()->formatNumber( value.toULongLong(), 0 );
01540             break;
01541 #endif
01542         case QVariant::UInt :
01543             s = KGlobal::locale()->formatNumber( value.toUInt() , 0);
01544             break;
01545 
01546         case QVariant::Double :
01547             s = KGlobal::locale()->formatNumber( value.toDouble(), 3);
01548             break;
01549 
01550         case QVariant::Date :
01551             s = KGlobal::locale()->formatDate( value.toDate(), true );
01552             break;
01553 
01554         case QVariant::Time :
01555             s = KGlobal::locale()->formatTime( value.toTime(), true );
01556             break;
01557 
01558         case QVariant::DateTime :
01559             s = KGlobal::locale()->formatDateTime( value.toDateTime(),
01560                                                    true, true );
01561             break;
01562 
01563         case QVariant::Size :
01564             s = QString("%1 x %2").arg(value.toSize().width())
01565                                 .arg(value.toSize().height());
01566             break;
01567 
01568         case QVariant::Point :
01569             s = QString("%1/%2").arg(value.toSize().width())
01570                                 .arg(value.toSize().height());
01571             break;
01572 
01573         default:
01574             s = value.toString();
01575     }
01576 
01577     if (mangle && !s.isNull())
01578     {
01579         s.prepend(prefix());
01580         s.append(" " + suffix());
01581     }
01582     return s;
01583 }
01584 
01585 
01588 
01589 
01590 
01591 // stream operators
01592 
01593 /* serialization of a KFileMetaInfoItem:
01594    first a bool that says if the items is valid, and if yes,
01595    all the elements of the Data
01596 */
01597 KIO_EXPORT QDataStream& operator <<(QDataStream& s, const KFileMetaInfoItem& item )
01598 {
01599 
01600      KFileMetaInfoItem::Data* d = item.d;
01601 
01602      // if the object is invalid, put only a char in the stream
01603      bool isValid = item.isValid();
01604      s << isValid;
01605      // ### what do about mimetypeInfo ?
01606      if (isValid)
01607          s << d->key
01608            << d->value
01609            << d->dirty
01610            << d->added
01611            << d->removed;
01612 
01613      return s;
01614 }
01615 
01616 
01617 KIO_EXPORT QDataStream& operator >>(QDataStream& s, KFileMetaInfoItem& item )
01618 {
01619      bool isValid;
01620      s >> isValid;
01621 
01622      if (!isValid)
01623      {
01624          item = KFileMetaInfoItem();
01625          return s;
01626      }
01627 
01628      // we need a new object for our data
01629      item.deref();
01630      item.d = new KFileMetaInfoItem::Data();
01631 
01632      // ### what do about mimetypeInfo ?
01633      bool dirty, added, removed;
01634      s >> item.d->key
01635        >> item.d->value
01636        >> dirty
01637        >> added
01638        >> removed;
01639      item.d->dirty = dirty;
01640      item.d->added = added;
01641      item.d->removed = removed;
01642 
01643     return s;
01644 }
01645 
01646 
01647 // serialization of a KFileMetaInfoGroup
01648 // we serialize the name of the mimetype here instead of the mimetype info
01649 // on the other side, we can simply use this to ask the provider for the info
01650 KIO_EXPORT QDataStream& operator <<(QDataStream& s, const KFileMetaInfoGroup& group )
01651 {
01652     KFileMetaInfoGroup::Data* d = group.d;
01653 
01654     // if the object is invalid, put only a byte in the stream
01655     bool isValid = group.isValid();
01656 
01657     s << isValid;
01658     if (isValid)
01659     {
01660         s << d->name
01661           << d->items
01662           << d->mimeTypeInfo->mimeType();
01663     }
01664     return s;
01665 }
01666 
01667 KIO_EXPORT QDataStream& operator >>(QDataStream& s, KFileMetaInfoGroup& group )
01668 {
01669     QString mimeType;
01670     bool isValid;
01671     s >> isValid;
01672 
01673     // if it's invalid, there is not much to do
01674     if (!isValid)
01675     {
01676         group = KFileMetaInfoGroup();
01677         return s;
01678     }
01679 
01680     // we need a new object for our data
01681     group.deref();
01682     group.d = new KFileMetaInfoGroup::Data();
01683 
01684     s >> group.d->name
01685       >> group.d->items
01686       >> mimeType;
01687 
01688     group.d->mimeTypeInfo = KFileMetaInfoProvider::self()->mimeTypeInfo(mimeType);
01689 
01690     // we need to set the item info for the items here
01691     QMapIterator<QString, KFileMetaInfoItem> it = group.d->items.begin();
01692     for ( ; it != group.d->items.end(); ++it)
01693     {
01694         (*it).d->mimeTypeInfo = group.d->mimeTypeInfo->groupInfo(group.d->name)
01695                                   ->itemInfo((*it).key());
01696     }
01697 
01698     return s;
01699 }
01700 
01701 // serialization of a KFileMetaInfo object
01702 // we serialize the name of the mimetype here instead of the mimetype info
01703 // on the other side, we can simply use this to ask the provider for the info
01704 KIO_EXPORT QDataStream& operator <<(QDataStream& s, const KFileMetaInfo& info )
01705 {
01706     KFileMetaInfo::Data* d = info.d;
01707 
01708     // if the object is invalid, put only a byte that tells this
01709     bool isValid = info.isValid();
01710 
01711     s << isValid;
01712     if (isValid)
01713     {
01714         s << d->url
01715           << d->what
01716           << d->groups
01717           << d->mimeTypeInfo->mimeType();
01718     }
01719     return s;
01720 }
01721 
01722 KIO_EXPORT QDataStream& operator >>(QDataStream& s, KFileMetaInfo& info )
01723 {
01724     QString mimeType;
01725     bool isValid;
01726     s >> isValid;
01727 
01728     // if it's invalid, there is not much to do
01729     if (!isValid)
01730     {
01731         info = KFileMetaInfo();
01732         return s;
01733     }
01734 
01735     // we need a new object for our data
01736     info.deref();
01737     info.d = new KFileMetaInfo::Data();
01738 
01739     s >> info.d->url
01740       >> info.d->what
01741       >> info.d->groups
01742       >> mimeType;
01743     info.d->mimeTypeInfo = KFileMetaInfoProvider::self()->mimeTypeInfo(mimeType);
01744 
01745     return s;
01746 }
01747 
01748 
01749 
01750 
01751 #include "kfilemetainfo.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 30 10:15:29 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003