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 KMimeType::Ptr mType = determineMimeType();
00716
00717 bool isLocalUrl;
00718 KUrl url = mostLocalUrl(isLocalUrl);
00719
00720 KMimeType::Ptr mime = mimeTypePtr();
00721 if (isLocalUrl && mime->is("application/x-desktop")) {
00722 KDesktopFile cfg( url.toLocalFile() );
00723 QString comment = cfg.desktopGroup().readEntry( "Comment" );
00724 if (!comment.isEmpty())
00725 return comment;
00726 }
00727
00728 QString comment = mType->comment( url );
00729
00730 if (!comment.isEmpty())
00731 return comment;
00732 else
00733 return mType->name();
00734 }
00735
00736 static QString iconFromDesktopFile(const QString& path)
00737 {
00738 KDesktopFile cfg( path );
00739 const KConfigGroup group = cfg.desktopGroup();
00740 const QString icon = cfg.readIcon();
00741 const QString type = cfg.readPath();
00742
00743 if ( cfg.hasDeviceType() )
00744 {
00745 const QString unmount_icon = group.readEntry( "UnmountIcon" );
00746 const QString dev = cfg.readDevice();
00747 if ( !icon.isEmpty() && !unmount_icon.isEmpty() && !dev.isEmpty() )
00748 {
00749 KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByDevice(dev);
00750 if (!mountPoint)
00751 return unmount_icon;
00752 }
00753 } else if ( cfg.hasLinkType() ) {
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
00760
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
00796
00797
00798 d->m_iconName = mime->iconName(url);
00799 d->m_useIconNameCache = d->m_bMimeTypeKnown;
00800
00801 return d->m_iconName;
00802 }
00803
00804 QStringList KFileItem::overlays() const
00805 {
00806 QStringList names;
00807 if ( d->m_bLink ) {
00808 names.append("emblem-symbolic-link");
00809 }
00810
00811 if ( !S_ISDIR( d->m_fileMode )
00812 && !isReadable()) {
00813 names.append("object-locked");
00814 }
00815
00816 if ( isDesktopFile() ) {
00817 KDesktopFile cfg( localPath() );
00818 const KConfigGroup group = cfg.desktopGroup();
00819
00820
00821
00822 if ( group.hasKey( "Exec" ) && !KDesktopFile::isAuthorizedDesktopFile( localPath() ) ) {
00823 names.append( "emblem-important" );
00824 }
00825 }
00826
00827 if ( isHidden() ) {
00828 names.append("hidden");
00829 }
00830
00831 #ifndef Q_OS_WIN
00832 if( S_ISDIR( d->m_fileMode ) && d->m_bIsLocalUrl)
00833 {
00834 if (KSambaShare::instance()->isDirectoryShared( d->m_url.toLocalFile() ) ||
00835 KNFSShare::instance()->isDirectoryShared( d->m_url.toLocalFile() ))
00836 {
00837
00838 names.append("network-workgroup");
00839 }
00840 }
00841 #endif // Q_OS_WIN
00842
00843 if ( d->m_pMimeType && d->m_url.fileName().endsWith( QLatin1String( ".gz" ) ) &&
00844 d->m_pMimeType->is("application/x-gzip") ) {
00845 names.append("application-zip");
00846 }
00847
00848 return names;
00849 }
00850
00851
00852 QPixmap KFileItem::pixmap( int _size, int _state ) const
00853 {
00854 const QString iconName = d->m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME );
00855 if ( !iconName.isEmpty() )
00856 return DesktopIcon(iconName, _size, _state);
00857
00858 if (!d->m_pMimeType) {
00859
00860 if (S_ISDIR(d->m_fileMode)) {
00861 static const QString * defaultFolderIcon = 0;
00862 if ( !defaultFolderIcon ) {
00863 const KMimeType::Ptr mimeType = KMimeType::mimeType( "inode/directory" );
00864 if ( mimeType )
00865 defaultFolderIcon = &KGlobal::staticQString( mimeType->iconName() );
00866 else
00867 kWarning(7000) << "No mimetype for inode/directory could be found. Check your installation.";
00868 }
00869 if ( defaultFolderIcon )
00870 return DesktopIcon( *defaultFolderIcon, _size, _state );
00871
00872 }
00873 return DesktopIcon( "unknown", _size, _state );
00874 }
00875
00876 KMimeType::Ptr mime;
00877
00878 if ( !d->m_bMimeTypeKnown && !d->m_guessedMimeType.isEmpty() )
00879 mime = KMimeType::mimeType( d->m_guessedMimeType );
00880 else
00881 mime = d->m_pMimeType;
00882
00883
00884
00885 if ( mime->name() == "application/x-gzip" && d->m_url.fileName().endsWith( QLatin1String( ".gz" ) ) )
00886 {
00887 KUrl sf;
00888 sf.setPath( d->m_url.path().left( d->m_url.path().length() - 3 ) );
00889
00890 mime = KMimeType::findByUrl( sf, 0, d->m_bIsLocalUrl );
00891 }
00892
00893 bool isLocalUrl;
00894 KUrl url = mostLocalUrl(isLocalUrl);
00895
00896 QPixmap p = KIconLoader::global()->loadMimeTypeIcon( mime->iconName( url ), KIconLoader::Desktop, _size, _state );
00897
00898 if (p.isNull())
00899 kWarning() << "Pixmap not found for mimetype " << d->m_pMimeType->name();
00900
00901 return p;
00902 }
00903
00904 bool KFileItem::isReadable() const
00905 {
00906
00907
00908
00909
00910
00911
00912
00913
00914 if (d->m_permissions != KFileItem::Unknown) {
00915
00916 if ( !(S_IRUSR & d->m_permissions) && !(S_IRGRP & d->m_permissions) && !(S_IROTH & d->m_permissions) )
00917 return false;
00918
00919
00920 if ( (S_IRUSR|S_IRGRP|S_IROTH) & d->m_permissions )
00921 return true;
00922 }
00923
00924
00925 if ( d->m_bIsLocalUrl && KDE::access( d->m_url.toLocalFile(), R_OK ) == -1 )
00926 return false;
00927
00928 return true;
00929 }
00930
00931 bool KFileItem::isWritable() const
00932 {
00933
00934
00935
00936
00937
00938
00939
00940
00941 if (d->m_permissions != KFileItem::Unknown) {
00942
00943 if ( !(S_IWUSR & d->m_permissions) && !(S_IWGRP & d->m_permissions) && !(S_IWOTH & d->m_permissions) )
00944 return false;
00945 }
00946
00947
00948 if ( d->m_bIsLocalUrl && KDE::access( d->m_url.toLocalFile(), W_OK ) == -1 )
00949 return false;
00950
00951 return true;
00952 }
00953
00954 bool KFileItem::isHidden() const
00955 {
00956
00957 if ( d->m_hidden != KFileItemPrivate::Auto )
00958 return d->m_hidden == KFileItemPrivate::Hidden;
00959
00960
00961 QString fileName = d->m_url.fileName();
00962 if (fileName.isEmpty())
00963 fileName = d->m_strName;
00964 return fileName.length() > 1 && fileName[0] == '.';
00965 }
00966
00967 bool KFileItem::isDir() const
00968 {
00969 if (d->m_fileMode == KFileItem::Unknown) {
00970
00971
00972 return false;
00973 }
00974 return (S_ISDIR(d->m_fileMode));
00975 }
00976
00977 bool KFileItem::isFile() const
00978 {
00979 return !isDir();
00980 }
00981
00982 bool KFileItem::acceptsDrops() const
00983 {
00984
00985 if ( S_ISDIR( mode() ) ) {
00986 return isWritable();
00987 }
00988
00989
00990 if ( !d->m_bIsLocalUrl )
00991 return false;
00992
00993 if ( mimetype() == "application/x-desktop")
00994 return true;
00995
00996
00997 if ( QFileInfo(d->m_url.toLocalFile()).isExecutable() )
00998 return true;
00999
01000 return false;
01001 }
01002
01003 QString KFileItem::getStatusBarInfo() const
01004 {
01005 QString text = d->m_strText;
01006 const QString comment = mimeComment();
01007
01008 if ( d->m_bLink )
01009 {
01010 text += ' ';
01011 if ( comment.isEmpty() )
01012 text += i18n ( "(Symbolic Link to %1)", linkDest() );
01013 else
01014 text += i18n("(%1, Link to %2)", comment, linkDest());
01015 }
01016 else if ( targetUrl() != url() )
01017 {
01018 text += i18n ( " (Points to %1)", targetUrl().pathOrUrl());
01019 }
01020 else if ( S_ISREG( d->m_fileMode ) )
01021 {
01022 text += QString(" (%1, %2)").arg( comment, KIO::convertSize( size() ) );
01023 }
01024 else
01025 {
01026 text += QString(" (%1)").arg( comment );
01027 }
01028 return text;
01029 }
01030
01031 QString KFileItem::getToolTipText(int maxcount) const
01032 {
01033
01034 QString tip;
01035 KFileMetaInfo info = metaInfo();
01036
01037
01038
01039 const QString colorName = QApplication::palette().color(QPalette::ToolTipText).name();
01040 const QString start = "<tr><td align=\"right\"><nobr><font color=\"" + colorName + "\"><b>";
01041 const QString mid = " </b></font></nobr></td><td><nobr><font color=\"" + colorName + "\">";
01042 const char* end = "</font></nobr></td></tr>";
01043
01044 tip = "<table cellspacing=0 cellpadding=0>";
01045
01046 tip += start + i18n("Name:") + mid + text() + end;
01047 tip += start + i18n("Type:") + mid;
01048
01049 QString type = Qt::escape(mimeComment());
01050 if ( d->m_bLink ) {
01051 tip += i18n("Link to %1 (%2)", linkDest(), type) + end;
01052 } else
01053 tip += type + end;
01054
01055 if ( !S_ISDIR ( d->m_fileMode ) )
01056 tip += start + i18n("Size:") + mid +
01057 QString("%1").arg(KIO::convertSize(size())) +
01058 end;
01059
01060 tip += start + i18n("Modified:") + mid +
01061 timeString( KFileItem::ModificationTime ) + end
01062 #ifndef Q_WS_WIN //TODO: show win32-specific permissions
01063 +start + i18n("Owner:") + mid + user() + " - " + group() + end +
01064 start + i18n("Permissions:") + mid +
01065 permissionsString() + end
01066 #endif
01067 ;
01068
01069 if (info.isValid())
01070 {
01071 const QStringList keys = info.preferredKeys();
01072
01073
01074 QStringList::ConstIterator it = keys.begin();
01075 for (int count = 0; count<maxcount && it!=keys.end() ; ++it)
01076 {
01077 if ( count == 0 )
01078 {
01079 tip += "<tr><td colspan=2><center><s> </s></center></td></tr>";
01080 }
01081
01082 KFileMetaInfoItem item = info.item( *it );
01083 if ( item.isValid() )
01084 {
01085 QString s = item.value().toString();
01086 if ( ( item.properties().attributes() & PredicateProperties::SqueezeText )
01087 && s.length() > 50) {
01088 s.truncate(47);
01089 s.append("...");
01090 }
01091 if ( !s.isEmpty() )
01092 {
01093 count++;
01094 tip += start +
01095 Qt::escape( item.name() ) + ':' +
01096 mid +
01097 Qt::escape( s ) +
01098 end;
01099 }
01100
01101 }
01102 }
01103 }
01104 tip += "</table>";
01105
01106
01107
01108
01109 return tip;
01110 }
01111
01112 void KFileItem::run( QWidget* parentWidget ) const
01113 {
01114 (void) new KRun( targetUrl(), parentWidget, d->m_fileMode, d->m_bIsLocalUrl );
01115 }
01116
01117 bool KFileItem::cmp( const KFileItem & item ) const
01118 {
01119 return d->cmp(*item.d);
01120 }
01121
01122 bool KFileItem::operator==(const KFileItem& other) const
01123 {
01124
01125 return d == other.d;
01126 }
01127
01128 bool KFileItem::operator!=(const KFileItem& other) const
01129 {
01130 return d != other.d;
01131 }
01132
01133 void KFileItem::setUDSEntry( const KIO::UDSEntry& _entry, const KUrl& _url,
01134 bool _delayedMimeTypes, bool _urlIsDirectory )
01135 {
01136 d->m_entry = _entry;
01137 d->m_url = _url;
01138 d->m_strName.clear();
01139 d->m_strText.clear();
01140 d->m_iconName.clear();
01141 d->m_strLowerCaseName.clear();
01142 d->m_pMimeType = 0;
01143 d->m_fileMode = KFileItem::Unknown;
01144 d->m_permissions = KFileItem::Unknown;
01145 d->m_bMarked = false;
01146 d->m_bLink = false;
01147 d->m_bIsLocalUrl = _url.isLocalFile();
01148 d->m_bMimeTypeKnown = false;
01149 d->m_hidden = KFileItemPrivate::Auto;
01150 d->m_guessedMimeType.clear();
01151 d->m_metaInfo = KFileMetaInfo();
01152 d->m_delayedMimeTypes = _delayedMimeTypes;
01153 d->m_useIconNameCache = false;
01154
01155 d->readUDSEntry( _urlIsDirectory );
01156 d->init();
01157 }
01158
01159 KFileItem::operator QVariant() const
01160 {
01161 return qVariantFromValue(*this);
01162 }
01163
01164 void KFileItem::setExtraData( const void *key, void *value )
01165 {
01166 if ( !key )
01167 return;
01168
01169 d->m_extra.insert( key, value );
01170 }
01171
01172 const void * KFileItem::extraData( const void *key ) const
01173 {
01174 return d->m_extra.value( key, 0 );
01175 }
01176
01177 void KFileItem::removeExtraData( const void *key )
01178 {
01179 d->m_extra.remove( key );
01180 }
01181
01182 QString KFileItem::permissionsString() const
01183 {
01184 if (d->m_access.isNull() && d->m_permissions != KFileItem::Unknown)
01185 d->m_access = d->parsePermissions( d->m_permissions );
01186
01187 return d->m_access;
01188 }
01189
01190
01191 QString KFileItem::timeString( FileTimes which ) const
01192 {
01193 return KGlobal::locale()->formatDateTime( d->time(which) );
01194 }
01195
01196 QString KFileItem::timeString( unsigned int which ) const
01197 {
01198 switch (which) {
01199 case KIO::UDSEntry::UDS_ACCESS_TIME:
01200 return timeString(AccessTime);
01201 case KIO::UDSEntry::UDS_CREATION_TIME:
01202 return timeString(CreationTime);
01203 case KIO::UDSEntry::UDS_MODIFICATION_TIME:
01204 default:
01205 return timeString(ModificationTime);
01206 }
01207 }
01208
01209 void KFileItem::setMetaInfo( const KFileMetaInfo & info ) const
01210 {
01211 d->m_metaInfo = info;
01212 }
01213
01214 KFileMetaInfo KFileItem::metaInfo(bool autoget, int) const
01215 {
01216 if ((isRegularFile() || isDir()) && autoget && !d->m_metaInfo.isValid())
01217 {
01218 bool isLocalUrl;
01219 KUrl url(mostLocalUrl(isLocalUrl));
01220 d->m_metaInfo = KFileMetaInfo(url);
01221 }
01222 return d->m_metaInfo;
01223 }
01224
01225 void KFileItem::assign( const KFileItem & item )
01226 {
01227 *this = item;
01228 }
01229
01230 KUrl KFileItem::mostLocalUrl(bool &local) const
01231 {
01232 QString local_path = localPath();
01233
01234 if ( !local_path.isEmpty() )
01235 {
01236 local = true;
01237 KUrl url;
01238 url.setPath(local_path);
01239 return url;
01240 }
01241 else
01242 {
01243 local = d->m_bIsLocalUrl;
01244 return d->m_url;
01245 }
01246 }
01247
01248 QDataStream & operator<< ( QDataStream & s, const KFileItem & a )
01249 {
01250
01251
01252 s << a.d->m_url;
01253 s << a.d->m_strName;
01254 s << a.d->m_strText;
01255 return s;
01256 }
01257
01258 QDataStream & operator>> ( QDataStream & s, KFileItem & a )
01259 {
01260 s >> a.d->m_url;
01261 s >> a.d->m_strName;
01262 s >> a.d->m_strText;
01263 a.d->m_bIsLocalUrl = a.d->m_url.isLocalFile();
01264 a.d->m_bMimeTypeKnown = false;
01265 a.refresh();
01266 return s;
01267 }
01268
01269 KUrl KFileItem::url() const
01270 {
01271 return d->m_url;
01272 }
01273
01274 mode_t KFileItem::permissions() const
01275 {
01276 return d->m_permissions;
01277 }
01278
01279 mode_t KFileItem::mode() const
01280 {
01281 return d->m_fileMode;
01282 }
01283
01284 bool KFileItem::isLink() const
01285 {
01286 return d->m_bLink;
01287 }
01288
01289 bool KFileItem::isLocalFile() const
01290 {
01291 return d->m_bIsLocalUrl;
01292 }
01293
01294 QString KFileItem::text() const
01295 {
01296 return d->m_strText;
01297 }
01298
01299 QString KFileItem::name( bool lowerCase ) const
01300 {
01301 if ( !lowerCase )
01302 return d->m_strName;
01303 else
01304 if ( d->m_strLowerCaseName.isNull() )
01305 d->m_strLowerCaseName = d->m_strName.toLower();
01306 return d->m_strLowerCaseName;
01307 }
01308
01309 KUrl KFileItem::targetUrl() const
01310 {
01311 const QString targetUrlStr = d->m_entry.stringValue( KIO::UDSEntry::UDS_TARGET_URL );
01312 if (!targetUrlStr.isEmpty())
01313 return KUrl(targetUrlStr);
01314 else
01315 return url();
01316 }
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330 KMimeType::Ptr KFileItem::mimeTypePtr() const
01331 {
01332 if (!d->m_pMimeType) {
01333
01334 Q_ASSERT(!d->m_url.isEmpty());
01335 bool isLocalUrl;
01336 KUrl url = mostLocalUrl(isLocalUrl);
01337 int accuracy;
01338 d->m_pMimeType = KMimeType::findByUrl( url, d->m_fileMode, isLocalUrl,
01339
01340 d->m_delayedMimeTypes, &accuracy );
01341
01342
01343 const bool canDoBetter = d->m_delayedMimeTypes && accuracy < 100;
01344
01345 d->m_bMimeTypeKnown = !canDoBetter;
01346 }
01347 return d->m_pMimeType;
01348 }
01349
01350 KIO::UDSEntry KFileItem::entry() const
01351 {
01352 return d->m_entry;
01353 }
01354
01355 bool KFileItem::isMarked() const
01356 {
01357 return d->m_bMarked;
01358 }
01359
01360 void KFileItem::mark()
01361 {
01362 d->m_bMarked = true;
01363 }
01364
01365 void KFileItem::unmark()
01366 {
01367 d->m_bMarked = false;
01368 }
01369
01370 KFileItem& KFileItem::operator=(const KFileItem& other)
01371 {
01372 d = other.d;
01373 return *this;
01374 }
01375
01376 bool KFileItem::isNull() const
01377 {
01378 return d == 0;
01379 }
01380
01381 KFileItemList::KFileItemList()
01382 {
01383 }
01384
01385 KFileItemList::KFileItemList( const QList<KFileItem> &items )
01386 : QList<KFileItem>( items )
01387 {
01388 }
01389
01390 KFileItem KFileItemList::findByName( const QString& fileName ) const
01391 {
01392 const_iterator it = begin();
01393 const const_iterator itend = end();
01394 for ( ; it != itend ; ++it ) {
01395 if ( (*it).name() == fileName ) {
01396 return *it;
01397 }
01398 }
01399 return KFileItem();
01400 }
01401
01402 KFileItem KFileItemList::findByUrl( const KUrl& url ) const {
01403 const_iterator it = begin();
01404 const const_iterator itend = end();
01405 for ( ; it != itend ; ++it ) {
01406 if ( (*it).url() == url ) {
01407 return *it;
01408 }
01409 }
01410 return KFileItem();
01411 }
01412
01413 KUrl::List KFileItemList::urlList() const {
01414 KUrl::List lst;
01415 const_iterator it = begin();
01416 const const_iterator itend = end();
01417 for ( ; it != itend ; ++it ) {
01418 lst.append( (*it).url() );
01419 }
01420 return lst;
01421 }
01422
01423 KUrl::List KFileItemList::targetUrlList() const {
01424 KUrl::List lst;
01425 const_iterator it = begin();
01426 const const_iterator itend = end();
01427 for ( ; it != itend ; ++it ) {
01428 lst.append( (*it).targetUrl() );
01429 }
01430 return lst;
01431 }
01432
01433 bool KFileItem::isDesktopFile() const
01434 {
01435
01436 bool isLocal;
01437 const KUrl url = mostLocalUrl(isLocal);
01438 if (!isLocal)
01439 return false;
01440
01441
01442 if (!S_ISREG(d->m_fileMode))
01443 return false;
01444
01445
01446 if (!isReadable())
01447 return false;
01448
01449
01450 return determineMimeType()->is("application/x-desktop");
01451 }
01452
01453 bool KFileItem::isRegularFile() const
01454 {
01455 return S_ISREG(d->m_fileMode);
01456 }