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