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