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:
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 ); }
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 KIO item has a UDS_LOCAL_PATH atom.
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)
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.
void result(KIO::Job *job)
KIO Job to get a thumbnail picture.
static TQStringList supportedMimeTypes()
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.
void gotPreview(const KFileItem *item, const TQPixmap &preview)
void failed(const KFileItem *item)
static TQStringList availablePlugins()
void setIgnoreMaximumSize(bool ignoreSize=true)
If ignoreSize is true, then the preview is always generated regardless of the settings.
A KIO job that retrieves information about a file or directory.
The transfer job pumps data into and/or out of a Slave.
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...
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 KTrader * self()
This is a static pointer to a KTrader instance.
TQValueList< KService::Ptr > OfferList
A list of services.
A namespace for KIO globals.
TQValueList< UDSAtom > UDSEntry
An entry is the list of atoms containing all the information for a file or URL.
KIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
KIO_EXPORT StatJob * stat(const KURL &url, bool showProgressInfo=true)
Find all details for one file or directory.
TQ_ULLONG filesize_t
64-bit file size
KIO_EXPORT TQString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike TQString::number(...)
@ UDS_MODIFICATION_TIME
The last time the file was modified.
@ UDS_SIZE
Size of the file.
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.
KIO_EXPORT SimpleJob * rename(const KURL &src, const KURL &dest, bool overwrite)
Rename a file or directory.
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.