/* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2005-04-21 * Description : slide show tool using preview of pictures. * * Copyright (C) 2005-2007 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #define MAXSTRINGLEN 80 // TQt includes. #include #include #include #include #include #include #include // KDE includes. #include #include #include #include #include // Local includes. #include "ddebug.h" #include "dimg.h" #include "toolbar.h" #include "previewloadthread.h" #include "slideshow.h" #include "slideshow.moc" namespace Digikam { class SlideShowPriv { public: SlideShowPriv() { previewThread = 0; mouseMoveTimer = 0; timer = 0; toolBar = 0; fileIndex = -1; endOfShow = false; pause = false; } bool endOfShow; bool pause; int deskX; int deskY; int deskWidth; int deskHeight; int fileIndex; TQTimer *mouseMoveTimer; // To hide cursor when not moved. TQTimer *timer; TQPixmap pixmap; DImg preview; KURL currentImage; PreviewLoadThread *previewThread; PreviewLoadThread *previewPreloadThread; ToolBar *toolBar; SlideShowSettings settings; }; SlideShow::SlideShow(const SlideShowSettings& settings) : TQWidget(0, 0, WStyle_StaysOnTop | WType_Popup | WX11BypassWM | WDestructiveClose) { d = new SlideShowPriv; d->settings = settings; // --------------------------------------------------------------- #if KDE_IS_VERSION(3,2,0) TQRect deskRect = TDEGlobalSettings::desktopGeometry(this); d->deskX = deskRect.x(); d->deskY = deskRect.y(); d->deskWidth = deskRect.width(); d->deskHeight = deskRect.height(); #else TQRect deskRect = TQApplication::desktop()->screenGeometry(this); d->deskX = deskRect.x(); d->deskY = deskRect.y(); d->deskWidth = deskRect.width(); d->deskHeight = deskRect.height(); #endif move(d->deskX, d->deskY); resize(d->deskWidth, d->deskHeight); setPaletteBackgroundColor(TQt::black); // --------------------------------------------------------------- d->toolBar = new ToolBar(this); d->toolBar->hide(); if (!d->settings.loop) d->toolBar->setEnabledPrev(false); connect(d->toolBar, TQ_SIGNAL(signalPause()), this, TQ_SLOT(slotPause())); connect(d->toolBar, TQ_SIGNAL(signalPlay()), this, TQ_SLOT(slotPlay())); connect(d->toolBar, TQ_SIGNAL(signalNext()), this, TQ_SLOT(slotNext())); connect(d->toolBar, TQ_SIGNAL(signalPrev()), this, TQ_SLOT(slotPrev())); connect(d->toolBar, TQ_SIGNAL(signalClose()), this, TQ_SLOT(slotClose())); // --------------------------------------------------------------- d->previewThread = new PreviewLoadThread(); d->previewPreloadThread = new PreviewLoadThread(); d->timer = new TQTimer(this); d->mouseMoveTimer = new TQTimer(this); connect(d->previewThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg &)), this, TQ_SLOT(slotGotImagePreview(const LoadingDescription &, const DImg&))); connect(d->mouseMoveTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotMouseMoveTimeOut())); connect(d->timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotTimeOut())); d->timer->start(10, true); // --------------------------------------------------------------- setMouseTracking(true); slotMouseMoveTimeOut(); } SlideShow::~SlideShow() { d->timer->stop(); d->mouseMoveTimer->stop(); delete d->timer; delete d->mouseMoveTimer; delete d->previewThread; delete d->previewPreloadThread; delete d; } void SlideShow::setCurrent(const KURL& url) { int index = d->settings.fileList.findIndex(url); if (index != -1) { d->currentImage = url; d->fileIndex = index-1; } } void SlideShow::slotTimeOut() { loadNextImage(); } void SlideShow::loadNextImage() { d->fileIndex++; int num = d->settings.fileList.count(); if (d->fileIndex >= num) { if (d->settings.loop) { d->fileIndex = 0; } } if (!d->settings.loop) { d->toolBar->setEnabledPrev(d->fileIndex > 0); d->toolBar->setEnabledNext(d->fileIndex < num-1); } if (d->fileIndex < num) { d->currentImage = d->settings.fileList[d->fileIndex]; d->previewThread->load(LoadingDescription(d->currentImage.path(), TQMAX(d->deskWidth, d->deskHeight), d->settings.exifRotate)); } else { d->currentImage = KURL(); d->preview = DImg(); updatePixmap(); update(); } } void SlideShow::loadPrevImage() { d->fileIndex--; int num = d->settings.fileList.count(); if (d->fileIndex < 0) { if (d->settings.loop) { d->fileIndex = num-1; } } if (!d->settings.loop) { d->toolBar->setEnabledPrev(d->fileIndex > 0); d->toolBar->setEnabledNext(d->fileIndex < num-1); } if (d->fileIndex >= 0) { d->currentImage = d->settings.fileList[d->fileIndex]; d->previewThread->load(LoadingDescription(d->currentImage.path(), TQMAX(d->deskWidth, d->deskHeight), d->settings.exifRotate)); } else { d->currentImage = KURL(); d->preview = DImg(); updatePixmap(); update(); } } void SlideShow::slotGotImagePreview(const LoadingDescription&, const DImg& preview) { d->preview = preview; updatePixmap(); update(); if (!d->endOfShow) { if (!d->pause) d->timer->start(d->settings.delay, true); preloadNextImage(); } } void SlideShow::preloadNextImage() { int index = d->fileIndex + 1; int num = d->settings.fileList.count(); if (index >= num) { if (d->settings.loop) { index = 0; } } if (index < num) { d->previewPreloadThread->load(LoadingDescription(d->settings.fileList[index].path(), TQMAX(d->deskWidth, d->deskHeight), d->settings.exifRotate)); } } void SlideShow::updatePixmap() { d->pixmap = TQPixmap(size()); d->pixmap.fill(TQt::black); TQPainter p(&(d->pixmap)); if (!d->currentImage.path().isEmpty()) { if (!d->preview.isNull()) { // Preview extraction is complete... Draw the image. TQPixmap pix(d->preview.smoothScale(width(), height(), TQSize::ScaleMin).convertToPixmap()); p.drawPixmap((width()-pix.width())/2, (height()-pix.height())/2, pix, 0, 0, pix.width(), pix.height()); TQString str; PhotoInfoContainer photoInfo = d->settings.pictInfoMap[d->currentImage].photoInfo; int offset = 0; // Display the Comments. if (d->settings.printComment) { str = d->settings.pictInfoMap[d->currentImage].comment; printComments(p, offset, str); } // Display the Make and Model. if (d->settings.printMakeModel) { str = TQString(); if (!photoInfo.make.isEmpty()) str = photoInfo.make; if (!photoInfo.model.isEmpty()) { if (!photoInfo.make.isEmpty()) str += TQString(" / "); str += photoInfo.model; } printInfoText(p, offset, str); } // Display the Exposure and Sensitivity. if (d->settings.printExpoSensitivity) { str = TQString(); if (!photoInfo.exposureTime.isEmpty()) str = photoInfo.exposureTime; if (!photoInfo.sensitivity.isEmpty()) { if (!photoInfo.exposureTime.isEmpty()) str += TQString(" / "); str += i18n("%1 ISO").arg(photoInfo.sensitivity); } printInfoText(p, offset, str); } // Display the Aperture and Focal. if (d->settings.printApertureFocal) { str = TQString(); if (!photoInfo.aperture.isEmpty()) str = photoInfo.aperture; if (photoInfo.focalLength35mm.isEmpty()) { if (!photoInfo.focalLength.isEmpty()) { if (!photoInfo.aperture.isEmpty()) str += TQString(" / "); str += photoInfo.focalLength; } } else { if (!photoInfo.aperture.isEmpty()) str += TQString(" / "); if (!photoInfo.focalLength.isEmpty()) str += TQString("%1 (35mm: %2)").arg(photoInfo.focalLength).arg(photoInfo.focalLength35mm); else str += TQString("35mm: %1)").arg(photoInfo.focalLength35mm); } printInfoText(p, offset, str); } // Display the Creation Date. if (d->settings.printDate) { if (photoInfo.dateTime.isValid()) { str = TDEGlobal::locale()->formatDateTime(photoInfo.dateTime, true, true); printInfoText(p, offset, str); } } // Display the image File Name. if (d->settings.printName) { str = TQString("%1 (%2/%3)").arg(d->currentImage.filename()) .arg(TQString::number(d->fileIndex + 1)) .arg(TQString::number(d->settings.fileList.count())); printInfoText(p, offset, str); } } else { // ...or preview extraction is failed. p.setPen(TQt::white); p.drawText(0, 0, d->pixmap.width(), d->pixmap.height(), TQt::AlignCenter|TQt::WordBreak, i18n("Cannot display image\n\"%1\"") .arg(d->currentImage.fileName())); } } else { // End of Slide Show. TQPixmap logo = kapp->iconLoader()->loadIcon("digikam", TDEIcon::NoGroup, 128, TDEIcon::DefaultState, 0, true); TQFont fn(font()); fn.setPointSize(fn.pointSize()+10); fn.setBold(true); p.setFont(fn); p.setPen(TQt::white); p.drawPixmap(50, 100, logo); p.drawText(60 + logo.width(), 100 + logo.height()/3, i18n("SlideShow Completed.")); p.drawText(60 + logo.width(), 100 + 2*logo.height()/3, i18n("Click To Exit...")); d->endOfShow = true; d->toolBar->setEnabledPlay(false); d->toolBar->setEnabledNext(false); d->toolBar->setEnabledPrev(false); } } void SlideShow::printInfoText(TQPainter &p, int &offset, const TQString& str) { if (!str.isEmpty()) { offset += 20; p.setPen(TQt::black); for (int x=9; x<=11; x++) for (int y=offset+1; y>=offset-1; y--) p.drawText(x, height()-y, str); p.setPen(TQt::white); p.drawText(10, height()-offset, str); } } void SlideShow::printComments(TQPainter &p, int &offset, const TQString& comments) { TQStringList commentsByLines; uint commentsIndex = 0; // Comments TQString index while (commentsIndex < comments.length()) { TQString newLine; bool breakLine = false; // End Of Line found uint currIndex; // Comments TQString current index // Check miminal lines dimension uint commentsLinesLengthLocal = MAXSTRINGLEN; for (currIndex = commentsIndex; currIndex < comments.length() && !breakLine; currIndex++ ) { if( comments[currIndex] == TQChar('\n') || comments[currIndex].isSpace() ) breakLine = true; } if (commentsLinesLengthLocal <= (currIndex - commentsIndex)) commentsLinesLengthLocal = (currIndex - commentsIndex); breakLine = false; for (currIndex = commentsIndex ; currIndex <= commentsIndex + commentsLinesLengthLocal && currIndex < comments.length() && !breakLine ; currIndex++ ) { breakLine = (comments[currIndex] == TQChar('\n')) ? true : false; if (breakLine) newLine.append(TQString(" ")); else newLine.append(comments[currIndex]); } commentsIndex = currIndex; // The line is ended if (commentsIndex != comments.length()) { while (!newLine.endsWith(" ")) { newLine.truncate(newLine.length() - 1); commentsIndex--; } } commentsByLines.prepend(newLine.stripWhiteSpace()); } for (int i = 0 ; i < (int)commentsByLines.count() ; i++ ) { printInfoText(p, offset, commentsByLines[i]); } } void SlideShow::paintEvent(TQPaintEvent *) { bitBlt(this, 0, 0, static_cast(&d->pixmap), 0, 0, d->pixmap.width(), d->pixmap.height(), TQt::CopyROP, true); } void SlideShow::slotPause() { d->timer->stop(); d->pause = true; if (d->toolBar->isHidden()) { int w = d->toolBar->width(); d->toolBar->move(d->deskWidth-w-1,0); d->toolBar->show(); } } void SlideShow::slotPlay() { d->toolBar->hide(); d->pause = false; slotTimeOut(); } void SlideShow::slotPrev() { loadPrevImage(); } void SlideShow::slotNext() { loadNextImage(); } void SlideShow::slotClose() { close(); } void SlideShow::wheelEvent(TQWheelEvent * e) { if (e->delta() < 0) { d->timer->stop(); d->pause = true; d->toolBar->setPaused(true); slotNext(); } if (e->delta() > 0 && d->fileIndex-1 >= 0) { d->timer->stop(); d->pause = true; d->toolBar->setPaused(true); slotPrev(); } } void SlideShow::mousePressEvent(TQMouseEvent *e) { if (d->endOfShow) close(); if (e->button() == TQt::LeftButton) { d->timer->stop(); d->pause = true; d->toolBar->setPaused(true); slotNext(); } else if (e->button() == TQt::RightButton && d->fileIndex-1 >= 0) { d->timer->stop(); d->pause = true; d->toolBar->setPaused(true); slotPrev(); } } void SlideShow::keyPressEvent(TQKeyEvent *event) { if (!event) return; d->toolBar->keyPressEvent(event); } void SlideShow::mouseMoveEvent(TQMouseEvent *e) { setCursor(TQCursor(TQt::ArrowCursor)); d->mouseMoveTimer->start(1000, true); if (!d->toolBar->canHide()) return; TQPoint pos(e->pos()); if ((pos.y() > (d->deskY+20)) && (pos.y() < (d->deskY+d->deskHeight-20-1))) { if (d->toolBar->isHidden()) return; else d->toolBar->hide(); return; } int w = d->toolBar->width(); int h = d->toolBar->height(); if (pos.y() < (d->deskY+20)) { if (pos.x() <= (d->deskX+d->deskWidth/2)) // position top left d->toolBar->move(d->deskX, d->deskY); else // position top right d->toolBar->move(d->deskX+d->deskWidth-w-1, d->deskY); } else { if (pos.x() <= (d->deskX+d->deskWidth/2)) // position bot left d->toolBar->move(d->deskX, d->deskY+d->deskHeight-h-1); else // position bot right d->toolBar->move(d->deskX+d->deskWidth-w-1, d->deskY+d->deskHeight-h-1); } d->toolBar->show(); } void SlideShow::slotMouseMoveTimeOut() { TQPoint pos(TQCursor::pos()); if ((pos.y() < (d->deskY+20)) || (pos.y() > (d->deskY+d->deskHeight-20-1))) return; setCursor(TQCursor(TQt::BlankCursor)); } } // NameSpace Digikam