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