kio Library API Documentation

kfilemetainfo.cpp

00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (C) 2001-2002 Rolf Magnus <ramagnus@kde.org> 00004 * Copyright (C) 2001-2002 Carsten Pfeiffer <pfeiffer@kde.org> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation version 2.0. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 * Boston, MA 02111-1307, USA. 00019 * 00020 * $Id: kfilemetainfo.cpp,v 1.88 2005/01/28 20:01:16 woebbe Exp $ 00021 */ 00022 00023 #include <assert.h> 00024 00025 #include <qshared.h> 00026 #include <qdict.h> 00027 00028 #include <ktrader.h> 00029 #include <kstaticdeleter.h> 00030 #include <kparts/componentfactory.h> 00031 #include <kuserprofile.h> 00032 #include <kdebug.h> 00033 #include <kmimetype.h> 00034 #include <kdatastream.h> // needed for serialization of bool 00035 #include <klocale.h> 00036 #include <kio/global.h> 00037 00038 #include "kfilemetainfo.h" 00039 00040 // shared data of a KFileMetaInfoItem 00041 class KFileMetaInfoItem::Data : public QShared 00042 { 00043 public: 00044 Data( const KFileMimeTypeInfo::ItemInfo* mti, const QString& _key, 00045 const QVariant& _value ) 00046 : QShared(), 00047 mimeTypeInfo( mti ), 00048 key( _key ), 00049 value( _value ), 00050 dirty( false ), 00051 added( false ), 00052 removed( false ) 00053 {} 00054 00055 // we use this one for the streaming operators 00056 Data() : mimeTypeInfo( 0L ) 00057 {} 00058 00059 ~Data() 00060 { 00061 if ( this == null ) // only the null item owns its mimeTypeInfo 00062 delete mimeTypeInfo; 00063 } 00064 00065 const KFileMimeTypeInfo::ItemInfo* mimeTypeInfo; 00066 // mimeTypeInfo has the key, too, but only for non-variable ones 00067 QString key; 00068 QVariant value; 00069 bool dirty :1; 00070 bool added :1; 00071 bool removed :1; 00072 00073 static Data* null; 00074 static Data* makeNull(); 00075 }; 00076 00077 //this is our null data 00078 KFileMetaInfoItem::Data* KFileMetaInfoItem::Data::null = 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"
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:20:24 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003