22 #include "previewjob.h"
26 #include <machine/param.h>
28 #include <sys/types.h>
41 #include <kdatastream.h>
42 #include <tdefileitem.h>
43 #include <tdeapplication.h>
44 #include <tdetempfile.h>
47 #include <tdeglobal.h>
48 #include <kstandarddirs.h>
50 #include <tdeio/kservice.h>
52 #include "previewjob.moc"
54 namespace TDEIO {
struct PreviewItem; }
55 using namespace TDEIO;
57 struct TDEIO::PreviewItem
63 struct TDEIO::PreviewJobPrivate
65 enum { STATE_STATORIG,
69 KFileItemList initialItems;
70 const TQStringList *enabledPlugins;
72 TQValueList<PreviewItem> items;
74 PreviewItem currentItem;
97 unsigned long maximumSize;
112 bool ignoreMaximumSize;
113 TQTimer startPreviewTimer;
117 int iconSize,
int iconAlpha,
bool scale,
bool save,
118 const TQStringList *enabledPlugins,
bool deleteItems )
121 d =
new PreviewJobPrivate;
125 d->initialItems = items;
126 d->enabledPlugins = enabledPlugins;
128 d->height = height ? height : width;
129 d->cacheWidth = d->width;
130 d->cacheHeight = d->height;
131 d->iconSize = iconSize;
132 d->iconAlpha = iconAlpha;
133 d->deleteItems = deleteItems;
135 d->bSave = save && scale;
136 d->succeeded =
false;
137 d->currentItem.item = 0;
138 d->thumbRoot = TQDir::homeDirPath() +
"/.thumbnails/";
139 d->ignoreMaximumSize =
false;
142 connect(&d->startPreviewTimer, TQT_SIGNAL(timeout()), TQT_SLOT(startPreview()) );
143 d->startPreviewTimer.start(0,
true);
146 PreviewJob::~PreviewJob()
150 shmdt((
char*)d->shmaddr);
151 shmctl(d->shmid, IPC_RMID, 0);
157 void PreviewJob::startPreview()
161 TQMap<TQString, KService::Ptr> mimeMap;
163 for (TDETrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
164 if (!d->enabledPlugins || d->enabledPlugins->contains((*it)->desktopEntryName()))
166 TQStringList mimeTypes = (*it)->property(
"MimeTypes").toStringList();
167 for (TQStringList::ConstIterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt)
168 mimeMap.insert(*mt, *it);
172 bool bNeedCache =
false;
173 for (KFileItemListIterator it(d->initialItems); it.current(); ++it )
176 item.item = it.current();
177 TQMap<TQString, KService::Ptr>::ConstIterator plugin = mimeMap.find(it.current()->mimetype());
178 if (plugin == mimeMap.end()
179 && (it.current()->mimetype() !=
"application/x-desktop")
180 && (it.current()->mimetype() !=
"media/builtin-mydocuments")
181 && (it.current()->mimetype() !=
"media/builtin-mycomputer")
182 && (it.current()->mimetype() !=
"media/builtin-mynetworkplaces")
183 && (it.current()->mimetype() !=
"media/builtin-printers")
184 && (it.current()->mimetype() !=
"media/builtin-trash")
185 && (it.current()->mimetype() !=
"media/builtin-webbrowser"))
187 TQString mimeType = it.current()->mimetype();
188 plugin = mimeMap.find(mimeType.replace(TQRegExp(
"/.*"),
"/*"));
190 if (plugin == mimeMap.end())
194 TQString parentMimeType = mimeInfo->parentMimeType();
195 while (!parentMimeType.isEmpty())
197 plugin = mimeMap.find(parentMimeType);
198 if (plugin != mimeMap.end())
break;
201 if (!parentMimeInfo)
break;
203 parentMimeType = parentMimeInfo->parentMimeType();
207 if (plugin == mimeMap.end())
211 TQVariant textProperty = mimeInfo->property(
"X-TDE-text");
212 if (textProperty.isValid() && textProperty.type() == TQVariant::Bool)
214 if (textProperty.toBool())
216 plugin = mimeMap.find(
"text/plain");
217 if (plugin == mimeMap.end())
219 plugin = mimeMap.find(
"text/*" );
226 if (plugin != mimeMap.end())
228 item.plugin = *plugin;
229 d->items.append(item);
230 if (!bNeedCache && d->bSave &&
231 (it.current()->url().protocol() !=
"file" ||
232 !it.current()->url().directory(
false ).startsWith(d->thumbRoot)) &&
233 (*plugin)->property(
"CacheThumbnail").toBool())
238 emitFailed(it.current());
245 TDEConfig * config = TDEGlobal::config();
246 TDEConfigGroupSaver cgs( config,
"PreviewSettings" );
247 d->maximumSize = config->readNumEntry(
"MaximumSize", 1024*1024 );
251 if (d->width <= 128 && d->height <= 128) d->cacheWidth = d->cacheHeight = 128;
252 else d->cacheWidth = d->cacheHeight = 256;
253 d->thumbPath = d->thumbRoot + (d->cacheWidth == 128 ?
"normal/" :
"large/");
254 TDEStandardDirs::makeDir(d->thumbPath, 0700);
263 for (TQValueList<PreviewItem>::Iterator it = d->items.begin(); it != d->items.end(); ++it)
264 if ((*it).item == item)
270 if (d->currentItem.item == item)
272 subjobs.first()->kill();
273 subjobs.removeFirst();
280 d->ignoreMaximumSize = ignoreSize;
283 void PreviewJob::determineNextFile()
285 if (d->currentItem.item)
289 if (d->deleteItems) {
290 delete d->currentItem.item;
291 d->currentItem.item = 0L;
295 if ( d->items.isEmpty() )
303 d->state = PreviewJobPrivate::STATE_STATORIG;
304 d->currentItem = d->items.first();
305 d->succeeded =
false;
306 d->items.remove(d->items.begin());
313 void PreviewJob::slotResult(
TDEIO::Job *job )
315 subjobs.remove( job );
316 Q_ASSERT ( subjobs.isEmpty() );
319 case PreviewJobPrivate::STATE_STATORIG:
328 TDEIO::UDSEntry::ConstIterator it = entry.begin();
331 for( ; it != entry.end() && found < 2; it++ )
335 d->tOrig = (time_t)((*it).m_long);
340 if (
filesize_t((*it).m_long) > d->maximumSize &&
341 !d->ignoreMaximumSize &&
342 !d->currentItem.plugin->property(
"IgnoreMaximumSize").toBool() )
351 if ( !d->currentItem.plugin->property(
"CacheThumbnail" ).toBool() )
355 getOrCreateThumbnail();
359 if ( statResultThumbnail() )
362 getOrCreateThumbnail();
365 case PreviewJobPrivate::STATE_GETORIG:
373 createThumbnail( static_cast<TDEIO::FileCopyJob*>(job)->destURL().path() );
376 case PreviewJobPrivate::STATE_CREATETHUMB:
378 if (!d->tempName.isEmpty())
380 TQFile::remove(d->tempName);
381 d->tempName = TQString::null;
389 bool PreviewJob::statResultThumbnail()
391 if ( d->thumbPath.isEmpty() )
394 KURL url = d->currentItem.item->url();
396 url.setPass(TQString::null);
399 #ifdef KURL_TRIPLE_SLASH_FILE_PROT
400 d->origName = url.url();
402 if (url.protocol() ==
"file") d->origName =
"file://" + url.path();
403 else d->origName = url.url();
406 KMD5 md5( TQFile::encodeName( d->origName ).data() );
407 d->thumbName = TQFile::encodeName( md5.hexDigest() ) +
".png";
410 if ( !thumb.load( d->thumbPath + d->thumbName ) )
return false;
412 if ( thumb.text(
"Thumb::URI", 0 ) != d->origName ||
413 thumb.text(
"Thumb::MTime", 0 ).toInt() != d->tOrig )
return false;
416 emitPreview( thumb );
423 void PreviewJob::getOrCreateThumbnail()
426 const KFileItem* item = d->currentItem.item;
427 const TQString localPath = item->
localPath();
428 if ( !localPath.isEmpty() )
429 createThumbnail( localPath );
432 d->state = PreviewJobPrivate::STATE_GETORIG;
435 localURL.setPath( d->tempName = localFile.name() );
436 const KURL currentURL = item->
url();
445 void PreviewJob::createThumbnail( TQString pixPath )
447 d->state = PreviewJobPrivate::STATE_CREATETHUMB;
449 thumbURL.setProtocol(
"thumbnail");
450 thumbURL.setPath(pixPath);
453 connect(job, TQT_SIGNAL(data(
TDEIO::Job *,
const TQByteArray &)), TQT_SLOT(slotThumbData(
TDEIO::Job *,
const TQByteArray &)));
454 bool save = d->bSave && d->currentItem.plugin->property(
"CacheThumbnail").toBool();
455 job->
addMetaData(
"mimeType", d->currentItem.item->mimetype());
456 job->
addMetaData(
"width", TQString().setNum(save ? d->cacheWidth : d->width));
457 job->
addMetaData(
"height", TQString().setNum(save ? d->cacheHeight : d->height));
458 job->
addMetaData(
"iconSize", TQString().setNum(save ? 64 : d->iconSize));
459 job->
addMetaData(
"iconAlpha", TQString().setNum(d->iconAlpha));
460 job->
addMetaData(
"plugin", d->currentItem.plugin->library());
465 shmdt((
char*)d->shmaddr);
466 shmctl(d->shmid, IPC_RMID, 0);
468 d->shmid = shmget(IPC_PRIVATE, d->cacheWidth * d->cacheHeight * 4, IPC_CREAT|0600);
471 d->shmaddr = (uchar *)(shmat(d->shmid, 0, SHM_RDONLY));
472 if (d->shmaddr == (uchar *)-1)
474 shmctl(d->shmid, IPC_RMID, 0);
483 job->
addMetaData(
"shmid", TQString().setNum(d->shmid));
487 void PreviewJob::slotThumbData(
TDEIO::Job *,
const TQByteArray &data)
489 bool save = d->bSave &&
490 d->currentItem.plugin->property(
"CacheThumbnail").toBool() &&
491 (d->currentItem.item->url().protocol() !=
"file" ||
492 !d->currentItem.item->url().directory(
false ).startsWith(d->thumbRoot));
497 TQDataStream str(data, IO_ReadOnly);
498 int width, height, depth;
500 str >> width >> height >> depth >> alpha;
501 thumb = TQImage(d->shmaddr, width, height, depth, 0, 0, TQImage::IgnoreEndian);
502 thumb.setAlphaBuffer(alpha);
506 thumb.loadFromData(data);
510 thumb.setText(
"Thumb::URI", 0, d->origName);
511 thumb.setText(
"Thumb::MTime", 0, TQString::number(d->tOrig));
512 thumb.setText(
"Thumb::Size", 0,
number(d->currentItem.item->size()));
513 thumb.setText(
"Thumb::Mimetype", 0, d->currentItem.item->mimetype());
514 thumb.setText(
"Software", 0,
"KDE Thumbnail Generator");
515 KTempFile temp(d->thumbPath +
"kde-tmp-",
".png");
516 if (temp.status() == 0)
518 thumb.save(temp.name(),
"PNG");
519 rename(TQFile::encodeName(temp.name()), TQFile::encodeName(d->thumbPath + d->thumbName));
522 emitPreview( thumb );
526 void PreviewJob::emitPreview(
const TQImage &thumb)
529 if (thumb.width() > d->width || thumb.height() > d->height)
531 double imgRatio = (double)thumb.height() / (double)thumb.width();
532 if (imgRatio > (
double)d->height / (
double)d->width)
533 pix.convertFromImage(
534 thumb.smoothScale((
int)TQMAX((
double)d->height / imgRatio, 1), d->height));
535 else pix.convertFromImage(
536 thumb.smoothScale(d->width, (
int)TQMAX((
double)d->width * imgRatio, 1)));
538 else pix.convertFromImage(thumb);
542 void PreviewJob::emitFailed(
const KFileItem *item)
545 item = d->currentItem.item;
553 for (TDETrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
554 if (!result.contains((*it)->desktopEntryName()))
555 result.append((*it)->desktopEntryName());
563 for (TDETrader::OfferList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
564 result += (*it)->property(
"MimeTypes").toStringList();
570 d->startPreviewTimer.stop();
575 int iconSize,
int iconAlpha,
bool scale,
bool save,
576 const TQStringList *enabledPlugins )
578 return new PreviewJob(items, width, height, iconSize, iconAlpha,
579 scale, save, enabledPlugins);
583 int iconSize,
int iconAlpha,
bool scale,
bool save,
584 const TQStringList *enabledPlugins )
586 KFileItemList fileItems;
587 for (KURL::List::ConstIterator it = items.begin(); it != items.end(); ++it)
588 fileItems.append(
new KFileItem(KFileItem::Unknown, KFileItem::Unknown, *it,
true));
589 return new PreviewJob(fileItems, width, height, iconSize, iconAlpha,
590 scale, save, enabledPlugins,
true);
593 void PreviewJob::virtual_hook(
int id,
void* data )
594 { TDEIO::Job::virtual_hook(
id, data ); }
virtual void addSubjob(Job *job, bool inheritMetaData=true)
Add a job that has to be finished before a result is emitted.
static TDETrader * self()
This is a static pointer to a TDETrader instance.
TQValueList< UDSAtom > UDSEntry
An entry is the list of atoms containing all the information for a file or URL.
static TQStringList supportedMimeTypes()
Returns a list of all supported MIME types.
const KURL & url() const
Returns the url of the file.
TDEIO_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.
TQ_ULLONG filesize_t
64-bit file size
void setIgnoreMaximumSize(bool ignoreSize=true)
If ignoreSize is true, then the preview is always generated regardless of the settings.
static TQStringList availablePlugins()
Returns a list of all available preview plugins.
A namespace for TDEIO globals.
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...
TDEIO Job to get a thumbnail picture.
virtual void kill(bool quietly=true)
Reimplemented for internal reasons.
The base class for all jobs.
A TDEIO job that retrieves information about a file or directory.
void removeItem(const KFileItem *item)
Removes an item from preview processing.
virtual OfferList query(const TQString &servicetype, const TQString &constraint=TQString::null, const TQString &preferences=TQString::null) const
The main function in the TDETrader class.
The last time the file was modified.
virtual void kill(bool quietly=true)
Abort this job.
TDEIO_EXPORT LocalURLJob * localURL(const KURL &remoteUrl)
Retrieve local URL if available.
int error() const
Returns the error code, if there has been an error.
TQString localPath() const
Returns the local path if isLocalFile() == true or the TDEIO item has a UDS_LOCAL_PATH atom...
TDEIO_EXPORT StatJob * stat(const KURL &url, bool showProgressInfo=true)
Find all details for one file or directory.
void addMetaData(const TQString &key, const TQString &value)
Add key/value pair to the meta data that is sent to the slave.
TDEIO_EXPORT TQString number(TDEIO::filesize_t size)
Converts a size to a string representation Not unlike TQString::number(...)
TDEIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
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.
TDEIO_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.
void gotPreview(const KFileItem *item, const TQPixmap &preview)
Emitted when a thumbnail picture for item has been successfully retrieved.
void result(TDEIO::Job *job)
Emitted when the job is finished, in any case (completed, canceled, failed...).
TQValueList< KService::Ptr > OfferList
A list of services.
TDEIO_EXPORT SimpleJob * rename(const KURL &src, const KURL &dest, bool overwrite)
Rename a file or directory.
The transfer job pumps data into and/or out of a Slave.
void failed(const KFileItem *item)
Emitted when a thumbnail for item could not be created, either because a ThumbCreator for its MIME ty...
void emitResult()
Utility function to emit the result signal, and suicide this job.
A KFileItem is a generic class to handle a file, local or remote.