kio Library: kfilemetainfo.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

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

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:58 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003