kfileitem.cpp
00001 /* This file is part of the KDE project 00002 Copyright (C) 1999 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 // $Id$ 00021 00022 #include <sys/time.h> 00023 #include <pwd.h> 00024 #include <grp.h> 00025 #include <sys/types.h> 00026 00027 #include <assert.h> 00028 #include <unistd.h> 00029 00030 #include "kfileitem.h" 00031 00032 #include <tqdir.h> 00033 #include <tqfile.h> 00034 #include <tqmap.h> 00035 #include <tqstylesheet.h> 00036 00037 #include <kdebug.h> 00038 #include <kfilemetainfo.h> 00039 #include <ksambashare.h> 00040 #include <knfsshare.h> 00041 #include <kglobal.h> 00042 #include <kglobalsettings.h> 00043 #include <kiconloader.h> 00044 #include <klargefile.h> 00045 #include <klocale.h> 00046 #include <kmimetype.h> 00047 #include <krun.h> 00048 00049 class KFileItem::KFileItemPrivate { 00050 public: 00051 KFileItemPrivate() : commentCached(false) {} 00052 00053 public: 00054 TQString iconName; 00055 TQString comment; 00056 bool commentCached; 00057 }; 00058 00059 KFileItem::KFileItem( const KIO::UDSEntry& _entry, const KURL& _url, 00060 bool _determineMimeTypeOnDemand, bool _urlIsDirectory ) : 00061 m_entry( _entry ), 00062 m_url( _url ), 00063 m_pMimeType( 0 ), 00064 m_fileMode( KFileItem::Unknown ), 00065 m_permissions( KFileItem::Unknown ), 00066 m_bMarked( false ), 00067 m_bLink( false ), 00068 m_bIsLocalURL( _url.isLocalFile() ), 00069 m_bMimeTypeKnown( false ), 00070 m_hidden( Auto ), 00071 d(0) 00072 { 00073 readUDSEntry( _urlIsDirectory ); 00074 init( _determineMimeTypeOnDemand ); 00075 } 00076 00077 KFileItem::KFileItem( mode_t _mode, mode_t _permissions, const KURL& _url, bool _determineMimeTypeOnDemand ) : 00078 m_entry(), // warning ! 00079 m_url( _url ), 00080 m_strName( _url.fileName() ), 00081 m_strText( KIO::decodeFileName( m_strName ) ), 00082 m_pMimeType( 0 ), 00083 m_fileMode ( _mode ), 00084 m_permissions( _permissions ), 00085 m_bMarked( false ), 00086 m_bLink( false ), 00087 m_bIsLocalURL( _url.isLocalFile() ), 00088 m_bMimeTypeKnown( false ), 00089 m_hidden( Auto ), 00090 d(0) 00091 { 00092 init( _determineMimeTypeOnDemand ); 00093 } 00094 00095 KFileItem::KFileItem( const KURL &url, const TQString &mimeType, mode_t mode ) 00096 : m_url( url ), 00097 m_strName( url.fileName() ), 00098 m_strText( KIO::decodeFileName( m_strName ) ), 00099 m_pMimeType( 0 ), 00100 m_fileMode( mode ), 00101 m_permissions( KFileItem::Unknown ), 00102 m_bMarked( false ), 00103 m_bLink( false ), 00104 m_bIsLocalURL( url.isLocalFile() ), 00105 m_bMimeTypeKnown( !mimeType.isEmpty() ), 00106 m_hidden( Auto ), 00107 d(0) 00108 { 00109 if (m_bMimeTypeKnown) 00110 m_pMimeType = KMimeType::mimeType( mimeType ); 00111 00112 init( false ); 00113 } 00114 00115 KFileItem::KFileItem( const KFileItem & item ) : 00116 d(0) 00117 { 00118 assign( item ); 00119 } 00120 00121 KFileItem& KFileItem::operator=( const KFileItem & item ) 00122 { 00123 assign( item ); 00124 return *this; 00125 } 00126 00127 KFileItem::~KFileItem() 00128 { 00129 delete d; 00130 } 00131 00132 void KFileItem::init( bool _determineMimeTypeOnDemand ) 00133 { 00134 m_access = TQString::null; 00135 m_size = (KIO::filesize_t) -1; 00136 // metaInfo = KFileMetaInfo(); 00137 for ( int i = 0; i < NumFlags; i++ ) 00138 m_time[i] = (time_t) -1; 00139 00140 // determine mode and/or permissions if unknown 00141 if ( m_fileMode == KFileItem::Unknown || m_permissions == KFileItem::Unknown ) 00142 { 00143 mode_t mode = 0; 00144 if ( m_url.isLocalFile() ) 00145 { 00146 /* directories may not have a slash at the end if 00147 * we want to stat() them; it requires that we 00148 * change into it .. which may not be allowed 00149 * stat("/is/unaccessible") -> rwx------ 00150 * stat("/is/unaccessible/") -> EPERM H.Z. 00151 * This is the reason for the -1 00152 */ 00153 KDE_struct_stat buf; 00154 TQCString path = TQFile::encodeName(m_url.path( -1 )); 00155 if ( KDE_lstat( path.data(), &buf ) == 0 ) 00156 { 00157 mode = buf.st_mode; 00158 if ( S_ISLNK( mode ) ) 00159 { 00160 m_bLink = true; 00161 if ( KDE_stat( path.data(), &buf ) == 0 ) 00162 mode = buf.st_mode; 00163 else // link pointing to nowhere (see kio/file/file.cc) 00164 mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO; 00165 } 00166 // While we're at it, store the times 00167 m_time[ Modification ] = buf.st_mtime; 00168 m_time[ Access ] = buf.st_atime; 00169 if ( m_fileMode == KFileItem::Unknown ) 00170 m_fileMode = mode & S_IFMT; // extract file type 00171 if ( m_permissions == KFileItem::Unknown ) 00172 m_permissions = mode & 07777; // extract permissions 00173 } 00174 } 00175 } 00176 00177 // determine the mimetype 00178 if (!m_pMimeType && !m_url.isEmpty()) 00179 { 00180 bool accurate = false; 00181 bool isLocalURL; 00182 KURL url = mostLocalURL(isLocalURL); 00183 00184 m_pMimeType = KMimeType::findByURL( url, m_fileMode, isLocalURL, 00185 // use fast mode if not mimetype on demand 00186 _determineMimeTypeOnDemand, &accurate ); 00187 //kdDebug() << "finding mimetype for " << url.url() << " : " << m_pMimeType->name() << endl; 00188 // if we didn't use fast mode, or if we got a result, then this is the mimetype 00189 // otherwise, determineMimeType will be able to do better. 00190 m_bMimeTypeKnown = (!_determineMimeTypeOnDemand) || accurate; 00191 } 00192 } 00193 00194 void KFileItem::readUDSEntry( bool _urlIsDirectory ) 00195 { 00196 // extract the mode and the filename from the KIO::UDS Entry 00197 bool UDS_URL_seen = false; 00198 00199 if (&m_entry == NULL) return; 00200 00201 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00202 for( ; it != m_entry.end(); ++it ) { 00203 switch ((*it).m_uds) { 00204 00205 case KIO::UDS_FILE_TYPE: 00206 m_fileMode = (mode_t)((*it).m_long); 00207 break; 00208 00209 case KIO::UDS_ACCESS: 00210 m_permissions = (mode_t)((*it).m_long); 00211 break; 00212 00213 case KIO::UDS_USER: 00214 m_user = ((*it).m_str); 00215 break; 00216 00217 case KIO::UDS_GROUP: 00218 m_group = ((*it).m_str); 00219 break; 00220 00221 case KIO::UDS_NAME: 00222 m_strName = (*it).m_str; 00223 m_strText = KIO::decodeFileName( m_strName ); 00224 break; 00225 00226 case KIO::UDS_URL: 00227 UDS_URL_seen = true; 00228 m_url = KURL((*it).m_str); 00229 if ( m_url.isLocalFile() ) 00230 m_bIsLocalURL = true; 00231 break; 00232 00233 case KIO::UDS_MIME_TYPE: 00234 m_pMimeType = KMimeType::mimeType((*it).m_str); 00235 m_bMimeTypeKnown = true; 00236 break; 00237 00238 case KIO::UDS_GUESSED_MIME_TYPE: 00239 m_guessedMimeType = (*it).m_str; 00240 break; 00241 00242 case KIO::UDS_LINK_DEST: 00243 m_bLink = !(*it).m_str.isEmpty(); // we don't store the link dest 00244 break; 00245 00246 case KIO::UDS_ICON_NAME: 00247 if ( !d ) { 00248 d = new KFileItemPrivate(); 00249 } 00250 d->iconName = (*it).m_str; 00251 break; 00252 00253 case KIO::UDS_HIDDEN: 00254 if ( (*it).m_long ) 00255 m_hidden = Hidden; 00256 else 00257 m_hidden = Shown; 00258 break; 00259 } 00260 } 00261 00262 // avoid creating these QStrings again and again 00263 static const TQString& dot = KGlobal::staticQString("."); 00264 if ( _urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != dot ) 00265 m_url.addPath( m_strName ); 00266 } 00267 00268 void KFileItem::refresh() 00269 { 00270 m_fileMode = KFileItem::Unknown; 00271 m_permissions = KFileItem::Unknown; 00272 m_pMimeType = 0L; 00273 m_user = TQString::null; 00274 m_group = TQString::null; 00275 m_metaInfo = KFileMetaInfo(); 00276 m_hidden = Auto; 00277 00278 // Basically, we can't trust any information we got while listing. 00279 // Everything could have changed... 00280 // Clearing m_entry makes it possible to detect changes in the size of the file, 00281 // the time information, etc. 00282 m_entry = KIO::UDSEntry(); 00283 init( false ); 00284 } 00285 00286 void KFileItem::refreshMimeType() 00287 { 00288 if ( d ) { 00289 d->iconName = TQString::null; 00290 d->comment = TQString::null; 00291 d->commentCached = false; 00292 } 00293 m_pMimeType = 0L; 00294 init( false ); // Will determine the mimetype 00295 } 00296 00297 void KFileItem::setURL( const KURL &url ) 00298 { 00299 m_url = url; 00300 setName( url.fileName() ); 00301 } 00302 00303 void KFileItem::setName( const TQString& name ) 00304 { 00305 m_strName = name; 00306 m_strText = KIO::decodeFileName( m_strName ); 00307 } 00308 00309 TQString KFileItem::linkDest() const 00310 { 00311 if (&m_entry == NULL) return TQString::null; 00312 00313 // Extract it from the KIO::UDSEntry 00314 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00315 for( ; it != m_entry.end(); ++it ) 00316 if ( (*it).m_uds == KIO::UDS_LINK_DEST ) 00317 return (*it).m_str; 00318 // If not in the KIO::UDSEntry, or if UDSEntry empty, use readlink() [if local URL] 00319 if ( m_bIsLocalURL ) 00320 { 00321 char buf[1000]; 00322 int n = readlink( TQFile::encodeName(m_url.path( -1 )), buf, sizeof(buf)-1 ); 00323 if ( n != -1 ) 00324 { 00325 buf[ n ] = 0; 00326 return TQFile::decodeName( buf ); 00327 } 00328 } 00329 return TQString::null; 00330 } 00331 00332 TQString KFileItem::localPath() const 00333 { 00334 if ( m_bIsLocalURL ) 00335 { 00336 return m_url.path(); 00337 } 00338 else 00339 { 00340 if (&m_entry == NULL) return TQString::null; 00341 00342 // Extract the local path from the KIO::UDSEntry 00343 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00344 const KIO::UDSEntry::ConstIterator end = m_entry.end(); 00345 for( ; it != end; ++it ) 00346 if ( (*it).m_uds == KIO::UDS_LOCAL_PATH ) 00347 return (*it).m_str; 00348 } 00349 00350 return TQString::null; 00351 } 00352 00353 KIO::filesize_t KFileItem::size(bool &exists) const 00354 { 00355 exists = true; 00356 if ( m_size != (KIO::filesize_t) -1 ) 00357 return m_size; 00358 00359 if (&m_entry == NULL) return 0L; 00360 00361 // Extract it from the KIO::UDSEntry 00362 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00363 for( ; it != m_entry.end(); ++it ) 00364 if ( (*it).m_uds == KIO::UDS_SIZE ) { 00365 m_size = (*it).m_long; 00366 return m_size; 00367 } 00368 // If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL] 00369 if ( m_bIsLocalURL ) 00370 { 00371 KDE_struct_stat buf; 00372 if ( KDE_stat( TQFile::encodeName(m_url.path( -1 )), &buf ) == 0 ) 00373 return buf.st_size; 00374 } 00375 exists = false; 00376 return 0L; 00377 } 00378 00379 bool KFileItem::hasExtendedACL() const 00380 { 00381 if (&m_entry == NULL) return false; 00382 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00383 for( ; it != m_entry.end(); it++ ) 00384 if ( (*it).m_uds == KIO::UDS_EXTENDED_ACL ) { 00385 return true; 00386 } 00387 return false; 00388 } 00389 00390 KACL KFileItem::ACL() const 00391 { 00392 if ( hasExtendedACL() ) { 00393 if (&m_entry == NULL) return KACL( m_permissions ); 00394 00395 // Extract it from the KIO::UDSEntry 00396 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00397 for( ; it != m_entry.end(); ++it ) 00398 if ( (*it).m_uds == KIO::UDS_ACL_STRING ) 00399 return KACL((*it).m_str); 00400 } 00401 // create one from the basic permissions 00402 return KACL( m_permissions ); 00403 } 00404 00405 KACL KFileItem::defaultACL() const 00406 { 00407 if (&m_entry == NULL) return KACL(); 00408 00409 // Extract it from the KIO::UDSEntry 00410 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00411 for( ; it != m_entry.end(); ++it ) 00412 if ( (*it).m_uds == KIO::UDS_DEFAULT_ACL_STRING ) 00413 return KACL((*it).m_str); 00414 return KACL(); 00415 } 00416 00417 KIO::filesize_t KFileItem::size() const 00418 { 00419 bool exists; 00420 return size(exists); 00421 } 00422 00423 time_t KFileItem::time( unsigned int which ) const 00424 { 00425 bool hasTime; 00426 return time(which, hasTime); 00427 } 00428 time_t KFileItem::time( unsigned int which, bool &hasTime ) const 00429 { 00430 hasTime = true; 00431 unsigned int mappedWhich = 0; 00432 00433 switch( which ) { 00434 case KIO::UDS_MODIFICATION_TIME: 00435 mappedWhich = Modification; 00436 break; 00437 case KIO::UDS_ACCESS_TIME: 00438 mappedWhich = Access; 00439 break; 00440 case KIO::UDS_CREATION_TIME: 00441 mappedWhich = Creation; 00442 break; 00443 } 00444 00445 if ( m_time[mappedWhich] != (time_t) -1 ) 00446 return m_time[mappedWhich]; 00447 00448 if (&m_entry == NULL) return static_cast<time_t>(0); 00449 00450 // Extract it from the KIO::UDSEntry 00451 KIO::UDSEntry::ConstIterator it = m_entry.begin(); 00452 for( ; it != m_entry.end(); ++it ) 00453 if ( (*it).m_uds == which ) { 00454 m_time[mappedWhich] = static_cast<time_t>((*it).m_long); 00455 return m_time[mappedWhich]; 00456 } 00457 00458 // If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL] 00459 if ( m_bIsLocalURL ) 00460 { 00461 KDE_struct_stat buf; 00462 if ( KDE_stat( TQFile::encodeName(m_url.path(-1)), &buf ) == 0 ) 00463 { 00464 if(which == KIO::UDS_CREATION_TIME) { 00465 // We can't determine creation time for local files 00466 hasTime = false; 00467 m_time[mappedWhich] = static_cast<time_t>(0); 00468 return m_time[mappedWhich]; 00469 } 00470 m_time[mappedWhich] = (which == KIO::UDS_MODIFICATION_TIME) ? 00471 buf.st_mtime : 00472 /* which == KIO::UDS_ACCESS_TIME)*/ 00473 buf.st_atime; 00474 return m_time[mappedWhich]; 00475 } 00476 } 00477 hasTime = false; 00478 return static_cast<time_t>(0); 00479 } 00480 00481 00482 TQString KFileItem::user() const 00483 { 00484 if ( m_user.isEmpty() && m_bIsLocalURL ) 00485 { 00486 KDE_struct_stat buff; 00487 if ( KDE_lstat( TQFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of the link, if it's a link 00488 { 00489 struct passwd *user = getpwuid( buff.st_uid ); 00490 if ( user != 0L ) 00491 m_user = TQString::fromLocal8Bit(user->pw_name); 00492 } 00493 } 00494 return m_user; 00495 } 00496 00497 TQString KFileItem::group() const 00498 { 00499 #ifdef Q_OS_UNIX 00500 if (m_group.isEmpty() && m_bIsLocalURL ) 00501 { 00502 KDE_struct_stat buff; 00503 if ( KDE_lstat( TQFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of the link, if it's a link 00504 { 00505 struct group *ge = getgrgid( buff.st_gid ); 00506 if ( ge != 0L ) { 00507 m_group = TQString::fromLocal8Bit(ge->gr_name); 00508 if (m_group.isEmpty()) 00509 m_group.sprintf("%d",ge->gr_gid); 00510 } else 00511 m_group.sprintf("%d",buff.st_gid); 00512 } 00513 } 00514 #endif 00515 return m_group; 00516 } 00517 00518 TQString KFileItem::mimetype() const 00519 { 00520 KFileItem * that = const_cast<KFileItem *>(this); 00521 return that->determineMimeType()->name(); 00522 } 00523 00524 TQString KFileItem::mimetypeFast() const 00525 { 00526 if (isMimeTypeKnown()) { 00527 return mimetype(); 00528 } 00529 else { 00530 return m_pMimeType->name(); 00531 } 00532 } 00533 00534 KMimeType::Ptr KFileItem::mimeTypePtrFast() 00535 { 00536 return m_pMimeType; 00537 } 00538 00539 KMimeType::Ptr KFileItem::determineMimeType() 00540 { 00541 if ( !m_pMimeType || !m_bMimeTypeKnown ) 00542 { 00543 bool isLocalURL; 00544 KURL url = mostLocalURL(isLocalURL); 00545 00546 m_pMimeType = KMimeType::findByURL( url, m_fileMode, isLocalURL ); 00547 //kdDebug() << "finding mimetype for " << url.url() << " : " << m_pMimeType->name() << endl; 00548 m_bMimeTypeKnown = true; 00549 } 00550 00551 return m_pMimeType; 00552 } 00553 00554 bool KFileItem::isMimeTypeKnown() const 00555 { 00556 // The mimetype isn't known if determineMimeType was never called (on-demand determination) 00557 // or if this fileitem has a guessed mimetype (e.g. ftp symlink) - in which case 00558 // it always remains "not fully determined" 00559 return m_bMimeTypeKnown && m_guessedMimeType.isEmpty(); 00560 } 00561 00562 TQString KFileItem::mimeComment() 00563 { 00564 if (d && (d->commentCached)) return d->comment; 00565 00566 KMimeType::Ptr mType = determineMimeType(); 00567 00568 bool isLocalURL; 00569 KURL url = mostLocalURL(isLocalURL); 00570 00571 TQString comment = mType->comment( url, isLocalURL ); 00572 //kdDebug() << "finding comment for " << url.url() << " : " << m_pMimeType->name() << endl; 00573 if ( !d ) { 00574 d = new KFileItemPrivate(); 00575 } 00576 if (!comment.isEmpty()) { 00577 d->comment = comment; 00578 d->commentCached = true; 00579 } 00580 else { 00581 d->comment = mType->name(); 00582 d->commentCached = true; 00583 } 00584 00585 return d->comment; 00586 } 00587 00588 TQString KFileItem::iconName() 00589 { 00590 if (d && (!d->iconName.isEmpty())) return d->iconName; 00591 00592 bool isLocalURL; 00593 KURL url = mostLocalURL(isLocalURL); 00594 00595 //kdDebug() << "finding icon for " << url.url() << " : " << m_pMimeType->name() << endl; 00596 return determineMimeType()->icon(url, isLocalURL); 00597 } 00598 00599 int KFileItem::overlays() const 00600 { 00601 int _state = 0; 00602 if ( m_bLink ) 00603 _state |= KIcon::LinkOverlay; 00604 00605 if ( !S_ISDIR( m_fileMode ) // Locked dirs have a special icon, use the overlay for files only 00606 && !isReadable()) 00607 _state |= KIcon::LockOverlay; 00608 00609 if ( isHidden() ) 00610 _state |= KIcon::HiddenOverlay; 00611 00612 if( S_ISDIR( m_fileMode ) && m_bIsLocalURL) 00613 { 00614 if (KSambaShare::instance()->isDirectoryShared( m_url.path() ) || 00615 KNFSShare::instance()->isDirectoryShared( m_url.path() )) 00616 { 00617 //kdDebug()<<"KFileShare::isDirectoryShared : "<<m_url.path()<<endl; 00618 _state |= KIcon::ShareOverlay; 00619 } 00620 } 00621 00622 if ( m_pMimeType->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" ) 00623 _state |= KIcon::ZipOverlay; 00624 return _state; 00625 } 00626 00627 TQPixmap KFileItem::pixmap( int _size, int _state ) const 00628 { 00629 if (d && (!d->iconName.isEmpty())) 00630 return DesktopIcon(d->iconName,_size,_state); 00631 00632 if ( !m_pMimeType ) 00633 { 00634 static const TQString & defaultFolderIcon = 00635 KGlobal::staticQString(KMimeType::mimeType( "inode/directory" )->KServiceType::icon()); 00636 00637 if ( S_ISDIR( m_fileMode ) ) 00638 return DesktopIcon( defaultFolderIcon, _size, _state ); 00639 00640 return DesktopIcon( "unknown", _size, _state ); 00641 } 00642 00643 _state |= overlays(); 00644 00645 KMimeType::Ptr mime; 00646 // Use guessed mimetype if the main one hasn't been determined for sure 00647 if ( !m_bMimeTypeKnown && !m_guessedMimeType.isEmpty() ) 00648 mime = KMimeType::mimeType( m_guessedMimeType ); 00649 else 00650 mime = m_pMimeType; 00651 00652 // Support for gzipped files: extract mimetype of contained file 00653 // See also the relevant code in overlays, which adds the zip overlay. 00654 if ( mime->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" ) 00655 { 00656 KURL sf; 00657 sf.setPath( m_url.path().left( m_url.path().length() - 3 ) ); 00658 //kdDebug() << "KFileItem::pixmap subFileName=" << subFileName << endl; 00659 mime = KMimeType::findByURL( sf, 0, m_bIsLocalURL ); 00660 } 00661 00662 bool isLocalURL; 00663 KURL url = mostLocalURL(isLocalURL); 00664 00665 TQPixmap p = mime->pixmap( url, KIcon::Desktop, _size, _state ); 00666 //kdDebug() << "finding pixmap for " << url.url() << " : " << mime->name() << endl; 00667 if (p.isNull()) 00668 kdWarning() << "Pixmap not found for mimetype " << m_pMimeType->name() << endl; 00669 00670 return p; 00671 } 00672 00673 bool KFileItem::isReadable() const 00674 { 00675 /* 00676 struct passwd * user = getpwuid( geteuid() ); 00677 bool isMyFile = (TQString::fromLocal8Bit(user->pw_name) == m_user); 00678 // This gets ugly for the group.... 00679 // Maybe we want a static TQString for the user and a static QStringList 00680 // for the groups... then we need to handle the deletion properly... 00681 */ 00682 00683 if ( m_permissions != KFileItem::Unknown ) { 00684 // No read permission at all 00685 if ( !(S_IRUSR & m_permissions) && !(S_IRGRP & m_permissions) && !(S_IROTH & m_permissions) ) 00686 return false; 00687 00688 // Read permissions for all: save a stat call 00689 if ( (S_IRUSR|S_IRGRP|S_IROTH) & m_permissions ) 00690 return true; 00691 } 00692 00693 // Or if we can't read it [using ::access()] - not network transparent 00694 if ( m_bIsLocalURL && ::access( TQFile::encodeName(m_url.path()), R_OK ) == -1 ) 00695 return false; 00696 00697 return true; 00698 } 00699 00700 bool KFileItem::isWritable() const 00701 { 00702 /* 00703 struct passwd * user = getpwuid( geteuid() ); 00704 bool isMyFile = (TQString::fromLocal8Bit(user->pw_name) == m_user); 00705 // This gets ugly for the group.... 00706 // Maybe we want a static TQString for the user and a static QStringList 00707 // for the groups... then we need to handle the deletion properly... 00708 */ 00709 00710 if ( m_permissions != KFileItem::Unknown ) { 00711 // No write permission at all 00712 if ( !(S_IWUSR & m_permissions) && !(S_IWGRP & m_permissions) && !(S_IWOTH & m_permissions) ) 00713 return false; 00714 } 00715 00716 // Or if we can't read it [using ::access()] - not network transparent 00717 if ( m_bIsLocalURL && ::access( TQFile::encodeName(m_url.path()), W_OK ) == -1 ) 00718 return false; 00719 00720 return true; 00721 } 00722 00723 bool KFileItem::isHidden() const 00724 { 00725 if ( m_hidden != Auto ) 00726 return m_hidden == Hidden; 00727 00728 if ( !m_url.isEmpty() ) 00729 return m_url.fileName()[0] == '.'; 00730 else // should never happen 00731 return m_strName[0] == '.'; 00732 } 00733 00734 bool KFileItem::isDir() const 00735 { 00736 if ( m_fileMode == KFileItem::Unknown ) 00737 { 00738 kdDebug() << " KFileItem::isDir can't say -> false " << endl; 00739 return false; // can't say for sure, so no 00740 } 00741 return (S_ISDIR(m_fileMode)); 00742 /* 00743 if (!S_ISDIR(m_fileMode)) { 00744 if (m_url.isLocalFile()) { 00745 KMimeType::Ptr ptr=KMimeType::findByURL(m_url,0,true,true); 00746 if ((ptr!=0) && (ptr->is("directory/inode"))) return true; 00747 } 00748 return false 00749 } else return true;*/ 00750 } 00751 00752 bool KFileItem::acceptsDrops() 00753 { 00754 // A directory ? 00755 if ( S_ISDIR( mode() ) ) { 00756 return isWritable(); 00757 } 00758 00759 // But only local .desktop files and executables 00760 if ( !m_bIsLocalURL ) 00761 return false; 00762 00763 if (( mimetype() == "application/x-desktop") || 00764 ( mimetype() == "media/builtin-mydocuments") || 00765 ( mimetype() == "media/builtin-mycomputer") || 00766 ( mimetype() == "media/builtin-mynetworkplaces") || 00767 ( mimetype() == "media/builtin-printers") || 00768 ( mimetype() == "media/builtin-trash") || 00769 ( mimetype() == "media/builtin-webbrowser")) 00770 return true; 00771 00772 // Executable, shell script ... ? 00773 if ( ::access( TQFile::encodeName(m_url.path()), X_OK ) == 0 ) 00774 return true; 00775 00776 return false; 00777 } 00778 00779 TQString KFileItem::getStatusBarInfo() 00780 { 00781 TQString text = m_strText; 00782 00783 if ( m_bLink ) 00784 { 00785 if ( !d ) { 00786 d = new KFileItemPrivate(); 00787 } 00788 if (!d->commentCached) { 00789 d->comment = determineMimeType()->comment( m_url, m_bIsLocalURL ); 00790 d->commentCached = true; 00791 } 00792 TQString tmp; 00793 if ( d->comment.isEmpty() ) 00794 tmp = i18n ( "Symbolic Link" ); 00795 else 00796 tmp = i18n("%1 (Link)").arg(d->comment); 00797 text += "->"; 00798 text += linkDest(); 00799 text += " "; 00800 text += tmp; 00801 } 00802 else if ( S_ISREG( m_fileMode ) ) 00803 { 00804 bool hasSize; 00805 KIO::filesize_t sizeValue = size(hasSize); 00806 if(hasSize) 00807 text += TQString(" (%1) ").arg( KIO::convertSize( sizeValue ) ); 00808 text += mimeComment(); 00809 } 00810 else if ( S_ISDIR ( m_fileMode ) ) 00811 { 00812 text += "/ "; 00813 text += mimeComment(); 00814 } 00815 else 00816 { 00817 text += " "; 00818 text += mimeComment(); 00819 } 00820 text.replace('\n', " "); // replace any newlines with a space, so the statusbar doesn't get a two-line string which messes the display up, Alex 00821 return text; 00822 } 00823 00824 TQString KFileItem::getToolTipText(int maxcount) 00825 { 00826 // we can return TQString::null if no tool tip should be shown 00827 TQString tip; 00828 KFileMetaInfo info = metaInfo(); 00829 00830 // the font tags are a workaround for the fact that the tool tip gets 00831 // screwed if the color scheme uses white as default text color 00832 const char* start = "<tr><td><nobr><font color=\"black\">"; 00833 const char* mid = "</font></nobr></td><td><nobr><font color=\"black\">"; 00834 const char* end = "</font></nobr></td></tr>"; 00835 00836 tip = "<table cellspacing=0 cellpadding=0>"; 00837 00838 tip += start + i18n("Name:") + mid + text() + end; 00839 tip += start + i18n("Type:") + mid; 00840 00841 TQString type = TQStyleSheet::escape(mimeComment()); 00842 if ( m_bLink ) { 00843 tip += i18n("Link to %1 (%2)").arg(linkDest(), type) + end; 00844 } else 00845 tip += type + end; 00846 00847 if ( !S_ISDIR ( m_fileMode ) ) { 00848 bool hasSize; 00849 KIO::filesize_t sizeValue = size(hasSize); 00850 if(hasSize) 00851 tip += start + i18n("Size:") + mid + 00852 KIO::convertSizeWithBytes(sizeValue) + end; 00853 } 00854 TQString timeStr = timeString( KIO::UDS_MODIFICATION_TIME); 00855 if(!timeStr.isEmpty()) 00856 tip += start + i18n("Modified:") + mid + 00857 timeStr + end; 00858 #ifndef Q_WS_WIN //TODO: show win32-specific permissions 00859 TQString userStr = user(); 00860 TQString groupStr = group(); 00861 if(!userStr.isEmpty() || !groupStr.isEmpty()) 00862 tip += start + i18n("Owner:") + mid + userStr + " - " + groupStr + end + 00863 start + i18n("Permissions:") + mid + 00864 parsePermissions(m_permissions) + end; 00865 #endif 00866 00867 if (info.isValid() && !info.isEmpty() ) 00868 { 00869 tip += "<tr><td colspan=2><center><s> </s></center></td></tr>"; 00870 TQStringList keys = info.preferredKeys(); 00871 00872 // now the rest 00873 TQStringList::Iterator it = keys.begin(); 00874 for (int count = 0; count<maxcount && it!=keys.end() ; ++it) 00875 { 00876 KFileMetaInfoItem item = info.item( *it ); 00877 if ( item.isValid() ) 00878 { 00879 TQString s = item.string(); 00880 if ( ( item.attributes() & KFileMimeTypeInfo::SqueezeText ) 00881 && s.length() > 50) { 00882 s.truncate(47); 00883 s.append("..."); 00884 } 00885 if ( !s.isEmpty() ) 00886 { 00887 count++; 00888 tip += start + 00889 TQStyleSheet::escape( item.translatedKey() ) + ":" + 00890 mid + 00891 TQStyleSheet::escape( s ) + 00892 end; 00893 } 00894 00895 } 00896 } 00897 } 00898 tip += "</table>"; 00899 00900 //kdDebug() << "making this the tool tip rich text:\n"; 00901 //kdDebug() << tip << endl; 00902 00903 return tip; 00904 } 00905 00906 void KFileItem::run() 00907 { 00908 // It might be faster to pass skip that when we know the mimetype, 00909 // and just call KRun::runURL. But then we need to use mostLocalURL() 00910 // for application/x-desktop files, to be able to execute them. 00911 (void) new KRun( m_url, m_fileMode, m_bIsLocalURL ); 00912 } 00913 00914 bool KFileItem::cmp( const KFileItem & item ) 00915 { 00916 bool hasSize1,hasSize2,hasTime1,hasTime2; 00917 hasSize1 = hasSize2 = hasTime1 = hasTime2 = false; 00918 return ( m_strName == item.m_strName 00919 && m_bIsLocalURL == item.m_bIsLocalURL 00920 && m_fileMode == item.m_fileMode 00921 && m_permissions == item.m_permissions 00922 && m_user == item.m_user 00923 && m_group == item.m_group 00924 && m_bLink == item.m_bLink 00925 && m_hidden == item.m_hidden 00926 && size(hasSize1) == item.size(hasSize2) 00927 && hasSize1 == hasSize2 00928 && time(KIO::UDS_MODIFICATION_TIME, hasTime1) == item.time(KIO::UDS_MODIFICATION_TIME, hasTime2) 00929 && hasTime1 == hasTime2 00930 && (!d || !item.d || d->iconName == item.d->iconName) ); 00931 00932 // Don't compare the mimetypes here. They might not be known, and we don't want to 00933 // do the slow operation of determining them here. 00934 } 00935 00936 void KFileItem::assign( const KFileItem & item ) 00937 { 00938 if ( this == &item ) 00939 return; 00940 m_entry = item.m_entry; 00941 m_url = item.m_url; 00942 m_bIsLocalURL = item.m_bIsLocalURL; 00943 m_strName = item.m_strName; 00944 m_strText = item.m_strText; 00945 m_fileMode = item.m_fileMode; 00946 m_permissions = item.m_permissions; 00947 m_user = item.m_user; 00948 m_group = item.m_group; 00949 m_bLink = item.m_bLink; 00950 m_pMimeType = item.m_pMimeType; 00951 m_strLowerCaseName = item.m_strLowerCaseName; 00952 m_bMimeTypeKnown = item.m_bMimeTypeKnown; 00953 m_hidden = item.m_hidden; 00954 m_guessedMimeType = item.m_guessedMimeType; 00955 m_access = item.m_access; 00956 m_metaInfo = item.m_metaInfo; 00957 for ( int i = 0; i < NumFlags; i++ ) 00958 m_time[i] = item.m_time[i]; 00959 m_size = item.m_size; 00960 // note: m_extra is NOT copied, as we'd have no control over who is 00961 // deleting the data or not. 00962 00963 // We had a mimetype previously (probably), so we need to re-determine it 00964 determineMimeType(); 00965 00966 if ( item.d ) { 00967 if ( !d ) { 00968 d = new KFileItemPrivate; 00969 } 00970 d->iconName = item.d->iconName; 00971 } else { 00972 delete d; 00973 d = 0; 00974 } 00975 } 00976 00977 void KFileItem::setUDSEntry( const KIO::UDSEntry& _entry, const KURL& _url, 00978 bool _determineMimeTypeOnDemand, bool _urlIsDirectory ) 00979 { 00980 m_entry = _entry; 00981 m_url = _url; 00982 m_strName = TQString::null; 00983 m_strText = TQString::null; 00984 m_user = TQString::null; 00985 m_group = TQString::null; 00986 m_strLowerCaseName = TQString::null; 00987 m_pMimeType = 0; 00988 m_fileMode = KFileItem::Unknown; 00989 m_permissions = KFileItem::Unknown; 00990 m_bMarked = false; 00991 m_bLink = false; 00992 m_bIsLocalURL = _url.isLocalFile(); 00993 m_bMimeTypeKnown = false; 00994 m_hidden = Auto; 00995 m_guessedMimeType = TQString::null; 00996 m_metaInfo = KFileMetaInfo(); 00997 00998 if ( d ) { 00999 d->iconName = TQString::null; 01000 d->comment = TQString::null; 01001 d->commentCached = false; 01002 } 01003 01004 readUDSEntry( _urlIsDirectory ); 01005 init( _determineMimeTypeOnDemand ); 01006 } 01007 01008 void KFileItem::setFileMode( mode_t m ) 01009 { 01010 m_fileMode = m; 01011 } 01012 01013 void KFileItem::setMimeType( const TQString& mimetype ) 01014 { 01015 m_pMimeType = KMimeType::mimeType( mimetype ); 01016 } 01017 01018 void KFileItem::setExtraData( const void *key, void *value ) 01019 { 01020 if ( !key ) 01021 return; 01022 01023 m_extra.replace( key, value ); 01024 } 01025 01026 const void * KFileItem::extraData( const void *key ) const 01027 { 01028 TQMapConstIterator<const void*,void*> it = m_extra.find( key ); 01029 if ( it != m_extra.end() ) 01030 return it.data(); 01031 return 0L; 01032 } 01033 01034 void * KFileItem::extraData( const void *key ) 01035 { 01036 TQMapIterator<const void*,void*> it = m_extra.find( key ); 01037 if ( it != m_extra.end() ) 01038 return it.data(); 01039 return 0L; 01040 } 01041 01042 void KFileItem::removeExtraData( const void *key ) 01043 { 01044 m_extra.remove( key ); 01045 } 01046 01047 TQString KFileItem::permissionsString() const 01048 { 01049 if (m_access.isNull()) 01050 m_access = parsePermissions( m_permissions ); 01051 01052 return m_access; 01053 } 01054 01055 TQString KFileItem::parsePermissions(mode_t perm) const 01056 { 01057 char p[] = "---------- "; 01058 01059 if (isDir()) 01060 p[0]='d'; 01061 else if (isLink()) 01062 p[0]='l'; 01063 01064 if (perm & TQFileInfo::ReadUser) 01065 p[1]='r'; 01066 if (perm & TQFileInfo::WriteUser) 01067 p[2]='w'; 01068 if ((perm & TQFileInfo::ExeUser) && !(perm & S_ISUID)) p[3]='x'; 01069 else if ((perm & TQFileInfo::ExeUser) && (perm & S_ISUID)) p[3]='s'; 01070 else if (!(perm & TQFileInfo::ExeUser) && (perm & S_ISUID)) p[3]='S'; 01071 01072 if (perm & TQFileInfo::ReadGroup) 01073 p[4]='r'; 01074 if (perm & TQFileInfo::WriteGroup) 01075 p[5]='w'; 01076 if ((perm & TQFileInfo::ExeGroup) && !(perm & S_ISGID)) p[6]='x'; 01077 else if ((perm & TQFileInfo::ExeGroup) && (perm & S_ISGID)) p[6]='s'; 01078 else if (!(perm & TQFileInfo::ExeGroup) && (perm & S_ISGID)) p[6]='S'; 01079 01080 if (perm & TQFileInfo::ReadOther) 01081 p[7]='r'; 01082 if (perm & TQFileInfo::WriteOther) 01083 p[8]='w'; 01084 if ((perm & TQFileInfo::ExeOther) && !(perm & S_ISVTX)) p[9]='x'; 01085 else if ((perm & TQFileInfo::ExeOther) && (perm & S_ISVTX)) p[9]='t'; 01086 else if (!(perm & TQFileInfo::ExeOther) && (perm & S_ISVTX)) p[9]='T'; 01087 01088 if (hasExtendedACL()) 01089 p[10]='+'; 01090 01091 return TQString::fromLatin1(p); 01092 } 01093 01094 // check if we need to cache this 01095 TQString KFileItem::timeString( unsigned int which ) const 01096 { 01097 bool hasTime; 01098 time_t time_ = time(which, hasTime); 01099 if(!hasTime) return TQString::null; 01100 01101 TQDateTime t; 01102 t.setTime_t( time_); 01103 return KGlobal::locale()->formatDateTime( t ); 01104 } 01105 01106 void KFileItem::setMetaInfo( const KFileMetaInfo & info ) 01107 { 01108 m_metaInfo = info; 01109 } 01110 01111 const KFileMetaInfo & KFileItem::metaInfo(bool autoget, int) const 01112 { 01113 bool isLocalURL; 01114 KURL url = mostLocalURL(isLocalURL); 01115 01116 if ( autoget && !m_metaInfo.isValid() && 01117 KGlobalSettings::showFilePreview(url) ) 01118 { 01119 m_metaInfo = KFileMetaInfo( url, mimetype() ); 01120 } 01121 01122 return m_metaInfo; 01123 } 01124 01125 KURL KFileItem::mostLocalURL(bool &local) const 01126 { 01127 TQString local_path = localPath(); 01128 01129 if ( !local_path.isEmpty() ) 01130 { 01131 local = true; 01132 KURL url; 01133 url.setPath(local_path); 01134 return url; 01135 } 01136 else 01137 { 01138 local = m_bIsLocalURL; 01139 return m_url; 01140 } 01141 } 01142 01143 void KFileItem::virtual_hook( int, void* ) 01144 { /*BASE::virtual_hook( id, data );*/ } 01145 01146 TQDataStream & operator<< ( TQDataStream & s, const KFileItem & a ) 01147 { 01148 // We don't need to save/restore anything that refresh() invalidates, 01149 // since that means we can re-determine those by ourselves. 01150 s << a.m_url; 01151 s << a.m_strName; 01152 s << a.m_strText; 01153 return s; 01154 } 01155 01156 TQDataStream & operator>> ( TQDataStream & s, KFileItem & a ) 01157 { 01158 s >> a.m_url; 01159 s >> a.m_strName; 01160 s >> a.m_strText; 01161 a.m_bIsLocalURL = a.m_url.isLocalFile(); 01162 a.m_bMimeTypeKnown = false; 01163 a.refresh(); 01164 return s; 01165 }