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