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