KIO
kfileitem.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 1999-2006 David Faure <faure@kde.org> 00003 2001 Carsten Pfeiffer <pfeiffer@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 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 00021 #include "kfileitem.h" 00022 00023 #include <config.h> 00024 #include <config-kio.h> 00025 00026 #include <sys/time.h> 00027 #include <pwd.h> 00028 #include <grp.h> 00029 #include <sys/types.h> 00030 #include <sys/stat.h> 00031 00032 #include <assert.h> 00033 #include <unistd.h> 00034 00035 #include <QtCore/QDate> 00036 #include <QtCore/QDir> 00037 #include <QtCore/QFile> 00038 #include <QtCore/QMap> 00039 #include <QtGui/QApplication> 00040 #include <QTextDocument> 00041 00042 #include <kdebug.h> 00043 #include <kfilemetainfo.h> 00044 #include <kglobal.h> 00045 #include <kglobalsettings.h> 00046 #include <kiconloader.h> 00047 #include <klocale.h> 00048 #include <kmimetype.h> 00049 #include <krun.h> 00050 #include <kde_file.h> 00051 #include <kdesktopfile.h> 00052 #include <kmountpoint.h> 00053 #include <kconfiggroup.h> 00054 #ifndef Q_OS_WIN 00055 #include <knfsshare.h> 00056 #include <ksambashare.h> 00057 #endif 00058 00059 class KFileItemPrivate : public QSharedData 00060 { 00061 public: 00062 KFileItemPrivate(const KIO::UDSEntry& entry, 00063 mode_t mode, mode_t permissions, 00064 const KUrl& itemOrDirUrl, 00065 bool urlIsDirectory, 00066 bool delayedMimeTypes) 00067 : m_entry( entry ), 00068 m_url(itemOrDirUrl), 00069 m_strName(), 00070 m_strText(), 00071 m_iconName(), 00072 m_strLowerCaseName(), 00073 m_pMimeType( 0 ), 00074 m_fileMode( mode ), 00075 m_permissions( permissions ), 00076 m_bMarked( false ), 00077 m_bLink( false ), 00078 m_bIsLocalUrl(itemOrDirUrl.isLocalFile()), 00079 m_bMimeTypeKnown( false ), 00080 m_delayedMimeTypes( delayedMimeTypes ), 00081 m_useIconNameCache(false), 00082 m_hidden( Auto ) 00083 { 00084 if (entry.count() != 0) { 00085 readUDSEntry( urlIsDirectory ); 00086 } else { 00087 Q_ASSERT(!urlIsDirectory); 00088 m_strName = itemOrDirUrl.fileName(); 00089 m_strText = KIO::decodeFileName( m_strName ); 00090 } 00091 init(); 00092 } 00093 00094 ~KFileItemPrivate() 00095 { 00096 } 00097 00104 void init(); 00105 00106 KIO::filesize_t size() const; 00107 KDateTime time( KFileItem::FileTimes which ) const; 00108 void setTime(KFileItem::FileTimes which, long long time_t_val) const; 00109 bool cmp( const KFileItemPrivate & item ) const; 00110 QString user() const; 00111 QString group() const; 00112 00117 void readUDSEntry( bool _urlIsDirectory ); 00118 00122 QString parsePermissions( mode_t perm ) const; 00123 00127 mutable KIO::UDSEntry m_entry; 00131 KUrl m_url; 00132 00136 QString m_strName; 00137 00142 QString m_strText; 00143 00147 mutable QString m_iconName; 00148 00152 mutable QString m_strLowerCaseName; 00153 00157 mutable KMimeType::Ptr m_pMimeType; 00158 00162 mode_t m_fileMode; 00166 mode_t m_permissions; 00167 00171 bool m_bMarked:1; 00175 bool m_bLink:1; 00179 bool m_bIsLocalUrl:1; 00180 00181 mutable bool m_bMimeTypeKnown:1; 00182 bool m_delayedMimeTypes:1; 00183 00185 mutable bool m_useIconNameCache:1; 00186 00187 // Auto: check leading dot. 00188 enum { Auto, Hidden, Shown } m_hidden:3; 00189 00190 // For special case like link to dirs over FTP 00191 QString m_guessedMimeType; 00192 mutable QString m_access; 00193 #ifndef KDE_NO_DEPRECATED 00194 QMap<const void*, void*> m_extra; // DEPRECATED 00195 #endif 00196 mutable KFileMetaInfo m_metaInfo; 00197 00198 enum { NumFlags = KFileItem::CreationTime + 1 }; 00199 mutable KDateTime m_time[3]; 00200 }; 00201 00202 void KFileItemPrivate::init() 00203 { 00204 m_access.clear(); 00205 // metaInfo = KFileMetaInfo(); 00206 00207 // determine mode and/or permissions if unknown 00208 // TODO: delay this until requested 00209 if ( m_fileMode == KFileItem::Unknown || m_permissions == KFileItem::Unknown ) 00210 { 00211 mode_t mode = 0; 00212 if ( m_url.isLocalFile() ) 00213 { 00214 /* directories may not have a slash at the end if 00215 * we want to stat() them; it requires that we 00216 * change into it .. which may not be allowed 00217 * stat("/is/unaccessible") -> rwx------ 00218 * stat("/is/unaccessible/") -> EPERM H.Z. 00219 * This is the reason for the -1 00220 */ 00221 KDE_struct_stat buf; 00222 const QString path = m_url.toLocalFile( KUrl::RemoveTrailingSlash ); 00223 if ( KDE::lstat( path, &buf ) == 0 ) 00224 { 00225 mode = buf.st_mode; 00226 if ( S_ISLNK( mode ) ) 00227 { 00228 m_bLink = true; 00229 if ( KDE::stat( path, &buf ) == 0 ) 00230 mode = buf.st_mode; 00231 else // link pointing to nowhere (see kio/file/file.cc) 00232 mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO; 00233 } 00234 // While we're at it, store the times 00235 setTime(KFileItem::ModificationTime, buf.st_mtime); 00236 setTime(KFileItem::AccessTime, buf.st_atime); 00237 if ( m_fileMode == KFileItem::Unknown ) 00238 m_fileMode = mode & S_IFMT; // extract file type 00239 if ( m_permissions == KFileItem::Unknown ) 00240 m_permissions = mode & 07777; // extract permissions 00241 } else { 00242 kDebug() << path << "does not exist anymore"; 00243 } 00244 } 00245 } 00246 } 00247 00248 void KFileItemPrivate::readUDSEntry( bool _urlIsDirectory ) 00249 { 00250 // extract fields from the KIO::UDS Entry 00251 00252 m_fileMode = m_entry.numberValue( KIO::UDSEntry::UDS_FILE_TYPE ); 00253 m_permissions = m_entry.numberValue( KIO::UDSEntry::UDS_ACCESS ); 00254 m_strName = m_entry.stringValue( KIO::UDSEntry::UDS_NAME ); 00255 00256 const QString displayName = m_entry.stringValue( KIO::UDSEntry::UDS_DISPLAY_NAME ); 00257 if (!displayName.isEmpty()) 00258 m_strText = displayName; 00259 else 00260 m_strText = KIO::decodeFileName( m_strName ); 00261 00262 const QString urlStr = m_entry.stringValue( KIO::UDSEntry::UDS_URL ); 00263 const bool UDS_URL_seen = !urlStr.isEmpty(); 00264 if ( UDS_URL_seen ) { 00265 m_url = KUrl( urlStr ); 00266 if ( m_url.isLocalFile() ) 00267 m_bIsLocalUrl = true; 00268 } 00269 const QString mimeTypeStr = m_entry.stringValue( KIO::UDSEntry::UDS_MIME_TYPE ); 00270 m_bMimeTypeKnown = !mimeTypeStr.isEmpty(); 00271 if ( m_bMimeTypeKnown ) 00272 m_pMimeType = KMimeType::mimeType( mimeTypeStr ); 00273 00274 m_guessedMimeType = m_entry.stringValue( KIO::UDSEntry::UDS_GUESSED_MIME_TYPE ); 00275 m_bLink = !m_entry.stringValue( KIO::UDSEntry::UDS_LINK_DEST ).isEmpty(); // we don't store the link dest 00276 00277 const int hiddenVal = m_entry.numberValue( KIO::UDSEntry::UDS_HIDDEN, -1 ); 00278 m_hidden = hiddenVal == 1 ? Hidden : ( hiddenVal == 0 ? Shown : Auto ); 00279 00280 // avoid creating these QStrings again and again 00281 static const QString& dot = KGlobal::staticQString("."); 00282 if ( _urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != dot ) 00283 m_url.addPath( m_strName ); 00284 00285 m_iconName.clear(); 00286 } 00287 00288 inline //because it is used only in one place 00289 KIO::filesize_t KFileItemPrivate::size() const 00290 { 00291 // Extract it from the KIO::UDSEntry 00292 long long fieldVal = m_entry.numberValue( KIO::UDSEntry::UDS_SIZE, -1 ); 00293 if ( fieldVal != -1 ) { 00294 return fieldVal; 00295 } 00296 00297 // If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL] 00298 if ( m_bIsLocalUrl ) { 00299 KDE_struct_stat buf; 00300 if ( KDE::stat( m_url.toLocalFile(KUrl::RemoveTrailingSlash), &buf ) == 0 ) 00301 return buf.st_size; 00302 } 00303 return 0; 00304 } 00305 00306 void KFileItemPrivate::setTime(KFileItem::FileTimes mappedWhich, long long time_t_val) const 00307 { 00308 m_time[mappedWhich].setTime_t(time_t_val); 00309 m_time[mappedWhich] = m_time[mappedWhich].toLocalZone(); // #160979 00310 } 00311 00312 KDateTime KFileItemPrivate::time( KFileItem::FileTimes mappedWhich ) const 00313 { 00314 if ( !m_time[mappedWhich].isNull() ) 00315 return m_time[mappedWhich]; 00316 00317 // Extract it from the KIO::UDSEntry 00318 long long fieldVal = -1; 00319 switch ( mappedWhich ) { 00320 case KFileItem::ModificationTime: 00321 fieldVal = m_entry.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME, -1 ); 00322 break; 00323 case KFileItem::AccessTime: 00324 fieldVal = m_entry.numberValue( KIO::UDSEntry::UDS_ACCESS_TIME, -1 ); 00325 break; 00326 case KFileItem::CreationTime: 00327 fieldVal = m_entry.numberValue( KIO::UDSEntry::UDS_CREATION_TIME, -1 ); 00328 break; 00329 } 00330 if ( fieldVal != -1 ) { 00331 setTime(mappedWhich, fieldVal); 00332 return m_time[mappedWhich]; 00333 } 00334 00335 // If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL] 00336 if ( m_bIsLocalUrl ) 00337 { 00338 KDE_struct_stat buf; 00339 if ( KDE::stat( m_url.toLocalFile(KUrl::RemoveTrailingSlash), &buf ) == 0 ) 00340 { 00341 setTime(KFileItem::ModificationTime, buf.st_mtime); 00342 setTime(KFileItem::AccessTime, buf.st_atime); 00343 m_time[KFileItem::CreationTime] = KDateTime(); 00344 return m_time[mappedWhich]; 00345 } 00346 } 00347 return KDateTime(); 00348 } 00349 00350 inline //because it is used only in one place 00351 bool KFileItemPrivate::cmp( const KFileItemPrivate & item ) const 00352 { 00353 #if 0 00354 kDebug() << "Comparing" << m_url << "and" << item.m_url; 00355 kDebug() << " name" << (m_strName == item.m_strName); 00356 kDebug() << " local" << (m_bIsLocalUrl == item.m_bIsLocalUrl); 00357 kDebug() << " mode" << (m_fileMode == item.m_fileMode); 00358 kDebug() << " perm" << (m_permissions == item.m_permissions); 00359 kDebug() << " UDS_USER" << (user() == item.user()); 00360 kDebug() << " UDS_GROUP" << (group() == item.group()); 00361 kDebug() << " UDS_EXTENDED_ACL" << (m_entry.stringValue( KIO::UDSEntry::UDS_EXTENDED_ACL ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_EXTENDED_ACL )); 00362 kDebug() << " UDS_ACL_STRING" << (m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING )); 00363 kDebug() << " UDS_DEFAULT_ACL_STRING" << (m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING )); 00364 kDebug() << " m_bLink" << (m_bLink == item.m_bLink); 00365 kDebug() << " m_hidden" << (m_hidden == item.m_hidden); 00366 kDebug() << " size" << (size() == item.size()); 00367 kDebug() << " ModificationTime" << (time(KFileItem::ModificationTime) == item.time(KFileItem::ModificationTime)); 00368 kDebug() << " UDS_ICON_NAME" << (m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME )); 00369 #endif 00370 return ( m_strName == item.m_strName 00371 && m_bIsLocalUrl == item.m_bIsLocalUrl 00372 && m_fileMode == item.m_fileMode 00373 && m_permissions == item.m_permissions 00374 && user() == item.user() 00375 && group() == item.group() 00376 && m_entry.stringValue( KIO::UDSEntry::UDS_EXTENDED_ACL ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_EXTENDED_ACL ) 00377 && m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING ) 00378 && m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING ) 00379 && m_bLink == item.m_bLink 00380 && m_hidden == item.m_hidden 00381 && size() == item.size() 00382 && time(KFileItem::ModificationTime) == item.time(KFileItem::ModificationTime) // TODO only if already known! 00383 && m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ) 00384 ); 00385 00386 // Don't compare the mimetypes here. They might not be known, and we don't want to 00387 // do the slow operation of determining them here. 00388 } 00389 00390 inline //because it is used only in one place 00391 QString KFileItemPrivate::parsePermissions(mode_t perm) const 00392 { 00393 static char buffer[ 12 ]; 00394 00395 char uxbit,gxbit,oxbit; 00396 00397 if ( (perm & (S_IXUSR|S_ISUID)) == (S_IXUSR|S_ISUID) ) 00398 uxbit = 's'; 00399 else if ( (perm & (S_IXUSR|S_ISUID)) == S_ISUID ) 00400 uxbit = 'S'; 00401 else if ( (perm & (S_IXUSR|S_ISUID)) == S_IXUSR ) 00402 uxbit = 'x'; 00403 else 00404 uxbit = '-'; 00405 00406 if ( (perm & (S_IXGRP|S_ISGID)) == (S_IXGRP|S_ISGID) ) 00407 gxbit = 's'; 00408 else if ( (perm & (S_IXGRP|S_ISGID)) == S_ISGID ) 00409 gxbit = 'S'; 00410 else if ( (perm & (S_IXGRP|S_ISGID)) == S_IXGRP ) 00411 gxbit = 'x'; 00412 else 00413 gxbit = '-'; 00414 00415 if ( (perm & (S_IXOTH|S_ISVTX)) == (S_IXOTH|S_ISVTX) ) 00416 oxbit = 't'; 00417 else if ( (perm & (S_IXOTH|S_ISVTX)) == S_ISVTX ) 00418 oxbit = 'T'; 00419 else if ( (perm & (S_IXOTH|S_ISVTX)) == S_IXOTH ) 00420 oxbit = 'x'; 00421 else 00422 oxbit = '-'; 00423 00424 // Include the type in the first char like kde3 did; people are more used to seeing it, 00425 // even though it's not really part of the permissions per se. 00426 if (m_bLink) 00427 buffer[0] = 'l'; 00428 else if (m_fileMode != KFileItem::Unknown) { 00429 if (S_ISDIR(m_fileMode)) 00430 buffer[0] = 'd'; 00431 else if (S_ISSOCK(m_fileMode)) 00432 buffer[0] = 's'; 00433 else if (S_ISCHR(m_fileMode)) 00434 buffer[0] = 'c'; 00435 else if (S_ISBLK(m_fileMode)) 00436 buffer[0] = 'b'; 00437 else if (S_ISFIFO(m_fileMode)) 00438 buffer[0] = 'p'; 00439 else 00440 buffer[0] = '-'; 00441 } else { 00442 buffer[0] = '-'; 00443 } 00444 00445 buffer[1] = ((( perm & S_IRUSR ) == S_IRUSR ) ? 'r' : '-' ); 00446 buffer[2] = ((( perm & S_IWUSR ) == S_IWUSR ) ? 'w' : '-' ); 00447 buffer[3] = uxbit; 00448 buffer[4] = ((( perm & S_IRGRP ) == S_IRGRP ) ? 'r' : '-' ); 00449 buffer[5] = ((( perm & S_IWGRP ) == S_IWGRP ) ? 'w' : '-' ); 00450 buffer[6] = gxbit; 00451 buffer[7] = ((( perm & S_IROTH ) == S_IROTH ) ? 'r' : '-' ); 00452 buffer[8] = ((( perm & S_IWOTH ) == S_IWOTH ) ? 'w' : '-' ); 00453 buffer[9] = oxbit; 00454 // if (hasExtendedACL()) 00455 if (m_entry.contains(KIO::UDSEntry::UDS_EXTENDED_ACL)) { 00456 buffer[10] = '+'; 00457 buffer[11] = 0; 00458 } else { 00459 buffer[10] = 0; 00460 } 00461 00462 return QString::fromLatin1(buffer); 00463 } 00464 00465 00467 00468 KFileItem::KFileItem() 00469 : d(0) 00470 { 00471 } 00472 00473 KFileItem::KFileItem( const KIO::UDSEntry& entry, const KUrl& itemOrDirUrl, 00474 bool delayedMimeTypes, bool urlIsDirectory ) 00475 : d(new KFileItemPrivate(entry, KFileItem::Unknown, KFileItem::Unknown, 00476 itemOrDirUrl, urlIsDirectory, delayedMimeTypes)) 00477 { 00478 } 00479 00480 KFileItem::KFileItem( mode_t mode, mode_t permissions, const KUrl& url, bool delayedMimeTypes ) 00481 : d(new KFileItemPrivate(KIO::UDSEntry(), mode, permissions, 00482 url, false, delayedMimeTypes)) 00483 { 00484 } 00485 00486 KFileItem::KFileItem( const KUrl &url, const QString &mimeType, mode_t mode ) 00487 : d(new KFileItemPrivate(KIO::UDSEntry(), mode, KFileItem::Unknown, 00488 url, false, false)) 00489 { 00490 d->m_bMimeTypeKnown = !mimeType.isEmpty(); 00491 if (d->m_bMimeTypeKnown) 00492 d->m_pMimeType = KMimeType::mimeType( mimeType ); 00493 } 00494 00495 00496 KFileItem::KFileItem(const KFileItem& other) 00497 : d(other.d) 00498 { 00499 } 00500 00501 KFileItem::~KFileItem() 00502 { 00503 } 00504 00505 void KFileItem::refresh() 00506 { 00507 d->m_fileMode = KFileItem::Unknown; 00508 d->m_permissions = KFileItem::Unknown; 00509 d->m_metaInfo = KFileMetaInfo(); 00510 d->m_hidden = KFileItemPrivate::Auto; 00511 refreshMimeType(); 00512 00513 // Basically, we can't trust any information we got while listing. 00514 // Everything could have changed... 00515 // Clearing m_entry makes it possible to detect changes in the size of the file, 00516 // the time information, etc. 00517 d->m_entry.clear(); 00518 d->init(); 00519 } 00520 00521 void KFileItem::refreshMimeType() 00522 { 00523 d->m_pMimeType = 0; 00524 d->m_bMimeTypeKnown = false; 00525 d->m_iconName.clear(); 00526 } 00527 00528 void KFileItem::setUrl( const KUrl &url ) 00529 { 00530 d->m_url = url; 00531 setName( url.fileName() ); 00532 } 00533 00534 void KFileItem::setName( const QString& name ) 00535 { 00536 d->m_strName = name; 00537 d->m_strText = KIO::decodeFileName( d->m_strName ); 00538 if (d->m_entry.contains(KIO::UDSEntry::UDS_NAME)) 00539 d->m_entry.insert(KIO::UDSEntry::UDS_NAME, d->m_strName); // #195385 00540 00541 } 00542 00543 QString KFileItem::linkDest() const 00544 { 00545 // Extract it from the KIO::UDSEntry 00546 const QString linkStr = d->m_entry.stringValue( KIO::UDSEntry::UDS_LINK_DEST ); 00547 if ( !linkStr.isEmpty() ) 00548 return linkStr; 00549 00550 // If not in the KIO::UDSEntry, or if UDSEntry empty, use readlink() [if local URL] 00551 if ( d->m_bIsLocalUrl ) 00552 { 00553 char buf[1000]; 00554 int n = readlink( QFile::encodeName(d->m_url.toLocalFile( KUrl::RemoveTrailingSlash )), buf, sizeof(buf)-1 ); 00555 if ( n != -1 ) 00556 { 00557 buf[ n ] = 0; 00558 return QFile::decodeName( buf ); 00559 } 00560 } 00561 return QString(); 00562 } 00563 00564 QString KFileItem::localPath() const 00565 { 00566 if ( d->m_bIsLocalUrl ) { 00567 return d->m_url.toLocalFile(); 00568 } 00569 00570 // Extract the local path from the KIO::UDSEntry 00571 return d->m_entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH ); 00572 } 00573 00574 KIO::filesize_t KFileItem::size() const 00575 { 00576 return d->size(); 00577 } 00578 00579 bool KFileItem::hasExtendedACL() const 00580 { 00581 // Check if the field exists; its value doesn't matter 00582 return d->m_entry.contains(KIO::UDSEntry::UDS_EXTENDED_ACL); 00583 } 00584 00585 KACL KFileItem::ACL() const 00586 { 00587 if ( hasExtendedACL() ) { 00588 // Extract it from the KIO::UDSEntry 00589 const QString fieldVal = d->m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING ); 00590 if ( !fieldVal.isEmpty() ) 00591 return KACL( fieldVal ); 00592 } 00593 // create one from the basic permissions 00594 return KACL( d->m_permissions ); 00595 } 00596 00597 KACL KFileItem::defaultACL() const 00598 { 00599 // Extract it from the KIO::UDSEntry 00600 const QString fieldVal = d->m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING ); 00601 if ( !fieldVal.isEmpty() ) 00602 return KACL(fieldVal); 00603 else 00604 return KACL(); 00605 } 00606 00607 KDateTime KFileItem::time( FileTimes which ) const 00608 { 00609 return d->time(which); 00610 } 00611 00612 #ifndef KDE_NO_DEPRECATED 00613 time_t KFileItem::time( unsigned int which ) const 00614 { 00615 switch (which) { 00616 case KIO::UDSEntry::UDS_ACCESS_TIME: 00617 return d->time(AccessTime).toTime_t(); 00618 case KIO::UDSEntry::UDS_CREATION_TIME: 00619 return d->time(CreationTime).toTime_t(); 00620 case KIO::UDSEntry::UDS_MODIFICATION_TIME: 00621 default: 00622 return d->time(ModificationTime).toTime_t(); 00623 } 00624 } 00625 #endif 00626 00627 QString KFileItem::user() const 00628 { 00629 return d->user(); 00630 } 00631 00632 QString KFileItemPrivate::user() const 00633 { 00634 QString userName = m_entry.stringValue(KIO::UDSEntry::UDS_USER); 00635 if (userName.isEmpty() && m_bIsLocalUrl) { 00636 #ifdef Q_WS_WIN 00637 QFileInfo a(m_url.toLocalFile( KUrl::RemoveTrailingSlash )); 00638 userName = a.owner(); 00639 m_entry.insert( KIO::UDSEntry::UDS_USER, userName ); 00640 #else 00641 KDE_struct_stat buff; 00642 if ( KDE::lstat( m_url.toLocalFile( KUrl::RemoveTrailingSlash ), &buff ) == 0) // get uid/gid of the link, if it's a link 00643 { 00644 struct passwd *pwuser = getpwuid( buff.st_uid ); 00645 if ( pwuser != 0 ) { 00646 userName = QString::fromLocal8Bit(pwuser->pw_name); 00647 m_entry.insert( KIO::UDSEntry::UDS_USER, userName ); 00648 } 00649 } 00650 #endif 00651 } 00652 return userName; 00653 } 00654 00655 QString KFileItem::group() const 00656 { 00657 return d->group(); 00658 } 00659 00660 QString KFileItemPrivate::group() const 00661 { 00662 QString groupName = m_entry.stringValue( KIO::UDSEntry::UDS_GROUP ); 00663 if (groupName.isEmpty() && m_bIsLocalUrl ) 00664 { 00665 #ifdef Q_WS_WIN 00666 QFileInfo a(m_url.toLocalFile( KUrl::RemoveTrailingSlash )); 00667 groupName = a.group(); 00668 m_entry.insert( KIO::UDSEntry::UDS_GROUP, groupName ); 00669 #else 00670 KDE_struct_stat buff; 00671 if ( KDE::lstat( m_url.toLocalFile( KUrl::RemoveTrailingSlash ), &buff ) == 0) // get uid/gid of the link, if it's a link 00672 { 00673 struct group *ge = getgrgid( buff.st_gid ); 00674 if ( ge != 0 ) { 00675 groupName = QString::fromLocal8Bit(ge->gr_name); 00676 if (groupName.isEmpty()) 00677 groupName.sprintf("%d",ge->gr_gid); 00678 } 00679 else 00680 groupName.sprintf("%d",buff.st_gid); 00681 m_entry.insert( KIO::UDSEntry::UDS_GROUP, groupName ); 00682 } 00683 #endif 00684 } 00685 return groupName; 00686 } 00687 00688 QString KFileItem::mimetype() const 00689 { 00690 KFileItem * that = const_cast<KFileItem *>(this); 00691 return that->determineMimeType()->name(); 00692 } 00693 00694 KMimeType::Ptr KFileItem::determineMimeType() const 00695 { 00696 if ( !d->m_pMimeType || !d->m_bMimeTypeKnown ) 00697 { 00698 bool isLocalUrl; 00699 KUrl url = mostLocalUrl(isLocalUrl); 00700 00701 d->m_pMimeType = KMimeType::findByUrl( url, d->m_fileMode, isLocalUrl ); 00702 Q_ASSERT(d->m_pMimeType); 00703 //kDebug() << d << "finding final mimetype for" << url << ":" << d->m_pMimeType->name(); 00704 d->m_bMimeTypeKnown = true; 00705 } 00706 00707 return d->m_pMimeType; 00708 } 00709 00710 bool KFileItem::isMimeTypeKnown() const 00711 { 00712 // The mimetype isn't known if determineMimeType was never called (on-demand determination) 00713 // or if this fileitem has a guessed mimetype (e.g. ftp symlink) - in which case 00714 // it always remains "not fully determined" 00715 return d->m_bMimeTypeKnown && d->m_guessedMimeType.isEmpty(); 00716 } 00717 00718 QString KFileItem::mimeComment() const 00719 { 00720 const QString displayType = d->m_entry.stringValue( KIO::UDSEntry::UDS_DISPLAY_TYPE ); 00721 if (!displayType.isEmpty()) 00722 return displayType; 00723 00724 KMimeType::Ptr mType = determineMimeType(); 00725 00726 bool isLocalUrl; 00727 KUrl url = mostLocalUrl(isLocalUrl); 00728 00729 KMimeType::Ptr mime = mimeTypePtr(); 00730 // This cannot move to kio_file (with UDS_DISPLAY_TYPE) because it needs 00731 // the mimetype to be determined, which is done here, and possibly delayed... 00732 if (isLocalUrl && mime->is("application/x-desktop")) { 00733 KDesktopFile cfg( url.toLocalFile() ); 00734 QString comment = cfg.desktopGroup().readEntry( "Comment" ); 00735 if (!comment.isEmpty()) 00736 return comment; 00737 } 00738 00739 QString comment = mType->comment( url ); 00740 //kDebug() << "finding comment for " << url.url() << " : " << d->m_pMimeType->name(); 00741 if (!comment.isEmpty()) 00742 return comment; 00743 else 00744 return mType->name(); 00745 } 00746 00747 static QString iconFromDesktopFile(const QString& path) 00748 { 00749 KDesktopFile cfg( path ); 00750 const QString icon = cfg.readIcon(); 00751 if ( cfg.hasLinkType() ) { 00752 const KConfigGroup group = cfg.desktopGroup(); 00753 const QString type = cfg.readPath(); 00754 const QString emptyIcon = group.readEntry( "EmptyIcon" ); 00755 if ( !emptyIcon.isEmpty() ) { 00756 const QString u = cfg.readUrl(); 00757 const KUrl url( u ); 00758 if ( url.protocol() == "trash" ) { 00759 // We need to find if the trash is empty, preferably without using a KIO job. 00760 // So instead kio_trash leaves an entry in its config file for us. 00761 KConfig trashConfig( "trashrc", KConfig::SimpleConfig ); 00762 if ( trashConfig.group("Status").readEntry( "Empty", true ) ) { 00763 return emptyIcon; 00764 } 00765 } 00766 } 00767 } 00768 return icon; 00769 } 00770 00771 QString KFileItem::iconName() const 00772 { 00773 if (d->m_useIconNameCache && !d->m_iconName.isEmpty()) { 00774 return d->m_iconName; 00775 } 00776 00777 d->m_iconName = d->m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ); 00778 if (!d->m_iconName.isEmpty()) { 00779 d->m_useIconNameCache = d->m_bMimeTypeKnown; 00780 return d->m_iconName; 00781 } 00782 00783 bool isLocalUrl; 00784 KUrl url = mostLocalUrl(isLocalUrl); 00785 00786 KMimeType::Ptr mime = mimeTypePtr(); 00787 if (isLocalUrl && mime->is("application/x-desktop")) { 00788 d->m_iconName = iconFromDesktopFile(url.toLocalFile()); 00789 if (!d->m_iconName.isEmpty()) { 00790 d->m_useIconNameCache = d->m_bMimeTypeKnown; 00791 return d->m_iconName; 00792 } 00793 } 00794 00795 // KDE5: handle .directory files here too, and get rid of 00796 // KFolderMimeType and the url argument in KMimeType::iconName(). 00797 00798 d->m_iconName = mime->iconName(url); 00799 d->m_useIconNameCache = d->m_bMimeTypeKnown; 00800 //kDebug() << "finding icon for" << url << ":" << d->m_iconName; 00801 return d->m_iconName; 00802 } 00803 00808 static bool checkDesktopFile(const KFileItem& item, bool _determineMimeType) 00809 { 00810 // only local files 00811 bool isLocal; 00812 const KUrl url = item.mostLocalUrl(isLocal); 00813 if (!isLocal) 00814 return false; 00815 00816 // only regular files 00817 if (!item.isRegularFile()) 00818 return false; 00819 00820 // only if readable 00821 if (!item.isReadable()) 00822 return false; 00823 00824 // return true if desktop file 00825 KMimeType::Ptr mime = _determineMimeType ? item.determineMimeType() : item.mimeTypePtr(); 00826 return mime->is("application/x-desktop"); 00827 } 00828 00829 QStringList KFileItem::overlays() const 00830 { 00831 QStringList names = d->m_entry.stringValue( KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES ).split(','); 00832 if ( d->m_bLink ) { 00833 names.append("emblem-symbolic-link"); 00834 } 00835 00836 if ( !S_ISDIR( d->m_fileMode ) // Locked dirs have a special icon, use the overlay for files only 00837 && !isReadable()) { 00838 names.append("object-locked"); 00839 } 00840 00841 if ( checkDesktopFile(*this, false) ) { 00842 KDesktopFile cfg( localPath() ); 00843 const KConfigGroup group = cfg.desktopGroup(); 00844 00845 // Add a warning emblem if this is an executable desktop file 00846 // which is untrusted. 00847 if ( group.hasKey( "Exec" ) && !KDesktopFile::isAuthorizedDesktopFile( localPath() ) ) { 00848 names.append( "emblem-important" ); 00849 } 00850 00851 if (cfg.hasDeviceType()) { 00852 const QString dev = cfg.readDevice(); 00853 if (!dev.isEmpty()) { 00854 KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByDevice(dev); 00855 if (mountPoint) // mounted? 00856 names.append("emblem-mounted"); 00857 } 00858 } 00859 } 00860 00861 if ( isHidden() ) { 00862 names.append("hidden"); 00863 } 00864 00865 #ifndef Q_OS_WIN 00866 if( S_ISDIR( d->m_fileMode ) && d->m_bIsLocalUrl) 00867 { 00868 if (KSambaShare::instance()->isDirectoryShared( d->m_url.toLocalFile() ) || 00869 KNFSShare::instance()->isDirectoryShared( d->m_url.toLocalFile() )) 00870 { 00871 //kDebug() << d->m_url.path(); 00872 names.append("network-workgroup"); 00873 } 00874 } 00875 #endif // Q_OS_WIN 00876 00877 if ( d->m_pMimeType && d->m_url.fileName().endsWith( QLatin1String( ".gz" ) ) && 00878 d->m_pMimeType->is("application/x-gzip") ) { 00879 names.append("application-zip"); 00880 } 00881 00882 return names; 00883 } 00884 00885 QString KFileItem::comment() const 00886 { 00887 return d->m_entry.stringValue( KIO::UDSEntry::UDS_COMMENT ); 00888 } 00889 00890 // ## where is this used? 00891 QPixmap KFileItem::pixmap( int _size, int _state ) const 00892 { 00893 const QString iconName = d->m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ); 00894 if ( !iconName.isEmpty() ) 00895 return DesktopIcon(iconName, _size, _state); 00896 00897 if (!d->m_pMimeType) { 00898 // No mimetype determined yet, go for a fast default icon 00899 if (S_ISDIR(d->m_fileMode)) { 00900 static const QString * defaultFolderIcon = 0; 00901 if ( !defaultFolderIcon ) { 00902 const KMimeType::Ptr mimeType = KMimeType::mimeType( "inode/directory" ); 00903 if ( mimeType ) 00904 defaultFolderIcon = &KGlobal::staticQString( mimeType->iconName() ); 00905 else 00906 kWarning(7000) << "No mimetype for inode/directory could be found. Check your installation."; 00907 } 00908 if ( defaultFolderIcon ) 00909 return DesktopIcon( *defaultFolderIcon, _size, _state ); 00910 00911 } 00912 return DesktopIcon( "unknown", _size, _state ); 00913 } 00914 00915 KMimeType::Ptr mime; 00916 // Use guessed mimetype if the main one hasn't been determined for sure 00917 if ( !d->m_bMimeTypeKnown && !d->m_guessedMimeType.isEmpty() ) 00918 mime = KMimeType::mimeType( d->m_guessedMimeType ); 00919 else 00920 mime = d->m_pMimeType; 00921 00922 // Support for gzipped files: extract mimetype of contained file 00923 // See also the relevant code in overlays, which adds the zip overlay. 00924 if ( mime->name() == "application/x-gzip" && d->m_url.fileName().endsWith( QLatin1String( ".gz" ) ) ) 00925 { 00926 KUrl sf; 00927 sf.setPath( d->m_url.path().left( d->m_url.path().length() - 3 ) ); 00928 //kDebug() << "subFileName=" << subFileName; 00929 mime = KMimeType::findByUrl( sf, 0, d->m_bIsLocalUrl ); 00930 } 00931 00932 bool isLocalUrl; 00933 KUrl url = mostLocalUrl(isLocalUrl); 00934 00935 QPixmap p = KIconLoader::global()->loadMimeTypeIcon( mime->iconName( url ), KIconLoader::Desktop, _size, _state ); 00936 //kDebug() << "finding pixmap for " << url.url() << " : " << mime->name(); 00937 if (p.isNull()) 00938 kWarning() << "Pixmap not found for mimetype " << d->m_pMimeType->name(); 00939 00940 return p; 00941 } 00942 00943 bool KFileItem::isReadable() const 00944 { 00945 /* 00946 struct passwd * user = getpwuid( geteuid() ); 00947 bool isMyFile = (QString::fromLocal8Bit(user->pw_name) == d->m_user); 00948 // This gets ugly for the group.... 00949 // Maybe we want a static QString for the user and a static QStringList 00950 // for the groups... then we need to handle the deletion properly... 00951 */ 00952 00953 if (d->m_permissions != KFileItem::Unknown) { 00954 // No read permission at all 00955 if ( !(S_IRUSR & d->m_permissions) && !(S_IRGRP & d->m_permissions) && !(S_IROTH & d->m_permissions) ) 00956 return false; 00957 00958 // Read permissions for all: save a stat call 00959 if ( (S_IRUSR|S_IRGRP|S_IROTH) & d->m_permissions ) 00960 return true; 00961 } 00962 00963 // Or if we can't read it [using ::access()] - not network transparent 00964 if ( d->m_bIsLocalUrl && KDE::access( d->m_url.toLocalFile(), R_OK ) == -1 ) 00965 return false; 00966 00967 return true; 00968 } 00969 00970 bool KFileItem::isWritable() const 00971 { 00972 /* 00973 struct passwd * user = getpwuid( geteuid() ); 00974 bool isMyFile = (QString::fromLocal8Bit(user->pw_name) == d->m_user); 00975 // This gets ugly for the group.... 00976 // Maybe we want a static QString for the user and a static QStringList 00977 // for the groups... then we need to handle the deletion properly... 00978 */ 00979 00980 if (d->m_permissions != KFileItem::Unknown) { 00981 // No write permission at all 00982 if ( !(S_IWUSR & d->m_permissions) && !(S_IWGRP & d->m_permissions) && !(S_IWOTH & d->m_permissions) ) 00983 return false; 00984 } 00985 00986 // Or if we can't read it [using ::access()] - not network transparent 00987 if ( d->m_bIsLocalUrl && KDE::access( d->m_url.toLocalFile(), W_OK ) == -1 ) 00988 return false; 00989 00990 return true; 00991 } 00992 00993 bool KFileItem::isHidden() const 00994 { 00995 // The kioslave can specify explicitly that a file is hidden or shown 00996 if ( d->m_hidden != KFileItemPrivate::Auto ) 00997 return d->m_hidden == KFileItemPrivate::Hidden; 00998 00999 // Prefer the filename that is part of the URL, in case the display name is different. 01000 QString fileName = d->m_url.fileName(); 01001 if (fileName.isEmpty()) // e.g. "trash:/" 01002 fileName = d->m_strName; 01003 return fileName.length() > 1 && fileName[0] == '.'; // Just "." is current directory, not hidden. 01004 } 01005 01006 bool KFileItem::isDir() const 01007 { 01008 if (d->m_fileMode == KFileItem::Unknown) { 01009 // Probably the file was deleted already, and KDirLister hasn't told the world yet. 01010 //kDebug() << d << url() << "can't say -> false"; 01011 return false; // can't say for sure, so no 01012 } 01013 return (S_ISDIR(d->m_fileMode)); 01014 } 01015 01016 bool KFileItem::isFile() const 01017 { 01018 return !isDir(); 01019 } 01020 01021 #ifndef KDE_NO_DEPRECATED 01022 bool KFileItem::acceptsDrops() const 01023 { 01024 // A directory ? 01025 if ( S_ISDIR( mode() ) ) { 01026 return isWritable(); 01027 } 01028 01029 // But only local .desktop files and executables 01030 if ( !d->m_bIsLocalUrl ) 01031 return false; 01032 01033 if ( mimetype() == "application/x-desktop") 01034 return true; 01035 01036 // Executable, shell script ... ? 01037 if ( QFileInfo(d->m_url.toLocalFile()).isExecutable() ) 01038 return true; 01039 01040 return false; 01041 } 01042 #endif 01043 01044 QString KFileItem::getStatusBarInfo() const 01045 { 01046 QString text = d->m_strText; 01047 const QString comment = mimeComment(); 01048 01049 if ( d->m_bLink ) 01050 { 01051 text += ' '; 01052 if ( comment.isEmpty() ) 01053 text += i18n ( "(Symbolic Link to %1)", linkDest() ); 01054 else 01055 text += i18n("(%1, Link to %2)", comment, linkDest()); 01056 } 01057 else if ( targetUrl() != url() ) 01058 { 01059 text += i18n ( " (Points to %1)", targetUrl().pathOrUrl()); 01060 } 01061 else if ( S_ISREG( d->m_fileMode ) ) 01062 { 01063 text += QString(" (%1, %2)").arg( comment, KIO::convertSize( size() ) ); 01064 } 01065 else 01066 { 01067 text += QString(" (%1)").arg( comment ); 01068 } 01069 return text; 01070 } 01071 01072 QString KFileItem::getToolTipText(int maxcount) const 01073 { 01074 // we can return QString() if no tool tip should be shown 01075 QString tip; 01076 KFileMetaInfo info = metaInfo(); 01077 01078 // the font tags are a workaround for the fact that the tool tip gets 01079 // screwed if the color scheme uses white as default text color 01080 const QString colorName = QApplication::palette().color(QPalette::ToolTipText).name(); 01081 const QString start = "<tr><td align=\"right\"><nobr><font color=\"" + colorName + "\"><b>"; 01082 const QString mid = " </b></font></nobr></td><td><nobr><font color=\"" + colorName + "\">"; 01083 const char* end = "</font></nobr></td></tr>"; 01084 01085 tip = "<table cellspacing=0 cellpadding=0>"; 01086 01087 tip += start + i18n("Name:") + mid + text() + end; 01088 tip += start + i18n("Type:") + mid; 01089 01090 QString type = Qt::escape(mimeComment()); 01091 if ( d->m_bLink ) { 01092 tip += i18n("Link to %1 (%2)", linkDest(), type) + end; 01093 } else 01094 tip += type + end; 01095 01096 if ( !S_ISDIR ( d->m_fileMode ) ) 01097 tip += start + i18n("Size:") + mid + 01098 QString("%1").arg(KIO::convertSize(size())) + 01099 end; 01100 01101 tip += start + i18n("Modified:") + mid + 01102 timeString( KFileItem::ModificationTime ) + end 01103 #ifndef Q_WS_WIN //TODO: show win32-specific permissions 01104 +start + i18n("Owner:") + mid + user() + " - " + group() + end + 01105 start + i18n("Permissions:") + mid + 01106 permissionsString() + end 01107 #endif 01108 ; 01109 01110 if (info.isValid()) 01111 { 01112 const QStringList keys = info.preferredKeys(); 01113 01114 // now the rest 01115 QStringList::ConstIterator it = keys.begin(); 01116 for (int count = 0; count<maxcount && it!=keys.end() ; ++it) 01117 { 01118 if ( count == 0 ) 01119 { 01120 tip += "<tr><td colspan=2><center><s> </s></center></td></tr>"; 01121 } 01122 01123 KFileMetaInfoItem item = info.item( *it ); 01124 if ( item.isValid() ) 01125 { 01126 QString s = item.value().toString(); 01127 if ( !s.isEmpty() ) 01128 { 01129 count++; 01130 tip += start + 01131 Qt::escape( item.name() ) + ':' + 01132 mid + 01133 Qt::escape( s ) + 01134 end; 01135 } 01136 01137 } 01138 } 01139 } 01140 tip += "</table>"; 01141 01142 //kDebug() << "making this the tool tip rich text:\n"; 01143 //kDebug() << tip; 01144 01145 return tip; 01146 } 01147 01148 void KFileItem::run( QWidget* parentWidget ) const 01149 { 01150 (void) new KRun( targetUrl(), parentWidget, d->m_fileMode, d->m_bIsLocalUrl ); 01151 } 01152 01153 bool KFileItem::cmp( const KFileItem & item ) const 01154 { 01155 return d->cmp(*item.d); 01156 } 01157 01158 bool KFileItem::operator==(const KFileItem& other) const 01159 { 01160 // is this enough? 01161 return d == other.d; 01162 } 01163 01164 bool KFileItem::operator!=(const KFileItem& other) const 01165 { 01166 return d != other.d; 01167 } 01168 01169 #ifndef KDE_NO_DEPRECATED 01170 void KFileItem::setUDSEntry( const KIO::UDSEntry& _entry, const KUrl& _url, 01171 bool _delayedMimeTypes, bool _urlIsDirectory ) 01172 { 01173 d->m_entry = _entry; 01174 d->m_url = _url; 01175 d->m_strName.clear(); 01176 d->m_strText.clear(); 01177 d->m_iconName.clear(); 01178 d->m_strLowerCaseName.clear(); 01179 d->m_pMimeType = 0; 01180 d->m_fileMode = KFileItem::Unknown; 01181 d->m_permissions = KFileItem::Unknown; 01182 d->m_bMarked = false; 01183 d->m_bLink = false; 01184 d->m_bIsLocalUrl = _url.isLocalFile(); 01185 d->m_bMimeTypeKnown = false; 01186 d->m_hidden = KFileItemPrivate::Auto; 01187 d->m_guessedMimeType.clear(); 01188 d->m_metaInfo = KFileMetaInfo(); 01189 d->m_delayedMimeTypes = _delayedMimeTypes; 01190 d->m_useIconNameCache = false; 01191 01192 d->readUDSEntry( _urlIsDirectory ); 01193 d->init(); 01194 } 01195 #endif 01196 01197 KFileItem::operator QVariant() const 01198 { 01199 return qVariantFromValue(*this); 01200 } 01201 01202 #ifndef KDE_NO_DEPRECATED 01203 void KFileItem::setExtraData( const void *key, void *value ) 01204 { 01205 if ( !key ) 01206 return; 01207 01208 d->m_extra.insert( key, value ); // replaces the value of key if already there 01209 } 01210 #endif 01211 01212 #ifndef KDE_NO_DEPRECATED 01213 const void * KFileItem::extraData( const void *key ) const 01214 { 01215 return d->m_extra.value( key, 0 ); 01216 } 01217 #endif 01218 01219 #ifndef KDE_NO_DEPRECATED 01220 void KFileItem::removeExtraData( const void *key ) 01221 { 01222 d->m_extra.remove( key ); 01223 } 01224 #endif 01225 01226 QString KFileItem::permissionsString() const 01227 { 01228 if (d->m_access.isNull() && d->m_permissions != KFileItem::Unknown) 01229 d->m_access = d->parsePermissions( d->m_permissions ); 01230 01231 return d->m_access; 01232 } 01233 01234 // check if we need to cache this 01235 QString KFileItem::timeString( FileTimes which ) const 01236 { 01237 return KGlobal::locale()->formatDateTime( d->time(which) ); 01238 } 01239 01240 #ifndef KDE_NO_DEPRECATED 01241 QString KFileItem::timeString( unsigned int which ) const 01242 { 01243 switch (which) { 01244 case KIO::UDSEntry::UDS_ACCESS_TIME: 01245 return timeString(AccessTime); 01246 case KIO::UDSEntry::UDS_CREATION_TIME: 01247 return timeString(CreationTime); 01248 case KIO::UDSEntry::UDS_MODIFICATION_TIME: 01249 default: 01250 return timeString(ModificationTime); 01251 } 01252 } 01253 #endif 01254 01255 void KFileItem::setMetaInfo( const KFileMetaInfo & info ) const 01256 { 01257 d->m_metaInfo = info; 01258 } 01259 01260 KFileMetaInfo KFileItem::metaInfo(bool autoget, int what) const 01261 { 01262 if ((isRegularFile() || isDir()) && autoget && !d->m_metaInfo.isValid()) 01263 { 01264 bool isLocalUrl; 01265 KUrl url(mostLocalUrl(isLocalUrl)); 01266 d->m_metaInfo = KFileMetaInfo(url.toLocalFile(), mimetype(), (KFileMetaInfo::What)what); 01267 } 01268 return d->m_metaInfo; 01269 } 01270 01271 #ifndef KDE_NO_DEPRECATED 01272 void KFileItem::assign( const KFileItem & item ) 01273 { 01274 *this = item; 01275 } 01276 #endif 01277 01278 KUrl KFileItem::mostLocalUrl(bool &local) const 01279 { 01280 QString local_path = localPath(); 01281 01282 if ( !local_path.isEmpty() ) 01283 { 01284 local = true; 01285 KUrl url; 01286 url.setPath(local_path); 01287 return url; 01288 } 01289 else 01290 { 01291 local = d->m_bIsLocalUrl; 01292 return d->m_url; 01293 } 01294 } 01295 01296 KUrl KFileItem::mostLocalUrl() const 01297 { 01298 bool local = false; 01299 return mostLocalUrl(local); 01300 } 01301 01302 QDataStream & operator<< ( QDataStream & s, const KFileItem & a ) 01303 { 01304 // We don't need to save/restore anything that refresh() invalidates, 01305 // since that means we can re-determine those by ourselves. 01306 s << a.d->m_url; 01307 s << a.d->m_strName; 01308 s << a.d->m_strText; 01309 return s; 01310 } 01311 01312 QDataStream & operator>> ( QDataStream & s, KFileItem & a ) 01313 { 01314 s >> a.d->m_url; 01315 s >> a.d->m_strName; 01316 s >> a.d->m_strText; 01317 a.d->m_bIsLocalUrl = a.d->m_url.isLocalFile(); 01318 a.d->m_bMimeTypeKnown = false; 01319 a.refresh(); 01320 return s; 01321 } 01322 01323 KUrl KFileItem::url() const 01324 { 01325 return d->m_url; 01326 } 01327 01328 mode_t KFileItem::permissions() const 01329 { 01330 return d->m_permissions; 01331 } 01332 01333 mode_t KFileItem::mode() const 01334 { 01335 return d->m_fileMode; 01336 } 01337 01338 bool KFileItem::isLink() const 01339 { 01340 return d->m_bLink; 01341 } 01342 01343 bool KFileItem::isLocalFile() const 01344 { 01345 return d->m_bIsLocalUrl; 01346 } 01347 01348 QString KFileItem::text() const 01349 { 01350 return d->m_strText; 01351 } 01352 01353 QString KFileItem::name( bool lowerCase ) const 01354 { 01355 if ( !lowerCase ) 01356 return d->m_strName; 01357 else 01358 if ( d->m_strLowerCaseName.isNull() ) 01359 d->m_strLowerCaseName = d->m_strName.toLower(); 01360 return d->m_strLowerCaseName; 01361 } 01362 01363 KUrl KFileItem::targetUrl() const 01364 { 01365 const QString targetUrlStr = d->m_entry.stringValue( KIO::UDSEntry::UDS_TARGET_URL ); 01366 if (!targetUrlStr.isEmpty()) 01367 return KUrl(targetUrlStr); 01368 else 01369 return url(); 01370 } 01371 01372 KUrl KFileItem::nepomukUri() const 01373 { 01374 #ifndef KIO_NO_NEPOMUK 01375 const QString nepomukUriStr = d->m_entry.stringValue( KIO::UDSEntry::UDS_NEPOMUK_URI ); 01376 if(!nepomukUriStr.isEmpty()) { 01377 return KUrl(nepomukUriStr); 01378 } 01379 else if(targetUrl().isLocalFile()) { 01380 return targetUrl(); 01381 } 01382 else { 01383 return KUrl(); 01384 } 01385 #else 01386 return KUrl(); 01387 #endif 01388 } 01389 01390 /* 01391 * Mimetype handling. 01392 * 01393 * Initial state: m_pMimeType = 0. 01394 * When mimeTypePtr() is called first: fast mimetype determination, 01395 * might either find an accurate mimetype (-> Final state), otherwise we 01396 * set m_pMimeType but not m_bMimeTypeKnown (-> Intermediate state) 01397 * Intermediate state: determineMimeType() does the real determination -> Final state. 01398 * 01399 * If delayedMimeTypes isn't set, then we always go to the Final state directly. 01400 */ 01401 01402 KMimeType::Ptr KFileItem::mimeTypePtr() const 01403 { 01404 if (!d->m_pMimeType) { 01405 // On-demand fast (but not always accurate) mimetype determination 01406 Q_ASSERT(!d->m_url.isEmpty()); 01407 bool isLocalUrl; 01408 KUrl url = mostLocalUrl(isLocalUrl); 01409 int accuracy; 01410 d->m_pMimeType = KMimeType::findByUrl( url, d->m_fileMode, isLocalUrl, 01411 // use fast mode if delayed mimetype determination can refine it later 01412 d->m_delayedMimeTypes, &accuracy ); 01413 // If we used the "fast mode" (no sniffing), and we didn't get a perfect (extension-based) match, 01414 // then determineMimeType will be able to do better. 01415 const bool canDoBetter = d->m_delayedMimeTypes && accuracy < 100; 01416 //kDebug() << "finding mimetype for" << url << ":" << d->m_pMimeType->name() << "canDoBetter=" << canDoBetter; 01417 d->m_bMimeTypeKnown = !canDoBetter; 01418 } 01419 return d->m_pMimeType; 01420 } 01421 01422 KIO::UDSEntry KFileItem::entry() const 01423 { 01424 return d->m_entry; 01425 } 01426 01427 bool KFileItem::isMarked() const 01428 { 01429 return d->m_bMarked; 01430 } 01431 01432 void KFileItem::mark() 01433 { 01434 d->m_bMarked = true; 01435 } 01436 01437 void KFileItem::unmark() 01438 { 01439 d->m_bMarked = false; 01440 } 01441 01442 KFileItem& KFileItem::operator=(const KFileItem& other) 01443 { 01444 d = other.d; 01445 return *this; 01446 } 01447 01448 bool KFileItem::isNull() const 01449 { 01450 return d == 0; 01451 } 01452 01453 KFileItemList::KFileItemList() 01454 { 01455 } 01456 01457 KFileItemList::KFileItemList( const QList<KFileItem> &items ) 01458 : QList<KFileItem>( items ) 01459 { 01460 } 01461 01462 KFileItem KFileItemList::findByName( const QString& fileName ) const 01463 { 01464 const_iterator it = begin(); 01465 const const_iterator itend = end(); 01466 for ( ; it != itend ; ++it ) { 01467 if ( (*it).name() == fileName ) { 01468 return *it; 01469 } 01470 } 01471 return KFileItem(); 01472 } 01473 01474 KFileItem KFileItemList::findByUrl( const KUrl& url ) const { 01475 const_iterator it = begin(); 01476 const const_iterator itend = end(); 01477 for ( ; it != itend ; ++it ) { 01478 if ( (*it).url() == url ) { 01479 return *it; 01480 } 01481 } 01482 return KFileItem(); 01483 } 01484 01485 KUrl::List KFileItemList::urlList() const { 01486 KUrl::List lst; 01487 const_iterator it = begin(); 01488 const const_iterator itend = end(); 01489 for ( ; it != itend ; ++it ) { 01490 lst.append( (*it).url() ); 01491 } 01492 return lst; 01493 } 01494 01495 KUrl::List KFileItemList::targetUrlList() const { 01496 KUrl::List lst; 01497 const_iterator it = begin(); 01498 const const_iterator itend = end(); 01499 for ( ; it != itend ; ++it ) { 01500 lst.append( (*it).targetUrl() ); 01501 } 01502 return lst; 01503 } 01504 01505 01506 bool KFileItem::isDesktopFile() const 01507 { 01508 return checkDesktopFile(*this, true); 01509 } 01510 01511 bool KFileItem::isRegularFile() const 01512 { 01513 return S_ISREG(d->m_fileMode); 01514 } 01515 01516 QDebug operator<<(QDebug stream, const KFileItem& item) 01517 { 01518 if (item.isNull()) { 01519 stream << "[null KFileItem]"; 01520 } else { 01521 stream << "[KFileItem for" << item.url() << "]"; 01522 } 01523 return stream; 01524 }
KDE 4.6 API Reference