24 #include "previewjob.h"
28 #include <machine/param.h>
30 #include <sys/types.h>
43 #include <kdatastream.h>
44 #include <kfileitem.h>
45 #include <kapplication.h>
46 #include <ktempfile.h>
50 #include <kstandarddirs.h>
52 #include <kio/kservice.h>
54 #include "previewjob.moc"
56 namespace KIO {
struct PreviewItem; }
59 struct KIO::PreviewItem
65 struct KIO::PreviewJobPrivate
67 enum { STATE_STATORIG,
71 KFileItemList initialItems;
72 const TQStringList *enabledPlugins;
74 TQValueList<PreviewItem> items;
76 PreviewItem currentItem;
99 unsigned long maximumSize;
114 bool ignoreMaximumSize;
115 TQTimer startPreviewTimer;
119 int iconSize,
int iconAlpha,
bool scale,
bool save,
120 const TQStringList *enabledPlugins,
bool deleteItems )
123 d =
new PreviewJobPrivate;
127 d->initialItems = items;
128 d->enabledPlugins = enabledPlugins;
130 d->height = height ? height : width;
131 d->cacheWidth = d->width;
132 d->cacheHeight = d->height;
133 d->iconSize = iconSize;
134 d->iconAlpha = iconAlpha;
135 d->deleteItems = deleteItems;
137 d->bSave = save && scale;
138 d->succeeded =
false;
139 d->currentItem.item = 0;
140 d->thumbRoot = TQDir::homeDirPath() +
"/.thumbnails/";
141 d->ignoreMaximumSize =
false;
144 connect(&d->startPreviewTimer, TQT_SIGNAL(timeout()), TQT_SLOT(startPreview()) );
145 d->startPreviewTimer.start(0,
true);
148 PreviewJob::~PreviewJob()
152 shmdt((
char*)d->shmaddr);
153 shmctl(d->shmid, IPC_RMID, 0);
159 void PreviewJob::startPreview()
163 TQMap<TQString, KService::Ptr> mimeMap;
165 for (KTrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
166 if (!d->enabledPlugins || d->enabledPlugins->contains((*it)->desktopEntryName()))
168 TQStringList mimeTypes = (*it)->property(
"MimeTypes").toStringList();
169 for (TQStringList::ConstIterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt)
170 mimeMap.insert(*mt, *it);
174 bool bNeedCache =
false;
175 for (KFileItemListIterator it(d->initialItems); it.current(); ++it )
178 item.item = it.current();
179 TQMap<TQString, KService::Ptr>::ConstIterator plugin = mimeMap.find(it.current()->mimetype());
180 if (plugin == mimeMap.end()
181 && (it.current()->mimetype() !=
"application/x-desktop")
182 && (it.current()->mimetype() !=
"media/builtin-mydocuments")
183 && (it.current()->mimetype() !=
"media/builtin-mycomputer")
184 && (it.current()->mimetype() !=
"media/builtin-mynetworkplaces")
185 && (it.current()->mimetype() !=
"media/builtin-printers")
186 && (it.current()->mimetype() !=
"media/builtin-trash")
187 && (it.current()->mimetype() !=
"media/builtin-webbrowser"))
189 TQString mimeType = it.current()->mimetype();
190 plugin = mimeMap.find(mimeType.replace(TQRegExp(
"/.*"),
"/*"));
192 if (plugin == mimeMap.end())
196 TQString parentMimeType = mimeInfo->parentMimeType();
197 while (!parentMimeType.isEmpty())
199 plugin = mimeMap.find(parentMimeType);
200 if (plugin != mimeMap.end())
break;
203 if (!parentMimeInfo)
break;
205 parentMimeType = parentMimeInfo->parentMimeType();
209 if (plugin == mimeMap.end())
213 TQVariant textProperty = mimeInfo->property(
"X-KDE-text");
214 if (textProperty.isValid() && textProperty.type() == TQVariant::Bool)
216 if (textProperty.toBool())
218 plugin = mimeMap.find(
"text/plain");
219 if (plugin == mimeMap.end())
221 plugin = mimeMap.find(
"text/*" );
228 if (plugin != mimeMap.end())
230 item.plugin = *plugin;
231 d->items.append(item);
232 if (!bNeedCache && d->bSave &&
233 (it.current()->url().protocol() !=
"file" ||
234 !it.current()->url().directory(
false ).startsWith(d->thumbRoot)) &&
235 (*plugin)->property(
"CacheThumbnail").toBool())
240 emitFailed(it.current());
247 KConfig * config = KGlobal::config();
248 KConfigGroupSaver cgs( config,
"PreviewSettings" );
249 d->maximumSize = config->readNumEntry(
"MaximumSize", 1024*1024 );
253 if (d->width <= 128 && d->height <= 128) d->cacheWidth = d->cacheHeight = 128;
254 else d->cacheWidth = d->cacheHeight = 256;
255 d->thumbPath = d->thumbRoot + (d->cacheWidth == 128 ?
"normal/" :
"large/");
256 KStandardDirs::makeDir(d->thumbPath, 0700);
265 for (TQValueList<PreviewItem>::Iterator it = d->items.begin(); it != d->items.end(); ++it)
266 if ((*it).item == item)
272 if (d->currentItem.item == item)
274 subjobs.first()->kill();
275 subjobs.removeFirst();
282 d->ignoreMaximumSize = ignoreSize;
285 void PreviewJob::determineNextFile()
287 if (d->currentItem.item)
291 if (d->deleteItems) {
292 delete d->currentItem.item;
293 d->currentItem.item = 0L;
297 if ( d->items.isEmpty() )
305 d->state = PreviewJobPrivate::STATE_STATORIG;
306 d->currentItem = d->items.first();
307 d->succeeded =
false;
308 d->items.remove(d->items.begin());
315 void PreviewJob::slotResult(
KIO::Job *job )
317 subjobs.remove( job );
318 Q_ASSERT ( subjobs.isEmpty() );
321 case PreviewJobPrivate::STATE_STATORIG:
330 KIO::UDSEntry::ConstIterator it = entry.begin();
333 for( ; it != entry.end() && found < 2; it++ )
337 d->tOrig = (time_t)((*it).m_long);
342 if (
filesize_t((*it).m_long) > d->maximumSize &&
343 !d->ignoreMaximumSize &&
344 !d->currentItem.plugin->property(
"IgnoreMaximumSize").toBool() )
353 if ( !d->currentItem.plugin->property(
"CacheThumbnail" ).toBool() )
357 getOrCreateThumbnail();
361 if ( statResultThumbnail() )
364 getOrCreateThumbnail();
367 case PreviewJobPrivate::STATE_GETORIG:
375 createThumbnail( static_cast<KIO::FileCopyJob*>(job)->destURL().path() );
378 case PreviewJobPrivate::STATE_CREATETHUMB:
380 if (!d->tempName.isEmpty())
382 TQFile::remove(d->tempName);
383 d->tempName = TQString::null;
391 bool PreviewJob::statResultThumbnail()
393 if ( d->thumbPath.isEmpty() )
396 KURL url = d->currentItem.item->url();
398 url.setPass(TQString::null);
401 #ifdef KURL_TRIPLE_SLASH_FILE_PROT
402 d->origName = url.url();
404 if (url.protocol() ==
"file") d->origName =
"file://" + url.path();
405 else d->origName = url.url();
408 KMD5 md5( TQFile::encodeName( d->origName ).data() );
409 d->thumbName = TQFile::encodeName( md5.hexDigest() ) +
".png";
412 if ( !thumb.load( d->thumbPath + d->thumbName ) )
return false;
414 if ( thumb.text(
"Thumb::URI", 0 ) != d->origName ||
415 thumb.text(
"Thumb::MTime", 0 ).toInt() != d->tOrig )
return false;
418 emitPreview( thumb );
425 void PreviewJob::getOrCreateThumbnail()
428 const KFileItem* item = d->currentItem.item;
429 const TQString localPath = item->
localPath();
430 if ( !localPath.isEmpty() )
431 createThumbnail( localPath );
434 d->state = PreviewJobPrivate::STATE_GETORIG;
437 localURL.setPath( d->tempName = localFile.name() );
438 const KURL currentURL = item->
url();
447 void PreviewJob::createThumbnail( TQString pixPath )
449 d->state = PreviewJobPrivate::STATE_CREATETHUMB;
451 thumbURL.setProtocol(
"thumbnail");
452 thumbURL.setPath(pixPath);
455 connect(job, TQT_SIGNAL(data(
KIO::Job *,
const TQByteArray &)), TQT_SLOT(slotThumbData(
KIO::Job *,
const TQByteArray &)));
456 bool save = d->bSave && d->currentItem.plugin->property(
"CacheThumbnail").toBool();
457 job->
addMetaData(
"mimeType", d->currentItem.item->mimetype());
458 job->
addMetaData(
"width", TQString().setNum(save ? d->cacheWidth : d->width));
459 job->
addMetaData(
"height", TQString().setNum(save ? d->cacheHeight : d->height));
460 job->
addMetaData(
"iconSize", TQString().setNum(save ? 64 : d->iconSize));
461 job->
addMetaData(
"iconAlpha", TQString().setNum(d->iconAlpha));
462 job->
addMetaData(
"plugin", d->currentItem.plugin->library());
467 shmdt((
char*)d->shmaddr);
468 shmctl(d->shmid, IPC_RMID, 0);
470 d->shmid = shmget(IPC_PRIVATE, d->cacheWidth * d->cacheHeight * 4, IPC_CREAT|0600);
473 d->shmaddr = (uchar *)(shmat(d->shmid, 0, SHM_RDONLY));
474 if (d->shmaddr == (uchar *)-1)
476 shmctl(d->shmid, IPC_RMID, 0);
485 job->
addMetaData(
"shmid", TQString().setNum(d->shmid));
489 void PreviewJob::slotThumbData(
KIO::Job *,
const TQByteArray &data)
491 bool save = d->bSave &&
492 d->currentItem.plugin->property(
"CacheThumbnail").toBool() &&
493 (d->currentItem.item->url().protocol() !=
"file" ||
494 !d->currentItem.item->url().directory(
false ).startsWith(d->thumbRoot));
499 TQDataStream str(data, IO_ReadOnly);
500 int width, height, depth;
502 str >> width >> height >> depth >> alpha;
503 thumb = TQImage(d->shmaddr, width, height, depth, 0, 0, TQImage::IgnoreEndian);
504 thumb.setAlphaBuffer(alpha);
508 thumb.loadFromData(data);
512 thumb.setText(
"Thumb::URI", 0, d->origName);
513 thumb.setText(
"Thumb::MTime", 0, TQString::number(d->tOrig));
514 thumb.setText(
"Thumb::Size", 0,
number(d->currentItem.item->size()));
515 thumb.setText(
"Thumb::Mimetype", 0, d->currentItem.item->mimetype());
516 thumb.setText(
"Software", 0,
"KDE Thumbnail Generator");
517 KTempFile temp(d->thumbPath +
"kde-tmp-",
".png");
518 if (temp.status() == 0)
520 thumb.save(temp.name(),
"PNG");
521 rename(TQFile::encodeName(temp.name()), TQFile::encodeName(d->thumbPath + d->thumbName));
524 emitPreview( thumb );
528 void PreviewJob::emitPreview(
const TQImage &thumb)
531 if (thumb.width() > d->width || thumb.height() > d->height)
533 double imgRatio = (double)thumb.height() / (double)thumb.width();
534 if (imgRatio > (
double)d->height / (
double)d->width)
535 pix.convertFromImage(
536 thumb.smoothScale((
int)TQMAX((
double)d->height / imgRatio, 1), d->height));
537 else pix.convertFromImage(
538 thumb.smoothScale(d->width, (
int)TQMAX((
double)d->width * imgRatio, 1)));
540 else pix.convertFromImage(thumb);
544 void PreviewJob::emitFailed(
const KFileItem *item)
547 item = d->currentItem.item;
555 for (KTrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
556 if (!result.contains((*it)->desktopEntryName()))
557 result.append((*it)->desktopEntryName());
565 for (KTrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
566 result += (*it)->property(
"MimeTypes").toStringList();
572 d->startPreviewTimer.stop();
577 int iconSize,
int iconAlpha,
bool scale,
bool save,
578 const TQStringList *enabledPlugins )
580 return new PreviewJob(items, width, height, iconSize, iconAlpha,
581 scale, save, enabledPlugins);
585 int iconSize,
int iconAlpha,
bool scale,
bool save,
586 const TQStringList *enabledPlugins )
588 KFileItemList fileItems;
589 for (KURL::List::ConstIterator it = items.begin(); it != items.end(); ++it)
590 fileItems.append(
new KFileItem(KFileItem::Unknown, KFileItem::Unknown, *it,
true));
591 return new PreviewJob(fileItems, width, height, iconSize, iconAlpha,
592 scale, save, enabledPlugins,
true);
595 void PreviewJob::virtual_hook(
int id,
void* data )
596 { KIO::Job::virtual_hook(
id, data ); }
const KURL & url() const
Returns the url of the file.
The last time the file was modified.
virtual void kill(bool quietly=true)
Abort this job.
A KIO job that retrieves information about a file or directory.
KIO_EXPORT FileCopyJob * file_copy(const KURL &src, const KURL &dest, int permissions=-1, bool overwrite=false, bool resume=false, bool showProgressInfo=true)
Copy a single file.
virtual OfferList query(const TQString &servicetype, const TQString &constraint=TQString::null, const TQString &preferences=TQString::null) const
The main function in the KTrader class.
static Ptr mimeType(const TQString &_name)
Retrieve a pointer to the mime type _name or a pointer to the default mime type "application/octet-st...
KIO_EXPORT PreviewJob * filePreview(const KFileItemList &items, int width, int height=0, int iconSize=0, int iconAlpha=70, bool scale=true, bool save=true, const TQStringList *enabledPlugins=0)
Creates a PreviewJob to generate or retrieve a preview image for the given URL.
KIO_EXPORT TQString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike TQString::number(...)
static TQStringList supportedMimeTypes()
Returns a list of all supported MIME types.
virtual void addSubjob(Job *job, bool inheritMetaData=true)
Add a job that has to be finished before a result is emitted.
TQValueList< UDSAtom > UDSEntry
An entry is the list of atoms containing all the information for a file or URL.
static TQStringList availablePlugins()
Returns a list of all available preview plugins.
virtual void kill(bool quietly=true)
Reimplemented for internal reasons.
void removeItem(const KFileItem *item)
Removes an item from preview processing.
TQString localPath() const
Returns the local path if isLocalFile() == true or the KIO item has a UDS_LOCAL_PATH atom...
void addMetaData(const TQString &key, const TQString &value)
Add key/value pair to the meta data that is sent to the slave.
void emitResult()
Utility function to emit the result signal, and suicide this job.
KIO_EXPORT SimpleJob * rename(const KURL &src, const KURL &dest, bool overwrite)
Rename a file or directory.
TQ_ULLONG filesize_t
64-bit file size
int error() const
Returns the error code, if there has been an error.
KIO Job to get a thumbnail picture.
KIO_EXPORT StatJob * stat(const KURL &url, bool showProgressInfo=true)
Find all details for one file or directory.
TQValueList< KService::Ptr > OfferList
A list of services.
void gotPreview(const KFileItem *item, const TQPixmap &preview)
Emitted when a thumbnail picture for item has been successfully retrieved.
void setIgnoreMaximumSize(bool ignoreSize=true)
If ignoreSize is true, then the preview is always generated regardless of the settings.
void failed(const KFileItem *item)
Emitted when a thumbnail for item could not be created, either because a ThumbCreator for its MIME ty...
static KTrader * self()
This is a static pointer to a KTrader instance.
The base class for all jobs.
PreviewJob(const KFileItemList &items, int width, int height, int iconSize, int iconAlpha, bool scale, bool save, const TQStringList *enabledPlugins, bool deleteItems=false)
Creates a new PreviewJob.
The transfer job pumps data into and/or out of a Slave.
KIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
void result(KIO::Job *job)
Emitted when the job is finished, in any case (completed, canceled, failed...).
A KFileItem is a generic class to handle a file, local or remote.