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, TQ_SIGNAL(timeout()), TQ_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:
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, TQ_SIGNAL(data(
TDEIO::Job *,
const TQByteArray &)), TQ_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 ); }
A KFileItem is a generic class to handle a file, local or remote.
const KURL & url() const
Returns the url of the file.
TQString localPath() const
Returns the local path if isLocalFile() == true or the TDEIO item has a UDS_LOCAL_PATH atom.
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...
The FileCopyJob copies data from one place to another.
The base class for all jobs.
void emitResult()
Utility function to emit the result signal, and suicide this job.
virtual void addSubjob(Job *job, bool inheritMetaData=true)
void result(TDEIO::Job *job)
virtual void kill(bool quietly=true)
Abort this job.
void addMetaData(const TQString &key, const TQString &value)
int error() const
Returns the error code, if there has been an error.
TDEIO Job to get a thumbnail picture.
static TQStringList supportedMimeTypes()
void failed(const KFileItem *item)
void gotPreview(const KFileItem *item, const TQPixmap &preview)
virtual void kill(bool quietly=true)
Reimplemented for internal reasons.
void removeItem(const KFileItem *item)
Removes an item from preview processing.
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.
static TQStringList availablePlugins()
void setIgnoreMaximumSize(bool ignoreSize=true)
If ignoreSize is true, then the preview is always generated regardless of the settings.
A TDEIO job that retrieves information about a file or directory.
The transfer job pumps data into and/or out of a Slave.
virtual OfferList query(const TQString &servicetype, const TQString &constraint=TQString::null, const TQString &preferences=TQString::null) const
The main function in the TDETrader class.
static TDETrader * self()
This is a static pointer to a TDETrader instance.
TQValueList< KService::Ptr > OfferList
A list of services.
A namespace for TDEIO globals.
TDEIO_EXPORT TQString number(TDEIO::filesize_t size)
Converts a size to a string representation Not unlike TQString::number(...)
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.
TDEIO_EXPORT LocalURLJob * localURL(const KURL &remoteUrl)
Retrieve local URL if available.
@ UDS_SIZE
Size of the file.
@ UDS_MODIFICATION_TIME
The last time the file was modified.
TQValueList< UDSAtom > UDSEntry
An entry is the list of atoms containing all the information for a file or URL.
TDEIO_EXPORT SimpleJob * rename(const KURL &src, const KURL &dest, bool overwrite)
Rename a file or directory.
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.
TDEIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
TQ_ULLONG filesize_t
64-bit file size
TDEIO_EXPORT StatJob * stat(const KURL &url, bool showProgressInfo=true)
Find all details for one file or directory.