summaryrefslogtreecommitdiffstats
path: root/kio/kio/previewjob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kio/kio/previewjob.cpp')
-rw-r--r--kio/kio/previewjob.cpp597
1 files changed, 0 insertions, 597 deletions
diff --git a/kio/kio/previewjob.cpp b/kio/kio/previewjob.cpp
deleted file mode 100644
index de4800ab1..000000000
--- a/kio/kio/previewjob.cpp
+++ /dev/null
@@ -1,597 +0,0 @@
-// -*- c++ -*-
-// vim: ts=4 sw=4 et
-/* This file is part of the KDE libraries
- Copyright (C) 2000 David Faure <faure@kde.org>
- 2000 Carsten Pfeiffer <pfeiffer@kde.org>
- 2001 Malte Starostik <malte.starostik@t-online.de>
-
- 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.
-*/
-
-#include "previewjob.h"
-
-#include <sys/stat.h>
-#ifdef __FreeBSD__
- #include <machine/param.h>
-#endif
-#include <sys/types.h>
-
-#ifdef Q_OS_UNIX
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif
-
-#include <tqdir.h>
-#include <tqfile.h>
-#include <tqimage.h>
-#include <tqtimer.h>
-#include <tqregexp.h>
-
-#include <kdatastream.h> // Do not remove, needed for correct bool serialization
-#include <kfileitem.h>
-#include <kapplication.h>
-#include <ktempfile.h>
-#include <ktrader.h>
-#include <kmdcodec.h>
-#include <kglobal.h>
-#include <kstandarddirs.h>
-
-#include <kio/kservice.h>
-
-#include "previewjob.moc"
-
-namespace TDEIO { struct PreviewItem; }
-using namespace TDEIO;
-
-struct TDEIO::PreviewItem
-{
- KFileItem *item;
- KService::Ptr plugin;
-};
-
-struct TDEIO::PreviewJobPrivate
-{
- enum { STATE_STATORIG, // if the thumbnail exists
- STATE_GETORIG, // if we create it
- STATE_CREATETHUMB // thumbnail:/ slave
- } state;
- KFileItemList initialItems;
- const TQStringList *enabledPlugins;
- // Our todo list :)
- TQValueList<PreviewItem> items;
- // The current item
- PreviewItem currentItem;
- // The modification time of that URL
- time_t tOrig;
- // Path to thumbnail cache for the current size
- TQString thumbPath;
- // Original URL of current item in TMS format
- // (file:///path/to/file instead of file:/path/to/file)
- TQString origName;
- // Thumbnail file name for current item
- TQString thumbName;
- // Size of thumbnail
- int width;
- int height;
- // Unscaled size of thumbnail (128 or 256 if cache is enabled)
- int cacheWidth;
- int cacheHeight;
- // Whether the thumbnail should be scaled
- bool bScale;
- // Whether we should save the thumbnail
- bool bSave;
- // If the file to create a thumb for was a temp file, this is its name
- TQString tempName;
- // Over that, it's too much
- unsigned long maximumSize;
- // the size for the icon overlay
- int iconSize;
- // the transparency of the blended mimetype icon
- int iconAlpha;
- // Shared memory segment Id. The segment is allocated to a size
- // of extent x extent x 4 (32 bit image) on first need.
- int shmid;
- // And the data area
- uchar *shmaddr;
- // Delete the KFileItems when done?
- bool deleteItems;
- bool succeeded;
- // Root of thumbnail cache
- TQString thumbRoot;
- bool ignoreMaximumSize;
- TQTimer startPreviewTimer;
-};
-
-PreviewJob::PreviewJob( const KFileItemList &items, int width, int height,
- int iconSize, int iconAlpha, bool scale, bool save,
- const TQStringList *enabledPlugins, bool deleteItems )
- : TDEIO::Job( false /* no GUI */ )
-{
- d = new PreviewJobPrivate;
- d->tOrig = 0;
- d->shmid = -1;
- d->shmaddr = 0;
- d->initialItems = items;
- d->enabledPlugins = enabledPlugins;
- d->width = width;
- d->height = height ? height : width;
- d->cacheWidth = d->width;
- d->cacheHeight = d->height;
- d->iconSize = iconSize;
- d->iconAlpha = iconAlpha;
- d->deleteItems = deleteItems;
- d->bScale = scale;
- d->bSave = save && scale;
- d->succeeded = false;
- d->currentItem.item = 0;
- d->thumbRoot = TQDir::homeDirPath() + "/.thumbnails/";
- d->ignoreMaximumSize = false;
-
- // Return to event loop first, determineNextFile() might delete this;
- connect(&d->startPreviewTimer, TQT_SIGNAL(timeout()), TQT_SLOT(startPreview()) );
- d->startPreviewTimer.start(0, true);
-}
-
-PreviewJob::~PreviewJob()
-{
-#ifdef Q_OS_UNIX
- if (d->shmaddr) {
- shmdt((char*)d->shmaddr);
- shmctl(d->shmid, IPC_RMID, 0);
- }
-#endif
- delete d;
-}
-
-void PreviewJob::startPreview()
-{
- // Load the list of plugins to determine which mimetypes are supported
- KTrader::OfferList plugins = KTrader::self()->query("ThumbCreator");
- TQMap<TQString, KService::Ptr> mimeMap;
-
- for (KTrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
- if (!d->enabledPlugins || d->enabledPlugins->contains((*it)->desktopEntryName()))
- {
- TQStringList mimeTypes = (*it)->property("MimeTypes").toStringList();
- for (TQStringList::ConstIterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt)
- mimeMap.insert(*mt, *it);
- }
-
- // Look for images and store the items in our todo list :)
- bool bNeedCache = false;
- for (KFileItemListIterator it(d->initialItems); it.current(); ++it )
- {
- PreviewItem item;
- item.item = it.current();
- TQMap<TQString, KService::Ptr>::ConstIterator plugin = mimeMap.find(it.current()->mimetype());
- if (plugin == mimeMap.end()
- && (it.current()->mimetype() != "application/x-desktop")
- && (it.current()->mimetype() != "media/builtin-mydocuments")
- && (it.current()->mimetype() != "media/builtin-mycomputer")
- && (it.current()->mimetype() != "media/builtin-mynetworkplaces")
- && (it.current()->mimetype() != "media/builtin-printers")
- && (it.current()->mimetype() != "media/builtin-trash")
- && (it.current()->mimetype() != "media/builtin-webbrowser"))
- {
- TQString mimeType = it.current()->mimetype();
- plugin = mimeMap.find(mimeType.replace(TQRegExp("/.*"), "/*"));
-
- if (plugin == mimeMap.end())
- {
- // check mime type inheritance
- KMimeType::Ptr mimeInfo = KMimeType::mimeType(it.current()->mimetype());
- TQString parentMimeType = mimeInfo->parentMimeType();
- while (!parentMimeType.isEmpty())
- {
- plugin = mimeMap.find(parentMimeType);
- if (plugin != mimeMap.end()) break;
-
- KMimeType::Ptr parentMimeInfo = KMimeType::mimeType(parentMimeType);
- if (!parentMimeInfo) break;
-
- parentMimeType = parentMimeInfo->parentMimeType();
- }
- }
-
- if (plugin == mimeMap.end())
- {
- // check X-TDE-Text property
- KMimeType::Ptr mimeInfo = KMimeType::mimeType(it.current()->mimetype());
- TQVariant textProperty = mimeInfo->property("X-TDE-text");
- if (textProperty.isValid() && textProperty.type() == TQVariant::Bool)
- {
- if (textProperty.toBool())
- {
- plugin = mimeMap.find("text/plain");
- if (plugin == mimeMap.end())
- {
- plugin = mimeMap.find( "text/*" );
- }
- }
- }
- }
- }
-
- if (plugin != mimeMap.end())
- {
- item.plugin = *plugin;
- d->items.append(item);
- if (!bNeedCache && d->bSave &&
- (it.current()->url().protocol() != "file" ||
- !it.current()->url().directory( false ).startsWith(d->thumbRoot)) &&
- (*plugin)->property("CacheThumbnail").toBool())
- bNeedCache = true;
- }
- else
- {
- emitFailed(it.current());
- if (d->deleteItems)
- delete it.current();
- }
- }
-
- // Read configuration value for the maximum allowed size
- TDEConfig * config = TDEGlobal::config();
- TDEConfigGroupSaver cgs( config, "PreviewSettings" );
- d->maximumSize = config->readNumEntry( "MaximumSize", 1024*1024 /* 1MB */ );
-
- if (bNeedCache)
- {
- if (d->width <= 128 && d->height <= 128) d->cacheWidth = d->cacheHeight = 128;
- else d->cacheWidth = d->cacheHeight = 256;
- d->thumbPath = d->thumbRoot + (d->cacheWidth == 128 ? "normal/" : "large/");
- KStandardDirs::makeDir(d->thumbPath, 0700);
- }
- else
- d->bSave = false;
- determineNextFile();
-}
-
-void PreviewJob::removeItem( const KFileItem *item )
-{
- for (TQValueList<PreviewItem>::Iterator it = d->items.begin(); it != d->items.end(); ++it)
- if ((*it).item == item)
- {
- d->items.remove(it);
- break;
- }
-
- if (d->currentItem.item == item)
- {
- subjobs.first()->kill();
- subjobs.removeFirst();
- determineNextFile();
- }
-}
-
-void PreviewJob::setIgnoreMaximumSize(bool ignoreSize)
-{
- d->ignoreMaximumSize = ignoreSize;
-}
-
-void PreviewJob::determineNextFile()
-{
- if (d->currentItem.item)
- {
- if (!d->succeeded)
- emitFailed();
- if (d->deleteItems) {
- delete d->currentItem.item;
- d->currentItem.item = 0L;
- }
- }
- // No more items ?
- if ( d->items.isEmpty() )
- {
- emitResult();
- return;
- }
- else
- {
- // First, stat the orig file
- d->state = PreviewJobPrivate::STATE_STATORIG;
- d->currentItem = d->items.first();
- d->succeeded = false;
- d->items.remove(d->items.begin());
- TDEIO::Job *job = TDEIO::stat( d->currentItem.item->url(), false );
- job->addMetaData( "no-auth-prompt", "true" );
- addSubjob(job);
- }
-}
-
-void PreviewJob::slotResult( TDEIO::Job *job )
-{
- subjobs.remove( job );
- Q_ASSERT ( subjobs.isEmpty() ); // We should have only one job at a time ...
- switch ( d->state )
- {
- case PreviewJobPrivate::STATE_STATORIG:
- {
- if (job->error()) // that's no good news...
- {
- // Drop this one and move on to the next one
- determineNextFile();
- return;
- }
- TDEIO::UDSEntry entry = ((TDEIO::StatJob*)job)->statResult();
- TDEIO::UDSEntry::ConstIterator it = entry.begin();
- d->tOrig = 0;
- int found = 0;
- for( ; it != entry.end() && found < 2; it++ )
- {
- if ( (*it).m_uds == TDEIO::UDS_MODIFICATION_TIME )
- {
- d->tOrig = (time_t)((*it).m_long);
- found++;
- }
- else if ( (*it).m_uds == TDEIO::UDS_SIZE )
- {
- if ( filesize_t((*it).m_long) > d->maximumSize &&
- !d->ignoreMaximumSize &&
- !d->currentItem.plugin->property("IgnoreMaximumSize").toBool() )
- {
- determineNextFile();
- return;
- }
- found++;
- }
- }
-
- if ( !d->currentItem.plugin->property( "CacheThumbnail" ).toBool() )
- {
- // This preview will not be cached, no need to look for a saved thumbnail
- // Just create it, and be done
- getOrCreateThumbnail();
- return;
- }
-
- if ( statResultThumbnail() )
- return;
-
- getOrCreateThumbnail();
- return;
- }
- case PreviewJobPrivate::STATE_GETORIG:
- {
- if (job->error())
- {
- determineNextFile();
- return;
- }
-
- createThumbnail( static_cast<TDEIO::FileCopyJob*>(job)->destURL().path() );
- return;
- }
- case PreviewJobPrivate::STATE_CREATETHUMB:
- {
- if (!d->tempName.isEmpty())
- {
- TQFile::remove(d->tempName);
- d->tempName = TQString::null;
- }
- determineNextFile();
- return;
- }
- }
-}
-
-bool PreviewJob::statResultThumbnail()
-{
- if ( d->thumbPath.isEmpty() )
- return false;
-
- KURL url = d->currentItem.item->url();
- // Don't include the password if any
- url.setPass(TQString::null);
- // The TMS defines local files as file:///path/to/file instead of KDE's
- // way (file:/path/to/file)
-#ifdef KURL_TRIPLE_SLASH_FILE_PROT
- d->origName = url.url();
-#else
- if (url.protocol() == "file") d->origName = "file://" + url.path();
- else d->origName = url.url();
-#endif
-
- KMD5 md5( TQFile::encodeName( d->origName ).data() );
- d->thumbName = TQFile::encodeName( md5.hexDigest() ) + ".png";
-
- TQImage thumb;
- if ( !thumb.load( d->thumbPath + d->thumbName ) ) return false;
-
- if ( thumb.text( "Thumb::URI", 0 ) != d->origName ||
- thumb.text( "Thumb::MTime", 0 ).toInt() != d->tOrig ) return false;
-
- // Found it, use it
- emitPreview( thumb );
- d->succeeded = true;
- determineNextFile();
- return true;
-}
-
-
-void PreviewJob::getOrCreateThumbnail()
-{
- // We still need to load the orig file ! (This is getting tedious) :)
- const KFileItem* item = d->currentItem.item;
- const TQString localPath = item->localPath();
- if ( !localPath.isEmpty() )
- createThumbnail( localPath );
- else
- {
- d->state = PreviewJobPrivate::STATE_GETORIG;
- KTempFile localFile;
- KURL localURL;
- localURL.setPath( d->tempName = localFile.name() );
- const KURL currentURL = item->url();
- TDEIO::Job * job = TDEIO::file_copy( currentURL, localURL, -1, true,
- false, false /* No GUI */ );
- job->addMetaData("thumbnail","1");
- addSubjob(job);
- }
-}
-
-// KDE 4: Make it const TQString &
-void PreviewJob::createThumbnail( TQString pixPath )
-{
- d->state = PreviewJobPrivate::STATE_CREATETHUMB;
- KURL thumbURL;
- thumbURL.setProtocol("thumbnail");
- thumbURL.setPath(pixPath);
- TDEIO::TransferJob *job = TDEIO::get(thumbURL, false, false);
- addSubjob(job);
- connect(job, TQT_SIGNAL(data(TDEIO::Job *, const TQByteArray &)), TQT_SLOT(slotThumbData(TDEIO::Job *, const TQByteArray &)));
- bool save = d->bSave && d->currentItem.plugin->property("CacheThumbnail").toBool();
- job->addMetaData("mimeType", d->currentItem.item->mimetype());
- job->addMetaData("width", TQString().setNum(save ? d->cacheWidth : d->width));
- job->addMetaData("height", TQString().setNum(save ? d->cacheHeight : d->height));
- job->addMetaData("iconSize", TQString().setNum(save ? 64 : d->iconSize));
- job->addMetaData("iconAlpha", TQString().setNum(d->iconAlpha));
- job->addMetaData("plugin", d->currentItem.plugin->library());
-#ifdef Q_OS_UNIX
- if (d->shmid == -1)
- {
- if (d->shmaddr) {
- shmdt((char*)d->shmaddr);
- shmctl(d->shmid, IPC_RMID, 0);
- }
- d->shmid = shmget(IPC_PRIVATE, d->cacheWidth * d->cacheHeight * 4, IPC_CREAT|0600);
- if (d->shmid != -1)
- {
- d->shmaddr = (uchar *)(shmat(d->shmid, 0, SHM_RDONLY));
- if (d->shmaddr == (uchar *)-1)
- {
- shmctl(d->shmid, IPC_RMID, 0);
- d->shmaddr = 0;
- d->shmid = -1;
- }
- }
- else
- d->shmaddr = 0;
- }
- if (d->shmid != -1)
- job->addMetaData("shmid", TQString().setNum(d->shmid));
-#endif
-}
-
-void PreviewJob::slotThumbData(TDEIO::Job *, const TQByteArray &data)
-{
- bool save = d->bSave &&
- d->currentItem.plugin->property("CacheThumbnail").toBool() &&
- (d->currentItem.item->url().protocol() != "file" ||
- !d->currentItem.item->url().directory( false ).startsWith(d->thumbRoot));
- TQImage thumb;
-#ifdef Q_OS_UNIX
- if (d->shmaddr)
- {
- TQDataStream str(data, IO_ReadOnly);
- int width, height, depth;
- bool alpha;
- str >> width >> height >> depth >> alpha;
- thumb = TQImage(d->shmaddr, width, height, depth, 0, 0, TQImage::IgnoreEndian);
- thumb.setAlphaBuffer(alpha);
- }
- else
-#endif
- thumb.loadFromData(data);
-
- if (save)
- {
- thumb.setText("Thumb::URI", 0, d->origName);
- thumb.setText("Thumb::MTime", 0, TQString::number(d->tOrig));
- thumb.setText("Thumb::Size", 0, number(d->currentItem.item->size()));
- thumb.setText("Thumb::Mimetype", 0, d->currentItem.item->mimetype());
- thumb.setText("Software", 0, "KDE Thumbnail Generator");
- KTempFile temp(d->thumbPath + "kde-tmp-", ".png");
- if (temp.status() == 0) //Only try to write out the thumbnail if we
- { //actually created the temp file.
- thumb.save(temp.name(), "PNG");
- rename(TQFile::encodeName(temp.name()), TQFile::encodeName(d->thumbPath + d->thumbName));
- }
- }
- emitPreview( thumb );
- d->succeeded = true;
-}
-
-void PreviewJob::emitPreview(const TQImage &thumb)
-{
- TQPixmap pix;
- if (thumb.width() > d->width || thumb.height() > d->height)
- {
- double imgRatio = (double)thumb.height() / (double)thumb.width();
- if (imgRatio > (double)d->height / (double)d->width)
- pix.convertFromImage(
- thumb.smoothScale((int)TQMAX((double)d->height / imgRatio, 1), d->height));
- else pix.convertFromImage(
- thumb.smoothScale(d->width, (int)TQMAX((double)d->width * imgRatio, 1)));
- }
- else pix.convertFromImage(thumb);
- emit gotPreview(d->currentItem.item, pix);
-}
-
-void PreviewJob::emitFailed(const KFileItem *item)
-{
- if (!item)
- item = d->currentItem.item;
- emit failed(item);
-}
-
-TQStringList PreviewJob::availablePlugins()
-{
- TQStringList result;
- KTrader::OfferList plugins = KTrader::self()->query("ThumbCreator");
- for (KTrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
- if (!result.contains((*it)->desktopEntryName()))
- result.append((*it)->desktopEntryName());
- return result;
-}
-
-TQStringList PreviewJob::supportedMimeTypes()
-{
- TQStringList result;
- KTrader::OfferList plugins = KTrader::self()->query("ThumbCreator");
- for (KTrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
- result += (*it)->property("MimeTypes").toStringList();
- return result;
-}
-
-void PreviewJob::kill( bool quietly )
-{
- d->startPreviewTimer.stop();
- Job::kill( quietly );
-}
-
-PreviewJob *TDEIO::filePreview( const KFileItemList &items, int width, int height,
- int iconSize, int iconAlpha, bool scale, bool save,
- const TQStringList *enabledPlugins )
-{
- return new PreviewJob(items, width, height, iconSize, iconAlpha,
- scale, save, enabledPlugins);
-}
-
-PreviewJob *TDEIO::filePreview( const KURL::List &items, int width, int height,
- int iconSize, int iconAlpha, bool scale, bool save,
- const TQStringList *enabledPlugins )
-{
- KFileItemList fileItems;
- for (KURL::List::ConstIterator it = items.begin(); it != items.end(); ++it)
- fileItems.append(new KFileItem(KFileItem::Unknown, KFileItem::Unknown, *it, true));
- return new PreviewJob(fileItems, width, height, iconSize, iconAlpha,
- scale, save, enabledPlugins, true);
-}
-
-void PreviewJob::virtual_hook( int id, void* data )
-{ TDEIO::Job::virtual_hook( id, data ); }
-