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 ); }