You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/tdeio/tdeio/tdefileitem.cpp

1203 lines
33 KiB

/* This file is part of the KDE project
Copyright (C) 1999 David Faure <faure@kde.org>
2001 Carsten Pfeiffer <pfeiffer@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
// $Id$
#include <config.h>
#include <sys/time.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <assert.h>
#include <unistd.h>
#include "tdefileitem.h"
#include <tqdir.h>
#include <tqfile.h>
#include <tqmap.h>
#include <tqstylesheet.h>
#include <tqimage.h>
#include <kdebug.h>
#include <tdefilemetainfo.h>
#include <ksambashare.h>
#include <knfsshare.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kiconloader.h>
#include <klargefile.h>
#include <klocale.h>
#include <kmimetype.h>
#include <krun.h>
#ifdef HAVE_ELFICON
#include "tdelficon.h"
#endif // HAVE_ELFICON
class KFileItem::KFileItemPrivate {
public:
TQString iconName;
};
KFileItem::KFileItem( const TDEIO::UDSEntry& _entry, const KURL& _url,
bool _determineMimeTypeOnDemand, bool _urlIsDirectory ) :
m_entry( _entry ),
m_url( _url ),
m_pMimeType( 0 ),
m_fileMode( KFileItem::Unknown ),
m_permissions( KFileItem::Unknown ),
m_bMarked( false ),
m_bLink( false ),
m_bIsLocalURL( _url.isLocalFile() ),
m_bMimeTypeKnown( false ),
m_hidden( Auto ),
d(0)
{
readUDSEntry( _urlIsDirectory );
init( _determineMimeTypeOnDemand );
}
KFileItem::KFileItem( mode_t _mode, mode_t _permissions, const KURL& _url, bool _determineMimeTypeOnDemand ) :
m_entry(), // warning !
m_url( _url ),
m_strName( _url.fileName() ),
m_strText( TDEIO::decodeFileName( m_strName ) ),
m_pMimeType( 0 ),
m_fileMode ( _mode ),
m_permissions( _permissions ),
m_bMarked( false ),
m_bLink( false ),
m_bIsLocalURL( _url.isLocalFile() ),
m_bMimeTypeKnown( false ),
m_hidden( Auto ),
d(0)
{
init( _determineMimeTypeOnDemand );
}
KFileItem::KFileItem( const KURL &url, const TQString &mimeType, mode_t mode )
: m_url( url ),
m_strName( url.fileName() ),
m_strText( TDEIO::decodeFileName( m_strName ) ),
m_pMimeType( 0 ),
m_fileMode( mode ),
m_permissions( KFileItem::Unknown ),
m_bMarked( false ),
m_bLink( false ),
m_bIsLocalURL( url.isLocalFile() ),
m_bMimeTypeKnown( !mimeType.isEmpty() ),
m_hidden( Auto ),
d(0)
{
if (m_bMimeTypeKnown)
m_pMimeType = KMimeType::mimeType( mimeType );
init( false );
}
KFileItem::KFileItem( const KFileItem & item ) :
d(0)
{
assign( item );
}
KFileItem& KFileItem::operator=( const KFileItem & item )
{
assign( item );
return *this;
}
KFileItem::~KFileItem()
{
delete d;
}
void KFileItem::init( bool _determineMimeTypeOnDemand )
{
m_access = TQString::null;
m_size = (TDEIO::filesize_t) -1;
// metaInfo = KFileMetaInfo();
for ( int i = 0; i < NumFlags; i++ )
m_time[i] = (time_t) -1;
// determine mode and/or permissions if unknown
if ( m_fileMode == KFileItem::Unknown || m_permissions == KFileItem::Unknown )
{
mode_t mode = 0;
if ( m_url.isLocalFile() )
{
/* directories may not have a slash at the end if
* we want to stat() them; it requires that we
* change into it .. which may not be allowed
* stat("/is/unaccessible") -> rwx------
* stat("/is/unaccessible/") -> EPERM H.Z.
* This is the reason for the -1
*/
KDE_struct_stat buf;
TQCString path = TQFile::encodeName(m_url.path( -1 ));
if ( KDE_lstat( path.data(), &buf ) == 0 )
{
mode = buf.st_mode;
if ( S_ISLNK( mode ) )
{
m_bLink = true;
if ( KDE_stat( path.data(), &buf ) == 0 )
mode = buf.st_mode;
else // link pointing to nowhere (see tdeio/file/file.cc)
mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO;
}
// While we're at it, store the times
m_time[ Modification ] = buf.st_mtime;
m_time[ Access ] = buf.st_atime;
if ( m_fileMode == KFileItem::Unknown )
m_fileMode = mode & S_IFMT; // extract file type
if ( m_permissions == KFileItem::Unknown )
m_permissions = mode & 07777; // extract permissions
}
}
}
// determine the mimetype
if (!m_pMimeType && !m_url.isEmpty())
{
bool accurate = false;
bool isLocalURL;
KURL url = mostLocalURL(isLocalURL);
m_pMimeType = KMimeType::findByURL( url, m_fileMode, isLocalURL,
// use fast mode if not mimetype on demand
_determineMimeTypeOnDemand, &accurate );
//kdDebug() << "finding mimetype for " << url.url() << " : " << m_pMimeType->name() << endl;
// if we didn't use fast mode, or if we got a result, then this is the mimetype
// otherwise, determineMimeType will be able to do better.
m_bMimeTypeKnown = (!_determineMimeTypeOnDemand) || accurate;
}
}
void KFileItem::readUDSEntry( bool _urlIsDirectory )
{
// extract the mode and the filename from the TDEIO::UDS Entry
bool UDS_URL_seen = false;
if (&m_entry == NULL) return;
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); ++it ) {
switch ((*it).m_uds) {
case TDEIO::UDS_FILE_TYPE:
m_fileMode = (mode_t)((*it).m_long);
break;
case TDEIO::UDS_ACCESS:
m_permissions = (mode_t)((*it).m_long);
break;
case TDEIO::UDS_USER:
m_user = ((*it).m_str);
break;
case TDEIO::UDS_GROUP:
m_group = ((*it).m_str);
break;
case TDEIO::UDS_NAME:
m_strName = (*it).m_str;
m_strText = TDEIO::decodeFileName( m_strName );
break;
case TDEIO::UDS_URL:
UDS_URL_seen = true;
m_url = KURL((*it).m_str);
if ( m_url.isLocalFile() )
m_bIsLocalURL = true;
break;
case TDEIO::UDS_MIME_TYPE:
m_pMimeType = KMimeType::mimeType((*it).m_str);
m_bMimeTypeKnown = true;
break;
case TDEIO::UDS_GUESSED_MIME_TYPE:
m_guessedMimeType = (*it).m_str;
break;
case TDEIO::UDS_LINK_DEST:
m_bLink = !(*it).m_str.isEmpty(); // we don't store the link dest
break;
case TDEIO::UDS_ICON_NAME:
if ( !d )
d = new KFileItemPrivate();
d->iconName = (*it).m_str;
break;
case TDEIO::UDS_HIDDEN:
if ( (*it).m_long )
m_hidden = Hidden;
else
m_hidden = Shown;
break;
}
}
// avoid creating these QStrings again and again
static const TQString& dot = TDEGlobal::staticQString(".");
if ( _urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != dot )
m_url.addPath( m_strName );
}
void KFileItem::refresh()
{
m_fileMode = KFileItem::Unknown;
m_permissions = KFileItem::Unknown;
m_pMimeType = 0L;
m_user = TQString::null;
m_group = TQString::null;
m_metaInfo = KFileMetaInfo();
m_hidden = Auto;
// Basically, we can't trust any information we got while listing.
// Everything could have changed...
// Clearing m_entry makes it possible to detect changes in the size of the file,
// the time information, etc.
m_entry = TDEIO::UDSEntry();
init( false );
}
void KFileItem::refreshMimeType()
{
m_pMimeType = 0L;
init( false ); // Will determine the mimetype
}
void KFileItem::setURL( const KURL &url )
{
m_url = url;
setName( url.fileName() );
}
void KFileItem::setName( const TQString& name )
{
m_strName = name;
m_strText = TDEIO::decodeFileName( m_strName );
}
TQString KFileItem::linkDest() const
{
if (&m_entry == NULL) return TQString::null;
// Extract it from the TDEIO::UDSEntry
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); ++it )
if ( (*it).m_uds == TDEIO::UDS_LINK_DEST )
return (*it).m_str;
// If not in the TDEIO::UDSEntry, or if UDSEntry empty, use readlink() [if local URL]
if ( m_bIsLocalURL )
{
char buf[1000];
int n = readlink( TQFile::encodeName(m_url.path( -1 )), buf, sizeof(buf)-1 );
if ( n != -1 )
{
buf[ n ] = 0;
return TQFile::decodeName( buf );
}
}
return TQString::null;
}
TQString KFileItem::localPath() const
{
if ( m_bIsLocalURL )
{
return m_url.path();
}
else
{
if (&m_entry == NULL) return TQString::null;
// Extract the local path from the TDEIO::UDSEntry
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
const TDEIO::UDSEntry::ConstIterator end = m_entry.end();
for( ; it != end; ++it )
if ( (*it).m_uds == TDEIO::UDS_LOCAL_PATH )
return (*it).m_str;
}
return TQString::null;
}
TDEIO::filesize_t KFileItem::size(bool &exists) const
{
exists = true;
if ( m_size != (TDEIO::filesize_t) -1 )
return m_size;
if (&m_entry == NULL) return 0L;
// Extract it from the TDEIO::UDSEntry
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); ++it )
if ( (*it).m_uds == TDEIO::UDS_SIZE ) {
m_size = (*it).m_long;
return m_size;
}
// If not in the TDEIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL]
if ( m_bIsLocalURL )
{
KDE_struct_stat buf;
if ( KDE_stat( TQFile::encodeName(m_url.path( -1 )), &buf ) == 0 )
return buf.st_size;
}
exists = false;
return 0L;
}
bool KFileItem::hasExtendedACL() const
{
if (&m_entry == NULL) return false;
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); it++ )
if ( (*it).m_uds == TDEIO::UDS_EXTENDED_ACL ) {
return true;
}
return false;
}
KACL KFileItem::ACL() const
{
if ( hasExtendedACL() ) {
if (&m_entry == NULL) return KACL( m_permissions );
// Extract it from the TDEIO::UDSEntry
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); ++it )
if ( (*it).m_uds == TDEIO::UDS_ACL_STRING )
return KACL((*it).m_str);
}
// create one from the basic permissions
return KACL( m_permissions );
}
KACL KFileItem::defaultACL() const
{
if (&m_entry == NULL) return KACL();
// Extract it from the TDEIO::UDSEntry
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); ++it )
if ( (*it).m_uds == TDEIO::UDS_DEFAULT_ACL_STRING )
return KACL((*it).m_str);
return KACL();
}
TDEIO::filesize_t KFileItem::size() const
{
bool exists;
return size(exists);
}
time_t KFileItem::time( unsigned int which ) const
{
bool hasTime;
return time(which, hasTime);
}
time_t KFileItem::time( unsigned int which, bool &hasTime ) const
{
hasTime = true;
unsigned int mappedWhich = 0;
switch( which ) {
case TDEIO::UDS_MODIFICATION_TIME:
mappedWhich = Modification;
break;
case TDEIO::UDS_ACCESS_TIME:
mappedWhich = Access;
break;
case TDEIO::UDS_CREATION_TIME:
mappedWhich = Creation;
break;
}
if ( m_time[mappedWhich] != (time_t) -1 )
return m_time[mappedWhich];
if (&m_entry == NULL) return static_cast<time_t>(0);
// Extract it from the TDEIO::UDSEntry
TDEIO::UDSEntry::ConstIterator it = m_entry.begin();
for( ; it != m_entry.end(); ++it )
if ( (*it).m_uds == which ) {
m_time[mappedWhich] = static_cast<time_t>((*it).m_long);
return m_time[mappedWhich];
}
// If not in the TDEIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL]
if ( m_bIsLocalURL )
{
KDE_struct_stat buf;
if ( KDE_stat( TQFile::encodeName(m_url.path(-1)), &buf ) == 0 )
{
if(which == TDEIO::UDS_CREATION_TIME) {
// We can't determine creation time for local files
hasTime = false;
m_time[mappedWhich] = static_cast<time_t>(0);
return m_time[mappedWhich];
}
m_time[mappedWhich] = (which == TDEIO::UDS_MODIFICATION_TIME) ?
buf.st_mtime :
/* which == TDEIO::UDS_ACCESS_TIME)*/
buf.st_atime;
return m_time[mappedWhich];
}
}
hasTime = false;
return static_cast<time_t>(0);
}
TQString KFileItem::user() const
{
if ( m_user.isEmpty() && m_bIsLocalURL )
{
KDE_struct_stat buff;
if ( KDE_lstat( TQFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of the link, if it's a link
{
struct passwd *user = getpwuid( buff.st_uid );
if ( user != 0L )
m_user = TQString::fromLocal8Bit(user->pw_name);
}
}
return m_user;
}
TQString KFileItem::group() const
{
#ifdef Q_OS_UNIX
if (m_group.isEmpty() && m_bIsLocalURL )
{
KDE_struct_stat buff;
if ( KDE_lstat( TQFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of the link, if it's a link
{
struct group *ge = getgrgid( buff.st_gid );
if ( ge != 0L ) {
m_group = TQString::fromLocal8Bit(ge->gr_name);
if (m_group.isEmpty())
m_group.sprintf("%d",ge->gr_gid);
} else
m_group.sprintf("%d",buff.st_gid);
}
}
#endif
return m_group;
}
TQString KFileItem::mimetype() const
{
KFileItem * that = const_cast<KFileItem *>(this);
return that->determineMimeType()->name();
}
KMimeType::Ptr KFileItem::determineMimeType()
{
if ( !m_pMimeType || !m_bMimeTypeKnown )
{
bool isLocalURL;
KURL url = mostLocalURL(isLocalURL);
m_pMimeType = KMimeType::findByURL( url, m_fileMode, isLocalURL );
//kdDebug() << "finding mimetype for " << url.url() << " : " << m_pMimeType->name() << endl;
m_bMimeTypeKnown = true;
}
return m_pMimeType;
}
bool KFileItem::isMimeTypeKnown() const
{
// The mimetype isn't known if determineMimeType was never called (on-demand determination)
// or if this fileitem has a guessed mimetype (e.g. ftp symlink) - in which case
// it always remains "not fully determined"
return m_bMimeTypeKnown && m_guessedMimeType.isEmpty();
}
TQString KFileItem::mimeComment()
{
KMimeType::Ptr mType = determineMimeType();
bool isLocalURL;
KURL url = mostLocalURL(isLocalURL);
TQString comment = mType->comment( url, isLocalURL );
//kdDebug() << "finding comment for " << url.url() << " : " << m_pMimeType->name() << endl;
if (!comment.isEmpty())
return comment;
else
return mType->name();
}
TQString KFileItem::iconName()
{
if (d && (!d->iconName.isEmpty())) return d->iconName;
bool isLocalURL;
KURL url = mostLocalURL(isLocalURL);
//kdDebug() << "finding icon for " << url.url() << " : " << m_pMimeType->name() << endl;
return determineMimeType()->icon(url, isLocalURL);
}
int KFileItem::overlays() const
{
int _state = 0;
if ( m_bLink )
_state |= KIcon::LinkOverlay;
if ( !S_ISDIR( m_fileMode ) // Locked dirs have a special icon, use the overlay for files only
&& !isReadable())
_state |= KIcon::LockOverlay;
if ( isHidden() )
_state |= KIcon::HiddenOverlay;
if( S_ISDIR( m_fileMode ) && m_bIsLocalURL)
{
if (KSambaShare::instance()->isDirectoryShared( m_url.path() ) ||
KNFSShare::instance()->isDirectoryShared( m_url.path() ))
{
//kdDebug()<<"KFileShare::isDirectoryShared : "<<m_url.path()<<endl;
_state |= KIcon::ShareOverlay;
}
}
if ( m_pMimeType->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
_state |= KIcon::ZipOverlay;
return _state;
}
TQPixmap KFileItem::pixmap( int _size, int _state ) const
{
if (d && (!d->iconName.isEmpty()))
return DesktopIcon(d->iconName,_size,_state);
if ( !m_pMimeType )
{
static const TQString & defaultFolderIcon =
TDEGlobal::staticQString(KMimeType::mimeType( "inode/directory" )->KServiceType::icon());
if ( S_ISDIR( m_fileMode ) )
return DesktopIcon( defaultFolderIcon, _size, _state );
return DesktopIcon( "unknown", _size, _state );
}
_state |= overlays();
KMimeType::Ptr mime;
// Use guessed mimetype if the main one hasn't been determined for sure
if ( !m_bMimeTypeKnown && !m_guessedMimeType.isEmpty() )
mime = KMimeType::mimeType( m_guessedMimeType );
else
mime = m_pMimeType;
// Support for gzipped files: extract mimetype of contained file
// See also the relevant code in overlays, which adds the zip overlay.
if ( mime->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
{
KURL sf;
sf.setPath( m_url.path().left( m_url.path().length() - 3 ) );
//kdDebug() << "KFileItem::pixmap subFileName=" << subFileName << endl;
mime = KMimeType::findByURL( sf, 0, m_bIsLocalURL );
}
bool isLocalURL;
KURL url = mostLocalURL(isLocalURL);
TQPixmap p = mime->pixmap( url, KIcon::Desktop, _size, _state );
//kdDebug() << "finding pixmap for " << url.url() << " : " << mime->name() << endl;
if (p.isNull())
kdWarning() << "Pixmap not found for mimetype " << m_pMimeType->name() << endl;
if ( mime->name() == "application/x-executable" ) {
// At first glance it might seem to be a good idea to
// look for .desktop files for this executable before resorting to the embedded icon
// in the same fashion as the minicli, but on close examination this is NOT A GOOD IDEA.
// Specifically it allows one executable to mimic another purely based on filename,
// which could at certain times fool any user regardless of experience level.
#ifdef HAVE_ELFICON
// Check for an embedded icon
unsigned int icon_size;
libr_icon *icon = NULL;
libr_file *handle = NULL;
libr_access_t access = LIBR_READ;
if((handle = libr_open(const_cast<char*>(url.path().ascii()), access)) == NULL)
{
kdWarning() << "failed to open file" << url.path() << endl;
return p;
}
icon_size = _size;
icon = libr_icon_geticon_bysize(handle, icon_size);
// See if the embedded icon name matches any icon file names already on the system
// If it does, use the system icon instead of the embedded one
int iconresnamefound = 0;
iconentry *entry = NULL;
iconlist icons;
if(!get_iconlist(handle, &icons))
{
// Failed to obtain a list of ELF icons
kdWarning() << "failed to obtain ELF icon: " << libr_errmsg() << endl;
// See if there is a system icon we can use
TQString sysIconName = elf_get_resource(handle, ".metadata_sysicon");
if (!sysIconName.isEmpty()) {
if (TDEGlobal::iconLoader()->iconPath(sysIconName.ascii(), 0, true) != "") {
p = DesktopIcon( sysIconName.ascii(), _size, _state );
}
}
libr_close(handle);
return p;
}
else {
while((entry = get_nexticon(&icons, entry)) != NULL)
{
if(icon == NULL)
{
// Try loading this icon as fallback
icon = libr_icon_geticon_byname(handle, entry->name);
}
if (TDEGlobal::iconLoader()->iconPath(entry->name, 0, true) != "") {
iconresnamefound = 1;
p = DesktopIcon( entry->name, _size, _state );
break;
}
}
}
if ((iconresnamefound == 0) && (icon)) {
// Extract the embedded icon
size_t icon_data_length;
char* icondata = libr_icon_malloc(icon, &icon_data_length);
p.loadFromData(static_cast<uchar*>(static_cast<void*>(icondata)), icon_data_length); // EVIL CAST
if (icon_size != 0) {
TQImage ip = p.convertToImage();
ip = ip.smoothScale(icon_size, icon_size);
p.convertFromImage(ip);
}
free(icondata);
libr_icon_close(icon);
}
libr_close(handle);
#endif // HAVE_ELFICON
}
return p;
}
bool KFileItem::isReadable() const
{
/*
struct passwd * user = getpwuid( geteuid() );
bool isMyFile = (TQString::fromLocal8Bit(user->pw_name) == m_user);
// This gets ugly for the group....
// Maybe we want a static TQString for the user and a static QStringList
// for the groups... then we need to handle the deletion properly...
*/
if ( m_permissions != KFileItem::Unknown ) {
// No read permission at all
if ( !(S_IRUSR & m_permissions) && !(S_IRGRP & m_permissions) && !(S_IROTH & m_permissions) )
return false;
// Read permissions for all: save a stat call
if ( (S_IRUSR|S_IRGRP|S_IROTH) & m_permissions )
return true;
}
// Or if we can't read it [using ::access()] - not network transparent
if ( m_bIsLocalURL && ::access( TQFile::encodeName(m_url.path()), R_OK ) == -1 )
return false;
return true;
}
bool KFileItem::isWritable() const
{
/*
struct passwd * user = getpwuid( geteuid() );
bool isMyFile = (TQString::fromLocal8Bit(user->pw_name) == m_user);
// This gets ugly for the group....
// Maybe we want a static TQString for the user and a static QStringList
// for the groups... then we need to handle the deletion properly...
*/
if ( m_permissions != KFileItem::Unknown ) {
// No write permission at all
if ( !(S_IWUSR & m_permissions) && !(S_IWGRP & m_permissions) && !(S_IWOTH & m_permissions) )
return false;
}
// Or if we can't read it [using ::access()] - not network transparent
if ( m_bIsLocalURL && ::access( TQFile::encodeName(m_url.path()), W_OK ) == -1 )
return false;
return true;
}
bool KFileItem::isHidden() const
{
if ( m_hidden != Auto )
return m_hidden == Hidden;
if ( !m_url.isEmpty() )
return m_url.fileName()[0] == '.';
else // should never happen
return m_strName[0] == '.';
}
bool KFileItem::isDir() const
{
if ( m_fileMode == KFileItem::Unknown )
{
kdDebug() << " KFileItem::isDir can't say -> false " << endl;
return false; // can't say for sure, so no
}
return (S_ISDIR(m_fileMode));
/*
if (!S_ISDIR(m_fileMode)) {
if (m_url.isLocalFile()) {
KMimeType::Ptr ptr=KMimeType::findByURL(m_url,0,true,true);
if ((ptr!=0) && (ptr->is("directory/inode"))) return true;
}
return false
} else return true;*/
}
bool KFileItem::acceptsDrops()
{
// A directory ?
if ( S_ISDIR( mode() ) ) {
return isWritable();
}
// But only local .desktop files and executables
if ( !m_bIsLocalURL )
return false;
if (( mimetype() == "application/x-desktop") ||
( mimetype() == "media/builtin-mydocuments") ||
( mimetype() == "media/builtin-mycomputer") ||
( mimetype() == "media/builtin-mynetworkplaces") ||
( mimetype() == "media/builtin-printers") ||
( mimetype() == "media/builtin-trash") ||
( mimetype() == "media/builtin-webbrowser"))
return true;
// Executable, shell script ... ?
if ( ::access( TQFile::encodeName(m_url.path()), X_OK ) == 0 )
return true;
return false;
}
TQString KFileItem::getStatusBarInfo()
{
TQString text = m_strText;
if ( m_bLink )
{
TQString comment = determineMimeType()->comment( m_url, m_bIsLocalURL );
TQString tmp;
if ( comment.isEmpty() )
tmp = i18n ( "Symbolic Link" );
else
tmp = i18n("%1 (Link)").arg(comment);
text += "->";
text += linkDest();
text += " ";
text += tmp;
}
else if ( S_ISREG( m_fileMode ) )
{
bool hasSize;
TDEIO::filesize_t sizeValue = size(hasSize);
if(hasSize)
text += TQString(" (%1) ").arg( TDEIO::convertSize( sizeValue ) );
text += mimeComment();
}
else if ( S_ISDIR ( m_fileMode ) )
{
text += "/ ";
text += mimeComment();
}
else
{
text += " ";
text += mimeComment();
}
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
return text;
}
TQString KFileItem::getToolTipText(int maxcount)
{
// we can return TQString::null if no tool tip should be shown
TQString tip;
KFileMetaInfo info = metaInfo();
// the font tags are a workaround for the fact that the tool tip gets
// screwed if the color scheme uses white as default text color
const char* start = "<tr><td><nobr><font color=\"black\">";
const char* mid = "</font></nobr></td><td><nobr><font color=\"black\">";
const char* end = "</font></nobr></td></tr>";
tip = "<table cellspacing=0 cellpadding=0>";
tip += start + i18n("Name:") + mid + text() + end;
tip += start + i18n("Type:") + mid;
TQString type = TQStyleSheet::escape(mimeComment());
if ( m_bLink ) {
tip += i18n("Link to %1 (%2)").arg(linkDest(), type) + end;
} else
tip += type + end;
if ( !S_ISDIR ( m_fileMode ) ) {
bool hasSize;
TDEIO::filesize_t sizeValue = size(hasSize);
if(hasSize)
tip += start + i18n("Size:") + mid +
TDEIO::convertSizeWithBytes(sizeValue) + end;
}
TQString timeStr = timeString( TDEIO::UDS_MODIFICATION_TIME);
if(!timeStr.isEmpty())
tip += start + i18n("Modified:") + mid +
timeStr + end;
#ifndef Q_WS_WIN //TODO: show win32-specific permissions
TQString userStr = user();
TQString groupStr = group();
if(!userStr.isEmpty() || !groupStr.isEmpty())
tip += start + i18n("Owner:") + mid + userStr + " - " + groupStr + end +
start + i18n("Permissions:") + mid +
parsePermissions(m_permissions) + end;
#endif
if (info.isValid() && !info.isEmpty() )
{
tip += "<tr><td colspan=2><center><s>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</s></center></td></tr>";
TQStringList keys = info.preferredKeys();
// now the rest
TQStringList::Iterator it = keys.begin();
for (int count = 0; count<maxcount && it!=keys.end() ; ++it)
{
KFileMetaInfoItem item = info.item( *it );
if ( item.isValid() )
{
TQString s = item.string();
if ( ( item.attributes() & KFileMimeTypeInfo::SqueezeText )
&& s.length() > 50) {
s.truncate(47);
s.append("...");
}
if ( !s.isEmpty() )
{
count++;
tip += start +
TQStyleSheet::escape( item.translatedKey() ) + ":" +
mid +
TQStyleSheet::escape( s ) +
end;
}
}
}
}
tip += "</table>";
//kdDebug() << "making this the tool tip rich text:\n";
//kdDebug() << tip << endl;
return tip;
}
void KFileItem::run()
{
// It might be faster to pass skip that when we know the mimetype,
// and just call KRun::runURL. But then we need to use mostLocalURL()
// for application/x-desktop files, to be able to execute them.
(void) new KRun( m_url, m_fileMode, m_bIsLocalURL );
}
bool KFileItem::cmp( const KFileItem & item )
{
bool hasSize1,hasSize2,hasTime1,hasTime2;
hasSize1 = hasSize2 = hasTime1 = hasTime2 = false;
return ( m_strName == item.m_strName
&& m_bIsLocalURL == item.m_bIsLocalURL
&& m_fileMode == item.m_fileMode
&& m_permissions == item.m_permissions
&& m_user == item.m_user
&& m_group == item.m_group
&& m_bLink == item.m_bLink
&& m_hidden == item.m_hidden
&& size(hasSize1) == item.size(hasSize2)
&& hasSize1 == hasSize2
&& time(TDEIO::UDS_MODIFICATION_TIME, hasTime1) == item.time(TDEIO::UDS_MODIFICATION_TIME, hasTime2)
&& hasTime1 == hasTime2
&& (!d || !item.d || d->iconName == item.d->iconName) );
// Don't compare the mimetypes here. They might not be known, and we don't want to
// do the slow operation of determining them here.
}
void KFileItem::assign( const KFileItem & item )
{
if ( this == &item )
return;
m_entry = item.m_entry;
m_url = item.m_url;
m_bIsLocalURL = item.m_bIsLocalURL;
m_strName = item.m_strName;
m_strText = item.m_strText;
m_fileMode = item.m_fileMode;
m_permissions = item.m_permissions;
m_user = item.m_user;
m_group = item.m_group;
m_bLink = item.m_bLink;
m_pMimeType = item.m_pMimeType;
m_strLowerCaseName = item.m_strLowerCaseName;
m_bMimeTypeKnown = item.m_bMimeTypeKnown;
m_hidden = item.m_hidden;
m_guessedMimeType = item.m_guessedMimeType;
m_access = item.m_access;
m_metaInfo = item.m_metaInfo;
for ( int i = 0; i < NumFlags; i++ )
m_time[i] = item.m_time[i];
m_size = item.m_size;
// note: m_extra is NOT copied, as we'd have no control over who is
// deleting the data or not.
// We had a mimetype previously (probably), so we need to re-determine it
determineMimeType();
if ( item.d ) {
if ( !d )
d = new KFileItemPrivate;
d->iconName = item.d->iconName;
} else {
delete d;
d = 0;
}
}
void KFileItem::setUDSEntry( const TDEIO::UDSEntry& _entry, const KURL& _url,
bool _determineMimeTypeOnDemand, bool _urlIsDirectory )
{
m_entry = _entry;
m_url = _url;
m_strName = TQString::null;
m_strText = TQString::null;
m_user = TQString::null;
m_group = TQString::null;
m_strLowerCaseName = TQString::null;
m_pMimeType = 0;
m_fileMode = KFileItem::Unknown;
m_permissions = KFileItem::Unknown;
m_bMarked = false;
m_bLink = false;
m_bIsLocalURL = _url.isLocalFile();
m_bMimeTypeKnown = false;
m_hidden = Auto;
m_guessedMimeType = TQString::null;
m_metaInfo = KFileMetaInfo();
if ( d )
d->iconName = TQString::null;
readUDSEntry( _urlIsDirectory );
init( _determineMimeTypeOnDemand );
}
void KFileItem::setFileMode( mode_t m )
{
m_fileMode = m;
}
void KFileItem::setMimeType( const TQString& mimetype )
{
m_pMimeType = KMimeType::mimeType( mimetype );
}
void KFileItem::setExtraData( const void *key, void *value )
{
if ( !key )
return;
m_extra.replace( key, value );
}
const void * KFileItem::extraData( const void *key ) const
{
TQMapConstIterator<const void*,void*> it = m_extra.find( key );
if ( it != m_extra.end() )
return it.data();
return 0L;
}
void * KFileItem::extraData( const void *key )
{
TQMapIterator<const void*,void*> it = m_extra.find( key );
if ( it != m_extra.end() )
return it.data();
return 0L;
}
void KFileItem::removeExtraData( const void *key )
{
m_extra.remove( key );
}
TQString KFileItem::permissionsString() const
{
if (m_access.isNull())
m_access = parsePermissions( m_permissions );
return m_access;
}
TQString KFileItem::parsePermissions(mode_t perm) const
{
char p[] = "---------- ";
if (isDir())
p[0]='d';
else if (isLink())
p[0]='l';
if (perm & TQFileInfo::ReadUser)
p[1]='r';
if (perm & TQFileInfo::WriteUser)
p[2]='w';
if ((perm & TQFileInfo::ExeUser) && !(perm & S_ISUID)) p[3]='x';
else if ((perm & TQFileInfo::ExeUser) && (perm & S_ISUID)) p[3]='s';
else if (!(perm & TQFileInfo::ExeUser) && (perm & S_ISUID)) p[3]='S';
if (perm & TQFileInfo::ReadGroup)
p[4]='r';
if (perm & TQFileInfo::WriteGroup)
p[5]='w';
if ((perm & TQFileInfo::ExeGroup) && !(perm & S_ISGID)) p[6]='x';
else if ((perm & TQFileInfo::ExeGroup) && (perm & S_ISGID)) p[6]='s';
else if (!(perm & TQFileInfo::ExeGroup) && (perm & S_ISGID)) p[6]='S';
if (perm & TQFileInfo::ReadOther)
p[7]='r';
if (perm & TQFileInfo::WriteOther)
p[8]='w';
if ((perm & TQFileInfo::ExeOther) && !(perm & S_ISVTX)) p[9]='x';
else if ((perm & TQFileInfo::ExeOther) && (perm & S_ISVTX)) p[9]='t';
else if (!(perm & TQFileInfo::ExeOther) && (perm & S_ISVTX)) p[9]='T';
if (hasExtendedACL())
p[10]='+';
return TQString::fromLatin1(p);
}
// check if we need to cache this
TQString KFileItem::timeString( unsigned int which ) const
{
bool hasTime;
time_t time_ = time(which, hasTime);
if(!hasTime) return TQString::null;
TQDateTime t;
t.setTime_t( time_);
return TDEGlobal::locale()->formatDateTime( t );
}
void KFileItem::setMetaInfo( const KFileMetaInfo & info )
{
m_metaInfo = info;
}
const KFileMetaInfo & KFileItem::metaInfo(bool autoget, int) const
{
bool isLocalURL;
KURL url = mostLocalURL(isLocalURL);
if ( autoget && !m_metaInfo.isValid() &&
TDEGlobalSettings::showFilePreview(url) )
{
m_metaInfo = KFileMetaInfo( url, mimetype() );
}
return m_metaInfo;
}
KURL KFileItem::mostLocalURL(bool &local) const
{
TQString local_path = localPath();
if ( !local_path.isEmpty() )
{
local = true;
KURL url;
url.setPath(local_path);
return url;
}
else
{
local = m_bIsLocalURL;
return m_url;
}
}
void KFileItem::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
TQDataStream & operator<< ( TQDataStream & s, const KFileItem & a )
{
// We don't need to save/restore anything that refresh() invalidates,
// since that means we can re-determine those by ourselves.
s << a.m_url;
s << a.m_strName;
s << a.m_strText;
return s;
}
TQDataStream & operator>> ( TQDataStream & s, KFileItem & a )
{
s >> a.m_url;
s >> a.m_strName;
s >> a.m_strText;
a.m_bIsLocalURL = a.m_url.isLocalFile();
a.m_bMimeTypeKnown = false;
a.refresh();
return s;
}