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 <QtGui/QPalette> 00041 #include <QTextDocument> 00042 00043 #include <kdebug.h> 00044 #include <kfilemetainfo.h> 00045 #include <kglobal.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 #ifndef KDE_NO_DEPRECATED 01073 QString KFileItem::getToolTipText(int maxcount) const 01074 { 01075 // we can return QString() if no tool tip should be shown 01076 QString tip; 01077 KFileMetaInfo info = metaInfo(); 01078 01079 // the font tags are a workaround for the fact that the tool tip gets 01080 // screwed if the color scheme uses white as default text color 01081 const QString colorName = QApplication::palette().color(QPalette::ToolTipText).name(); 01082 const QString start = "<tr><td align=\"right\"><nobr><font color=\"" + colorName + "\"><b>"; 01083 const QString mid = " </b></font></nobr></td><td><nobr><font color=\"" + colorName + "\">"; 01084 const char* end = "</font></nobr></td></tr>"; 01085 01086 tip = "<table cellspacing=0 cellpadding=0>"; 01087 01088 tip += start + i18n("Name:") + mid + text() + end; 01089 tip += start + i18n("Type:") + mid; 01090 01091 QString type = Qt::escape(mimeComment()); 01092 if ( d->m_bLink ) { 01093 tip += i18n("Link to %1 (%2)", linkDest(), type) + end; 01094 } else 01095 tip += type + end; 01096 01097 if ( !S_ISDIR ( d->m_fileMode ) ) 01098 tip += start + i18n("Size:") + mid + 01099 QString("%1").arg(KIO::convertSize(size())) + 01100 end; 01101 01102 tip += start + i18n("Modified:") + mid + 01103 timeString( KFileItem::ModificationTime ) + end 01104 #ifndef Q_WS_WIN //TODO: show win32-specific permissions 01105 +start + i18n("Owner:") + mid + user() + " - " + group() + end + 01106 start + i18n("Permissions:") + mid + 01107 permissionsString() + end 01108 #endif 01109 ; 01110 01111 if (info.isValid()) 01112 { 01113 const QStringList keys = info.preferredKeys(); 01114 01115 // now the rest 01116 QStringList::ConstIterator it = keys.begin(); 01117 for (int count = 0; count<maxcount && it!=keys.end() ; ++it) 01118 { 01119 if ( count == 0 ) 01120 { 01121 tip += "<tr><td colspan=2><center><s> </s></center></td></tr>"; 01122 } 01123 01124 KFileMetaInfoItem item = info.item( *it ); 01125 if ( item.isValid() ) 01126 { 01127 QString s = item.value().toString(); 01128 if ( !s.isEmpty() ) 01129 { 01130 count++; 01131 tip += start + 01132 Qt::escape( item.name() ) + ':' + 01133 mid + 01134 Qt::escape( s ) + 01135 end; 01136 } 01137 01138 } 01139 } 01140 } 01141 tip += "</table>"; 01142 01143 //kDebug() << "making this the tool tip rich text:\n"; 01144 //kDebug() << tip; 01145 01146 return tip; 01147 } 01148 #endif 01149 01150 void KFileItem::run( QWidget* parentWidget ) const 01151 { 01152 (void) new KRun( targetUrl(), parentWidget, d->m_fileMode, d->m_bIsLocalUrl ); 01153 } 01154 01155 bool KFileItem::cmp( const KFileItem & item ) const 01156 { 01157 return d->cmp(*item.d); 01158 } 01159 01160 bool KFileItem::operator==(const KFileItem& other) const 01161 { 01162 // is this enough? 01163 return d == other.d; 01164 } 01165 01166 bool KFileItem::operator!=(const KFileItem& other) const 01167 { 01168 return d != other.d; 01169 } 01170 01171 #ifndef KDE_NO_DEPRECATED 01172 void KFileItem::setUDSEntry( const KIO::UDSEntry& _entry, const KUrl& _url, 01173 bool _delayedMimeTypes, bool _urlIsDirectory ) 01174 { 01175 d->m_entry = _entry; 01176 d->m_url = _url; 01177 d->m_strName.clear(); 01178 d->m_strText.clear(); 01179 d->m_iconName.clear(); 01180 d->m_strLowerCaseName.clear(); 01181 d->m_pMimeType = 0; 01182 d->m_fileMode = KFileItem::Unknown; 01183 d->m_permissions = KFileItem::Unknown; 01184 d->m_bMarked = false; 01185 d->m_bLink = false; 01186 d->m_bIsLocalUrl = _url.isLocalFile(); 01187 d->m_bMimeTypeKnown = false; 01188 d->m_hidden = KFileItemPrivate::Auto; 01189 d->m_guessedMimeType.clear(); 01190 d->m_metaInfo = KFileMetaInfo(); 01191 d->m_delayedMimeTypes = _delayedMimeTypes; 01192 d->m_useIconNameCache = false; 01193 01194 d->readUDSEntry( _urlIsDirectory ); 01195 d->init(); 01196 } 01197 #endif 01198 01199 KFileItem::operator QVariant() const 01200 { 01201 return qVariantFromValue(*this); 01202 } 01203 01204 #ifndef KDE_NO_DEPRECATED 01205 void KFileItem::setExtraData( const void *key, void *value ) 01206 { 01207 if ( !key ) 01208 return; 01209 01210 d->m_extra.insert( key, value ); // replaces the value of key if already there 01211 } 01212 #endif 01213 01214 #ifndef KDE_NO_DEPRECATED 01215 const void * KFileItem::extraData( const void *key ) const 01216 { 01217 return d->m_extra.value( key, 0 ); 01218 } 01219 #endif 01220 01221 #ifndef KDE_NO_DEPRECATED 01222 void KFileItem::removeExtraData( const void *key ) 01223 { 01224 d->m_extra.remove( key ); 01225 } 01226 #endif 01227 01228 QString KFileItem::permissionsString() const 01229 { 01230 if (d->m_access.isNull() && d->m_permissions != KFileItem::Unknown) 01231 d->m_access = d->parsePermissions( d->m_permissions ); 01232 01233 return d->m_access; 01234 } 01235 01236 // check if we need to cache this 01237 QString KFileItem::timeString( FileTimes which ) const 01238 { 01239 return KGlobal::locale()->formatDateTime( d->time(which) ); 01240 } 01241 01242 #ifndef KDE_NO_DEPRECATED 01243 QString KFileItem::timeString( unsigned int which ) const 01244 { 01245 switch (which) { 01246 case KIO::UDSEntry::UDS_ACCESS_TIME: 01247 return timeString(AccessTime); 01248 case KIO::UDSEntry::UDS_CREATION_TIME: 01249 return timeString(CreationTime); 01250 case KIO::UDSEntry::UDS_MODIFICATION_TIME: 01251 default: 01252 return timeString(ModificationTime); 01253 } 01254 } 01255 #endif 01256 01257 void KFileItem::setMetaInfo( const KFileMetaInfo & info ) const 01258 { 01259 d->m_metaInfo = info; 01260 } 01261 01262 KFileMetaInfo KFileItem::metaInfo(bool autoget, int what) const 01263 { 01264 if ((isRegularFile() || isDir()) && autoget && !d->m_metaInfo.isValid()) 01265 { 01266 bool isLocalUrl; 01267 KUrl url(mostLocalUrl(isLocalUrl)); 01268 d->m_metaInfo = KFileMetaInfo(url.toLocalFile(), mimetype(), (KFileMetaInfo::What)what); 01269 } 01270 return d->m_metaInfo; 01271 } 01272 01273 #ifndef KDE_NO_DEPRECATED 01274 void KFileItem::assign( const KFileItem & item ) 01275 { 01276 *this = item; 01277 } 01278 #endif 01279 01280 KUrl KFileItem::mostLocalUrl(bool &local) const 01281 { 01282 QString local_path = localPath(); 01283 01284 if ( !local_path.isEmpty() ) 01285 { 01286 local = true; 01287 KUrl url; 01288 url.setPath(local_path); 01289 return url; 01290 } 01291 else 01292 { 01293 local = d->m_bIsLocalUrl; 01294 return d->m_url; 01295 } 01296 } 01297 01298 KUrl KFileItem::mostLocalUrl() const 01299 { 01300 bool local = false; 01301 return mostLocalUrl(local); 01302 } 01303 01304 QDataStream & operator<< ( QDataStream & s, const KFileItem & a ) 01305 { 01306 // We don't need to save/restore anything that refresh() invalidates, 01307 // since that means we can re-determine those by ourselves. 01308 s << a.d->m_url; 01309 s << a.d->m_strName; 01310 s << a.d->m_strText; 01311 return s; 01312 } 01313 01314 QDataStream & operator>> ( QDataStream & s, KFileItem & a ) 01315 { 01316 s >> a.d->m_url; 01317 s >> a.d->m_strName; 01318 s >> a.d->m_strText; 01319 a.d->m_bIsLocalUrl = a.d->m_url.isLocalFile(); 01320 a.d->m_bMimeTypeKnown = false; 01321 a.refresh(); 01322 return s; 01323 } 01324 01325 KUrl KFileItem::url() const 01326 { 01327 return d->m_url; 01328 } 01329 01330 mode_t KFileItem::permissions() const 01331 { 01332 return d->m_permissions; 01333 } 01334 01335 mode_t KFileItem::mode() const 01336 { 01337 return d->m_fileMode; 01338 } 01339 01340 bool KFileItem::isLink() const 01341 { 01342 return d->m_bLink; 01343 } 01344 01345 bool KFileItem::isLocalFile() const 01346 { 01347 return d->m_bIsLocalUrl; 01348 } 01349 01350 QString KFileItem::text() const 01351 { 01352 return d->m_strText; 01353 } 01354 01355 QString KFileItem::name( bool lowerCase ) const 01356 { 01357 if ( !lowerCase ) 01358 return d->m_strName; 01359 else 01360 if ( d->m_strLowerCaseName.isNull() ) 01361 d->m_strLowerCaseName = d->m_strName.toLower(); 01362 return d->m_strLowerCaseName; 01363 } 01364 01365 KUrl KFileItem::targetUrl() const 01366 { 01367 const QString targetUrlStr = d->m_entry.stringValue( KIO::UDSEntry::UDS_TARGET_URL ); 01368 if (!targetUrlStr.isEmpty()) 01369 return KUrl(targetUrlStr); 01370 else 01371 return url(); 01372 } 01373 01374 KUrl KFileItem::nepomukUri() const 01375 { 01376 #ifndef KIO_NO_NEPOMUK 01377 const QString nepomukUriStr = d->m_entry.stringValue( KIO::UDSEntry::UDS_NEPOMUK_URI ); 01378 if(!nepomukUriStr.isEmpty()) { 01379 return KUrl(nepomukUriStr); 01380 } 01381 else if(targetUrl().isLocalFile()) { 01382 return targetUrl(); 01383 } 01384 else { 01385 return KUrl(); 01386 } 01387 #else 01388 return KUrl(); 01389 #endif 01390 } 01391 01392 /* 01393 * Mimetype handling. 01394 * 01395 * Initial state: m_pMimeType = 0. 01396 * When mimeTypePtr() is called first: fast mimetype determination, 01397 * might either find an accurate mimetype (-> Final state), otherwise we 01398 * set m_pMimeType but not m_bMimeTypeKnown (-> Intermediate state) 01399 * Intermediate state: determineMimeType() does the real determination -> Final state. 01400 * 01401 * If delayedMimeTypes isn't set, then we always go to the Final state directly. 01402 */ 01403 01404 KMimeType::Ptr KFileItem::mimeTypePtr() const 01405 { 01406 if (!d->m_pMimeType) { 01407 // On-demand fast (but not always accurate) mimetype determination 01408 Q_ASSERT(!d->m_url.isEmpty()); 01409 bool isLocalUrl; 01410 KUrl url = mostLocalUrl(isLocalUrl); 01411 int accuracy; 01412 d->m_pMimeType = KMimeType::findByUrl( url, d->m_fileMode, isLocalUrl, 01413 // use fast mode if delayed mimetype determination can refine it later 01414 d->m_delayedMimeTypes, &accuracy ); 01415 // If we used the "fast mode" (no sniffing), and we didn't get a perfect (extension-based) match, 01416 // then determineMimeType will be able to do better. 01417 const bool canDoBetter = d->m_delayedMimeTypes && accuracy < 100; 01418 //kDebug() << "finding mimetype for" << url << ":" << d->m_pMimeType->name() << "canDoBetter=" << canDoBetter; 01419 d->m_bMimeTypeKnown = !canDoBetter; 01420 } 01421 return d->m_pMimeType; 01422 } 01423 01424 KIO::UDSEntry KFileItem::entry() const 01425 { 01426 return d->m_entry; 01427 } 01428 01429 bool KFileItem::isMarked() const 01430 { 01431 return d->m_bMarked; 01432 } 01433 01434 void KFileItem::mark() 01435 { 01436 d->m_bMarked = true; 01437 } 01438 01439 void KFileItem::unmark() 01440 { 01441 d->m_bMarked = false; 01442 } 01443 01444 KFileItem& KFileItem::operator=(const KFileItem& other) 01445 { 01446 d = other.d; 01447 return *this; 01448 } 01449 01450 bool KFileItem::isNull() const 01451 { 01452 return d == 0; 01453 } 01454 01455 KFileItemList::KFileItemList() 01456 { 01457 } 01458 01459 KFileItemList::KFileItemList( const QList<KFileItem> &items ) 01460 : QList<KFileItem>( items ) 01461 { 01462 } 01463 01464 KFileItem KFileItemList::findByName( const QString& fileName ) const 01465 { 01466 const_iterator it = begin(); 01467 const const_iterator itend = end(); 01468 for ( ; it != itend ; ++it ) { 01469 if ( (*it).name() == fileName ) { 01470 return *it; 01471 } 01472 } 01473 return KFileItem(); 01474 } 01475 01476 KFileItem KFileItemList::findByUrl( const KUrl& url ) const { 01477 const_iterator it = begin(); 01478 const const_iterator itend = end(); 01479 for ( ; it != itend ; ++it ) { 01480 if ( (*it).url() == url ) { 01481 return *it; 01482 } 01483 } 01484 return KFileItem(); 01485 } 01486 01487 KUrl::List KFileItemList::urlList() const { 01488 KUrl::List lst; 01489 const_iterator it = begin(); 01490 const const_iterator itend = end(); 01491 for ( ; it != itend ; ++it ) { 01492 lst.append( (*it).url() ); 01493 } 01494 return lst; 01495 } 01496 01497 KUrl::List KFileItemList::targetUrlList() const { 01498 KUrl::List lst; 01499 const_iterator it = begin(); 01500 const const_iterator itend = end(); 01501 for ( ; it != itend ; ++it ) { 01502 lst.append( (*it).targetUrl() ); 01503 } 01504 return lst; 01505 } 01506 01507 01508 bool KFileItem::isDesktopFile() const 01509 { 01510 return checkDesktopFile(*this, true); 01511 } 01512 01513 bool KFileItem::isRegularFile() const 01514 { 01515 return S_ISREG(d->m_fileMode); 01516 } 01517 01518 QDebug operator<<(QDebug stream, const KFileItem& item) 01519 { 01520 if (item.isNull()) { 01521 stream << "[null KFileItem]"; 01522 } else { 01523 stream << "[KFileItem for" << item.url() << "]"; 01524 } 01525 return stream; 01526 }
KDE 4.7 API Reference